mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
36 Commits
v13.0.0-ni
...
v12.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b47fd7cbf | ||
|
|
9b1913b613 | ||
|
|
36c695ce2a | ||
|
|
afcdf661a0 | ||
|
|
3d01b83daa | ||
|
|
e77d9ff3b9 | ||
|
|
fb35356b47 | ||
|
|
37d21bb80e | ||
|
|
e84539f2e0 | ||
|
|
d2591ed4f8 | ||
|
|
6b54fe37de | ||
|
|
561fe63813 | ||
|
|
9543f8b30a | ||
|
|
cec2c73733 | ||
|
|
2e9305d964 | ||
|
|
0491cc6906 | ||
|
|
badcdd6566 | ||
|
|
a0d0bd60a5 | ||
|
|
c0f0a02419 | ||
|
|
8046f0560a | ||
|
|
2a8961b52f | ||
|
|
36163af228 | ||
|
|
29f42e943e | ||
|
|
4597cb6499 | ||
|
|
4ba78b81c1 | ||
|
|
80e0473649 | ||
|
|
db0d4c8224 | ||
|
|
4fbb58020c | ||
|
|
c9801ab5a5 | ||
|
|
46441c1bd7 | ||
|
|
1cac3354e7 | ||
|
|
57c69ab3ac | ||
|
|
39b9c40a05 | ||
|
|
66a22a28a5 | ||
|
|
17a8b7724b | ||
|
|
c512995426 |
@@ -295,10 +295,10 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
run:
|
||||
name: Setup Goma
|
||||
command: |
|
||||
if [ "`uname`" == "Linux" ]; then
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
else
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=25' >> $BASH_ENV
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
echo 'ulimit -n 10000' >> $BASH_ENV
|
||||
echo 'sudo launchctl limit maxfiles 65536 200000' >> $BASH_ENV
|
||||
fi
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ]; then
|
||||
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
|
||||
@@ -307,7 +307,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
cd build-tools
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
node -e "require('./src/utils/goma.js').ensure()"
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
As a member project of the OpenJS Foundation, Electron uses [Contributor Covenant v2.0](https://contributor-covenant.org/version/2/0/code_of_conduct) as their code of conduct. The full text is included [below](#contributor-covenant-code-of-conduct) in English, and translations are available from the Contributor Covenant organisation:
|
||||
|
||||
* [contributor-covenant.org/translations](https://www.contributor-covenant.org/translations)
|
||||
* [github.com/ContributorCovenant](https://github.com/ContributorCovenant/contributor_covenant/tree/release/content/version/2/0)
|
||||
- [contributor-covenant.org/translations](https://www.contributor-covenant.org/translations)
|
||||
- [github.com/ContributorCovenant](https://github.com/ContributorCovenant/contributor_covenant/tree/release/content/version/2/0)
|
||||
|
||||
## Contributor Covenant Code of Conduct
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ _If an issue has been closed and you still feel it's relevant, feel free to ping
|
||||
### Languages
|
||||
|
||||
We accept issues in *any* language.
|
||||
When an issue is posted in a language besides English, it is acceptable and encouraged to post an English-translated copy as a reply.
|
||||
When an issue is posted in a language besides English, it is acceptable and encouraged to post an English-translated copy as a reply.
|
||||
Anyone may post the translated reply.
|
||||
In most cases, a quick pass through translation software is sufficient.
|
||||
Having the original text _as well as_ the translation can help mitigate translation errors.
|
||||
@@ -66,5 +66,5 @@ See [Coding Style](https://electronjs.org/docs/development/coding-style) for inf
|
||||
|
||||
## Further Reading
|
||||
|
||||
For more in-depth guides on developing Electron, see
|
||||
For more in-depth guides on developing Electron, see
|
||||
[/docs/development](/docs/development/README.md)
|
||||
|
||||
2
DEPS
2
DEPS
@@ -20,7 +20,7 @@ vars = {
|
||||
'nan_version':
|
||||
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
|
||||
'squirrel.mac_version':
|
||||
'cdc0729c8bf8576bfef18629186e1e9ecf1b0d9f',
|
||||
'a3a5b3f03b824441c014893b18f99a103b2603e9',
|
||||
|
||||
'pyyaml_version': '3.12',
|
||||
'requests_version': 'e4d59bedfd3c7f4f254f4f5d036587bcd8152458',
|
||||
|
||||
@@ -1 +1 @@
|
||||
13.0.0-nightly.20201126
|
||||
12.0.0-beta.10
|
||||
@@ -1,5 +1,6 @@
|
||||
[](https://electronjs.org)
|
||||
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/master)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/master)
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
|
||||
@@ -13,5 +13,4 @@ Report security bugs in third-party modules to the person or team maintaining th
|
||||
For context on Electron's security notification process, please see the [Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md#notifications) section of the Security WG's [Membership and Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md) Governance document.
|
||||
|
||||
## Learning More About Security
|
||||
|
||||
To learn more about securing an Electron application, please see the [security tutorial](docs/tutorial/security.md).
|
||||
|
||||
@@ -141,7 +141,8 @@ build_script:
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- node -e "require('./src/utils/goma.js').downloadAndPrepare()"
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
|
||||
node_module_version = 89
|
||||
node_module_version = 87
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
|
||||
@@ -65,12 +65,12 @@ Forces the maximum disk space to be used by the disk cache, in bytes.
|
||||
|
||||
Enables caller stack logging for the following APIs (filtering events):
|
||||
|
||||
* `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
|
||||
* `remote.require()` / `remote-require`
|
||||
* `remote.getGlobal()` / `remote-get-builtin`
|
||||
* `remote.getBuiltin()` / `remote-get-global`
|
||||
* `remote.getCurrentWindow()` / `remote-get-current-window`
|
||||
* `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
|
||||
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
|
||||
- `remote.require()` / `remote-require`
|
||||
- `remote.getGlobal()` / `remote-get-builtin`
|
||||
- `remote.getBuiltin()` / `remote-get-global`
|
||||
- `remote.getCurrentWindow()` / `remote-get-current-window`
|
||||
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
|
||||
|
||||
### --enable-logging
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ const { app, contentTracing } = require('electron')
|
||||
app.whenReady().then(() => {
|
||||
(async () => {
|
||||
await contentTracing.startRecording({
|
||||
include_categories: ['*']
|
||||
included_categories: ['*']
|
||||
})
|
||||
console.log('Tracing started')
|
||||
await new Promise(resolve => setTimeout(resolve, 5000))
|
||||
|
||||
@@ -128,7 +128,7 @@ must be at most 39 bytes long, and values must be no longer than 127 bytes.
|
||||
Keys with names longer than the maximum will be silently ignored. Key values
|
||||
longer than the maximum length will be truncated.
|
||||
|
||||
**Note:** Calling this method from the renderer process is deprecated.
|
||||
**Note:** This method is only available in the main process.
|
||||
|
||||
### `crashReporter.getLastCrashReport()`
|
||||
|
||||
@@ -137,7 +137,7 @@ last crash report. Only crash reports that have been uploaded will be returned;
|
||||
even if a crash report is present on disk it will not be returned until it is
|
||||
uploaded. In the case that there are no uploaded reports, `null` is returned.
|
||||
|
||||
**Note:** Calling this method from the renderer process is deprecated.
|
||||
**Note:** This method is only available in the main process.
|
||||
|
||||
### `crashReporter.getUploadedReports()`
|
||||
|
||||
@@ -146,14 +146,14 @@ Returns [`CrashReport[]`](structures/crash-report.md):
|
||||
Returns all uploaded crash reports. Each report contains the date and uploaded
|
||||
ID.
|
||||
|
||||
**Note:** Calling this method from the renderer process is deprecated.
|
||||
**Note:** This method is only available in the main process.
|
||||
|
||||
### `crashReporter.getUploadToServer()`
|
||||
|
||||
Returns `Boolean` - Whether reports should be submitted to the server. Set through
|
||||
the `start` method or `setUploadToServer`.
|
||||
|
||||
**Note:** Calling this method from the renderer process is deprecated.
|
||||
**Note:** This method is only available in the main process.
|
||||
|
||||
### `crashReporter.setUploadToServer(uploadToServer)`
|
||||
|
||||
@@ -162,13 +162,7 @@ the `start` method or `setUploadToServer`.
|
||||
This would normally be controlled by user preferences. This has no effect if
|
||||
called before `start` is called.
|
||||
|
||||
**Note:** Calling this method from the renderer process is deprecated.
|
||||
|
||||
### `crashReporter.getCrashesDirectory()` _Deprecated_
|
||||
|
||||
Returns `String` - The directory where crashes are temporarily stored before being uploaded.
|
||||
|
||||
**Note:** This method is deprecated, use `app.getPath('crashDumps')` instead.
|
||||
**Note:** This method is only available in the main process.
|
||||
|
||||
### `crashReporter.addExtraParameter(key, value)`
|
||||
|
||||
|
||||
@@ -12,28 +12,28 @@ It adds the following events, properties, and methods:
|
||||
|
||||
In sandboxed renderers the `process` object contains only a subset of the APIs:
|
||||
|
||||
* `crash()`
|
||||
* `hang()`
|
||||
* `getCreationTime()`
|
||||
* `getHeapStatistics()`
|
||||
* `getBlinkMemoryInfo()`
|
||||
* `getProcessMemoryInfo()`
|
||||
* `getSystemMemoryInfo()`
|
||||
* `getSystemVersion()`
|
||||
* `getCPUUsage()`
|
||||
* `getIOCounters()`
|
||||
* `argv`
|
||||
* `execPath`
|
||||
* `env`
|
||||
* `pid`
|
||||
* `arch`
|
||||
* `platform`
|
||||
* `sandboxed`
|
||||
* `type`
|
||||
* `version`
|
||||
* `versions`
|
||||
* `mas`
|
||||
* `windowsStore`
|
||||
- `crash()`
|
||||
- `hang()`
|
||||
- `getCreationTime()`
|
||||
- `getHeapStatistics()`
|
||||
- `getBlinkMemoryInfo()`
|
||||
- `getProcessMemoryInfo()`
|
||||
- `getSystemMemoryInfo()`
|
||||
- `getSystemVersion()`
|
||||
- `getCPUUsage()`
|
||||
- `getIOCounters()`
|
||||
- `argv`
|
||||
- `execPath`
|
||||
- `env`
|
||||
- `pid`
|
||||
- `arch`
|
||||
- `platform`
|
||||
- `sandboxed`
|
||||
- `type`
|
||||
- `version`
|
||||
- `versions`
|
||||
- `mas`
|
||||
- `windowsStore`
|
||||
|
||||
## Events
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ you can use [webContents.executeJavaScript](web-contents.md#contentsexecutejavas
|
||||
|
||||
**Note:** The remote module can be disabled for security reasons in the following contexts:
|
||||
|
||||
* [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
|
||||
* [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
|
||||
- [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
|
||||
- [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
|
||||
|
||||
## Remote Objects
|
||||
|
||||
|
||||
@@ -101,8 +101,8 @@ Returns:
|
||||
Emitted after an extension is loaded. This occurs whenever an extension is
|
||||
added to the "enabled" set of extensions. This includes:
|
||||
|
||||
* Extensions being loaded from `Session.loadExtension`.
|
||||
* Extensions being reloaded:
|
||||
- Extensions being loaded from `Session.loadExtension`.
|
||||
- Extensions being reloaded:
|
||||
* from a crash.
|
||||
* if the extension requested it ([`chrome.runtime.reload()`](https://developer.chrome.com/extensions/runtime#method-reload)).
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# IpcMainEvent Object extends `Event`
|
||||
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `returnValue` any - Set this to the value to be returned in a synchronous message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# IpcMainInvokeEvent Object extends `Event`
|
||||
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
|
||||
@@ -433,7 +433,7 @@ It will always return `granted` for `screen` and for all media types on older ve
|
||||
|
||||
Returns `Promise<Boolean>` - A promise that resolves with `true` if consent was granted and `false` if it was denied. If an invalid `mediaType` is passed, the promise will be rejected. If an access request was denied and later is changed through the System Preferences pane, a restart of the app will be required for the new permissions to take effect. If access has already been requested and denied, it _must_ be changed through the preference pane; an alert will not pop up and the promise will resolve with the existing access status.
|
||||
|
||||
**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](../tutorial/application-distribution.md#macos) for more information about how to set these in the context of Electron.
|
||||
**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](https://electronjs.org/docs/tutorial/application-distribution#macos) for more information about how to set these in the context of Electron.
|
||||
|
||||
This user consent was not required until macOS 10.14 Mojave, so this method will always return `true` if your system is running 10.13 High Sierra or lower.
|
||||
|
||||
|
||||
@@ -195,30 +195,29 @@ myBrowserWindow.webContents.on('new-window', (event, url, frameName, disposition
|
||||
#### Event: 'did-create-window'
|
||||
|
||||
Returns:
|
||||
|
||||
* `window` BrowserWindow
|
||||
* `details` Object
|
||||
* `url` String - URL for the created window.
|
||||
* `frameName` String - Name given to the created window in the
|
||||
`window.open()` call.
|
||||
* `options` BrowserWindowConstructorOptions - The options used to create the
|
||||
BrowserWindow. They are merged in increasing precedence: options inherited
|
||||
from the parent, parsed options from the `features` string from
|
||||
`window.open()`, and options given by
|
||||
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
|
||||
Unrecognized options are not filtered out.
|
||||
* `additionalFeatures` String[] - The non-standard features (features not
|
||||
handled Chromium or Electron) _Deprecated_
|
||||
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
|
||||
passed to the new window. May or may not result in the `Referer` header
|
||||
being sent, depending on the referrer policy.
|
||||
* `postBody` [PostBody](structures/post-body.md) (optional) - The post data
|
||||
that will be sent to the new window, along with the appropriate headers
|
||||
that will be set. If no post data is to be sent, the value will be `null`.
|
||||
Only defined when the window is being created by a form that set
|
||||
`target=_blank`.
|
||||
* `disposition` String - Can be `default`, `foreground-tab`,
|
||||
`background-tab`, `new-window`, `save-to-disk` and `other`.
|
||||
* `url` String - URL for the created window.
|
||||
* `frameName` String - Name given to the created window in the
|
||||
`window.open()` call.
|
||||
* `options` BrowserWindowConstructorOptions - The options used to create the
|
||||
BrowserWindow. They are merged in increasing precedence: options inherited
|
||||
from the parent, parsed options from the `features` string from
|
||||
`window.open()`, and options given by
|
||||
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
|
||||
Unrecognized options are not filtered out.
|
||||
* `additionalFeatures` String[] - The non-standard features (features not
|
||||
handled Chromium or Electron) _Deprecated_
|
||||
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
|
||||
passed to the new window. May or may not result in the `Referer` header
|
||||
being sent, depending on the referrer policy.
|
||||
* `postBody` [PostBody](structures/post-body.md) (optional) - The post data
|
||||
that will be sent to the new window, along with the appropriate headers
|
||||
that will be set. If no post data is to be sent, the value will be `null`.
|
||||
Only defined when the window is being created by a form that set
|
||||
`target=_blank`.
|
||||
* `disposition` String - Can be `default`, `foreground-tab`,
|
||||
`background-tab`, `new-window`, `save-to-disk` and `other`.
|
||||
|
||||
Emitted _after_ successful creation of a window via `window.open` in the renderer.
|
||||
Not emitted if the creation of the window is canceled from
|
||||
@@ -1465,7 +1464,7 @@ By default, an empty `options` will be regarded as:
|
||||
}
|
||||
```
|
||||
|
||||
Use `page-break-before: always;` CSS style to force to print to a new page.
|
||||
Use `page-break-before: always; ` CSS style to force to print to a new page.
|
||||
|
||||
An example of `webContents.printToPDF`:
|
||||
|
||||
@@ -1696,7 +1695,7 @@ app.whenReady().then(() => {
|
||||
|
||||
#### `contents.sendToFrame(frameId, channel, ...args)`
|
||||
|
||||
* `frameId` Integer
|
||||
* `frameId` Integer | [number, number]
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
There are several ways to control how windows are created from trusted or
|
||||
untrusted content within a renderer. Windows can be created from the renderer in two ways:
|
||||
|
||||
* clicking on links or submitting forms adorned with `target=_blank`
|
||||
* JavaScript calling `window.open()`
|
||||
- clicking on links or submitting forms adorned with `target=_blank`
|
||||
- JavaScript calling `window.open()`
|
||||
|
||||
In non-sandboxed renderers, or when `nativeWindowOpen` is false (the default), this results in the creation of a
|
||||
[`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper around
|
||||
|
||||
@@ -6,11 +6,11 @@ Breaking changes will be documented here, and deprecation warnings added to JS c
|
||||
|
||||
This document uses the following convention to categorize breaking changes:
|
||||
|
||||
* **API Changed:** An API was changed in such a way that code that has not been updated is guaranteed to throw an exception.
|
||||
* **Behavior Changed:** The behavior of Electron has changed, but not in such a way that an exception will necessarily be thrown.
|
||||
* **Default Changed:** Code depending on the old default may break, not necessarily throwing an exception. The old behavior can be restored by explicitly specifying the value.
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
- **API Changed:** An API was changed in such a way that code that has not been updated is guaranteed to throw an exception.
|
||||
- **Behavior Changed:** The behavior of Electron has changed, but not in such a way that an exception will necessarily be thrown.
|
||||
- **Default Changed:** Code depending on the old default may break, not necessarily throwing an exception. The old behavior can be restored by explicitly specifying the value.
|
||||
- **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
- **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (13.0)
|
||||
|
||||
@@ -43,17 +43,29 @@ We [recommend having contextIsolation enabled](https://github.com/electron/elect
|
||||
|
||||
For more details see: https://github.com/electron/electron/issues/23506
|
||||
|
||||
### Removed: `crashReporter.getCrashesDirectory()`
|
||||
|
||||
The `crashReporter.getCrashesDirectory` method has been removed. Usage
|
||||
should be replaced by `app.getPath('crashDumps')`.
|
||||
|
||||
```js
|
||||
// Removed in Electron 12
|
||||
crashReporter.getCrashesDirectory()
|
||||
// Replace with
|
||||
app.getPath('crashDumps')
|
||||
```
|
||||
|
||||
### Removed: `crashReporter` methods in the renderer process
|
||||
|
||||
The following `crashReporter` methods are no longer available in the renderer
|
||||
process:
|
||||
|
||||
* `crashReporter.start`
|
||||
* `crashReporter.getLastCrashReport`
|
||||
* `crashReporter.getUploadedReports`
|
||||
* `crashReporter.getUploadToServer`
|
||||
* `crashReporter.setUploadToServer`
|
||||
* `crashReporter.getCrashesDirectory`
|
||||
- `crashReporter.start`
|
||||
- `crashReporter.getLastCrashReport`
|
||||
- `crashReporter.getUploadedReports`
|
||||
- `crashReporter.getUploadToServer`
|
||||
- `crashReporter.setUploadToServer`
|
||||
- `crashReporter.getCrashesDirectory`
|
||||
|
||||
They should be called only from the main process.
|
||||
|
||||
@@ -104,7 +116,6 @@ shell.trashItem(path).then(/* ... */)
|
||||
## Planned Breaking API Changes (11.0)
|
||||
|
||||
### Removed: `BrowserView.{destroy, fromId, fromWebContents, getAllViews}` and `id` property of `BrowserView`
|
||||
|
||||
The experimental APIs `BrowserView.{destroy, fromId, fromWebContents, getAllViews}`
|
||||
have now been removed. Additionally, the `id` property of `BrowserView`
|
||||
has also been removed.
|
||||
@@ -144,12 +155,12 @@ app.getPath('crashDumps')
|
||||
Calling the following `crashReporter` methods from the renderer process is
|
||||
deprecated:
|
||||
|
||||
* `crashReporter.start`
|
||||
* `crashReporter.getLastCrashReport`
|
||||
* `crashReporter.getUploadedReports`
|
||||
* `crashReporter.getUploadToServer`
|
||||
* `crashReporter.setUploadToServer`
|
||||
* `crashReporter.getCrashesDirectory`
|
||||
- `crashReporter.start`
|
||||
- `crashReporter.getLastCrashReport`
|
||||
- `crashReporter.getUploadedReports`
|
||||
- `crashReporter.getUploadToServer`
|
||||
- `crashReporter.setUploadToServer`
|
||||
- `crashReporter.getCrashesDirectory`
|
||||
|
||||
The only non-deprecated methods remaining in the `crashReporter` module in the
|
||||
renderer are `addExtraParameter`, `removeExtraParameter` and `getParameters`.
|
||||
@@ -191,7 +202,6 @@ We [recommend moving away from the remote
|
||||
module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
|
||||
|
||||
### `protocol.unregisterProtocol`
|
||||
|
||||
### `protocol.uninterceptProtocol`
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
@@ -204,23 +214,14 @@ protocol.unregisterProtocol(scheme)
|
||||
```
|
||||
|
||||
### `protocol.registerFileProtocol`
|
||||
|
||||
### `protocol.registerBufferProtocol`
|
||||
|
||||
### `protocol.registerStringProtocol`
|
||||
|
||||
### `protocol.registerHttpProtocol`
|
||||
|
||||
### `protocol.registerStreamProtocol`
|
||||
|
||||
### `protocol.interceptFileProtocol`
|
||||
|
||||
### `protocol.interceptStringProtocol`
|
||||
|
||||
### `protocol.interceptBufferProtocol`
|
||||
|
||||
### `protocol.interceptHttpProtocol`
|
||||
|
||||
### `protocol.interceptStreamProtocol`
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
@@ -262,6 +263,45 @@ you should plan to update your native modules to be context aware.
|
||||
|
||||
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||
|
||||
### Deprecated: `BrowserWindow` extension APIs
|
||||
|
||||
The following extension APIs have been deprecated:
|
||||
* `BrowserWindow.addExtension(path)`
|
||||
* `BrowserWindow.addDevToolsExtension(path)`
|
||||
* `BrowserWindow.removeExtension(name)`
|
||||
* `BrowserWindow.removeDevToolsExtension(name)`
|
||||
* `BrowserWindow.getExtensions()`
|
||||
* `BrowserWindow.getDevToolsExtensions()`
|
||||
|
||||
Use the session APIs instead:
|
||||
* `ses.loadExtension(path)`
|
||||
* `ses.removeExtension(extension_id)`
|
||||
* `ses.getAllExtensions()`
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.addExtension(path)
|
||||
BrowserWindow.addDevToolsExtension(path)
|
||||
// Replace with
|
||||
session.defaultSession.loadExtension(path)
|
||||
```
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.removeExtension(name)
|
||||
BrowserWindow.removeDevToolsExtension(name)
|
||||
// Replace with
|
||||
session.defaultSession.removeExtension(extension_id)
|
||||
```
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.getExtensions()
|
||||
BrowserWindow.getDevToolsExtensions()
|
||||
// Replace with
|
||||
session.defaultSession.getAllExtensions()
|
||||
```
|
||||
|
||||
### Removed: `<webview>.getWebContents()`
|
||||
|
||||
This API, which was deprecated in Electron 8.0, is now removed.
|
||||
@@ -314,7 +354,7 @@ Clone Algorithm][SCA], the same algorithm used to serialize messages for
|
||||
`postMessage`. This brings about a 2x performance improvement for large
|
||||
messages, but also brings some breaking changes in behavior.
|
||||
|
||||
* Sending Functions, Promises, WeakMaps, WeakSets, or objects containing any
|
||||
- Sending Functions, Promises, WeakMaps, WeakSets, or objects containing any
|
||||
such values, over IPC will now throw an exception, instead of silently
|
||||
converting the functions to `undefined`.
|
||||
|
||||
@@ -328,21 +368,21 @@ ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
|
||||
// => throws Error("() => {} could not be cloned.")
|
||||
```
|
||||
|
||||
* `NaN`, `Infinity` and `-Infinity` will now be correctly serialized, instead
|
||||
- `NaN`, `Infinity` and `-Infinity` will now be correctly serialized, instead
|
||||
of being converted to `null`.
|
||||
* Objects containing cyclic references will now be correctly serialized,
|
||||
- Objects containing cyclic references will now be correctly serialized,
|
||||
instead of being converted to `null`.
|
||||
* `Set`, `Map`, `Error` and `RegExp` values will be correctly serialized,
|
||||
- `Set`, `Map`, `Error` and `RegExp` values will be correctly serialized,
|
||||
instead of being converted to `{}`.
|
||||
* `BigInt` values will be correctly serialized, instead of being converted to
|
||||
- `BigInt` values will be correctly serialized, instead of being converted to
|
||||
`null`.
|
||||
* Sparse arrays will be serialized as such, instead of being converted to dense
|
||||
- Sparse arrays will be serialized as such, instead of being converted to dense
|
||||
arrays with `null`s.
|
||||
* `Date` objects will be transferred as `Date` objects, instead of being
|
||||
- `Date` objects will be transferred as `Date` objects, instead of being
|
||||
converted to their ISO string representation.
|
||||
* Typed Arrays (such as `Uint8Array`, `Uint16Array`, `Uint32Array` and so on)
|
||||
- Typed Arrays (such as `Uint8Array`, `Uint16Array`, `Uint32Array` and so on)
|
||||
will be transferred as such, instead of being converted to Node.js `Buffer`.
|
||||
* Node.js `Buffer` objects will be transferred as `Uint8Array`s. You can
|
||||
- Node.js `Buffer` objects will be transferred as `Uint8Array`s. You can
|
||||
convert a `Uint8Array` back to a Node.js `Buffer` by wrapping the underlying
|
||||
`ArrayBuffer`:
|
||||
|
||||
@@ -408,6 +448,52 @@ in Electron 8.x, and cease to exist in Electron 9.x. The layout zoom level
|
||||
limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined
|
||||
[here](https://chromium.googlesource.com/chromium/src/+/938b37a6d2886bf8335fc7db792f1eb46c65b2ae/third_party/blink/common/page/page_zoom.cc#11).
|
||||
|
||||
### Deprecated events in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` events have been deprecated:
|
||||
* `inverted-color-scheme-changed`
|
||||
* `high-contrast-color-scheme-changed`
|
||||
|
||||
Use the new `updated` event on the `nativeTheme` module instead.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.on('inverted-color-scheme-changed', () => { /* ... */ })
|
||||
systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })
|
||||
|
||||
// Replace with
|
||||
nativeTheme.on('updated', () => { /* ... */ })
|
||||
```
|
||||
|
||||
### Deprecated: methods in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` methods have been deprecated:
|
||||
* `systemPreferences.isDarkMode()`
|
||||
* `systemPreferences.isInvertedColorScheme()`
|
||||
* `systemPreferences.isHighContrastColorScheme()`
|
||||
|
||||
Use the following `nativeTheme` properties instead:
|
||||
* `nativeTheme.shouldUseDarkColors`
|
||||
* `nativeTheme.shouldUseInvertedColorScheme`
|
||||
* `nativeTheme.shouldUseHighContrastColors`
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.isDarkMode()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseDarkColors
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.isInvertedColorScheme()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseInvertedColorScheme
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.isHighContrastColorScheme()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseHighContrastColors
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (7.0)
|
||||
|
||||
### Deprecated: Atom.io Node Headers URL
|
||||
|
||||
@@ -189,6 +189,7 @@ Not all combinations of source and target CPU/OS are supported by Chromium.
|
||||
| Windows x64 | Windows x86 | Automatically tested |
|
||||
| Linux x64 | Linux x86 | Automatically tested |
|
||||
|
||||
|
||||
If you test other combinations and find them to work, please update this document :)
|
||||
|
||||
See the GN reference for allowable values of [`target_os`][target_os values]
|
||||
|
||||
@@ -66,11 +66,11 @@ formatted correctly.
|
||||
|
||||
Electron APIs uses the same capitalization scheme as Node.js:
|
||||
|
||||
* When the module itself is a class like `BrowserWindow`, use `PascalCase`.
|
||||
* When the module is a set of APIs, like `globalShortcut`, use `camelCase`.
|
||||
* When the API is a property of object, and it is complex enough to be in a
|
||||
- When the module itself is a class like `BrowserWindow`, use `PascalCase`.
|
||||
- When the module is a set of APIs, like `globalShortcut`, use `camelCase`.
|
||||
- When the API is a property of object, and it is complex enough to be in a
|
||||
separate chapter like `win.webContents`, use `mixedCase`.
|
||||
* For other non-module APIs, use natural titles, like `<webview> Tag` or
|
||||
- For other non-module APIs, use natural titles, like `<webview> Tag` or
|
||||
`Process Object`.
|
||||
|
||||
When creating a new API, it is preferred to use getters and setters instead of
|
||||
|
||||
@@ -36,9 +36,9 @@ $ git fetch upstream
|
||||
Build steps and dependencies differ slightly depending on your operating system.
|
||||
See these detailed guides on building Electron locally:
|
||||
|
||||
* [Building on macOS](build-instructions-macos.md)
|
||||
* [Building on Linux](build-instructions-linux.md)
|
||||
* [Building on Windows](build-instructions-windows.md)
|
||||
* [Building on macOS](https://electronjs.org/docs/development/build-instructions-macos)
|
||||
* [Building on Linux](https://electronjs.org/docs/development/build-instructions-linux)
|
||||
* [Building on Windows](https://electronjs.org/docs/development/build-instructions-windows)
|
||||
|
||||
Once you've built the project locally, you're ready to start making changes!
|
||||
|
||||
@@ -63,7 +63,7 @@ or tests in the `spec/` folder.
|
||||
Please be sure to run `npm run lint` from time to time on any code changes
|
||||
to ensure that they follow the project's code style.
|
||||
|
||||
See [coding style](coding-style.md) for
|
||||
See [coding style](https://electronjs.org/docs/development/coding-style) for
|
||||
more information about best practice when modifying code in different parts of
|
||||
the project.
|
||||
|
||||
@@ -91,29 +91,29 @@ Before a pull request can be merged, it **must** have a pull request title with
|
||||
|
||||
Examples of commit messages with semantic prefixes:
|
||||
|
||||
* `fix: don't overwrite prevent_default if default wasn't prevented`
|
||||
* `feat: add app.isPackaged() method`
|
||||
* `docs: app.isDefaultProtocolClient is now available on Linux`
|
||||
- `fix: don't overwrite prevent_default if default wasn't prevented`
|
||||
- `feat: add app.isPackaged() method`
|
||||
- `docs: app.isDefaultProtocolClient is now available on Linux`
|
||||
|
||||
Common prefixes:
|
||||
|
||||
* fix: A bug fix
|
||||
* feat: A new feature
|
||||
* docs: Documentation changes
|
||||
* test: Adding missing tests or correcting existing tests
|
||||
* build: Changes that affect the build system
|
||||
* ci: Changes to our CI configuration files and scripts
|
||||
* perf: A code change that improves performance
|
||||
* refactor: A code change that neither fixes a bug nor adds a feature
|
||||
* style: Changes that do not affect the meaning of the code (linting)
|
||||
* vendor: Bumping a dependency like libchromiumcontent or node
|
||||
- fix: A bug fix
|
||||
- feat: A new feature
|
||||
- docs: Documentation changes
|
||||
- test: Adding missing tests or correcting existing tests
|
||||
- build: Changes that affect the build system
|
||||
- ci: Changes to our CI configuration files and scripts
|
||||
- perf: A code change that improves performance
|
||||
- refactor: A code change that neither fixes a bug nor adds a feature
|
||||
- style: Changes that do not affect the meaning of the code (linting)
|
||||
- vendor: Bumping a dependency like libchromiumcontent or node
|
||||
|
||||
Other things to keep in mind when writing a commit message:
|
||||
|
||||
1. The first line should:
|
||||
* contain a short description of the change (preferably 50 characters or less,
|
||||
- contain a short description of the change (preferably 50 characters or less,
|
||||
and no more than 72 characters)
|
||||
* be entirely in lowercase with the exception of proper nouns, acronyms, and
|
||||
- be entirely in lowercase with the exception of proper nouns, acronyms, and
|
||||
the words that refer to code, like function/variable names
|
||||
2. Keep the second line blank.
|
||||
3. Wrap all other lines at 72 columns.
|
||||
@@ -144,7 +144,7 @@ master.
|
||||
### Step 7: Test
|
||||
|
||||
Bug fixes and features should always come with tests. A
|
||||
[testing guide](testing.md) has been
|
||||
[testing guide](https://electronjs.org/docs/development/testing) has been
|
||||
provided to make the process easier. Looking at other tests to see how they
|
||||
should be structured can also help.
|
||||
|
||||
|
||||
18
docs/fiddles/features/drag-and-drop/index.html
Normal file
18
docs/fiddles/features/drag-and-drop/index.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<a href="#" id="drag">Drag me</a>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
41
docs/fiddles/features/drag-and-drop/main.js
Normal file
41
docs/fiddles/features/drag-and-drop/main.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeImage, NativeImage } = require('electron')
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
const iconName = 'iconForDragAndDrop.png';
|
||||
const icon = fs.createWriteStream(`${process.cwd()}/${iconName}`);
|
||||
http.get('http://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
|
||||
response.pipe(icon);
|
||||
});
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
ipcMain.on('ondragstart', (event, filePath) => {
|
||||
event.sender.startDrag({
|
||||
file: filePath,
|
||||
icon: `${process.cwd()}/${iconName}`
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
9
docs/fiddles/features/drag-and-drop/renderer.js
Normal file
9
docs/fiddles/features/drag-and-drop/renderer.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
const fs = require('fs')
|
||||
|
||||
document.getElementById('drag').ondragstart = (event) => {
|
||||
const fileName = 'drag-and-drop.md'
|
||||
fs.writeFileSync(fileName, '# Test drag and drop');
|
||||
event.preventDefault()
|
||||
ipcRenderer.send('ondragstart', process.cwd() + `/${fileName}`)
|
||||
}
|
||||
16
docs/fiddles/features/keyboard-shortcuts/global/index.html
Normal file
16
docs/fiddles/features/keyboard-shortcuts/global/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
31
docs/fiddles/features/keyboard-shortcuts/global/main.js
Normal file
31
docs/fiddles/features/keyboard-shortcuts/global/main.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const { app, BrowserWindow, globalShortcut } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
globalShortcut.register('Alt+CommandOrControl+I', () => {
|
||||
console.log('Electron loves global shortcuts!')
|
||||
})
|
||||
}).then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
if (input.control && input.key.toLowerCase() === 'i') {
|
||||
console.log('Pressed Control+I')
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
})
|
||||
16
docs/fiddles/features/keyboard-shortcuts/local/index.html
Normal file
16
docs/fiddles/features/keyboard-shortcuts/local/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
39
docs/fiddles/features/keyboard-shortcuts/local/main.js
Normal file
39
docs/fiddles/features/keyboard-shortcuts/local/main.js
Normal file
@@ -0,0 +1,39 @@
|
||||
const { app, BrowserWindow, Menu, MenuItem } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const menu = new Menu()
|
||||
menu.append(new MenuItem({
|
||||
label: 'Electron',
|
||||
submenu: [{
|
||||
role: 'help',
|
||||
accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Alt+Shift+I',
|
||||
click: () => { console.log('Electron rocks!') }
|
||||
}]
|
||||
}))
|
||||
|
||||
Menu.setApplicationMenu(menu)
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
19
docs/fiddles/features/macos-dark-mode/index.html
Normal file
19
docs/fiddles/features/macos-dark-mode/index.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>Current theme source: <strong id="theme-source">System</strong></p>
|
||||
|
||||
<button id="toggle-dark-mode">Toggle Dark Mode</button>
|
||||
<button id="reset-to-system">Reset to System Theme</button>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
40
docs/fiddles/features/macos-dark-mode/main.js
Normal file
40
docs/fiddles/features/macos-dark-mode/main.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
ipcMain.handle('dark-mode:toggle', () => {
|
||||
if (nativeTheme.shouldUseDarkColors) {
|
||||
nativeTheme.themeSource = 'light'
|
||||
} else {
|
||||
nativeTheme.themeSource = 'dark'
|
||||
}
|
||||
return nativeTheme.shouldUseDarkColors
|
||||
})
|
||||
|
||||
ipcMain.handle('dark-mode:system', () => {
|
||||
nativeTheme.themeSouce = 'system'
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
11
docs/fiddles/features/macos-dark-mode/renderer.js
Normal file
11
docs/fiddles/features/macos-dark-mode/renderer.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
||||
const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
|
||||
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
|
||||
})
|
||||
|
||||
document.getElementById('reset-to-system').addEventListener('click', async () => {
|
||||
await ipcRenderer.invoke('dark-mode:system')
|
||||
document.getElementById('theme-source').innerHTML = 'System'
|
||||
})
|
||||
7
docs/fiddles/features/macos-dark-mode/styles.css
Normal file
7
docs/fiddles/features/macos-dark-mode/styles.css
Normal file
@@ -0,0 +1,7 @@
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #333; color: white; }
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
body { background: #ddd; color: black; }
|
||||
}
|
||||
16
docs/fiddles/features/macos-dock-menu/index.html
Normal file
16
docs/fiddles/features/macos-dock-menu/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
43
docs/fiddles/features/macos-dock-menu/main.js
Normal file
43
docs/fiddles/features/macos-dock-menu/main.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const { app, BrowserWindow, Menu } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const dockMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'New Window',
|
||||
click () { console.log('New Window') }
|
||||
}, {
|
||||
label: 'New Window with Settings',
|
||||
submenu: [
|
||||
{ label: 'Basic' },
|
||||
{ label: 'Pro' }
|
||||
]
|
||||
},
|
||||
{ label: 'New Command...' }
|
||||
])
|
||||
|
||||
app.whenReady().then(() => {
|
||||
app.dock.setMenu(dockMenu)
|
||||
}).then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
16
docs/fiddles/features/notifications/main/index.html
Normal file
16
docs/fiddles/features/notifications/main/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
35
docs/fiddles/features/notifications/main/main.js
Normal file
35
docs/fiddles/features/notifications/main/main.js
Normal file
@@ -0,0 +1,35 @@
|
||||
const { app, BrowserWindow, Notification } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
function showNotification () {
|
||||
const notification = {
|
||||
title: 'Basic Notification',
|
||||
body: 'Notification from the Main process'
|
||||
}
|
||||
new Notification(notification).show()
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow).then(showNotification)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
17
docs/fiddles/features/notifications/renderer/index.html
Normal file
17
docs/fiddles/features/notifications/renderer/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
27
docs/fiddles/features/notifications/renderer/main.js
Normal file
27
docs/fiddles/features/notifications/renderer/main.js
Normal file
@@ -0,0 +1,27 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
7
docs/fiddles/features/notifications/renderer/renderer.js
Normal file
7
docs/fiddles/features/notifications/renderer/renderer.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const myNotification = new Notification('Title', {
|
||||
body: 'Notification from the Renderer process'
|
||||
})
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
15
docs/fiddles/features/offscreen-rendering/index.html
Normal file
15
docs/fiddles/features/offscreen-rendering/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
28
docs/fiddles/features/offscreen-rendering/main.js
Normal file
28
docs/fiddles/features/offscreen-rendering/main.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const fs = require('fs')
|
||||
|
||||
app.disableHardwareAcceleration()
|
||||
|
||||
let win
|
||||
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({ webPreferences: { offscreen: true } })
|
||||
win.loadURL('https://github.com')
|
||||
win.webContents.on('paint', (event, dirty, image) => {
|
||||
fs.writeFileSync('ex.png', image.toPNG())
|
||||
})
|
||||
win.webContents.setFrameRate(60)
|
||||
console.log(`The screenshot has been successfully saved to ${process.cwd()}/ex.png`)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
17
docs/fiddles/features/online-detection/main/index.html
Normal file
17
docs/fiddles/features/online-detection/main/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
24
docs/fiddles/features/online-detection/main/main.js
Normal file
24
docs/fiddles/features/online-detection/main/main.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
|
||||
let onlineStatusWindow
|
||||
|
||||
app.whenReady().then(() => {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false, webPreferences: { nodeIntegration: true } })
|
||||
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
|
||||
})
|
||||
|
||||
ipcMain.on('online-status-changed', (event, status) => {
|
||||
console.log(status)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
7
docs/fiddles/features/online-detection/main/renderer.js
Normal file
7
docs/fiddles/features/online-detection/main/renderer.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', updateOnlineStatus)
|
||||
window.addEventListener('offline', updateOnlineStatus)
|
||||
|
||||
updateOnlineStatus()
|
||||
17
docs/fiddles/features/online-detection/renderer/index.html
Normal file
17
docs/fiddles/features/online-detection/renderer/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
20
docs/fiddles/features/online-detection/renderer/main.js
Normal file
20
docs/fiddles/features/online-detection/renderer/main.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let onlineStatusWindow
|
||||
|
||||
app.whenReady().then(() => {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false })
|
||||
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', alertOnlineStatus)
|
||||
window.addEventListener('offline', alertOnlineStatus)
|
||||
|
||||
alertOnlineStatus()
|
||||
16
docs/fiddles/features/progress-bar/index.html
Normal file
16
docs/fiddles/features/progress-bar/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
30
docs/fiddles/features/progress-bar/main.js
Normal file
30
docs/fiddles/features/progress-bar/main.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.setProgressBar(0.5)
|
||||
}
|
||||
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
16
docs/fiddles/features/recent-documents/index.html
Normal file
16
docs/fiddles/features/recent-documents/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
34
docs/fiddles/features/recent-documents/main.js
Normal file
34
docs/fiddles/features/recent-documents/main.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
const fileName = 'recently-used.md'
|
||||
fs.writeFile(fileName, 'Lorem Ipsum', () => {
|
||||
app.addRecentDocument(path.join(process.cwd(), `${fileName}`))
|
||||
})
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
app.clearRecentDocuments()
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
16
docs/fiddles/features/represented-file/index.html
Normal file
16
docs/fiddles/features/represented-file/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
33
docs/fiddles/features/represented-file/main.js
Normal file
33
docs/fiddles/features/represented-file/main.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const os = require('os');
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.setRepresentedFilename(os.homedir())
|
||||
win.setDocumentEdited(true)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
16
docs/fiddles/quick-start/index.html
Normal file
16
docs/fiddles/quick-start/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
27
docs/fiddles/quick-start/main.js
Normal file
27
docs/fiddles/quick-start/main.js
Normal file
@@ -0,0 +1,27 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
@@ -49,7 +49,6 @@ For API references, there are exceptions to this rule.
|
||||
* No nesting lists more than 2 levels (due to the markdown renderer).
|
||||
* All `js` and `javascript` code blocks are linted with
|
||||
[standard-markdown](https://www.npmjs.com/package/standard-markdown).
|
||||
* For unordered lists, use asterisks instead of dashes
|
||||
|
||||
## Picking words
|
||||
|
||||
|
||||
@@ -43,6 +43,6 @@ If the V8 context crashes, the DevTools will display this message.
|
||||
|
||||
`DevTools was disconnected from the page. Once page is reloaded, DevTools will automatically reconnect.`
|
||||
|
||||
Chromium logs can be enabled via the `ELECTRON_ENABLE_LOGGING` environment variable. For more information, see the [environment variables documentation](../api/environment-variables.md#electron_enable_logging).
|
||||
Chromium logs can be enabled via the `ELECTRON_ENABLE_LOGGING` environment variable. For more information, see the [environment variables documentation](https://www.electronjs.org/docs/api/environment-variables#electron_enable_logging).
|
||||
|
||||
Alternatively, the command line argument `--enable-logging` can be passed. More information is available in the [command line switches documentation](../api/command-line-switches.md#--enable-logging).
|
||||
Alternatively, the command line argument `--enable-logging` can be passed. More information is available in the [command line switches documentation](https://www.electronjs.org/docs/api/command-line-switches#--enable-logging).
|
||||
|
||||
@@ -196,11 +196,11 @@ it may be worth your time to shop around. Popular resellers include:
|
||||
|
||||
There are a number of tools for signing your packaged app:
|
||||
|
||||
* [`electron-winstaller`] will generate an installer for windows and sign it for
|
||||
- [`electron-winstaller`] will generate an installer for windows and sign it for
|
||||
you
|
||||
* [`electron-forge`] can sign installers it generates through the
|
||||
- [`electron-forge`] can sign installers it generates through the
|
||||
Squirrel.Windows or MSI targets.
|
||||
* [`electron-builder`] can sign some of its windows targets
|
||||
- [`electron-builder`] can sign some of its windows targets
|
||||
|
||||
## Windows Store
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ the system's dark mode setting. You can do this by using the
|
||||
|
||||
If you want to manually switch between light/dark modes, you can do this by
|
||||
setting the desired mode in the
|
||||
[themeSource](../api/native-theme.md#nativethemethemesource)
|
||||
[themeSource](https://www.electronjs.org/docs/api/native-theme#nativethemethemesource)
|
||||
property of the `nativeTheme` module. This property's value will be propagated
|
||||
to your Renderer process. Any CSS rules related to `prefers-color-scheme` will
|
||||
be updated accordingly.
|
||||
|
||||
@@ -35,6 +35,7 @@ $ code electron-quick-start
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 3. Debugging
|
||||
|
||||
Set some breakpoints in `main.js`, and start debugging in the [Debug View](https://code.visualstudio.com/docs/editor/debugging). You should be able to hit the breakpoints.
|
||||
@@ -83,16 +84,16 @@ $ code electron-quick-start
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Configuration Notes**
|
||||
|
||||
* `cppvsdbg` requires the [built-in C/C++ extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) be enabled.
|
||||
* `${workspaceFolder}` is the full path to Chromium's `src` directory.
|
||||
* `your-executable-location` will be one of the following depending on a few items:
|
||||
* `Testing`: If you are using the default settings of [Electron's Build-Tools](https://github.com/electron/build-tools) or the default instructions when [building from source](https://www.electronjs.org/docs/development/build-instructions-gn#building).
|
||||
* `Release`: If you built a Release build rather than a Testing build.
|
||||
* `your-directory-name`: If you modified this during your build process from the default, this will be whatever you specified.
|
||||
* The `args` array string `"your-electron-project-path"` should be the absolute path to either the directory or `main.js` file of the Electron project you are using for testing. In this example, it should be your path to `electron-quick-start`.
|
||||
- `cppvsdbg` requires the [built-in C/C++ extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) be enabled.
|
||||
- `${workspaceFolder}` is the full path to Chromium's `src` directory.
|
||||
- `your-executable-location` will be one of the following depending on a few items:
|
||||
- `Testing`: If you are using the default settings of [Electron's Build-Tools](https://github.com/electron/build-tools) or the default instructions when [building from source](https://www.electronjs.org/docs/development/build-instructions-gn#building).
|
||||
- `Release`: If you built a Release build rather than a Testing build.
|
||||
- `your-directory-name`: If you modified this during your build process from the default, this will be whatever you specified.
|
||||
- The `args` array string `"your-electron-project-path"` should be the absolute path to either the directory or `main.js` file of the Electron project you are using for testing. In this example, it should be your path to `electron-quick-start`.
|
||||
|
||||
|
||||
#### 3. Debugging
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Electron versions *< 2.0* did not conform to the [semver](https://semver.org) sp
|
||||
|
||||
Here is an example of the 1.x strategy:
|
||||
|
||||

|
||||

|
||||
|
||||
An app developed with `1.8.1` cannot take the `1.8.3` bug fix without either absorbing the `1.8.2` feature, or by backporting the fix and maintaining a new release line.
|
||||
|
||||
@@ -54,12 +54,12 @@ Note that most Chromium updates will be considered breaking. Fixes that can be b
|
||||
|
||||
Stabilization branches are branches that run parallel to master, taking in only cherry-picked commits that are related to security or stability. These branches are never merged back to master.
|
||||
|
||||

|
||||

|
||||
|
||||
Since Electron 8, stabilization branches are always **major** version lines, and named against the following template `$MAJOR-x-y` e.g. `8-x-y`. Prior to that we used **minor** version lines and named them as `$MAJOR-$MINOR-x` e.g. `2-0-x`
|
||||
|
||||
We allow for multiple stabilization branches to exist simultaneously, and intend to support at least two in parallel at all times, backporting security fixes as necessary.
|
||||

|
||||

|
||||
|
||||
Older lines will not be supported by GitHub, but other groups can take ownership and backport stability and security fixes on their own. We discourage this, but recognize that it makes life easier for many app developers.
|
||||
|
||||
@@ -104,17 +104,17 @@ For each major and minor bump, you should expect to see something like the follo
|
||||
An example lifecycle in pictures:
|
||||
|
||||
* A new release branch is created that includes the latest set of features. It is published as `2.0.0-beta.1`.
|
||||

|
||||

|
||||
* A bug fix comes into master that can be backported to the release branch. The patch is applied, and a new beta is published as `2.0.0-beta.2`.
|
||||

|
||||

|
||||
* The beta is considered _generally stable_ and it is published again as a non-beta under `2.0.0`.
|
||||

|
||||

|
||||
* Later, a zero-day exploit is revealed and a fix is applied to master. We backport the fix to the `2-0-x` line and release `2.0.1`.
|
||||

|
||||

|
||||
|
||||
A few examples of how various semver ranges will pick up new releases:
|
||||
|
||||

|
||||

|
||||
|
||||
# Missing Features: Alphas
|
||||
|
||||
@@ -145,7 +145,7 @@ We seek to increase clarity at all levels of the update and releases process. St
|
||||
|
||||
# Versioned `master`
|
||||
|
||||
* The `master` branch will always contain the next major version `X.0.0-nightly.DATE` in its `package.json`
|
||||
* Release branches are never merged back to master
|
||||
* Release branches _do_ contain the correct version in their `package.json`
|
||||
* As soon as a release branch is cut for a major, master must be bumped to the next major. I.e. `master` is always versioned as the next theoretical release branch
|
||||
- The `master` branch will always contain the next major version `X.0.0-nightly.DATE` in its `package.json`
|
||||
- Release branches are never merged back to master
|
||||
- Release branches _do_ contain the correct version in their `package.json`
|
||||
- As soon as a release branch is cut for a major, master must be bumped to the next major. I.e. `master` is always versioned as the next theoretical release branch
|
||||
|
||||
@@ -71,4 +71,4 @@ Although the spellchecker itself does not send any typings, words or user input
|
||||
myWindow.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
|
||||
```
|
||||
|
||||
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](../api/session.md#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.
|
||||
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](https://www.electronjs.org/docs/api/session#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.
|
||||
|
||||
@@ -10,21 +10,21 @@ for answers to questions,
|
||||
or to join in discussion with other developers who use Electron,
|
||||
you can interact with the community in these locations:
|
||||
|
||||
* [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
|
||||
* Getting help
|
||||
* Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
|
||||
* Sharing ideas with other Electron app developers
|
||||
* And more!
|
||||
* [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
|
||||
* `#atom-shell` channel on Freenode
|
||||
* `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
|
||||
* [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
* [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
* [`electron-kr`](https://electron-kr.github.io/electron-kr) *(Korean)*
|
||||
* [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
* [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
|
||||
* [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
* [`electron-pl`](https://electronpl.github.io) *(Poland)*
|
||||
- [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
|
||||
- Getting help
|
||||
- Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
|
||||
- Sharing ideas with other Electron app developers
|
||||
- And more!
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](https://electron-kr.github.io/electron-kr) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
- [`electron-pl`](https://electronpl.github.io) *(Poland)*
|
||||
|
||||
If you'd like to contribute to Electron,
|
||||
see the [contributing document](https://github.com/electron/electron/blob/master/CONTRIBUTING.md).
|
||||
@@ -64,9 +64,9 @@ until the maintainers feel the maintenance burden is too high to continue doing
|
||||
|
||||
### Currently supported versions
|
||||
|
||||
* 11.x.y
|
||||
* 10.x.y
|
||||
* 9.x.y
|
||||
- 11.x.y
|
||||
- 10.x.y
|
||||
- 9.x.y
|
||||
|
||||
### End-of-life
|
||||
|
||||
|
||||
@@ -129,13 +129,13 @@ should look like this:
|
||||
|
||||
In particular, it's important that:
|
||||
|
||||
* you link against `node.lib` from _Electron_ and not Node. If you link against
|
||||
- you link against `node.lib` from _Electron_ and not Node. If you link against
|
||||
the wrong `node.lib` you will get load-time errors when you require the
|
||||
module in Electron.
|
||||
* you include the flag `/DELAYLOAD:node.exe`. If the `node.exe` link is not
|
||||
- you include the flag `/DELAYLOAD:node.exe`. If the `node.exe` link is not
|
||||
delayed, then the delay-load hook won't get a chance to fire and the node
|
||||
symbols won't be correctly resolved.
|
||||
* `win_delay_load_hook.obj` is linked directly into the final DLL. If the hook
|
||||
- `win_delay_load_hook.obj` is linked directly into the final DLL. If the hook
|
||||
is set up in a dependent DLL, it won't fire at the right time.
|
||||
|
||||
See [`node-gyp`](https://github.com/nodejs/node-gyp/blob/e2401e1395bef1d3c8acec268b42dc5fb71c4a38/src/win_delay_load_hook.cc)
|
||||
|
||||
@@ -20,7 +20,7 @@ and only allow the capabilities you want to support.
|
||||
### WebViews
|
||||
|
||||
> Important Note:
|
||||
[we do not recommend you to use use WebViews](../api/webview-tag.md#warning),
|
||||
[we do not recommend you to use use WebViews](https://www.electronjs.org/docs/api/webview-tag#warning),
|
||||
as this tag undergoes dramatic architectural changes that may affect stability
|
||||
of your application. Consider switching to alternatives, like `iframe` and
|
||||
Electron's `BrowserView`, or an architecture that avoids embedded content
|
||||
|
||||
@@ -689,7 +689,8 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
if (info.size === 0) return ['', false];
|
||||
if (info.unpacked) {
|
||||
const realPath = archive.copyFileOut(filePath);
|
||||
return fs.readFileSync(realPath, { encoding: 'utf8' });
|
||||
const str = fs.readFileSync(realPath, { encoding: 'utf8' });
|
||||
return [str, str.length > 0];
|
||||
}
|
||||
|
||||
logASARAccess(asarPath, filePath, info.offset);
|
||||
|
||||
@@ -51,10 +51,6 @@ class CrashReporter {
|
||||
return binding.getUploadedReports();
|
||||
}
|
||||
|
||||
getCrashesDirectory () {
|
||||
return app.getPath('crashDumps');
|
||||
}
|
||||
|
||||
getUploadToServer () {
|
||||
if (process.type === 'browser') {
|
||||
return binding.getUploadToServer();
|
||||
|
||||
@@ -2,37 +2,39 @@ const { createScreen } = process._linkedBinding('electron_common_screen');
|
||||
|
||||
let _screen: Electron.Screen;
|
||||
|
||||
const createScreenIfNeeded = () => {
|
||||
if (_screen === undefined) {
|
||||
_screen = createScreen();
|
||||
}
|
||||
};
|
||||
|
||||
// We can't call createScreen until after app.on('ready'), but this module
|
||||
// exposes an instance created by createScreen. In order to avoid
|
||||
// side-effecting and calling createScreen upon import of this module, instead
|
||||
// we export a proxy which lazily calls createScreen on first access.
|
||||
export default new Proxy({}, {
|
||||
get: (target, prop: keyof Electron.Screen) => {
|
||||
if (_screen === undefined) {
|
||||
_screen = createScreen();
|
||||
get: (target, property: keyof Electron.Screen) => {
|
||||
createScreenIfNeeded();
|
||||
const value = _screen[property];
|
||||
if (typeof value === 'function') {
|
||||
return value.bind(_screen);
|
||||
}
|
||||
const v = _screen[prop];
|
||||
if (typeof v === 'function') {
|
||||
return v.bind(_screen);
|
||||
}
|
||||
return v;
|
||||
return value;
|
||||
},
|
||||
set: (target, property: string, value: unknown) => {
|
||||
createScreenIfNeeded();
|
||||
return Reflect.set(_screen, property, value);
|
||||
},
|
||||
ownKeys: () => {
|
||||
if (_screen === undefined) {
|
||||
_screen = createScreen();
|
||||
}
|
||||
createScreenIfNeeded();
|
||||
return Reflect.ownKeys(_screen);
|
||||
},
|
||||
has: (target, prop: string) => {
|
||||
if (_screen === undefined) {
|
||||
_screen = createScreen();
|
||||
}
|
||||
return prop in _screen;
|
||||
has: (target, property: string) => {
|
||||
createScreenIfNeeded();
|
||||
return property in _screen;
|
||||
},
|
||||
getOwnPropertyDescriptor: (target, prop: string) => {
|
||||
if (_screen === undefined) {
|
||||
_screen = createScreen();
|
||||
}
|
||||
return Reflect.getOwnPropertyDescriptor(_screen, prop);
|
||||
getOwnPropertyDescriptor: (target, property: string) => {
|
||||
createScreenIfNeeded();
|
||||
return Reflect.getOwnPropertyDescriptor(_screen, property);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ if ('getAppLevelAppearance' in systemPreferences) {
|
||||
}
|
||||
|
||||
if ('getEffectiveAppearance' in systemPreferences) {
|
||||
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
|
||||
const nativeEAGetter = systemPreferences.getEffectiveAppearance;
|
||||
Object.defineProperty(systemPreferences, 'effectiveAppearance', {
|
||||
get: () => nativeEAGetter.call(systemPreferences)
|
||||
});
|
||||
|
||||
@@ -164,29 +164,29 @@ WebContents.prototype._sendInternalToAll = function (channel, ...args) {
|
||||
|
||||
return this._send(internal, sendToAll, channel, args);
|
||||
};
|
||||
WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
|
||||
WebContents.prototype.sendToFrame = function (frame, channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
} else if (typeof frameId !== 'number') {
|
||||
throw new Error('Missing required frameId argument');
|
||||
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
|
||||
throw new Error('Missing required frame argument (must be number or array)');
|
||||
}
|
||||
|
||||
const internal = false;
|
||||
const sendToAll = false;
|
||||
|
||||
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
|
||||
return this._sendToFrame(internal, sendToAll, frame, channel, args);
|
||||
};
|
||||
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
|
||||
WebContents.prototype._sendToFrameInternal = function (frame, channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
} else if (typeof frameId !== 'number') {
|
||||
throw new Error('Missing required frameId argument');
|
||||
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
|
||||
throw new Error('Missing required frame argument (must be number or array)');
|
||||
}
|
||||
|
||||
const internal = true;
|
||||
const sendToAll = false;
|
||||
|
||||
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
|
||||
return this._sendToFrame(internal, sendToAll, frame, channel, args);
|
||||
};
|
||||
|
||||
// Following methods are mapped to webFrame.
|
||||
@@ -478,8 +478,9 @@ WebContents.prototype._callWindowOpenHandler = function (event: any, url: string
|
||||
};
|
||||
|
||||
const addReplyToEvent = (event: any) => {
|
||||
const { processId, frameId } = event;
|
||||
event.reply = (...args: any[]) => {
|
||||
event.sender.sendToFrame(event.frameId, ...args);
|
||||
event.sender.sendToFrame([processId, frameId], ...args);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ const watchEmbedder = function (embedder: Electron.WebContents) {
|
||||
|
||||
const isWebViewTagEnabledCache = new WeakMap();
|
||||
|
||||
const isWebViewTagEnabled = function (contents: Electron.WebContents) {
|
||||
export const isWebViewTagEnabled = function (contents: Electron.WebContents) {
|
||||
if (!isWebViewTagEnabledCache.has(contents)) {
|
||||
const webPreferences = contents.getLastWebPreferences() || {};
|
||||
isWebViewTagEnabledCache.set(contents, !!webPreferences.webviewTag);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { WebContents } from 'electron/main';
|
||||
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const getOwnerKey = (webContents: WebContents, contextId: string) => {
|
||||
return `${webContents.id}-${contextId}`;
|
||||
};
|
||||
|
||||
const electronIds = new WeakMap<Object, number>();
|
||||
|
||||
class ObjectsRegistry {
|
||||
private nextId: number = 0
|
||||
|
||||
@@ -81,14 +81,14 @@ class ObjectsRegistry {
|
||||
|
||||
// Private: Saves the object into storage and assigns an ID for it.
|
||||
saveToStorage (object: any) {
|
||||
let id = electronIds.get(object);
|
||||
let id: number = v8Util.getHiddenValue(object, 'electronId');
|
||||
if (!id) {
|
||||
id = ++this.nextId;
|
||||
this.storage[id] = {
|
||||
count: 0,
|
||||
object: object
|
||||
};
|
||||
electronIds.set(object, id);
|
||||
v8Util.setHiddenValue(object, 'electronId', id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ class ObjectsRegistry {
|
||||
}
|
||||
pointer.count -= 1;
|
||||
if (pointer.count === 0) {
|
||||
electronIds.delete(pointer.object);
|
||||
v8Util.deleteHiddenValue(pointer.object, 'electronId');
|
||||
delete this.storage[id];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ const FUNCTION_PROPERTIES = [
|
||||
];
|
||||
|
||||
type RendererFunctionId = [string, number] // [contextId, funcId]
|
||||
type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: number };
|
||||
type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: [number, number] };
|
||||
type CallIntoRenderer = (...args: any[]) => void
|
||||
|
||||
// The remote functions in renderer processes.
|
||||
@@ -31,7 +31,7 @@ const finalizationRegistry = new FinalizationRegistry((fi: FinalizerInfo) => {
|
||||
const ref = rendererFunctionCache.get(mapKey);
|
||||
if (ref !== undefined && ref.deref() === undefined) {
|
||||
rendererFunctionCache.delete(mapKey);
|
||||
if (!fi.webContents.isDestroyed()) { fi.webContents.sendToFrame(fi.frameId, IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, fi.id[0], fi.id[1]); }
|
||||
if (!fi.webContents.isDestroyed()) { fi.webContents._sendToFrameInternal(fi.frameId, IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, fi.id[0], fi.id[1]); }
|
||||
}
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@ function getCachedRendererFunction (id: RendererFunctionId): CallIntoRenderer |
|
||||
if (deref !== undefined) return deref;
|
||||
}
|
||||
}
|
||||
function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebContents, frameId: number, value: CallIntoRenderer) {
|
||||
function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebContents, frameId: [number, number], value: CallIntoRenderer) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const wr = new WeakRef<CallIntoRenderer>(value);
|
||||
const mapKey = id[0] + '~' + id[1];
|
||||
@@ -56,8 +56,6 @@ function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebCont
|
||||
return value;
|
||||
}
|
||||
|
||||
const locationInfo = new WeakMap<Object, string>();
|
||||
|
||||
// Return the description of object's members:
|
||||
const getObjectMembers = function (object: any): ObjectMember[] {
|
||||
let names = Object.getOwnPropertyNames(object);
|
||||
@@ -188,7 +186,7 @@ const throwRPCError = function (message: string) {
|
||||
};
|
||||
|
||||
const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...args: any[]) => void) => {
|
||||
const location = locationInfo.get(callIntoRenderer);
|
||||
const location = v8Util.getHiddenValue(callIntoRenderer, 'location');
|
||||
let message = 'Attempting to call a function in a renderer window that has been closed or released.' +
|
||||
`\nFunction provided here: ${location}`;
|
||||
|
||||
@@ -220,7 +218,7 @@ const fakeConstructor = (constructor: Function, name: string) =>
|
||||
});
|
||||
|
||||
// Convert array of meta data from renderer into array of real values.
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: number, contextId: string, args: any[]) {
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: [number, number], contextId: string, args: any[]) {
|
||||
const metaToValue = function (meta: MetaTypeFromRenderer): any {
|
||||
switch (meta.type) {
|
||||
case 'nativeimage':
|
||||
@@ -271,7 +269,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
|
||||
removeRemoteListenersAndLogWarning(this, callIntoRenderer);
|
||||
}
|
||||
};
|
||||
locationInfo.set(callIntoRenderer, meta.location);
|
||||
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
|
||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
|
||||
|
||||
setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);
|
||||
@@ -423,7 +421,7 @@ handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_CURRENT_WEB_CONTENTS, function (eve
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_CONSTRUCTOR, function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const constructor = objectsRegistry.get(id);
|
||||
|
||||
if (constructor == null) {
|
||||
@@ -434,7 +432,7 @@ handleRemoteCommand(IPC_MESSAGES.BROWSER_CONSTRUCTOR, function (event, contextId
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_FUNCTION_CALL, function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const func = objectsRegistry.get(id);
|
||||
|
||||
if (func == null) {
|
||||
@@ -451,7 +449,7 @@ handleRemoteCommand(IPC_MESSAGES.BROWSER_FUNCTION_CALL, function (event, context
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CONSTRUCTOR, function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
@@ -462,7 +460,7 @@ handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CONSTRUCTOR, function (event, co
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CALL, function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
@@ -479,7 +477,7 @@ handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CALL, function (event, contextId
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_SET, function (event, contextId, id, name, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const obj = objectsRegistry.get(id);
|
||||
|
||||
if (obj == null) {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { app } from 'electron/main';
|
||||
import type { WebContents } from 'electron/main';
|
||||
import { clipboard, crashReporter, nativeImage } from 'electron/common';
|
||||
import { clipboard, nativeImage } from 'electron/common';
|
||||
import * as fs from 'fs';
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
|
||||
import * as guestViewManager from '@electron/internal/browser/guest-view-manager';
|
||||
import * as typeUtils from '@electron/internal/common/type-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
@@ -73,6 +74,10 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
});
|
||||
}
|
||||
|
||||
const isRemoteModuleEnabled = BUILDFLAG(ENABLE_REMOTE_MODULE)
|
||||
? require('@electron/internal/browser/remote/server').isRemoteModuleEnabled
|
||||
: () => false;
|
||||
|
||||
const getPreloadScript = async function (preloadPath: string) {
|
||||
let preloadSrc = null;
|
||||
let preloadError = null;
|
||||
@@ -86,9 +91,14 @@ const getPreloadScript = async function (preloadPath: string) {
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event) {
|
||||
const preloadPaths = event.sender._getPreloadPaths();
|
||||
const webPreferences = event.sender.getLastWebPreferences() || {};
|
||||
|
||||
return {
|
||||
preloadScripts: await Promise.all(preloadPaths.map(path => getPreloadScript(path))),
|
||||
isRemoteModuleEnabled: isRemoteModuleEnabled(event.sender),
|
||||
isWebViewTagEnabled: guestViewManager.isWebViewTagEnabled(event.sender),
|
||||
guestInstanceId: webPreferences.guestInstanceId,
|
||||
openerId: webPreferences.openerId,
|
||||
process: {
|
||||
arch: process.arch,
|
||||
platform: process.platform,
|
||||
@@ -104,26 +114,6 @@ ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadP
|
||||
event.sender.emit('preload-error', event, preloadPath, error);
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_LAST_CRASH_REPORT, () => {
|
||||
return crashReporter.getLastCrashReport();
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_UPLOADED_REPORTS, () => {
|
||||
return crashReporter.getUploadedReports();
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_UPLOAD_TO_SERVER, () => {
|
||||
return crashReporter.getUploadToServer();
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_SET_UPLOAD_TO_SERVER, (event, uploadToServer: boolean) => {
|
||||
return crashReporter.setUploadToServer(uploadToServer);
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_CRASHES_DIRECTORY, () => {
|
||||
return crashReporter.getCrashesDirectory();
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, async (_, path: string, size: Electron.Size) => {
|
||||
return typeUtils.serialize(await nativeImage.createThumbnailFromPath(path, size));
|
||||
});
|
||||
|
||||
@@ -5,12 +5,6 @@ export const enum IPC_MESSAGES {
|
||||
BROWSER_SANDBOX_LOAD = 'BROWSER_SANDBOX_LOAD',
|
||||
BROWSER_WINDOW_CLOSE = 'BROWSER_WINDOW_CLOSE',
|
||||
|
||||
CRASH_REPORTER_GET_LAST_CRASH_REPORT = 'CRASH_REPORTER_GET_LAST_CRASH_REPORT',
|
||||
CRASH_REPORTER_GET_UPLOADED_REPORTS = 'CRASH_REPORTER_GET_UPLOADED_REPORTS',
|
||||
CRASH_REPORTER_GET_UPLOAD_TO_SERVER = 'CRASH_REPORTER_GET_UPLOAD_TO_SERVER',
|
||||
CRASH_REPORTER_SET_UPLOAD_TO_SERVER = 'CRASH_REPORTER_SET_UPLOAD_TO_SERVER',
|
||||
CRASH_REPORTER_GET_CRASHES_DIRECTORY = 'CRASH_REPORTER_GET_CRASHES_DIRECTORY',
|
||||
|
||||
GUEST_INSTANCE_VISIBILITY_CHANGE = 'GUEST_INSTANCE_VISIBILITY_CHANGE',
|
||||
|
||||
GUEST_VIEW_INTERNAL_DESTROY_GUEST = 'GUEST_VIEW_INTERNAL_DESTROY_GUEST',
|
||||
|
||||
@@ -1,42 +1,6 @@
|
||||
import { invokeSync } from '../ipc-renderer-internal-utils';
|
||||
import { deprecate } from 'electron';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
const binding = process._linkedBinding('electron_renderer_crash_reporter');
|
||||
|
||||
export default {
|
||||
start (options: Electron.CrashReporterStartOptions) {
|
||||
deprecate.log('crashReporter.start is deprecated in the renderer process. Call it from the main process instead.');
|
||||
for (const [k, v] of Object.entries(options.extra || {})) {
|
||||
binding.addExtraParameter(k, String(v));
|
||||
}
|
||||
},
|
||||
|
||||
getLastCrashReport (): Electron.CrashReport | null {
|
||||
deprecate.log('crashReporter.getLastCrashReport is deprecated in the renderer process. Call it from the main process instead.');
|
||||
return invokeSync(IPC_MESSAGES.CRASH_REPORTER_GET_LAST_CRASH_REPORT);
|
||||
},
|
||||
|
||||
getUploadedReports () {
|
||||
deprecate.log('crashReporter.getUploadedReports is deprecated in the renderer process. Call it from the main process instead.');
|
||||
return invokeSync(IPC_MESSAGES.CRASH_REPORTER_GET_UPLOADED_REPORTS);
|
||||
},
|
||||
|
||||
getUploadToServer () {
|
||||
deprecate.log('crashReporter.getUploadToServer is deprecated in the renderer process. Call it from the main process instead.');
|
||||
return invokeSync(IPC_MESSAGES.CRASH_REPORTER_GET_UPLOAD_TO_SERVER);
|
||||
},
|
||||
|
||||
setUploadToServer (uploadToServer: boolean) {
|
||||
deprecate.log('crashReporter.setUploadToServer is deprecated in the renderer process. Call it from the main process instead.');
|
||||
return invokeSync(IPC_MESSAGES.CRASH_REPORTER_SET_UPLOAD_TO_SERVER, uploadToServer);
|
||||
},
|
||||
|
||||
getCrashesDirectory () {
|
||||
deprecate.log('crashReporter.getCrashesDirectory is deprecated in the renderer process. Call it from the main process instead.');
|
||||
return invokeSync(IPC_MESSAGES.CRASH_REPORTER_GET_CRASHES_DIRECTORY);
|
||||
},
|
||||
|
||||
addExtraParameter (key: string, value: string) {
|
||||
binding.addExtraParameter(key, value);
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const enableRemoteModule = getWebPreference(window, 'enableRemoteModule');
|
||||
const enableRemoteModule = v8Util.getHiddenValue<boolean>(global, 'enableRemoteModule');
|
||||
|
||||
// Renderer side modules, please sort alphabetically.
|
||||
export const rendererModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
|
||||
@@ -23,9 +23,6 @@ const finalizationRegistry = new (window as any).FinalizationRegistry((id: numbe
|
||||
}
|
||||
});
|
||||
|
||||
const electronIds = new WeakMap<Object, number>();
|
||||
const isReturnValue = new WeakSet<Object>();
|
||||
|
||||
function getCachedRemoteObject (id: number) {
|
||||
const ref = remoteObjectCache.get(id);
|
||||
if (ref !== undefined) {
|
||||
@@ -93,10 +90,10 @@ function wrapArgs (args: any[], visited = new Set()): any {
|
||||
value.then(onFulfilled, onRejected);
|
||||
})
|
||||
};
|
||||
} else if (electronIds.has(value)) {
|
||||
} else if (v8Util.getHiddenValue(value, 'electronId')) {
|
||||
return {
|
||||
type: 'remote-object',
|
||||
id: electronIds.get(value)
|
||||
id: v8Util.getHiddenValue(value, 'electronId')
|
||||
};
|
||||
}
|
||||
|
||||
@@ -114,7 +111,7 @@ function wrapArgs (args: any[], visited = new Set()): any {
|
||||
}
|
||||
visited.delete(value);
|
||||
return meta;
|
||||
} else if (typeof value === 'function' && isReturnValue.has(value)) {
|
||||
} else if (typeof value === 'function' && v8Util.getHiddenValue(value, 'returnValue')) {
|
||||
return {
|
||||
type: 'function-with-return-value',
|
||||
value: valueToMeta(value())
|
||||
@@ -123,7 +120,7 @@ function wrapArgs (args: any[], visited = new Set()): any {
|
||||
return {
|
||||
type: 'function',
|
||||
id: callbacksRegistry.add(value),
|
||||
location: callbacksRegistry.getLocation(value),
|
||||
location: v8Util.getHiddenValue(value, 'location'),
|
||||
length: value.length
|
||||
};
|
||||
} else {
|
||||
@@ -290,7 +287,7 @@ function metaToValue (meta: MetaType): any {
|
||||
}
|
||||
|
||||
// Track delegate obj's lifetime & tell browser to clean up when object is GCed.
|
||||
electronIds.set(ret, meta.id);
|
||||
v8Util.setHiddenValue(ret, 'electronId', meta.id);
|
||||
setCachedRemoteObject(meta.id, ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -376,7 +373,7 @@ Object.defineProperty(exports, 'process', {
|
||||
// Create a function that will return the specified value when called in browser.
|
||||
export function createFunctionWithReturnValue<T> (returnValue: T): () => T {
|
||||
const func = () => returnValue;
|
||||
isReturnValue.add(func);
|
||||
v8Util.setHiddenValue(func, 'returnValue', true);
|
||||
return func;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,16 +57,30 @@ webFrameInit();
|
||||
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
const parseOption = function<TDefault> (
|
||||
name: string, defaultValue: TDefault, converter?: (value: string) => any
|
||||
) {
|
||||
const value = getWebPreference(window, name);
|
||||
return value
|
||||
? (
|
||||
converter
|
||||
? converter(value)
|
||||
: value
|
||||
)
|
||||
: defaultValue;
|
||||
};
|
||||
|
||||
const contextIsolation = getWebPreference(window, 'contextIsolation');
|
||||
const nodeIntegration = getWebPreference(window, 'nodeIntegration');
|
||||
const webviewTag = getWebPreference(window, 'webviewTag');
|
||||
const isHiddenPage = getWebPreference(window, 'hiddenPage');
|
||||
const usesNativeWindowOpen = getWebPreference(window, 'nativeWindowOpen');
|
||||
const rendererProcessReuseEnabled = getWebPreference(window, 'disableElectronSiteInstanceOverrides');
|
||||
const preloadScript = getWebPreference(window, 'preload');
|
||||
const preloadScripts = getWebPreference(window, 'preloadScripts');
|
||||
const guestInstanceId = getWebPreference(window, 'guestInstanceId') || null;
|
||||
const openerId = getWebPreference(window, 'openerId') || null;
|
||||
|
||||
const preloadScript = parseOption('preload', null);
|
||||
const preloadScripts = parseOption('preloadScripts', []);
|
||||
const guestInstanceId = parseOption('guestInstanceId', null, value => parseInt(value));
|
||||
const openerId = parseOption('openerId', null, value => parseInt(value));
|
||||
const appPath = hasSwitch('app-path') ? getSwitchValue('app-path') : null;
|
||||
|
||||
// The webContents preload script is loaded after the session preload scripts.
|
||||
@@ -83,9 +97,8 @@ switch (window.location.protocol) {
|
||||
case 'chrome-extension:': {
|
||||
break;
|
||||
}
|
||||
case 'chrome:': {
|
||||
case 'chrome:':
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Override default web functions.
|
||||
const { windowSetup } = require('@electron/internal/renderer/window-setup');
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const callbackIds = new WeakMap<Function, number>();
|
||||
const locationInfo = new WeakMap<Function, string>();
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
export class CallbacksRegistry {
|
||||
private nextId: number = 0
|
||||
@@ -7,7 +6,7 @@ export class CallbacksRegistry {
|
||||
|
||||
add (callback: Function) {
|
||||
// The callback is already added.
|
||||
let id = callbackIds.get(callback);
|
||||
let id = v8Util.getHiddenValue<number>(callback, 'callbackId');
|
||||
if (id != null) return id;
|
||||
|
||||
id = this.nextId += 1;
|
||||
@@ -18,7 +17,7 @@ export class CallbacksRegistry {
|
||||
const stackString = (new Error()).stack;
|
||||
if (!stackString) return;
|
||||
|
||||
let filenameAndLine: string;
|
||||
let filenameAndLine;
|
||||
let match;
|
||||
|
||||
while ((match = regexp.exec(stackString)) !== null) {
|
||||
@@ -33,8 +32,8 @@ export class CallbacksRegistry {
|
||||
}
|
||||
|
||||
this.callbacks.set(id, callback);
|
||||
callbackIds.set(callback, id);
|
||||
locationInfo.set(callback, filenameAndLine!);
|
||||
v8Util.setHiddenValue(callback, 'callbackId', id);
|
||||
v8Util.setHiddenValue(callback, 'location', filenameAndLine);
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -42,10 +41,6 @@ export class CallbacksRegistry {
|
||||
return this.callbacks.get(id) || function () {};
|
||||
}
|
||||
|
||||
getLocation (callback: Function) {
|
||||
return locationInfo.get(callback);
|
||||
}
|
||||
|
||||
apply (id: number, ...args: any[]) {
|
||||
return this.get(id).apply(global, ...args);
|
||||
}
|
||||
@@ -53,7 +48,7 @@ export class CallbacksRegistry {
|
||||
remove (id: number) {
|
||||
const callback = this.callbacks.get(id);
|
||||
if (callback) {
|
||||
callbackIds.delete(callback);
|
||||
v8Util.deleteHiddenValue(callback, 'callbackId');
|
||||
this.callbacks.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ const warnAboutInsecureCSP = function () {
|
||||
|
||||
console.warn('%cElectron Security Warning (Insecure Content-Security-Policy)',
|
||||
'font-weight: bold;', warning);
|
||||
});
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
const enableRemoteModule = getWebPreference(window, 'enableRemoteModule');
|
||||
|
||||
export const moduleList: ElectronInternal.ModuleEntry[] = [
|
||||
{
|
||||
name: 'contextBridge',
|
||||
@@ -38,7 +34,7 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
});
|
||||
}
|
||||
|
||||
if (BUILDFLAG(ENABLE_REMOTE_MODULE) && enableRemoteModule) {
|
||||
if (BUILDFLAG(ENABLE_REMOTE_MODULE) && process.isRemoteModuleEnabled) {
|
||||
moduleList.push({
|
||||
name: 'remote',
|
||||
loader: () => require('@electron/internal/renderer/api/remote')
|
||||
|
||||
@@ -23,7 +23,16 @@ Object.setPrototypeOf(process, EventEmitter.prototype);
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils');
|
||||
|
||||
const { preloadScripts, process: processProps } = ipcRendererUtils.invokeSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD);
|
||||
const {
|
||||
preloadScripts,
|
||||
isRemoteModuleEnabled,
|
||||
isWebViewTagEnabled,
|
||||
guestInstanceId,
|
||||
openerId,
|
||||
process: processProps
|
||||
} = ipcRendererUtils.invokeSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD);
|
||||
|
||||
process.isRemoteModuleEnabled = isRemoteModuleEnabled;
|
||||
|
||||
const electron = require('electron');
|
||||
|
||||
@@ -114,12 +123,9 @@ if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
}
|
||||
|
||||
const contextIsolation = getWebPreference(window, 'contextIsolation');
|
||||
const webviewTag = getWebPreference(window, 'webviewTag');
|
||||
const isHiddenPage = getWebPreference(window, 'hiddenPage');
|
||||
const rendererProcessReuseEnabled = getWebPreference(window, 'disableElectronSiteInstanceOverrides');
|
||||
const usesNativeWindowOpen = true;
|
||||
const guestInstanceId = getWebPreference(window, 'guestInstanceId') || null;
|
||||
const openerId = getWebPreference(window, 'openerId') || null;
|
||||
|
||||
switch (window.location.protocol) {
|
||||
case 'devtools:': {
|
||||
@@ -130,7 +136,7 @@ switch (window.location.protocol) {
|
||||
case 'chrome-extension:': {
|
||||
break;
|
||||
}
|
||||
case 'chrome:': {
|
||||
case 'chrome': {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -143,7 +149,7 @@ switch (window.location.protocol) {
|
||||
// Load webview tag implementation.
|
||||
if (process.isMainFrame) {
|
||||
const { webViewInit } = require('@electron/internal/renderer/web-view/web-view-init');
|
||||
webViewInit(contextIsolation, webviewTag, guestInstanceId);
|
||||
webViewInit(contextIsolation, isWebViewTagEnabled, guestInstanceId);
|
||||
}
|
||||
|
||||
// Wrap the script into a function executed in global scope. It won't have
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "13.0.0-nightly.20201126",
|
||||
"version": "12.0.0-beta.10",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -4,8 +4,6 @@ Date: Fri, 26 Jun 2020 11:06:12 -0700
|
||||
Subject: build: conditionally import EXT headers from framework or from
|
||||
relative path
|
||||
|
||||
This patch is required for building Squirrel from source code.
|
||||
|
||||
diff --git a/ReactiveObjC/NSControl+RACTextSignalSupport.m b/ReactiveObjC/NSControl+RACTextSignalSupport.m
|
||||
index 88da38f6e8117bbabdd898c8a1d4bde5e59deda7..483caea62eaaf26d9ad7d267a5c3e9aa44638ce7 100644
|
||||
--- a/ReactiveObjC/NSControl+RACTextSignalSupport.m
|
||||
|
||||
@@ -103,3 +103,5 @@ fix_use_electron_generated_resources.patch
|
||||
chore_expose_v8_initialization_isolate_callbacks.patch
|
||||
export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch
|
||||
use_public_apis_to_determine_if_a_font_is_a_system_font_in_mas_build.patch
|
||||
cherry-pick-47e21abe349a.patch
|
||||
fix_setparentacessibile_crash_win.patch
|
||||
|
||||
727
patches/chromium/cherry-pick-47e21abe349a.patch
Normal file
727
patches/chromium/cherry-pick-47e21abe349a.patch
Normal file
@@ -0,0 +1,727 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Robinson <mrobinson@igalia.com>
|
||||
Date: Thu, 19 Nov 2020 21:28:45 +0000
|
||||
Subject: Improve AXTextStateChangeType in
|
||||
NSAccessibilitySelectedTextChangedNotification
|
||||
|
||||
When setting the AXTextStateChangeType key in the user info data
|
||||
structure for the notification, use AXTextStateChangeTypeSelectionMove
|
||||
when we detect a focus change. This causes VoiceOver to properly
|
||||
announce the label and type of form entries when their contents are
|
||||
selected due to focus changes.
|
||||
|
||||
type are now announced.
|
||||
|
||||
Bug: 1127421
|
||||
Change-Id: I42d66ad60fbcba7c8c34396fdbc3f6e0c739d1a2
|
||||
AX-Relnotes: When focus changes moves to form inputs, the input label and
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2512913
|
||||
Commit-Queue: Martin Robinson <mrobinson@igalia.com>
|
||||
Reviewed-by: Nektarios Paisios <nektar@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#829380}
|
||||
|
||||
diff --git a/content/browser/accessibility/accessibility_event_recorder_mac.mm b/content/browser/accessibility/accessibility_event_recorder_mac.mm
|
||||
index 6efa579decbfef81ddd38b27696133f7f68673ee..cdf4f8f87cf1554044e698f8b85c0f8a28a741e8 100644
|
||||
--- a/content/browser/accessibility/accessibility_event_recorder_mac.mm
|
||||
+++ b/content/browser/accessibility/accessibility_event_recorder_mac.mm
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
+#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "base/logging.h"
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "content/browser/accessibility/accessibility_tools_utils_mac.h"
|
||||
#include "content/browser/accessibility/browser_accessibility_manager.h"
|
||||
+#include "ui/accessibility/platform/ax_private_webkit_constants_mac.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
@@ -28,7 +30,11 @@
|
||||
~AccessibilityEventRecorderMac() override;
|
||||
|
||||
// Callback executed every time we receive an event notification.
|
||||
- void EventReceived(AXUIElementRef element, CFStringRef notification);
|
||||
+ void EventReceived(AXUIElementRef element,
|
||||
+ CFStringRef notification,
|
||||
+ CFDictionaryRef user_info);
|
||||
+ static std::string SerializeTextSelectionChangedProperties(
|
||||
+ CFDictionaryRef user_info);
|
||||
|
||||
private:
|
||||
// Add one notification to the list of notifications monitored by our
|
||||
@@ -54,10 +60,11 @@
|
||||
static void EventReceivedThunk(AXObserverRef observer_ref,
|
||||
AXUIElementRef element,
|
||||
CFStringRef notification,
|
||||
+ CFDictionaryRef user_info,
|
||||
void* refcon) {
|
||||
AccessibilityEventRecorderMac* this_ptr =
|
||||
static_cast<AccessibilityEventRecorderMac*>(refcon);
|
||||
- this_ptr->EventReceived(element, notification);
|
||||
+ this_ptr->EventReceived(element, notification, user_info);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -95,8 +102,9 @@ static void EventReceivedThunk(AXObserverRef observer_ref,
|
||||
base::ProcessId pid,
|
||||
AXUIElementRef node)
|
||||
: AccessibilityEventRecorder(manager), observer_run_loop_source_(NULL) {
|
||||
- if (kAXErrorSuccess != AXObserverCreate(pid, EventReceivedThunk,
|
||||
- observer_ref_.InitializeInto())) {
|
||||
+ if (kAXErrorSuccess !=
|
||||
+ AXObserverCreateWithInfoCallback(pid, EventReceivedThunk,
|
||||
+ observer_ref_.InitializeInto())) {
|
||||
LOG(FATAL) << "Failed to create AXObserverRef";
|
||||
}
|
||||
|
||||
@@ -157,7 +165,8 @@ static void EventReceivedThunk(AXObserverRef observer_ref,
|
||||
}
|
||||
|
||||
void AccessibilityEventRecorderMac::EventReceived(AXUIElementRef element,
|
||||
- CFStringRef notification) {
|
||||
+ CFStringRef notification,
|
||||
+ CFDictionaryRef user_info) {
|
||||
std::string notification_str = base::SysCFStringRefToUTF8(notification);
|
||||
std::string role = GetAXAttributeValue(element, NSAccessibilityRoleAttribute);
|
||||
if (role.empty())
|
||||
@@ -180,7 +189,49 @@ static void EventReceivedThunk(AXObserverRef observer_ref,
|
||||
if (!value.empty())
|
||||
log += base::StringPrintf(" AXValue=\"%s\"", value.c_str());
|
||||
|
||||
+ if (notification_str ==
|
||||
+ base::SysNSStringToUTF8(NSAccessibilitySelectedTextChangedNotification))
|
||||
+ log += " " + SerializeTextSelectionChangedProperties(user_info);
|
||||
+
|
||||
OnEvent(log);
|
||||
}
|
||||
|
||||
+std::string
|
||||
+AccessibilityEventRecorderMac::SerializeTextSelectionChangedProperties(
|
||||
+ CFDictionaryRef user_info) {
|
||||
+ std::vector<std::string> serialized_info;
|
||||
+ CFDictionaryApplyFunction(
|
||||
+ user_info,
|
||||
+ [](const void* raw_key, const void* raw_value, void* context) {
|
||||
+ auto* key = static_cast<NSString*>(raw_key);
|
||||
+ auto* value = static_cast<NSObject*>(raw_value);
|
||||
+ auto* serialized_info = static_cast<std::vector<std::string>*>(context);
|
||||
+ std::string value_string;
|
||||
+ if ([key isEqual:ui::NSAccessibilityTextStateChangeTypeKey]) {
|
||||
+ value_string = ToString(static_cast<ui::AXTextStateChangeType>(
|
||||
+ [static_cast<NSNumber*>(value) intValue]));
|
||||
+ } else if ([key isEqual:ui::NSAccessibilityTextSelectionDirection]) {
|
||||
+ value_string = ToString(static_cast<ui::AXTextSelectionDirection>(
|
||||
+ [static_cast<NSNumber*>(value) intValue]));
|
||||
+ } else if ([key isEqual:ui::NSAccessibilityTextSelectionGranularity]) {
|
||||
+ value_string = ToString(static_cast<ui::AXTextSelectionGranularity>(
|
||||
+ [static_cast<NSNumber*>(value) intValue]));
|
||||
+ } else if ([key isEqual:ui::NSAccessibilityTextEditType]) {
|
||||
+ value_string = ToString(static_cast<ui::AXTextEditType>(
|
||||
+ [static_cast<NSNumber*>(value) intValue]));
|
||||
+ } else {
|
||||
+ return;
|
||||
+ }
|
||||
+ serialized_info->push_back(base::SysNSStringToUTF8(key) + "=" +
|
||||
+ value_string);
|
||||
+ },
|
||||
+ &serialized_info);
|
||||
+
|
||||
+ // Always sort the info so that we don't depend on CFDictionary for
|
||||
+ // consistent output ordering.
|
||||
+ std::sort(serialized_info.begin(), serialized_info.end());
|
||||
+
|
||||
+ return base::JoinString(serialized_info, " ");
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.h b/content/browser/accessibility/browser_accessibility_manager_mac.h
|
||||
index b4043f56341e72bcf75ef71c56cb8cf9fc442579..925bfe1ea191ab846805fdbff1b0314e779b1c9e 100644
|
||||
--- a/content/browser/accessibility/browser_accessibility_manager_mac.h
|
||||
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.h
|
||||
@@ -54,7 +54,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
|
||||
const std::vector<Change>& changes) override;
|
||||
|
||||
// Returns an autoreleased object.
|
||||
- NSDictionary* GetUserInfoForSelectedTextChangedNotification();
|
||||
+ NSDictionary* GetUserInfoForSelectedTextChangedNotification(
|
||||
+ bool focus_changed);
|
||||
|
||||
// Returns an autoreleased object.
|
||||
NSDictionary* GetUserInfoForValueChangedNotification(
|
||||
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
|
||||
index 122e517ddcb3944847fc289eb45c87d5fb156afc..5a2b73f664646efc0bc8e506e93b179b8e96635a 100644
|
||||
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
|
||||
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
|
||||
@@ -19,91 +19,13 @@
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
#include "ui/accessibility/ax_role_properties.h"
|
||||
+#include "ui/accessibility/platform/ax_private_webkit_constants_mac.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Use same value as in Safari's WebKit.
|
||||
const int kLiveRegionChangeIntervalMS = 20;
|
||||
|
||||
-// Declare undocumented accessibility constants and enums only present in
|
||||
-// WebKit.
|
||||
-
|
||||
-enum AXTextStateChangeType {
|
||||
- AXTextStateChangeTypeUnknown,
|
||||
- AXTextStateChangeTypeEdit,
|
||||
- AXTextStateChangeTypeSelectionMove,
|
||||
- AXTextStateChangeTypeSelectionExtend
|
||||
-};
|
||||
-
|
||||
-enum AXTextSelectionDirection {
|
||||
- AXTextSelectionDirectionUnknown,
|
||||
- AXTextSelectionDirectionBeginning,
|
||||
- AXTextSelectionDirectionEnd,
|
||||
- AXTextSelectionDirectionPrevious,
|
||||
- AXTextSelectionDirectionNext,
|
||||
- AXTextSelectionDirectionDiscontiguous
|
||||
-};
|
||||
-
|
||||
-enum AXTextSelectionGranularity {
|
||||
- AXTextSelectionGranularityUnknown,
|
||||
- AXTextSelectionGranularityCharacter,
|
||||
- AXTextSelectionGranularityWord,
|
||||
- AXTextSelectionGranularityLine,
|
||||
- AXTextSelectionGranularitySentence,
|
||||
- AXTextSelectionGranularityParagraph,
|
||||
- AXTextSelectionGranularityPage,
|
||||
- AXTextSelectionGranularityDocument,
|
||||
- AXTextSelectionGranularityAll
|
||||
-};
|
||||
-
|
||||
-enum AXTextEditType {
|
||||
- AXTextEditTypeUnknown,
|
||||
- AXTextEditTypeDelete,
|
||||
- AXTextEditTypeInsert,
|
||||
- AXTextEditTypeTyping,
|
||||
- AXTextEditTypeDictation,
|
||||
- AXTextEditTypeCut,
|
||||
- AXTextEditTypePaste,
|
||||
- AXTextEditTypeAttributesChange
|
||||
-};
|
||||
-
|
||||
-// Native mac notifications fired.
|
||||
-NSString* const NSAccessibilityAutocorrectionOccurredNotification =
|
||||
- @"AXAutocorrectionOccurred";
|
||||
-NSString* const NSAccessibilityLoadCompleteNotification = @"AXLoadComplete";
|
||||
-NSString* const NSAccessibilityInvalidStatusChangedNotification =
|
||||
- @"AXInvalidStatusChanged";
|
||||
-NSString* const NSAccessibilityLiveRegionCreatedNotification =
|
||||
- @"AXLiveRegionCreated";
|
||||
-NSString* const NSAccessibilityLiveRegionChangedNotification =
|
||||
- @"AXLiveRegionChanged";
|
||||
-NSString* const NSAccessibilityExpandedChanged = @"AXExpandedChanged";
|
||||
-NSString* const NSAccessibilityMenuItemSelectedNotification =
|
||||
- @"AXMenuItemSelected";
|
||||
-
|
||||
-// The following native mac notifications are not fired:
|
||||
-// AXLayoutComplete: Voiceover does not use this, it is considered too spammy.
|
||||
-
|
||||
-// Attributes used for NSAccessibilitySelectedTextChangedNotification and
|
||||
-// NSAccessibilityValueChangedNotification.
|
||||
-NSString* const NSAccessibilityTextStateChangeTypeKey =
|
||||
- @"AXTextStateChangeType";
|
||||
-NSString* const NSAccessibilityTextStateSyncKey = @"AXTextStateSync";
|
||||
-NSString* const NSAccessibilityTextSelectionDirection =
|
||||
- @"AXTextSelectionDirection";
|
||||
-NSString* const NSAccessibilityTextSelectionGranularity =
|
||||
- @"AXTextSelectionGranularity";
|
||||
-NSString* const NSAccessibilityTextSelectionChangedFocus =
|
||||
- @"AXTextSelectionChangedFocus";
|
||||
-NSString* const NSAccessibilityTextChangeElement = @"AXTextChangeElement";
|
||||
-NSString* const NSAccessibilityTextEditType = @"AXTextEditType";
|
||||
-NSString* const NSAccessibilityTextChangeValue = @"AXTextChangeValue";
|
||||
-NSString* const NSAccessibilityChangeValueStartMarker =
|
||||
- @"AXTextChangeValueStartMarker";
|
||||
-NSString* const NSAccessibilityTextChangeValueLength =
|
||||
- @"AXTextChangeValueLength";
|
||||
-NSString* const NSAccessibilityTextChangeValues = @"AXTextChangeValues";
|
||||
-
|
||||
} // namespace
|
||||
|
||||
namespace content {
|
||||
@@ -164,7 +86,7 @@
|
||||
NSString* mac_notification = nullptr;
|
||||
switch (event_type) {
|
||||
case ax::mojom::Event::kAutocorrectionOccured:
|
||||
- mac_notification = NSAccessibilityAutocorrectionOccurredNotification;
|
||||
+ mac_notification = ui::NSAccessibilityAutocorrectionOccurredNotification;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -203,6 +125,8 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
auto native_node = ToBrowserAccessibilityCocoa(node);
|
||||
DCHECK(native_node);
|
||||
|
||||
+ bool focus_changed = GetFocus() != GetLastFocusedNode();
|
||||
+
|
||||
// Refer to |AXObjectCache::postPlatformNotification| in WebKit source code.
|
||||
NSString* mac_notification = nullptr;
|
||||
switch (event_type) {
|
||||
@@ -223,7 +147,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
break;
|
||||
case ui::AXEventGenerator::Event::ALERT:
|
||||
NSAccessibilityPostNotification(
|
||||
- native_node, NSAccessibilityLiveRegionCreatedNotification);
|
||||
+ native_node, ui::NSAccessibilityLiveRegionCreatedNotification);
|
||||
// Voiceover requires a live region changed notification to actually
|
||||
// announce the live region.
|
||||
FireGeneratedEvent(ui::AXEventGenerator::Event::LIVE_REGION_CHANGED,
|
||||
@@ -242,7 +166,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
node->GetRole() == ax::mojom::Role::kTreeItem) {
|
||||
mac_notification = NSAccessibilityRowCollapsedNotification;
|
||||
} else {
|
||||
- mac_notification = NSAccessibilityExpandedChanged;
|
||||
+ mac_notification = ui::NSAccessibilityExpandedChanged;
|
||||
}
|
||||
break;
|
||||
case ui::AXEventGenerator::Event::DOCUMENT_SELECTION_CHANGED: {
|
||||
@@ -259,7 +183,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
// API has been present on versions of OS X since 10.7 but doesn't
|
||||
// appear to be needed by Voiceover before version 10.11.
|
||||
NSDictionary* user_info =
|
||||
- GetUserInfoForSelectedTextChangedNotification();
|
||||
+ GetUserInfoForSelectedTextChangedNotification(focus_changed);
|
||||
|
||||
BrowserAccessibilityManager* root_manager = GetRootManager();
|
||||
if (!root_manager)
|
||||
@@ -284,11 +208,11 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
node->GetRole() == ax::mojom::Role::kTreeItem) {
|
||||
mac_notification = NSAccessibilityRowExpandedNotification;
|
||||
} else {
|
||||
- mac_notification = NSAccessibilityExpandedChanged;
|
||||
+ mac_notification = ui::NSAccessibilityExpandedChanged;
|
||||
}
|
||||
break;
|
||||
case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
|
||||
- mac_notification = NSAccessibilityInvalidStatusChangedNotification;
|
||||
+ mac_notification = ui::NSAccessibilityInvalidStatusChangedNotification;
|
||||
break;
|
||||
case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED: {
|
||||
// Voiceover seems to drop live region changed notifications if they come
|
||||
@@ -297,7 +221,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
|
||||
if (never_suppress_or_delay_events_for_testing_) {
|
||||
NSAccessibilityPostNotification(
|
||||
- native_node, NSAccessibilityLiveRegionChangedNotification);
|
||||
+ native_node, ui::NSAccessibilityLiveRegionChangedNotification);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -321,7 +245,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
[](base::scoped_nsobject<BrowserAccessibilityCocoa> node) {
|
||||
if (node && [node instanceActive]) {
|
||||
NSAccessibilityPostNotification(
|
||||
- node, NSAccessibilityLiveRegionChangedNotification);
|
||||
+ node, ui::NSAccessibilityLiveRegionChangedNotification);
|
||||
}
|
||||
},
|
||||
std::move(retained_node)),
|
||||
@@ -329,7 +253,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
return;
|
||||
}
|
||||
case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
|
||||
- mac_notification = NSAccessibilityLiveRegionCreatedNotification;
|
||||
+ mac_notification = ui::NSAccessibilityLiveRegionCreatedNotification;
|
||||
break;
|
||||
case ui::AXEventGenerator::Event::LOAD_COMPLETE:
|
||||
// On MacOS 10.15, firing AXLoadComplete causes focus to move to the
|
||||
@@ -343,7 +267,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
// |NSAccessibilityLoadCompleteNotification| should only be fired on the
|
||||
// top document and when the document is not Chrome's new tab page.
|
||||
if (IsRootTree() && !IsChromeNewTabPage()) {
|
||||
- mac_notification = NSAccessibilityLoadCompleteNotification;
|
||||
+ mac_notification = ui::NSAccessibilityLoadCompleteNotification;
|
||||
} else {
|
||||
// Voiceover moves focus to the web content when it receives an
|
||||
// AXLoadComplete event. On Chrome's new tab page, focus should stay
|
||||
@@ -353,7 +277,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
}
|
||||
break;
|
||||
case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
|
||||
- mac_notification = NSAccessibilityMenuItemSelectedNotification;
|
||||
+ mac_notification = ui::NSAccessibilityMenuItemSelectedNotification;
|
||||
break;
|
||||
case ui::AXEventGenerator::Event::RANGE_VALUE_CHANGED:
|
||||
DCHECK(node->GetData().IsRangeValueSupported());
|
||||
@@ -532,18 +456,32 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
}
|
||||
}
|
||||
|
||||
-NSDictionary* BrowserAccessibilityManagerMac::
|
||||
- GetUserInfoForSelectedTextChangedNotification() {
|
||||
+NSDictionary*
|
||||
+BrowserAccessibilityManagerMac::GetUserInfoForSelectedTextChangedNotification(
|
||||
+ bool focus_changed) {
|
||||
NSMutableDictionary* user_info =
|
||||
[[[NSMutableDictionary alloc] init] autorelease];
|
||||
- [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey];
|
||||
- [user_info setObject:@(AXTextStateChangeTypeUnknown)
|
||||
- forKey:NSAccessibilityTextStateChangeTypeKey];
|
||||
- [user_info setObject:@(AXTextSelectionDirectionUnknown)
|
||||
- forKey:NSAccessibilityTextSelectionDirection];
|
||||
- [user_info setObject:@(AXTextSelectionGranularityUnknown)
|
||||
- forKey:NSAccessibilityTextSelectionGranularity];
|
||||
- [user_info setObject:@YES forKey:NSAccessibilityTextSelectionChangedFocus];
|
||||
+ [user_info setObject:@YES forKey:ui::NSAccessibilityTextStateSyncKey];
|
||||
+ [user_info setObject:@(ui::AXTextSelectionDirectionUnknown)
|
||||
+ forKey:ui::NSAccessibilityTextSelectionDirection];
|
||||
+ [user_info setObject:@(ui::AXTextSelectionGranularityUnknown)
|
||||
+ forKey:ui::NSAccessibilityTextSelectionGranularity];
|
||||
+ [user_info setObject:@YES
|
||||
+ forKey:ui::NSAccessibilityTextSelectionChangedFocus];
|
||||
+
|
||||
+ // Try to detect when the text selection changes due to a focus change.
|
||||
+ // This is necessary so that VoiceOver also anounces information about the
|
||||
+ // element that contains this selection.
|
||||
+ // TODO(mrobinson): Determine definitively what the type of this text
|
||||
+ // selection change is. This requires passing this information here from
|
||||
+ // blink.
|
||||
+ if (focus_changed) {
|
||||
+ [user_info setObject:@(ui::AXTextStateChangeTypeSelectionMove)
|
||||
+ forKey:ui::NSAccessibilityTextStateChangeTypeKey];
|
||||
+ } else {
|
||||
+ [user_info setObject:@(ui::AXTextStateChangeTypeUnknown)
|
||||
+ forKey:ui::NSAccessibilityTextStateChangeTypeKey];
|
||||
+ }
|
||||
|
||||
int32_t focus_id = ax_tree()->GetUnignoredSelection().focus_object_id;
|
||||
BrowserAccessibility* focus_object = GetFromID(focus_id);
|
||||
@@ -552,7 +490,7 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
auto native_focus_object = ToBrowserAccessibilityCocoa(focus_object);
|
||||
if (native_focus_object && [native_focus_object instanceActive]) {
|
||||
[user_info setObject:native_focus_object
|
||||
- forKey:NSAccessibilityTextChangeElement];
|
||||
+ forKey:ui::NSAccessibilityTextChangeElement];
|
||||
|
||||
#ifndef MAS_BUILD
|
||||
id selected_text = [native_focus_object selectedTextMarkerRange];
|
||||
@@ -583,38 +521,39 @@ void PostAnnouncementNotification(NSString* announcement) {
|
||||
if (!deleted_text.empty()) {
|
||||
NSMutableDictionary* change =
|
||||
[NSMutableDictionary dictionaryWithDictionary:@{
|
||||
- NSAccessibilityTextEditType : @(AXTextEditTypeDelete),
|
||||
- NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
|
||||
- NSAccessibilityTextChangeValue :
|
||||
+ ui::NSAccessibilityTextEditType : @(ui::AXTextEditTypeDelete),
|
||||
+ ui::NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
|
||||
+ ui::NSAccessibilityTextChangeValue :
|
||||
base::SysUTF16ToNSString(deleted_text)
|
||||
}];
|
||||
if (edit_text_marker) {
|
||||
- change[NSAccessibilityChangeValueStartMarker] = edit_text_marker;
|
||||
+ change[ui::NSAccessibilityChangeValueStartMarker] = edit_text_marker;
|
||||
}
|
||||
[changes addObject:change];
|
||||
}
|
||||
if (!inserted_text.empty()) {
|
||||
// TODO(nektar): Figure out if this is a paste, insertion or typing.
|
||||
// Changes to Blink would be required. A heuristic is currently used.
|
||||
- auto edit_type = inserted_text.length() > 1 ? @(AXTextEditTypeInsert)
|
||||
- : @(AXTextEditTypeTyping);
|
||||
+ auto edit_type = inserted_text.length() > 1 ? @(ui::AXTextEditTypeInsert)
|
||||
+ : @(ui::AXTextEditTypeTyping);
|
||||
NSMutableDictionary* change =
|
||||
[NSMutableDictionary dictionaryWithDictionary:@{
|
||||
- NSAccessibilityTextEditType : edit_type,
|
||||
- NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
|
||||
- NSAccessibilityTextChangeValue :
|
||||
+ ui::NSAccessibilityTextEditType : edit_type,
|
||||
+ ui::NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
|
||||
+ ui::NSAccessibilityTextChangeValue :
|
||||
base::SysUTF16ToNSString(inserted_text)
|
||||
}];
|
||||
if (edit_text_marker) {
|
||||
- change[NSAccessibilityChangeValueStartMarker] = edit_text_marker;
|
||||
+ change[ui::NSAccessibilityChangeValueStartMarker] = edit_text_marker;
|
||||
}
|
||||
[changes addObject:change];
|
||||
}
|
||||
|
||||
return @{
|
||||
- NSAccessibilityTextStateChangeTypeKey : @(AXTextStateChangeTypeEdit),
|
||||
- NSAccessibilityTextChangeValues : changes,
|
||||
- NSAccessibilityTextChangeElement : native_node
|
||||
+ ui::
|
||||
+ NSAccessibilityTextStateChangeTypeKey : @(ui::AXTextStateChangeTypeEdit),
|
||||
+ ui::NSAccessibilityTextChangeValues : changes,
|
||||
+ ui::NSAccessibilityTextChangeElement : native_node
|
||||
};
|
||||
}
|
||||
|
||||
diff --git a/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt b/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt
|
||||
index ad5e2bf2c8029185c51eecc94cac1dbe7608c99e..67e07a89f77f7c61a57eb51cecea211df5227341 100644
|
||||
--- a/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt
|
||||
+++ b/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt
|
||||
@@ -1,3 +1,3 @@
|
||||
AXFocusedUIElementChanged on AXStaticText AXValue="Apple not selected"
|
||||
-AXSelectedTextChanged on AXStaticText AXValue="Apple not selected"
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
\ No newline at end of file
|
||||
+AXSelectedTextChanged on AXStaticText AXValue="Apple not selected" AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
|
||||
diff --git a/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt b/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt
|
||||
index ec0b74d984ade9928705242f9b0682a743e20fb2..87447c5a4b14efde5b64b1d340a3fa2fb6574b80 100644
|
||||
--- a/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt
|
||||
+++ b/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt
|
||||
@@ -1,5 +1,5 @@
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
=== Start Continuation ===
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
diff --git a/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt b/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt
|
||||
index ec0b74d984ade9928705242f9b0682a743e20fb2..87447c5a4b14efde5b64b1d340a3fa2fb6574b80 100644
|
||||
--- a/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt
|
||||
+++ b/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt
|
||||
@@ -1,5 +1,5 @@
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
=== Start Continuation ===
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
-AXSelectedTextChanged on AXWebArea
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
diff --git a/content/test/data/accessibility/event/text-selection-changed-expected-mac.txt b/content/test/data/accessibility/event/text-selection-changed-expected-mac.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9213c873393d595bba8796cdb0e2325d3ee37ee9
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/accessibility/event/text-selection-changed-expected-mac.txt
|
||||
@@ -0,0 +1,10 @@
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
|
||||
+=== Start Continuation ===
|
||||
+AXFocusedUIElementChanged on AXTextField AXDescription="input" AXValue="input"
|
||||
+AXSelectedTextChanged on AXTextField AXDescription="input" AXValue="input" AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
|
||||
+=== Start Continuation ===
|
||||
+AXFocusedUIElementChanged on AXTextArea AXDescription="textarea"
|
||||
+AXSelectedTextChanged on AXTextArea AXDescription="textarea" AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
|
||||
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
|
||||
diff --git a/ui/accessibility/platform/BUILD.gn b/ui/accessibility/platform/BUILD.gn
|
||||
index 99df759347f899a78dc37846e30598f82edb34f7..47d57fcf7aa02b5b2c5afab18a96666dda3b79bb 100644
|
||||
--- a/ui/accessibility/platform/BUILD.gn
|
||||
+++ b/ui/accessibility/platform/BUILD.gn
|
||||
@@ -118,6 +118,8 @@ source_set("platform") {
|
||||
"ax_event_intent_mac.mm",
|
||||
"ax_platform_node_mac.h",
|
||||
"ax_platform_node_mac.mm",
|
||||
+ "ax_private_webkit_constants_mac.h",
|
||||
+ "ax_private_webkit_constants_mac.mm",
|
||||
]
|
||||
|
||||
frameworks = [
|
||||
diff --git a/ui/accessibility/platform/ax_private_webkit_constants_mac.h b/ui/accessibility/platform/ax_private_webkit_constants_mac.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5f1776a3aeac89b70d6d852b8e5209a1208271ae
|
||||
--- /dev/null
|
||||
+++ b/ui/accessibility/platform/ax_private_webkit_constants_mac.h
|
||||
@@ -0,0 +1,96 @@
|
||||
+// Copyright 2020 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#ifndef UI_ACCESSIBILITY_PLATFORM_AX_PRIVATE_WEBKIT_CONSTANTS_MAC_H_
|
||||
+#define UI_ACCESSIBILITY_PLATFORM_AX_PRIVATE_WEBKIT_CONSTANTS_MAC_H_
|
||||
+
|
||||
+#import <Cocoa/Cocoa.h>
|
||||
+#include "ui/accessibility/ax_export.h"
|
||||
+
|
||||
+namespace ui {
|
||||
+
|
||||
+enum AXTextStateChangeType {
|
||||
+ AXTextStateChangeTypeUnknown,
|
||||
+ AXTextStateChangeTypeEdit,
|
||||
+ AXTextStateChangeTypeSelectionMove,
|
||||
+ AXTextStateChangeTypeSelectionExtend
|
||||
+};
|
||||
+
|
||||
+enum AXTextSelectionDirection {
|
||||
+ AXTextSelectionDirectionUnknown,
|
||||
+ AXTextSelectionDirectionBeginning,
|
||||
+ AXTextSelectionDirectionEnd,
|
||||
+ AXTextSelectionDirectionPrevious,
|
||||
+ AXTextSelectionDirectionNext,
|
||||
+ AXTextSelectionDirectionDiscontiguous
|
||||
+};
|
||||
+
|
||||
+enum AXTextSelectionGranularity {
|
||||
+ AXTextSelectionGranularityUnknown,
|
||||
+ AXTextSelectionGranularityCharacter,
|
||||
+ AXTextSelectionGranularityWord,
|
||||
+ AXTextSelectionGranularityLine,
|
||||
+ AXTextSelectionGranularitySentence,
|
||||
+ AXTextSelectionGranularityParagraph,
|
||||
+ AXTextSelectionGranularityPage,
|
||||
+ AXTextSelectionGranularityDocument,
|
||||
+ AXTextSelectionGranularityAll
|
||||
+};
|
||||
+
|
||||
+enum AXTextEditType {
|
||||
+ AXTextEditTypeUnknown,
|
||||
+ AXTextEditTypeDelete,
|
||||
+ AXTextEditTypeInsert,
|
||||
+ AXTextEditTypeTyping,
|
||||
+ AXTextEditTypeDictation,
|
||||
+ AXTextEditTypeCut,
|
||||
+ AXTextEditTypePaste,
|
||||
+ AXTextEditTypeAttributesChange
|
||||
+};
|
||||
+
|
||||
+// Native mac notifications fired.
|
||||
+NSString* const NSAccessibilityAutocorrectionOccurredNotification =
|
||||
+ @"AXAutocorrectionOccurred";
|
||||
+NSString* const NSAccessibilityLoadCompleteNotification = @"AXLoadComplete";
|
||||
+NSString* const NSAccessibilityInvalidStatusChangedNotification =
|
||||
+ @"AXInvalidStatusChanged";
|
||||
+NSString* const NSAccessibilityLiveRegionCreatedNotification =
|
||||
+ @"AXLiveRegionCreated";
|
||||
+NSString* const NSAccessibilityLiveRegionChangedNotification =
|
||||
+ @"AXLiveRegionChanged";
|
||||
+NSString* const NSAccessibilityExpandedChanged = @"AXExpandedChanged";
|
||||
+NSString* const NSAccessibilityMenuItemSelectedNotification =
|
||||
+ @"AXMenuItemSelected";
|
||||
+
|
||||
+// The following native mac notifications are not fired:
|
||||
+// AXLayoutComplete: Voiceover does not use this, it is considered too spammy.
|
||||
+
|
||||
+// Attributes used for NSAccessibilitySelectedTextChangedNotification and
|
||||
+// NSAccessibilityValueChangedNotification.
|
||||
+NSString* const NSAccessibilityTextStateChangeTypeKey =
|
||||
+ @"AXTextStateChangeType";
|
||||
+NSString* const NSAccessibilityTextStateSyncKey = @"AXTextStateSync";
|
||||
+NSString* const NSAccessibilityTextSelectionDirection =
|
||||
+ @"AXTextSelectionDirection";
|
||||
+NSString* const NSAccessibilityTextSelectionGranularity =
|
||||
+ @"AXTextSelectionGranularity";
|
||||
+NSString* const NSAccessibilityTextSelectionChangedFocus =
|
||||
+ @"AXTextSelectionChangedFocus";
|
||||
+NSString* const NSAccessibilityTextChangeElement = @"AXTextChangeElement";
|
||||
+NSString* const NSAccessibilityTextEditType = @"AXTextEditType";
|
||||
+NSString* const NSAccessibilityTextChangeValue = @"AXTextChangeValue";
|
||||
+NSString* const NSAccessibilityChangeValueStartMarker =
|
||||
+ @"AXTextChangeValueStartMarker";
|
||||
+NSString* const NSAccessibilityTextChangeValueLength =
|
||||
+ @"AXTextChangeValueLength";
|
||||
+NSString* const NSAccessibilityTextChangeValues = @"AXTextChangeValues";
|
||||
+
|
||||
+AX_EXPORT const char* ToString(AXTextStateChangeType);
|
||||
+AX_EXPORT const char* ToString(AXTextSelectionDirection);
|
||||
+AX_EXPORT const char* ToString(AXTextSelectionGranularity);
|
||||
+AX_EXPORT const char* ToString(AXTextEditType);
|
||||
+
|
||||
+} // namespace ui
|
||||
+
|
||||
+#endif // UI_ACCESSIBILITY_PLATFORM_AX_PRIVATE_WEBKIT_CONSTANTS_MAC_H_
|
||||
diff --git a/ui/accessibility/platform/ax_private_webkit_constants_mac.mm b/ui/accessibility/platform/ax_private_webkit_constants_mac.mm
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7de31a487dd6e0e6a4af2f4fa62e463f41a0d96a
|
||||
--- /dev/null
|
||||
+++ b/ui/accessibility/platform/ax_private_webkit_constants_mac.mm
|
||||
@@ -0,0 +1,91 @@
|
||||
+// Copyright 2020 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "ui/accessibility/platform/ax_private_webkit_constants_mac.h"
|
||||
+
|
||||
+namespace ui {
|
||||
+
|
||||
+const char* ToString(AXTextStateChangeType type) {
|
||||
+ switch (type) {
|
||||
+ case AXTextStateChangeTypeUnknown:
|
||||
+ return "AXTextStateChangeTypeUnknown";
|
||||
+ case AXTextStateChangeTypeEdit:
|
||||
+ return "AXTextStateChangeTypeEdit";
|
||||
+ case AXTextStateChangeTypeSelectionMove:
|
||||
+ return "AXTextStateChangeTypeSelectionMove";
|
||||
+ case AXTextStateChangeTypeSelectionExtend:
|
||||
+ return "AXTextStateChangeTypeSelectionExtend";
|
||||
+ }
|
||||
+
|
||||
+ return "";
|
||||
+}
|
||||
+
|
||||
+const char* ToString(AXTextSelectionDirection direction) {
|
||||
+ switch (direction) {
|
||||
+ case AXTextSelectionDirectionUnknown:
|
||||
+ return "AXTextSelectionDirectionUnknown";
|
||||
+ case AXTextSelectionDirectionBeginning:
|
||||
+ return "AXTextSelectionDirectionBeginning";
|
||||
+ case AXTextSelectionDirectionEnd:
|
||||
+ return "AXTextSelectionDirectionEnd";
|
||||
+ case AXTextSelectionDirectionPrevious:
|
||||
+ return "AXTextSelectionDirectionPrevious";
|
||||
+ case AXTextSelectionDirectionNext:
|
||||
+ return "AXTextSelectionDirectionNext";
|
||||
+ case AXTextSelectionDirectionDiscontiguous:
|
||||
+ return "AXTextSelectionDirectionDiscontiguous";
|
||||
+ }
|
||||
+
|
||||
+ return "";
|
||||
+}
|
||||
+
|
||||
+const char* ToString(AXTextSelectionGranularity granularity) {
|
||||
+ switch (granularity) {
|
||||
+ case AXTextSelectionGranularityUnknown:
|
||||
+ return "AXTextSelectionGranularityUnknown";
|
||||
+ case AXTextSelectionGranularityCharacter:
|
||||
+ return "AXTextSelectionGranularityCharacter";
|
||||
+ case AXTextSelectionGranularityWord:
|
||||
+ return "AXTextSelectionGranularityWord";
|
||||
+ case AXTextSelectionGranularityLine:
|
||||
+ return "AXTextSelectionGranularityLine";
|
||||
+ case AXTextSelectionGranularitySentence:
|
||||
+ return "AXTextSelectionGranularitySentence";
|
||||
+ case AXTextSelectionGranularityParagraph:
|
||||
+ return "AXTextSelectionGranularityParagraph";
|
||||
+ case AXTextSelectionGranularityPage:
|
||||
+ return "AXTextSelectionGranularityPage";
|
||||
+ case AXTextSelectionGranularityDocument:
|
||||
+ return "AXTextSelectionGranularityDocument";
|
||||
+ case AXTextSelectionGranularityAll:
|
||||
+ return "AXTextSelectionGranularityAll";
|
||||
+ }
|
||||
+
|
||||
+ return "";
|
||||
+}
|
||||
+
|
||||
+const char* ToString(AXTextEditType type) {
|
||||
+ switch (type) {
|
||||
+ case AXTextEditTypeUnknown:
|
||||
+ return "AXTextEditTypeUnknown";
|
||||
+ case AXTextEditTypeDelete:
|
||||
+ return "AXTextEditTypeDelete";
|
||||
+ case AXTextEditTypeInsert:
|
||||
+ return "AXTextEditTypeInsert";
|
||||
+ case AXTextEditTypeTyping:
|
||||
+ return "AXTextEditTypeTyping";
|
||||
+ case AXTextEditTypeDictation:
|
||||
+ return "AXTextEditTypeDictation";
|
||||
+ case AXTextEditTypeCut:
|
||||
+ return "AXTextEditTypeCut";
|
||||
+ case AXTextEditTypePaste:
|
||||
+ return "AXTextEditTypePaste";
|
||||
+ case AXTextEditTypeAttributesChange:
|
||||
+ return "AXTextEditTypeAttributesChange";
|
||||
+ }
|
||||
+
|
||||
+ return "";
|
||||
+}
|
||||
+
|
||||
+} // namespace ui
|
||||
@@ -4,8 +4,6 @@ Date: Sun, 1 Mar 2020 16:33:55 -0800
|
||||
Subject: feat: allow embedders to add observers on created hunspell
|
||||
dictionaries
|
||||
|
||||
This patch is used by Electron to implement spellchecker events.
|
||||
|
||||
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc
|
||||
index 09256573b848bbb248530f77619df47ddbeb8a0e..75b70e375ed1d680cbd2fba1ca73a4e2e5403fb6 100644
|
||||
--- a/chrome/browser/spellchecker/spellcheck_service.cc
|
||||
|
||||
28
patches/chromium/fix_setparentacessibile_crash_win.patch
Normal file
28
patches/chromium/fix_setparentacessibile_crash_win.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Biru Mohanathas <birunthan@mohanathas.com>
|
||||
Date: Thu, 10 Dec 2020 19:02:37 +0200
|
||||
Subject: fix crash in NativeViewHost::SetParentAccessible
|
||||
|
||||
This fixes random crashes on Windows 10. It presumably started happening
|
||||
after the changes in
|
||||
https://chromium.googlesource.com/chromium/src.git/+/5c6c8e994bce2bfb867279ae5068e9f9134e70c3%5E!/#F15
|
||||
|
||||
For context, see: https://github.com/electron/electron/issues/26905
|
||||
|
||||
This patch can likely be upstreamed. The crash cannot be fixed without
|
||||
patching something in Chromium - this is the least invasive change.
|
||||
|
||||
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc
|
||||
index f9e1aa1b455ae49b59d53a75ae0634d0c092a130..4785f0c0368e0ab22db0cc968ad85d23a9b26240 100644
|
||||
--- a/ui/views/controls/native/native_view_host.cc
|
||||
+++ b/ui/views/controls/native/native_view_host.cc
|
||||
@@ -55,6 +55,9 @@ void NativeViewHost::Detach() {
|
||||
}
|
||||
|
||||
void NativeViewHost::SetParentAccessible(gfx::NativeViewAccessible accessible) {
|
||||
+ if (!native_wrapper_.get())
|
||||
+ return;
|
||||
+
|
||||
native_wrapper_->SetParentAccessible(accessible);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ Date: Fri, 26 Oct 2018 15:35:13 +1100
|
||||
Subject: fix: expose tracing::Agent and use tracing::TracingController instead
|
||||
of v8::TracingController
|
||||
|
||||
This API is used by Electron to create Node's tracing controller.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 2c4acbc4fa0eca3b7c6d03b997445633646446e7..53b07052e43a09f29f863ee1b2287bdebe7b7a7f 100644
|
||||
--- a/src/api/environment.cc
|
||||
|
||||
@@ -305,7 +305,7 @@ index e42332ab13fb01000c73cf0b3b757d1f7141da6f..f8754dbd6a1490d2b50f1014e2daa5c1
|
||||
|
||||
NSString * const SQRLCodeSignatureErrorDomain = @"SQRLCodeSignatureErrorDomain";
|
||||
diff --git a/Squirrel/SQRLDirectoryManager.m b/Squirrel/SQRLDirectoryManager.m
|
||||
index fb130fa5dca4570e0822c8cfdab6831bb57ab5ad..d439906827e0f9fb5550bb6c9840a4e75352f3d7 100644
|
||||
index 34f321077f0bf59de98a41dea2cea95eff72486d..200891ca73ac67754219204340881ef85aff4845 100644
|
||||
--- a/Squirrel/SQRLDirectoryManager.m
|
||||
+++ b/Squirrel/SQRLDirectoryManager.m
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
@@ -40,7 +40,7 @@ DevToolsSecurity -enable
|
||||
# security import "$dir"/public.key -k $KEY_CHAIN
|
||||
|
||||
# Generate Trust Settings
|
||||
npm_config_yes=true npx ts-node "$(dirname $0)"/gen-trust.ts "$dir"/certificate.cer "$dir"/trust.xml
|
||||
npx ts-node "$(dirname $0)"/gen-trust.ts "$dir"/certificate.cer "$dir"/trust.xml
|
||||
|
||||
# Import Trust Settings
|
||||
sudo security trust-settings-import -d "$dir/trust.xml"
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def npx(*npx_args):
|
||||
npx_env = os.environ.copy()
|
||||
npx_env['npm_config_yes'] = 'true'
|
||||
call_args = [__get_executable_name()] + list(npx_args)
|
||||
subprocess.check_call(call_args, env=npx_env)
|
||||
subprocess.check_call(call_args)
|
||||
|
||||
|
||||
def __get_executable_name():
|
||||
|
||||
@@ -22,8 +22,7 @@ async function main () {
|
||||
const env = Object.assign({}, process.env, {
|
||||
npm_config_nodedir: nodeDir,
|
||||
npm_config_msvs_version: '2019',
|
||||
npm_config_arch: process.env.NPM_CONFIG_ARCH,
|
||||
npm_config_yes: 'true'
|
||||
npm_config_arch: process.env.NPM_CONFIG_ARCH
|
||||
});
|
||||
const { status: buildStatus } = cp.spawnSync(NPX_CMD, ['node-gyp', 'rebuild', '--directory', 'test', '-j', 'max'], {
|
||||
env,
|
||||
|
||||
@@ -29,6 +29,8 @@ PDB_LIST = [
|
||||
os.path.join(RELEASE_DIR, '{0}.exe.pdb'.format(PROJECT_NAME))
|
||||
]
|
||||
|
||||
PDB_LIST += glob.glob(os.path.join(RELEASE_DIR, '*.dll.pdb'))
|
||||
|
||||
NPX_CMD = "npx"
|
||||
if sys.platform == "win32":
|
||||
NPX_CMD += ".cmd"
|
||||
@@ -46,11 +48,9 @@ def main():
|
||||
|
||||
for symbol_file in files:
|
||||
print("Generating Sentry src bundle for: " + symbol_file)
|
||||
npx_env = os.environ.copy()
|
||||
npx_env['npm_config_yes'] = 'true'
|
||||
subprocess.check_output([
|
||||
NPX_CMD, '@sentry/cli@1.51.1', 'difutil', 'bundle-sources',
|
||||
symbol_file], env=npx_env)
|
||||
symbol_file])
|
||||
|
||||
files += glob.glob(SYMBOLS_DIR + '/*/*/*.src.zip')
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user