mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
138 Commits
v10.0.0-be
...
v11.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8eb198bab4 | ||
|
|
16a3f41fd3 | ||
|
|
605e50269e | ||
|
|
9b4572de44 | ||
|
|
5b80556da2 | ||
|
|
4290555a0d | ||
|
|
1429a8961c | ||
|
|
46f58b28c3 | ||
|
|
6369748a2a | ||
|
|
abf2e9c93d | ||
|
|
b2b5a6a3de | ||
|
|
acb64a2d3c | ||
|
|
3853fd3e99 | ||
|
|
659e79fc08 | ||
|
|
4c77fe318d | ||
|
|
72a089262e | ||
|
|
61a05caa78 | ||
|
|
563a8c83ea | ||
|
|
046a05944a | ||
|
|
0629c6c2ea | ||
|
|
48d1a70b52 | ||
|
|
5c6d8c2b7d | ||
|
|
0f44682be0 | ||
|
|
2376c45443 | ||
|
|
b665eb6d43 | ||
|
|
4e66f1b2c6 | ||
|
|
a54fcde3f4 | ||
|
|
7cc780d077 | ||
|
|
59f9d75324 | ||
|
|
cb6476fd12 | ||
|
|
e1e73fa5f5 | ||
|
|
09c0ee8f87 | ||
|
|
cf284991d8 | ||
|
|
f9fe8a67b9 | ||
|
|
7bf0af7d96 | ||
|
|
7a216a8fab | ||
|
|
673169a7ba | ||
|
|
9c7d73c6d6 | ||
|
|
0b830ba9e5 | ||
|
|
c0182bca15 | ||
|
|
8412aae231 | ||
|
|
b9ac334efc | ||
|
|
379bb174e9 | ||
|
|
178e46cd23 | ||
|
|
66744ecb4d | ||
|
|
a7599a0838 | ||
|
|
d5f642938d | ||
|
|
7274467f73 | ||
|
|
7c7ea141f0 | ||
|
|
c66282a460 | ||
|
|
78fe545d18 | ||
|
|
81d09bea44 | ||
|
|
130b176796 | ||
|
|
2e2e9a3702 | ||
|
|
04be1ac4a1 | ||
|
|
a33c10c3ed | ||
|
|
ce042184de | ||
|
|
b1574f9e59 | ||
|
|
9554d063a5 | ||
|
|
3eade2c228 | ||
|
|
71e2b7151c | ||
|
|
d08cfce6cb | ||
|
|
b2ef299efc | ||
|
|
fc8b49485a | ||
|
|
aa32fbf1d6 | ||
|
|
980e592271 | ||
|
|
c6c022dc46 | ||
|
|
261f385b5e | ||
|
|
6e710a20a6 | ||
|
|
46c9e15182 | ||
|
|
5185501b85 | ||
|
|
27d629abb9 | ||
|
|
9d960e29eb | ||
|
|
a1c55a13e1 | ||
|
|
491caf59c1 | ||
|
|
2d47daa8c4 | ||
|
|
25e4a9431c | ||
|
|
3fa4299939 | ||
|
|
90caa5eac9 | ||
|
|
b1adbf7fd7 | ||
|
|
2fadb73032 | ||
|
|
ac81a39e09 | ||
|
|
83247c48c3 | ||
|
|
5de6adfb84 | ||
|
|
d8594f7a78 | ||
|
|
087567655a | ||
|
|
512e1541c6 | ||
|
|
c36981da8b | ||
|
|
d3fa5ed1e8 | ||
|
|
edc5050a2e | ||
|
|
a5efc387c7 | ||
|
|
0062b126b4 | ||
|
|
969f46a48f | ||
|
|
c6f4573a13 | ||
|
|
95037a7d2a | ||
|
|
5218a6e6ab | ||
|
|
5918dd6e65 | ||
|
|
fbf397e15d | ||
|
|
066b8c5ab3 | ||
|
|
634ab45095 | ||
|
|
a4de915b74 | ||
|
|
4a551bde16 | ||
|
|
b809d104d0 | ||
|
|
4133c71105 | ||
|
|
f67aff2704 | ||
|
|
aa8d81511f | ||
|
|
236c1334e3 | ||
|
|
9f21d09dfd | ||
|
|
9dec16d81e | ||
|
|
b086197968 | ||
|
|
e8ea007104 | ||
|
|
e5da2caa34 | ||
|
|
a1edf5cf94 | ||
|
|
6516110c70 | ||
|
|
3a7775fa73 | ||
|
|
5d88d0ee74 | ||
|
|
7b0a84477a | ||
|
|
f78504515b | ||
|
|
ca6a415626 | ||
|
|
f445e0a797 | ||
|
|
204f001c5d | ||
|
|
dc72f74020 | ||
|
|
2b39111e30 | ||
|
|
2bc85b2579 | ||
|
|
0a026cde0c | ||
|
|
db5cf816b4 | ||
|
|
08f288faf1 | ||
|
|
0dabd5e8c7 | ||
|
|
2029ff1903 | ||
|
|
9bc5e98238 | ||
|
|
762f7bcca2 | ||
|
|
75847a0c5b | ||
|
|
e3c2ec9f7c | ||
|
|
fdf40ce07a | ||
|
|
82924679fe | ||
|
|
f373cc770f | ||
|
|
78d74bf8b4 | ||
|
|
5ed2512881 |
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -15,6 +15,7 @@ Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTIN
|
||||
- [ ] relevant documentation is changed or added
|
||||
- [ ] PR title follows semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
|
||||
- [ ] [PR release notes](https://github.com/electron/clerk/blob/master/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/master/README.md#examples).
|
||||
- [ ] This is **NOT A BREAKING CHANGE**. Breaking changes may not be merged to master until 11-x-y is branched.
|
||||
|
||||
#### Release Notes
|
||||
|
||||
|
||||
10
BUILD.gn
10
BUILD.gn
@@ -347,6 +347,7 @@ source_set("electron_lib") {
|
||||
"//device/bluetooth",
|
||||
"//device/bluetooth/public/cpp",
|
||||
"//gin",
|
||||
"//media/blink:blink",
|
||||
"//media/capture/mojom:video_capture",
|
||||
"//media/mojo/mojom",
|
||||
"//net:extras",
|
||||
@@ -601,15 +602,6 @@ source_set("electron_lib") {
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_remote_module) {
|
||||
sources += [
|
||||
"shell/common/api/remote/remote_callback_freer.cc",
|
||||
"shell/common/api/remote/remote_callback_freer.h",
|
||||
"shell/common/api/remote/remote_object_freer.cc",
|
||||
"shell/common/api/remote/remote_object_freer.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_desktop_capturer) {
|
||||
if (is_component_build && !is_linux) {
|
||||
# On windows the implementation relies on unexported
|
||||
|
||||
4
DEPS
4
DEPS
@@ -13,9 +13,9 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'85.0.4181.1',
|
||||
'9ae03ef8f7d4f6ac663f725bcfe70311987652f3',
|
||||
'node_version':
|
||||
'v12.16.3',
|
||||
'v12.18.1',
|
||||
'nan_version':
|
||||
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
10.0.0-beta.7
|
||||
11.0.0-nightly.20200626
|
||||
@@ -93,14 +93,6 @@ static_library("chrome") {
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
"//chrome/browser/win/icon_reader_service.cc",
|
||||
"//chrome/browser/win/icon_reader_service.h",
|
||||
]
|
||||
public_deps += [ "//chrome/services/util_win:lib" ]
|
||||
}
|
||||
|
||||
if (enable_desktop_capturer) {
|
||||
sources += [
|
||||
"//chrome/browser/media/webrtc/desktop_media_list.h",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { app, dialog } from 'electron';
|
||||
import * as electron from 'electron';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
const { app, dialog } = electron;
|
||||
|
||||
type DefaultAppOptions = {
|
||||
file: null | string;
|
||||
@@ -145,13 +146,90 @@ function startRepl () {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// prevent quitting
|
||||
// Prevent quitting.
|
||||
app.on('window-all-closed', () => {});
|
||||
|
||||
const repl = require('repl');
|
||||
repl.start('> ').on('exit', () => {
|
||||
const GREEN = '32';
|
||||
const colorize = (color: string, s: string) => `\x1b[${color}m${s}\x1b[0m`;
|
||||
const electronVersion = colorize(GREEN, `v${process.versions.electron}`);
|
||||
const nodeVersion = colorize(GREEN, `v${process.versions.node}`);
|
||||
|
||||
console.info(`
|
||||
Welcome to the Electron.js REPL \\[._.]/
|
||||
|
||||
You can access all Electron.js modules here as well as Node.js modules.
|
||||
Using: Node.js ${nodeVersion} and Electron.js ${electronVersion}
|
||||
`);
|
||||
|
||||
const { REPLServer } = require('repl');
|
||||
const repl = new REPLServer({
|
||||
prompt: '> '
|
||||
}).on('exit', () => {
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
function defineBuiltin (context: any, name: string, getter: Function) {
|
||||
const setReal = (val: any) => {
|
||||
// Deleting the property before re-assigning it disables the
|
||||
// getter/setter mechanism.
|
||||
delete context[name];
|
||||
context[name] = val;
|
||||
};
|
||||
|
||||
Object.defineProperty(context, name, {
|
||||
get: () => {
|
||||
const lib = getter();
|
||||
|
||||
delete context[name];
|
||||
Object.defineProperty(context, name, {
|
||||
get: () => lib,
|
||||
set: setReal,
|
||||
configurable: true,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return lib;
|
||||
},
|
||||
set: setReal,
|
||||
configurable: true,
|
||||
enumerable: false
|
||||
});
|
||||
}
|
||||
|
||||
defineBuiltin(repl.context, 'electron', () => electron);
|
||||
for (const api of Object.keys(electron) as (keyof typeof electron)[]) {
|
||||
defineBuiltin(repl.context, api, () => electron[api]);
|
||||
}
|
||||
|
||||
// Copied from node/lib/repl.js. For better DX, we don't want to
|
||||
// show e.g 'contentTracing' at a higher priority than 'const', so
|
||||
// we only trigger custom tab-completion when no common words are
|
||||
// potentially matches.
|
||||
const commonWords = [
|
||||
'async', 'await', 'break', 'case', 'catch', 'const', 'continue',
|
||||
'debugger', 'default', 'delete', 'do', 'else', 'export', 'false',
|
||||
'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'let',
|
||||
'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try',
|
||||
'typeof', 'var', 'void', 'while', 'with', 'yield'
|
||||
];
|
||||
|
||||
const electronBuiltins = [...Object.keys(electron), 'original-fs', 'electron'];
|
||||
|
||||
const defaultComplete = repl.completer;
|
||||
repl.completer = (line: string, callback: Function) => {
|
||||
const lastSpace = line.lastIndexOf(' ');
|
||||
const currentSymbol = line.substring(lastSpace + 1, repl.cursor);
|
||||
|
||||
const filterFn = (c: string) => c.startsWith(currentSymbol);
|
||||
const ignores = commonWords.filter(filterFn);
|
||||
const hits = electronBuiltins.filter(filterFn);
|
||||
|
||||
if (!ignores.length && hits.length) {
|
||||
callback(null, [hits, currentSymbol]);
|
||||
} else {
|
||||
defaultComplete.apply(repl, [line, callback]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Start the specified app if there is one specified in command line, otherwise
|
||||
|
||||
@@ -92,7 +92,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* Electron Releases & Developer Feedback
|
||||
* [Versioning Policy](tutorial/electron-versioning.md)
|
||||
* [Release Timelines](tutorial/electron-timelines.md)
|
||||
* [App Feedback Program](tutorial/app-feedback-program.md)
|
||||
* [Packaging App Source Code with asar](tutorial/application-packaging.md)
|
||||
* [Generating asar Archives](tutorial/application-packaging.md#generating-asar-archives)
|
||||
* [Using asar Archives](tutorial/application-packaging.md#using-asar-archives)
|
||||
|
||||
@@ -140,6 +140,16 @@ this event, such as launching the application for the first time, attempting
|
||||
to re-launch the application when it's already running, or clicking on the
|
||||
application's dock or taskbar icon.
|
||||
|
||||
### Event: 'did-become-active' _macOS_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
|
||||
Emitted when mac application become active. Difference from `activate` event is
|
||||
that `did-become-active` is emitted every time the app becomes active, not only
|
||||
when Dock icon is clicked or application is re-launched.
|
||||
|
||||
### Event: 'continue-activity' _macOS_
|
||||
|
||||
Returns:
|
||||
@@ -1222,7 +1232,7 @@ Show the app's about panel options. These options can be overridden with `app.se
|
||||
* `credits` String (optional) _macOS_ _Windows_ - Credit information.
|
||||
* `authors` String[] (optional) _Linux_ - List of app authors.
|
||||
* `website` String (optional) _Linux_ - The app's website.
|
||||
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
|
||||
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon in a JPEG or PNG file format. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
|
||||
|
||||
Set the about panel options. This will override the values defined in the app's `.plist` file on macOS. See the [Apple docs][about-panel-options] for more details. On Linux, values must be set in order to be shown; there are no defaults.
|
||||
|
||||
|
||||
@@ -72,6 +72,50 @@ const constraints = {
|
||||
}
|
||||
```
|
||||
|
||||
This example shows how to capture a video from a [WebContents](web-contents.md)
|
||||
|
||||
```javascript
|
||||
// In the renderer process.
|
||||
const { desktopCapturer, remote } = require('electron')
|
||||
|
||||
desktopCapturer.getMediaSourceIdForWebContents(remote.getCurrentWebContents().id).then(async mediaSourceId => {
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
mandatory: {
|
||||
chromeMediaSource: 'tab',
|
||||
chromeMediaSourceId: mediaSourceId
|
||||
}
|
||||
},
|
||||
video: {
|
||||
mandatory: {
|
||||
chromeMediaSource: 'tab',
|
||||
chromeMediaSourceId: mediaSourceId,
|
||||
minWidth: 1280,
|
||||
maxWidth: 1280,
|
||||
minHeight: 720,
|
||||
maxHeight: 720
|
||||
}
|
||||
}
|
||||
})
|
||||
handleStream(stream)
|
||||
} catch (e) {
|
||||
handleError(e)
|
||||
}
|
||||
})
|
||||
|
||||
function handleStream (stream) {
|
||||
const video = document.querySelector('video')
|
||||
video.srcObject = stream
|
||||
video.onloadedmetadata = (e) => video.play()
|
||||
}
|
||||
|
||||
function handleError (e) {
|
||||
console.log(e)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
The `desktopCapturer` module has the following methods:
|
||||
@@ -94,6 +138,15 @@ Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`Desktop
|
||||
**Note** Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
|
||||
which can detected by [`systemPreferences.getMediaAccessStatus`].
|
||||
|
||||
### `desktopCapturer.getMediaSourceIdForWebContents(webContentsId)`
|
||||
|
||||
* `webContentsId` number - Id of the WebContents to get stream of
|
||||
|
||||
Returns `Promise<string>` - Resolves with the identifier of a WebContents stream, this identifier can be
|
||||
used with [`navigator.mediaDevices.getUserMedia`].
|
||||
The identifier is **only valid for 10 seconds**.
|
||||
The identifier may be empty if not requested from a renderer process.
|
||||
|
||||
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
|
||||
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-macos
|
||||
|
||||
|
||||
@@ -63,8 +63,8 @@ The `protocol` module has the following methods:
|
||||
module gets emitted and can be called only once.
|
||||
|
||||
Registers the `scheme` as standard, secure, bypasses content security policy for
|
||||
resources, allows registering ServiceWorker and supports fetch API. Specify a
|
||||
privilege with the value of `true` to enable the capability.
|
||||
resources, allows registering ServiceWorker, supports fetch API, and streaming
|
||||
video/audio. Specify a privilege with the value of `true` to enable the capability.
|
||||
|
||||
An example of registering a privileged scheme, that bypasses Content Security
|
||||
Policy:
|
||||
@@ -103,6 +103,11 @@ cookies) are disabled for non standard schemes. So in general if you want to
|
||||
register a custom protocol to replace the `http` protocol, you have to register
|
||||
it as a standard scheme.
|
||||
|
||||
Protocols that use streams (http and stream protocols) should set `stream: true`.
|
||||
The `<video>` and `<audio>` HTML elements expect protocols to buffer their
|
||||
responses by default. The `stream` flag configures those elements to correctly
|
||||
expect streaming responses.
|
||||
|
||||
### `protocol.registerFileProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
* `message` String - The actual console message
|
||||
* `versionId` Number - The version ID of the service worker that sent the log message
|
||||
* `source` String - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `app-cache`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
|
||||
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
|
||||
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
|
||||
* `sourceUrl` String - The URL the message came from
|
||||
* `lineNumber` Number - The line number of the source that triggered this console message
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@
|
||||
* `allowServiceWorkers` Boolean (optional) - Default false.
|
||||
* `supportFetchAPI` Boolean (optional) - Default false.
|
||||
* `corsEnabled` Boolean (optional) - Default false.
|
||||
* `stream` Boolean (optional) - Default false.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* `trace_buffer_size_in_events` number (optional) - maximum size of the trace
|
||||
recording buffer in events.
|
||||
* `enable_argument_filter` boolean (optional) - if true, filter event data
|
||||
according to a whitelist of events that have been manually vetted to not
|
||||
according to a specific list of events that have been manually vetted to not
|
||||
include any PII. See [the implementation in
|
||||
Chromium][trace_event_args_whitelist.cc] for specifics.
|
||||
* `included_categories` String[] (optional) - a list of tracing categories to
|
||||
|
||||
@@ -416,7 +416,7 @@ This API itself will not protect your user data; rather, it is a mechanism to al
|
||||
|
||||
Returns `Boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.
|
||||
|
||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
|
||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _Windows_ _macOS_
|
||||
|
||||
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
|
||||
|
||||
@@ -426,6 +426,9 @@ This user consent was not required on macOS 10.13 High Sierra or lower so this m
|
||||
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
|
||||
macOS 10.15 Catalina or higher requires consent for `screen` access.
|
||||
|
||||
Windows 10 has a global setting controlling `microphone` and `camera` access for all win32 applications.
|
||||
It will always return `granted` for `screen` and for all media types on older versions of Windows.
|
||||
|
||||
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
|
||||
|
||||
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.
|
||||
|
||||
@@ -738,9 +738,9 @@ Emitted when a `<webview>` has been attached to this web contents.
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `level` Integer
|
||||
* `message` String
|
||||
* `line` Integer
|
||||
* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
|
||||
* `message` String - The actual console message
|
||||
* `line` Integer - The line number of the source that triggered this console message
|
||||
* `sourceId` String
|
||||
|
||||
Emitted when the associated window logs a console message.
|
||||
|
||||
@@ -755,9 +755,9 @@ Fired when page leaves fullscreen triggered by HTML API.
|
||||
|
||||
Returns:
|
||||
|
||||
* `level` Integer
|
||||
* `message` String
|
||||
* `line` Integer
|
||||
* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
|
||||
* `message` String - The actual console message
|
||||
* `line` Integer - The line number of the source that triggered this console message
|
||||
* `sourceId` String
|
||||
|
||||
Fired when the guest window logs a console message.
|
||||
|
||||
@@ -14,6 +14,15 @@ This document uses the following convention to categorize breaking changes:
|
||||
|
||||
## Planned Breaking API Changes (12.0)
|
||||
|
||||
### Default Changed: `contextIsolation` defaults to `true`
|
||||
|
||||
In Electron 12, `contextIsolation` will be enabled by default. To restore
|
||||
the previous behavior, `contextIsolation: false` must be specified in WebPreferences.
|
||||
|
||||
We [recommend having contextIsolation enabled](https://github.com/electron/electron/blob/master/docs/tutorial/security.md#3-enable-context-isolation-for-remote-content) for the security of your application.
|
||||
|
||||
For more details see: https://github.com/electron/electron/issues/23506
|
||||
|
||||
### Removed: `crashReporter` methods in the renderer process
|
||||
|
||||
The following `crashReporter` methods are no longer available in the renderer
|
||||
|
||||
@@ -23,4 +23,3 @@ For guides on Electron app development, see
|
||||
* [Debugging on macOS](debugging-instructions-macos.md)
|
||||
* [Setting Up Symbol Server in Debugger](setting-up-symbol-server.md)
|
||||
* [Patches](patches.md)
|
||||
* [Upgrading Node](upgrading-node.md)
|
||||
|
||||
@@ -10,6 +10,10 @@ Check the build prerequisites for your platform before proceeding
|
||||
* [Linux](build-instructions-linux.md#prerequisites)
|
||||
* [Windows](build-instructions-windows.md#prerequisites)
|
||||
|
||||
## Build Tools
|
||||
|
||||
[Electron's Build Tools](https://github.com/electron/build-tools) automate much of the setup for compiling Electron from source with different configurations and build targets. If you wish to set up the environment manually, the instructions are listed below.
|
||||
|
||||
## GN prerequisites
|
||||
|
||||
You'll need to install [`depot_tools`][depot-tools], the toolset
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
# Upgrading Node
|
||||
|
||||
## Discussion
|
||||
|
||||
Chromium and Node.js both depend on V8, and Electron contains
|
||||
only a single copy of V8, so it's important to ensure that the
|
||||
version of V8 chosen is compatible with the build's version of
|
||||
Node.js and Chromium.
|
||||
|
||||
Upgrading Node is much easier than upgrading Chromium, so fewer
|
||||
conflicts arise if one upgrades Chromium first, then chooses the
|
||||
upstream Node release whose version of V8 is closest to the one
|
||||
Chromium contains.
|
||||
|
||||
Electron has its own [Node fork](https://github.com/electron/node)
|
||||
with modifications for the V8 build details mentioned above
|
||||
and for exposing API needed by Electron. Once an upstream Node
|
||||
release is chosen, it's placed in a branch in Electron's Node fork
|
||||
and any Electron Node patches are applied there.
|
||||
|
||||
Another factor is that the Node project patches its version of V8.
|
||||
As mentioned above, Electron builds everything with a single copy
|
||||
of V8, so Node's V8 patches must be ported to that copy.
|
||||
|
||||
Once all of Electron's dependencies are building and using the same
|
||||
copy of V8, the next step is to fix any Electron code issues caused
|
||||
by the Node upgrade.
|
||||
|
||||
[FIXME] something about a Node debugger in Atom that we (e.g. deepak)
|
||||
use and need to confirm doesn't break with the Node upgrade?
|
||||
|
||||
So in short, the primary steps are:
|
||||
|
||||
1. Update Electron's Node fork to the desired version
|
||||
2. Backport Node's V8 patches to our copy of V8
|
||||
3. Update the GN build files, porting changes from node's GYP files
|
||||
4. Update Electron's DEPS to use new version of Node
|
||||
|
||||
## Updating Electron's Node [fork](https://github.com/electron/node)
|
||||
|
||||
1. Ensure that `master` on `electron/node` has updated release tags from `nodejs/node`
|
||||
2. Create a branch in https://github.com/electron/node: `electron-node-vX.X.X` where the base that you're branching from is the tag for the desired update
|
||||
- `vX.X.X` Must use a version of Node compatible with our current version of Chromium
|
||||
3. Re-apply our commits from the previous version of Node we were using (`vY.Y.Y`) to `v.X.X.X`
|
||||
- Check release tag and select the range of commits we need to re-apply
|
||||
- Cherry-pick commit range:
|
||||
1. Checkout both `vY.Y.Y` & `v.X.X.X`
|
||||
2. `git cherry-pick FIRST_COMMIT_HASH..LAST_COMMIT_HASH`
|
||||
- Resolve merge conflicts in each file encountered, then:
|
||||
1. `git add <conflict-file>`
|
||||
2. `git cherry-pick --continue`
|
||||
3. Repeat until finished
|
||||
|
||||
|
||||
## Updating [V8](https://github.com/electron/node/src/V8) Patches
|
||||
|
||||
We need to generate a patch file from each patch that Node
|
||||
applies to V8.
|
||||
|
||||
```sh
|
||||
$ cd third_party/electron_node
|
||||
$ CURRENT_NODE_VERSION=vX.Y.Z
|
||||
# Find the last commit with the message "deps: update V8 to <some version>"
|
||||
# This commit corresponds to Node resetting V8 to its pristine upstream
|
||||
# state at the stated version.
|
||||
$ LAST_V8_UPDATE="$(git log --grep='^deps: update V8' --format='%H' -1 deps/v8)"
|
||||
# This creates a patch file containing all changes in deps/v8 from
|
||||
# $LAST_V8_UPDATE up to the current Node version, formatted in a way that
|
||||
# it will apply cleanly to the V8 repository (i.e. with `deps/v8`
|
||||
# stripped off the path and excluding the v8/gypfiles directory, which
|
||||
# isn't present in V8.
|
||||
$ git format-patch \
|
||||
--relative=deps/v8 \
|
||||
$LAST_V8_UPDATE..$CURRENT_NODE_VERSION \
|
||||
deps/v8 \
|
||||
':(exclude)deps/v8/gypfiles' \
|
||||
--stdout \
|
||||
> ../../electron/common/patches/v8/node_v8_patches.patch
|
||||
```
|
||||
|
||||
This list of patches will probably include one that claims to
|
||||
make the V8 API backwards-compatible with a previous version of
|
||||
V8. Unfortunately, those patches almost always change the V8 API
|
||||
in a way that is incompatible with Chromium.
|
||||
|
||||
It's usually easier to update Node to work without the
|
||||
compatibility patch than to update Chromium to work with the
|
||||
compatibility patch, so it's recommended to revert the
|
||||
compatibility patch and fix any errors that arise when compiling
|
||||
Node.
|
||||
|
||||
## Update Electron's `DEPS` file
|
||||
|
||||
Update the `DEPS` file in the root of
|
||||
[electron/electron](https://github.com/electron/electron) to
|
||||
point to the git hash of the updated Node.
|
||||
|
||||
## Notes
|
||||
|
||||
- Node maintains its own fork of V8
|
||||
- They backport a small amount of things as needed
|
||||
- Documentation in Node about how [they work with V8](https://nodejs.org/api/v8.html)
|
||||
- We update code such that we only use one copy of V8 across all of Electron
|
||||
- E.g Electron, Chromium, and Node.js
|
||||
- We don’t track upstream closely due to logistics:
|
||||
- Upstream uses multiple repos and so merging into a single repo
|
||||
would result in lost history. So we only update when we’re planning
|
||||
a Node version bump in Electron.
|
||||
- Chromium is large and time-consuming to update, so we typically
|
||||
choose the Node version based on which of its releases has a version
|
||||
of V8 that’s closest to the version in Chromium that we’re using.
|
||||
- We sometimes have to wait for the next periodic Node release
|
||||
because it will sync more closely with the version of V8 in the new Chromium
|
||||
- Electron keeps all its patches in the repo because it’s simpler than
|
||||
maintaining different repos for patches for each upstream project.
|
||||
- Crashpad, Node.js, Chromium, Skia etc. patches are all kept in the same place
|
||||
- Building Node:
|
||||
- We maintain our own GN build files for Node.js to make it easier to ensure
|
||||
that eevrything is built with the same compiler flags.
|
||||
This means that every time we upgrade Node.js we have to do a modest amount of
|
||||
work to synchronize the GN files with the upstream GYP files.
|
||||
@@ -1,3 +0,0 @@
|
||||
# Electron App Feedback Program
|
||||
|
||||
Electron is working on building a streamlined release process and having faster releases. To help with that, we have the App Feedback Program for large-scale Electron apps to test our beta releases and report app-specific issues to the Electron team. We use this program to help us prioritize work and get applications upgraded to the next stable release as soon as possible. There are a few requirements we expect from participants, such as attending short, online weekly check-ins. Please visit the [blog post](https://electronjs.org/blog/app-feedback-program) for details and sign-up.
|
||||
@@ -44,23 +44,10 @@ run the main process. An example of your `package.json` might look like this:
|
||||
```
|
||||
|
||||
__Note__: If the `main` field is not present in `package.json`, Electron will
|
||||
attempt to load an `index.js` (as Node.js does). If this was actually
|
||||
a simple Node application, you would add a `start` script that instructs `node`
|
||||
to execute the current package:
|
||||
attempt to load an `index.js` (as Node.js does).
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "your-app",
|
||||
"version": "0.1.0",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "node ."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Turning this Node application into an Electron application is quite simple - we
|
||||
merely replace the `node` runtime with the `electron` runtime.
|
||||
By default, `npm start` would run the main script with Node.js. in order to make
|
||||
it run with Electron, you can add a `start` script:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -154,10 +141,10 @@ function createWindow () {
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', () => {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
|
||||
@@ -75,9 +75,4 @@
|
||||
<message name="IDS_ACCEPT_LANGUAGES" use_name_for_id="true">
|
||||
en-US,en
|
||||
</message>
|
||||
<if expr="is_win">
|
||||
<message name="IDS_UTILITY_PROCESS_UTILITY_WIN_NAME" desc="The name of the utility process used to handle Windows utility operations.">
|
||||
Windows Utilities
|
||||
</message>
|
||||
</if>
|
||||
</grit-part>
|
||||
|
||||
@@ -135,13 +135,12 @@ auto_filenames = {
|
||||
|
||||
sandbox_bundle_deps = [
|
||||
"lib/browser/api/module-names.ts",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
@@ -149,7 +148,7 @@ auto_filenames = {
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
"lib/renderer/api/desktop-capturer.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/remote.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
@@ -166,20 +165,23 @@ auto_filenames = {
|
||||
"lib/renderer/window-setup.ts",
|
||||
"lib/sandboxed_renderer/api/exports/electron.ts",
|
||||
"lib/sandboxed_renderer/api/module-list.ts",
|
||||
"lib/sandboxed_renderer/init.js",
|
||||
"lib/sandboxed_renderer/init.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
"typings/internal-ambient.d.ts",
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
|
||||
isolated_bundle_deps = [
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/isolated_renderer/init.js",
|
||||
"lib/renderer/web-view/web-view-constants.ts",
|
||||
"lib/renderer/web-view/web-view-element.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
"typings/internal-ambient.d.ts",
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
|
||||
browser_bundle_deps = [
|
||||
@@ -188,15 +190,15 @@ auto_filenames = {
|
||||
"lib/browser/api/auto-updater/auto-updater-native.js",
|
||||
"lib/browser/api/auto-updater/auto-updater-win.js",
|
||||
"lib/browser/api/auto-updater/squirrel-update-win.js",
|
||||
"lib/browser/api/browser-view.js",
|
||||
"lib/browser/api/browser-view.ts",
|
||||
"lib/browser/api/browser-window.js",
|
||||
"lib/browser/api/content-tracing.js",
|
||||
"lib/browser/api/content-tracing.ts",
|
||||
"lib/browser/api/crash-reporter.ts",
|
||||
"lib/browser/api/desktop-capturer.ts",
|
||||
"lib/browser/api/dialog.js",
|
||||
"lib/browser/api/exports/electron.ts",
|
||||
"lib/browser/api/global-shortcut.js",
|
||||
"lib/browser/api/in-app-purchase.js",
|
||||
"lib/browser/api/global-shortcut.ts",
|
||||
"lib/browser/api/in-app-purchase.ts",
|
||||
"lib/browser/api/ipc-main.ts",
|
||||
"lib/browser/api/menu-item-roles.js",
|
||||
"lib/browser/api/menu-item.js",
|
||||
@@ -207,19 +209,19 @@ auto_filenames = {
|
||||
"lib/browser/api/native-theme.ts",
|
||||
"lib/browser/api/net-log.js",
|
||||
"lib/browser/api/net.ts",
|
||||
"lib/browser/api/notification.js",
|
||||
"lib/browser/api/notification.ts",
|
||||
"lib/browser/api/power-monitor.ts",
|
||||
"lib/browser/api/power-save-blocker.js",
|
||||
"lib/browser/api/power-save-blocker.ts",
|
||||
"lib/browser/api/protocol.ts",
|
||||
"lib/browser/api/screen.ts",
|
||||
"lib/browser/api/session.js",
|
||||
"lib/browser/api/session.ts",
|
||||
"lib/browser/api/system-preferences.ts",
|
||||
"lib/browser/api/top-level-window.js",
|
||||
"lib/browser/api/touch-bar.js",
|
||||
"lib/browser/api/tray.js",
|
||||
"lib/browser/api/view.js",
|
||||
"lib/browser/api/views/image-view.js",
|
||||
"lib/browser/api/web-contents-view.js",
|
||||
"lib/browser/api/tray.ts",
|
||||
"lib/browser/api/view.ts",
|
||||
"lib/browser/api/views/image-view.ts",
|
||||
"lib/browser/api/web-contents-view.ts",
|
||||
"lib/browser/api/web-contents.js",
|
||||
"lib/browser/chrome-extension-shim.js",
|
||||
"lib/browser/default-menu.ts",
|
||||
@@ -235,15 +237,14 @@ auto_filenames = {
|
||||
"lib/browser/navigation-controller.js",
|
||||
"lib/browser/remote/objects-registry.ts",
|
||||
"lib/browser/remote/server.ts",
|
||||
"lib/browser/rpc-server.js",
|
||||
"lib/browser/rpc-server.ts",
|
||||
"lib/browser/utils.ts",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/parse-features-string.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
@@ -255,17 +256,18 @@ auto_filenames = {
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
"typings/internal-ambient.d.ts",
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
|
||||
renderer_bundle_deps = [
|
||||
"lib/browser/api/module-names.ts",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
@@ -277,7 +279,7 @@ auto_filenames = {
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/remote.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/init.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
@@ -297,17 +299,18 @@ auto_filenames = {
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
"typings/internal-ambient.d.ts",
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
|
||||
worker_bundle_deps = [
|
||||
"lib/browser/api/module-names.ts",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
@@ -318,7 +321,7 @@ auto_filenames = {
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/remote.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
@@ -328,5 +331,7 @@ auto_filenames = {
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
"typings/internal-ambient.d.ts",
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import * as path from 'path';
|
||||
import { deprecate, Menu } from 'electron';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const bindings = process.electronBinding('app');
|
||||
const commandLine = process.electronBinding('command_line');
|
||||
const bindings = process._linkedBinding('electron_browser_app');
|
||||
const commandLine = process._linkedBinding('electron_common_command_line');
|
||||
const { app, App } = bindings;
|
||||
|
||||
// Only one app object permitted.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const { autoUpdater, AutoUpdater } = process.electronBinding('auto_updater');
|
||||
const { autoUpdater, AutoUpdater } = process._linkedBinding('electron_browser_auto_updater');
|
||||
|
||||
// AutoUpdater is an EventEmitter.
|
||||
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype);
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const { BrowserView } = process.electronBinding('browser_view');
|
||||
|
||||
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
|
||||
|
||||
BrowserView.fromWebContents = (webContents) => {
|
||||
for (const view of BrowserView.getAllViews()) {
|
||||
if (view.webContents.equal(webContents)) return view;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
module.exports = BrowserView;
|
||||
15
lib/browser/api/browser-view.ts
Normal file
15
lib/browser/api/browser-view.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { BrowserView } = process._linkedBinding('electron_browser_browser_view');
|
||||
|
||||
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
|
||||
|
||||
BrowserView.fromWebContents = (webContents: Electron.WebContents) => {
|
||||
for (const view of BrowserView.getAllViews()) {
|
||||
if (view.webContents.equal(webContents)) return view;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default BrowserView;
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const electron = require('electron');
|
||||
const { TopLevelWindow, deprecate } = electron;
|
||||
const { BrowserWindow } = process.electronBinding('window');
|
||||
const { BrowserWindow } = process._linkedBinding('electron_browser_window');
|
||||
|
||||
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype);
|
||||
|
||||
@@ -59,7 +59,7 @@ BrowserWindow.prototype._init = function () {
|
||||
}
|
||||
|
||||
// Notify the creation of the window.
|
||||
const event = process.electronBinding('event').createEmpty();
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('browser-window-created', event, this);
|
||||
|
||||
Object.defineProperty(this, 'devToolsWebContents', {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
'use strict';
|
||||
module.exports = process.electronBinding('content_tracing');
|
||||
1
lib/browser/api/content-tracing.ts
Normal file
1
lib/browser/api/content-tracing.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default process._linkedBinding('electron_browser_content_tracing');
|
||||
@@ -1,6 +1,6 @@
|
||||
import { app, deprecate } from 'electron';
|
||||
|
||||
const binding = process.electronBinding('crash_reporter');
|
||||
const binding = process._linkedBinding('electron_browser_crash_reporter');
|
||||
|
||||
class CrashReporter {
|
||||
start (options: Electron.CrashReporterStartOptions) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const { app, BrowserWindow, deprecate } = require('electron');
|
||||
const binding = process.electronBinding('dialog');
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const binding = process._linkedBinding('electron_browser_dialog');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const DialogType = {
|
||||
OPEN: 'OPEN',
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = process.electronBinding('global_shortcut').globalShortcut;
|
||||
2
lib/browser/api/global-shortcut.ts
Normal file
2
lib/browser/api/global-shortcut.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
const { globalShortcut } = process._linkedBinding('electron_browser_global_shortcut');
|
||||
export default globalShortcut;
|
||||
@@ -1,22 +1,24 @@
|
||||
'use strict';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { deprecate } = require('electron');
|
||||
let _inAppPurchase;
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
const { EventEmitter } = require('events');
|
||||
const { inAppPurchase, InAppPurchase } = process.electronBinding('in_app_purchase');
|
||||
const { inAppPurchase, InAppPurchase } = process._linkedBinding('electron_browser_in_app_purchase');
|
||||
|
||||
// inAppPurchase is an EventEmitter.
|
||||
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype);
|
||||
EventEmitter.call(inAppPurchase);
|
||||
|
||||
module.exports = inAppPurchase;
|
||||
_inAppPurchase = inAppPurchase;
|
||||
} else {
|
||||
module.exports = {
|
||||
purchaseProduct: (productID, quantity, callback) => {
|
||||
_inAppPurchase = new EventEmitter();
|
||||
Object.assign(_inAppPurchase, {
|
||||
purchaseProduct: () => {
|
||||
throw new Error('The inAppPurchase module can only be used on macOS');
|
||||
},
|
||||
canMakePayments: () => false,
|
||||
getReceiptURL: () => ''
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export default _inAppPurchase;
|
||||
@@ -3,8 +3,8 @@
|
||||
const { TopLevelWindow, MenuItem, webContents } = require('electron');
|
||||
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const bindings = process.electronBinding('menu');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
const bindings = process._linkedBinding('electron_browser_menu');
|
||||
|
||||
const { Menu } = bindings;
|
||||
let applicationMenu = null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
const { createPair } = process.electronBinding('message_port');
|
||||
const { createPair } = process._linkedBinding('electron_browser_message_port');
|
||||
|
||||
export default class MessageChannelMain {
|
||||
port1: MessagePortMain;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { NativeTheme, nativeTheme } = process.electronBinding('native_theme');
|
||||
const { NativeTheme, nativeTheme } = process._linkedBinding('electron_common_native_theme');
|
||||
|
||||
Object.setPrototypeOf(NativeTheme.prototype, EventEmitter.prototype);
|
||||
EventEmitter.call(nativeTheme as any);
|
||||
|
||||
@@ -2,7 +2,13 @@ import * as url from 'url';
|
||||
import { Readable, Writable } from 'stream';
|
||||
import { app } from 'electron';
|
||||
import { ClientRequestConstructorOptions, UploadProgress } from 'electron/main';
|
||||
const { net, Net, isValidHeaderName, isValidHeaderValue, createURLLoader } = process.electronBinding('net');
|
||||
const {
|
||||
net,
|
||||
Net,
|
||||
isValidHeaderName,
|
||||
isValidHeaderValue,
|
||||
createURLLoader
|
||||
} = process._linkedBinding('electron_browser_net');
|
||||
|
||||
const kSupportedProtocols = new Set(['http:', 'https:']);
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { Notification, isSupported } = process.electronBinding('notification');
|
||||
|
||||
Notification.isSupported = isSupported;
|
||||
|
||||
module.exports = Notification;
|
||||
8
lib/browser/api/notification.ts
Normal file
8
lib/browser/api/notification.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
const {
|
||||
Notification: ElectronNotification,
|
||||
isSupported
|
||||
} = process._linkedBinding('electron_common_notification');
|
||||
|
||||
ElectronNotification.isSupported = isSupported;
|
||||
|
||||
export default ElectronNotification;
|
||||
@@ -1,7 +1,11 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { app } from 'electron';
|
||||
|
||||
const { createPowerMonitor, getSystemIdleState, getSystemIdleTime } = process.electronBinding('power_monitor');
|
||||
const {
|
||||
createPowerMonitor,
|
||||
getSystemIdleState,
|
||||
getSystemIdleTime
|
||||
} = process._linkedBinding('electron_browser_power_monitor');
|
||||
|
||||
class PowerMonitor extends EventEmitter {
|
||||
constructor () {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = process.electronBinding('power_save_blocker').powerSaveBlocker;
|
||||
2
lib/browser/api/power-save-blocker.ts
Normal file
2
lib/browser/api/power-save-blocker.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
const { powerSaveBlocker } = process._linkedBinding('electron_browser_power_save_blocker');
|
||||
export default powerSaveBlocker;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { app, session } from 'electron';
|
||||
|
||||
// Global protocol APIs.
|
||||
const protocol = process.electronBinding('protocol');
|
||||
const protocol = process._linkedBinding('electron_browser_protocol');
|
||||
|
||||
// Fallback protocol APIs of default session.
|
||||
Object.setPrototypeOf(protocol, new Proxy({}, {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { createLazyInstance } from '../utils';
|
||||
const { EventEmitter } = require('events');
|
||||
const { Screen, createScreen } = process.electronBinding('screen');
|
||||
const { Screen, createScreen } = process._linkedBinding('electron_common_screen');
|
||||
|
||||
// Screen is an EventEmitter.
|
||||
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype);
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const { app, deprecate } = require('electron');
|
||||
const { fromPartition } = process.electronBinding('session');
|
||||
|
||||
// Public API.
|
||||
Object.defineProperties(exports, {
|
||||
defaultSession: {
|
||||
enumerable: true,
|
||||
get () { return fromPartition(''); }
|
||||
},
|
||||
fromPartition: {
|
||||
enumerable: true,
|
||||
value: fromPartition
|
||||
}
|
||||
});
|
||||
8
lib/browser/api/session.ts
Normal file
8
lib/browser/api/session.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
const { fromPartition } = process._linkedBinding('electron_browser_session');
|
||||
|
||||
export default {
|
||||
fromPartition,
|
||||
get defaultSession () {
|
||||
return fromPartition('');
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { deprecate } from 'electron';
|
||||
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences');
|
||||
const { systemPreferences, SystemPreferences } = process._linkedBinding('electron_browser_system_preferences');
|
||||
|
||||
// SystemPreferences is an EventEmitter.
|
||||
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const electron = require('electron');
|
||||
const { EventEmitter } = require('events');
|
||||
const { TopLevelWindow } = process.electronBinding('top_level_window');
|
||||
const { TopLevelWindow } = process._linkedBinding('electron_browser_top_level_window');
|
||||
|
||||
Object.setPrototypeOf(TopLevelWindow.prototype, EventEmitter.prototype);
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { Tray } = process.electronBinding('tray');
|
||||
|
||||
module.exports = Tray;
|
||||
3
lib/browser/api/tray.ts
Normal file
3
lib/browser/api/tray.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
const { Tray } = process._linkedBinding('electron_browser_tray');
|
||||
|
||||
export default Tray;
|
||||
@@ -1,5 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { View } = process.electronBinding('view');
|
||||
|
||||
module.exports = View;
|
||||
3
lib/browser/api/view.ts
Normal file
3
lib/browser/api/view.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
const { View } = process._linkedBinding('electron_browser_view');
|
||||
|
||||
export default View;
|
||||
@@ -1,8 +0,0 @@
|
||||
const electron = require('electron');
|
||||
|
||||
const { View } = electron;
|
||||
const { ImageView } = process.electronBinding('image_view');
|
||||
|
||||
Object.setPrototypeOf(ImageView.prototype, View.prototype);
|
||||
|
||||
module.exports = ImageView;
|
||||
7
lib/browser/api/views/image-view.ts
Normal file
7
lib/browser/api/views/image-view.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { View } from 'electron';
|
||||
|
||||
const { ImageView } = process._linkedBinding('electron_browser_image_view');
|
||||
|
||||
Object.setPrototypeOf(ImageView.prototype, View.prototype);
|
||||
|
||||
export default ImageView;
|
||||
@@ -1,10 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const electron = require('electron');
|
||||
|
||||
const { View } = electron;
|
||||
const { WebContentsView } = process.electronBinding('web_contents_view');
|
||||
|
||||
Object.setPrototypeOf(WebContentsView.prototype, View.prototype);
|
||||
|
||||
module.exports = WebContentsView;
|
||||
7
lib/browser/api/web-contents-view.ts
Normal file
7
lib/browser/api/web-contents-view.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { View } from 'electron';
|
||||
|
||||
const { WebContentsView } = process._linkedBinding('electron_browser_web_contents_view');
|
||||
|
||||
Object.setPrototypeOf(WebContentsView.prototype, View.prototype);
|
||||
|
||||
export default WebContentsView;
|
||||
@@ -97,7 +97,7 @@ const defaultPrintingSetting = {
|
||||
};
|
||||
|
||||
// JavaScript implementations of WebContents.
|
||||
const binding = process.electronBinding('web_contents');
|
||||
const binding = process._linkedBinding('electron_browser_web_contents');
|
||||
const { WebContents } = binding;
|
||||
|
||||
Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype);
|
||||
@@ -562,7 +562,7 @@ WebContents.prototype._init = function () {
|
||||
app.emit('login', event, this, ...args);
|
||||
});
|
||||
|
||||
const event = process.electronBinding('event').createEmpty();
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
|
||||
// Properties
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { shell, Menu } from 'electron';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const isMac = process.platform === 'darwin';
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
const { createDesktopCapturer } = process.electronBinding('desktop_capturer');
|
||||
const {
|
||||
createDesktopCapturer,
|
||||
getMediaSourceIdForWebContents: getMediaSourceIdForWebContentsBinding
|
||||
} = process._linkedBinding('electron_browser_desktop_capturer');
|
||||
|
||||
const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b);
|
||||
|
||||
@@ -77,3 +80,7 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
|
||||
|
||||
return getSources;
|
||||
};
|
||||
|
||||
export const getMediaSourceIdForWebContents = (event: Electron.IpcMainEvent, webContentsId: number) => {
|
||||
return getMediaSourceIdForWebContentsBinding(event.sender.id, webContentsId);
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ function sanitizeOptionsForGuest (options) {
|
||||
// Create a new guest instance.
|
||||
const createGuest = function (embedder, params) {
|
||||
if (webViewManager == null) {
|
||||
webViewManager = process.electronBinding('web_view_manager');
|
||||
webViewManager = process._linkedBinding('electron_browser_web_view_manager');
|
||||
}
|
||||
|
||||
const guest = webContents.create({
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const electron = require('electron');
|
||||
const { BrowserWindow } = electron;
|
||||
const { isSameOrigin } = process.electronBinding('v8_util');
|
||||
const { isSameOrigin } = process._linkedBinding('electron_common_v8_util');
|
||||
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils');
|
||||
const { parseFeatures } = require('@electron/internal/common/parse-features-string');
|
||||
|
||||
@@ -17,7 +17,7 @@ require('../common/reset-search-paths');
|
||||
// Import common settings.
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
process.electronBinding('event_emitter').setEventEmitterPrototype(EventEmitter.prototype);
|
||||
process._linkedBinding('electron_browser_event_emitter').setEventEmitterPrototype(EventEmitter.prototype);
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
// Redirect node's console to use our own implementations, since node can not
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { WebContents } from 'electron';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const getOwnerKey = (webContents: WebContents, contextId: string) => {
|
||||
return `${webContents.id}-${contextId}`;
|
||||
@@ -51,19 +51,11 @@ class ObjectsRegistry {
|
||||
// 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).
|
||||
// rendererSideRefCount is the ref count that the renderer process reported
|
||||
// at time of GC if this is different to the number of references we sent to
|
||||
// the given owner then a GC occurred between a ref being sent and the value
|
||||
// being pulled out of the weak map.
|
||||
// In this case we decrement out ref count and do not delete the stored
|
||||
// object
|
||||
// For more details on why we do renderer side ref counting see
|
||||
// https://github.com/electron/electron/pull/17464
|
||||
remove (webContents: WebContents, contextId: string, id: number, rendererSideRefCount: number) {
|
||||
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)! - rendererSideRefCount;
|
||||
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
|
||||
|
||||
@@ -1,38 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
import * as electron from 'electron';
|
||||
import { EventEmitter } from 'events';
|
||||
import objectsRegistry from './objects-registry';
|
||||
import { ipcMainInternal } from '../ipc-main-internal';
|
||||
import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
|
||||
import { Size } from 'electron/main';
|
||||
import { isPromise, isSerializableObject, deserialize, serialize } from '../../common/type-utils';
|
||||
import type { MetaTypeFromRenderer, ObjectMember, MetaType, ObjProtoDescriptor } from '../../common/remote/types';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const eventBinding = process.electronBinding('event');
|
||||
const features = process.electronBinding('features');
|
||||
const { NativeImage } = process.electronBinding('native_image');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
const eventBinding = process._linkedBinding('electron_browser_event');
|
||||
const features = process._linkedBinding('electron_common_features');
|
||||
const { NativeImage } = process._linkedBinding('electron_common_native_image');
|
||||
|
||||
if (!features.isRemoteModuleEnabled()) {
|
||||
throw new Error('remote module is disabled');
|
||||
}
|
||||
|
||||
const hasProp = {}.hasOwnProperty;
|
||||
|
||||
// The internal properties of Function.
|
||||
const FUNCTION_PROPERTIES = [
|
||||
'length', 'name', 'arguments', 'caller', 'prototype'
|
||||
];
|
||||
|
||||
// The remote functions in renderer processes.
|
||||
// id => Function
|
||||
const rendererFunctions = v8Util.createDoubleIDWeakMap<(...args: any[]) => void>();
|
||||
type RendererFunctionId = [string, number] // [contextId, funcId]
|
||||
type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: number };
|
||||
type WeakRef<T> = { deref(): T | undefined }
|
||||
type CallIntoRenderer = (...args: any[]) => void
|
||||
|
||||
type ObjectMember = {
|
||||
name: string,
|
||||
value?: any,
|
||||
enumerable?: boolean,
|
||||
writable?: boolean,
|
||||
type?: 'method' | 'get'
|
||||
// The remote functions in renderer processes.
|
||||
const rendererFunctionCache = new Map<string, WeakRef<CallIntoRenderer>>();
|
||||
// eslint-disable-next-line no-undef
|
||||
const finalizationRegistry = new (globalThis as any).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()) { fi.webContents.sendToFrame(fi.frameId, 'ELECTRON_RENDERER_RELEASE_CALLBACK', fi.id[0], fi.id[1]); }
|
||||
}
|
||||
});
|
||||
|
||||
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, value: CallIntoRenderer) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const wr = new (globalThis as any).WeakRef(value) as WeakRef<CallIntoRenderer>;
|
||||
const mapKey = id[0] + '~' + id[1];
|
||||
rendererFunctionCache.set(mapKey, wr);
|
||||
finalizationRegistry.register(value, {
|
||||
id,
|
||||
webContents: wc,
|
||||
frameId
|
||||
} as FinalizerInfo);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Return the description of object's members:
|
||||
@@ -60,11 +82,6 @@ const getObjectMembers = function (object: any): ObjectMember[] {
|
||||
});
|
||||
};
|
||||
|
||||
type ObjProtoDescriptor = {
|
||||
members: ObjectMember[],
|
||||
proto: ObjProtoDescriptor
|
||||
} | null
|
||||
|
||||
// Return the description of object's prototype.
|
||||
const getObjectPrototype = function (object: any): ObjProtoDescriptor {
|
||||
const proto = Object.getPrototypeOf(object);
|
||||
@@ -75,76 +92,42 @@ const getObjectPrototype = function (object: any): ObjProtoDescriptor {
|
||||
};
|
||||
};
|
||||
|
||||
type MetaType = {
|
||||
type: 'number',
|
||||
value: number
|
||||
} | {
|
||||
type: 'boolean',
|
||||
value: boolean
|
||||
} | {
|
||||
type: 'string',
|
||||
value: string
|
||||
} | {
|
||||
type: 'bigint',
|
||||
value: bigint
|
||||
} | {
|
||||
type: 'symbol',
|
||||
value: symbol
|
||||
} | {
|
||||
type: 'undefined',
|
||||
value: undefined
|
||||
} | {
|
||||
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: 'promise',
|
||||
then: MetaType
|
||||
} | {
|
||||
type: 'nativeimage'
|
||||
value: electron.NativeImage
|
||||
}
|
||||
|
||||
// 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'] = typeof value;
|
||||
if (type === 'object') {
|
||||
// Recognize certain types of objects.
|
||||
if (value instanceof Buffer) {
|
||||
type = 'buffer';
|
||||
} else if (value instanceof NativeImage) {
|
||||
type = 'nativeimage';
|
||||
} else if (Array.isArray(value)) {
|
||||
type = 'array';
|
||||
} else if (value instanceof Error) {
|
||||
type = 'error';
|
||||
} else if (isSerializableObject(value)) {
|
||||
let type: MetaType['type'];
|
||||
|
||||
switch (typeof value) {
|
||||
case 'object':
|
||||
// Recognize certain types of objects.
|
||||
if (value instanceof Buffer) {
|
||||
type = 'buffer';
|
||||
} else if (value instanceof 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';
|
||||
} else if (isPromise(value)) {
|
||||
type = 'promise';
|
||||
} else if (hasProp.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';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Fill the meta object according to value's type.
|
||||
@@ -224,46 +207,6 @@ const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...a
|
||||
console.warn(message);
|
||||
};
|
||||
|
||||
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
|
||||
}[]
|
||||
}
|
||||
|
||||
const fakeConstructor = (constructor: Function, name: string) =>
|
||||
new Proxy(Object, {
|
||||
get (target, prop, receiver) {
|
||||
@@ -315,9 +258,8 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
|
||||
const objectId: [string, number] = [contextId, meta.id];
|
||||
|
||||
// Cache the callbacks in renderer.
|
||||
if (rendererFunctions.has(objectId)) {
|
||||
return rendererFunctions.get(objectId);
|
||||
}
|
||||
const cachedFunction = getCachedRendererFunction(objectId);
|
||||
if (cachedFunction !== undefined) { return cachedFunction; }
|
||||
|
||||
const callIntoRenderer = function (this: any, ...args: any[]) {
|
||||
let succeed = false;
|
||||
@@ -331,8 +273,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
|
||||
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
|
||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
|
||||
|
||||
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId, contextId, meta.id, sender);
|
||||
rendererFunctions.set(objectId, callIntoRenderer);
|
||||
setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);
|
||||
return callIntoRenderer;
|
||||
}
|
||||
default:
|
||||
@@ -343,13 +284,13 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
|
||||
};
|
||||
|
||||
const isRemoteModuleEnabledImpl = function (contents: electron.WebContents) {
|
||||
const webPreferences = (contents as any).getLastWebPreferences() || {};
|
||||
const webPreferences = contents.getLastWebPreferences() || {};
|
||||
return webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : false;
|
||||
};
|
||||
|
||||
const isRemoteModuleEnabledCache = new WeakMap();
|
||||
|
||||
const isRemoteModuleEnabled = function (contents: electron.WebContents) {
|
||||
export const isRemoteModuleEnabled = function (contents: electron.WebContents) {
|
||||
if (!isRemoteModuleEnabledCache.has(contents)) {
|
||||
isRemoteModuleEnabledCache.set(contents, isRemoteModuleEnabledImpl(contents));
|
||||
}
|
||||
@@ -397,11 +338,12 @@ const logStack = function (contents: electron.WebContents, code: string, stack:
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_WRONG_CONTEXT_ERROR', function (event, contextId, passedContextId, id) {
|
||||
const objectId: [string, number] = [passedContextId, id];
|
||||
if (!rendererFunctions.has(objectId)) {
|
||||
const cachedFunction = getCachedRendererFunction(objectId);
|
||||
if (cachedFunction === undefined) {
|
||||
// Do nothing if the error has already been reported before.
|
||||
return;
|
||||
}
|
||||
removeRemoteListenersAndLogWarning(event.sender, rendererFunctions.get(objectId)!);
|
||||
removeRemoteListenersAndLogWarning(event.sender, cachedFunction);
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_REQUIRE', function (event, contextId, moduleName, stack) {
|
||||
@@ -557,14 +499,10 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_GET', function (event, contextId, i
|
||||
return valueToMeta(event.sender, contextId, obj[name]);
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_DEREFERENCE', function (event, contextId, id, rendererSideRefCount) {
|
||||
objectsRegistry.remove(event.sender, contextId, id, rendererSideRefCount);
|
||||
handleRemoteCommand('ELECTRON_BROWSER_DEREFERENCE', function (event, contextId, id) {
|
||||
objectsRegistry.remove(event.sender, contextId, id);
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_CONTEXT_RELEASE', (event, contextId) => {
|
||||
objectsRegistry.clear(event.sender, contextId);
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
isRemoteModuleEnabled
|
||||
};
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
'use strict';
|
||||
import * as electron from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import { ipcMainInternal } from './ipc-main-internal';
|
||||
import * as ipcMainUtils from './ipc-main-internal-utils';
|
||||
import * as guestViewManager from './guest-view-manager';
|
||||
import * as typeUtils from '../common/type-utils';
|
||||
import { IpcMainInvokeEvent } from 'electron/main';
|
||||
|
||||
const electron = require('electron');
|
||||
const fs = require('fs');
|
||||
const eventBinding = process._linkedBinding('electron_browser_event');
|
||||
const clipboard = process._linkedBinding('electron_common_clipboard');
|
||||
|
||||
const eventBinding = process.electronBinding('event');
|
||||
const clipboard = process.electronBinding('clipboard');
|
||||
|
||||
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils');
|
||||
const guestViewManager = require('@electron/internal/browser/guest-view-manager');
|
||||
const typeUtils = require('@electron/internal/common/type-utils');
|
||||
|
||||
const emitCustomEvent = function (contents, eventName, ...args) {
|
||||
const emitCustomEvent = function (contents: electron.WebContents, eventName: string, ...args: any[]) {
|
||||
const event = eventBinding.createWithSender(contents);
|
||||
|
||||
electron.app.emit(eventName, event, contents, ...args);
|
||||
@@ -20,14 +18,14 @@ const emitCustomEvent = function (contents, eventName, ...args) {
|
||||
return event;
|
||||
};
|
||||
|
||||
const logStack = function (contents, code, stack) {
|
||||
const logStack = function (contents: electron.WebContents, code: string, stack: string) {
|
||||
if (stack) {
|
||||
console.warn(`WebContents (${contents.id}): ${code}`, stack);
|
||||
}
|
||||
};
|
||||
|
||||
// Implements window.close()
|
||||
ipcMainInternal.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) {
|
||||
ipcMainInternal.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event: ElectronInternal.IpcMainInternalEvent) {
|
||||
const window = event.sender.getOwnerBrowserWindow();
|
||||
if (window) {
|
||||
window.close();
|
||||
@@ -35,7 +33,7 @@ ipcMainInternal.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) {
|
||||
event.returnValue = null;
|
||||
});
|
||||
|
||||
ipcMainInternal.handle('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event) {
|
||||
ipcMainInternal.handle('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event: IpcMainInvokeEvent) {
|
||||
return event.sender.getLastWebPreferences();
|
||||
});
|
||||
|
||||
@@ -51,18 +49,18 @@ const allowedClipboardMethods = (() => {
|
||||
}
|
||||
})();
|
||||
|
||||
ipcMainUtils.handleSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', function (event, method, ...args) {
|
||||
ipcMainUtils.handleSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', function (event: IpcMainInvokeEvent, method: string, ...args: any[]) {
|
||||
if (!allowedClipboardMethods.has(method)) {
|
||||
throw new Error(`Invalid method: ${method}`);
|
||||
}
|
||||
|
||||
return typeUtils.serialize(electron.clipboard[method](...typeUtils.deserialize(args)));
|
||||
return typeUtils.serialize((electron.clipboard as any)[method](...typeUtils.deserialize(args)));
|
||||
});
|
||||
|
||||
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
const desktopCapturer = require('@electron/internal/browser/desktop-capturer');
|
||||
|
||||
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', async function (event, options, stack) {
|
||||
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', async function (event: IpcMainInvokeEvent, options: Electron.SourcesOptions, stack: string) {
|
||||
logStack(event.sender, 'desktopCapturer.getSources()', stack);
|
||||
const customEvent = emitCustomEvent(event.sender, 'desktop-capturer-get-sources');
|
||||
|
||||
@@ -73,13 +71,17 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
|
||||
return typeUtils.serialize(await desktopCapturer.getSourcesImpl(event, options));
|
||||
});
|
||||
|
||||
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', function (event: IpcMainInvokeEvent, webContentsId: number) {
|
||||
return desktopCapturer.getMediaSourceIdForWebContents(event, webContentsId);
|
||||
});
|
||||
}
|
||||
|
||||
const isRemoteModuleEnabled = BUILDFLAG(ENABLE_REMOTE_MODULE)
|
||||
? require('@electron/internal/browser/remote/server').isRemoteModuleEnabled
|
||||
: () => false;
|
||||
|
||||
const getPreloadScript = async function (preloadPath) {
|
||||
const getPreloadScript = async function (preloadPath: string) {
|
||||
let preloadSrc = null;
|
||||
let preloadError = null;
|
||||
try {
|
||||
@@ -90,7 +92,7 @@ const getPreloadScript = async function (preloadPath) {
|
||||
return { preloadPath, preloadSrc, preloadError };
|
||||
};
|
||||
|
||||
ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event) {
|
||||
ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event: IpcMainInvokeEvent) {
|
||||
const preloadPaths = event.sender._getPreloadPaths();
|
||||
const webPreferences = event.sender.getLastWebPreferences() || {};
|
||||
|
||||
@@ -111,7 +113,7 @@ ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event)
|
||||
};
|
||||
});
|
||||
|
||||
ipcMainInternal.on('ELECTRON_BROWSER_PRELOAD_ERROR', function (event, preloadPath, error) {
|
||||
ipcMainInternal.on('ELECTRON_BROWSER_PRELOAD_ERROR', function (event: ElectronInternal.IpcMainInternalEvent, preloadPath: string, error: Error) {
|
||||
event.sender.emit('preload-error', event, preloadPath, error);
|
||||
});
|
||||
|
||||
@@ -127,7 +129,7 @@ ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_GET_UPLOAD_TO_SERVER', () => {
|
||||
return electron.crashReporter.getUploadToServer();
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_SET_UPLOAD_TO_SERVER', (event, uploadToServer) => {
|
||||
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_SET_UPLOAD_TO_SERVER', (event: IpcMainInvokeEvent, uploadToServer: boolean) => {
|
||||
return electron.crashReporter.setUploadToServer(uploadToServer);
|
||||
});
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const clipboard = process.electronBinding('clipboard');
|
||||
const clipboard = process._linkedBinding('electron_common_clipboard');
|
||||
|
||||
if (process.type === 'renderer') {
|
||||
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils');
|
||||
const typeUtils = require('@electron/internal/common/type-utils');
|
||||
|
||||
const makeRemoteMethod = function (method) {
|
||||
return (...args) => {
|
||||
const makeRemoteMethod = function (method: keyof Electron.Clipboard) {
|
||||
return (...args: any[]) => {
|
||||
args = typeUtils.serialize(args);
|
||||
const result = ipcRendererUtils.invokeSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', method, ...args);
|
||||
return typeUtils.deserialize(result);
|
||||
@@ -16,7 +14,7 @@ if (process.type === 'renderer') {
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
// On Linux we could not access clipboard in renderer process.
|
||||
for (const method of Object.keys(clipboard)) {
|
||||
for (const method of Object.keys(clipboard) as (keyof Electron.Clipboard)[]) {
|
||||
clipboard[method] = makeRemoteMethod(method);
|
||||
}
|
||||
} else if (process.platform === 'darwin') {
|
||||
@@ -26,4 +24,4 @@ if (process.type === 'renderer') {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = clipboard;
|
||||
export default clipboard;
|
||||
@@ -76,23 +76,6 @@ const deprecate: ElectronInternal.DeprecationUtil = {
|
||||
});
|
||||
},
|
||||
|
||||
// deprecate a getter/setter function pair in favor of a property
|
||||
fnToProperty: (prototype: any, prop: string, getter: string, setter?: string) => {
|
||||
const withWarnOnce = function (obj: any, key: any, oldName: string, newName: string) {
|
||||
const warn = warnOnce(oldName, newName);
|
||||
const method = obj[key];
|
||||
return function (this: any, ...args: any) {
|
||||
warn();
|
||||
return method.apply(this, args);
|
||||
};
|
||||
};
|
||||
|
||||
prototype[getter.substr(1)] = withWarnOnce(prototype, getter, `${getter.substr(1)} function`, `${prop} property`);
|
||||
if (setter) {
|
||||
prototype[setter.substr(1)] = withWarnOnce(prototype, setter, `${setter.substr(1)} function`, `${prop} property`);
|
||||
}
|
||||
},
|
||||
|
||||
// remove a property with no replacement
|
||||
removeProperty: (o, removedName, onlyForValues) => {
|
||||
// if the property's already been removed, warn about it
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { nativeImage } = process.electronBinding('native_image');
|
||||
|
||||
module.exports = nativeImage;
|
||||
3
lib/common/api/native-image.ts
Normal file
3
lib/common/api/native-image.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
const { nativeImage } = process._linkedBinding('electron_common_native_image');
|
||||
|
||||
export default nativeImage;
|
||||
@@ -1,3 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = process.electronBinding('shell');
|
||||
1
lib/common/api/shell.ts
Normal file
1
lib/common/api/shell.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default process._linkedBinding('electron_common_shell');
|
||||
@@ -1,13 +0,0 @@
|
||||
export function electronBindingSetup (binding: typeof process['_linkedBinding'], processType: typeof process['type']): typeof process['electronBinding'] {
|
||||
return function electronBinding (name: string) {
|
||||
try {
|
||||
return binding(`electron_${processType}_${name}`);
|
||||
} catch (error) {
|
||||
if (/No such module/.test(error.message)) {
|
||||
return binding(`electron_common_${name}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
import * as util from 'util';
|
||||
|
||||
import { electronBindingSetup } from '@electron/internal/common/electron-binding-setup';
|
||||
|
||||
const timers = require('timers');
|
||||
|
||||
process.electronBinding = electronBindingSetup(process._linkedBinding, process.type);
|
||||
|
||||
type AnyFn = (...args: any[]) => any
|
||||
|
||||
// setImmediate and process.nextTick makes use of uv_check and uv_prepare to
|
||||
|
||||
85
lib/common/remote/types.ts
Normal file
85
lib/common/remote/types.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
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
|
||||
}[]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const { nativeImage, NativeImage } = process.electronBinding('native_image');
|
||||
const { nativeImage, NativeImage } = process._linkedBinding('electron_common_native_image');
|
||||
|
||||
export function isPromise (val: any) {
|
||||
return (
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
/* global nodeProcess, isolatedWorld */
|
||||
|
||||
process.electronBinding = require('@electron/internal/common/electron-binding-setup').electronBindingSetup(nodeProcess._linkedBinding, 'renderer');
|
||||
process._linkedBinding = nodeProcess._linkedBinding;
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const webViewImpl = v8Util.getHiddenValue(isolatedWorld, 'web-view-impl');
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { hasSwitch } = process.electronBinding('command_line');
|
||||
const binding = process.electronBinding('context_bridge');
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
const binding = process._linkedBinding('electron_renderer_context_bridge');
|
||||
|
||||
const contextIsolationEnabled = hasSwitch('context-isolation');
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { invokeSync } from '../ipc-renderer-internal-utils';
|
||||
import { deprecate } from 'electron';
|
||||
|
||||
const binding = process.electronBinding('crash_reporter');
|
||||
const binding = process._linkedBinding('electron_renderer_crash_reporter');
|
||||
|
||||
export default {
|
||||
start (options: Electron.CrashReporterStartOptions) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import { deserialize } from '@electron/internal/common/type-utils';
|
||||
|
||||
const { hasSwitch } = process.electronBinding('command_line');
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
const enableStacks = hasSwitch('enable-api-filtering-logging');
|
||||
|
||||
@@ -16,3 +16,7 @@ function getCurrentStack () {
|
||||
export async function getSources (options: Electron.SourcesOptions) {
|
||||
return deserialize(await ipcRendererInternal.invoke('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', options, getCurrentStack()));
|
||||
}
|
||||
|
||||
export function getMediaSourceIdForWebContents (webContentsId: number) {
|
||||
return ipcRendererInternal.invoke<string>('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', webContentsId, getCurrentStack());
|
||||
}
|
||||
|
||||
@@ -1,39 +1,36 @@
|
||||
const { ipc } = process.electronBinding('ipc');
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { ipc } = process._linkedBinding('electron_renderer_ipc');
|
||||
|
||||
// Created by init.js.
|
||||
const ipcRenderer = v8Util.getHiddenValue<Electron.IpcRenderer>(global, 'ipc');
|
||||
const internal = false;
|
||||
|
||||
// TODO(MarshallOfSound): Remove if statement when isolated_bundle and content_script_bundle are gone
|
||||
if (!ipcRenderer.send) {
|
||||
ipcRenderer.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
const ipcRenderer = new EventEmitter() as Electron.IpcRenderer;
|
||||
ipcRenderer.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
|
||||
ipcRenderer.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
ipcRenderer.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
|
||||
ipcRenderer.sendToHost = function (channel, ...args) {
|
||||
return ipc.sendToHost(channel, args);
|
||||
};
|
||||
ipcRenderer.sendToHost = function (channel, ...args) {
|
||||
return ipc.sendToHost(channel, args);
|
||||
};
|
||||
|
||||
ipcRenderer.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
ipcRenderer.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
|
||||
ipcRenderer.invoke = async function (channel, ...args) {
|
||||
const { error, result } = await ipc.invoke(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
ipcRenderer.invoke = async function (channel, ...args) {
|
||||
const { error, result } = await ipc.invoke(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
ipcRenderer.postMessage = function (channel: string, message: any, transferables: any) {
|
||||
return ipc.postMessage(channel, message, transferables);
|
||||
};
|
||||
}
|
||||
ipcRenderer.postMessage = function (channel: string, message: any, transferables: any) {
|
||||
return ipc.postMessage(channel, message, transferables);
|
||||
};
|
||||
|
||||
export default ipcRenderer;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const enableRemoteModule = v8Util.getHiddenValue<boolean>(global, 'enableRemoteModule');
|
||||
|
||||
|
||||
@@ -1,18 +1,41 @@
|
||||
'use strict';
|
||||
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 { browserModuleNames } from '@electron/internal/browser/api/module-names';
|
||||
import { commonModuleList } from '@electron/internal/common/api/module-list';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const { hasSwitch } = process.electronBinding('command_line');
|
||||
const { NativeImage } = process.electronBinding('native_image');
|
||||
|
||||
const { CallbacksRegistry } = require('@electron/internal/renderer/remote/callbacks-registry');
|
||||
const { isPromise, isSerializableObject, serialize, deserialize } = require('@electron/internal/common/type-utils');
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
const { NativeImage } = process._linkedBinding('electron_common_native_image');
|
||||
|
||||
const callbacksRegistry = new CallbacksRegistry();
|
||||
const remoteObjectCache = v8Util.createIDWeakMap();
|
||||
const remoteObjectCache = new Map();
|
||||
const finalizationRegistry = new (window as any).FinalizationRegistry((id: number) => {
|
||||
const ref = remoteObjectCache.get(id);
|
||||
if (ref !== undefined && ref.deref() === undefined) {
|
||||
remoteObjectCache.delete(id);
|
||||
ipcRendererInternal.send('ELECTRON_BROWSER_DEREFERENCE', contextId, id, 0);
|
||||
}
|
||||
});
|
||||
|
||||
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 (window as any).WeakRef(value);
|
||||
remoteObjectCache.set(id, wr);
|
||||
finalizationRegistry.register(value, id);
|
||||
return value;
|
||||
}
|
||||
|
||||
// An unique ID that can represent current context.
|
||||
const contextId = v8Util.getHiddenValue(global, 'contextId');
|
||||
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
|
||||
@@ -26,8 +49,8 @@ process.on('exit', () => {
|
||||
const IS_REMOTE_PROXY = Symbol('is-remote-proxy');
|
||||
|
||||
// Convert the arguments object into an array of meta data.
|
||||
function wrapArgs (args, visited = new Set()) {
|
||||
const valueToMeta = (value) => {
|
||||
function wrapArgs (args: any[], visited = new Set()): any {
|
||||
const valueToMeta = (value: any): any => {
|
||||
// Check for circular reference.
|
||||
if (visited.has(value)) {
|
||||
return {
|
||||
@@ -60,7 +83,7 @@ function wrapArgs (args, visited = new Set()) {
|
||||
if (isPromise(value)) {
|
||||
return {
|
||||
type: 'promise',
|
||||
then: valueToMeta(function (onFulfilled, onRejected) {
|
||||
then: valueToMeta(function (onFulfilled: Function, onRejected: Function) {
|
||||
value.then(onFulfilled, onRejected);
|
||||
})
|
||||
};
|
||||
@@ -71,7 +94,7 @@ function wrapArgs (args, visited = new Set()) {
|
||||
};
|
||||
}
|
||||
|
||||
const meta = {
|
||||
const meta: MetaTypeFromRenderer = {
|
||||
type: 'object',
|
||||
name: value.constructor ? value.constructor.name : '',
|
||||
members: []
|
||||
@@ -110,15 +133,15 @@ function wrapArgs (args, visited = new Set()) {
|
||||
// Populate object's members from descriptors.
|
||||
// The |ref| will be kept referenced by |members|.
|
||||
// This matches |getObjectMemebers| in rpc-server.
|
||||
function setObjectMembers (ref, object, metaId, members) {
|
||||
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 = { enumerable: member.enumerable };
|
||||
const descriptor: PropertyDescriptor = { enumerable: member.enumerable };
|
||||
if (member.type === 'method') {
|
||||
const remoteMemberFunction = function (...args) {
|
||||
const remoteMemberFunction = function (this: any, ...args: any[]) {
|
||||
let command;
|
||||
if (this && this.constructor === remoteMemberFunction) {
|
||||
command = 'ELECTRON_BROWSER_MEMBER_CONSTRUCTOR';
|
||||
@@ -165,7 +188,7 @@ function setObjectMembers (ref, object, metaId, members) {
|
||||
|
||||
// Populate object's prototype from descriptor.
|
||||
// This matches |getObjectPrototype| in rpc-server.
|
||||
function setObjectPrototype (ref, object, metaId, descriptor) {
|
||||
function setObjectPrototype (ref: any, object: any, metaId: number, descriptor: ObjProtoDescriptor) {
|
||||
if (descriptor === null) return;
|
||||
const proto = {};
|
||||
setObjectMembers(ref, proto, metaId, descriptor.members);
|
||||
@@ -174,7 +197,7 @@ function setObjectPrototype (ref, object, metaId, descriptor) {
|
||||
}
|
||||
|
||||
// Wrap function in Proxy for accessing remote properties
|
||||
function proxyFunctionProperties (remoteMemberFunction, metaId, name) {
|
||||
function proxyFunctionProperties (remoteMemberFunction: Function, metaId: number, name: string) {
|
||||
let loaded = false;
|
||||
|
||||
// Lazily load function properties
|
||||
@@ -186,13 +209,13 @@ function proxyFunctionProperties (remoteMemberFunction, metaId, name) {
|
||||
setObjectMembers(remoteMemberFunction, remoteMemberFunction, meta.id, meta.members);
|
||||
};
|
||||
|
||||
return new Proxy(remoteMemberFunction, {
|
||||
set: (target, property, value, receiver) => {
|
||||
return new Proxy(remoteMemberFunction as any, {
|
||||
set: (target, property, value) => {
|
||||
if (property !== 'ref') loadRemoteProperties();
|
||||
target[property] = value;
|
||||
return true;
|
||||
},
|
||||
get: (target, property, receiver) => {
|
||||
get: (target, property) => {
|
||||
if (property === IS_REMOTE_PROXY) return true;
|
||||
if (!Object.prototype.hasOwnProperty.call(target, property)) loadRemoteProperties();
|
||||
const value = target[property];
|
||||
@@ -215,29 +238,31 @@ function proxyFunctionProperties (remoteMemberFunction, metaId, name) {
|
||||
}
|
||||
|
||||
// Convert meta data from browser into real value.
|
||||
function metaToValue (meta) {
|
||||
const types = {
|
||||
value: () => meta.value,
|
||||
array: () => meta.members.map((member) => metaToValue(member)),
|
||||
nativeimage: () => deserialize(meta.value),
|
||||
buffer: () => Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength),
|
||||
promise: () => Promise.resolve({ then: metaToValue(meta.then) }),
|
||||
error: () => metaToError(meta),
|
||||
exception: () => { throw metaToError(meta.value); }
|
||||
};
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(types, meta.type)) {
|
||||
return types[meta.type]();
|
||||
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 (remoteObjectCache.has(meta.id)) {
|
||||
v8Util.addRemoteObjectRef(contextId, meta.id);
|
||||
return remoteObjectCache.get(meta.id);
|
||||
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 (...args) {
|
||||
const remoteFunction = function (this: any, ...args: any[]) {
|
||||
let command;
|
||||
if (this && this.constructor === remoteFunction) {
|
||||
command = 'ELECTRON_BROWSER_CONSTRUCTOR';
|
||||
@@ -254,20 +279,18 @@ function metaToValue (meta) {
|
||||
|
||||
setObjectMembers(ret, ret, meta.id, meta.members);
|
||||
setObjectPrototype(ret, ret, meta.id, meta.proto);
|
||||
if (ret.constructor && ret.constructor[IS_REMOTE_PROXY]) {
|
||||
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.
|
||||
v8Util.setRemoteObjectFreer(ret, contextId, meta.id);
|
||||
v8Util.setHiddenValue(ret, 'electronId', meta.id);
|
||||
v8Util.addRemoteObjectRef(contextId, meta.id);
|
||||
remoteObjectCache.set(meta.id, ret);
|
||||
setCachedRemoteObject(meta.id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
function metaToError (meta) {
|
||||
function metaToError (meta: { type: 'error', value: any, members: ObjectMember[] }) {
|
||||
const obj = meta.value;
|
||||
for (const { name, value } of meta.members) {
|
||||
obj[name] = metaToValue(value);
|
||||
@@ -275,7 +298,7 @@ function metaToError (meta) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
function handleMessage (channel, handler) {
|
||||
function handleMessage (channel: string, handler: Function) {
|
||||
ipcRendererInternal.on(channel, (event, passedContextId, id, ...args) => {
|
||||
if (passedContextId === contextId) {
|
||||
handler(id, ...args);
|
||||
@@ -288,8 +311,8 @@ function handleMessage (channel, handler) {
|
||||
|
||||
const enableStacks = hasSwitch('enable-api-filtering-logging');
|
||||
|
||||
function getCurrentStack () {
|
||||
const target = {};
|
||||
function getCurrentStack (): string | undefined {
|
||||
const target = { stack: undefined as string | undefined };
|
||||
if (enableStacks) {
|
||||
Error.captureStackTrace(target, getCurrentStack);
|
||||
}
|
||||
@@ -297,47 +320,47 @@ function getCurrentStack () {
|
||||
}
|
||||
|
||||
// Browser calls a callback in renderer.
|
||||
handleMessage('ELECTRON_RENDERER_CALLBACK', (id, args) => {
|
||||
handleMessage('ELECTRON_RENDERER_CALLBACK', (id: number, args: any) => {
|
||||
callbacksRegistry.apply(id, metaToValue(args));
|
||||
});
|
||||
|
||||
// A callback in browser is released.
|
||||
handleMessage('ELECTRON_RENDERER_RELEASE_CALLBACK', (id) => {
|
||||
handleMessage('ELECTRON_RENDERER_RELEASE_CALLBACK', (id: number) => {
|
||||
callbacksRegistry.remove(id);
|
||||
});
|
||||
|
||||
exports.require = (module) => {
|
||||
exports.require = (module: string) => {
|
||||
const command = 'ELECTRON_BROWSER_REQUIRE';
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, module, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
};
|
||||
|
||||
// Alias to remote.require('electron').xxx.
|
||||
exports.getBuiltin = (module) => {
|
||||
export function getBuiltin (module: string) {
|
||||
const command = 'ELECTRON_BROWSER_GET_BUILTIN';
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, module, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
};
|
||||
}
|
||||
|
||||
exports.getCurrentWindow = () => {
|
||||
export function getCurrentWindow (): BrowserWindow {
|
||||
const command = 'ELECTRON_BROWSER_CURRENT_WINDOW';
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
};
|
||||
}
|
||||
|
||||
// Get current WebContents object.
|
||||
exports.getCurrentWebContents = () => {
|
||||
export function getCurrentWebContents (): WebContents {
|
||||
const command = 'ELECTRON_BROWSER_CURRENT_WEB_CONTENTS';
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
};
|
||||
}
|
||||
|
||||
// Get a global object in browser.
|
||||
exports.getGlobal = (name) => {
|
||||
export function getGlobal<T = any> (name: string): T {
|
||||
const command = 'ELECTRON_BROWSER_GLOBAL';
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, name, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
};
|
||||
}
|
||||
|
||||
// Get the process object in browser.
|
||||
Object.defineProperty(exports, 'process', {
|
||||
@@ -345,22 +368,19 @@ Object.defineProperty(exports, 'process', {
|
||||
});
|
||||
|
||||
// Create a function that will return the specified value when called in browser.
|
||||
exports.createFunctionWithReturnValue = (returnValue) => {
|
||||
export function createFunctionWithReturnValue<T> (returnValue: T): () => T {
|
||||
const func = () => returnValue;
|
||||
v8Util.setHiddenValue(func, 'returnValue', true);
|
||||
return func;
|
||||
};
|
||||
}
|
||||
|
||||
const addBuiltinProperty = (name) => {
|
||||
const addBuiltinProperty = (name: string) => {
|
||||
Object.defineProperty(exports, name, {
|
||||
get: () => exports.getBuiltin(name)
|
||||
});
|
||||
};
|
||||
|
||||
const { commonModuleList } = require('@electron/internal/common/api/module-list');
|
||||
const { browserModuleNames } = require('@electron/internal/browser/api/module-names');
|
||||
|
||||
const browserModules = commonModuleList.concat(browserModuleNames.map(name => ({ name })));
|
||||
const browserModules = commonModuleList.concat(browserModuleNames.map(name => ({ name, loader: () => {} })));
|
||||
|
||||
// And add a helper receiver for each one.
|
||||
browserModules
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const binding = process.electronBinding('web_frame');
|
||||
const binding = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
class WebFrame extends EventEmitter {
|
||||
constructor (public context: Window) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { webFrame } from 'electron';
|
||||
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const IsolatedWorldIDs = {
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import * as path from 'path';
|
||||
|
||||
const Module = require('module');
|
||||
@@ -37,27 +36,24 @@ require('../common/reset-search-paths');
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
// The global variable will be used by ipc for event dispatching
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const ipcEmitter = new EventEmitter();
|
||||
const ipcInternalEmitter = new EventEmitter();
|
||||
v8Util.setHiddenValue(global, 'ipc', ipcEmitter);
|
||||
v8Util.setHiddenValue(global, 'ipc-internal', ipcInternalEmitter);
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||
const ipcRenderer = require('@electron/internal/renderer/api/ipc-renderer').default;
|
||||
|
||||
v8Util.setHiddenValue(global, 'ipcNative', {
|
||||
onMessage (internal: boolean, channel: string, ports: any[], args: any[], senderId: number) {
|
||||
const sender = internal ? ipcInternalEmitter : ipcEmitter;
|
||||
const sender = internal ? ipcRendererInternal : ipcRenderer;
|
||||
sender.emit(channel, { sender, senderId, ports }, ...args);
|
||||
}
|
||||
});
|
||||
|
||||
// Use electron module after everything is ready.
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||
const { webFrameInit } = require('@electron/internal/renderer/web-frame-init');
|
||||
webFrameInit();
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch, getSwitchValue } = process.electronBinding('command_line');
|
||||
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
const parseOption = function<T> (
|
||||
name: string, defaultValue: T, converter?: (value: string) => T
|
||||
@@ -84,9 +80,6 @@ const appPath = parseOption('app-path', null);
|
||||
const guestInstanceId = parseOption('guest-instance-id', null, value => parseInt(value));
|
||||
const openerId = parseOption('opener-id', null, value => parseInt(value));
|
||||
|
||||
// The arguments to be passed to isolated world.
|
||||
const isolatedWorldArgs = { ipcRendererInternal, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen, rendererProcessReuseEnabled };
|
||||
|
||||
// The webContents preload script is loaded after the session preload scripts.
|
||||
if (preloadScript) {
|
||||
preloadScripts.push(preloadScript);
|
||||
@@ -116,11 +109,6 @@ if (process.isMainFrame) {
|
||||
webViewInit(contextIsolation, webviewTag, guestInstanceId);
|
||||
}
|
||||
|
||||
// Pass the arguments to isolatedWorld.
|
||||
if (contextIsolation) {
|
||||
v8Util.setHiddenValue(global, 'isolated-world-args', isolatedWorldArgs);
|
||||
}
|
||||
|
||||
if (nodeIntegration) {
|
||||
// Export node bindings to global.
|
||||
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers') // eslint-disable-line
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
const { ipc } = process.electronBinding('ipc');
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { ipc } = process._linkedBinding('electron_renderer_ipc');
|
||||
|
||||
// Created by init.js.
|
||||
export const ipcRendererInternal = v8Util.getHiddenValue<Electron.IpcRendererInternal>(global, 'ipc-internal');
|
||||
const internal = true;
|
||||
|
||||
// TODO(MarshallOfSound): Remove if statement when isolated_bundle and content_script_bundle are gone
|
||||
if (!ipcRendererInternal.send) {
|
||||
ipcRendererInternal.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
const ipcRendererInternal = new EventEmitter() as any as Electron.IpcRendererInternal;
|
||||
ipcRendererInternal.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
ipcRendererInternal.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
|
||||
ipcRendererInternal.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
ipcRendererInternal.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.sendToAll = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, true, webContentsId, channel, args);
|
||||
};
|
||||
ipcRendererInternal.sendToAll = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, true, webContentsId, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[]) {
|
||||
const { error, result } = await ipc.invoke<T>(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[]) {
|
||||
const { error, result } = await ipc.invoke<T>(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export { ipcRendererInternal };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
export class CallbacksRegistry {
|
||||
private nextId: number = 0
|
||||
|
||||
@@ -8,7 +8,7 @@ import { syncMethods, asyncMethods, properties } from '@electron/internal/common
|
||||
import { deserialize } from '@electron/internal/common/type-utils';
|
||||
const { webFrame } = electron;
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
// ID generator.
|
||||
let nextId = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
function handleFocusBlur (guestInstanceId: number) {
|
||||
// Note that while Chromium content APIs have observer for focus/blur, they
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/* eslint no-eval: "off" */
|
||||
/* global binding, Buffer */
|
||||
const events = require('events');
|
||||
import * as events from 'events';
|
||||
|
||||
const { EventEmitter } = events;
|
||||
|
||||
process.electronBinding = require('@electron/internal/common/electron-binding-setup').electronBindingSetup(binding.get, 'renderer');
|
||||
process._linkedBinding = binding.get;
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
// Expose Buffer shim as a hidden value. This is used by C++ code to
|
||||
// deserialize Buffer instances sent from browser process.
|
||||
v8Util.setHiddenValue(global, 'Buffer', Buffer);
|
||||
// The `lib/renderer/api/ipc-renderer.ts` module looks for the ipc object in the
|
||||
// "ipc" hidden value
|
||||
v8Util.setHiddenValue(global, 'ipc', new EventEmitter());
|
||||
// The `lib/renderer/ipc-renderer-internal.ts` module looks for the ipc object in the
|
||||
// "ipc-internal" hidden value
|
||||
v8Util.setHiddenValue(global, 'ipc-internal', new EventEmitter());
|
||||
// The process object created by webpack is not an event emitter, fix it so
|
||||
// the API is more compatible with non-sandboxed renderers.
|
||||
for (const prop of Object.keys(EventEmitter.prototype)) {
|
||||
for (const prop of Object.keys(EventEmitter.prototype) as (keyof typeof process)[]) {
|
||||
if (Object.prototype.hasOwnProperty.call(process, prop)) {
|
||||
delete process[prop];
|
||||
}
|
||||
@@ -40,22 +33,24 @@ const {
|
||||
|
||||
process.isRemoteModuleEnabled = isRemoteModuleEnabled;
|
||||
|
||||
// The electron module depends on process.electronBinding
|
||||
const electron = require('electron');
|
||||
|
||||
const loadedModules = new Map([
|
||||
const loadedModules = new Map<string, any>([
|
||||
['electron', electron],
|
||||
['electron/common', electron],
|
||||
['electron/renderer', electron],
|
||||
['events', events],
|
||||
['timers', require('timers')],
|
||||
['url', require('url')]
|
||||
['events', events]
|
||||
]);
|
||||
|
||||
const loadableModules = new Map<string, Function>([
|
||||
['timers', () => require('timers')],
|
||||
['url', () => require('url')]
|
||||
]);
|
||||
|
||||
// ElectronApiServiceImpl will look for the "ipcNative" hidden object when
|
||||
// invoking the 'onMessage' callback.
|
||||
v8Util.setHiddenValue(global, 'ipcNative', {
|
||||
onMessage (internal, channel, ports, args, senderId) {
|
||||
onMessage (internal: boolean, channel: string, ports: MessagePort[], args: any[], senderId: number) {
|
||||
const sender = internal ? ipcRendererInternal : electron.ipcRenderer;
|
||||
sender.emit(channel, { sender, senderId, ports }, ...args);
|
||||
}
|
||||
@@ -64,25 +59,24 @@ v8Util.setHiddenValue(global, 'ipcNative', {
|
||||
// ElectronSandboxedRendererClient will look for the "lifecycle" hidden object when
|
||||
v8Util.setHiddenValue(global, 'lifecycle', {
|
||||
onLoaded () {
|
||||
process.emit('loaded');
|
||||
(process as events.EventEmitter).emit('loaded');
|
||||
},
|
||||
onExit () {
|
||||
process.emit('exit');
|
||||
(process as events.EventEmitter).emit('exit');
|
||||
},
|
||||
onDocumentStart () {
|
||||
process.emit('document-start');
|
||||
(process as events.EventEmitter).emit('document-start');
|
||||
},
|
||||
onDocumentEnd () {
|
||||
process.emit('document-end');
|
||||
(process as events.EventEmitter).emit('document-end');
|
||||
}
|
||||
});
|
||||
|
||||
const { webFrameInit } = require('@electron/internal/renderer/web-frame-init');
|
||||
webFrameInit();
|
||||
|
||||
// Pass different process object to the preload script(which should not have
|
||||
// access to things like `process.electronBinding`).
|
||||
const preloadProcess = new EventEmitter();
|
||||
// Pass different process object to the preload script.
|
||||
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
|
||||
|
||||
Object.assign(preloadProcess, binding.process);
|
||||
Object.assign(preloadProcess, processProps);
|
||||
@@ -99,26 +93,31 @@ Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||
}
|
||||
});
|
||||
|
||||
process.on('loaded', () => preloadProcess.emit('loaded'));
|
||||
process.on('exit', () => preloadProcess.emit('exit'));
|
||||
process.on('document-start', () => preloadProcess.emit('document-start'));
|
||||
process.on('document-end', () => preloadProcess.emit('document-end'));
|
||||
process.on('loaded', () => (preloadProcess as events.EventEmitter).emit('loaded'));
|
||||
process.on('exit', () => (preloadProcess as events.EventEmitter).emit('exit'));
|
||||
(process as events.EventEmitter).on('document-start', () => (preloadProcess as events.EventEmitter).emit('document-start'));
|
||||
(process as events.EventEmitter).on('document-end', () => (preloadProcess as events.EventEmitter).emit('document-end'));
|
||||
|
||||
// This is the `require` function that will be visible to the preload script
|
||||
function preloadRequire (module) {
|
||||
function preloadRequire (module: string) {
|
||||
if (loadedModules.has(module)) {
|
||||
return loadedModules.get(module);
|
||||
}
|
||||
if (loadableModules.has(module)) {
|
||||
const loadedModule = loadableModules.get(module)!();
|
||||
loadedModules.set(module, loadedModule);
|
||||
return loadedModule;
|
||||
}
|
||||
throw new Error(`module not found: ${module}`);
|
||||
}
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch } = process.electronBinding('command_line');
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Similar to nodes --expose-internals flag, this exposes electronBinding so
|
||||
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
||||
// that tests can call it to get access to some test only bindings
|
||||
if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
preloadProcess.electronBinding = process.electronBinding;
|
||||
preloadProcess._linkedBinding = process._linkedBinding;
|
||||
}
|
||||
|
||||
const contextIsolation = hasSwitch('context-isolation');
|
||||
@@ -126,9 +125,6 @@ const isHiddenPage = hasSwitch('hidden-page');
|
||||
const rendererProcessReuseEnabled = hasSwitch('disable-electron-site-instance-overrides');
|
||||
const usesNativeWindowOpen = true;
|
||||
|
||||
// The arguments to be passed to isolated world.
|
||||
const isolatedWorldArgs = { ipcRendererInternal, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen, rendererProcessReuseEnabled };
|
||||
|
||||
switch (window.location.protocol) {
|
||||
case 'devtools:': {
|
||||
// Override some inspector APIs.
|
||||
@@ -154,11 +150,6 @@ if (process.isMainFrame) {
|
||||
webViewInit(contextIsolation, isWebViewTagEnabled, guestInstanceId);
|
||||
}
|
||||
|
||||
// Pass the arguments to isolatedWorld.
|
||||
if (contextIsolation) {
|
||||
v8Util.setHiddenValue(global, 'isolated-world-args', isolatedWorldArgs);
|
||||
}
|
||||
|
||||
// Wrap the script into a function executed in global scope. It won't have
|
||||
// access to the current scope, so we'll expose a few objects as arguments:
|
||||
//
|
||||
@@ -166,7 +157,7 @@ if (contextIsolation) {
|
||||
// - `process`: The `preloadProcess` object
|
||||
// - `Buffer`: Shim of `Buffer` implementation
|
||||
// - `global`: The window object, which is aliased to `global` by webpack.
|
||||
function runPreloadScript (preloadSrc) {
|
||||
function runPreloadScript (preloadSrc: string) {
|
||||
const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate, clearImmediate, exports) {
|
||||
${preloadSrc}
|
||||
})`;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "10.0.0-beta.7",
|
||||
"version": "11.0.0-nightly.20200626",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -134,7 +134,8 @@
|
||||
"git add filenames.auto.gni"
|
||||
],
|
||||
"{*.patch,.patches}": [
|
||||
"node script/lint.js --patches --only --"
|
||||
"node script/lint.js --patches --only --",
|
||||
"node script/check-patch-diff.js"
|
||||
],
|
||||
"DEPS": [
|
||||
"node script/gen-hunspell-filenames.js"
|
||||
|
||||
@@ -87,16 +87,16 @@ feat_add_onclose_to_messageport.patch
|
||||
fix_account_for_print_preview_disabled_when_printing_to_pdf.patch
|
||||
web_contents.patch
|
||||
ui_gtk_public_header.patch
|
||||
refactor_expose_cursor_changes_to_the_webcontentsobserver.patch
|
||||
crash_allow_setting_more_options.patch
|
||||
breakpad_treat_node_processes_as_browser_processes.patch
|
||||
upload_list_add_loadsync_method.patch
|
||||
breakpad_allow_getting_string_values_for_crash_keys.patch
|
||||
crash_allow_disabling_compression_on_linux.patch
|
||||
fix_swap_global_proxies_before_initializing_the_windows_proxies.patch
|
||||
allow_setting_secondary_label_via_simplemenumodel.patch
|
||||
refactor_expose_cursor_changes_to_the_webcontentsobserver.patch
|
||||
disable_unnecessary_ischromefirstrun_check.patch
|
||||
disable_dcheck_that_fails_with_software_compositing.patch
|
||||
fix_swap_global_proxies_before_initializing_the_windows_proxies.patch
|
||||
feat_add_streaming-protocol_registry_to_multibuffer_data_source.patch
|
||||
fix_handling_non_client_pointer_events_from_pen_on_windows_10.patch
|
||||
remove_menu_window_task_item.patch
|
||||
use_electron_resources_in_icon_reader_service.patch
|
||||
|
||||
@@ -23,10 +23,10 @@ index 4e195f960d7b9bf50f6784ce380a84a10867914f..dbf85ffe8504bdbab1c4c29f085e5307
|
||||
int32_t world_id) {}
|
||||
virtual void DidClearWindowObject() {}
|
||||
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
||||
index 5586d724ef30e8183787c1cbba21fe9741d587c5..a5a95523e16fd35018f9646ae4a4d51e5ca626c0 100644
|
||||
index 0cb96dd693459a9747aa1e2c46c5257df510211a..010ed22b5da75c445b777bd0db503b268c7a767f 100644
|
||||
--- a/content/renderer/render_frame_impl.cc
|
||||
+++ b/content/renderer/render_frame_impl.cc
|
||||
@@ -4735,6 +4735,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
@@ -4745,6 +4745,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
observer.DidCreateScriptContext(context, world_id);
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ index 5586d724ef30e8183787c1cbba21fe9741d587c5..a5a95523e16fd35018f9646ae4a4d51e
|
||||
int world_id) {
|
||||
for (auto& observer : observers_)
|
||||
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
|
||||
index 745610204f08a39912b92f8b8ba9028465c9c57f..ddc571fbec08a38ada5c84acdadd618f1b349bed 100644
|
||||
index b1465918040a8eaafd5780aaf9fb6f870c9ea943..2fb7927168ac62c52d2e65942608dd9b73ac3133 100644
|
||||
--- a/content/renderer/render_frame_impl.h
|
||||
+++ b/content/renderer/render_frame_impl.h
|
||||
@@ -721,6 +721,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
@@ -722,6 +722,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
bool ShouldTrackUseCounter(const blink::WebURL& url) override;
|
||||
void DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
int world_id) override;
|
||||
@@ -79,10 +79,10 @@ index 5ac9a7ed3d0f91764452579992471c83104de64f..15ac214bc9177f2fc228cf93c459a7b3
|
||||
if (World().IsMainWorld()) {
|
||||
GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
|
||||
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
|
||||
index f9d867fb84e544a2705d22c9fef1f04e639c052b..9b26988f4c7dd96269fd44c57dc9632f47ec409f 100644
|
||||
index ba02a164a799b2b9e92bbeeb2bff2a4a2fd7d662..42ed050d572b13f1302bfb9eb5b59b15ba5a6904 100644
|
||||
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
|
||||
@@ -363,6 +363,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
|
||||
@@ -349,6 +349,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
|
||||
web_frame_->Client()->DidCreateScriptContext(context, world_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ WebContents, and cancels the authentication if there's no WebContents
|
||||
available, which there isn't in the case of the 'net' module.
|
||||
|
||||
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
|
||||
index 6d15b6b5ff7b36b85f6b8200b76a32b285f0e675..c21234572976a6de7db5b0f2f7f44ec770832178 100644
|
||||
index 842a4d27ee7a27a4e5c6d60033cee6526aac1bee..07682bd496e0872498f1fd404466408ebf21583c 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -214,6 +214,25 @@ struct CTPolicy {
|
||||
|
||||
@@ -14,7 +14,7 @@ when there is code doing that.
|
||||
This patch reverts the change to fix the crash in Electron.
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
index 657034319731c660e5c513be7d92bab280c9dee0..1c51cab672063a2b9ac8a63d6c42a7c4451e5879 100644
|
||||
index ba48c66cc8a982dc66750673e9ea116f94710688..aca8f1173e4abfd4cb536543c1f98cf466776899 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
@@ -538,10 +538,6 @@ void LocalFrame::DetachImpl(FrameDetachType type) {
|
||||
|
||||
@@ -7,10 +7,10 @@ This exposes a method for obtaining a reference to an isolated world, which is
|
||||
otherwise not available in the Blink API.
|
||||
|
||||
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
|
||||
index be5efdc896fd9318b50c9e5ad02ec404ba7be23d..79234d0def2d4e97e05a03ecb1dbd7b077bc44b2 100644
|
||||
index dbc00b0e8e34ab0ba922cb4ad42a78bb188faccc..ce078ef2a5dbe360e1aff4926df4b5ac434c17a3 100644
|
||||
--- a/third_party/blink/public/web/web_local_frame.h
|
||||
+++ b/third_party/blink/public/web/web_local_frame.h
|
||||
@@ -354,6 +354,8 @@ class WebLocalFrame : public WebFrame {
|
||||
@@ -352,6 +352,8 @@ class WebLocalFrame : public WebFrame {
|
||||
// Returns the world ID associated with |script_context|.
|
||||
virtual int32_t GetScriptContextWorldId(
|
||||
v8::Local<v8::Context> script_context) const = 0;
|
||||
@@ -20,7 +20,7 @@ index be5efdc896fd9318b50c9e5ad02ec404ba7be23d..79234d0def2d4e97e05a03ecb1dbd7b0
|
||||
// Executes script in the context of the current page and returns the value
|
||||
// that the script evaluated to with callback. Script execution can be
|
||||
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
index 857f31b2d7af86138b8b5cfd8b7131f2524bc94e..4891f5aa60469b224c933adaa334eef8ac8a19ec 100644
|
||||
index ad206e51535ebf3e44de6dcfa98c2ba28e67e825..08bc2ce2f6cc938c22172ee03eeb807d3a4a2fd9 100644
|
||||
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
@@ -967,6 +967,13 @@ v8::Local<v8::Object> WebLocalFrameImpl::GlobalProxy() const {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user