Browse Source

chore: remove deprecated remote module (#25734)

Co-authored-by: Jeremy Rose <[email protected]>
Milan Burda 4 years ago
parent
commit
5b205731f6
75 changed files with 18 additions and 3650 deletions
  1. 0 6
      .github/CODEOWNERS
  2. 0 7
      build/webpack/webpack.config.base.js
  3. 0 1
      buildflags/BUILD.gn
  4. 0 2
      buildflags/buildflags.gni
  5. 1 2
      default_app/default_app.ts
  6. 0 1
      docs/README.md
  7. 0 58
      docs/api/app.md
  8. 0 2
      docs/api/browser-window.md
  9. 0 5
      docs/api/command-line-switches.md
  10. 0 217
      docs/api/remote.md
  11. 0 53
      docs/api/web-contents.md
  12. 0 9
      docs/api/webview-tag.md
  13. 3 132
      docs/tutorial/security.md
  14. 0 22
      filenames.auto.gni
  15. 0 50
      lib/browser/api/module-names.ts
  16. 0 4
      lib/browser/api/web-contents.ts
  17. 0 2
      lib/browser/guest-view-manager.ts
  18. 0 1
      lib/browser/guest-window-manager.ts
  19. 0 4
      lib/browser/init.ts
  20. 0 128
      lib/browser/remote/objects-registry.ts
  21. 0 519
      lib/browser/remote/server.ts
  22. 1 1
      lib/common/parse-features-string.ts
  23. 0 85
      lib/common/remote/types.ts
  24. 0 11
      lib/renderer/api/module-list.ts
  25. 0 395
      lib/renderer/api/remote.ts
  26. 0 59
      lib/renderer/remote/callbacks-registry.ts
  27. 0 22
      lib/renderer/security-warnings.ts
  28. 0 15
      lib/renderer/web-view/web-view-attributes.ts
  29. 0 1
      lib/renderer/web-view/web-view-constants.ts
  30. 0 1
      lib/renderer/web-view/web-view-element.ts
  31. 0 11
      lib/sandboxed_renderer/api/module-list.ts
  32. 10 18
      patches/chromium/allow_in_process_windows_to_have_different_web_prefs.patch
  33. 0 5
      shell/browser/web_contents_preferences.cc
  34. 0 5
      shell/common/api/BUILD.gn
  35. 0 5
      shell/common/api/features.cc
  36. 0 4
      shell/common/options_switches.cc
  37. 0 4
      shell/common/options_switches.h
  38. 0 4
      shell/renderer/api/electron_api_web_frame.cc
  39. 0 95
      spec-main/api-app-spec.ts
  40. 0 149
      spec-main/api-browser-window-spec.ts
  41. 0 47
      spec-main/api-callbacks-registry-spec.ts
  42. 0 1049
      spec-main/api-remote-spec.ts
  43. 0 7
      spec-main/fixtures/remote/call.js
  44. 0 3
      spec-main/fixtures/remote/circular.js
  45. 0 29
      spec-main/fixtures/remote/class.js
  46. 0 11
      spec-main/fixtures/remote/delete-buffer.js
  47. 0 11
      spec-main/fixtures/remote/error-properties.js
  48. 0 3
      spec-main/fixtures/remote/exception.js
  49. 0 4
      spec-main/fixtures/remote/export-function-with-properties.js
  50. 0 3
      spec-main/fixtures/remote/function-with-args.js
  51. 0 13
      spec-main/fixtures/remote/function-with-missing-properties.js
  52. 0 17
      spec-main/fixtures/remote/function-with-properties.js
  53. 0 1
      spec-main/fixtures/remote/function.js
  54. 0 1
      spec-main/fixtures/remote/id.js
  55. 0 11
      spec-main/fixtures/remote/no-prototype.js
  56. 0 5
      spec-main/fixtures/remote/preload-remote-function.js
  57. 0 5
      spec-main/fixtures/remote/preload-remote.js
  58. 0 36
      spec-main/fixtures/remote/print_name.js
  59. 0 5
      spec-main/fixtures/remote/promise.js
  60. 0 11
      spec-main/fixtures/remote/property.js
  61. 0 5
      spec-main/fixtures/remote/rejected-promise.js
  62. 0 18
      spec-main/fixtures/remote/remote-event-handler.html
  63. 0 11
      spec-main/fixtures/remote/remote-object-set.js
  64. 0 15
      spec-main/fixtures/remote/remote-static.js
  65. 0 32
      spec-main/fixtures/remote/render-view-deleted.html
  66. 0 11
      spec-main/fixtures/remote/send-on-exit.html
  67. 0 4
      spec-main/fixtures/remote/to-string-non-function.js
  68. 0 3
      spec-main/fixtures/remote/unhandled-rejection.js
  69. 3 30
      spec-main/security-warnings-spec.ts
  70. 0 49
      spec-main/webview-spec.ts
  71. 0 8
      spec/fixtures/module/preload-disable-remote.js
  72. 0 1
      spec/static/main.js
  73. 0 62
      spec/ts-smoke/electron/renderer.ts
  74. 0 11
      spec/webview-spec.js
  75. 0 3
      typings/internal-ambient.d.ts

+ 0 - 6
.github/CODEOWNERS

@@ -13,9 +13,3 @@ DEPS                                    @electron/wg-upgrades
 
 # Security WG
 /lib/browser/rpc-server.ts              @electron/wg-security
-
-# Remote Change Disliker
-/lib/browser/remote/                    @nornagon
-/lib/renderer/remote/                   @nornagon
-/lib/renderer/api/remote.ts             @nornagon
-/docs/api/remote.md                     @nornagon

+ 0 - 7
build/webpack/webpack.config.base.js

@@ -61,13 +61,6 @@ module.exports = ({
       );
     }
 
-    if (defines.ENABLE_REMOTE_MODULE === 'false') {
-      ignoredModules.push(
-        '@electron/internal/browser/remote/server',
-        '@electron/internal/renderer/api/remote'
-      );
-    }
-
     if (defines.ENABLE_VIEWS_API === 'false') {
       ignoredModules.push(
         '@electron/internal/browser/api/views/image-view.js'

+ 0 - 1
buildflags/BUILD.gn

@@ -12,7 +12,6 @@ buildflag_header("buildflags") {
     "ENABLE_DESKTOP_CAPTURER=$enable_desktop_capturer",
     "ENABLE_RUN_AS_NODE=$enable_run_as_node",
     "ENABLE_OSR=$enable_osr",
-    "ENABLE_REMOTE_MODULE=$enable_remote_module",
     "ENABLE_VIEWS_API=$enable_views_api",
     "ENABLE_PDF_VIEWER=$enable_pdf_viewer",
     "ENABLE_TTS=$enable_tts",

+ 0 - 2
buildflags/buildflags.gni

@@ -10,8 +10,6 @@ declare_args() {
 
   enable_osr = true
 
-  enable_remote_module = true
-
   enable_views_api = true
 
   enable_pdf_viewer = true

+ 1 - 2
default_app/default_app.ts

@@ -52,8 +52,7 @@ async function createWindow () {
     webPreferences: {
       preload: path.resolve(__dirname, 'preload.js'),
       contextIsolation: true,
-      sandbox: true,
-      enableRemoteModule: false
+      sandbox: true
     },
     useContentSize: true,
     show: false

+ 0 - 1
docs/README.md

@@ -146,7 +146,6 @@ These individual tutorials expand on topics discussed in the guide above.
 * [contextBridge](api/context-bridge.md)
 * [desktopCapturer](api/desktop-capturer.md)
 * [ipcRenderer](api/ipc-renderer.md)
-* [remote](api/remote.md)
 * [webFrame](api/web-frame.md)
 
 ### Modules for Both Processes:

+ 0 - 58
docs/api/app.md

@@ -507,64 +507,6 @@ 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' _Deprecated_
-
-Returns:
-
-* `event` Event
-* `webContents` [WebContents](web-contents.md)
-* `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' _Deprecated_
-
-Returns:
-
-* `event` Event
-* `webContents` [WebContents](web-contents.md)
-* `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' _Deprecated_
-
-Returns:
-
-* `event` Event
-* `webContents` [WebContents](web-contents.md)
-* `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' _Deprecated_
-
-Returns:
-
-* `event` Event
-* `webContents` [WebContents](web-contents.md)
-
-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' _Deprecated_
-
-Returns:
-
-* `event` Event
-* `webContents` [WebContents](web-contents.md)
-
-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:

+ 0 - 2
docs/api/browser-window.md

@@ -273,8 +273,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
       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](sandbox-option.md).
-    * `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
-      Default is `false`.
     * `session` [Session](session.md#class-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

+ 0 - 5
docs/api/command-line-switches.md

@@ -66,11 +66,6 @@ Forces the maximum disk space to be used by the disk cache, in bytes.
 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
 

+ 0 - 217
docs/api/remote.md

@@ -1,217 +0,0 @@
-# remote
-
-> Use main process modules from the renderer process.
-
-Process: [Renderer](../glossary.md#renderer-process)
-
-> ⚠️ WARNING ⚠️
-> The `remote` module is [deprecated](https://github.com/electron/electron/issues/21408).
-> Instead of `remote`, use [`ipcRenderer`](ipc-renderer.md) and
-> [`ipcMain`](ipc-main.md).
->
-> Read more about why the `remote` module is deprecated [here](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
->
-> If you still want to use `remote` despite the performance and security
-> concerns, see [@electron/remote](https://github.com/electron/remote).
-
-The `remote` module provides a simple way to do inter-process communication
-(IPC) between the renderer process (web page) and the main process.
-
-In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only
-available in the main process, not in the renderer process. In order to use them
-from the renderer process, the `ipc` module is necessary to send inter-process
-messages to the main process. With the `remote` module, you can invoke methods
-of the main process object without explicitly sending inter-process messages,
-similar to Java's [RMI][rmi]. An example of creating a browser window from a
-renderer process:
-
-```javascript
-const { BrowserWindow } = require('electron').remote
-const win = new BrowserWindow({ width: 800, height: 600 })
-win.loadURL('https://github.com')
-```
-
-**Note:** For the reverse (access the renderer process from the main process),
-you can use [webContents.executeJavaScript](web-contents.md#contentsexecutejavascriptcode-usergesture).
-
-**Note:** The remote module can be disabled for security reasons in the following contexts:
-
-* [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
-* [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
-
-## Remote Objects
-
-Each object (including functions) returned by the `remote` module represents an
-object in the main process (we call it a remote object or remote function).
-When you invoke methods of a remote object, call a remote function, or create
-a new object with the remote constructor (function), you are actually sending
-synchronous inter-process messages.
-
-In the example above, both [`BrowserWindow`](browser-window.md) and `win` were remote objects and
-`new BrowserWindow` didn't create a `BrowserWindow` object in the renderer
-process. Instead, it created a `BrowserWindow` object in the main process and
-returned the corresponding remote object in the renderer process, namely the
-`win` object.
-
-**Note:** Only [enumerable properties][enumerable-properties] which are present
-when the remote object is first referenced are accessible via remote.
-
-**Note:** Arrays and Buffers are copied over IPC when accessed via the `remote`
-module. Modifying them in the renderer process does not modify them in the main
-process and vice versa.
-
-## Lifetime of Remote Objects
-
-Electron makes sure that as long as the remote object in the renderer process
-lives (in other words, has not been garbage collected), the corresponding object
-in the main process will not be released. When the remote object has been
-garbage collected, the corresponding object in the main process will be
-dereferenced.
-
-If the remote object is leaked in the renderer process (e.g. stored in a map but
-never freed), the corresponding object in the main process will also be leaked,
-so you should be very careful not to leak remote objects.
-
-Primary value types like strings and numbers, however, are sent by copy.
-
-## Passing callbacks to the main process
-
-Code in the main process can accept callbacks from the renderer - for instance
-the `remote` module - but you should be extremely careful when using this
-feature.
-
-First, in order to avoid deadlocks, the callbacks passed to the main process
-are called asynchronously. You should not expect the main process to
-get the return value of the passed callbacks.
-
-For instance you can't use a function from the renderer process in an
-`Array.map` called in the main process:
-
-```javascript
-// main process mapNumbers.js
-exports.withRendererCallback = (mapper) => {
-  return [1, 2, 3].map(mapper)
-}
-
-exports.withLocalCallback = () => {
-  return [1, 2, 3].map(x => x + 1)
-}
-```
-
-```javascript
-// renderer process
-const mapNumbers = require('electron').remote.require('./mapNumbers')
-const withRendererCb = mapNumbers.withRendererCallback(x => x + 1)
-const withLocalCb = mapNumbers.withLocalCallback()
-
-console.log(withRendererCb, withLocalCb)
-// [undefined, undefined, undefined], [2, 3, 4]
-```
-
-As you can see, the renderer callback's synchronous return value was not as
-expected, and didn't match the return value of an identical callback that lives
-in the main process.
-
-Second, the callbacks passed to the main process will persist until the
-main process garbage-collects them.
-
-For example, the following code seems innocent at first glance. It installs a
-callback for the `close` event on a remote object:
-
-```javascript
-require('electron').remote.getCurrentWindow().on('close', () => {
-  // window was closed...
-})
-```
-
-But remember the callback is referenced by the main process until you
-explicitly uninstall it. If you do not, each time you reload your window the
-callback will be installed again, leaking one callback for each restart.
-
-To make things worse, since the context of previously installed callbacks has
-been released, exceptions will be raised in the main process when the `close`
-event is emitted.
-
-To avoid this problem, ensure you clean up any references to renderer callbacks
-passed to the main process. This involves cleaning up event handlers, or
-ensuring the main process is explicitly told to dereference callbacks that came
-from a renderer process that is exiting.
-
-## Accessing built-in modules in the main process
-
-The built-in modules in the main process are added as getters in the `remote`
-module, so you can use them directly like the `electron` module.
-
-```javascript
-const app = require('electron').remote.app
-console.log(app)
-```
-
-## Methods
-
-The `remote` module has the following methods:
-
-### `remote.getCurrentWindow()`
-
-Returns [`BrowserWindow`](browser-window.md) - The window to which this web page
-belongs.
-
-**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.
-
-### `remote.getCurrentWebContents()`
-
-Returns [`WebContents`](web-contents.md) - The web contents of this web page.
-
-### `remote.getGlobal(name)`
-
-* `name` String
-
-Returns `any` - The global variable of `name` (e.g. `global[name]`) in the main
-process.
-
-## Properties
-
-### `remote.require`
-
-A `NodeJS.Require` function equivalent to `require(module)` in the main process.
-Modules specified by their relative path will resolve relative to the entrypoint
-of the main process.
-
-e.g.
-
-```sh
-project/
-├── main
-│   ├── foo.js
-│   └── index.js
-├── package.json
-└── renderer
-    └── index.js
-```
-
-```js
-// main process: main/index.js
-const { app } = require('electron')
-app.whenReady().then(() => { /* ... */ })
-```
-
-```js
-// some relative module: main/foo.js
-module.exports = 'bar'
-```
-
-```js
-// renderer process: renderer/index.js
-const foo = require('electron').remote.require('./foo') // bar
-```
-
-### `remote.process` _Readonly_
-
-A `NodeJS.Process` object.  The `process` object in the main process. This is the same as
-`remote.getGlobal('process')` but is cached.
-
-[rmi]: https://en.wikipedia.org/wiki/Java_remote_method_invocation
-[enumerable-properties]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties

+ 0 - 53
docs/api/web-contents.md

@@ -839,59 +839,6 @@ Returns:
 Emitted when `desktopCapturer.getSources()` is called in the renderer process.
 Calling `event.preventDefault()` will make it return empty sources.
 
-#### Event: 'remote-require' _Deprecated_
-
-Returns:
-
-* `event` IpcMainEvent
-* `moduleName` String
-
-Emitted when `remote.require()` is called in the renderer process.
-Calling `event.preventDefault()` will prevent the module from being returned.
-Custom value can be returned by setting `event.returnValue`.
-
-#### Event: 'remote-get-global' _Deprecated_
-
-Returns:
-
-* `event` IpcMainEvent
-* `globalName` String
-
-Emitted when `remote.getGlobal()` is called in the renderer process.
-Calling `event.preventDefault()` will prevent the global from being returned.
-Custom value can be returned by setting `event.returnValue`.
-
-#### Event: 'remote-get-builtin' _Deprecated_
-
-Returns:
-
-* `event` IpcMainEvent
-* `moduleName` String
-
-Emitted when `remote.getBuiltin()` is called in the renderer process.
-Calling `event.preventDefault()` will prevent the module from being returned.
-Custom value can be returned by setting `event.returnValue`.
-
-#### Event: 'remote-get-current-window' _Deprecated_
-
-Returns:
-
-* `event` IpcMainEvent
-
-Emitted when `remote.getCurrentWindow()` is called in the renderer process.
-Calling `event.preventDefault()` will prevent the object from being returned.
-Custom value can be returned by setting `event.returnValue`.
-
-#### Event: 'remote-get-current-web-contents' _Deprecated_
-
-Returns:
-
-* `event` IpcMainEvent
-
-Emitted when `remote.getCurrentWebContents()` is called in the renderer process.
-Calling `event.preventDefault()` will prevent the object from being returned.
-Custom value can be returned by setting `event.returnValue`.
-
 #### Event: 'preferred-size-changed'
 
 Returns:

+ 0 - 9
docs/api/webview-tag.md

@@ -130,15 +130,6 @@ inside the `webview`. All your preloads will load for every iframe, you can
 use `process.isMainFrame` to determine if you are in the main frame or not.
 This option is disabled by default in the guest page.
 
-### `enableremotemodule`
-
-```html
-<webview src="http://www.google.com/" enableremotemodule="false"></webview>
-```
-
-A `Boolean`. When this attribute is `false` the guest page in `webview` will not have access
-to the [`remote`](remote.md) module. The remote module is unavailable by default.
-
 ### `plugins`
 
 ```html

+ 3 - 132
docs/tutorial/security.md

@@ -44,7 +44,7 @@ Chromium shared library and Node.js. Vulnerabilities affecting these components
 may impact the security of your application. By updating Electron to the latest
 version, you ensure that critical vulnerabilities (such as *nodeIntegration bypasses*)
 are already patched and cannot be exploited in your application. For more information,
-see "[Use a current version of Electron](#17-use-a-current-version-of-electron)".
+see "[Use a current version of Electron](#15-use-a-current-version-of-electron)".
 
 * **Evaluate your dependencies.** While NPM provides half a million reusable packages,
 it is your responsibility to choose trusted 3rd-party libraries. If you use outdated
@@ -99,9 +99,7 @@ You should at least follow these steps to improve the security of your applicati
 12. [Disable or limit navigation](#12-disable-or-limit-navigation)
 13. [Disable or limit creation of new windows](#13-disable-or-limit-creation-of-new-windows)
 14. [Do not use `openExternal` with untrusted content](#14-do-not-use-openexternal-with-untrusted-content)
-15. [Disable the `remote` module](#15-disable-the-remote-module)
-16. [Filter the `remote` module](#16-filter-the-remote-module)
-17. [Use a current version of Electron](#17-use-a-current-version-of-electron)
+15. [Use a current version of Electron](#15-use-a-current-version-of-electron)
 
 To automate the detection of misconfigurations and insecure patterns, it is
 possible to use
@@ -665,134 +663,7 @@ const { shell } = require('electron')
 shell.openExternal('https://example.com/index.html')
 ```
 
-## 15) Disable the `remote` module
-
-The `remote` module provides a way for the renderer processes to
-access APIs normally only available in the main process. Using it, a
-renderer can invoke methods of a main process object without explicitly sending
-inter-process messages. If your desktop application does not run untrusted
-content, this can be a useful way to have your renderer processes access and
-work with modules that are only available to the main process, such as
-GUI-related modules (dialogs, menus, etc.).
-
-However, if your app can run untrusted content and even if you
-[sandbox][sandbox] your renderer processes accordingly, the `remote` module
-makes it easy for malicious code to escape the sandbox and have access to
-system resources via the higher privileges of the main process. Therefore,
-it should be disabled in such circumstances.
-
-### Why?
-
-`remote` uses an internal IPC channel to communicate with the main process.
-"Prototype pollution" attacks can grant malicious code access to the internal
-IPC channel, which can then be used to escape the sandbox by mimicking `remote`
-IPC messages and getting access to main process modules running with higher
-privileges.
-
-Additionally, it's possible for preload scripts to accidentally leak modules to a
-sandboxed renderer. Leaking `remote` arms malicious code with a multitude
-of main process modules with which to perform an attack.
-
-Disabling the `remote` module eliminates these attack vectors. Enabling
-context isolation also prevents the "prototype pollution" attacks from
-succeeding.
-
-### How?
-
-```js
-// Bad if the renderer can run untrusted content
-const mainWindow = new BrowserWindow({
-  webPreferences: {
-    enableRemoteModule: true
-  }
-})
-```
-
-```js
-// Good
-const mainWindow = new BrowserWindow({
-  webPreferences: {
-    enableRemoteModule: false
-  }
-})
-```
-
-```html
-<!-- Bad if the renderer can run untrusted content  -->
-<webview enableremotemodule="true" src="page.html"></webview>
-
-<!-- Good -->
-<webview enableremotemodule="false" src="page.html"></webview>
-```
-
-> **Note:** The default value of `enableRemoteModule` is `false` starting
-> from Electron 10. For prior versions, you need to explicitly disable
-> the `remote` module by the means above.
-
-## 16) Filter the `remote` module
-
-If you cannot disable the `remote` module, you should filter the globals,
-Node, and Electron modules (so-called built-ins) accessible via `remote`
-that your application does not require. This can be done by blocking
-certain modules entirely and by replacing others with proxies that
-expose only the functionality that your app needs.
-
-### Why?
-
-Due to the system access privileges of the main process, functionality
-provided by the main process modules may be dangerous in the hands of
-malicious code running in a compromised renderer process. By limiting
-the set of accessible modules to the minimum that your app needs and
-filtering out the others, you reduce the toolset that malicious code
-can use to attack the system.
-
-Note that the safest option is to
-[fully disable the remote module](#15-disable-the-remote-module). If
-you choose to filter access rather than completely disable the module,
-you must be very careful to ensure that no escalation of privilege is
-possible through the modules you allow past the filter.
-
-### How?
-
-```js
-const readOnlyFsProxy = require(/* ... */) // exposes only file read functionality
-
-const allowedModules = new Set(['crypto'])
-const proxiedModules = new Map([['fs', readOnlyFsProxy]])
-const allowedElectronModules = new Set(['shell'])
-const allowedGlobals = new Set()
-
-app.on('remote-require', (event, webContents, moduleName) => {
-  if (proxiedModules.has(moduleName)) {
-    event.returnValue = proxiedModules.get(moduleName)
-  }
-  if (!allowedModules.has(moduleName)) {
-    event.preventDefault()
-  }
-})
-
-app.on('remote-get-builtin', (event, webContents, moduleName) => {
-  if (!allowedElectronModules.has(moduleName)) {
-    event.preventDefault()
-  }
-})
-
-app.on('remote-get-global', (event, webContents, globalName) => {
-  if (!allowedGlobals.has(globalName)) {
-    event.preventDefault()
-  }
-})
-
-app.on('remote-get-current-window', (event, webContents) => {
-  event.preventDefault()
-})
-
-app.on('remote-get-current-web-contents', (event, webContents) => {
-  event.preventDefault()
-})
-```
-
-## 17) Use a current version of Electron
+## 15) Use a current version of Electron
 
 You should strive for always using the latest available version of Electron.
 Whenever a new major version is released, you should attempt to update your

+ 0 - 22
filenames.auto.gni

@@ -43,7 +43,6 @@ auto_filenames = {
     "docs/api/power-save-blocker.md",
     "docs/api/process.md",
     "docs/api/protocol.md",
-    "docs/api/remote.md",
     "docs/api/sandbox-option.md",
     "docs/api/screen.md",
     "docs/api/service-workers.md",
@@ -135,29 +134,21 @@ auto_filenames = {
   ]
 
   sandbox_bundle_deps = [
-    "lib/browser/api/module-names.ts",
-    "lib/common/api/clipboard.ts",
     "lib/common/api/deprecate.ts",
-    "lib/common/api/module-list.ts",
-    "lib/common/api/shell.ts",
     "lib/common/define-properties.ts",
     "lib/common/ipc-messages.ts",
-    "lib/common/remote/ipc-messages.ts",
     "lib/common/type-utils.ts",
     "lib/common/web-view-events.ts",
     "lib/common/web-view-methods.ts",
-    "lib/common/webpack-globals-provider.ts",
     "lib/renderer/api/context-bridge.ts",
     "lib/renderer/api/crash-reporter.ts",
     "lib/renderer/api/desktop-capturer.ts",
     "lib/renderer/api/ipc-renderer.ts",
     "lib/renderer/api/native-image.ts",
-    "lib/renderer/api/remote.ts",
     "lib/renderer/api/web-frame.ts",
     "lib/renderer/inspector.ts",
     "lib/renderer/ipc-renderer-internal-utils.ts",
     "lib/renderer/ipc-renderer-internal.ts",
-    "lib/renderer/remote/callbacks-registry.ts",
     "lib/renderer/security-warnings.ts",
     "lib/renderer/web-frame-init.ts",
     "lib/renderer/web-view/guest-view-internal.ts",
@@ -242,8 +233,6 @@ auto_filenames = {
     "lib/browser/ipc-main-internal.ts",
     "lib/browser/message-port-main.ts",
     "lib/browser/navigation-controller.ts",
-    "lib/browser/remote/objects-registry.ts",
-    "lib/browser/remote/server.ts",
     "lib/browser/rpc-server.ts",
     "lib/common/api/clipboard.ts",
     "lib/common/api/deprecate.ts",
@@ -253,7 +242,6 @@ auto_filenames = {
     "lib/common/init.ts",
     "lib/common/ipc-messages.ts",
     "lib/common/parse-features-string.ts",
-    "lib/common/remote/ipc-messages.ts",
     "lib/common/reset-search-paths.ts",
     "lib/common/type-utils.ts",
     "lib/common/web-view-events.ts",
@@ -269,7 +257,6 @@ auto_filenames = {
   ]
 
   renderer_bundle_deps = [
-    "lib/browser/api/module-names.ts",
     "lib/common/api/clipboard.ts",
     "lib/common/api/deprecate.ts",
     "lib/common/api/module-list.ts",
@@ -277,12 +264,10 @@ auto_filenames = {
     "lib/common/define-properties.ts",
     "lib/common/init.ts",
     "lib/common/ipc-messages.ts",
-    "lib/common/remote/ipc-messages.ts",
     "lib/common/reset-search-paths.ts",
     "lib/common/type-utils.ts",
     "lib/common/web-view-events.ts",
     "lib/common/web-view-methods.ts",
-    "lib/common/webpack-globals-provider.ts",
     "lib/common/webpack-provider.ts",
     "lib/renderer/api/context-bridge.ts",
     "lib/renderer/api/crash-reporter.ts",
@@ -291,13 +276,11 @@ auto_filenames = {
     "lib/renderer/api/ipc-renderer.ts",
     "lib/renderer/api/module-list.ts",
     "lib/renderer/api/native-image.ts",
-    "lib/renderer/api/remote.ts",
     "lib/renderer/api/web-frame.ts",
     "lib/renderer/init.ts",
     "lib/renderer/inspector.ts",
     "lib/renderer/ipc-renderer-internal-utils.ts",
     "lib/renderer/ipc-renderer-internal.ts",
-    "lib/renderer/remote/callbacks-registry.ts",
     "lib/renderer/security-warnings.ts",
     "lib/renderer/web-frame-init.ts",
     "lib/renderer/web-view/guest-view-internal.ts",
@@ -315,7 +298,6 @@ auto_filenames = {
   ]
 
   worker_bundle_deps = [
-    "lib/browser/api/module-names.ts",
     "lib/common/api/clipboard.ts",
     "lib/common/api/deprecate.ts",
     "lib/common/api/module-list.ts",
@@ -323,10 +305,8 @@ auto_filenames = {
     "lib/common/define-properties.ts",
     "lib/common/init.ts",
     "lib/common/ipc-messages.ts",
-    "lib/common/remote/ipc-messages.ts",
     "lib/common/reset-search-paths.ts",
     "lib/common/type-utils.ts",
-    "lib/common/webpack-globals-provider.ts",
     "lib/common/webpack-provider.ts",
     "lib/renderer/api/context-bridge.ts",
     "lib/renderer/api/crash-reporter.ts",
@@ -335,11 +315,9 @@ auto_filenames = {
     "lib/renderer/api/ipc-renderer.ts",
     "lib/renderer/api/module-list.ts",
     "lib/renderer/api/native-image.ts",
-    "lib/renderer/api/remote.ts",
     "lib/renderer/api/web-frame.ts",
     "lib/renderer/ipc-renderer-internal-utils.ts",
     "lib/renderer/ipc-renderer-internal.ts",
-    "lib/renderer/remote/callbacks-registry.ts",
     "lib/worker/init.ts",
     "package.json",
     "tsconfig.electron.json",

+ 0 - 50
lib/browser/api/module-names.ts

@@ -1,50 +0,0 @@
-// TODO: Figure out a way to not duplicate this information between here and module-list
-// It is currently duplicated as module-list "require"s all the browser API file and the
-// remote module in the renderer process depends on that file.  As a result webpack
-// includes all the browser API files in the renderer process as well and we want to avoid that
-
-// Browser side modules, please sort alphabetically.
-export const browserModuleNames = [
-  'app',
-  'autoUpdater',
-  'BaseWindow',
-  'BrowserView',
-  'BrowserWindow',
-  'contentTracing',
-  'crashReporter',
-  'dialog',
-  'globalShortcut',
-  'ipcMain',
-  'inAppPurchase',
-  'Menu',
-  'MenuItem',
-  'nativeImage',
-  'nativeTheme',
-  'net',
-  'netLog',
-  'MessageChannelMain',
-  'Notification',
-  'powerMonitor',
-  'powerSaveBlocker',
-  'protocol',
-  'screen',
-  'session',
-  'ShareMenu',
-  'systemPreferences',
-  'TouchBar',
-  'Tray',
-  'View',
-  'webContents',
-  'WebContentsView',
-  'webFrameMain'
-];
-
-if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
-  browserModuleNames.push('desktopCapturer');
-}
-
-if (BUILDFLAG(ENABLE_VIEWS_API)) {
-  browserModuleNames.push(
-    'ImageView'
-  );
-}

+ 0 - 4
lib/browser/api/web-contents.ts

@@ -498,10 +498,6 @@ WebContents.prototype._init = function () {
 
   this._windowOpenHandler = null;
 
-  // Every remote callback from renderer process would add a listener to the
-  // render-view-deleted event, so ignore the listeners warning.
-  this.setMaxListeners(0);
-
   // Dispatch IPC messages to the ipc module.
   this.on('-ipc-message' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
     addSenderFrameToEvent(event);

+ 0 - 2
lib/browser/guest-view-manager.ts

@@ -168,7 +168,6 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
     guestInstanceId: guestInstanceId,
     nodeIntegration: params.nodeintegration != null ? params.nodeintegration : false,
     nodeIntegrationInSubFrames: params.nodeintegrationinsubframes != null ? params.nodeintegrationinsubframes : false,
-    enableRemoteModule: params.enableremotemodule,
     plugins: params.plugins,
     zoomFactor: embedder.zoomFactor,
     disablePopups: !params.allowpopups,
@@ -188,7 +187,6 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
     ['javascript', false],
     ['nativeWindowOpen', true],
     ['nodeIntegration', false],
-    ['enableRemoteModule', false],
     ['sandbox', true],
     ['nodeIntegrationInSubFrames', false],
     ['enableWebSQL', false]

+ 0 - 1
lib/browser/guest-window-manager.ts

@@ -191,7 +191,6 @@ const securityWebPreferences: { [key: string]: boolean } = {
   javascript: false,
   nativeWindowOpen: true,
   nodeIntegration: false,
-  enableRemoteModule: false,
   sandbox: true,
   webviewTag: false,
   nodeIntegrationInSubFrames: false,

+ 0 - 4
lib/browser/init.ts

@@ -132,10 +132,6 @@ app._setDefaultAppPaths(packagePath);
 // Load the chrome devtools support.
 require('@electron/internal/browser/devtools');
 
-if (BUILDFLAG(ENABLE_REMOTE_MODULE)) {
-  require('@electron/internal/browser/remote/server');
-}
-
 // Load protocol module to ensure it is populated on app ready
 require('@electron/internal/browser/api/protocol');
 

+ 0 - 128
lib/browser/remote/objects-registry.ts

@@ -1,128 +0,0 @@
-import { WebContents } from 'electron/main';
-
-const getOwnerKey = (webContents: WebContents, contextId: string) => {
-  return `${webContents.id}-${contextId}`;
-};
-
-class ObjectsRegistry {
-  private nextId: number = 0
-
-  // Stores all objects by ref-counting.
-  // (id) => {object, count}
-  private storage: Record<number, { count: number, object: any }> = {}
-
-  // Stores the IDs + refCounts of objects referenced by WebContents.
-  // (ownerKey) => { id: refCount }
-  private owners: Record<string, Map<number, number>> = {}
-
-  private electronIds = new WeakMap<Object, number>();
-
-  // Register a new object and return its assigned ID. If the object is already
-  // registered then the already assigned ID would be returned.
-  add (webContents: WebContents, contextId: string, obj: any) {
-    // Get or assign an ID to the object.
-    const id = this.saveToStorage(obj);
-
-    // Add object to the set of referenced objects.
-    const ownerKey = getOwnerKey(webContents, contextId);
-    let owner = this.owners[ownerKey];
-    if (!owner) {
-      owner = this.owners[ownerKey] = new Map();
-      this.registerDeleteListener(webContents, contextId);
-    }
-    if (!owner.has(id)) {
-      owner.set(id, 0);
-      // Increase reference count if not referenced before.
-      this.storage[id].count++;
-    }
-
-    owner.set(id, owner.get(id)! + 1);
-    return id;
-  }
-
-  // Get an object according to its ID.
-  get (id: number) {
-    const pointer = this.storage[id];
-    if (pointer != null) return pointer.object;
-  }
-
-  // Dereference an object according to its ID.
-  // Note that an object may be double-freed (cleared when page is reloaded, and
-  // then garbage collected in old page).
-  remove (webContents: WebContents, contextId: string, id: number) {
-    const ownerKey = getOwnerKey(webContents, contextId);
-    const owner = this.owners[ownerKey];
-    if (owner && owner.has(id)) {
-      const newRefCount = owner.get(id)! - 1;
-
-      // Only completely remove if the number of references GCed in the
-      // renderer is the same as the number of references we sent them
-      if (newRefCount <= 0) {
-        // Remove the reference in owner.
-        owner.delete(id);
-        // Dereference from the storage.
-        this.dereference(id);
-      } else {
-        owner.set(id, newRefCount);
-      }
-    }
-  }
-
-  // Clear all references to objects refrenced by the WebContents.
-  clear (webContents: WebContents, contextId: string) {
-    const ownerKey = getOwnerKey(webContents, contextId);
-    const owner = this.owners[ownerKey];
-    if (!owner) return;
-
-    for (const id of owner.keys()) this.dereference(id);
-
-    delete this.owners[ownerKey];
-  }
-
-  // Private: Saves the object into storage and assigns an ID for it.
-  saveToStorage (object: any) {
-    let id = this.electronIds.get(object);
-    if (!id) {
-      id = ++this.nextId;
-      this.storage[id] = {
-        count: 0,
-        object: object
-      };
-      this.electronIds.set(object, id);
-    }
-    return id;
-  }
-
-  // Private: Dereference the object from store.
-  dereference (id: number) {
-    const pointer = this.storage[id];
-    if (pointer == null) {
-      return;
-    }
-    pointer.count -= 1;
-    if (pointer.count === 0) {
-      this.electronIds.delete(pointer.object);
-      delete this.storage[id];
-    }
-  }
-
-  // Private: Clear the storage when renderer process is destroyed.
-  registerDeleteListener (webContents: WebContents, contextId: string) {
-    // contextId => ${processHostId}-${contextCount}
-    const processHostId = contextId.split('-')[0];
-    const listener = (_: any, deletedProcessHostId: string) => {
-      if (deletedProcessHostId &&
-          deletedProcessHostId.toString() === processHostId) {
-        webContents.removeListener('render-view-deleted' as any, listener);
-        this.clear(webContents, contextId);
-      }
-    };
-    // Note that the "render-view-deleted" event may not be emitted on time when
-    // the renderer process get destroyed because of navigation, we rely on the
-    // renderer process to send "ELECTRON_BROWSER_CONTEXT_RELEASE" message to
-    // guard this situation.
-    webContents.on('render-view-deleted' as any, listener);
-  }
-}
-
-export default new ObjectsRegistry();

+ 0 - 519
lib/browser/remote/server.ts

@@ -1,519 +0,0 @@
-import * as electron from 'electron/main';
-import { EventEmitter } from 'events';
-import objectsRegistry from '@electron/internal/browser/remote/objects-registry';
-import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
-import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
-import type { MetaTypeFromRenderer, ObjectMember, MetaType, ObjProtoDescriptor } from '@electron/internal/common/remote/types';
-import { IPC_MESSAGES } from '@electron/internal/common/remote/ipc-messages';
-
-const v8Util = process._linkedBinding('electron_common_v8_util');
-const eventBinding = process._linkedBinding('electron_browser_event');
-const features = process._linkedBinding('electron_common_features');
-
-if (!features.isRemoteModuleEnabled()) {
-  throw new Error('remote module is disabled');
-}
-
-// The internal properties of Function.
-const FUNCTION_PROPERTIES = [
-  'length', 'name', 'arguments', 'caller', 'prototype'
-];
-
-type RendererFunctionId = [string, number] // [contextId, funcId]
-type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: [number, number] };
-type CallIntoRenderer = (...args: any[]) => void
-
-// The remote functions in renderer processes.
-const rendererFunctionCache = new Map<string, WeakRef<CallIntoRenderer>>();
-// eslint-disable-next-line no-undef
-const finalizationRegistry = new FinalizationRegistry((fi: FinalizerInfo) => {
-  const mapKey = fi.id[0] + '~' + fi.id[1];
-  const ref = rendererFunctionCache.get(mapKey);
-  if (ref !== undefined && ref.deref() === undefined) {
-    rendererFunctionCache.delete(mapKey);
-    if (!fi.webContents.isDestroyed()) {
-      try {
-        fi.webContents._sendToFrameInternal(fi.frameId, IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, fi.id[0], fi.id[1]);
-      } catch (error) {
-        console.warn(`_sendToFrameInternal() failed: ${error}`);
-      }
-    }
-  }
-});
-
-function getCachedRendererFunction (id: RendererFunctionId): CallIntoRenderer | undefined {
-  const mapKey = id[0] + '~' + id[1];
-  const ref = rendererFunctionCache.get(mapKey);
-  if (ref !== undefined) {
-    const deref = ref.deref();
-    if (deref !== undefined) return deref;
-  }
-}
-function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebContents, frameId: [number, number], value: CallIntoRenderer) {
-  // eslint-disable-next-line no-undef
-  const wr = new WeakRef<CallIntoRenderer>(value);
-  const mapKey = id[0] + '~' + id[1];
-  rendererFunctionCache.set(mapKey, wr);
-  finalizationRegistry.register(value, {
-    id,
-    webContents: wc,
-    frameId
-  } as FinalizerInfo);
-  return value;
-}
-
-const locationInfo = new WeakMap<Object, string>();
-
-// Return the description of object's members:
-const getObjectMembers = function (object: any): ObjectMember[] {
-  let names = Object.getOwnPropertyNames(object);
-  // For Function, we should not override following properties even though they
-  // are "own" properties.
-  if (typeof object === 'function') {
-    names = names.filter((name) => {
-      return !FUNCTION_PROPERTIES.includes(name);
-    });
-  }
-  // Map properties to descriptors.
-  return names.map((name) => {
-    const descriptor = Object.getOwnPropertyDescriptor(object, name)!;
-    let type: ObjectMember['type'];
-    let writable = false;
-    if (descriptor.get === undefined && typeof object[name] === 'function') {
-      type = 'method';
-    } else {
-      if (descriptor.set || descriptor.writable) writable = true;
-      type = 'get';
-    }
-    return { name, enumerable: descriptor.enumerable, writable, type };
-  });
-};
-
-// Return the description of object's prototype.
-const getObjectPrototype = function (object: any): ObjProtoDescriptor {
-  const proto = Object.getPrototypeOf(object);
-  if (proto === null || proto === Object.prototype) return null;
-  return {
-    members: getObjectMembers(proto),
-    proto: getObjectPrototype(proto)
-  };
-};
-
-// Convert a real value into meta data.
-const valueToMeta = function (sender: electron.WebContents, contextId: string, value: any, optimizeSimpleObject = false): MetaType {
-  // Determine the type of value.
-  let type: MetaType['type'];
-
-  switch (typeof value) {
-    case 'object':
-      // Recognize certain types of objects.
-      if (value instanceof Buffer) {
-        type = 'buffer';
-      } else if (value && value.constructor && value.constructor.name === 'NativeImage') {
-        type = 'nativeimage';
-      } else if (Array.isArray(value)) {
-        type = 'array';
-      } else if (value instanceof Error) {
-        type = 'error';
-      } else if (isSerializableObject(value)) {
-        type = 'value';
-      } else if (isPromise(value)) {
-        type = 'promise';
-      } else if (Object.prototype.hasOwnProperty.call(value, 'callee') && value.length != null) {
-        // Treat the arguments object as array.
-        type = 'array';
-      } else if (optimizeSimpleObject && v8Util.getHiddenValue(value, 'simple')) {
-        // Treat simple objects as value.
-        type = 'value';
-      } else {
-        type = 'object';
-      }
-      break;
-    case 'function':
-      type = 'function';
-      break;
-    default:
-      type = 'value';
-      break;
-  }
-
-  // Fill the meta object according to value's type.
-  if (type === 'array') {
-    return {
-      type,
-      members: value.map((el: any) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
-    };
-  } else if (type === 'nativeimage') {
-    return { type, value: serialize(value) };
-  } else if (type === 'object' || type === 'function') {
-    return {
-      type,
-      name: value.constructor ? value.constructor.name : '',
-      // Reference the original value if it's an object, because when it's
-      // passed to renderer we would assume the renderer keeps a reference of
-      // it.
-      id: objectsRegistry.add(sender, contextId, value),
-      members: getObjectMembers(value),
-      proto: getObjectPrototype(value)
-    };
-  } else if (type === 'buffer') {
-    return { type, value };
-  } else if (type === 'promise') {
-    // Add default handler to prevent unhandled rejections in main process
-    // Instead they should appear in the renderer process
-    value.then(function () {}, function () {});
-
-    return {
-      type,
-      then: valueToMeta(sender, contextId, function (onFulfilled: Function, onRejected: Function) {
-        value.then(onFulfilled, onRejected);
-      })
-    };
-  } else if (type === 'error') {
-    return {
-      type,
-      value,
-      members: Object.keys(value).map(name => ({
-        name,
-        value: valueToMeta(sender, contextId, value[name])
-      }))
-    };
-  } else {
-    return {
-      type: 'value',
-      value
-    };
-  }
-};
-
-const throwRPCError = function (message: string) {
-  const error = new Error(message) as Error & {code: string, errno: number};
-  error.code = 'EBADRPC';
-  error.errno = -72;
-  throw error;
-};
-
-const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...args: any[]) => void) => {
-  const location = locationInfo.get(callIntoRenderer);
-  let message = 'Attempting to call a function in a renderer window that has been closed or released.' +
-    `\nFunction provided here: ${location}`;
-
-  if (sender instanceof EventEmitter) {
-    const remoteEvents = sender.eventNames().filter((eventName) => {
-      return sender.listeners(eventName).includes(callIntoRenderer);
-    });
-
-    if (remoteEvents.length > 0) {
-      message += `\nRemote event names: ${remoteEvents.join(', ')}`;
-      remoteEvents.forEach((eventName) => {
-        sender.removeListener(eventName, callIntoRenderer);
-      });
-    }
-  }
-
-  console.warn(message);
-};
-
-const fakeConstructor = (constructor: Function, name: string) =>
-  new Proxy(Object, {
-    get (target, prop, receiver) {
-      if (prop === 'name') {
-        return name;
-      } else {
-        return Reflect.get(target, prop, receiver);
-      }
-    }
-  });
-
-// Convert array of meta data from renderer into array of real values.
-const unwrapArgs = function (sender: electron.WebContents, frameId: [number, number], contextId: string, args: any[]) {
-  const metaToValue = function (meta: MetaTypeFromRenderer): any {
-    switch (meta.type) {
-      case 'nativeimage':
-        return deserialize(meta.value);
-      case 'value':
-        return meta.value;
-      case 'remote-object':
-        return objectsRegistry.get(meta.id);
-      case 'array':
-        return unwrapArgs(sender, frameId, contextId, meta.value);
-      case 'buffer':
-        return Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength);
-      case 'promise':
-        return Promise.resolve({
-          then: metaToValue(meta.then)
-        });
-      case 'object': {
-        const ret: any = meta.name !== 'Object' ? Object.create({
-          constructor: fakeConstructor(Object, meta.name)
-        }) : {};
-
-        for (const { name, value } of meta.members) {
-          ret[name] = metaToValue(value);
-        }
-        return ret;
-      }
-      case 'function-with-return-value': {
-        const returnValue = metaToValue(meta.value);
-        return function () {
-          return returnValue;
-        };
-      }
-      case 'function': {
-        // Merge contextId and meta.id, since meta.id can be the same in
-        // different webContents.
-        const objectId: [string, number] = [contextId, meta.id];
-
-        // Cache the callbacks in renderer.
-        const cachedFunction = getCachedRendererFunction(objectId);
-        if (cachedFunction !== undefined) { return cachedFunction; }
-
-        const callIntoRenderer = function (this: any, ...args: any[]) {
-          let succeed = false;
-          if (!sender.isDestroyed()) {
-            try {
-              succeed = sender._sendToFrameInternal(frameId, IPC_MESSAGES.RENDERER_CALLBACK, contextId, meta.id, valueToMeta(sender, contextId, args));
-            } catch (error) {
-              console.warn(`_sendToFrameInternal() failed: ${error}`);
-            }
-          }
-          if (!succeed) {
-            removeRemoteListenersAndLogWarning(this, callIntoRenderer);
-          }
-        };
-        locationInfo.set(callIntoRenderer, meta.location);
-        Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
-
-        setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);
-        return callIntoRenderer;
-      }
-      default:
-        throw new TypeError(`Unknown type: ${(meta as any).type}`);
-    }
-  };
-  return args.map(metaToValue);
-};
-
-const isRemoteModuleEnabledImpl = function (contents: electron.WebContents) {
-  const webPreferences = contents.getLastWebPreferences() || {};
-  return webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : false;
-};
-
-const isRemoteModuleEnabledCache = new WeakMap();
-
-export const isRemoteModuleEnabled = function (contents: electron.WebContents) {
-  if (!isRemoteModuleEnabledCache.has(contents)) {
-    isRemoteModuleEnabledCache.set(contents, isRemoteModuleEnabledImpl(contents));
-  }
-
-  return isRemoteModuleEnabledCache.get(contents);
-};
-
-const handleRemoteCommand = function (channel: string, handler: (event: ElectronInternal.IpcMainInternalEvent, contextId: string, ...args: any[]) => void) {
-  ipcMainInternal.on(channel, (event, contextId: string, ...args: any[]) => {
-    let returnValue;
-    if (!isRemoteModuleEnabled(event.sender)) {
-      event.returnValue = null;
-      return;
-    }
-
-    try {
-      returnValue = handler(event, contextId, ...args);
-    } catch (error) {
-      returnValue = {
-        type: 'exception',
-        value: valueToMeta(event.sender, contextId, error)
-      };
-    }
-
-    if (returnValue !== undefined) {
-      event.returnValue = returnValue;
-    }
-  });
-};
-
-const emitCustomEvent = function (contents: electron.WebContents, eventName: string, ...args: any[]) {
-  const event = eventBinding.createWithSender(contents);
-
-  electron.app.emit(eventName, event, contents, ...args);
-  contents.emit(eventName, event, ...args);
-
-  return event;
-};
-
-const logStack = function (contents: electron.WebContents, code: string, stack: string | undefined) {
-  if (stack) {
-    console.warn(`WebContents (${contents.id}): ${code}`, stack);
-  }
-};
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_WRONG_CONTEXT_ERROR, function (event, contextId, passedContextId, id) {
-  const objectId: [string, number] = [passedContextId, id];
-  const cachedFunction = getCachedRendererFunction(objectId);
-  if (cachedFunction === undefined) {
-    // Do nothing if the error has already been reported before.
-    return;
-  }
-  removeRemoteListenersAndLogWarning(event.sender, cachedFunction);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_REQUIRE, function (event, contextId, moduleName, stack) {
-  logStack(event.sender, `remote.require('${moduleName}')`, stack);
-  const customEvent = emitCustomEvent(event.sender, 'remote-require', moduleName);
-
-  if (customEvent.returnValue === undefined) {
-    if (customEvent.defaultPrevented) {
-      throw new Error(`Blocked remote.require('${moduleName}')`);
-    } else {
-      customEvent.returnValue = process.mainModule.require(moduleName);
-    }
-  }
-
-  return valueToMeta(event.sender, contextId, customEvent.returnValue);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_BUILTIN, function (event, contextId, moduleName, stack) {
-  logStack(event.sender, `remote.getBuiltin('${moduleName}')`, stack);
-  const customEvent = emitCustomEvent(event.sender, 'remote-get-builtin', moduleName);
-
-  if (customEvent.returnValue === undefined) {
-    if (customEvent.defaultPrevented) {
-      throw new Error(`Blocked remote.getBuiltin('${moduleName}')`);
-    } else {
-      customEvent.returnValue = (electron as any)[moduleName];
-    }
-  }
-
-  return valueToMeta(event.sender, contextId, customEvent.returnValue);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_GLOBAL, function (event, contextId, globalName, stack) {
-  logStack(event.sender, `remote.getGlobal('${globalName}')`, stack);
-  const customEvent = emitCustomEvent(event.sender, 'remote-get-global', globalName);
-
-  if (customEvent.returnValue === undefined) {
-    if (customEvent.defaultPrevented) {
-      throw new Error(`Blocked remote.getGlobal('${globalName}')`);
-    } else {
-      customEvent.returnValue = (global as any)[globalName];
-    }
-  }
-
-  return valueToMeta(event.sender, contextId, customEvent.returnValue);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_CURRENT_WINDOW, function (event, contextId, stack) {
-  logStack(event.sender, 'remote.getCurrentWindow()', stack);
-  const customEvent = emitCustomEvent(event.sender, 'remote-get-current-window');
-
-  if (customEvent.returnValue === undefined) {
-    if (customEvent.defaultPrevented) {
-      throw new Error('Blocked remote.getCurrentWindow()');
-    } else {
-      customEvent.returnValue = event.sender.getOwnerBrowserWindow();
-    }
-  }
-
-  return valueToMeta(event.sender, contextId, customEvent.returnValue);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_CURRENT_WEB_CONTENTS, function (event, contextId, stack) {
-  logStack(event.sender, 'remote.getCurrentWebContents()', stack);
-  const customEvent = emitCustomEvent(event.sender, 'remote-get-current-web-contents');
-
-  if (customEvent.returnValue === undefined) {
-    if (customEvent.defaultPrevented) {
-      throw new Error('Blocked remote.getCurrentWebContents()');
-    } else {
-      customEvent.returnValue = event.sender;
-    }
-  }
-
-  return valueToMeta(event.sender, contextId, customEvent.returnValue);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_CONSTRUCTOR, function (event, contextId, id, args) {
-  args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
-  const constructor = objectsRegistry.get(id);
-
-  if (constructor == null) {
-    throwRPCError(`Cannot call constructor on missing remote object ${id}`);
-  }
-
-  return valueToMeta(event.sender, contextId, new constructor(...args));
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_FUNCTION_CALL, function (event, contextId, id, args) {
-  args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
-  const func = objectsRegistry.get(id);
-
-  if (func == null) {
-    throwRPCError(`Cannot call function on missing remote object ${id}`);
-  }
-
-  try {
-    return valueToMeta(event.sender, contextId, func(...args), true);
-  } catch (error) {
-    const err = new Error(`Could not call remote function '${func.name || 'anonymous'}'. Check that the function signature is correct. Underlying error: ${error.message}\nUnderlying stack: ${error.stack}\n`);
-    (err as any).cause = error;
-    throw err;
-  }
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CONSTRUCTOR, function (event, contextId, id, method, args) {
-  args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
-  const object = objectsRegistry.get(id);
-
-  if (object == null) {
-    throwRPCError(`Cannot call constructor '${method}' on missing remote object ${id}`);
-  }
-
-  return valueToMeta(event.sender, contextId, new object[method](...args));
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CALL, function (event, contextId, id, method, args) {
-  args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
-  const object = objectsRegistry.get(id);
-
-  if (object == null) {
-    throwRPCError(`Cannot call method '${method}' on missing remote object ${id}`);
-  }
-
-  try {
-    return valueToMeta(event.sender, contextId, object[method](...args), true);
-  } catch (error) {
-    const err = new Error(`Could not call remote method '${method}'. Check that the method signature is correct. Underlying error: ${error.message}\nUnderlying stack: ${error.stack}\n`);
-    (err as any).cause = error;
-    throw err;
-  }
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_SET, function (event, contextId, id, name, args) {
-  args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
-  const obj = objectsRegistry.get(id);
-
-  if (obj == null) {
-    throwRPCError(`Cannot set property '${name}' on missing remote object ${id}`);
-  }
-
-  obj[name] = args[0];
-  return null;
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_GET, function (event, contextId, id, name) {
-  const obj = objectsRegistry.get(id);
-
-  if (obj == null) {
-    throwRPCError(`Cannot get property '${name}' on missing remote object ${id}`);
-  }
-
-  return valueToMeta(event.sender, contextId, obj[name]);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_DEREFERENCE, function (event, contextId, id) {
-  objectsRegistry.remove(event.sender, contextId, id);
-});
-
-handleRemoteCommand(IPC_MESSAGES.BROWSER_CONTEXT_RELEASE, (event, contextId) => {
-  objectsRegistry.clear(event.sender, contextId);
-});

+ 1 - 1
lib/common/parse-features-string.ts

@@ -75,7 +75,7 @@ export function parseWebViewWebPreferences (preferences: string) {
   return parseCommaSeparatedKeyValue(preferences, false).parsed;
 }
 
-const allowedWebPreferences = ['zoomFactor', 'nodeIntegration', 'enableRemoteModule', 'javascript', 'contextIsolation', 'webviewTag'] as const;
+const allowedWebPreferences = ['zoomFactor', 'nodeIntegration', 'javascript', 'contextIsolation', 'webviewTag'] as const;
 type AllowedWebPreference = (typeof allowedWebPreferences)[number];
 
 /**

+ 0 - 85
lib/common/remote/types.ts

@@ -1,85 +0,0 @@
-import type { Size } from 'electron/main';
-import type { NativeImage } from 'electron/common';
-
-export type ObjectMember = {
-  name: string,
-  value?: any,
-  enumerable?: boolean,
-  writable?: boolean,
-  type?: 'method' | 'get'
-}
-
-export type ObjProtoDescriptor = {
-  members: ObjectMember[],
-  proto: ObjProtoDescriptor
-} | null
-
-export type MetaType = {
-  type: 'object' | 'function',
-  name: string,
-  members: ObjectMember[],
-  proto: ObjProtoDescriptor,
-  id: number,
-} | {
-  type: 'value',
-  value: any,
-} | {
-  type: 'buffer',
-  value: Uint8Array,
-} | {
-  type: 'array',
-  members: MetaType[]
-} | {
-  type: 'error',
-  value: Error,
-  members: ObjectMember[]
-} | {
-  type: 'exception',
-  value: MetaType,
-} | {
-  type: 'promise',
-  then: MetaType
-} | {
-  type: 'nativeimage'
-  value: NativeImage
-}
-
-export type MetaTypeFromRenderer = {
-  type: 'value',
-  value: any
-} | {
-  type: 'remote-object',
-  id: number
-} | {
-  type: 'array',
-  value: MetaTypeFromRenderer[]
-} | {
-  type: 'buffer',
-  value: Uint8Array
-} | {
-  type: 'promise',
-  then: MetaTypeFromRenderer
-} | {
-  type: 'object',
-  name: string,
-  members: {
-    name: string,
-    value: MetaTypeFromRenderer
-  }[]
-} | {
-  type: 'function-with-return-value',
-  value: MetaTypeFromRenderer
-} | {
-  type: 'function',
-  id: number,
-  location: string,
-  length: number
-} | {
-  type: 'nativeimage',
-  value: {
-    size: Size,
-    buffer: Buffer,
-    scaleFactor: number,
-    dataURL: string
-  }[]
-}

+ 0 - 11
lib/renderer/api/module-list.ts

@@ -1,7 +1,3 @@
-const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
-
-const enableRemoteModule = getWebPreference(window, 'enableRemoteModule');
-
 // Renderer side modules, please sort alphabetically.
 export const rendererModuleList: ElectronInternal.ModuleEntry[] = [
   { name: 'contextBridge', loader: () => require('./context-bridge') },
@@ -17,10 +13,3 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
     loader: () => require('@electron/internal/renderer/api/desktop-capturer')
   });
 }
-
-if (BUILDFLAG(ENABLE_REMOTE_MODULE) && enableRemoteModule) {
-  rendererModuleList.push({
-    name: 'remote',
-    loader: () => require('@electron/internal/renderer/api/remote')
-  });
-}

+ 0 - 395
lib/renderer/api/remote.ts

@@ -1,395 +0,0 @@
-import { CallbacksRegistry } from '../remote/callbacks-registry';
-import { isPromise, isSerializableObject, serialize, deserialize } from '../../common/type-utils';
-import { MetaTypeFromRenderer, ObjectMember, ObjProtoDescriptor, MetaType } from '../../common/remote/types';
-import { ipcRendererInternal } from '../ipc-renderer-internal';
-import type { BrowserWindow, WebContents } from 'electron/main';
-import deprecate from '@electron/internal/common/api/deprecate';
-import { browserModuleNames } from '@electron/internal/browser/api/module-names';
-import { commonModuleList } from '@electron/internal/common/api/module-list';
-import { IPC_MESSAGES } from '@electron/internal/common/remote/ipc-messages';
-
-deprecate.log('The remote module is deprecated. Use https://github.com/electron/remote instead.');
-
-const v8Util = process._linkedBinding('electron_common_v8_util');
-const { hasSwitch } = process._linkedBinding('electron_common_command_line');
-
-const callbacksRegistry = new CallbacksRegistry();
-const remoteObjectCache = new Map();
-const finalizationRegistry = new FinalizationRegistry((id: number) => {
-  const ref = remoteObjectCache.get(id);
-  if (ref !== undefined && ref.deref() === undefined) {
-    remoteObjectCache.delete(id);
-    ipcRendererInternal.send(IPC_MESSAGES.BROWSER_DEREFERENCE, contextId, id, 0);
-  }
-});
-
-const electronIds = new WeakMap<Object, number>();
-const isReturnValue = new WeakSet<Object>();
-
-function getCachedRemoteObject (id: number) {
-  const ref = remoteObjectCache.get(id);
-  if (ref !== undefined) {
-    const deref = ref.deref();
-    if (deref !== undefined) return deref;
-  }
-}
-function setCachedRemoteObject (id: number, value: any) {
-  const wr = new WeakRef(value);
-  remoteObjectCache.set(id, wr);
-  finalizationRegistry.register(value, id);
-  return value;
-}
-
-// An unique ID that can represent current context.
-const contextId = v8Util.getHiddenValue<string>(global, 'contextId');
-
-// Notify the main process when current context is going to be released.
-// Note that when the renderer process is destroyed, the message may not be
-// sent, we also listen to the "render-view-deleted" event in the main process
-// to guard that situation.
-process.on('exit', () => {
-  const command = IPC_MESSAGES.BROWSER_CONTEXT_RELEASE;
-  ipcRendererInternal.send(command, contextId);
-});
-
-const IS_REMOTE_PROXY = Symbol('is-remote-proxy');
-
-// Convert the arguments object into an array of meta data.
-function wrapArgs (args: any[], visited = new Set()): any {
-  const valueToMeta = (value: any): any => {
-    // Check for circular reference.
-    if (visited.has(value)) {
-      return {
-        type: 'value',
-        value: null
-      };
-    }
-
-    if (value && value.constructor && value.constructor.name === 'NativeImage') {
-      return { type: 'nativeimage', value: serialize(value) };
-    } else if (Array.isArray(value)) {
-      visited.add(value);
-      const meta = {
-        type: 'array',
-        value: wrapArgs(value, visited)
-      };
-      visited.delete(value);
-      return meta;
-    } else if (value instanceof Buffer) {
-      return {
-        type: 'buffer',
-        value
-      };
-    } else if (isSerializableObject(value)) {
-      return {
-        type: 'value',
-        value
-      };
-    } else if (typeof value === 'object') {
-      if (isPromise(value)) {
-        return {
-          type: 'promise',
-          then: valueToMeta(function (onFulfilled: Function, onRejected: Function) {
-            value.then(onFulfilled, onRejected);
-          })
-        };
-      } else if (electronIds.has(value)) {
-        return {
-          type: 'remote-object',
-          id: electronIds.get(value)
-        };
-      }
-
-      const meta: MetaTypeFromRenderer = {
-        type: 'object',
-        name: value.constructor ? value.constructor.name : '',
-        members: []
-      };
-      visited.add(value);
-      for (const prop in value) { // eslint-disable-line guard-for-in
-        meta.members.push({
-          name: prop,
-          value: valueToMeta(value[prop])
-        });
-      }
-      visited.delete(value);
-      return meta;
-    } else if (typeof value === 'function' && isReturnValue.has(value)) {
-      return {
-        type: 'function-with-return-value',
-        value: valueToMeta(value())
-      };
-    } else if (typeof value === 'function') {
-      return {
-        type: 'function',
-        id: callbacksRegistry.add(value),
-        location: callbacksRegistry.getLocation(value),
-        length: value.length
-      };
-    } else {
-      return {
-        type: 'value',
-        value
-      };
-    }
-  };
-  return args.map(valueToMeta);
-}
-
-// Populate object's members from descriptors.
-// The |ref| will be kept referenced by |members|.
-// This matches |getObjectMembers| in rpc-server.
-function setObjectMembers (ref: any, object: any, metaId: number, members: ObjectMember[]) {
-  if (!Array.isArray(members)) return;
-
-  for (const member of members) {
-    if (Object.prototype.hasOwnProperty.call(object, member.name)) continue;
-
-    const descriptor: PropertyDescriptor = { enumerable: member.enumerable };
-    if (member.type === 'method') {
-      const remoteMemberFunction = function (this: any, ...args: any[]) {
-        let command;
-        if (this && this.constructor === remoteMemberFunction) {
-          command = IPC_MESSAGES.BROWSER_MEMBER_CONSTRUCTOR;
-        } else {
-          command = IPC_MESSAGES.BROWSER_MEMBER_CALL;
-        }
-        const ret = ipcRendererInternal.sendSync(command, contextId, metaId, member.name, wrapArgs(args));
-        return metaToValue(ret);
-      };
-
-      let descriptorFunction = proxyFunctionProperties(remoteMemberFunction, metaId, member.name);
-
-      descriptor.get = () => {
-        descriptorFunction.ref = ref; // The member should reference its object.
-        return descriptorFunction;
-      };
-      // Enable monkey-patch the method
-      descriptor.set = (value) => {
-        descriptorFunction = value;
-        return value;
-      };
-      descriptor.configurable = true;
-    } else if (member.type === 'get') {
-      descriptor.get = () => {
-        const command = IPC_MESSAGES.BROWSER_MEMBER_GET;
-        const meta = ipcRendererInternal.sendSync(command, contextId, metaId, member.name);
-        return metaToValue(meta);
-      };
-
-      if (member.writable) {
-        descriptor.set = (value) => {
-          const args = wrapArgs([value]);
-          const command = IPC_MESSAGES.BROWSER_MEMBER_SET;
-          const meta = ipcRendererInternal.sendSync(command, contextId, metaId, member.name, args);
-          if (meta != null) metaToValue(meta);
-          return value;
-        };
-      }
-    }
-
-    Object.defineProperty(object, member.name, descriptor);
-  }
-}
-
-// Populate object's prototype from descriptor.
-// This matches |getObjectPrototype| in rpc-server.
-function setObjectPrototype (ref: any, object: any, metaId: number, descriptor: ObjProtoDescriptor) {
-  if (descriptor === null) return;
-  const proto = {};
-  setObjectMembers(ref, proto, metaId, descriptor.members);
-  setObjectPrototype(ref, proto, metaId, descriptor.proto);
-  Object.setPrototypeOf(object, proto);
-}
-
-// Wrap function in Proxy for accessing remote properties
-function proxyFunctionProperties (remoteMemberFunction: Function, metaId: number, name: string) {
-  let loaded = false;
-
-  // Lazily load function properties
-  const loadRemoteProperties = () => {
-    if (loaded) return;
-    loaded = true;
-    const command = IPC_MESSAGES.BROWSER_MEMBER_GET;
-    const meta = ipcRendererInternal.sendSync(command, contextId, metaId, name);
-    setObjectMembers(remoteMemberFunction, remoteMemberFunction, meta.id, meta.members);
-  };
-
-  return new Proxy(remoteMemberFunction as any, {
-    set: (target, property, value) => {
-      if (property !== 'ref') loadRemoteProperties();
-      target[property] = value;
-      return true;
-    },
-    get: (target, property) => {
-      if (property === IS_REMOTE_PROXY) return true;
-      if (!Object.prototype.hasOwnProperty.call(target, property)) loadRemoteProperties();
-      const value = target[property];
-      if (property === 'toString' && typeof value === 'function') {
-        return value.bind(target);
-      }
-      return value;
-    },
-    ownKeys: (target) => {
-      loadRemoteProperties();
-      return Object.getOwnPropertyNames(target);
-    },
-    getOwnPropertyDescriptor: (target, property) => {
-      const descriptor = Object.getOwnPropertyDescriptor(target, property);
-      if (descriptor) return descriptor;
-      loadRemoteProperties();
-      return Object.getOwnPropertyDescriptor(target, property);
-    }
-  });
-}
-
-// Convert meta data from browser into real value.
-function metaToValue (meta: MetaType): any {
-  if (meta.type === 'value') {
-    return meta.value;
-  } else if (meta.type === 'array') {
-    return meta.members.map((member) => metaToValue(member));
-  } else if (meta.type === 'nativeimage') {
-    return deserialize(meta.value);
-  } else if (meta.type === 'buffer') {
-    return Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength);
-  } else if (meta.type === 'promise') {
-    return Promise.resolve({ then: metaToValue(meta.then) });
-  } else if (meta.type === 'error') {
-    return metaToError(meta);
-  } else if (meta.type === 'exception') {
-    if (meta.value.type === 'error') { throw metaToError(meta.value); } else { throw new Error(`Unexpected value type in exception: ${meta.value.type}`); }
-  } else {
-    let ret;
-    if ('id' in meta) {
-      const cached = getCachedRemoteObject(meta.id);
-      if (cached !== undefined) { return cached; }
-    }
-
-    // A shadow class to represent the remote function object.
-    if (meta.type === 'function') {
-      const remoteFunction = function (this: any, ...args: any[]) {
-        let command;
-        if (this && this.constructor === remoteFunction) {
-          command = IPC_MESSAGES.BROWSER_CONSTRUCTOR;
-        } else {
-          command = IPC_MESSAGES.BROWSER_FUNCTION_CALL;
-        }
-        const obj = ipcRendererInternal.sendSync(command, contextId, meta.id, wrapArgs(args));
-        return metaToValue(obj);
-      };
-      ret = remoteFunction;
-    } else {
-      ret = {};
-    }
-
-    setObjectMembers(ret, ret, meta.id, meta.members);
-    setObjectPrototype(ret, ret, meta.id, meta.proto);
-    if (ret.constructor && (ret.constructor as any)[IS_REMOTE_PROXY]) {
-      Object.defineProperty(ret.constructor, 'name', { value: meta.name });
-    }
-
-    // Track delegate obj's lifetime & tell browser to clean up when object is GCed.
-    electronIds.set(ret, meta.id);
-    setCachedRemoteObject(meta.id, ret);
-    return ret;
-  }
-}
-
-function metaToError (meta: { type: 'error', value: any, members: ObjectMember[] }) {
-  const obj = meta.value;
-  for (const { name, value } of meta.members) {
-    obj[name] = metaToValue(value);
-  }
-  return obj;
-}
-
-function handleMessage (channel: string, handler: Function) {
-  ipcRendererInternal.on(channel, (event, passedContextId, id, ...args) => {
-    if (passedContextId === contextId) {
-      handler(id, ...args);
-    } else {
-      // Message sent to an un-exist context, notify the error to main process.
-      ipcRendererInternal.send(IPC_MESSAGES.BROWSER_WRONG_CONTEXT_ERROR, contextId, passedContextId, id);
-    }
-  });
-}
-
-const enableStacks = hasSwitch('enable-api-filtering-logging');
-
-function getCurrentStack (): string | undefined {
-  const target = { stack: undefined as string | undefined };
-  if (enableStacks) {
-    Error.captureStackTrace(target, getCurrentStack);
-  }
-  return target.stack;
-}
-
-// Browser calls a callback in renderer.
-handleMessage(IPC_MESSAGES.RENDERER_CALLBACK, (id: number, args: any) => {
-  callbacksRegistry.apply(id, metaToValue(args));
-});
-
-// A callback in browser is released.
-handleMessage(IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, (id: number) => {
-  callbacksRegistry.remove(id);
-});
-
-exports.require = (module: string) => {
-  const command = IPC_MESSAGES.BROWSER_REQUIRE;
-  const meta = ipcRendererInternal.sendSync(command, contextId, module, getCurrentStack());
-  return metaToValue(meta);
-};
-
-// Alias to remote.require('electron').xxx.
-export function getBuiltin (module: string) {
-  const command = IPC_MESSAGES.BROWSER_GET_BUILTIN;
-  const meta = ipcRendererInternal.sendSync(command, contextId, module, getCurrentStack());
-  return metaToValue(meta);
-}
-
-export function getCurrentWindow (): BrowserWindow {
-  const command = IPC_MESSAGES.BROWSER_GET_CURRENT_WINDOW;
-  const meta = ipcRendererInternal.sendSync(command, contextId, getCurrentStack());
-  return metaToValue(meta);
-}
-
-// Get current WebContents object.
-export function getCurrentWebContents (): WebContents {
-  const command = IPC_MESSAGES.BROWSER_GET_CURRENT_WEB_CONTENTS;
-  const meta = ipcRendererInternal.sendSync(command, contextId, getCurrentStack());
-  return metaToValue(meta);
-}
-
-// Get a global object in browser.
-export function getGlobal<T = any> (name: string): T {
-  const command = IPC_MESSAGES.BROWSER_GET_GLOBAL;
-  const meta = ipcRendererInternal.sendSync(command, contextId, name, getCurrentStack());
-  return metaToValue(meta);
-}
-
-// Get the process object in browser.
-Object.defineProperty(exports, 'process', {
-  get: () => exports.getGlobal('process')
-});
-
-// Create a function that will return the specified value when called in browser.
-export function createFunctionWithReturnValue<T> (returnValue: T): () => T {
-  const func = () => returnValue;
-  isReturnValue.add(func);
-  return func;
-}
-
-const addBuiltinProperty = (name: string) => {
-  Object.defineProperty(exports, name, {
-    get: () => exports.getBuiltin(name)
-  });
-};
-
-const browserModules = commonModuleList.concat(browserModuleNames.map(name => ({ name, loader: () => {} })));
-
-// And add a helper receiver for each one.
-browserModules
-  .filter((m) => !m.private)
-  .map((m) => m.name)
-  .forEach(addBuiltinProperty);

+ 0 - 59
lib/renderer/remote/callbacks-registry.ts

@@ -1,59 +0,0 @@
-export class CallbacksRegistry {
-  private nextId: number = 0
-  private callbacks = new Map<number, Function>()
-  private callbackIds = new WeakMap<Function, number>();
-  private locationInfo = new WeakMap<Function, string>();
-
-  add (callback: Function) {
-    // The callback is already added.
-    let id = this.callbackIds.get(callback);
-    if (id != null) return id;
-
-    id = this.nextId += 1;
-
-    // Capture the location of the function and put it in the ID string,
-    // so that release errors can be tracked down easily.
-    const regexp = /at (.*)/gi;
-    const stackString = (new Error()).stack;
-    if (!stackString) return;
-
-    let filenameAndLine: string;
-    let match;
-
-    while ((match = regexp.exec(stackString)) !== null) {
-      const location = match[1];
-      if (location.includes('(native)')) continue;
-      if (location.includes('(<anonymous>)')) continue;
-      if (location.includes('electron/js2c')) continue;
-
-      const ref = /([^/^)]*)\)?$/gi.exec(location);
-      if (ref) filenameAndLine = ref![1];
-      break;
-    }
-
-    this.callbacks.set(id, callback);
-    this.callbackIds.set(callback, id);
-    this.locationInfo.set(callback, filenameAndLine!);
-    return id;
-  }
-
-  get (id: number) {
-    return this.callbacks.get(id) || function () {};
-  }
-
-  getLocation (callback: Function) {
-    return this.locationInfo.get(callback);
-  }
-
-  apply (id: number, ...args: any[]) {
-    return this.get(id).apply(global, ...args);
-  }
-
-  remove (id: number) {
-    const callback = this.callbacks.get(id);
-    if (callback) {
-      this.callbackIds.delete(callback);
-      this.callbacks.delete(id);
-    }
-  }
-}

+ 0 - 22
lib/renderer/security-warnings.ts

@@ -266,27 +266,6 @@ const warnAboutAllowedPopups = function () {
 //   #13 Disable or limit creation of new windows
 //   #14 Do not use `openExternal` with untrusted content
 
-// #15 on the checklist: Disable the `remote` module
-// Logs a warning message about the remote module
-
-const warnAboutRemoteModuleWithRemoteContent = function (webPreferences?: Electron.WebPreferences) {
-  if (!webPreferences || isLocalhost()) return;
-  const remoteModuleEnabled = webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : true;
-  if (!remoteModuleEnabled) return;
-
-  if (getIsRemoteProtocol()) {
-    const warning = `This renderer process has "enableRemoteModule" enabled
-    and attempted to load remote content from '${window.location}'. This
-    exposes users of this app to unnecessary security risks.\n${moreInformation}`;
-
-    console.warn('%cElectron Security Warning (enableRemoteModule)',
-      'font-weight: bold;', warning);
-  }
-};
-
-// Currently missing since we can't easily programmatically check for it:
-//   #16 Filter the `remote` module
-
 const logSecurityWarnings = function (
   webPreferences: Electron.WebPreferences | undefined, nodeIntegration: boolean
 ) {
@@ -298,7 +277,6 @@ const logSecurityWarnings = function (
   warnAboutEnableBlinkFeatures(webPreferences);
   warnAboutInsecureCSP();
   warnAboutAllowedPopups();
-  warnAboutRemoteModuleWithRemoteContent(webPreferences);
 };
 
 const getWebPreferences = async function () {

+ 0 - 15
lib/renderer/web-view/web-view-attributes.ts

@@ -259,20 +259,6 @@ class WebPreferencesAttribute extends WebViewAttribute {
   }
 }
 
-class EnableRemoteModuleAttribute extends WebViewAttribute {
-  constructor (webViewImpl: WebViewImpl) {
-    super(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, webViewImpl);
-  }
-
-  public getValue () {
-    return this.webViewImpl.webviewNode.getAttribute(this.name) !== 'false';
-  }
-
-  public setValue (value: any) {
-    this.webViewImpl.webviewNode.setAttribute(this.name, value ? 'true' : 'false');
-  }
-}
-
 // Sets up all of the webview attributes.
 WebViewImpl.prototype.setupWebViewAttributes = function () {
   this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION, new PartitionAttribute(this));
@@ -284,7 +270,6 @@ WebViewImpl.prototype.setupWebViewAttributes = function () {
   this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this));
   this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this));
   this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this));
-  this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, new EnableRemoteModuleAttribute(this));
   this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD, new PreloadAttribute(this));
   this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES, new BlinkFeaturesAttribute(this));
   this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES, new DisableBlinkFeaturesAttribute(this));

+ 0 - 1
lib/renderer/web-view/web-view-constants.ts

@@ -6,7 +6,6 @@ export const enum WEB_VIEW_CONSTANTS {
   ATTRIBUTE_HTTPREFERRER = 'httpreferrer',
   ATTRIBUTE_NODEINTEGRATION = 'nodeintegration',
   ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES = 'nodeintegrationinsubframes',
-  ATTRIBUTE_ENABLEREMOTEMODULE = 'enableremotemodule',
   ATTRIBUTE_PLUGINS = 'plugins',
   ATTRIBUTE_DISABLEWEBSECURITY = 'disablewebsecurity',
   ATTRIBUTE_ALLOWPOPUPS = 'allowpopups',

+ 0 - 1
lib/renderer/web-view/web-view-element.ts

@@ -29,7 +29,6 @@ const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof
         WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS,
         WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY,
         WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS,
-        WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE,
         WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD,
         WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES,
         WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES,

+ 0 - 11
lib/sandboxed_renderer/api/module-list.ts

@@ -1,7 +1,3 @@
-const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
-
-const enableRemoteModule = getWebPreference(window, 'enableRemoteModule');
-
 export const moduleList: ElectronInternal.ModuleEntry[] = [
   {
     name: 'contextBridge',
@@ -37,10 +33,3 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
     loader: () => require('@electron/internal/renderer/api/desktop-capturer')
   });
 }
-
-if (BUILDFLAG(ENABLE_REMOTE_MODULE) && enableRemoteModule) {
-  moduleList.push({
-    name: 'remote',
-    loader: () => require('@electron/internal/renderer/api/remote')
-  });
-}

+ 10 - 18
patches/chromium/allow_in_process_windows_to_have_different_web_prefs.patch

@@ -8,10 +8,10 @@ WebPreferences of in-process child windows, rather than relying on
 process-level command line switches, as before.
 
 diff --git a/third_party/blink/common/web_preferences/web_preferences.cc b/third_party/blink/common/web_preferences/web_preferences.cc
-index 758b0b1616ecf86b7dd090adce94395851d9baf2..55f20eb6266368c65fc0ec80d52caa332f85ecfb 100644
+index 758b0b1616ecf86b7dd090adce94395851d9baf2..43eed39329d5d4337471a2ae8512714d6c6cb841 100644
 --- a/third_party/blink/common/web_preferences/web_preferences.cc
 +++ b/third_party/blink/common/web_preferences/web_preferences.cc
-@@ -146,6 +146,29 @@ WebPreferences::WebPreferences()
+@@ -146,6 +146,28 @@ WebPreferences::WebPreferences()
        navigate_on_drag_drop(true),
        v8_cache_options(blink::mojom::V8CacheOptions::kDefault),
        record_whole_document(false),
@@ -21,7 +21,6 @@ index 758b0b1616ecf86b7dd090adce94395851d9baf2..55f20eb6266368c65fc0ec80d52caa33
 +      background_color(base::EmptyString()),
 +      opener_id(0),
 +      context_isolation(false),
-+      enable_remote_module(false),
 +      world_safe_execute_javascript(false),
 +      guest_instance_id(0),
 +      hidden_page(false),
@@ -42,7 +41,7 @@ index 758b0b1616ecf86b7dd090adce94395851d9baf2..55f20eb6266368c65fc0ec80d52caa33
        accelerated_video_decode_enabled(false),
        animation_policy(
 diff --git a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
-index ba1ba323ec45296c33b5931652a001d6bd24dbe0..663d47894592499531ff924c78b518325020dc04 100644
+index ba1ba323ec45296c33b5931652a001d6bd24dbe0..178cae9c389e48733fde982f4906d9748004dbe3 100644
 --- a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
 +++ b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
 @@ -24,6 +24,11 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
@@ -57,7 +56,7 @@ index ba1ba323ec45296c33b5931652a001d6bd24dbe0..663d47894592499531ff924c78b51832
        !data.ReadLazyFrameLoadingDistanceThresholdsPx(
            &out->lazy_frame_loading_distance_thresholds_px) ||
        !data.ReadLazyImageLoadingDistanceThresholdsPx(
-@@ -152,6 +157,27 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
+@@ -152,6 +157,26 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
    out->navigate_on_drag_drop = data.navigate_on_drag_drop();
    out->v8_cache_options = data.v8_cache_options();
    out->record_whole_document = data.record_whole_document();
@@ -66,7 +65,6 @@ index ba1ba323ec45296c33b5931652a001d6bd24dbe0..663d47894592499531ff924c78b51832
 +  out->disable_electron_site_instance_overrides = data.disable_electron_site_instance_overrides();
 +  out->opener_id = data.opener_id();
 +  out->context_isolation = data.context_isolation();
-+  out->enable_remote_module = data.enable_remote_module();
 +  out->world_safe_execute_javascript = data.world_safe_execute_javascript();
 +  out->guest_instance_id = data.guest_instance_id();
 +  out->hidden_page = data.hidden_page();
@@ -86,7 +84,7 @@ index ba1ba323ec45296c33b5931652a001d6bd24dbe0..663d47894592499531ff924c78b51832
    out->accelerated_video_decode_enabled =
        data.accelerated_video_decode_enabled();
 diff --git a/third_party/blink/public/common/web_preferences/web_preferences.h b/third_party/blink/public/common/web_preferences/web_preferences.h
-index ab727750abcb0253463e83c984bf1afd9e296021..cd4598e022b144c728990b47957baa031097dfc9 100644
+index ab727750abcb0253463e83c984bf1afd9e296021..fd2a58f20e0a725fb441dc8607e862717537bcf6 100644
 --- a/third_party/blink/public/common/web_preferences/web_preferences.h
 +++ b/third_party/blink/public/common/web_preferences/web_preferences.h
 @@ -9,6 +9,7 @@
@@ -97,7 +95,7 @@ index ab727750abcb0253463e83c984bf1afd9e296021..cd4598e022b144c728990b47957baa03
  #include "base/strings/string16.h"
  #include "base/time/time.h"
  #include "build/build_config.h"
-@@ -161,6 +162,29 @@ struct BLINK_COMMON_EXPORT WebPreferences {
+@@ -161,6 +162,28 @@ struct BLINK_COMMON_EXPORT WebPreferences {
    blink::mojom::V8CacheOptions v8_cache_options;
    bool record_whole_document;
  
@@ -107,7 +105,6 @@ index ab727750abcb0253463e83c984bf1afd9e296021..cd4598e022b144c728990b47957baa03
 +  std::string background_color;
 +  int opener_id;
 +  bool context_isolation;
-+  bool enable_remote_module;
 +  bool world_safe_execute_javascript;
 +  int guest_instance_id;
 +  bool hidden_page;
@@ -128,7 +125,7 @@ index ab727750abcb0253463e83c984bf1afd9e296021..cd4598e022b144c728990b47957baa03
    // only controls whether or not the "document.cookie" field is properly
    // connected to the backing store, for instance if you wanted to be able to
 diff --git a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
-index 68d33ca3be294fc79f6d5d1a6ae6a8dfd427f4b1..9663462132151638ad480f8431a0ea428c6f0563 100644
+index 68d33ca3be294fc79f6d5d1a6ae6a8dfd427f4b1..e8a2c0f48f61f31a96290c02489378795a9e9f6a 100644
 --- a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
 +++ b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
 @@ -6,6 +6,7 @@
@@ -139,7 +136,7 @@ index 68d33ca3be294fc79f6d5d1a6ae6a8dfd427f4b1..9663462132151638ad480f8431a0ea42
  #include "mojo/public/cpp/bindings/struct_traits.h"
  #include "net/nqe/effective_connection_type.h"
  #include "third_party/blink/public/common/common_export.h"
-@@ -441,6 +442,88 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
+@@ -441,6 +442,84 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
      return r.record_whole_document;
    }
  
@@ -164,10 +161,6 @@ index 68d33ca3be294fc79f6d5d1a6ae6a8dfd427f4b1..9663462132151638ad480f8431a0ea42
 +    return r.context_isolation;
 +  }
 +
-+  static bool enable_remote_module(const blink::web_pref::WebPreferences& r) {
-+    return r.enable_remote_module;
-+  }
-+
 +  static bool world_safe_execute_javascript(const blink::web_pref::WebPreferences& r) {
 +    return r.world_safe_execute_javascript;
 +  }
@@ -229,7 +222,7 @@ index 68d33ca3be294fc79f6d5d1a6ae6a8dfd427f4b1..9663462132151638ad480f8431a0ea42
      return r.cookie_enabled;
    }
 diff --git a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
-index 5428fa6e79ed60774fcd6e87dcd6a602143158b7..eb21ecde85e91aef14cbe8ad6fc9e1e7d9150a61 100644
+index 5428fa6e79ed60774fcd6e87dcd6a602143158b7..3f86e539fb4c70c690286f9eecf8d60bd23939af 100644
 --- a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
 +++ b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
 @@ -9,6 +9,7 @@ import "third_party/blink/public/mojom/css/preferred_contrast.mojom";
@@ -240,7 +233,7 @@ index 5428fa6e79ed60774fcd6e87dcd6a602143158b7..eb21ecde85e91aef14cbe8ad6fc9e1e7
  
  enum PointerType {
    kPointerNone                              = 1,             // 1 << 0
-@@ -211,6 +212,29 @@ struct WebPreferences {
+@@ -211,6 +212,28 @@ struct WebPreferences {
    V8CacheOptions v8_cache_options;
    bool record_whole_document;
  
@@ -250,7 +243,6 @@ index 5428fa6e79ed60774fcd6e87dcd6a602143158b7..eb21ecde85e91aef14cbe8ad6fc9e1e7
 +  string background_color;
 +  int32 opener_id;
 +  bool context_isolation;
-+  bool enable_remote_module;
 +  bool world_safe_execute_javascript;
 +  int32 guest_instance_id;
 +  bool hidden_page;

+ 0 - 5
shell/browser/web_contents_preferences.cc

@@ -422,11 +422,6 @@ void WebContentsPreferences::OverrideWebkitPrefs(
   // Run Electron APIs and preload script in isolated world
   prefs->context_isolation = IsEnabled(options::kContextIsolation, true);
 
-#if BUILDFLAG(ENABLE_REMOTE_MODULE)
-  // Whether to enable the remote module
-  prefs->enable_remote_module = IsEnabled(options::kEnableRemoteModule, false);
-#endif
-
   prefs->world_safe_execute_javascript =
       IsEnabled(options::kWorldSafeExecuteJavaScript, true);
 

+ 0 - 5
shell/common/api/BUILD.gn

@@ -14,9 +14,4 @@ mojom("mojo") {
   # interfaces aready included in blink_common.dll
   overridden_deps = [ "//third_party/blink/public/mojom:mojom_core" ]
   component_deps = [ "//third_party/blink/public/common" ]
-
-  enabled_features = []
-  if (enable_remote_module) {
-    enabled_features += [ "enable_remote_module" ]
-  }
 }

+ 0 - 5
shell/common/api/features.cc

@@ -22,10 +22,6 @@ bool IsOffscreenRenderingEnabled() {
   return BUILDFLAG(ENABLE_OSR);
 }
 
-bool IsRemoteModuleEnabled() {
-  return BUILDFLAG(ENABLE_REMOTE_MODULE);
-}
-
 bool IsPDFViewerEnabled() {
   return BUILDFLAG(ENABLE_PDF_VIEWER);
 }
@@ -78,7 +74,6 @@ void Initialize(v8::Local<v8::Object> exports,
   dict.SetMethod("isBuiltinSpellCheckerEnabled", &IsBuiltinSpellCheckerEnabled);
   dict.SetMethod("isDesktopCapturerEnabled", &IsDesktopCapturerEnabled);
   dict.SetMethod("isOffscreenRenderingEnabled", &IsOffscreenRenderingEnabled);
-  dict.SetMethod("isRemoteModuleEnabled", &IsRemoteModuleEnabled);
   dict.SetMethod("isPDFViewerEnabled", &IsPDFViewerEnabled);
   dict.SetMethod("isRunAsNodeEnabled", &IsRunAsNodeEnabled);
   dict.SetMethod("isFakeLocationProviderEnabled",

+ 0 - 4
shell/common/options_switches.cc

@@ -193,10 +193,6 @@ const char kHiddenPage[] = "hiddenPage";
 const char kSpellcheck[] = "spellcheck";
 #endif
 
-#if BUILDFLAG(ENABLE_REMOTE_MODULE)
-const char kEnableRemoteModule[] = "enableRemoteModule";
-#endif
-
 const char kEnableWebSQL[] = "enableWebSQL";
 
 const char kEnablePreferredSizeMode[] = "enablePreferredSizeMode";

+ 0 - 4
shell/common/options_switches.h

@@ -99,10 +99,6 @@ extern const char kHiddenPage[];
 extern const char kSpellcheck[];
 #endif
 
-#if BUILDFLAG(ENABLE_REMOTE_MODULE)
-extern const char kEnableRemoteModule[];
-#endif
-
 }  // namespace options
 
 // Following are actually command line switches, should be moved to other files.

+ 0 - 4
shell/renderer/api/electron_api_web_frame.cc

@@ -427,10 +427,6 @@ v8::Local<v8::Value> GetWebPreference(v8::Isolate* isolate,
     return gin::ConvertToV8(isolate, prefs.opener_id);
   } else if (pref_name == options::kContextIsolation) {
     return gin::ConvertToV8(isolate, prefs.context_isolation);
-#if BUILDFLAG(ENABLE_REMOTE_MODULE)
-  } else if (pref_name == options::kEnableRemoteModule) {
-    return gin::ConvertToV8(isolate, prefs.enable_remote_module);
-#endif
   } else if (pref_name == options::kWorldSafeExecuteJavaScript) {
     return gin::ConvertToV8(isolate, prefs.world_safe_execute_javascript);
   } else if (pref_name == options::kGuestInstanceID) {

+ 0 - 95
spec-main/api-app-spec.ts

@@ -466,101 +466,6 @@ describe('app module', () => {
         expect(webContents).to.equal(w.webContents);
       });
     });
-
-    ifdescribe(features.isRemoteModuleEnabled())('remote module filtering', () => {
-      it('should emit remote-require event when remote.require() is invoked', async () => {
-        w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            nodeIntegration: true,
-            enableRemoteModule: true,
-            contextIsolation: false
-          }
-        });
-        await w.loadURL('about:blank');
-
-        const promise = emittedOnce(app, 'remote-require');
-        w.webContents.executeJavaScript('require(\'electron\').remote.require(\'test\')');
-
-        const [, webContents, moduleName] = await promise;
-        expect(webContents).to.equal(w.webContents);
-        expect(moduleName).to.equal('test');
-      });
-
-      it('should emit remote-get-global event when remote.getGlobal() is invoked', async () => {
-        w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            nodeIntegration: true,
-            enableRemoteModule: true,
-            contextIsolation: false
-          }
-        });
-        await w.loadURL('about:blank');
-
-        const promise = emittedOnce(app, 'remote-get-global');
-        w.webContents.executeJavaScript('require(\'electron\').remote.getGlobal(\'test\')');
-
-        const [, webContents, globalName] = await promise;
-        expect(webContents).to.equal(w.webContents);
-        expect(globalName).to.equal('test');
-      });
-
-      it('should emit remote-get-builtin event when remote.getBuiltin() is invoked', async () => {
-        w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            nodeIntegration: true,
-            enableRemoteModule: true,
-            contextIsolation: false
-          }
-        });
-        await w.loadURL('about:blank');
-
-        const promise = emittedOnce(app, 'remote-get-builtin');
-        w.webContents.executeJavaScript('require(\'electron\').remote.app');
-
-        const [, webContents, moduleName] = await promise;
-        expect(webContents).to.equal(w.webContents);
-        expect(moduleName).to.equal('app');
-      });
-
-      it('should emit remote-get-current-window event when remote.getCurrentWindow() is invoked', async () => {
-        w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            nodeIntegration: true,
-            enableRemoteModule: true,
-            contextIsolation: false
-          }
-        });
-        await w.loadURL('about:blank');
-
-        const promise = emittedOnce(app, 'remote-get-current-window');
-        w.webContents.executeJavaScript('{ require(\'electron\').remote.getCurrentWindow() }');
-
-        const [, webContents] = await promise;
-        expect(webContents).to.equal(w.webContents);
-      });
-
-      it('should emit remote-get-current-web-contents event when remote.getCurrentWebContents() is invoked', async () => {
-        w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            nodeIntegration: true,
-            enableRemoteModule: true,
-            contextIsolation: false
-          }
-        });
-        await w.loadURL('about:blank');
-
-        const promise = emittedOnce(app, 'remote-get-current-web-contents');
-        w.webContents.executeJavaScript('{ require(\'electron\').remote.getCurrentWebContents() }');
-
-        const [, webContents] = await promise;
-        expect(webContents).to.equal(w.webContents);
-      });
-    });
   });
 
   describe('app.badgeCount', () => {

+ 0 - 149
spec-main/api-browser-window-spec.ts

@@ -2031,21 +2031,6 @@ describe('BrowserWindow module', () => {
         const [, test] = await emittedOnce(ipcMain, 'answer');
         expect(test).to.eql('preload');
       });
-      ifit(features.isRemoteModuleEnabled())('can successfully delete the Buffer global', async () => {
-        const preload = path.join(__dirname, 'fixtures', 'remote', 'delete-buffer.js');
-        const w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            nodeIntegration: true,
-            enableRemoteModule: true,
-            contextIsolation: false,
-            preload
-          }
-        });
-        w.loadFile(path.join(fixtures, 'api', 'preload.html'));
-        const [, test] = await emittedOnce(ipcMain, 'answer');
-        expect(test).to.eql(Buffer.from('buffer'));
-      });
       it('has synchronous access to all eventual window APIs', async () => {
         const preload = path.join(fixtures, 'module', 'access-blink-apis.js');
         const w = new BrowserWindow({
@@ -2158,61 +2143,6 @@ describe('BrowserWindow module', () => {
       });
     });
 
-    ifdescribe(features.isRemoteModuleEnabled())('"enableRemoteModule" option', () => {
-      const generateSpecs = (description: string, sandbox: boolean) => {
-        describe(description, () => {
-          const preload = path.join(__dirname, 'fixtures', 'remote', 'preload-remote.js');
-
-          it('disables the remote module by default', async () => {
-            const w = new BrowserWindow({
-              show: false,
-              webPreferences: {
-                preload,
-                sandbox
-              }
-            });
-            const p = emittedOnce(ipcMain, 'remote');
-            w.loadFile(path.join(fixtures, 'api', 'blank.html'));
-            const [, remote] = await p;
-            expect(remote).to.equal('undefined');
-          });
-
-          it('disables the remote module when false', async () => {
-            const w = new BrowserWindow({
-              show: false,
-              webPreferences: {
-                preload,
-                sandbox,
-                enableRemoteModule: false
-              }
-            });
-            const p = emittedOnce(ipcMain, 'remote');
-            w.loadFile(path.join(fixtures, 'api', 'blank.html'));
-            const [, remote] = await p;
-            expect(remote).to.equal('undefined');
-          });
-
-          it('enables the remote module when true', async () => {
-            const w = new BrowserWindow({
-              show: false,
-              webPreferences: {
-                preload,
-                sandbox,
-                enableRemoteModule: true
-              }
-            });
-            const p = emittedOnce(ipcMain, 'remote');
-            w.loadFile(path.join(fixtures, 'api', 'blank.html'));
-            const [, remote] = await p;
-            expect(remote).to.equal('object');
-          });
-        });
-      };
-
-      generateSpecs('without sandbox', false);
-      generateSpecs('with sandbox', true);
-    });
-
     describe('"sandbox" option', () => {
       const preload = path.join(path.resolve(__dirname, 'fixtures'), 'module', 'preload-sandbox.js');
 
@@ -2528,85 +2458,6 @@ describe('BrowserWindow module', () => {
         w.loadFile(path.join(fixtures, 'pages', 'window-open.html'));
       });
 
-      // see #9387
-      ifit(features.isRemoteModuleEnabled())('properly manages remote object references after page reload', (done) => {
-        const w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            preload,
-            sandbox: true,
-            enableRemoteModule: true,
-            contextIsolation: false
-          }
-        });
-        w.loadFile(path.join(__dirname, 'fixtures', 'api', 'sandbox.html'), { search: 'reload-remote' });
-
-        ipcMain.on('get-remote-module-path', (event) => {
-          event.returnValue = path.join(fixtures, 'module', 'hello.js');
-        });
-
-        let reload = false;
-        ipcMain.on('reloaded', (event) => {
-          event.returnValue = reload;
-          reload = !reload;
-        });
-
-        ipcMain.once('reload', (event) => {
-          event.sender.reload();
-        });
-
-        ipcMain.once('answer', (event, arg) => {
-          ipcMain.removeAllListeners('reloaded');
-          ipcMain.removeAllListeners('get-remote-module-path');
-          try {
-            expect(arg).to.equal('hi');
-            done();
-          } catch (e) {
-            done(e);
-          }
-        });
-      });
-
-      ifit(features.isRemoteModuleEnabled())('properly manages remote object references after page reload in child window', (done) => {
-        const w = new BrowserWindow({
-          show: false,
-          webPreferences: {
-            preload,
-            sandbox: true,
-            enableRemoteModule: true,
-            contextIsolation: false
-          }
-        });
-        w.webContents.setWindowOpenHandler(() => ({ action: 'allow', overrideBrowserWindowOptions: { webPreferences: { preload } } }));
-
-        w.loadFile(path.join(__dirname, 'fixtures', 'api', 'sandbox.html'), { search: 'reload-remote-child' });
-
-        ipcMain.on('get-remote-module-path', (event) => {
-          event.returnValue = path.join(fixtures, 'module', 'hello-child.js');
-        });
-
-        let reload = false;
-        ipcMain.on('reloaded', (event) => {
-          event.returnValue = reload;
-          reload = !reload;
-        });
-
-        ipcMain.once('reload', (event) => {
-          event.sender.reload();
-        });
-
-        ipcMain.once('answer', (event, arg) => {
-          ipcMain.removeAllListeners('reloaded');
-          ipcMain.removeAllListeners('get-remote-module-path');
-          try {
-            expect(arg).to.equal('hi child window');
-            done();
-          } catch (e) {
-            done(e);
-          }
-        });
-      });
-
       it('validates process APIs access in sandboxed renderer', async () => {
         const w = new BrowserWindow({
           show: false,

+ 0 - 47
spec-main/api-callbacks-registry-spec.ts

@@ -1,47 +0,0 @@
-import { expect } from 'chai';
-import { CallbacksRegistry } from '../lib/renderer/remote/callbacks-registry';
-import { ifdescribe } from './spec-helpers';
-
-const features = process._linkedBinding('electron_common_features');
-
-ifdescribe(features.isRemoteModuleEnabled())('CallbacksRegistry module', () => {
-  let registry: CallbacksRegistry;
-
-  beforeEach(() => {
-    registry = new CallbacksRegistry();
-  });
-
-  it('adds a callback to the registry', () => {
-    const cb = () => [1, 2, 3, 4, 5];
-    const key = registry.add(cb);
-
-    expect(key).to.exist('key');
-  });
-
-  it('returns a specified callback if it is in the registry', () => {
-    const cb = () => [1, 2, 3, 4, 5];
-    const key = registry.add(cb);
-    expect(key).to.exist('key');
-    const callback = registry.get(key!);
-
-    expect(callback.toString()).equal(cb.toString());
-  });
-
-  it('returns an empty function if the cb doesnt exist', () => {
-    const callback = registry.get(1);
-
-    expect(callback).to.be.a('function');
-  });
-
-  it('removes a callback to the registry', () => {
-    const cb = () => [1, 2, 3, 4, 5];
-    const key = registry.add(cb);
-    expect(key).to.exist('key');
-
-    registry.remove(key!);
-    const afterCB = registry.get(key!);
-
-    expect(afterCB).to.be.a('function');
-    expect(afterCB.toString()).to.not.equal(cb.toString());
-  });
-});

+ 0 - 1049
spec-main/api-remote-spec.ts

@@ -1,1049 +0,0 @@
-import * as path from 'path';
-import { expect } from 'chai';
-import { closeAllWindows } from './window-helpers';
-import { ifdescribe } from './spec-helpers';
-
-import { ipcMain, BrowserWindow } from 'electron/main';
-import { emittedOnce } from './events-helpers';
-import { NativeImage } from 'electron/common';
-import { serialize, deserialize } from '../lib/common/type-utils';
-import { protocol, nativeImage } from 'electron';
-
-const features = process._linkedBinding('electron_common_features');
-
-const expectPathsEqual = (path1: string, path2: string) => {
-  if (process.platform === 'win32') {
-    path1 = path1.toLowerCase();
-    path2 = path2.toLowerCase();
-  }
-  expect(path1).to.equal(path2);
-};
-
-function makeRemotely (windowGetter: () => BrowserWindow) {
-  async function remotely (script: Function, ...args: any[]) {
-    // executeJavaScript obfuscates the error if the script throws, so catch any
-    // errors manually.
-    const assembledScript = `(async function() {
-      try {
-        return { result: await Promise.resolve((${script})(...${JSON.stringify(args)})) }
-      } catch (e) {
-        return { error: e.message, stack: e.stack }
-      }
-    })()`;
-    const { result, error, stack } = await windowGetter().webContents.executeJavaScript(assembledScript);
-    if (error) {
-      const e = new Error(error);
-      e.stack = stack;
-      throw e;
-    }
-    return result;
-  }
-  remotely.it = (...vars: any[]) => (name: string, fn: Function) => {
-    it(name, async () => {
-      await remotely(fn, ...vars);
-    });
-  };
-  return remotely;
-}
-
-function makeWindow () {
-  let w: BrowserWindow;
-  before(async () => {
-    w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, enableRemoteModule: true, contextIsolation: false } });
-    await w.loadURL('about:blank');
-    await w.webContents.executeJavaScript(`{
-      const chai_1 = window.chai_1 = require('chai')
-      chai_1.use(require('chai-as-promised'))
-      chai_1.use(require('dirty-chai'))
-      null
-    }`);
-  });
-  after(closeAllWindows);
-  return () => w;
-}
-
-function makeEachWindow () {
-  let w: BrowserWindow;
-  beforeEach(async () => {
-    w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, enableRemoteModule: true, contextIsolation: false } });
-    await w.loadURL('about:blank');
-    await w.webContents.executeJavaScript(`{
-      const chai_1 = window.chai_1 = require('chai')
-      chai_1.use(require('chai-as-promised'))
-      chai_1.use(require('dirty-chai'))
-      null
-    }`);
-  });
-  afterEach(closeAllWindows);
-  return () => w;
-}
-
-describe('typeUtils serialization/deserialization', () => {
-  it('serializes and deserializes an empty NativeImage', () => {
-    const image = nativeImage.createEmpty();
-    const serializedImage = serialize(image);
-    const empty = deserialize(serializedImage);
-
-    expect(empty.isEmpty()).to.be.true();
-    expect(empty.getAspectRatio()).to.equal(1);
-    expect(empty.toDataURL()).to.equal('data:image/png;base64,');
-    expect(empty.toDataURL({ scaleFactor: 2.0 })).to.equal('data:image/png;base64,');
-    expect(empty.getSize()).to.deep.equal({ width: 0, height: 0 });
-    expect(empty.getBitmap()).to.be.empty();
-    expect(empty.getBitmap({ scaleFactor: 2.0 })).to.be.empty();
-    expect(empty.toBitmap()).to.be.empty();
-    expect(empty.toBitmap({ scaleFactor: 2.0 })).to.be.empty();
-    expect(empty.toJPEG(100)).to.be.empty();
-    expect(empty.toPNG()).to.be.empty();
-    expect(empty.toPNG({ scaleFactor: 2.0 })).to.be.empty();
-  });
-
-  it('serializes and deserializes a non-empty NativeImage', () => {
-    const dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAFklEQVQYlWP8//8/AwMDEwMDAwMDAwAkBgMBBMzldwAAAABJRU5ErkJggg==';
-    const image = nativeImage.createFromDataURL(dataURL);
-    const serializedImage = serialize(image);
-    const nonEmpty = deserialize(serializedImage);
-
-    expect(nonEmpty.isEmpty()).to.be.false();
-    expect(nonEmpty.getAspectRatio()).to.equal(1);
-    expect(nonEmpty.toDataURL()).to.not.be.empty();
-    expect(nonEmpty.toBitmap({ scaleFactor: 1.0 })).to.deep.equal(image.toBitmap({ scaleFactor: 1.0 }));
-    expect(nonEmpty.getSize()).to.deep.equal({ width: 2, height: 2 });
-    expect(nonEmpty.getBitmap()).to.not.be.empty();
-    expect(nonEmpty.toPNG()).to.not.be.empty();
-  });
-
-  it('serializes and deserializes a non-empty NativeImage with multiple representations', () => {
-    const image = nativeImage.createEmpty();
-
-    const dataURL1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYlWNgAAIAAAUAAdafFs0AAAAASUVORK5CYII=';
-    image.addRepresentation({ scaleFactor: 1.0, dataURL: dataURL1 });
-
-    const dataURL2 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAFklEQVQYlWP8//8/AwMDEwMDAwMDAwAkBgMBBMzldwAAAABJRU5ErkJggg==';
-    image.addRepresentation({ scaleFactor: 2.0, dataURL: dataURL2 });
-
-    const serializedImage = serialize(image);
-    const nonEmpty = deserialize(serializedImage);
-
-    expect(nonEmpty.isEmpty()).to.be.false();
-    expect(nonEmpty.getAspectRatio()).to.equal(1);
-    expect(nonEmpty.getSize()).to.deep.equal({ width: 1, height: 1 });
-    expect(nonEmpty.getBitmap()).to.not.be.empty();
-    expect(nonEmpty.getBitmap({ scaleFactor: 1.0 })).to.not.be.empty();
-    expect(nonEmpty.getBitmap({ scaleFactor: 2.0 })).to.not.be.empty();
-    expect(nonEmpty.toBitmap()).to.not.be.empty();
-    expect(nonEmpty.toBitmap({ scaleFactor: 1.0 })).to.deep.equal(image.toBitmap({ scaleFactor: 1.0 }));
-    expect(nonEmpty.toBitmap({ scaleFactor: 2.0 })).to.deep.equal(image.toBitmap({ scaleFactor: 2.0 }));
-    expect(nonEmpty.toPNG()).to.not.be.empty();
-    expect(nonEmpty.toPNG({ scaleFactor: 1.0 })).to.not.be.empty();
-    expect(nonEmpty.toPNG({ scaleFactor: 2.0 })).to.not.be.empty();
-    expect(nonEmpty.toDataURL()).to.not.be.empty();
-  });
-
-  it('serializes and deserializes an Array', () => {
-    const array = [1, 2, 3, 4, 5];
-    const serialized = serialize(array);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.deep.equal(array);
-  });
-
-  it('serializes and deserializes a Buffer', () => {
-    const buffer = Buffer.from('hello world!', 'utf-8');
-    const serialized = serialize(buffer);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.deep.equal(buffer);
-  });
-
-  it('serializes and deserializes a Boolean', () => {
-    const bool = true;
-    const serialized = serialize(bool);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.equal(bool);
-  });
-
-  it('serializes and deserializes a Date', () => {
-    const date = new Date();
-    const serialized = serialize(date);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.equal(date);
-  });
-
-  it('serializes and deserializes a Number', () => {
-    const number = 42;
-    const serialized = serialize(number);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.equal(number);
-  });
-
-  it('serializes and deserializes a Regexp', () => {
-    const regex = new RegExp('ab+c');
-    const serialized = serialize(regex);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.equal(regex);
-  });
-
-  it('serializes and deserializes a String', () => {
-    const str = 'hello world';
-    const serialized = serialize(str);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.equal(str);
-  });
-
-  it('serializes and deserializes an Error', () => {
-    const err = new Error('oh crap');
-    const serialized = serialize(err);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.equal(err);
-  });
-
-  it('serializes and deserializes a simple Object', () => {
-    const obj = { hello: 'world', 'answer-to-everything': 42 };
-    const serialized = serialize(obj);
-    const deserialized = deserialize(serialized);
-
-    expect(deserialized).to.deep.equal(obj);
-  });
-});
-
-ifdescribe(features.isRemoteModuleEnabled())('remote module', () => {
-  const fixtures = path.join(__dirname, 'fixtures', 'remote');
-
-  describe('', () => {
-    const w = makeWindow();
-    const remotely = makeRemotely(w);
-
-    describe('remote.getGlobal filtering', () => {
-      it('can return custom values', async () => {
-        w().webContents.once('remote-get-global', (event, name) => {
-          event.returnValue = name;
-        });
-        expect(await remotely(() => require('electron').remote.getGlobal('test'))).to.equal('test');
-      });
-
-      it('throws when no returnValue set', async () => {
-        w().webContents.once('remote-get-global', (event) => {
-          event.preventDefault();
-        });
-        await expect(remotely(() => require('electron').remote.getGlobal('test'))).to.eventually.be.rejected('Blocked remote.getGlobal(\'test\')');
-      });
-    });
-
-    describe('remote.getBuiltin filtering', () => {
-      it('can return custom values', async () => {
-        w().webContents.once('remote-get-builtin', (event, name) => {
-          event.returnValue = name;
-        });
-        expect(await remotely(() => (require('electron').remote as any).getBuiltin('test'))).to.equal('test');
-      });
-
-      it('throws when no returnValue set', async () => {
-        w().webContents.once('remote-get-builtin', (event) => {
-          event.preventDefault();
-        });
-        await expect(remotely(() => (require('electron').remote as any).getBuiltin('test'))).to.eventually.be.rejected('Blocked remote.getGlobal(\'test\')');
-      });
-    });
-
-    describe('remote.require filtering', () => {
-      it('can return custom values', async () => {
-        w().webContents.once('remote-require', (event, name) => {
-          event.returnValue = name;
-        });
-        expect(await remotely(() => require('electron').remote.require('test'))).to.equal('test');
-      });
-
-      it('throws when no returnValue set', async () => {
-        w().webContents.once('remote-require', (event) => {
-          event.preventDefault();
-        });
-        await expect(remotely(() => require('electron').remote.require('test'))).to.eventually.be.rejected('Blocked remote.require(\'test\')');
-      });
-    });
-
-    describe('remote.getCurrentWindow filtering', () => {
-      it('can return custom value', async () => {
-        w().webContents.once('remote-get-current-window', (e) => {
-          e.returnValue = 'some window';
-        });
-        expect(await remotely(() => require('electron').remote.getCurrentWindow())).to.equal('some window');
-      });
-
-      it('throws when no returnValue set', async () => {
-        w().webContents.once('remote-get-current-window', (event) => {
-          event.preventDefault();
-        });
-        await expect(remotely(() => require('electron').remote.getCurrentWindow())).to.eventually.be.rejected('Blocked remote.getCurrentWindow()');
-      });
-    });
-
-    describe('remote.getCurrentWebContents filtering', () => {
-      it('can return custom value', async () => {
-        w().webContents.once('remote-get-current-web-contents', (event) => {
-          event.returnValue = 'some web contents';
-        });
-        expect(await remotely(() => require('electron').remote.getCurrentWebContents())).to.equal('some web contents');
-      });
-
-      it('throws when no returnValue set', async () => {
-        w().webContents.once('remote-get-current-web-contents', (event) => {
-          event.preventDefault();
-        });
-        await expect(remotely(() => require('electron').remote.getCurrentWebContents())).to.eventually.be.rejected('Blocked remote.getCurrentWebContents()');
-      });
-    });
-  });
-
-  describe('remote references', () => {
-    const w = makeEachWindow();
-    it('render-view-deleted is sent when page is destroyed', (done) => {
-      w().webContents.once('render-view-deleted' as any, () => {
-        done();
-      });
-      w().destroy();
-    });
-
-    // The ELECTRON_BROWSER_CONTEXT_RELEASE message relies on this to work.
-    it('message can be sent on exit when page is being navigated', async () => {
-      after(() => { ipcMain.removeAllListeners('SENT_ON_EXIT'); });
-      w().webContents.once('did-finish-load', () => {
-        w().webContents.loadURL('about:blank');
-      });
-      w().loadFile(path.join(fixtures, 'send-on-exit.html'));
-      await emittedOnce(ipcMain, 'SENT_ON_EXIT');
-    });
-  });
-
-  describe('remote function in renderer', () => {
-    afterEach(() => {
-      ipcMain.removeAllListeners('done');
-    });
-    afterEach(closeAllWindows);
-
-    it('works when created in preload script', async () => {
-      const preload = path.join(fixtures, 'preload-remote-function.js');
-      const w = new BrowserWindow({
-        show: false,
-        webPreferences: {
-          preload,
-          enableRemoteModule: true,
-          contextIsolation: false
-        }
-      });
-      w.loadURL('about:blank');
-      await emittedOnce(ipcMain, 'done');
-    });
-  });
-
-  describe('remote objects registry', () => {
-    it('does not dereference until the render view is deleted (regression)', async () => {
-      const w = new BrowserWindow({
-        show: false,
-        webPreferences: {
-          nodeIntegration: true,
-          enableRemoteModule: true,
-          contextIsolation: false
-        }
-      });
-
-      const message = emittedOnce(ipcMain, 'error-message');
-      w.loadFile(path.join(fixtures, 'render-view-deleted.html'));
-      const [, msg] = await message;
-      expect(msg).to.match(/^Cannot call method 'getURL' on missing remote object/);
-    });
-  });
-
-  describe('nativeImage serialization', () => {
-    const w = makeWindow();
-    const remotely = makeRemotely(w);
-
-    it('can serialize an empty nativeImage from renderer to main', async () => {
-      const getImageEmpty = (img: NativeImage) => img.isEmpty();
-
-      w().webContents.once('remote-get-global', (event) => {
-        event.returnValue = getImageEmpty;
-      });
-
-      await expect(remotely(() => {
-        const emptyImage = require('electron').nativeImage.createEmpty();
-        return require('electron').remote.getGlobal('someFunction')(emptyImage);
-      })).to.eventually.be.true();
-    });
-
-    it('can serialize an empty nativeImage from main to renderer', async () => {
-      w().webContents.once('remote-get-global', (event) => {
-        const emptyImage = require('electron').nativeImage.createEmpty();
-        event.returnValue = emptyImage;
-      });
-
-      await expect(remotely(() => {
-        const image = require('electron').remote.getGlobal('someFunction');
-        return image.isEmpty();
-      })).to.eventually.be.true();
-    });
-
-    it('can serialize a non-empty nativeImage from renderer to main', async () => {
-      const getImageSize = (img: NativeImage) => img.getSize();
-
-      w().webContents.once('remote-get-global', (event) => {
-        event.returnValue = getImageSize;
-      });
-
-      await expect(remotely(() => {
-        const { nativeImage } = require('electron');
-        const nonEmptyImage = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAFklEQVQYlWP8//8/AwMDEwMDAwMDAwAkBgMBBMzldwAAAABJRU5ErkJggg==');
-        return require('electron').remote.getGlobal('someFunction')(nonEmptyImage);
-      })).to.eventually.deep.equal({ width: 2, height: 2 });
-    });
-
-    it('can serialize a non-empty nativeImage from main to renderer', async () => {
-      w().webContents.once('remote-get-global', (event) => {
-        const nonEmptyImage = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAFklEQVQYlWP8//8/AwMDEwMDAwMDAwAkBgMBBMzldwAAAABJRU5ErkJggg==');
-        event.returnValue = nonEmptyImage;
-      });
-
-      await expect(remotely(() => {
-        const image = require('electron').remote.getGlobal('someFunction');
-        return image.getSize();
-      })).to.eventually.deep.equal({ width: 2, height: 2 });
-    });
-
-    it('can properly create a menu with an nativeImage icon in the renderer', async () => {
-      await expect(remotely(() => {
-        const { remote, nativeImage } = require('electron');
-        remote.Menu.buildFromTemplate([
-          {
-            label: 'hello',
-            icon: nativeImage.createEmpty()
-          }
-        ]);
-      })).to.be.fulfilled();
-    });
-  });
-
-  describe('remote listeners', () => {
-    afterEach(closeAllWindows);
-
-    it('detaches listeners subscribed to destroyed renderers, and shows a warning', async () => {
-      const w = new BrowserWindow({
-        show: false,
-        webPreferences: {
-          nodeIntegration: true,
-          enableRemoteModule: true,
-          contextIsolation: false
-        }
-      });
-      await w.loadFile(path.join(fixtures, 'remote-event-handler.html'));
-      w.webContents.reload();
-      await emittedOnce(w.webContents, 'did-finish-load');
-
-      const expectedMessage = [
-        'Attempting to call a function in a renderer window that has been closed or released.',
-        'Function provided here: remote-event-handler.html:11:33',
-        'Remote event names: remote-handler, other-remote-handler'
-      ].join('\n');
-
-      expect(w.webContents.listenerCount('remote-handler')).to.equal(2);
-      let warnMessage: string | null = null;
-      const originalWarn = console.warn;
-      let warned: Function;
-      const warnPromise = new Promise(resolve => {
-        warned = resolve;
-      });
-      try {
-        console.warn = (message: string) => {
-          warnMessage = message;
-          warned();
-        };
-        w.webContents.emit('remote-handler', { sender: w.webContents });
-        await warnPromise;
-      } finally {
-        console.warn = originalWarn;
-      }
-      expect(w.webContents.listenerCount('remote-handler')).to.equal(1);
-      expect(warnMessage).to.equal(expectedMessage);
-    });
-  });
-
-  describe('remote.require', () => {
-    const w = makeWindow();
-    const remotely = makeRemotely(w);
-
-    remotely.it()('should returns same object for the same module', () => {
-      const { remote } = require('electron');
-      const a = remote.require('electron');
-      const b = remote.require('electron');
-      expect(a).to.equal(b);
-    });
-
-    remotely.it(path.join(fixtures, 'id.js'))('should work when object contains id property', (module: string) => {
-      const { id } = require('electron').remote.require(module);
-      expect(id).to.equal(1127);
-    });
-
-    remotely.it(path.join(fixtures, 'no-prototype.js'))('should work when object has no prototype', (module: string) => {
-      const a = require('electron').remote.require(module);
-      expect(a.foo.bar).to.equal('baz');
-      expect(a.foo.baz).to.equal(false);
-      expect(a.bar).to.equal(1234);
-      expect(a.getConstructorName(Object.create(null))).to.equal('');
-      expect(a.getConstructorName(new (class {})())).to.equal('');
-    });
-
-    it('should search module from the user app', async () => {
-      expectPathsEqual(
-        path.normalize(await remotely(() => {
-          const { remote } = require('electron');
-          return (remote as any).process.mainModule.filename;
-        })),
-        path.resolve(__dirname, 'index.js')
-      );
-      expectPathsEqual(
-        path.normalize(await remotely(() => {
-          const { remote } = require('electron');
-          return (remote as any).process.mainModule.paths[0];
-        })),
-        path.resolve(__dirname, 'node_modules')
-      );
-    });
-
-    remotely.it(fixtures)('should work with function properties', (fixtures: string) => {
-      const path = require('path');
-
-      {
-        const a = require('electron').remote.require(path.join(fixtures, 'export-function-with-properties.js'));
-        expect(typeof a).to.equal('function');
-        expect(a.bar).to.equal('baz');
-      }
-
-      {
-        const a = require('electron').remote.require(path.join(fixtures, 'function-with-properties.js'));
-        expect(typeof a).to.equal('object');
-        expect(a.foo()).to.equal('hello');
-        expect(a.foo.bar).to.equal('baz');
-        expect(a.foo.nested.prop).to.equal('yes');
-        expect(a.foo.method1()).to.equal('world');
-        expect(a.foo.method1.prop1()).to.equal(123);
-      }
-
-      {
-        const a = require('electron').remote.require(path.join(fixtures, 'function-with-missing-properties.js')).setup();
-        expect(a.bar()).to.equal(true);
-        expect(a.bar.baz).to.be.undefined();
-      }
-    });
-
-    remotely.it(fixtures)('should work with static class members', (fixtures: string) => {
-      const path = require('path');
-      const a = require('electron').remote.require(path.join(fixtures, 'remote-static.js'));
-      expect(typeof a.Foo).to.equal('function');
-      expect(a.Foo.foo()).to.equal(3);
-      expect(a.Foo.bar).to.equal('baz');
-      expect(new a.Foo().baz()).to.equal(123);
-    });
-
-    remotely.it(fixtures)('includes the length of functions specified as arguments', (fixtures: string) => {
-      const path = require('path');
-      const a = require('electron').remote.require(path.join(fixtures, 'function-with-args.js'));
-      /* eslint-disable @typescript-eslint/no-unused-vars */
-      expect(a((a: any, b: any, c: any) => {})).to.equal(3);
-      expect(a((a: any) => {})).to.equal(1);
-      expect(a((...args: any[]) => {})).to.equal(0);
-      /* eslint-enable @typescript-eslint/no-unused-vars */
-    });
-
-    remotely.it(fixtures)('handles circular references in arrays and objects', (fixtures: string) => {
-      const path = require('path');
-      const a = require('electron').remote.require(path.join(fixtures, 'circular.js'));
-
-      let arrayA: any[] = ['foo'];
-      const arrayB = [arrayA, 'bar'];
-      arrayA.push(arrayB);
-      expect(a.returnArgs(arrayA, arrayB)).to.deep.equal([
-        ['foo', [null, 'bar']],
-        [['foo', null], 'bar']
-      ]);
-
-      let objectA: any = { foo: 'bar' };
-      const objectB = { baz: objectA };
-      objectA.objectB = objectB;
-      expect(a.returnArgs(objectA, objectB)).to.deep.equal([
-        { foo: 'bar', objectB: { baz: null } },
-        { baz: { foo: 'bar', objectB: null } }
-      ]);
-
-      arrayA = [1, 2, 3];
-      expect(a.returnArgs({ foo: arrayA }, { bar: arrayA })).to.deep.equal([
-        { foo: [1, 2, 3] },
-        { bar: [1, 2, 3] }
-      ]);
-
-      objectA = { foo: 'bar' };
-      expect(a.returnArgs({ foo: objectA }, { bar: objectA })).to.deep.equal([
-        { foo: { foo: 'bar' } },
-        { bar: { foo: 'bar' } }
-      ]);
-
-      arrayA = [];
-      arrayA.push(arrayA);
-      expect(a.returnArgs(arrayA)).to.deep.equal([
-        [null]
-      ]);
-
-      objectA = {};
-      objectA.foo = objectA;
-      objectA.bar = 'baz';
-      expect(a.returnArgs(objectA)).to.deep.equal([
-        { foo: null, bar: 'baz' }
-      ]);
-
-      objectA = {};
-      objectA.foo = { bar: objectA };
-      objectA.bar = 'baz';
-      expect(a.returnArgs(objectA)).to.deep.equal([
-        { foo: { bar: null }, bar: 'baz' }
-      ]);
-    });
-  });
-
-  describe('remote.createFunctionWithReturnValue', () => {
-    const remotely = makeRemotely(makeWindow());
-
-    remotely.it(fixtures)('should be called in browser synchronously', async (fixtures: string) => {
-      const { remote } = require('electron');
-      const path = require('path');
-      const buf = Buffer.from('test');
-      const call = remote.require(path.join(fixtures, 'call.js'));
-      const result = call.call((remote as any).createFunctionWithReturnValue(buf));
-      expect(result).to.be.an.instanceOf(Uint8Array);
-    });
-  });
-
-  describe('remote modules', () => {
-    const remotely = makeRemotely(makeWindow());
-
-    const mainModules = Object.keys(require('electron'));
-    remotely.it(mainModules)('includes browser process modules as properties', (mainModules: string[]) => {
-      const { remote } = require('electron');
-      const remoteModules = mainModules.filter(name => (remote as any)[name]);
-      expect(remoteModules).to.be.deep.equal(mainModules);
-    });
-
-    remotely.it(fixtures)('returns toString() of original function via toString()', (fixtures: string) => {
-      const path = require('path');
-      const { readText } = require('electron').remote.clipboard;
-      expect(readText.toString().startsWith('function')).to.be.true();
-
-      const { functionWithToStringProperty } = require('electron').remote.require(path.join(fixtures, 'to-string-non-function.js'));
-      expect(functionWithToStringProperty.toString).to.equal('hello');
-    });
-
-    const protocolKeys = Object.getOwnPropertyNames(protocol);
-    remotely.it(protocolKeys)('remote.protocol returns all keys', (protocolKeys: [string]) => {
-      const protocol = require('electron').remote.protocol;
-      const remoteKeys = Object.getOwnPropertyNames(protocol);
-      expect(remoteKeys).to.deep.equal(protocolKeys);
-      for (const key of remoteKeys) {
-        expect(typeof (protocol as any)[key]).to.equal('function');
-      }
-    });
-  });
-
-  describe('remote object in renderer', () => {
-    const win = makeWindow();
-    const remotely = makeRemotely(win);
-
-    remotely.it(fixtures)('can change its properties', (fixtures: string) => {
-      const module = require('path').join(fixtures, 'property.js');
-      const property = require('electron').remote.require(module);
-      expect(property.property).to.equal(1127);
-      property.property = null;
-      expect(property.property).to.equal(null);
-      property.property = undefined;
-      expect(property.property).to.equal(undefined);
-      property.property = 1007;
-      expect(property.property).to.equal(1007);
-
-      expect(property.getFunctionProperty()).to.equal('foo-browser');
-      property.func.property = 'bar';
-      expect(property.getFunctionProperty()).to.equal('bar-browser');
-      property.func.property = 'foo'; // revert back
-
-      const property2 = require('electron').remote.require(module);
-      expect(property2.property).to.equal(1007);
-
-      property.property = 1127; // revert back
-    });
-
-    remotely.it(fixtures)('rethrows errors getting/setting properties', (fixtures: string) => {
-      const foo = require('electron').remote.require(require('path').join(fixtures, 'error-properties.js'));
-
-      expect(() => {
-        // eslint-disable-next-line
-        foo.bar
-      }).to.throw('getting error');
-
-      expect(() => {
-        foo.bar = 'test';
-      }).to.throw('setting error');
-    });
-
-    remotely.it(fixtures)('can set a remote property with a remote object', (fixtures: string) => {
-      const { remote } = require('electron');
-      const foo = remote.require(require('path').join(fixtures, 'remote-object-set.js'));
-      foo.bar = remote.getCurrentWindow();
-    });
-
-    remotely.it(fixtures)('can construct an object from its member', (fixtures: string) => {
-      const call = require('electron').remote.require(require('path').join(fixtures, 'call.js'));
-      const obj = new call.constructor();
-      expect(obj.test).to.equal('test');
-    });
-
-    remotely.it(fixtures)('can reassign and delete its member functions', (fixtures: string) => {
-      const remoteFunctions = require('electron').remote.require(require('path').join(fixtures, 'function.js'));
-      expect(remoteFunctions.aFunction()).to.equal(1127);
-
-      remoteFunctions.aFunction = () => { return 1234; };
-      expect(remoteFunctions.aFunction()).to.equal(1234);
-
-      expect(delete remoteFunctions.aFunction).to.equal(true);
-    });
-
-    remotely.it('is referenced by its members', () => {
-      const stringify = require('electron').remote.getGlobal('JSON').stringify;
-      global.gc();
-      stringify({});
-    });
-
-    it('can handle objects without constructors', async () => {
-      win().webContents.once('remote-get-global', (event) => {
-        class Foo { bar () { return 'bar'; } }
-        Foo.prototype.constructor = undefined as any;
-        event.returnValue = new Foo();
-      });
-      expect(await remotely(() => require('electron').remote.getGlobal('test').bar())).to.equal('bar');
-    });
-  });
-
-  describe('remote value in browser', () => {
-    const remotely = makeRemotely(makeWindow());
-    const print = path.join(fixtures, 'print_name.js');
-
-    remotely.it(print)('preserves NaN', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      expect(printName.getNaN()).to.be.NaN();
-      expect(printName.echo(NaN)).to.be.NaN();
-    });
-
-    remotely.it(print)('preserves Infinity', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      expect(printName.getInfinity()).to.equal(Infinity);
-      expect(printName.echo(Infinity)).to.equal(Infinity);
-    });
-
-    remotely.it(print)('keeps its constructor name for objects', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const buf = Buffer.from('test');
-      expect(printName.print(buf)).to.equal('Buffer');
-    });
-
-    remotely.it(print)('supports instanceof Boolean', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const obj = Boolean(true);
-      expect(printName.print(obj)).to.equal('Boolean');
-      expect(printName.echo(obj)).to.deep.equal(obj);
-    });
-
-    remotely.it(print)('supports instanceof Number', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const obj = Number(42);
-      expect(printName.print(obj)).to.equal('Number');
-      expect(printName.echo(obj)).to.deep.equal(obj);
-    });
-
-    remotely.it(print)('supports instanceof String', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const obj = String('Hello World!');
-      expect(printName.print(obj)).to.equal('String');
-      expect(printName.echo(obj)).to.deep.equal(obj);
-    });
-
-    remotely.it(print)('supports instanceof Date', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const now = new Date();
-      expect(printName.print(now)).to.equal('Date');
-      expect(printName.echo(now)).to.deep.equal(now);
-    });
-
-    remotely.it(print)('supports instanceof RegExp', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const regexp = RegExp('.*');
-      expect(printName.print(regexp)).to.equal('RegExp');
-      expect(printName.echo(regexp)).to.deep.equal(regexp);
-    });
-
-    remotely.it(print)('supports instanceof Buffer', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const buffer = Buffer.from('test');
-      expect(buffer.equals(printName.echo(buffer))).to.be.true();
-
-      const objectWithBuffer = { a: 'foo', b: Buffer.from('bar') };
-      expect(objectWithBuffer.b.equals(printName.echo(objectWithBuffer).b)).to.be.true();
-
-      const arrayWithBuffer = [1, 2, Buffer.from('baz')];
-      expect((arrayWithBuffer[2] as Buffer).equals(printName.echo(arrayWithBuffer)[2])).to.be.true();
-    });
-
-    remotely.it(print)('supports instanceof ArrayBuffer', (print: string) => {
-      const printName = require('electron').remote.require(print);
-      const buffer = new ArrayBuffer(8);
-      const view = new DataView(buffer);
-
-      view.setFloat64(0, Math.PI);
-      expect(printName.echo(buffer)).to.deep.equal(buffer);
-      expect(printName.print(buffer)).to.equal('ArrayBuffer');
-    });
-
-    const arrayTests: [string, number[]][] = [
-      ['Int8Array', [1, 2, 3, 4]],
-      ['Uint8Array', [1, 2, 3, 4]],
-      ['Uint8ClampedArray', [1, 2, 3, 4]],
-      ['Int16Array', [0x1234, 0x2345, 0x3456, 0x4567]],
-      ['Uint16Array', [0x1234, 0x2345, 0x3456, 0x4567]],
-      ['Int32Array', [0x12345678, 0x23456789]],
-      ['Uint32Array', [0x12345678, 0x23456789]],
-      ['Float32Array', [0.5, 1.0, 1.5]],
-      ['Float64Array', [0.5, 1.0, 1.5]]
-    ];
-
-    arrayTests.forEach(([arrayType, values]) => {
-      remotely.it(print, arrayType, values)(`supports instanceof ${arrayType}`, (print: string, arrayType: string, values: number[]) => {
-        const printName = require('electron').remote.require(print);
-        expect([...printName.typedArray(arrayType, values)]).to.deep.equal(values);
-
-        const int8values = new ((window as any)[arrayType])(values);
-        expect(printName.typedArray(arrayType, int8values)).to.deep.equal(int8values);
-        expect(printName.print(int8values)).to.equal(arrayType);
-      });
-    });
-
-    describe('constructing a Uint8Array', () => {
-      remotely.it()('does not crash', () => {
-        const RUint8Array = require('electron').remote.getGlobal('Uint8Array');
-        new RUint8Array() // eslint-disable-line
-      });
-    });
-  });
-
-  describe('remote promise', () => {
-    const remotely = makeRemotely(makeWindow());
-
-    remotely.it(fixtures)('can be used as promise in each side', async (fixtures: string) => {
-      const promise = require('electron').remote.require(require('path').join(fixtures, 'promise.js'));
-      const value = await promise.twicePromise(Promise.resolve(1234));
-      expect(value).to.equal(2468);
-    });
-
-    remotely.it(fixtures)('handles rejections via catch(onRejected)', async (fixtures: string) => {
-      const promise = require('electron').remote.require(require('path').join(fixtures, 'rejected-promise.js'));
-      const error = await new Promise<Error>(resolve => {
-        promise.reject(Promise.resolve(1234)).catch(resolve);
-      });
-      expect(error.message).to.equal('rejected');
-    });
-
-    remotely.it(fixtures)('handles rejections via then(onFulfilled, onRejected)', async (fixtures: string) => {
-      const promise = require('electron').remote.require(require('path').join(fixtures, 'rejected-promise.js'));
-      const error = await new Promise<Error>(resolve => {
-        promise.reject(Promise.resolve(1234)).then(() => {}, resolve);
-      });
-      expect(error.message).to.equal('rejected');
-    });
-
-    it('does not emit unhandled rejection events in the main process', (done) => {
-      function onUnhandledRejection () {
-        done(new Error('Unexpected unhandledRejection event'));
-      }
-      process.once('unhandledRejection', onUnhandledRejection);
-
-      remotely(async (fixtures: string) => {
-        const promise = require('electron').remote.require(require('path').join(fixtures, 'unhandled-rejection.js'));
-        return new Promise((resolve, reject) => {
-          promise.reject().then(() => {
-            reject(new Error('Promise was not rejected'));
-          }).catch((error: Error) => {
-            resolve(error);
-          });
-        });
-      }, fixtures).then(error => {
-        try {
-          expect(error.message).to.equal('rejected');
-          done();
-        } catch (e) {
-          done(e);
-        } finally {
-          process.off('unhandledRejection', onUnhandledRejection);
-        }
-      });
-    });
-
-    it('emits unhandled rejection events in the renderer process', (done) => {
-      remotely((module: string) => new Promise((resolve, reject) => {
-        const promise = require('electron').remote.require(module);
-
-        window.addEventListener('unhandledrejection', function handler (event) {
-          event.preventDefault();
-          window.removeEventListener('unhandledrejection', handler);
-          resolve(event.reason.message);
-        });
-
-        promise.reject().then(() => {
-          reject(new Error('Promise was not rejected'));
-        });
-      }), path.join(fixtures, 'unhandled-rejection.js')).then(
-        (message) => {
-          try {
-            expect(message).to.equal('rejected');
-            done();
-          } catch (e) {
-            done(e);
-          }
-        },
-        done
-      );
-    });
-
-    before(() => {
-      (global as any).returnAPromise = (value: any) => new Promise((resolve) => setTimeout(() => resolve(value), 100));
-    });
-    after(() => {
-      delete (global as any).returnAPromise;
-    });
-    remotely.it()('using a promise based method resolves correctly when global Promise is overridden', async () => {
-      const { remote } = require('electron');
-      const original = global.Promise;
-      try {
-        expect(await remote.getGlobal('returnAPromise')(123)).to.equal(123);
-        global.Promise = { resolve: () => ({}) } as any;
-        expect(await remote.getGlobal('returnAPromise')(456)).to.equal(456);
-      } finally {
-        global.Promise = original;
-      }
-    });
-  });
-
-  describe('remote webContents', () => {
-    const remotely = makeRemotely(makeWindow());
-
-    it('can return same object with different getters', async () => {
-      const equal = await remotely(() => {
-        const { remote } = require('electron');
-        const contents1 = remote.getCurrentWindow().webContents;
-        const contents2 = remote.getCurrentWebContents();
-        return contents1 === contents2;
-      });
-      expect(equal).to.be.true();
-    });
-  });
-
-  describe('remote class', () => {
-    const remotely = makeRemotely(makeWindow());
-
-    remotely.it(fixtures)('can get methods', (fixtures: string) => {
-      const { base } = require('electron').remote.require(require('path').join(fixtures, 'class.js'));
-      expect(base.method()).to.equal('method');
-    });
-
-    remotely.it(fixtures)('can get properties', (fixtures: string) => {
-      const { base } = require('electron').remote.require(require('path').join(fixtures, 'class.js'));
-      expect(base.readonly).to.equal('readonly');
-    });
-
-    remotely.it(fixtures)('can change properties', (fixtures: string) => {
-      const { base } = require('electron').remote.require(require('path').join(fixtures, 'class.js'));
-      expect(base.value).to.equal('old');
-      base.value = 'new';
-      expect(base.value).to.equal('new');
-      base.value = 'old';
-    });
-
-    remotely.it(fixtures)('has unenumerable methods', (fixtures: string) => {
-      const { base } = require('electron').remote.require(require('path').join(fixtures, 'class.js'));
-      expect(base).to.not.have.ownProperty('method');
-      expect(Object.getPrototypeOf(base)).to.have.ownProperty('method');
-    });
-
-    remotely.it(fixtures)('keeps prototype chain in derived class', (fixtures: string) => {
-      const { derived } = require('electron').remote.require(require('path').join(fixtures, 'class.js'));
-      expect(derived.method()).to.equal('method');
-      expect(derived.readonly).to.equal('readonly');
-      expect(derived).to.not.have.ownProperty('method');
-      const proto = Object.getPrototypeOf(derived);
-      expect(proto).to.not.have.ownProperty('method');
-      expect(Object.getPrototypeOf(proto)).to.have.ownProperty('method');
-    });
-
-    remotely.it(fixtures)('is referenced by methods in prototype chain', (fixtures: string) => {
-      let { derived } = require('electron').remote.require(require('path').join(fixtures, 'class.js'));
-      const method = derived.method;
-      derived = null;
-      global.gc();
-      expect(method()).to.equal('method');
-    });
-  });
-
-  describe('remote exception', () => {
-    const remotely = makeRemotely(makeWindow());
-
-    remotely.it(fixtures)('throws errors from the main process', (fixtures: string) => {
-      const throwFunction = require('electron').remote.require(require('path').join(fixtures, 'exception.js'));
-      expect(() => {
-        throwFunction();
-      }).to.throw(/undefined/);
-    });
-
-    remotely.it(fixtures)('tracks error cause', (fixtures: string) => {
-      const throwFunction = require('electron').remote.require(require('path').join(fixtures, 'exception.js'));
-      try {
-        throwFunction(new Error('error from main'));
-        expect.fail();
-      } catch (e) {
-        expect(e.message).to.match(/Could not call remote function/);
-        expect(e.cause.message).to.equal('error from main');
-      }
-    });
-  });
-
-  describe('gc behavior', () => {
-    const win = makeWindow();
-    const remotely = makeRemotely(win);
-    it('is resilient to gc happening between request and response', async () => {
-      const obj = { x: 'y' };
-      win().webContents.on('remote-get-global', (event) => {
-        event.returnValue = obj;
-      });
-      await remotely(() => {
-        const { ipc } = process._linkedBinding('electron_renderer_ipc');
-        const originalSendSync = ipc.sendSync.bind(ipc) as any;
-        ipc.sendSync = (...args: any[]): any => {
-          const ret = originalSendSync(...args);
-          (window as any).gc();
-          return ret;
-        };
-
-        for (let i = 0; i < 100; i++) {
-          // eslint-disable-next-line
-          require('electron').remote.getGlobal('test').x;
-        }
-      });
-    });
-  });
-});

+ 0 - 7
spec-main/fixtures/remote/call.js

@@ -1,7 +0,0 @@
-exports.call = function (func) {
-  return func();
-};
-
-exports.constructor = function () {
-  this.test = 'test';
-};

+ 0 - 3
spec-main/fixtures/remote/circular.js

@@ -1,3 +0,0 @@
-exports.returnArgs = function (...args) {
-  return args;
-};

+ 0 - 29
spec-main/fixtures/remote/class.js

@@ -1,29 +0,0 @@
-'use strict';
-
-let value = 'old';
-
-class BaseClass {
-  method () {
-    return 'method';
-  }
-
-  get readonly () {
-    return 'readonly';
-  }
-
-  get value () {
-    return value;
-  }
-
-  set value (val) {
-    value = val;
-  }
-}
-
-class DerivedClass extends BaseClass {
-}
-
-module.exports = {
-  base: new BaseClass(),
-  derived: new DerivedClass()
-};

+ 0 - 11
spec-main/fixtures/remote/delete-buffer.js

@@ -1,11 +0,0 @@
-const path = require('path');
-const { remote } = require('electron');
-const { Buffer } = window;
-
-delete window.Buffer;
-delete global.Buffer;
-
-// Test that remote.js doesn't use Buffer global
-remote.require(path.join(__dirname, 'print_name.js')).echo(Buffer.from('bar'));
-
-window.test = Buffer.from('buffer');

+ 0 - 11
spec-main/fixtures/remote/error-properties.js

@@ -1,11 +0,0 @@
-class Foo {
-  set bar (value) {
-    throw new Error('setting error');
-  }
-
-  get bar () {
-    throw new Error('getting error');
-  }
-}
-
-module.exports = new Foo();

+ 0 - 3
spec-main/fixtures/remote/exception.js

@@ -1,3 +0,0 @@
-module.exports = function (error) {
-  throw error;
-};

+ 0 - 4
spec-main/fixtures/remote/export-function-with-properties.js

@@ -1,4 +0,0 @@
-function foo () {}
-foo.bar = 'baz';
-
-module.exports = foo;

+ 0 - 3
spec-main/fixtures/remote/function-with-args.js

@@ -1,3 +0,0 @@
-module.exports = function (cb) {
-  return cb.length;
-};

+ 0 - 13
spec-main/fixtures/remote/function-with-missing-properties.js

@@ -1,13 +0,0 @@
-exports.setup = function () {
-  const foo = {};
-
-  foo.bar = function () {
-    return delete foo.bar.baz && delete foo.bar;
-  };
-
-  foo.bar.baz = function () {
-    return 3;
-  };
-
-  return foo;
-};

+ 0 - 17
spec-main/fixtures/remote/function-with-properties.js

@@ -1,17 +0,0 @@
-function foo () {
-  return 'hello';
-}
-foo.bar = 'baz';
-foo.nested = {
-  prop: 'yes'
-};
-foo.method1 = function () {
-  return 'world';
-};
-foo.method1.prop1 = function () {
-  return 123;
-};
-
-module.exports = {
-  foo: foo
-};

+ 0 - 1
spec-main/fixtures/remote/function.js

@@ -1 +0,0 @@
-exports.aFunction = function () { return 1127; };

+ 0 - 1
spec-main/fixtures/remote/id.js

@@ -1 +0,0 @@
-exports.id = 1127;

+ 0 - 11
spec-main/fixtures/remote/no-prototype.js

@@ -1,11 +0,0 @@
-const foo = Object.create(null);
-foo.bar = 'baz';
-foo.baz = false;
-module.exports = {
-  foo: foo,
-  bar: 1234,
-  anonymous: new (class {})(),
-  getConstructorName: function (value) {
-    return value.constructor.name;
-  }
-};

+ 0 - 5
spec-main/fixtures/remote/preload-remote-function.js

@@ -1,5 +0,0 @@
-const { remote, ipcRenderer } = require('electron');
-remote.getCurrentWindow().rendererFunc = () => {
-  ipcRenderer.send('done');
-};
-remote.getCurrentWindow().rendererFunc();

+ 0 - 5
spec-main/fixtures/remote/preload-remote.js

@@ -1,5 +0,0 @@
-const { ipcRenderer, remote } = require('electron');
-
-window.onload = function () {
-  ipcRenderer.send('remote', typeof remote);
-};

+ 0 - 36
spec-main/fixtures/remote/print_name.js

@@ -1,36 +0,0 @@
-exports.print = function (obj) {
-  return obj.constructor.name;
-};
-
-exports.echo = function (obj) {
-  return obj;
-};
-
-const typedArrays = {
-  Int8Array,
-  Uint8Array,
-  Uint8ClampedArray,
-  Int16Array,
-  Uint16Array,
-  Int32Array,
-  Uint32Array,
-  Float32Array,
-  Float64Array
-};
-
-exports.typedArray = function (type, values) {
-  const constructor = typedArrays[type];
-  const array = new constructor(values.length);
-  for (let i = 0; i < values.length; ++i) {
-    array[i] = values[i];
-  }
-  return array;
-};
-
-exports.getNaN = function () {
-  return NaN;
-};
-
-exports.getInfinity = function () {
-  return Infinity;
-};

+ 0 - 5
spec-main/fixtures/remote/promise.js

@@ -1,5 +0,0 @@
-exports.twicePromise = function (promise) {
-  return promise.then(function (value) {
-    return value * 2;
-  });
-};

+ 0 - 11
spec-main/fixtures/remote/property.js

@@ -1,11 +0,0 @@
-exports.property = 1127;
-
-function func () {
-
-}
-func.property = 'foo';
-exports.func = func;
-
-exports.getFunctionProperty = () => {
-  return `${func.property}-${process.type}`;
-};

+ 0 - 5
spec-main/fixtures/remote/rejected-promise.js

@@ -1,5 +0,0 @@
-exports.reject = function (promise) {
-  return promise.then(function () {
-    throw Error('rejected');
-  });
-};

+ 0 - 18
spec-main/fixtures/remote/remote-event-handler.html

@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title></title>
-    <script>
-      const {remote} = require('electron')
-      const browserWindow = remote.getCurrentWindow()
-
-      const handler = () => {}
-      browserWindow.webContents.on('remote-handler', handler)
-      browserWindow.webContents.on('other-remote-handler', handler)
-    </script>
-  </head>
-  <body>
-
-  </body>
-</html>

+ 0 - 11
spec-main/fixtures/remote/remote-object-set.js

@@ -1,11 +0,0 @@
-const { BrowserWindow } = require('electron');
-
-class Foo {
-  set bar (value) { // eslint-disable-line accessor-pairs
-    if (!(value instanceof BrowserWindow)) {
-      throw new Error('setting error');
-    }
-  }
-}
-
-module.exports = new Foo();

+ 0 - 15
spec-main/fixtures/remote/remote-static.js

@@ -1,15 +0,0 @@
-class Foo {
-  static foo () {
-    return 3;
-  }
-
-  baz () {
-    return 123;
-  }
-}
-
-Foo.bar = 'baz';
-
-module.exports = {
-  Foo: Foo
-};

+ 0 - 32
spec-main/fixtures/remote/render-view-deleted.html

@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title></title>
-    <script>
-      const {ipcRenderer, remote} = require('electron')
-
-      const contents = remote.getCurrentWebContents()
-
-      // This should not trigger a dereference and a remote getURL call should not fail
-      contents.emit('render-view-deleted', {}, 'not-a-process-id')
-      try {
-        contents.getURL()
-      } catch (error) {
-        ipcRenderer.send('error-message', 'Unexpected error on getURL call')
-      }
-
-      // This should trigger a dereference and a remote getURL call should fail
-      contents.emit('render-view-deleted', {}, contents.getProcessId())
-      try {
-        contents.getURL()
-        ipcRenderer.send('error-message', 'No error thrown')
-      } catch (error) {
-        ipcRenderer.send('error-message', error.message)
-      }
-    </script>
-  </head>
-  <body>
-
-  </body>
-</html>

+ 0 - 11
spec-main/fixtures/remote/send-on-exit.html

@@ -1,11 +0,0 @@
-<html>
-<body>
-<script type="text/javascript" charset="utf-8">
-  const {ipcRenderer} = require('electron')
-
-  process.on('exit', () => {
-    ipcRenderer.send('SENT_ON_EXIT')
-  })
-</script>
-</body>
-</html>

+ 0 - 4
spec-main/fixtures/remote/to-string-non-function.js

@@ -1,4 +0,0 @@
-function hello () {
-}
-hello.toString = 'hello';
-module.exports = { functionWithToStringProperty: hello };

+ 0 - 3
spec-main/fixtures/remote/unhandled-rejection.js

@@ -1,3 +0,0 @@
-exports.reject = function () {
-  return Promise.reject(new Error('rejected'));
-};

+ 3 - 30
spec-main/security-warnings-spec.ts

@@ -123,10 +123,7 @@ describe('security warnings', () => {
       it('should warn about insecure Content-Security-Policy', async () => {
         w = new BrowserWindow({
           show: false,
-          webPreferences: {
-            enableRemoteModule: false,
-            ...webPreferences
-          }
+          webPreferences
         });
 
         useCsp = false;
@@ -138,10 +135,7 @@ describe('security warnings', () => {
       it('should warn about insecure Content-Security-Policy (Trusted Types)', async () => {
         w = new BrowserWindow({
           show: false,
-          webPreferences: {
-            enableRemoteModule: false,
-            ...webPreferences
-          }
+          webPreferences
         });
 
         useCsp = false;
@@ -207,7 +201,7 @@ describe('security warnings', () => {
       it('should warn about insecure resources', async () => {
         w = new BrowserWindow({
           show: false,
-          webPreferences: { ...webPreferences }
+          webPreferences
         });
 
         w.loadURL(`${serverUrl}/insecure-resources.html`);
@@ -225,27 +219,6 @@ describe('security warnings', () => {
         const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
         expect(message).to.not.include('insecure-resources.html');
       });
-
-      it('should warn about enabled remote module with remote content', async () => {
-        w = new BrowserWindow({
-          show: false,
-          webPreferences
-        });
-
-        w.loadURL(`${serverUrl}/base-page-security.html`);
-        const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
-        expect(message).to.include('enableRemoteModule');
-      });
-
-      it('should not warn about enabled remote module with remote content from localhost', async () => {
-        w = new BrowserWindow({
-          show: false,
-          webPreferences
-        });
-        w.loadURL(`${serverUrl}/base-page-security-onload-message.html`);
-        const [,, message] = await emittedUntil(w.webContents, 'console-message', isLoaded);
-        expect(message).to.not.include('enableRemoteModule');
-      });
     });
   };
 

+ 0 - 49
spec-main/webview-spec.ts

@@ -3,11 +3,8 @@ import * as url from 'url';
 import { BrowserWindow, session, ipcMain, app, WebContents } from 'electron/main';
 import { closeAllWindows } from './window-helpers';
 import { emittedOnce, emittedUntil } from './events-helpers';
-import { ifdescribe } from './spec-helpers';
 import { expect } from 'chai';
 
-const features = process._linkedBinding('electron_common_features');
-
 async function loadWebView (w: WebContents, attributes: Record<string, string>, openDevTools: boolean = false): Promise<void> {
   await w.executeJavaScript(`
     new Promise((resolve, reject) => {
@@ -654,52 +651,6 @@ describe('<webview> tag', function () {
     });
   });
 
-  ifdescribe(features.isRemoteModuleEnabled())('enableremotemodule attribute', () => {
-    let w: BrowserWindow;
-    beforeEach(async () => {
-      w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, webviewTag: true } });
-      await w.loadURL('about:blank');
-    });
-    afterEach(closeAllWindows);
-
-    const generateSpecs = (description: string, sandbox: boolean) => {
-      describe(description, () => {
-        const preload = `file://${fixtures}/module/preload-disable-remote.js`;
-        const src = `file://${fixtures}/api/blank.html`;
-
-        it('enables the remote module by default', async () => {
-          loadWebView(w.webContents, {
-            preload,
-            src,
-            sandbox: sandbox.toString()
-          });
-          const [, webViewContents] = await emittedOnce(app, 'web-contents-created');
-          const [, , message] = await emittedUntil(webViewContents, 'console-message', (event: any, level: any, message: string) => !/deprecated/.test(message));
-
-          const typeOfRemote = JSON.parse(message);
-          expect(typeOfRemote).to.equal('object');
-        });
-
-        it('disables the remote module when false', async () => {
-          loadWebView(w.webContents, {
-            preload,
-            src,
-            sandbox: sandbox.toString(),
-            enableremotemodule: 'false'
-          });
-          const [, webViewContents] = await emittedOnce(app, 'web-contents-created');
-          const [, , message] = await emittedOnce(webViewContents, 'console-message');
-
-          const typeOfRemote = JSON.parse(message);
-          expect(typeOfRemote).to.equal('undefined');
-        });
-      });
-    };
-
-    generateSpecs('without sandbox', false);
-    generateSpecs('with sandbox', true);
-  });
-
   describe('DOM events', () => {
     afterEach(closeAllWindows);
     it('receives extra properties on DOM events when contextIsolation is enabled', async () => {

+ 0 - 8
spec/fixtures/module/preload-disable-remote.js

@@ -1,8 +0,0 @@
-setImmediate(function () {
-  try {
-    const { remote } = require('electron');
-    console.log(JSON.stringify(typeof remote));
-  } catch (e) {
-    console.log(e.message);
-  }
-});

+ 0 - 1
spec/static/main.js

@@ -108,7 +108,6 @@ app.whenReady().then(async function () {
     webPreferences: {
       backgroundThrottling: false,
       nodeIntegration: true,
-      enableRemoteModule: false,
       webviewTag: true,
       contextIsolation: false
     }

+ 0 - 62
spec/ts-smoke/electron/renderer.ts

@@ -2,11 +2,9 @@
 import {
   desktopCapturer,
   ipcRenderer,
-  remote,
   webFrame,
   clipboard,
   crashReporter,
-  screen,
   shell
 } from 'electron'
 
@@ -23,31 +21,6 @@ ipcRenderer.on('asynchronous-reply', (event, arg: any) => {
 
 ipcRenderer.send('asynchronous-message', 'ping')
 
-// remote
-// https://github.com/electron/electron/blob/master/docs/api/remote.md
-
-const BrowserWindow = remote.BrowserWindow
-const win = new BrowserWindow({ width: 800, height: 600 })
-win.loadURL('https://github.com')
-
-remote.getCurrentWindow().on('close', () => {
-  // blabla...
-})
-
-remote.getCurrentWindow().capturePage().then(image => {
-  fs.writeFile('/tmp/screenshot.png', image.toBitmap(), err => {
-    console.log(err)
-  })
-})
-
-remote.getCurrentWebContents().print()
-
-remote.getCurrentWindow().capturePage().then(image => {
-  remote.require('fs').writeFile('/tmp/screenshot.png', image.toBitmap(), (err: Error) => {
-    console.log(err)
-  })
-})
-
 // web-frame
 // https://github.com/electron/electron/blob/master/docs/api/web-frame.md
 
@@ -166,12 +139,7 @@ holder.ondrop = function (e) {
 // nativeImage
 // https://github.com/electron/electron/blob/master/docs/api/native-image.md
 
-const Tray = remote.Tray
-const appIcon2 = new Tray('/Users/somebody/images/icon.png')
-const window2 = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
 const image = clipboard.readImage()
-const appIcon3 = new Tray(image)
-const appIcon4 = new Tray('/Users/somebody/images/icon.png')
 
 // https://github.com/electron/electron/blob/master/docs/api/process.md
 
@@ -183,36 +151,6 @@ process.once('loaded', function () {
   global.clearImmediate = _clearImmediate
 })
 
-// screen
-// https://github.com/electron/electron/blob/master/docs/api/screen.md
-
-const app = remote.app
-
-let mainWindow: Electron.BrowserWindow = null
-
-app.whenReady().then(() => {
-  const size = screen.getPrimaryDisplay().workAreaSize
-  mainWindow = new BrowserWindow({ width: size.width, height: size.height })
-})
-
-app.whenReady().then(() => {
-  const displays = screen.getAllDisplays()
-  let externalDisplay: any = null
-  for (const i in displays) {
-    if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
-      externalDisplay = displays[i]
-      break
-    }
-  }
-
-  if (externalDisplay) {
-    mainWindow = new BrowserWindow({
-      x: externalDisplay.bounds.x + 50,
-      y: externalDisplay.bounds.y + 50
-    })
-  }
-})
-
 // shell
 // https://github.com/electron/electron/blob/master/docs/api/shell.md
 

+ 0 - 11
spec/webview-spec.js

@@ -482,17 +482,6 @@ describe('<webview> tag', function () {
       });
     });
 
-    ifit(features.isRemoteModuleEnabled())('can disable the remote module', async () => {
-      const message = await startLoadingWebViewAndWaitForMessage(webview, {
-        preload: `${fixtures}/module/preload-disable-remote.js`,
-        src: `file://${fixtures}/api/blank.html`,
-        webpreferences: 'enableRemoteModule=no'
-      });
-
-      const typeOfRemote = JSON.parse(message);
-      expect(typeOfRemote).to.equal('undefined');
-    });
-
     it('can disables web security and enable nodeintegration', async () => {
       const jqueryPath = path.join(__dirname, '/static/jquery-2.0.3.min.js');
       const src = `<script src='file://${jqueryPath}'></script> <script>console.log(typeof require);</script>`;

+ 0 - 3
typings/internal-ambient.d.ts

@@ -7,7 +7,6 @@ declare var binding: { get: (name: string) => any; process: NodeJS.Process; crea
 declare const BUILDFLAG: (flag: boolean) => boolean;
 
 declare const ENABLE_DESKTOP_CAPTURER: boolean;
-declare const ENABLE_REMOTE_MODULE: boolean;
 declare const ENABLE_VIEWS_API: boolean;
 
 declare namespace NodeJS {
@@ -15,7 +14,6 @@ declare namespace NodeJS {
     isBuiltinSpellCheckerEnabled(): boolean;
     isDesktopCapturerEnabled(): boolean;
     isOffscreenRenderingEnabled(): boolean;
-    isRemoteModuleEnabled(): boolean;
     isPDFViewerEnabled(): boolean;
     isRunAsNodeEnabled(): boolean;
     isFakeLocationProviderEnabled(): boolean;
@@ -45,7 +43,6 @@ declare namespace NodeJS {
     weaklyTrackValue(value: any): void;
     clearWeaklyTrackedValues(): void;
     getWeaklyTrackedValues(): any[];
-    addRemoteObjectRef(contextId: string, id: number): void;
     isSameOrigin(a: string, b: string): boolean;
     triggerFatalErrorForTesting(): void;
   }