mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d010bcca86 | ||
|
|
1ba8128c8c | ||
|
|
25e504a7ed | ||
|
|
589199f335 | ||
|
|
c0371ab218 | ||
|
|
50f2f10b94 | ||
|
|
2ee36539ba | ||
|
|
0d05ce8d12 | ||
|
|
9e064fec80 | ||
|
|
619a88cf56 | ||
|
|
080bc57145 | ||
|
|
a03ec151e1 | ||
|
|
0858a08097 | ||
|
|
53b6270320 | ||
|
|
4c44e86fd1 | ||
|
|
543a29c926 | ||
|
|
c0c83d2719 | ||
|
|
a7848809fc | ||
|
|
d8ca287700 | ||
|
|
b0c881f608 | ||
|
|
6620ba4e15 | ||
|
|
1babaec6da | ||
|
|
cbe1debbe2 | ||
|
|
3c73ea5259 | ||
|
|
02622b02a6 | ||
|
|
700906c1f1 | ||
|
|
d19a0ac51b | ||
|
|
25521f6286 | ||
|
|
f89b51fe0a | ||
|
|
2a42cd2f65 | ||
|
|
9e419bc4e9 | ||
|
|
1921f802fd | ||
|
|
06e585d82f | ||
|
|
febee696d6 | ||
|
|
57917c4b5a | ||
|
|
3f7f4de319 | ||
|
|
91bafdd3d5 | ||
|
|
c676831a54 | ||
|
|
a62b98a23f | ||
|
|
cbd39f73f8 | ||
|
|
eb819e0881 | ||
|
|
36885ea919 | ||
|
|
bc09b08664 | ||
|
|
880d06e304 | ||
|
|
cb5b28f833 | ||
|
|
e867b08172 | ||
|
|
4541c432af | ||
|
|
604034a899 | ||
|
|
c256db23ce | ||
|
|
c19f09e92e | ||
|
|
328368be56 | ||
|
|
73deb5f56d | ||
|
|
46c416190b | ||
|
|
046ef10147 | ||
|
|
7c8d5f68d5 | ||
|
|
4be4dc7c4f | ||
|
|
5cfb58161c | ||
|
|
2f116aacfb | ||
|
|
2f5c0f9eec | ||
|
|
c730abc55d |
@@ -216,6 +216,7 @@ step-maybe-cleanup-arm64-mac: &step-maybe-cleanup-arm64-mac
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
security delete-generic-password -l "Chromium Safe Storage" || echo "✓ Keychain does not contain password from tests"
|
||||
security delete-generic-password -l "Electron Test Main Safe Storage" || echo "✓ Keychain does not contain password from tests"
|
||||
security delete-generic-password -a "electron-test-safe-storage" || echo "✓ Keychain does not contain password from tests"
|
||||
elif [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
XVFB=/usr/bin/Xvfb
|
||||
/sbin/start-stop-daemon --stop --exec $XVFB || echo "Xvfb not running"
|
||||
|
||||
2
.github/semantic.yml
vendored
2
.github/semantic.yml
vendored
@@ -1,2 +0,0 @@
|
||||
# Always validate the PR title, and ignore the commits
|
||||
titleOnly: true
|
||||
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'104.0.5112.114',
|
||||
'104.0.5112.124',
|
||||
'node_version':
|
||||
'v16.15.0',
|
||||
'nan_version':
|
||||
|
||||
@@ -1 +1 @@
|
||||
20.1.2
|
||||
20.3.3
|
||||
@@ -38,7 +38,7 @@ For more installation options and troubleshooting tips, see
|
||||
|
||||
Each Electron release provides binaries for macOS, Windows, and Linux.
|
||||
|
||||
* macOS (El Capitan and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
|
||||
* macOS (High Sierra and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
|
||||
* Windows (Windows 7 and up): Electron provides `ia32` (`x86`), `x64` (`amd64`), and `arm64` binaries for Windows. Windows on ARM support was added in Electron 5.0.8.
|
||||
* Linux: The prebuilt binaries of Electron are built on Ubuntu 20.04. They have also been verified to work on:
|
||||
* Ubuntu 14.04 and newer
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
"node_options": "1",
|
||||
"node_cli_inspect": "1",
|
||||
"embedded_asar_integrity_validation": "0",
|
||||
"only_load_app_from_asar": "0"
|
||||
"only_load_app_from_asar": "0",
|
||||
"load_browser_process_specific_v8_snapshot": "0"
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ function loadApplicationPackage (packagePath: string) {
|
||||
});
|
||||
|
||||
try {
|
||||
// Override app name and version.
|
||||
// Override app's package.json data.
|
||||
packagePath = path.resolve(packagePath);
|
||||
const packageJsonPath = path.join(packagePath, 'package.json');
|
||||
let appPath;
|
||||
@@ -104,6 +104,16 @@ function loadApplicationPackage (packagePath: string) {
|
||||
} else if (packageJson.name) {
|
||||
app.name = packageJson.name;
|
||||
}
|
||||
if (packageJson.desktopName) {
|
||||
app.setDesktopName(packageJson.desktopName);
|
||||
} else {
|
||||
app.setDesktopName(`${app.name}.desktop`);
|
||||
}
|
||||
// Set v8 flags, deliberately lazy load so that apps that do not use this
|
||||
// feature do not pay the price
|
||||
if (packageJson.v8Flags) {
|
||||
require('v8').setFlagsFromString(packageJson.v8Flags);
|
||||
}
|
||||
appPath = packagePath;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ an issue:
|
||||
* [Mac App Store](tutorial/mac-app-store-submission-guide.md)
|
||||
* [Windows Store](tutorial/windows-store-guide.md)
|
||||
* [Snapcraft](tutorial/snapcraft.md)
|
||||
* [ASAR Archives](tutorial/asar-archives.md)
|
||||
* [Updates](tutorial/updates.md)
|
||||
* [Getting Support](tutorial/support.md)
|
||||
|
||||
@@ -82,7 +83,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* Electron Releases & Developer Feedback
|
||||
* [Versioning Policy](tutorial/electron-versioning.md)
|
||||
* [Release Timelines](tutorial/electron-timelines.md)
|
||||
* [Testing Widevine CDM](tutorial/testing-widevine-cdm.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -10,11 +10,12 @@ An example of implementing a protocol that has the same effect as the
|
||||
```javascript
|
||||
const { app, protocol } = require('electron')
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
protocol.registerFileProtocol('atom', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||
const filePath = url.fileURLToPath('file://' + request.url.slice('atom://'.length))
|
||||
callback(filePath)
|
||||
})
|
||||
})
|
||||
```
|
||||
@@ -175,7 +176,7 @@ property.
|
||||
* `handler` Function
|
||||
* `request` [ProtocolRequest](structures/protocol-request.md)
|
||||
* `callback` Function
|
||||
* `response` ProtocolResponse
|
||||
* `response` [ProtocolResponse](structures/protocol-response.md)
|
||||
|
||||
Returns `boolean` - Whether the protocol was successfully registered
|
||||
|
||||
|
||||
@@ -635,7 +635,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `notifications` - Request notification creation and the ability to display them in the user's system tray.
|
||||
* `midi` - Request MIDI access in the `webmidi` API.
|
||||
* `midiSysex` - Request the use of system exclusive messages in the `webmidi` API.
|
||||
* `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more.
|
||||
* `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more. These requests always appear to originate from the main frame.
|
||||
* `fullscreen` - Request for the app to enter fullscreen mode.
|
||||
* `openExternal` - Request to open links in external applications.
|
||||
* `unknown` - An unrecognized permission request
|
||||
|
||||
@@ -144,6 +144,16 @@ ipcRenderer.on('port', (e, msg) => {
|
||||
|
||||
A `string` representing the current URL of the frame.
|
||||
|
||||
#### `frame.origin` _Readonly_
|
||||
|
||||
A `string` representing the current origin of the frame, serialized according
|
||||
to [RFC 6454](https://www.rfc-editor.org/rfc/rfc6454). This may be different
|
||||
from the URL. For instance, if the frame is a child window opened to
|
||||
`about:blank`, then `frame.origin` will return the parent frame's origin, while
|
||||
`frame.url` will return the empty string. Pages without a scheme/host/port
|
||||
triple origin will have the serialized origin of `"null"` (that is, the string
|
||||
containing the letters n, u, l, l).
|
||||
|
||||
#### `frame.top` _Readonly_
|
||||
|
||||
A `WebFrameMain | null` representing top frame in the frame hierarchy to which `frame`
|
||||
|
||||
@@ -135,7 +135,7 @@ is only available in renderer processes.
|
||||
|
||||
If [sub-pixel anti-aliasing](https://alienryderflex.com/sub_pixel/) is deactivated, then fonts on LCD screens can look blurry. Example:
|
||||
|
||||
![subpixel rendering example]
|
||||

|
||||
|
||||
Sub-pixel anti-aliasing needs a non-transparent background of the layer containing the font glyphs. (See [this issue](https://github.com/electron/electron/issues/6344#issuecomment-420371918) for more info).
|
||||
|
||||
@@ -161,4 +161,3 @@ Notice that just setting the background in the CSS does not have the desired eff
|
||||
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
|
||||
[message-port]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
||||
[browser-window]: api/browser-window.md
|
||||
[subpixel rendering example]: images/subpixel-rendering-screenshot.gif
|
||||
|
||||
@@ -33,12 +33,16 @@ function createWindow () {
|
||||
if (permission === 'serial' && details.securityOrigin === 'file:///') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (details.deviceType === 'serial' && details.origin === 'file://') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
@@ -11,8 +11,8 @@ can either use specialized tooling or manual approaches.
|
||||
## With tooling
|
||||
|
||||
There are a couple tools out there that exist to package and distribute your Electron app.
|
||||
We recommend using [Electron Forge](https://www.electronforge.io). You can check out
|
||||
its documentation directly, or refer to the [Packaging and Distribution](./tutorial-5-packaging.md)
|
||||
We recommend using [Electron Forge](./forge-overview.md). You can check out
|
||||
its [documentation](https://www.electronforge.io) directly, or refer to the [Packaging and Distribution](./tutorial-5-packaging.md)
|
||||
part of the Electron tutorial.
|
||||
|
||||
## Manual packaging
|
||||
|
||||
175
docs/tutorial/asar-archives.md
Normal file
175
docs/tutorial/asar-archives.md
Normal file
@@ -0,0 +1,175 @@
|
||||
---
|
||||
title: ASAR Archives
|
||||
description: What is ASAR archive and how does it affect the application.
|
||||
slug: asar-archives
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
After creating an [application distribution](application-distribution.md), the
|
||||
app's source code are usually bundled into an [ASAR
|
||||
archive](https://github.com/electron/asar), which is a simple extensive archive
|
||||
format designed for Electron apps. By bundling the app we can mitigate issues
|
||||
around long path names on Windows, speed up `require` and conceal your source
|
||||
code from cursory inspection.
|
||||
|
||||
The bundled app runs in a virtual file system and most APIs would just work
|
||||
normally, but for some cases you might want to work on ASAR archives explicitly
|
||||
due to a few caveats.
|
||||
|
||||
## Using ASAR Archives
|
||||
|
||||
In Electron there are two sets of APIs: Node APIs provided by Node.js and Web
|
||||
APIs provided by Chromium. Both APIs support reading files from ASAR archives.
|
||||
|
||||
### Node API
|
||||
|
||||
With special patches in Electron, Node APIs like `fs.readFile` and `require`
|
||||
treat ASAR archives as virtual directories, and the files in it as normal
|
||||
files in the filesystem.
|
||||
|
||||
For example, suppose we have an `example.asar` archive under `/path/to`:
|
||||
|
||||
```sh
|
||||
$ asar list /path/to/example.asar
|
||||
/app.js
|
||||
/file.txt
|
||||
/dir/module.js
|
||||
/static/index.html
|
||||
/static/main.css
|
||||
/static/jquery.min.js
|
||||
```
|
||||
|
||||
Read a file in the ASAR archive:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs')
|
||||
fs.readFileSync('/path/to/example.asar/file.txt')
|
||||
```
|
||||
|
||||
List all files under the root of the archive:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs')
|
||||
fs.readdirSync('/path/to/example.asar')
|
||||
```
|
||||
|
||||
Use a module from the archive:
|
||||
|
||||
```javascript
|
||||
require('./path/to/example.asar/dir/module.js')
|
||||
```
|
||||
|
||||
You can also display a web page in an ASAR archive with `BrowserWindow`:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.loadURL('file:///path/to/example.asar/static/index.html')
|
||||
```
|
||||
|
||||
### Web API
|
||||
|
||||
In a web page, files in an archive can be requested with the `file:` protocol.
|
||||
Like the Node API, ASAR archives are treated as directories.
|
||||
|
||||
For example, to get a file with `$.get`:
|
||||
|
||||
```html
|
||||
<script>
|
||||
let $ = require('./jquery.min.js')
|
||||
$.get('file:///path/to/example.asar/file.txt', (data) => {
|
||||
console.log(data)
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### Treating an ASAR archive as a Normal File
|
||||
|
||||
For some cases like verifying the ASAR archive's checksum, we need to read the
|
||||
content of an ASAR archive as a file. For this purpose you can use the built-in
|
||||
`original-fs` module which provides original `fs` APIs without `asar` support:
|
||||
|
||||
```javascript
|
||||
const originalFs = require('original-fs')
|
||||
originalFs.readFileSync('/path/to/example.asar')
|
||||
```
|
||||
|
||||
You can also set `process.noAsar` to `true` to disable the support for `asar` in
|
||||
the `fs` module:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs')
|
||||
process.noAsar = true
|
||||
fs.readFileSync('/path/to/example.asar')
|
||||
```
|
||||
|
||||
## Limitations of the Node API
|
||||
|
||||
Even though we tried hard to make ASAR archives in the Node API work like
|
||||
directories as much as possible, there are still limitations due to the
|
||||
low-level nature of the Node API.
|
||||
|
||||
### Archives Are Read-only
|
||||
|
||||
The archives can not be modified so all Node APIs that can modify files will not
|
||||
work with ASAR archives.
|
||||
|
||||
### Working Directory Can Not Be Set to Directories in Archive
|
||||
|
||||
Though ASAR archives are treated as directories, there are no actual
|
||||
directories in the filesystem, so you can never set the working directory to
|
||||
directories in ASAR archives. Passing them as the `cwd` option of some APIs
|
||||
will also cause errors.
|
||||
|
||||
### Extra Unpacking on Some APIs
|
||||
|
||||
Most `fs` APIs can read a file or get a file's information from ASAR archives
|
||||
without unpacking, but for some APIs that rely on passing the real file path to
|
||||
underlying system calls, Electron will extract the needed file into a
|
||||
temporary file and pass the path of the temporary file to the APIs to make them
|
||||
work. This adds a little overhead for those APIs.
|
||||
|
||||
APIs that requires extra unpacking are:
|
||||
|
||||
* `child_process.execFile`
|
||||
* `child_process.execFileSync`
|
||||
* `fs.open`
|
||||
* `fs.openSync`
|
||||
* `process.dlopen` - Used by `require` on native modules
|
||||
|
||||
### Fake Stat Information of `fs.stat`
|
||||
|
||||
The `Stats` object returned by `fs.stat` and its friends on files in `asar`
|
||||
archives is generated by guessing, because those files do not exist on the
|
||||
filesystem. So you should not trust the `Stats` object except for getting file
|
||||
size and checking file type.
|
||||
|
||||
### Executing Binaries Inside ASAR archive
|
||||
|
||||
There are Node APIs that can execute binaries like `child_process.exec`,
|
||||
`child_process.spawn` and `child_process.execFile`, but only `execFile` is
|
||||
supported to execute binaries inside ASAR archive.
|
||||
|
||||
This is because `exec` and `spawn` accept `command` instead of `file` as input,
|
||||
and `command`s are executed under shell. There is no reliable way to determine
|
||||
whether a command uses a file in asar archive, and even if we do, we can not be
|
||||
sure whether we can replace the path in command without side effects.
|
||||
|
||||
## Adding Unpacked Files to ASAR archives
|
||||
|
||||
As stated above, some Node APIs will unpack the file to the filesystem when
|
||||
called. Apart from the performance issues, various anti-virus scanners might
|
||||
be triggered by this behavior.
|
||||
|
||||
As a workaround, you can leave various files unpacked using the `--unpack` option.
|
||||
In the following example, shared libraries of native Node.js modules will not be
|
||||
packed:
|
||||
|
||||
```sh
|
||||
$ asar pack app app.asar --unpack *.node
|
||||
```
|
||||
|
||||
After running the command, you will notice that a folder named `app.asar.unpacked`
|
||||
was created together with the `app.asar` file. It contains the unpacked files
|
||||
and should be shipped together with the `app.asar` archive.
|
||||
53
docs/tutorial/asar-integrity.md
Normal file
53
docs/tutorial/asar-integrity.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: 'ASAR Integrity'
|
||||
description: 'An experimental feature that ensures the validity of ASAR contents at runtime.'
|
||||
slug: asar-integrity
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
## Platform Support
|
||||
|
||||
Currently ASAR integrity checking is only supported on macOS.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Electron Forge / Electron Packager
|
||||
|
||||
If you are using `>= electron-packager@15.4.0` or `>= @electron-forge/core@6.0.0-beta.61` then all these requirements are met for you automatically and you can skip to [Toggling the Fuse](#toggling-the-fuse).
|
||||
|
||||
### Other build systems
|
||||
|
||||
In order to enable ASAR integrity checking you need to ensure that your `app.asar` file was generated by a version of the `asar` npm package that supports asar integrity. Support was introduced in version `3.1.0`.
|
||||
|
||||
Your must then populate a valid `ElectronAsarIntegrity` dictionary block in your packaged apps `Info.plist`. An example is included below.
|
||||
|
||||
```plist
|
||||
<key>ElectronAsarIntegrity</key>
|
||||
<dict>
|
||||
<key>Resources/app.asar</key>
|
||||
<dict>
|
||||
<key>algorithm</key>
|
||||
<string>SHA256</string>
|
||||
<key>hash</key>
|
||||
<string>9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac</string>
|
||||
</dict>
|
||||
</dict>
|
||||
```
|
||||
|
||||
Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of the ASAR header using the given algorithm. The `asar` package exposes a `getRawHeader` method whose result can then be hashed to generate this value.
|
||||
|
||||
## Toggling the Fuse
|
||||
|
||||
ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path.
|
||||
|
||||
```js
|
||||
require('@electron/fuses').flipFuses(
|
||||
// E.g. /a/b/Foo.app
|
||||
pathToPackagedApp,
|
||||
{
|
||||
version: FuseVersion.V1,
|
||||
[FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
|
||||
[FuseV1Options.OnlyLoadAppFromAsar]: true
|
||||
}
|
||||
)
|
||||
```
|
||||
@@ -26,10 +26,8 @@ beginners, using a command line tool is likely to be helpful*.
|
||||
|
||||
## electron-forge
|
||||
|
||||
A "complete tool for building modern Electron applications". Electron Forge
|
||||
unifies the existing (and well maintained) build tools for Electron development
|
||||
into a cohesive package so that anyone can jump right in to Electron
|
||||
development.
|
||||
Electron Forge is a tool for packaging and publishing Electron applications. It unifies Electron's tooling ecosystem
|
||||
into a single extensible interface so that anyone can jump right into making Electron apps.
|
||||
|
||||
Forge comes with [a ready-to-use template](https://electronforge.io/templates) using Webpack as a bundler. It includes an example typescript configuration and provides two configuration files to enable easy customization. It uses the same core modules used by the
|
||||
greater Electron community (like [`electron-packager`](https://github.com/electron/electron-packager)) –
|
||||
|
||||
@@ -54,85 +54,11 @@ and notarized requires a few additions to your configuration. [Forge](https://el
|
||||
collection of the official Electron tools, using [`electron-packager`],
|
||||
[`electron-osx-sign`], and [`electron-notarize`] under the hood.
|
||||
|
||||
Let's take a look at an example `package.json` configuration with all required fields. Not all of them are
|
||||
required: the tools will be clever enough to automatically find a suitable `identity`, for instance,
|
||||
but we recommend that you are explicit.
|
||||
|
||||
```json title="package.json" {7}
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.0.1",
|
||||
"config": {
|
||||
"forge": {
|
||||
"packagerConfig": {
|
||||
"osxSign": {
|
||||
"identity": "Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)",
|
||||
"hardened-runtime": true,
|
||||
"entitlements": "entitlements.plist",
|
||||
"entitlements-inherit": "entitlements.plist",
|
||||
"signature-flags": "library"
|
||||
},
|
||||
"osxNotarize": {
|
||||
"appleId": "felix@felix.fun",
|
||||
"appleIdPassword": "my-apple-id-password"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `entitlements.plist` file referenced here needs the following macOS-specific entitlements
|
||||
to assure the Apple security mechanisms that your app is doing these things
|
||||
without meaning any harm:
|
||||
|
||||
```xml title="entitlements.plist"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Note that up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
To see all of this in action, check out Electron Fiddle's source code,
|
||||
[especially its `electron-forge` configuration
|
||||
file](https://github.com/electron/fiddle/blob/master/forge.config.js).
|
||||
|
||||
If you plan to access the microphone or camera within your app using Electron's APIs, you'll also
|
||||
need to add the following entitlements:
|
||||
|
||||
```xml title="entitlements.plist"
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<true/>
|
||||
```
|
||||
|
||||
If these are not present in your app's entitlements when you invoke, for example:
|
||||
|
||||
```js title="main.js"
|
||||
const { systemPreferences } = require('electron')
|
||||
const microphone = systemPreferences.askForMediaAccess('microphone')
|
||||
```
|
||||
|
||||
Your app may crash. See the Resource Access section in [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) for more information and entitlements you may need.
|
||||
|
||||
### Using Electron Builder
|
||||
|
||||
Electron Builder comes with a custom solution for signing your application. You
|
||||
can find [its documentation here](https://www.electron.build/code-signing).
|
||||
Detailed instructions on how to configure your application can be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-macos).
|
||||
|
||||
### Using Electron Packager
|
||||
|
||||
If you're not using an integrated build pipeline like Forge or Builder, you
|
||||
If you're not using an integrated build pipeline like Forge, you
|
||||
are likely using [`electron-packager`], which includes [`electron-osx-sign`] and
|
||||
[`electron-notarize`].
|
||||
|
||||
@@ -204,36 +130,7 @@ commit it to your source code.
|
||||
|
||||
### Using Electron Forge
|
||||
|
||||
Once you have a code signing certificate file (`.pfx`), you can sign
|
||||
[Squirrel.Windows][maker-squirrel] and [MSI][maker-msi] installers in Electron Forge
|
||||
with the `certificateFile` and `certificatePassword` fields in their respective
|
||||
configuration objects.
|
||||
|
||||
For example, if you keep your Forge config in your `package.json` file and are
|
||||
creating a Squirrel.Windows installer:
|
||||
|
||||
```json {9-15} title='package.json'
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.0.1",
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
"packagerConfig": {},
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-squirrel",
|
||||
"config": {
|
||||
"certificateFile": "./cert.pfx",
|
||||
"certificatePassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
Electron Forge is the recommended way to sign your `Squirrel.Windows` and `WiX MSI` installers. Detailed instructions on how to configure your application can be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-macos).
|
||||
|
||||
### Using electron-winstaller (Squirrel.Windows)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ you can deliver it to your users.
|
||||
## Packaging
|
||||
|
||||
To distribute your app with Electron, you need to package all your resources and assets
|
||||
into an executable and rebrand it. To do this, you can either use specialized tooling
|
||||
into an executable and rebrand it. To do this, you can either use specialized tooling like Electron Forge
|
||||
or do it manually. See the [Application Packaging][application-packaging] tutorial
|
||||
for more information.
|
||||
|
||||
|
||||
36
docs/tutorial/forge-overview.md
Normal file
36
docs/tutorial/forge-overview.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Distributing Apps With Electron Forge
|
||||
|
||||
Electron Forge is a tool for packaging and publishing Electron applications.
|
||||
It unifies Electron's build tooling ecosystem into
|
||||
a single extensible interface so that anyone can jump right into making Electron apps.
|
||||
|
||||
## Getting started
|
||||
|
||||
The [Electron Forge docs] contain detailed information on taking your application
|
||||
from source code to your end users' machines.
|
||||
This includes:
|
||||
|
||||
* Packaging your application [(package)]
|
||||
* Generating executables and installers for each OS [(make)], and,
|
||||
* Publishing these files to online platforms to download [(publish)].
|
||||
|
||||
For beginners, we recommend following through Electron's [tutorial] to develop, build,
|
||||
package and publish your first Electron app. If you have already developed an app on your machine
|
||||
and want to start on packaging and distribution, start from [step 5] of the tutorial.
|
||||
|
||||
## Getting help
|
||||
|
||||
* If you need help with developing your app, our [community Discord server][discord] is a great place
|
||||
to get advice from other Electron app developers.
|
||||
* If you suspect you're running into a bug with Forge, please check the [GitHub issue tracker]
|
||||
to see if any existing issues match your problem. If not, feel free to fill out our bug report
|
||||
template and submit a new issue.
|
||||
|
||||
[Electron Forge Docs]: https://www.electronforge.io/
|
||||
[step 5]: ./tutorial-5-packaging.md
|
||||
[(package)]: https://www.electronforge.io/cli#package
|
||||
[(make)]: https://www.electronforge.io/cli#make
|
||||
[(publish)]: https://www.electronforge.io/cli#publish
|
||||
[GitHub issue tracker]: https://github.com/electron-userland/electron-forge/issues
|
||||
[discord]: https://discord.gg/APGC3k5yaH
|
||||
[tutorial]: https://www.electronjs.org/docs/latest/tutorial/tutorial-prerequisites
|
||||
@@ -8,6 +8,59 @@ For a subset of Electron functionality it makes sense to disable certain feature
|
||||
|
||||
Fuses are the solution to this problem, at a high level they are "magic bits" in the Electron binary that can be flipped when packaging your Electron app to enable / disable certain features / restrictions. Because they are flipped at package time before you code sign your app the OS becomes responsible for ensuring those bits aren't flipped back via OS level code signing validation (Gatekeeper / App Locker).
|
||||
|
||||
## Current Fuses
|
||||
|
||||
### `runAsNode`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.RunAsNode`
|
||||
|
||||
The runAsNode fuse toggles whether the `ELECTRON_RUN_AS_NODE` environment variable is respected or not. Please note that if this fuse is disabled then `process.fork` in the main process will not function as expected as it depends on this environment variable to function.
|
||||
|
||||
### `cookieEncryption`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableCookieEncryption`
|
||||
|
||||
The cookieEncryption fuse toggles whether the cookie store on disk is encrypted using OS level cryptography keys. By default the sqlite database that Chromium uses to store cookies stores the values in plaintext. If you wish to ensure your apps cookies are encrypted in the same way Chrome does then you should enable this fuse. Please note it is a one-way transition, if you enable this fuse existing unencrypted cookies will be encrypted-on-write but if you then disable the fuse again your cookie store will effectively be corrupt and useless. Most apps can safely enable this fuse.
|
||||
|
||||
### `nodeOptions`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableNodeOptionsEnvironmentVariable`
|
||||
|
||||
The nodeOptions fuse toggles whether the [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#node_optionsoptions) environment variable is respected or not. This environment variable can be used to pass all kinds of custom options to the Node.js runtime and isn't typically used by apps in production. Most apps can safely disable this fuse.
|
||||
|
||||
### `nodeCliInspect`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableNodeCliInspectArguments`
|
||||
|
||||
The nodeCliInspect fuse toggles whether the `--inspect`, `--inspect-brk`, etc. flags are respected or not. When disabled it also ensures that `SIGUSR1` signal does not initialize the main process inspector. Most apps can safely disable this fuse.
|
||||
|
||||
### `embeddedAsarIntegrityValidation`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableEmbeddedAsarIntegrityValidation`
|
||||
|
||||
The embeddedAsarIntegrityValidation fuse toggles an experimental feature on macOS that validates the content of the `app.asar` file when it is loaded. This feature is designed to have a minimal performance impact but may marginally slow down file reads from inside the `app.asar` archive.
|
||||
|
||||
For more information on how to use asar integrity validation please read the [Asar Integrity](asar-integrity.md) documentation.
|
||||
|
||||
### `onlyLoadAppFromAsar`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.OnlyLoadAppFromAsar`
|
||||
|
||||
The onlyLoadAppFromAsar fuse changes the search system that Electron uses to locate your app code. By default Electron will search in the following order `app.asar` -> `app` -> `default_app.asar`. When this fuse is enabled the search order becomes a single entry `app.asar` thus ensuring that when combined with the `embeddedAsarIntegrityValidation` fuse it is impossible to load non-validated code.
|
||||
|
||||
### `loadBrowserProcessSpecificV8Snapshot`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.LoadBrowserProcessSpecificV8Snapshot`
|
||||
|
||||
The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is used for the browser process. By default Electron's processes will all use the same V8 snapshot file. When this fuse is enabled the browser process uses the file called `browser_v8_context_snapshot.bin` for its V8 snapshot. The other processes will use the V8 snapshot file that they normally do.
|
||||
|
||||
## How do I flip the fuses?
|
||||
|
||||
### The easy way
|
||||
@@ -20,11 +73,18 @@ require('@electron/fuses').flipFuses(
|
||||
require('electron'),
|
||||
// Fuses to flip
|
||||
{
|
||||
runAsNode: false
|
||||
version: FuseVersion.V1,
|
||||
[FuseV1Options.RunAsNode]: false
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
You can validate the fuses have been flipped or check the fuse status of an arbitrary Electron app using the fuses CLI.
|
||||
|
||||
```bash
|
||||
npx @electron/fuses read --app /Applications/Foo.app
|
||||
```
|
||||
|
||||
### The hard way
|
||||
|
||||
#### Quick Glossary
|
||||
|
||||
@@ -101,7 +101,7 @@ app.whenReady().then(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
const secondaryWindow = BrowserWindow({
|
||||
const secondaryWindow = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
@@ -144,7 +144,7 @@ to use `contextIsolation` and set up specific contextBridge calls for each of yo
|
||||
expected messages, but for the simplicity of this example we don't. You can find an
|
||||
example of context isolation further down this page at [Communicating directly between the main process and the main world of a context-isolated page](#communicating-directly-between-the-main-process-and-the-main-world-of-a-context-isolated-page)
|
||||
|
||||
That means window.messagePort is globally available and you can call
|
||||
That means window.electronMessagePort is globally available and you can call
|
||||
`postMessage` on it from anywhere in your app to send a message to the other
|
||||
renderer.
|
||||
|
||||
@@ -272,7 +272,7 @@ const makeStreamingRequest = (element, callback) => {
|
||||
}
|
||||
|
||||
makeStreamingRequest(42, (data) => {
|
||||
console.log('got response data:', event.data)
|
||||
console.log('got response data:', data)
|
||||
})
|
||||
// We will see "got response data: 42" 10 times.
|
||||
```
|
||||
|
||||
@@ -12,28 +12,10 @@ the GPU service and the network service.
|
||||
|
||||
See Chromium's [Sandbox design document][sandbox] for more information.
|
||||
|
||||
## Electron's sandboxing policies
|
||||
|
||||
Electron comes with a mixed sandbox environment, meaning sandboxed processes can run
|
||||
alongside privileged ones. By default, renderer processes are not sandboxed, but
|
||||
utility processes are. Note that as in Chromium, the main (browser) process is
|
||||
privileged and cannot be sandboxed.
|
||||
|
||||
Historically, this mixed sandbox approach was established because having Node.js available
|
||||
in the renderer is an extremely powerful tool for app developers. Unfortunately, this
|
||||
feature is also an equally massive security vulnerability.
|
||||
|
||||
Theoretically, unsandboxed renderers are not a problem for desktop applications that
|
||||
only display trusted code, but they make Electron less secure than Chromium for
|
||||
displaying untrusted web content. However, even purportedly trusted code may be
|
||||
dangerous — there are countless attack vectors that malicious actors can use, from
|
||||
cross-site scripting to content injection to man-in-the-middle attacks on remotely loaded
|
||||
websites, just to name a few. For this reason, we recommend enabling renderer sandboxing
|
||||
for the vast majority of cases under an abundance of caution.
|
||||
|
||||
<!--TODO: update this guide when #28466 is either solved or closed -->
|
||||
Note that there is an active discussion in the issue tracker to enable renderer sandboxing
|
||||
by default. See [#28466][issue-28466]) for details.
|
||||
Starting from Electron 20, the sandbox is enabled for renderer processes without any
|
||||
further configuration. If you want to disable the sandbox for a process, see the
|
||||
[Disabling the sandbox for a single process](#disabling-the-sandbox-for-a-single-process)
|
||||
section.
|
||||
|
||||
## Sandbox behaviour in Electron
|
||||
|
||||
@@ -46,12 +28,17 @@ When renderer processes in Electron are sandboxed, they behave in the same way a
|
||||
regular Chrome renderer would. A sandboxed renderer won't have a Node.js
|
||||
environment initialized.
|
||||
|
||||
<!-- TODO(erickzhao): when we have a solid guide for IPC, link it here -->
|
||||
Therefore, when the sandbox is enabled, renderer processes can only perform privileged
|
||||
tasks (such as interacting with the filesystem, making changes to the system, or spawning
|
||||
subprocesses) by delegating these tasks to the main process via inter-process
|
||||
communication (IPC).
|
||||
|
||||
:::note
|
||||
|
||||
For more info on inter-process communication, check out our [IPC guide](./ipc.md).
|
||||
|
||||
:::
|
||||
|
||||
### Preload scripts
|
||||
|
||||
In order to allow renderer processes to communicate with the main process, preload
|
||||
@@ -66,7 +53,7 @@ but can only import a subset of Electron and Node's built-in modules:
|
||||
|
||||
In addition, the preload script also polyfills certain Node.js primitives as globals:
|
||||
|
||||
* [`Buffer`](https://nodejs.org/api/Buffer.html)
|
||||
* [`Buffer`](https://nodejs.org/api/buffer.html)
|
||||
* [`process`](../api/process.md)
|
||||
* [`clearImmediate`](https://nodejs.org/api/timers.html#timers_clearimmediate_immediate)
|
||||
* [`setImmediate`](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args)
|
||||
@@ -83,13 +70,17 @@ privileged APIs to untrusted code running in the renderer process unless
|
||||
|
||||
## Configuring the sandbox
|
||||
|
||||
### Enabling the sandbox for a single process
|
||||
For most apps, sandboxing is the best choice. In certain use cases that are incompatible with
|
||||
the sandbox (for instance, when using native node modules in the renderer),
|
||||
it is possible to disable the sandbox for specific processes. This comes with security
|
||||
risks, especially if any untrusted code or content is present in the unsandboxed process.
|
||||
|
||||
In Electron, renderer sandboxing can be enabled on a per-process basis with
|
||||
the `sandbox: true` preference in the [`BrowserWindow`][browser-window] constructor.
|
||||
### Disabling the sandbox for a single process
|
||||
|
||||
```js
|
||||
// main.js
|
||||
In Electron, renderer sandboxing can be disabled on a per-process basis with
|
||||
the `sandbox: false` preference in the [`BrowserWindow`][browser-window] constructor.
|
||||
|
||||
```js title='main.js'
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
@@ -100,17 +91,30 @@ app.whenReady().then(() => {
|
||||
})
|
||||
```
|
||||
|
||||
Sandboxing is also disabled whenever Node.js integration is enabled in the renderer.
|
||||
This can be done through the BrowserWindow constructor with the `nodeIntegration: true` flag.
|
||||
|
||||
```js title='main.js'
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
win.loadURL('https://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
### Enabling the sandbox globally
|
||||
|
||||
If you want to force sandboxing for all renderers, you can also use the
|
||||
[`app.enableSandbox`][enable-sandbox] API. Note that this API has to be called before the
|
||||
app's `ready` event.
|
||||
|
||||
```js
|
||||
// main.js
|
||||
```js title='main.js'
|
||||
app.enableSandbox()
|
||||
app.whenReady().then(() => {
|
||||
// no need to pass `sandbox: true` since `app.enableSandbox()` was called.
|
||||
// any sandbox:false calls are overridden since `app.enableSandbox()` was called.
|
||||
const win = new BrowserWindow()
|
||||
win.loadURL('https://google.com')
|
||||
})
|
||||
@@ -139,16 +143,16 @@ issues:
|
||||
have, to inherit everything we can from Chromium, and to respond quickly to
|
||||
security issues, but Electron cannot be as secure as Chromium without the
|
||||
resources that Chromium is able to dedicate.
|
||||
2. Some security features in Chrome (such as Safe Browsing and Certificate
|
||||
1. Some security features in Chrome (such as Safe Browsing and Certificate
|
||||
Transparency) require a centralized authority and dedicated servers, both of
|
||||
which run counter to the goals of the Electron project. As such, we disable
|
||||
those features in Electron, at the cost of the associated security they
|
||||
would otherwise bring.
|
||||
3. There is only one Chromium, whereas there are many thousands of apps built
|
||||
1. There is only one Chromium, whereas there are many thousands of apps built
|
||||
on Electron, all of which behave slightly differently. Accounting for those
|
||||
differences can yield a huge possibility space, and make it challenging to
|
||||
ensure the security of the platform in unusual use cases.
|
||||
4. We can't push security updates to users directly, so we rely on app vendors
|
||||
1. We can't push security updates to users directly, so we rely on app vendors
|
||||
to upgrade the version of Electron underlying their app in order for
|
||||
security updates to reach users.
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ the sandbox in all renderers. Loading, reading or processing any untrusted
|
||||
content in an unsandboxed process, including the main process, is not advised.
|
||||
|
||||
:::info
|
||||
For more information on what `contextIsolation` is and how to enable it please
|
||||
For more information on what Process Sandboxing is and how to enable it please
|
||||
see our dedicated [Process Sandboxing](sandbox.md) document.
|
||||
:::info
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
# Testing Widevine CDM
|
||||
|
||||
In Electron you can use the Widevine CDM library shipped with Chrome browser.
|
||||
|
||||
Widevine Content Decryption Modules (CDMs) are how streaming services protect
|
||||
content using HTML5 video to web browsers without relying on an NPAPI plugin
|
||||
like Flash or Silverlight. Widevine support is an alternative solution for
|
||||
streaming services that currently rely on Silverlight for playback of
|
||||
DRM-protected video content. It will allow websites to show DRM-protected video
|
||||
content in Firefox without the use of NPAPI plugins. The Widevine CDM runs in an
|
||||
open-source CDM sandbox providing better user security than NPAPI plugins.
|
||||
|
||||
#### Note on VMP
|
||||
|
||||
As of [`Electron v1.8.0 (Chrome v59)`](https://electronjs.org/releases#1.8.1),
|
||||
the below steps are may only be some of the necessary steps to enable Widevine;
|
||||
any app on or after that version intending to use the Widevine CDM may need to
|
||||
be signed using a license obtained from [Widevine](https://www.widevine.com/)
|
||||
itself.
|
||||
|
||||
Per [Widevine](https://www.widevine.com/):
|
||||
|
||||
> Chrome 59 (and later) includes support for Verified Media Path (VMP). VMP
|
||||
> provides a method to verify the authenticity of a device platform. For browser
|
||||
> deployments, this will provide an additional signal to determine if a
|
||||
> browser-based implementation is reliable and secure.
|
||||
>
|
||||
> The proxy integration guide has been updated with information about VMP and
|
||||
> how to issue licenses.
|
||||
>
|
||||
> Widevine recommends our browser-based integrations (vendors and browser-based
|
||||
> applications) add support for VMP.
|
||||
|
||||
To enable video playback with this new restriction,
|
||||
[castLabs](https://castlabs.com/open-source/downstream/) has created a
|
||||
[fork](https://github.com/castlabs/electron-releases) that has implemented the
|
||||
necessary changes to enable Widevine to be played in an Electron application if
|
||||
one has obtained the necessary licenses from widevine.
|
||||
|
||||
## Getting the library
|
||||
|
||||
Open `chrome://components/` in Chrome browser, find `Widevine Content Decryption Module`
|
||||
and make sure it is up to date, then you can find the library files from the
|
||||
application directory.
|
||||
|
||||
### On Windows
|
||||
|
||||
The library file `widevinecdm.dll` will be under
|
||||
`Program Files(x86)/Google/Chrome/Application/CHROME_VERSION/WidevineCdm/_platform_specific/win_(x86|x64)/`
|
||||
directory.
|
||||
|
||||
### On macOS
|
||||
|
||||
The library file `libwidevinecdm.dylib` will be under
|
||||
`/Applications/Google Chrome.app/Contents/Versions/CHROME_VERSION/Google Chrome Framework.framework/Versions/A/Libraries/WidevineCdm/_platform_specific/mac_(x86|x64)/`
|
||||
directory.
|
||||
|
||||
**Note:** Make sure that chrome version used by Electron is greater than or
|
||||
equal to the `min_chrome_version` value of Chrome's widevine cdm component.
|
||||
The value can be found in `manifest.json` under `WidevineCdm` directory.
|
||||
|
||||
## Using the library
|
||||
|
||||
After getting the library files, you should pass the path to the file
|
||||
with `--widevine-cdm-path` command line switch, and the library's version
|
||||
with `--widevine-cdm-version` switch. The command line switches have to be
|
||||
passed before the `ready` event of `app` module gets emitted.
|
||||
|
||||
Example code:
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// You have to pass the directory that contains widevine library here, it is
|
||||
// * `libwidevinecdm.dylib` on macOS,
|
||||
// * `widevinecdm.dll` on Windows.
|
||||
app.commandLine.appendSwitch('widevine-cdm-path', '/path/to/widevine_library')
|
||||
// The version of plugin can be got from `chrome://components` page in Chrome.
|
||||
app.commandLine.appendSwitch('widevine-cdm-version', '1.4.8.866')
|
||||
|
||||
let win = null
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow()
|
||||
win.show()
|
||||
})
|
||||
```
|
||||
|
||||
## Verifying Widevine CDM support
|
||||
|
||||
To verify whether widevine works, you can use following ways:
|
||||
|
||||
* Open https://shaka-player-demo.appspot.com/ and load a manifest that uses
|
||||
`Widevine`.
|
||||
* Open http://www.dash-player.com/demo/drm-test-area/, check whether the page
|
||||
says `bitdash uses Widevine in your browser`, then play the video.
|
||||
@@ -123,7 +123,7 @@ the list of versions in the [electron/releases] repository.
|
||||
[homebrew]: https://brew.sh/
|
||||
[mdn-guide]: https://developer.mozilla.org/en-US/docs/Learn/
|
||||
[node]: https://nodejs.org/
|
||||
[node-guide]: https://nodejs.dev/learn
|
||||
[node-guide]: https://nodejs.dev/en/learn/
|
||||
[node-download]: https://nodejs.org/en/download/
|
||||
[nvm]: https://github.com/nvm-sh/nvm
|
||||
[process-model]: ./process-model.md
|
||||
|
||||
@@ -369,12 +369,12 @@ run. Create a launch.json configuration in a new `.vscode` folder in your projec
|
||||
"name": "Renderer",
|
||||
"port": 9222,
|
||||
"request": "attach",
|
||||
"type": "pwa-chrome",
|
||||
"type": "chrome",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Main",
|
||||
"type": "pwa-node",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
|
||||
@@ -398,11 +398,11 @@ What we have done in the `launch.json` file is to create 3 configurations:
|
||||
- `Main` is used to start the main process and also expose port 9222 for remote debugging
|
||||
(`--remote-debugging-port=9222`). This is the port that we will use to attach the debugger
|
||||
for the `Renderer`. Because the main process is a Node.js process, the type is set to
|
||||
`pwa-node` (`pwa-` is the prefix that tells VS Code to use the latest JavaScript debugger).
|
||||
`node`.
|
||||
- `Renderer` is used to debug the renderer process. Because the main process is the one
|
||||
that creates the process, we have to "attach" to it (`"request": "attach"`) instead of
|
||||
creating a new one.
|
||||
The renderer process is a web one, so the debugger we have to use is `pwa-chrome`.
|
||||
The renderer process is a web one, so the debugger we have to use is `chrome`.
|
||||
- `Main + renderer` is a [compound task] that executes the previous ones simultaneously.
|
||||
|
||||
:::caution
|
||||
|
||||
@@ -38,7 +38,25 @@ called a **preload**.
|
||||
## Augmenting the renderer with a preload script
|
||||
|
||||
A BrowserWindow's preload script runs in a context that has access to both the HTML DOM
|
||||
and a Node.js environment. Preload scripts are injected before a web page loads in the renderer,
|
||||
and a limited subset of Node.js and Electron APIs.
|
||||
|
||||
:::info Preload script sandboxing
|
||||
|
||||
From Electron 20 onwards, preload scripts are **sandboxed** by default and no longer have access
|
||||
to a full Node.js environment. Practically, this means that you have a polyfilled `require`
|
||||
function that only has access to a limited set of APIs.
|
||||
|
||||
| Available API | Details |
|
||||
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Electron modules | Renderer process modules |
|
||||
| Node.js modules | [`events`](https://nodejs.org/api/events.html), [`timers`](https://nodejs.org/api/timers.html), [`url`](https://nodejs.org/api/url.html) |
|
||||
| Polyfilled globals | [`Buffer`](https://nodejs.org/api/buffer.html), [`process`](../api/process.md), [`clearImmediate`](https://nodejs.org/api/timers.html#timers_clearimmediate_immediate), [`setImmediate`](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args) |
|
||||
|
||||
For more information, check out the [Process Sandboxing](./sandbox.md) guide.
|
||||
|
||||
:::
|
||||
|
||||
Preload scripts are injected before a web page loads in the renderer,
|
||||
similar to a Chrome extension's [content scripts][content-script]. To add features to your renderer
|
||||
that require privileged access, you can define [global] objects through the
|
||||
[contextBridge][contextbridge] API.
|
||||
|
||||
@@ -111,6 +111,12 @@ Electron Forge can be configured to create distributables in different OS-specif
|
||||
|
||||
:::
|
||||
|
||||
:::tip Creating and Adding Application Icons
|
||||
|
||||
Setting custom application icons requires a few additions to your config. Check out [Forge's icon tutorial] for more information.
|
||||
|
||||
:::
|
||||
|
||||
:::note Packaging without Electron Forge
|
||||
|
||||
If you want to manually package your code, or if you're just interested understanding the
|
||||
@@ -214,6 +220,7 @@ information.
|
||||
[electron forge]: https://www.electronforge.io
|
||||
[electron forge cli documentation]: https://www.electronforge.io/cli#commands
|
||||
[makers]: https://www.electronforge.io/config/makers
|
||||
[Forge's icon tutorial]: https://www.electronforge.io/guides/create-and-add-icons
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +72,8 @@ BrowserWindow.getAllWindows = () => {
|
||||
|
||||
BrowserWindow.getFocusedWindow = () => {
|
||||
for (const window of BrowserWindow.getAllWindows()) {
|
||||
const hasWC = window.webContents && !window.webContents.isDestroyed();
|
||||
if (!window.isDestroyed() && hasWC) {
|
||||
if (window.isFocused() || window.isDevToolsFocused()) return window;
|
||||
if (!window.isDestroyed() && window.webContents && !window.webContents.isDestroyed()) {
|
||||
if (window.isFocused() || window.webContents.isDevToolsFocused()) return window;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
23
lib/common/.eslintrc.json
Normal file
23
lib/common/.eslintrc.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main",
|
||||
"electron/renderer"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*",
|
||||
"@electron/internal/isolated_renderer/*",
|
||||
"@electron/internal/renderer/*",
|
||||
"@electron/internal/sandboxed_worker/*",
|
||||
"@electron/internal/worker/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
|
||||
const clipboard = process._linkedBinding('electron_common_clipboard');
|
||||
|
||||
18
lib/isolated_renderer/.eslintrc.json
Normal file
18
lib/isolated_renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/renderer/.eslintrc.json
Normal file
18
lib/renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ipcRenderer } from 'electron';
|
||||
import { ipcRenderer } from 'electron/renderer';
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
import type * as webViewInitModule from '@electron/internal/renderer/web-view/web-view-init';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { internalContextBridge } from '@electron/internal/renderer/api/context-b
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { webFrame } from 'electron/renderer';
|
||||
import { IPC_MESSAGES } from '../common/ipc-messages';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
const { contextIsolationEnabled } = internalContextBridge;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { webFrame, WebFrame } from 'electron';
|
||||
import { webFrame, WebFrame } from 'electron/renderer';
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
|
||||
18
lib/sandboxed_renderer/.eslintrc.json
Normal file
18
lib/sandboxed_renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/worker/.eslintrc.json
Normal file
18
lib/worker/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -70,8 +70,30 @@ function isInstalled () {
|
||||
|
||||
// unzips and makes path.txt point at the correct executable
|
||||
function extractFile (zipPath) {
|
||||
return extract(zipPath, { dir: path.join(__dirname, 'dist') })
|
||||
.then(() => fs.promises.writeFile(path.join(__dirname, 'path.txt'), platformPath));
|
||||
return new Promise((resolve, reject) => {
|
||||
const distPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist');
|
||||
|
||||
extract(zipPath, { dir: path.join(__dirname, 'dist') })
|
||||
.then(() => {
|
||||
// If the zip contains an "electron.d.ts" file,
|
||||
// move that up
|
||||
const srcTypeDefPath = path.join(distPath, 'electron.d.ts');
|
||||
const targetTypeDefPath = path.join(__dirname, 'electron.d.ts');
|
||||
const hasTypeDefinitions = fs.existsSync(srcTypeDefPath);
|
||||
|
||||
if (hasTypeDefinitions) {
|
||||
try {
|
||||
fs.renameSync(srcTypeDefPath, targetTypeDefPath);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Write a "path.txt" file.
|
||||
return fs.promises.writeFile(path.join(__dirname, 'path.txt'), platformPath);
|
||||
})
|
||||
.catch((err) => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
function getPlatformPath () {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "20.1.2",
|
||||
"version": "20.3.3",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -123,3 +123,10 @@ add_electron_deps_to_license_credits_file.patch
|
||||
feat_add_set_can_resize_mutator.patch
|
||||
cherry-pick-2083e894852c.patch
|
||||
cherry-pick-51daffbf5cd8.patch
|
||||
dpwa_enable_window_controls_overlay_by_default.patch
|
||||
create_browser_v8_snapshot_file_name_fuse.patch
|
||||
cherry-pick-fefd6198da31.patch
|
||||
cherry-pick-1eb1e18ad41d.patch
|
||||
cherry-pick-05a0d99c9715.patch
|
||||
cherry-pick-c83640db21b5.patch
|
||||
fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch
|
||||
|
||||
34
patches/chromium/cherry-pick-05a0d99c9715.patch
Normal file
34
patches/chromium/cherry-pick-05a0d99c9715.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: David Bokan <bokan@chromium.org>
|
||||
Date: Thu, 28 Jul 2022 18:09:13 +0000
|
||||
Subject: Prevent handling input for provisional frames
|
||||
|
||||
Bug: 1347644,1322812
|
||||
Change-Id: Ifd60f6aa593ce23ca6cbb65552fc9fb8f8690035
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3791883
|
||||
Commit-Queue: David Bokan <bokan@chromium.org>
|
||||
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1029361}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
|
||||
index fe775337fbc22817d7489df143821eea2d9425ec..13a241273090e54fabdba9d82510e36d2386c4a4 100644
|
||||
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
|
||||
@@ -2460,10 +2460,15 @@ WebInputEventResult WebFrameWidgetImpl::HandleInputEvent(
|
||||
DCHECK(!WebInputEvent::IsTouchEventType(input_event.GetType()));
|
||||
CHECK(LocalRootImpl());
|
||||
|
||||
+ // Clients shouldn't be dispatching events to a provisional frame but this
|
||||
+ // can happen. Ensure that event handling can assume we're in a committed
|
||||
+ // frame.
|
||||
+ if (IsProvisional())
|
||||
+ return WebInputEventResult::kHandledSuppressed;
|
||||
+
|
||||
// Only record metrics for the root frame.
|
||||
- if (ForTopMostMainFrame()) {
|
||||
+ if (ForTopMostMainFrame())
|
||||
GetPage()->GetVisualViewport().StartTrackingPinchStats();
|
||||
- }
|
||||
|
||||
// If a drag-and-drop operation is in progress, ignore input events except
|
||||
// PointerCancel and GestureLongPress.
|
||||
184
patches/chromium/cherry-pick-1eb1e18ad41d.patch
Normal file
184
patches/chromium/cherry-pick-1eb1e18ad41d.patch
Normal file
@@ -0,0 +1,184 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Date: Tue, 20 Sep 2022 17:43:47 +0000
|
||||
Subject: Add CSSTokenizer-created strings to CSSVariableData's backing strings
|
||||
|
||||
When computing the value of a registered custom property, we create
|
||||
a CSSVariableData object equivalent to the computed CSSValue by
|
||||
serializing that CSSValue to a String, then tokenizing that value.
|
||||
|
||||
The problem is that CSSTokenizer can create *new* string objects
|
||||
during the tokenization process (see calls to CSSTokenizer::
|
||||
RegisterString), without communicating that fact to the call-site.
|
||||
|
||||
Therefore, this CL adds a way to access those strings so they can
|
||||
be added to the backing strings of the CSSVariableData.
|
||||
|
||||
Also added a DCHECK to verify that we don't have any tokens with
|
||||
non-backed string pointers.
|
||||
|
||||
Fixed: 1358907
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3892782
|
||||
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
|
||||
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1046868}
|
||||
Change-Id: Ifb6d194508e99030a5a3ed5fbad5496b7263bdc1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3905727
|
||||
Auto-Submit: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#518}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/css_variable_data.cc b/third_party/blink/renderer/core/css/css_variable_data.cc
|
||||
index a2294cc70c59ac0357dddf0f7719cc3c09d23554..b3a61b312eb5f0360e8aa4cb706c60f0085fead9 100644
|
||||
--- a/third_party/blink/renderer/core/css/css_variable_data.cc
|
||||
+++ b/third_party/blink/renderer/core/css/css_variable_data.cc
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/core/css/css_variable_data.h"
|
||||
|
||||
+#include "base/containers/span.h"
|
||||
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
|
||||
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
|
||||
@@ -109,6 +110,51 @@ void CSSVariableData::ConsumeAndUpdateTokens(const CSSParserTokenRange& range) {
|
||||
UpdateTokens<UChar>(range, backing_string, tokens_);
|
||||
}
|
||||
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+template <typename CharacterType>
|
||||
+bool IsSubspan(base::span<const CharacterType> inner,
|
||||
+ base::span<const CharacterType> outer) {
|
||||
+ // Note that base::span uses CheckedContiguousIterator, which restricts
|
||||
+ // which comparisons are allowed. Therefore we must avoid begin()/end() here.
|
||||
+ return inner.data() >= outer.data() &&
|
||||
+ (inner.data() + inner.size()) <= (outer.data() + outer.size());
|
||||
+}
|
||||
+
|
||||
+bool TokenValueIsBacked(const CSSParserToken& token,
|
||||
+ const String& backing_string) {
|
||||
+ StringView value = token.Value();
|
||||
+ if (value.Is8Bit() != backing_string.Is8Bit())
|
||||
+ return false;
|
||||
+ return value.Is8Bit() ? IsSubspan(value.Span8(), backing_string.Span8())
|
||||
+ : IsSubspan(value.Span16(), backing_string.Span16());
|
||||
+}
|
||||
+
|
||||
+bool TokenValueIsBacked(const CSSParserToken& token,
|
||||
+ const Vector<String>& backing_strings) {
|
||||
+ DCHECK(token.HasStringBacking());
|
||||
+ for (const String& backing_string : backing_strings) {
|
||||
+ if (TokenValueIsBacked(token, backing_string)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+void CSSVariableData::VerifyStringBacking() const {
|
||||
+ for (const CSSParserToken& token : tokens_) {
|
||||
+ DCHECK(!token.HasStringBacking() ||
|
||||
+ TokenValueIsBacked(token, backing_strings_))
|
||||
+ << "Token value is not backed: " << token.Value().ToString();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+
|
||||
CSSVariableData::CSSVariableData(const CSSTokenizedValue& tokenized_value,
|
||||
bool is_animation_tainted,
|
||||
bool needs_variable_resolution,
|
||||
@@ -120,6 +166,9 @@ CSSVariableData::CSSVariableData(const CSSTokenizedValue& tokenized_value,
|
||||
base_url_(base_url.IsValid() ? base_url.GetString() : String()),
|
||||
charset_(charset) {
|
||||
ConsumeAndUpdateTokens(tokenized_value.range);
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ VerifyStringBacking();
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
}
|
||||
|
||||
const CSSValue* CSSVariableData::ParseForSyntax(
|
||||
diff --git a/third_party/blink/renderer/core/css/css_variable_data.h b/third_party/blink/renderer/core/css/css_variable_data.h
|
||||
index f042f85736c2c49f8337c29cb742976c5e97a14b..7be7d201313ec3e591e2c45c9fd5bda327856645 100644
|
||||
--- a/third_party/blink/renderer/core/css/css_variable_data.h
|
||||
+++ b/third_party/blink/renderer/core/css/css_variable_data.h
|
||||
@@ -100,11 +100,18 @@ class CORE_EXPORT CSSVariableData : public RefCounted<CSSVariableData> {
|
||||
has_font_units_(has_font_units),
|
||||
has_root_font_units_(has_root_font_units),
|
||||
base_url_(base_url),
|
||||
- charset_(charset) {}
|
||||
+ charset_(charset) {
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ VerifyStringBacking();
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ }
|
||||
CSSVariableData(const CSSVariableData&) = delete;
|
||||
CSSVariableData& operator=(const CSSVariableData&) = delete;
|
||||
|
||||
void ConsumeAndUpdateTokens(const CSSParserTokenRange&);
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ void VerifyStringBacking() const;
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
|
||||
// tokens_ may have raw pointers to string data, we store the String objects
|
||||
// owning that data in backing_strings_ to keep it alive alongside the
|
||||
diff --git a/third_party/blink/renderer/core/css/parser/css_tokenizer.h b/third_party/blink/renderer/core/css/parser/css_tokenizer.h
|
||||
index 817bcbd4b6b9a9a5519bb92d6870c5b16a19278f..682a44a478bcd0ee3aa1638601650fd420033625 100644
|
||||
--- a/third_party/blink/renderer/core/css/parser/css_tokenizer.h
|
||||
+++ b/third_party/blink/renderer/core/css/parser/css_tokenizer.h
|
||||
@@ -33,6 +33,7 @@ class CORE_EXPORT CSSTokenizer {
|
||||
wtf_size_t Offset() const { return input_.Offset(); }
|
||||
wtf_size_t PreviousOffset() const { return prev_offset_; }
|
||||
StringView StringRangeAt(wtf_size_t start, wtf_size_t length) const;
|
||||
+ const Vector<String>& StringPool() const { return string_pool_; }
|
||||
|
||||
private:
|
||||
CSSParserToken TokenizeSingle();
|
||||
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
|
||||
index 6739b9de4b500d6173c04966905e26f856594502..f0082d88d70d4ea76604cfac77c09727de134f2a 100644
|
||||
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
|
||||
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
|
||||
@@ -2176,6 +2176,10 @@ StyleBuilderConverter::ConvertRegisteredPropertyVariableData(
|
||||
|
||||
Vector<String> backing_strings;
|
||||
backing_strings.push_back(text);
|
||||
+ // CSSTokenizer may allocate new strings for some tokens (e.g. for escapes)
|
||||
+ // and produce tokens that point to those strings. We need to retain those
|
||||
+ // strings (if any) as well.
|
||||
+ backing_strings.AppendVector(tokenizer.StringPool());
|
||||
|
||||
const bool has_font_units = false;
|
||||
const bool has_root_font_units = false;
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html
|
||||
index f03b257246e520bd93055203a5cb27188babc8ca..168495247a3b16a2203fb361f662b6db83044d09 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html
|
||||
@@ -167,4 +167,6 @@ test_computed_value('<resolution>', '1dppx', '1dppx');
|
||||
test_computed_value('<resolution>', '96dpi', '1dppx');
|
||||
test_computed_value('<resolution>', 'calc(1dppx + 96dpi)', '2dppx');
|
||||
|
||||
+test_computed_value('*', 'url(why)', 'url(why)');
|
||||
+
|
||||
</script>
|
||||
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt
|
||||
index 3823a752b99f506d11c50aee36474c6c51c849cd..eeed0dfc0def17b1ba636f7f6a076caf770e1327 100644
|
||||
--- a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt
|
||||
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt
|
||||
@@ -1,5 +1,5 @@
|
||||
This is a testharness.js-based test.
|
||||
-Found 60 tests; 59 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||
+Found 61 tests; 60 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||
PASS <length> values computed are correctly via var()-reference
|
||||
PASS <length> values computed are correctly via var()-reference when font-size is inherited
|
||||
PASS <length> values are computed correctly when font-size is inherited [14em]
|
||||
@@ -60,5 +60,6 @@ PASS * values are computed correctly [50dpi]
|
||||
PASS <resolution> values are computed correctly [1dppx]
|
||||
PASS <resolution> values are computed correctly [96dpi]
|
||||
FAIL <resolution> values are computed correctly [calc(1dppx + 96dpi)] assert_equals: expected "2dppx" but got "0dppx"
|
||||
+PASS * values are computed correctly [url(why)]
|
||||
Harness: the test ran to completion.
|
||||
|
||||
122
patches/chromium/cherry-pick-c83640db21b5.patch
Normal file
122
patches/chromium/cherry-pick-c83640db21b5.patch
Normal file
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Wed, 5 Oct 2022 06:03:23 +0000
|
||||
Subject: build: set DTSDKBuild correctly when generating plist files
|
||||
|
||||
Currently we set DTSDKBuild to the version of the SDK used to build
|
||||
Chromium. This value is supposed to be the build version (this is
|
||||
what xcode sets it to for instance). We read this value out of the
|
||||
SDK directly and use it instead.
|
||||
|
||||
Change-Id: Ieb7990f13095683ad8c026f027b2605ae39523a4
|
||||
|
||||
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni
|
||||
index 7b1761607c853ae79619d6b872167a00a39f8236..c8e07ad62519236ead55c9b7ce1b1a4c3d5491af 100644
|
||||
--- a/build/config/mac/mac_sdk.gni
|
||||
+++ b/build/config/mac/mac_sdk.gni
|
||||
@@ -40,6 +40,11 @@ declare_args() {
|
||||
# will fail.
|
||||
mac_sdk_official_version = "12.3"
|
||||
|
||||
+ # The SDK build version used when making official builds. This is a single
|
||||
+ # exact version found at "System/Library/CoreServices/SystemVersion.plist"
|
||||
+ # inside the SDK.
|
||||
+ mac_sdk_official_build_version = "21E226"
|
||||
+
|
||||
# Production builds should use hermetic Xcode. If you want to do production
|
||||
# builds with system Xcode to test new SDKs, set this.
|
||||
# Don't set this on any bots.
|
||||
@@ -101,11 +106,13 @@ if (use_system_xcode) {
|
||||
find_sdk_args = [
|
||||
"--print_sdk_path",
|
||||
"--print_bin_path",
|
||||
+ "--print_sdk_build",
|
||||
mac_sdk_min,
|
||||
]
|
||||
find_sdk_lines =
|
||||
exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines")
|
||||
- mac_sdk_version = find_sdk_lines[2]
|
||||
+ mac_sdk_version = find_sdk_lines[3]
|
||||
+ mac_sdk_build_version = find_sdk_lines[2]
|
||||
if (mac_sdk_path == "") {
|
||||
mac_sdk_path = find_sdk_lines[0]
|
||||
mac_bin_path = find_sdk_lines[1]
|
||||
@@ -114,6 +121,7 @@ if (use_system_xcode) {
|
||||
}
|
||||
} else {
|
||||
mac_sdk_version = mac_sdk_official_version
|
||||
+ mac_sdk_build_version = mac_sdk_official_build_version
|
||||
_dev = _hermetic_xcode_path + "/Contents/Developer"
|
||||
_sdk = "MacOSX${mac_sdk_version}.sdk"
|
||||
mac_sdk_path = _dev + "/Platforms/MacOSX.platform/Developer/SDKs/$_sdk"
|
||||
diff --git a/build/config/mac/rules.gni b/build/config/mac/rules.gni
|
||||
index 03073f830401c4891376a3b59e2e7a870e3d34b7..04d403054c1a83fcbbc70be7cfd239ecbec315d3 100644
|
||||
--- a/build/config/mac/rules.gni
|
||||
+++ b/build/config/mac/rules.gni
|
||||
@@ -41,7 +41,7 @@ template("mac_info_plist") {
|
||||
apple_info_plist(target_name) {
|
||||
format = "xml1"
|
||||
extra_substitutions = [
|
||||
- "MAC_SDK_BUILD=$mac_sdk_version",
|
||||
+ "MAC_SDK_BUILD=$mac_sdk_build_version",
|
||||
"MAC_SDK_NAME=$mac_sdk_name$mac_sdk_version",
|
||||
"MACOSX_DEPLOYMENT_TARGET=$mac_deployment_target",
|
||||
"CHROMIUM_MIN_SYSTEM_VERSION=$mac_min_system_version",
|
||||
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py
|
||||
index d86f3109357a9246d570cb02992dc82552ba7c20..b2400c7e8c70957e364444f509880900ce3b641f 100755
|
||||
--- a/build/mac/find_sdk.py
|
||||
+++ b/build/mac/find_sdk.py
|
||||
@@ -24,6 +24,7 @@ Sample Output:
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
+import plistlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -51,6 +52,9 @@ def main():
|
||||
parser.add_option("--print_bin_path",
|
||||
action="store_true", dest="print_bin_path", default=False,
|
||||
help="Additionally print the path the toolchain bin dir.")
|
||||
+ parser.add_option("--print_sdk_build",
|
||||
+ action="store_true", dest="print_sdk_build", default=False,
|
||||
+ help="Additionally print the build version of the SDK.")
|
||||
options, args = parser.parse_args()
|
||||
if len(args) != 1:
|
||||
parser.error('Please specify a minimum SDK version')
|
||||
@@ -80,20 +84,30 @@ def main():
|
||||
if not sdks:
|
||||
raise Exception('No %s+ SDK found' % min_sdk_version)
|
||||
best_sdk = sorted(sdks, key=parse_version)[0]
|
||||
+ sdk_name = 'MacOSX' + best_sdk + '.sdk'
|
||||
+ sdk_path = os.path.join(sdk_dir, sdk_name)
|
||||
|
||||
if options.print_sdk_path:
|
||||
- sdk_name = 'MacOSX' + best_sdk + '.sdk'
|
||||
- print(os.path.join(sdk_dir, sdk_name))
|
||||
+ print(sdk_path)
|
||||
|
||||
if options.print_bin_path:
|
||||
bin_path = 'Toolchains/XcodeDefault.xctoolchain/usr/bin/'
|
||||
print(os.path.join(dev_dir, bin_path))
|
||||
|
||||
- return best_sdk
|
||||
+ if options.print_sdk_build:
|
||||
+ system_version_plist = os.path.join(sdk_path,
|
||||
+ 'System/Library/CoreServices/SystemVersion.plist')
|
||||
+ with open(system_version_plist, 'rb') as f:
|
||||
+ system_version_info = plistlib.load(f)
|
||||
+ if 'ProductBuildVersion' not in system_version_info:
|
||||
+ raise Exception('Failed to determine ProductBuildVersion' +
|
||||
+ 'for SDK at path %s' % system_version_plist)
|
||||
+ print(system_version_info['ProductBuildVersion'])
|
||||
+
|
||||
+ print(best_sdk)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.platform != 'darwin':
|
||||
raise Exception("This script only runs on Mac")
|
||||
- print(main())
|
||||
- sys.exit(0)
|
||||
+ sys.exit(main())
|
||||
305
patches/chromium/cherry-pick-fefd6198da31.patch
Normal file
305
patches/chromium/cherry-pick-fefd6198da31.patch
Normal file
@@ -0,0 +1,305 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Wagner <benjaminwagner@google.com>
|
||||
Date: Tue, 20 Sep 2022 18:38:53 +0000
|
||||
Subject: Fix races in FrameQueueUnderlyingSource related to
|
||||
CrossThreadPersistent
|
||||
|
||||
The repro in bug 1323488 unfortunately does not reliably reproduce
|
||||
the races when run as a web test. I was also not able to repro the
|
||||
races in a unit test.
|
||||
|
||||
There are actually three fixes in this CL; it was easiest to fix them
|
||||
all together so that I can run the repro locally for an extended period
|
||||
without it being stopped by a crash.
|
||||
|
||||
The underlying cause for all three races is that CrossThreadPersistent
|
||||
can refer to an object whose heap has already been destroyed. When
|
||||
accessed on the thread corresponding to that heap, there is no race,
|
||||
but when accessed from a different thread, there is a period of time
|
||||
after the heap is destroyed before the CrossThreadPersistent is
|
||||
cleared.
|
||||
|
||||
1. The FrameQueueUnderlyingSource::transferred_source_ member's pointer
|
||||
is accessed in FrameQueueUnderlyingSource::Close. This CL adds a
|
||||
callback to clear the pointer in
|
||||
TransferredFrameQueueUnderlyingSource::ContextDestroyed.
|
||||
|
||||
2. The TransferredFrameQueueUnderlyingSource constructor takes a raw
|
||||
pointer to the original FrameQueueUnderlyingSource, which is
|
||||
associated with a different thread. GC won't be able to update this
|
||||
raw pointer since it's on the wrong stack. This CL changes the raw
|
||||
pointer to a CrossThreadPersistent which is visible to GC.
|
||||
|
||||
3. Same as 2, but for the callstack ConnectHostCallback,
|
||||
MediaStream(Audio|Video)TrackUnderlyingSource::OnSourceTransferStarted
|
||||
and FrameQueueUnderlyingSource::TransferSource.
|
||||
|
||||
(cherry picked from commit 63ce9c40e1a67395278dfc70ecfb545a818747bb)
|
||||
|
||||
Bug: 1323488
|
||||
Change-Id: Id63484eebefd2e003959b25bd752ac8263caab4f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3865452
|
||||
Commit-Queue: Ben Wagner <benjaminwagner@google.com>
|
||||
Reviewed-by: Thomas Guilbert <tguilbert@chromium.org>
|
||||
Auto-Submit: Ben Wagner <benjaminwagner@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1041434}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3908010
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Reviewed-by: Srinivas Sista <srinivassista@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#521}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc
|
||||
index 2cc89e8cd32421bf80b262bac2e4a7cb685db62f..ab41fa086ad9eb8c1cd66db74ea1f05a66ac56a4 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc
|
||||
@@ -19,10 +19,13 @@ FrameQueueTransferringOptimizer<NativeFrameType>::
|
||||
FrameQueueHost* host,
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
wtf_size_t max_queue_size,
|
||||
- ConnectHostCallback connect_host_callback)
|
||||
+ ConnectHostCallback connect_host_callback,
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback)
|
||||
: host_(host),
|
||||
host_runner_(std::move(host_runner)),
|
||||
connect_host_callback_(std::move(connect_host_callback)),
|
||||
+ transferred_source_destroyed_callback_(
|
||||
+ std::move(transferred_source_destroyed_callback)),
|
||||
max_queue_size_(max_queue_size) {}
|
||||
|
||||
template <typename NativeFrameType>
|
||||
@@ -40,7 +43,8 @@ FrameQueueTransferringOptimizer<NativeFrameType>::PerformInProcessOptimization(
|
||||
|
||||
auto* source = MakeGarbageCollected<
|
||||
TransferredFrameQueueUnderlyingSource<NativeFrameType>>(
|
||||
- script_state, host, host_runner_);
|
||||
+ script_state, host, host_runner_,
|
||||
+ std::move(transferred_source_destroyed_callback_));
|
||||
|
||||
PostCrossThreadTask(
|
||||
*host_runner_, FROM_HERE,
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h
|
||||
index 6d33945b7c840e55ae73a1efd1f1cf33ccfaaa71..336073235ba7f6c05cf2cf19fccbfac0be9597c9 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h
|
||||
@@ -25,13 +25,15 @@ class FrameQueueTransferringOptimizer final
|
||||
|
||||
using ConnectHostCallback = CrossThreadOnceFunction<void(
|
||||
scoped_refptr<base::SequencedTaskRunner>,
|
||||
- TransferredFrameQueueUnderlyingSource<NativeFrameType>*)>;
|
||||
+ CrossThreadPersistent<
|
||||
+ TransferredFrameQueueUnderlyingSource<NativeFrameType>>)>;
|
||||
|
||||
FrameQueueTransferringOptimizer(
|
||||
FrameQueueHost*,
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
wtf_size_t max_queue_size,
|
||||
- ConnectHostCallback callback);
|
||||
+ ConnectHostCallback connect_host_callback,
|
||||
+ CrossThreadOnceFunction<void()> transferred_source_destroyed_callback);
|
||||
~FrameQueueTransferringOptimizer() override = default;
|
||||
|
||||
UnderlyingSourceBase* PerformInProcessOptimization(
|
||||
@@ -41,6 +43,7 @@ class FrameQueueTransferringOptimizer final
|
||||
CrossThreadWeakPersistent<FrameQueueHost> host_;
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner_;
|
||||
ConnectHostCallback connect_host_callback_;
|
||||
+ CrossThreadOnceFunction<void()> transferred_source_destroyed_callback_;
|
||||
wtf_size_t max_queue_size_;
|
||||
};
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
|
||||
index b93b67f131e1e58118e32d2c9b29e472a28d4664..fcd676b3035e19c6e0b28ee1c44109c6737a1c35 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
|
||||
@@ -266,15 +266,22 @@ double FrameQueueUnderlyingSource<NativeFrameType>::DesiredSizeForTesting()
|
||||
|
||||
template <typename NativeFrameType>
|
||||
void FrameQueueUnderlyingSource<NativeFrameType>::TransferSource(
|
||||
- FrameQueueUnderlyingSource<NativeFrameType>* transferred_source) {
|
||||
+ CrossThreadPersistent<FrameQueueUnderlyingSource<NativeFrameType>>
|
||||
+ transferred_source) {
|
||||
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
|
||||
MutexLocker locker(mutex_);
|
||||
DCHECK(!transferred_source_);
|
||||
- transferred_source_ = transferred_source;
|
||||
+ transferred_source_ = std::move(transferred_source);
|
||||
CloseController();
|
||||
frame_queue_handle_.Invalidate();
|
||||
}
|
||||
|
||||
+template <typename NativeFrameType>
|
||||
+void FrameQueueUnderlyingSource<NativeFrameType>::ClearTransferredSource() {
|
||||
+ MutexLocker locker(mutex_);
|
||||
+ transferred_source_.Clear();
|
||||
+}
|
||||
+
|
||||
template <typename NativeFrameType>
|
||||
void FrameQueueUnderlyingSource<NativeFrameType>::CloseController() {
|
||||
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
|
||||
index 7e097b4eb6e9085be73ceb7fd84a4588baf64471..3908909d04f5b6cf4a9be4a3a3e004c3775a3d42 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
|
||||
@@ -85,7 +85,13 @@ class FrameQueueUnderlyingSource
|
||||
// QueueFrame(). |transferred_source| will pull frames from the same circular
|
||||
// queue. Must be called on |realm_task_runner_|.
|
||||
void TransferSource(
|
||||
- FrameQueueUnderlyingSource<NativeFrameType>* transferred_source);
|
||||
+ CrossThreadPersistent<FrameQueueUnderlyingSource<NativeFrameType>>
|
||||
+ transferred_source);
|
||||
+
|
||||
+ // Due to a potential race condition between |transferred_source_|'s heap
|
||||
+ // being destroyed and the Close() method being called, we need to explicitly
|
||||
+ // clear |transferred_source_| when its context is being destroyed.
|
||||
+ void ClearTransferredSource();
|
||||
|
||||
protected:
|
||||
bool MustUseMonitor() const;
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
|
||||
index bfc966452e4134e5133d559698497ce82f89aad4..da9a4bffc3a8c9ec5a1595a7cd78110bfadbfb5e 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
|
||||
@@ -93,14 +93,17 @@ MediaStreamAudioTrackUnderlyingSource::GetTransferringOptimizer() {
|
||||
this, GetRealmRunner(), MaxQueueSize(),
|
||||
CrossThreadBindOnce(
|
||||
&MediaStreamAudioTrackUnderlyingSource::OnSourceTransferStarted,
|
||||
+ WrapCrossThreadWeakPersistent(this)),
|
||||
+ CrossThreadBindOnce(
|
||||
+ &MediaStreamAudioTrackUnderlyingSource::ClearTransferredSource,
|
||||
WrapCrossThreadWeakPersistent(this)));
|
||||
}
|
||||
|
||||
void MediaStreamAudioTrackUnderlyingSource::OnSourceTransferStarted(
|
||||
scoped_refptr<base::SequencedTaskRunner> transferred_runner,
|
||||
- TransferredAudioDataQueueUnderlyingSource* source) {
|
||||
+ CrossThreadPersistent<TransferredAudioDataQueueUnderlyingSource> source) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
- TransferSource(source);
|
||||
+ TransferSource(std::move(source));
|
||||
RecordBreakoutBoxUsage(BreakoutBoxUsage::kReadableAudioWorker);
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
|
||||
index 19a290ea6b83e4b56b8d96cb7632fca55bd65fd0..73c16dc5ff3855e258e1e70397def478485f1481 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
|
||||
@@ -56,7 +56,7 @@ class MODULES_EXPORT MediaStreamAudioTrackUnderlyingSource
|
||||
void DisconnectFromTrack();
|
||||
void OnSourceTransferStarted(
|
||||
scoped_refptr<base::SequencedTaskRunner> transferred_runner,
|
||||
- TransferredAudioDataQueueUnderlyingSource* source);
|
||||
+ CrossThreadPersistent<TransferredAudioDataQueueUnderlyingSource> source);
|
||||
|
||||
// Only used to prevent the gargabe collector from reclaiming the media
|
||||
// stream track processor that created |this|.
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
|
||||
index bcb941aca4e4d0729dc1253e01ef477fdaae1877..e748bf6eaf8f9d1acf8519c38a5a8cb53b031d0e 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
|
||||
@@ -66,6 +66,9 @@ MediaStreamVideoTrackUnderlyingSource::GetStreamTransferOptimizer() {
|
||||
this, GetRealmRunner(), MaxQueueSize(),
|
||||
CrossThreadBindOnce(
|
||||
&MediaStreamVideoTrackUnderlyingSource::OnSourceTransferStarted,
|
||||
+ WrapCrossThreadWeakPersistent(this)),
|
||||
+ CrossThreadBindOnce(
|
||||
+ &MediaStreamVideoTrackUnderlyingSource::ClearTransferredSource,
|
||||
WrapCrossThreadWeakPersistent(this)));
|
||||
}
|
||||
|
||||
@@ -76,9 +79,9 @@ MediaStreamVideoTrackUnderlyingSource::GetIOTaskRunner() {
|
||||
|
||||
void MediaStreamVideoTrackUnderlyingSource::OnSourceTransferStarted(
|
||||
scoped_refptr<base::SequencedTaskRunner> transferred_runner,
|
||||
- TransferredVideoFrameQueueUnderlyingSource* source) {
|
||||
+ CrossThreadPersistent<TransferredVideoFrameQueueUnderlyingSource> source) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
- TransferSource(source);
|
||||
+ TransferSource(std::move(source));
|
||||
RecordBreakoutBoxUsage(BreakoutBoxUsage::kReadableVideoWorker);
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
|
||||
index 1bbd4f6bbf20eaf168bf1319f1b35819dabe3cce..8964eb5eb83964c4bb2633092a12cb144da4e9b0 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
|
||||
@@ -59,8 +59,9 @@ class MODULES_EXPORT MediaStreamVideoTrackUnderlyingSource
|
||||
bool StartFrameDelivery() override;
|
||||
void StopFrameDelivery() override;
|
||||
|
||||
- void OnSourceTransferStarted(scoped_refptr<base::SequencedTaskRunner>,
|
||||
- TransferredVideoFrameQueueUnderlyingSource*);
|
||||
+ void OnSourceTransferStarted(
|
||||
+ scoped_refptr<base::SequencedTaskRunner>,
|
||||
+ CrossThreadPersistent<TransferredVideoFrameQueueUnderlyingSource>);
|
||||
|
||||
void OnFrameFromTrack(
|
||||
scoped_refptr<media::VideoFrame> media_frame,
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc
|
||||
index 5c62b8f1b752c24f8b8d0048d646ea64dba0e49c..e38173482d455788861a1d831dd3422119d4d4d6 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc
|
||||
@@ -15,11 +15,14 @@ template <typename NativeFrameType>
|
||||
TransferredFrameQueueUnderlyingSource<NativeFrameType>::
|
||||
TransferredFrameQueueUnderlyingSource(
|
||||
ScriptState* script_state,
|
||||
- FrameQueueHost* host,
|
||||
- scoped_refptr<base::SequencedTaskRunner> host_runner)
|
||||
+ CrossThreadPersistent<FrameQueueHost> host,
|
||||
+ scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback)
|
||||
: FrameQueueUnderlyingSource<NativeFrameType>(script_state, host),
|
||||
host_runner_(host_runner),
|
||||
- host_(host) {}
|
||||
+ host_(std::move(host)),
|
||||
+ transferred_source_destroyed_callback_(
|
||||
+ std::move(transferred_source_destroyed_callback)) {}
|
||||
|
||||
template <typename NativeFrameType>
|
||||
bool TransferredFrameQueueUnderlyingSource<
|
||||
@@ -44,6 +47,13 @@ void TransferredFrameQueueUnderlyingSource<
|
||||
CrossThreadBindOnce(&FrameQueueHost::Close, host_));
|
||||
}
|
||||
|
||||
+template <typename NativeFrameType>
|
||||
+void TransferredFrameQueueUnderlyingSource<
|
||||
+ NativeFrameType>::ContextDestroyed() {
|
||||
+ std::move(transferred_source_destroyed_callback_).Run();
|
||||
+ FrameQueueUnderlyingSource<NativeFrameType>::ContextDestroyed();
|
||||
+}
|
||||
+
|
||||
template <typename NativeFrameType>
|
||||
void TransferredFrameQueueUnderlyingSource<NativeFrameType>::Trace(
|
||||
Visitor* visitor) const {
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h
|
||||
index 5f8a36719407a404756d672530c0b9fcff9d6924..7cd3270fbb3cf5b0e2c09b16000ea5c0e4247866 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h
|
||||
@@ -19,8 +19,9 @@ class TransferredFrameQueueUnderlyingSource
|
||||
|
||||
TransferredFrameQueueUnderlyingSource(
|
||||
ScriptState*,
|
||||
- FrameQueueHost*,
|
||||
- scoped_refptr<base::SequencedTaskRunner> host_runner);
|
||||
+ CrossThreadPersistent<FrameQueueHost>,
|
||||
+ scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback);
|
||||
~TransferredFrameQueueUnderlyingSource() override = default;
|
||||
|
||||
TransferredFrameQueueUnderlyingSource(
|
||||
@@ -32,11 +33,15 @@ class TransferredFrameQueueUnderlyingSource
|
||||
bool StartFrameDelivery() override;
|
||||
void StopFrameDelivery() override;
|
||||
|
||||
+ // ExecutionLifecycleObserver
|
||||
+ void ContextDestroyed() override;
|
||||
+
|
||||
void Trace(Visitor*) const override;
|
||||
|
||||
private:
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner_;
|
||||
CrossThreadPersistent<FrameQueueHost> host_;
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback_;
|
||||
};
|
||||
|
||||
extern template class MODULES_EXTERN_TEMPLATE_EXPORT
|
||||
156
patches/chromium/create_browser_v8_snapshot_file_name_fuse.patch
Normal file
156
patches/chromium/create_browser_v8_snapshot_file_name_fuse.patch
Normal file
@@ -0,0 +1,156 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ryan Manuel <ryanm@cypress.io>
|
||||
Date: Thu, 4 Aug 2022 22:37:01 -0500
|
||||
Subject: Create browser v8 snapshot file name fuse
|
||||
|
||||
By default, chromium sets up one v8 snapshot to be used in all v8 contexts. This patch allows consumers
|
||||
to have a dedicated browser process v8 snapshot defined by the file `browser_v8_context_snapshot.bin`.
|
||||
|
||||
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
|
||||
index 328f8b800c36544f7906536416ac61dc87cc45d3..2f973efcf3e38edcc74060929339fc21bdf0aa3b 100644
|
||||
--- a/content/app/content_main_runner_impl.cc
|
||||
+++ b/content/app/content_main_runner_impl.cc
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "base/process/memory.h"
|
||||
#include "base/process/process.h"
|
||||
#include "base/process/process_handle.h"
|
||||
+#include "base/strings/string_piece.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/task/thread_pool/thread_pool_instance.h"
|
||||
@@ -232,8 +233,13 @@ std::string GetSnapshotDataDescriptor(const base::CommandLine& command_line) {
|
||||
|
||||
#endif
|
||||
|
||||
-void LoadV8SnapshotFile(const base::CommandLine& command_line) {
|
||||
+void LoadV8SnapshotFile(const raw_ptr<ContentMainDelegate> delegate, const base::CommandLine& command_line) {
|
||||
const gin::V8SnapshotFileType snapshot_type = GetSnapshotType(command_line);
|
||||
+ base::StringPiece browser_v8_snapshot_file_name = delegate->GetBrowserV8SnapshotFilename();
|
||||
+ if (!browser_v8_snapshot_file_name.empty()) {
|
||||
+ gin::V8Initializer::LoadV8SnapshotFromFileName(browser_v8_snapshot_file_name, snapshot_type);
|
||||
+ return;
|
||||
+ }
|
||||
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
|
||||
base::FileDescriptorStore& file_descriptor_store =
|
||||
base::FileDescriptorStore::GetInstance();
|
||||
@@ -262,11 +268,12 @@ bool ShouldLoadV8Snapshot(const base::CommandLine& command_line,
|
||||
|
||||
#endif // V8_USE_EXTERNAL_STARTUP_DATA
|
||||
|
||||
-void LoadV8SnapshotIfNeeded(const base::CommandLine& command_line,
|
||||
+void LoadV8SnapshotIfNeeded(const raw_ptr<ContentMainDelegate> delegate,
|
||||
+ const base::CommandLine& command_line,
|
||||
const std::string& process_type) {
|
||||
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
|
||||
if (ShouldLoadV8Snapshot(command_line, process_type))
|
||||
- LoadV8SnapshotFile(command_line);
|
||||
+ LoadV8SnapshotFile(delegate, command_line);
|
||||
#endif // V8_USE_EXTERNAL_STARTUP_DATA
|
||||
}
|
||||
|
||||
@@ -917,7 +924,7 @@ int ContentMainRunnerImpl::Initialize(ContentMainParams params) {
|
||||
return TerminateForFatalInitializationError();
|
||||
#endif // BUILDFLAG(IS_ANDROID) && (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE)
|
||||
|
||||
- LoadV8SnapshotIfNeeded(command_line, process_type);
|
||||
+ LoadV8SnapshotIfNeeded(delegate_, command_line, process_type);
|
||||
|
||||
blink::TrialTokenValidator::SetOriginTrialPolicyGetter(
|
||||
base::BindRepeating([]() -> blink::OriginTrialPolicy* {
|
||||
diff --git a/content/public/app/content_main_delegate.cc b/content/public/app/content_main_delegate.cc
|
||||
index ce6b8b454d0cc57ec4de81c7a19b5e0f0087a162..c421d3b5bc02b702e89c714d3d521207cbca156b 100644
|
||||
--- a/content/public/app/content_main_delegate.cc
|
||||
+++ b/content/public/app/content_main_delegate.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "content/public/app/content_main_delegate.h"
|
||||
|
||||
#include "base/check.h"
|
||||
+#include "base/strings/string_piece.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "content/public/common/content_client.h"
|
||||
@@ -55,6 +56,10 @@ ContentMainDelegate::CreateVariationsIdsProvider() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+base::StringPiece ContentMainDelegate::GetBrowserV8SnapshotFilename() {
|
||||
+ return base::StringPiece();
|
||||
+}
|
||||
+
|
||||
ContentClient* ContentMainDelegate::CreateContentClient() {
|
||||
return new ContentClient();
|
||||
}
|
||||
diff --git a/content/public/app/content_main_delegate.h b/content/public/app/content_main_delegate.h
|
||||
index f81430b564a3cf44c2168e18c4c53c6629353d75..34a5531cd33b439114a796adc71af7251b6b1f81 100644
|
||||
--- a/content/public/app/content_main_delegate.h
|
||||
+++ b/content/public/app/content_main_delegate.h
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
+#include "base/strings/string_piece.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/common/content_export.h"
|
||||
#include "content/public/common/main_function_params.h"
|
||||
@@ -149,6 +150,8 @@ class CONTENT_EXPORT ContentMainDelegate {
|
||||
virtual bool ShouldHandleConsoleControlEvents();
|
||||
#endif
|
||||
|
||||
+ virtual base::StringPiece GetBrowserV8SnapshotFilename();
|
||||
+
|
||||
protected:
|
||||
friend class ContentClientCreator;
|
||||
friend class ContentClientInitializer;
|
||||
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc
|
||||
index 34a65998cbaa22241fd7c6cc60d8ab01982ca3ce..68c12e9bb1f334d6fec050018da8bc0a6db4a850 100644
|
||||
--- a/gin/v8_initializer.cc
|
||||
+++ b/gin/v8_initializer.cc
|
||||
@@ -512,8 +512,7 @@ void V8Initializer::GetV8ExternalSnapshotData(const char** snapshot_data_out,
|
||||
|
||||
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
|
||||
|
||||
-// static
|
||||
-void V8Initializer::LoadV8Snapshot(V8SnapshotFileType snapshot_file_type) {
|
||||
+void V8Initializer::LoadV8SnapshotFromFileName(base::StringPiece file_name, V8SnapshotFileType snapshot_file_type) {
|
||||
if (g_mapped_snapshot) {
|
||||
// TODO(crbug.com/802962): Confirm not loading different type of snapshot
|
||||
// files in a process.
|
||||
@@ -522,10 +521,17 @@ void V8Initializer::LoadV8Snapshot(V8SnapshotFileType snapshot_file_type) {
|
||||
|
||||
base::MemoryMappedFile::Region file_region;
|
||||
base::File file =
|
||||
- OpenV8File(GetSnapshotFileName(snapshot_file_type), &file_region);
|
||||
+ OpenV8File(file_name.data(), &file_region);
|
||||
LoadV8SnapshotFromFile(std::move(file), &file_region, snapshot_file_type);
|
||||
}
|
||||
|
||||
+// static
|
||||
+void V8Initializer::LoadV8Snapshot(V8SnapshotFileType snapshot_file_type) {
|
||||
+ const char* file_name = GetSnapshotFileName(snapshot_file_type);
|
||||
+
|
||||
+ LoadV8SnapshotFromFileName(file_name, snapshot_file_type);
|
||||
+}
|
||||
+
|
||||
// static
|
||||
void V8Initializer::LoadV8SnapshotFromFile(
|
||||
base::File snapshot_file,
|
||||
diff --git a/gin/v8_initializer.h b/gin/v8_initializer.h
|
||||
index 13a120c7fe8e69a44793473f3124c33d572a07a3..acb294780873c1d84546eb2b9acc00f86838361d 100644
|
||||
--- a/gin/v8_initializer.h
|
||||
+++ b/gin/v8_initializer.h
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/memory_mapped_file.h"
|
||||
+#include "base/strings/string_piece.h"
|
||||
#include "build/build_config.h"
|
||||
#include "gin/array_buffer.h"
|
||||
#include "gin/gin_export.h"
|
||||
@@ -42,6 +43,7 @@ class GIN_EXPORT V8Initializer {
|
||||
int* snapshot_size_out);
|
||||
|
||||
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
|
||||
+ static void LoadV8SnapshotFromFileName(base::StringPiece file_name, V8SnapshotFileType snapshot_file_type);
|
||||
// Load V8 snapshot from default resources, if they are available.
|
||||
static void LoadV8Snapshot(
|
||||
V8SnapshotFileType snapshot_file_type = V8SnapshotFileType::kDefault);
|
||||
@@ -0,0 +1,125 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hassan Talat <hatalat@microsoft.com>
|
||||
Date: Mon, 13 Jun 2022 21:27:53 +0000
|
||||
Subject: dpwa: Enable Window Controls Overlay by default
|
||||
|
||||
This reverts commit d61c4042374672712176e43e33f39a1e66da4faa.
|
||||
I2S: https://groups.google.com/a/chromium.org/g/blink-dev/c/guI1QCPJTAA
|
||||
|
||||
Bug: 937121
|
||||
Change-Id: I3dfebec2356c7a12fd7eab32f12ef8d9e4bf6ee6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3430266
|
||||
Commit-Queue: Alex Russell <slightlyoff@chromium.org>
|
||||
Reviewed-by: Alex Russell <slightlyoff@chromium.org>
|
||||
Reviewed-by: Avi Drissman <avi@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1013665}
|
||||
|
||||
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
|
||||
index ee8c06004a0b38883d60b2bd3e6d1ac5cdf93277..3169ed9adc24961050500ad6fb62cec6b522eac1 100644
|
||||
--- a/content/public/common/content_features.cc
|
||||
+++ b/content/public/common/content_features.cc
|
||||
@@ -1025,7 +1025,7 @@ const base::Feature kV8VmFuture{"V8VmFuture",
|
||||
|
||||
// Enable window controls overlays for desktop PWAs
|
||||
const base::Feature kWebAppWindowControlsOverlay{
|
||||
- "WebAppWindowControlsOverlay", base::FEATURE_DISABLED_BY_DEFAULT};
|
||||
+ "WebAppWindowControlsOverlay", base::FEATURE_ENABLED_BY_DEFAULT};
|
||||
|
||||
// Enable WebAssembly baseline compilation (Liftoff).
|
||||
const base::Feature kWebAssemblyBaseline{"WebAssemblyBaseline",
|
||||
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
index 3efb1d07380a117f0a6fe0c07890d39d94e5f6ec..f99b90db892d6190c8f7146d2892ca6f6b26ea2b 100644
|
||||
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
@@ -2575,7 +2575,7 @@
|
||||
name: "WebAppWindowControlsOverlay",
|
||||
origin_trial_feature_name: "WebAppWindowControlsOverlay",
|
||||
origin_trial_os: ["win", "mac", "linux", "chromeos"],
|
||||
- status: "experimental",
|
||||
+ status: "stable",
|
||||
},
|
||||
{
|
||||
name: "WebAssemblyCSP",
|
||||
diff --git a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
|
||||
index a2bac6e1f0fc6404a8fabbab87cd78da3e50570c..d6e4d3d5846ec3de2056af5a89a74f168a0e216d 100644
|
||||
--- a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
|
||||
+++ b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
|
||||
@@ -77,6 +77,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.x is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null
|
||||
PASS window.cached_navigator_virtualKeyboard.overlaysContent is false
|
||||
+PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null
|
||||
+PASS window.cached_navigator_windowControlsOverlay.visible is false
|
||||
PASS window.cached_navigator_xr.ondevicechange is null
|
||||
PASS window.cached_performance.onresourcetimingbufferfull is null
|
||||
PASS window.cached_performance_navigation.redirectCount is 0
|
||||
diff --git a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
|
||||
index 9b413dea03d864d6cef496279187b39cf81ba4b0..5cfdedb36e5f9bd0dbfae11d5ba5cc1172823071 100644
|
||||
--- a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
|
||||
+++ b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
|
||||
@@ -77,6 +77,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.x is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null
|
||||
PASS window.cached_navigator_virtualKeyboard.overlaysContent is false
|
||||
+PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null
|
||||
+PASS window.cached_navigator_windowControlsOverlay.visible is false
|
||||
PASS window.cached_navigator_xr.ondevicechange is null
|
||||
PASS window.cached_performance.onresourcetimingbufferfull is null
|
||||
PASS window.cached_performance_navigation.redirectCount is 0
|
||||
diff --git a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
|
||||
index 6f480ccfc7031fbdab98b50511a667aed5840af1..37bba469a00c719128762f861313e383d1ad4b86 100644
|
||||
--- a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
|
||||
+++ b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
|
||||
@@ -77,6 +77,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.x is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null
|
||||
PASS window.cached_navigator_virtualKeyboard.overlaysContent is false
|
||||
+PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null
|
||||
+PASS window.cached_navigator_windowControlsOverlay.visible is false
|
||||
PASS window.cached_navigator_xr.ondevicechange is null
|
||||
PASS window.cached_performance.onresourcetimingbufferfull is null
|
||||
PASS window.cached_performance_navigation.redirectCount is 0
|
||||
diff --git a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
|
||||
index ef72385e2cc50ae9519f2d0cf496e8cc771cf5aa..36efa30d35e4b8e5e7752bfde58f50cdef865e89 100644
|
||||
--- a/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
|
||||
+++ b/third_party/blink/web_tests/platform/generic/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
|
||||
@@ -87,6 +87,8 @@ PASS oldChildWindow.navigator.virtualKeyboard.boundingRect.y is newChildWindow.n
|
||||
PASS oldChildWindow.navigator.virtualKeyboard.ongeometrychange is newChildWindow.navigator.virtualKeyboard.ongeometrychange
|
||||
PASS oldChildWindow.navigator.virtualKeyboard.overlaysContent is newChildWindow.navigator.virtualKeyboard.overlaysContent
|
||||
PASS oldChildWindow.navigator.webdriver is newChildWindow.navigator.webdriver
|
||||
+PASS oldChildWindow.navigator.windowControlsOverlay.ongeometrychange is newChildWindow.navigator.windowControlsOverlay.ongeometrychange
|
||||
+PASS oldChildWindow.navigator.windowControlsOverlay.visible is newChildWindow.navigator.windowControlsOverlay.visible
|
||||
PASS oldChildWindow.navigator.xr.ondevicechange is newChildWindow.navigator.xr.ondevicechange
|
||||
PASS oldChildWindow.onabort is newChildWindow.onabort
|
||||
PASS oldChildWindow.onafterprint is newChildWindow.onafterprint
|
||||
diff --git a/third_party/blink/web_tests/platform/generic/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/stable/webexposed/global-interface-listing-expected.txt
|
||||
index 8dd54bc97aaeb0d563d7d839ff945881a5c7a422..ec02c2f0024fb6479aa469b4aeb66521b4f741f7 100644
|
||||
--- a/third_party/blink/web_tests/platform/generic/virtual/stable/webexposed/global-interface-listing-expected.txt
|
||||
+++ b/third_party/blink/web_tests/platform/generic/virtual/stable/webexposed/global-interface-listing-expected.txt
|
||||
@@ -4976,6 +4976,7 @@ interface Navigator
|
||||
getter webdriver
|
||||
getter webkitPersistentStorage
|
||||
getter webkitTemporaryStorage
|
||||
+ getter windowControlsOverlay
|
||||
getter xr
|
||||
method clearAppBadge
|
||||
method constructor
|
||||
@@ -9676,6 +9677,18 @@ interface Window : EventTarget
|
||||
attribute PERSISTENT
|
||||
attribute TEMPORARY
|
||||
method constructor
|
||||
+interface WindowControlsOverlay : EventTarget
|
||||
+ attribute @@toStringTag
|
||||
+ getter ongeometrychange
|
||||
+ getter visible
|
||||
+ method constructor
|
||||
+ method getTitlebarAreaRect
|
||||
+ setter ongeometrychange
|
||||
+interface WindowControlsOverlayGeometryChangeEvent : Event
|
||||
+ attribute @@toStringTag
|
||||
+ getter titlebarAreaRect
|
||||
+ getter visible
|
||||
+ method constructor
|
||||
interface Worker : EventTarget
|
||||
attribute @@toStringTag
|
||||
getter onerror
|
||||
@@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyrylo Hrechykhin <khrechykhin@microsoft.com>
|
||||
Date: Thu, 6 Oct 2022 18:30:53 +0200
|
||||
Subject: fix: on-screen-keyboard hides on input blur in webview
|
||||
|
||||
Changes introduced by this patch fix issue where OSK does not hide on
|
||||
input rendered inside webview is blurred. This patch should be removed
|
||||
when proper fix in chromium repo is available.
|
||||
|
||||
Note: the issue still occurs if input rendered in webview blurred due
|
||||
to touch outside of webview. It is caused by webview implementation
|
||||
details. Specificaly due to webview has its own tree nodes and focused
|
||||
node does not change in this case.
|
||||
|
||||
chromium-bug: https://crbug.com/1369605
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
index c56d5c06ca3eb5e2c11bd1af00a8667bfa422dc9..bccc940958180481947a5a5ee82562bd99d28b78 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
@@ -985,6 +985,12 @@ RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
|
||||
return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
|
||||
}
|
||||
|
||||
+void RenderWidgetHostViewChildFrame::FocusedNodeChanged(
|
||||
+ bool is_editable_node,
|
||||
+ const gfx::Rect& node_bounds_in_screen) {
|
||||
+ NOTREACHED();
|
||||
+}
|
||||
+
|
||||
ui::TextInputType RenderWidgetHostViewChildFrame::GetTextInputType() const {
|
||||
if (!text_input_manager_)
|
||||
return ui::TEXT_INPUT_TYPE_NONE;
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
index 457dabe428e84230b2e831e9281feee06e7c8e76..9436d55b390ac6fa16398efebad0a87beef6e959 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
@@ -178,6 +178,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
|
||||
void DisableAutoResize(const gfx::Size& new_size) override;
|
||||
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) override;
|
||||
+ void FocusedNodeChanged(bool is_editable_node,
|
||||
+ const gfx::Rect& node_bounds_in_screen) override;
|
||||
|
||||
// RenderFrameMetadataProvider::Observer implementation.
|
||||
void OnRenderFrameMetadataChangedBeforeActivation(
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 8982a2a4d2be23e56472b17e9d59e289e8255336..92f73106ba8c9559281add6fe7a2f2a613ca3cdc 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -7891,7 +7891,7 @@ void WebContentsImpl::OnFocusedElementChangedInFrame(
|
||||
"WebContentsImpl::OnFocusedElementChangedInFrame",
|
||||
"render_frame_host", frame);
|
||||
RenderWidgetHostViewBase* root_view =
|
||||
- static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
|
||||
+ static_cast<RenderWidgetHostViewBase*>(GetTopLevelRenderWidgetHostView());
|
||||
if (!root_view || !frame->GetView())
|
||||
return;
|
||||
// Convert to screen coordinates from window coordinates by adding the
|
||||
@@ -45,3 +45,4 @@ json_parse_errors_made_user-friendly.patch
|
||||
build_ensure_v8_pointer_compression_sandbox_is_enabled_on_64bit.patch
|
||||
build_ensure_native_module_compilation_fails_if_not_using_a_new.patch
|
||||
buffer_fix_atob_input_validation.patch
|
||||
fix_expose_the_built-in_electron_module_via_the_esm_loader.patch
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: fix: crash caused by GetHostNameW on Windows 7
|
||||
Backported from https://github.com/libuv/libuv/pull/3285.
|
||||
|
||||
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
|
||||
index 33e874ac442f88b58d2b68c8ec9764f6f664552e..2d4cc0aaa02e61bf359e80eca27527efb49fd85e 100644
|
||||
index 33e874ac442f88b58d2b68c8ec9764f6f664552e..37ece5e2867ab836492a8b7faa0aa5e1b8e562f0 100644
|
||||
--- a/deps/uv/src/win/util.c
|
||||
+++ b/deps/uv/src/win/util.c
|
||||
@@ -37,6 +37,7 @@
|
||||
@@ -166,3 +166,17 @@ index 33e874ac442f88b58d2b68c8ec9764f6f664552e..2d4cc0aaa02e61bf359e80eca27527ef
|
||||
int uv_os_gethostname(char* buffer, size_t* size) {
|
||||
WCHAR buf[UV_MAXHOSTNAMESIZE];
|
||||
size_t len;
|
||||
@@ -1674,10 +1803,10 @@ int uv_os_gethostname(char* buffer, size_t* size) {
|
||||
|
||||
uv__once_init(); /* Initialize winsock */
|
||||
|
||||
- if (pGetHostNameW == NULL)
|
||||
- return UV_ENOSYS;
|
||||
+ uv_sGetHostNameW gethostnamew =
|
||||
+ pGetHostNameW == NULL ? uv__gethostnamew_nt60 : pGetHostNameW;
|
||||
|
||||
- if (pGetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
|
||||
+ if (gethostnamew(buf, UV_MAXHOSTNAMESIZE) != 0)
|
||||
return uv_translate_sys_error(WSAGetLastError());
|
||||
|
||||
convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str);
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@salesforce.com>
|
||||
Date: Thu, 6 Oct 2022 04:09:16 -0700
|
||||
Subject: fix: expose the built-in electron module via the ESM loader
|
||||
|
||||
This allows usage of `import { app } from 'electron'` and `import('electron')` natively in the browser + non-sandboxed renderer
|
||||
|
||||
diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js
|
||||
index 5ae0e17dcfb5e24a1a117c33c4d42891686e693f..619fe6cef3b02eb575410225f41d3e7d51f37b93 100644
|
||||
--- a/lib/internal/modules/esm/get_format.js
|
||||
+++ b/lib/internal/modules/esm/get_format.js
|
||||
@@ -31,6 +31,7 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), {
|
||||
'http:': getHttpProtocolModuleFormat,
|
||||
'https:': getHttpProtocolModuleFormat,
|
||||
'node:'() { return 'builtin'; },
|
||||
+ 'electron:'() { return 'commonjs'; },
|
||||
});
|
||||
|
||||
function getDataProtocolModuleFormat(parsed) {
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 3576f75f0a40a64dceb7e2649b344b83ebc04b39..314fbb78931eef154a1e47c655e2d4bafe11bac3 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -888,6 +888,8 @@ function parsePackageName(specifier, base) {
|
||||
return { packageName, packageSubpath, isScoped };
|
||||
}
|
||||
|
||||
+const electronSpecifiers = new SafeSet(['electron', 'electron/main', 'electron/common', 'electron/renderer']);
|
||||
+
|
||||
/**
|
||||
* @param {string} specifier
|
||||
* @param {string | URL | undefined} base
|
||||
@@ -898,6 +900,10 @@ function packageResolve(specifier, base, conditions) {
|
||||
if (NativeModule.canBeRequiredByUsers(specifier))
|
||||
return new URL('node:' + specifier);
|
||||
|
||||
+ if (electronSpecifiers.has(specifier)) {
|
||||
+ return new URL('electron:electron');
|
||||
+ }
|
||||
+
|
||||
const { packageName, packageSubpath, isScoped } =
|
||||
parsePackageName(specifier, base);
|
||||
|
||||
@@ -1099,7 +1105,7 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) {
|
||||
|
||||
function throwIfUnsupportedURLProtocol(url) {
|
||||
if (url.protocol !== 'file:' && url.protocol !== 'data:' &&
|
||||
- url.protocol !== 'node:') {
|
||||
+ url.protocol !== 'node:' && url.protocol !== 'electron:') {
|
||||
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(url);
|
||||
}
|
||||
}
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index d7f4c7edec63d3ce500955a37c6eac00e3e524fd..b97cac53365b121f8e232f0085ff166511c3dda3 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -155,7 +155,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
|
||||
if (!cjsParse) await initCJSParse();
|
||||
const { module, exportNames } = cjsPreparseModuleExports(filename);
|
||||
- const namesWithDefault = exportNames.has('default') ?
|
||||
+ const namesWithDefault = filename === 'electron' ? ['default', ...Object.keys(module.exports)] : exportNames.has('default') ?
|
||||
[...exportNames] : ['default', ...exportNames];
|
||||
|
||||
return new ModuleWrap(url, undefined, namesWithDefault, function() {
|
||||
@@ -174,7 +174,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
}
|
||||
}
|
||||
|
||||
- for (const exportName of exportNames) {
|
||||
+ for (const exportName of namesWithDefault) {
|
||||
if (!ObjectPrototypeHasOwnProperty(exports, exportName) ||
|
||||
exportName === 'default')
|
||||
continue;
|
||||
diff --git a/lib/internal/url.js b/lib/internal/url.js
|
||||
index 939374a495856cf2b9c573fa98dc1895eee5e143..c37258ac29e8b7558c1f9a2af7ba6bdd0eab1355 100644
|
||||
--- a/lib/internal/url.js
|
||||
+++ b/lib/internal/url.js
|
||||
@@ -1418,6 +1418,8 @@ function fileURLToPath(path) {
|
||||
path = new URL(path);
|
||||
else if (!isURLInstance(path))
|
||||
throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);
|
||||
+ if (path.protocol === 'electron:')
|
||||
+ return 'electron';
|
||||
if (path.protocol !== 'file:')
|
||||
throw new ERR_INVALID_URL_SCHEME('file');
|
||||
return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path);
|
||||
@@ -6,7 +6,7 @@ Subject: fix: suppress clang -Wdeprecated-declarations in libuv
|
||||
Should be upstreamed.
|
||||
|
||||
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
|
||||
index 2d4cc0aaa02e61bf359e80eca27527efb49fd85e..aaa16052e2a9c7d1dca82763c41c0890371f1471 100644
|
||||
index 37ece5e2867ab836492a8b7faa0aa5e1b8e562f0..d50296728f7e0810064647125a469f3ed714f8ea 100644
|
||||
--- a/deps/uv/src/win/util.c
|
||||
+++ b/deps/uv/src/win/util.c
|
||||
@@ -1950,10 +1950,17 @@ int uv_os_uname(uv_utsname_t* buffer) {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
utf-8_q_simplify_20the_20logic_20that_20converts_20the_20_1_20.patch
|
||||
utf-8_q_when_20applying_20the_20omit-order-by_20optimization.patch
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ayu Ishii <ayui@chromium.org>
|
||||
Date: Fri, 15 Jul 2022 13:20:47 +0000
|
||||
Subject: When applying the omit-ORDER-BY optimization, defer deleting the AST
|
||||
of the deleted ORDER BY clause until after code generation ends.
|
||||
|
||||
FossilOrigin-Name: b88d6c4b814ec4166ec50f32a2f10d7857df05414c0048c1234ab290a273e50c
|
||||
(cherry picked from commit 9dde91f61386e4fc53eb95b6cbd26bf30521225f)
|
||||
Bug: 1343348
|
||||
Change-Id: Id677f72166c00a05f95c25438230f4b1d40f4d4d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/deps/sqlite/+/3764026
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Ayu Ishii <ayui@chromium.org>
|
||||
Reviewed-by: Joshua Bell <jsbell@chromium.org>
|
||||
|
||||
diff --git a/amalgamation/sqlite3.c b/amalgamation/sqlite3.c
|
||||
index b903fd1c4440a9f83b2ec513c5f38ec21b9557ef..9b9c2d727e7b0c21a03353aba6b4725e7d7c1633 100644
|
||||
--- a/amalgamation/sqlite3.c
|
||||
+++ b/amalgamation/sqlite3.c
|
||||
@@ -140765,7 +140765,9 @@ SQLITE_PRIVATE int sqlite3Select(
|
||||
){
|
||||
SELECTTRACE(0x100,pParse,p,
|
||||
("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
|
||||
- sqlite3ExprListDelete(db, pSub->pOrderBy);
|
||||
+ sqlite3ParserAddCleanup(pParse,
|
||||
+ (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
|
||||
+ pSub->pOrderBy);
|
||||
pSub->pOrderBy = 0;
|
||||
}
|
||||
|
||||
diff --git a/amalgamation_dev/sqlite3.c b/amalgamation_dev/sqlite3.c
|
||||
index 88b0bcb38e8e2f45aa449b5895bfc29baa543fea..94222875ff2d1e47370e3fa766003cfb0f8dc015 100644
|
||||
--- a/amalgamation_dev/sqlite3.c
|
||||
+++ b/amalgamation_dev/sqlite3.c
|
||||
@@ -140778,7 +140778,9 @@ SQLITE_PRIVATE int sqlite3Select(
|
||||
){
|
||||
SELECTTRACE(0x100,pParse,p,
|
||||
("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
|
||||
- sqlite3ExprListDelete(db, pSub->pOrderBy);
|
||||
+ sqlite3ParserAddCleanup(pParse,
|
||||
+ (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
|
||||
+ pSub->pOrderBy);
|
||||
pSub->pOrderBy = 0;
|
||||
}
|
||||
|
||||
diff --git a/src/select.c b/src/select.c
|
||||
index d6d6097401a748bf1b8268deb8a66daf23f4ea7c..ad7635f76c29c7a7206920947f9ea21626faf0ab 100644
|
||||
--- a/src/select.c
|
||||
+++ b/src/select.c
|
||||
@@ -6518,7 +6518,9 @@ int sqlite3Select(
|
||||
){
|
||||
SELECTTRACE(0x100,pParse,p,
|
||||
("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
|
||||
- sqlite3ExprListDelete(db, pSub->pOrderBy);
|
||||
+ sqlite3ParserAddCleanup(pParse,
|
||||
+ (void(*)(sqlite3*,void*))sqlite3ExprListDelete,
|
||||
+ pSub->pOrderBy);
|
||||
pSub->pOrderBy = 0;
|
||||
}
|
||||
|
||||
@@ -11,3 +11,5 @@ revert_runtime_dhceck_terminating_exception_in_microtasks.patch
|
||||
allow_disabling_of_v8_sandboxed_pointers.patch
|
||||
chore_disable_is_execution_terminating_dcheck.patch
|
||||
ext-code-space_fix_coderange_allocation_logic.patch
|
||||
cherry-pick-8b040cb69e96.patch
|
||||
cherry-pick-2f6a2939514f.patch
|
||||
|
||||
33
patches/v8/cherry-pick-2f6a2939514f.patch
Normal file
33
patches/v8/cherry-pick-2f6a2939514f.patch
Normal file
@@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Thu, 1 Sep 2022 15:35:33 +0200
|
||||
Subject: Merged: [compiler] fix typing of [[DateValue]]
|
||||
|
||||
Bug: chromium:1356308
|
||||
(cherry picked from commit ae329407989f1e4689baba7a7827863057d688a9)
|
||||
|
||||
Change-Id: I1e132e96325296d180488774ef183daa36dc22c7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3915224
|
||||
Reviewed-by: Darius Mercadier <dmercadier@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#25}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/compiler/type-cache.h b/src/compiler/type-cache.h
|
||||
index 6442b6f6b0ee39bf1a820168e9dd924e81bc0cb3..a34d094edaa4cb7dd7ac692e4a11d7c890744d7c 100644
|
||||
--- a/src/compiler/type-cache.h
|
||||
+++ b/src/compiler/type-cache.h
|
||||
@@ -131,9 +131,10 @@ class V8_EXPORT_PRIVATE TypeCache final {
|
||||
Type const kStringLengthType = CreateRange(0.0, String::kMaxLength);
|
||||
|
||||
// A time value always contains a tagged number in the range
|
||||
- // [-kMaxTimeInMs, kMaxTimeInMs].
|
||||
- Type const kTimeValueType =
|
||||
- CreateRange(-DateCache::kMaxTimeInMs, DateCache::kMaxTimeInMs);
|
||||
+ // [-kMaxTimeInMs, kMaxTimeInMs] or -0.
|
||||
+ Type const kTimeValueType = Type::Union(
|
||||
+ CreateRange(-DateCache::kMaxTimeInMs, DateCache::kMaxTimeInMs),
|
||||
+ Type::MinusZero(), zone());
|
||||
|
||||
// The JSDate::day property always contains a tagged number in the range
|
||||
// [1, 31] or NaN.
|
||||
47
patches/v8/cherry-pick-8b040cb69e96.patch
Normal file
47
patches/v8/cherry-pick-8b040cb69e96.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Date: Fri, 23 Sep 2022 13:13:37 +0200
|
||||
Subject: Fix a register reuse corner case
|
||||
|
||||
Fixed: chromium:1366399
|
||||
(cherry picked from commit 6c214db445827707d65be08d177c9a4257a03a7b)
|
||||
|
||||
Change-Id: I72cf30cbd31a21acb44b524a194acfb89d8fecbc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3925795
|
||||
Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#29}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/wasm/baseline/liftoff-compiler.cc b/src/wasm/baseline/liftoff-compiler.cc
|
||||
index 2b269516dd302c06a3eebc1c9d70f4d36612b942..3f768f8f5adcc1bfd1d64e68c638a5bf2e737051 100644
|
||||
--- a/src/wasm/baseline/liftoff-compiler.cc
|
||||
+++ b/src/wasm/baseline/liftoff-compiler.cc
|
||||
@@ -1421,9 +1421,11 @@ class LiftoffCompiler {
|
||||
__ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ emit_jump(c->label.get());
|
||||
}
|
||||
- // Merge the else state into the end state.
|
||||
+ // Merge the else state into the end state. Set this state as the current
|
||||
+ // state first so helper functions know which registers are in use.
|
||||
__ bind(c->else_state->label.get());
|
||||
- __ MergeFullStackWith(c->label_state, c->else_state->state);
|
||||
+ __ cache_state()->Steal(c->else_state->state);
|
||||
+ __ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ cache_state()->Steal(c->label_state);
|
||||
} else if (c->reachable()) {
|
||||
// No merge yet at the end of the if, but we need to create a merge for
|
||||
@@ -1435,9 +1437,11 @@ class LiftoffCompiler {
|
||||
c->stack_depth + c->num_exceptions);
|
||||
__ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ emit_jump(c->label.get());
|
||||
- // Merge the else state into the end state.
|
||||
+ // Merge the else state into the end state. Set this state as the current
|
||||
+ // state first so helper functions know which registers are in use.
|
||||
__ bind(c->else_state->label.get());
|
||||
- __ MergeFullStackWith(c->label_state, c->else_state->state);
|
||||
+ __ cache_state()->Steal(c->else_state->state);
|
||||
+ __ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ cache_state()->Steal(c->label_state);
|
||||
} else {
|
||||
// No merge needed, just continue with the else state.
|
||||
@@ -2,13 +2,14 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const utils = require('./lib/utils');
|
||||
const branding = require('../shell/app/BRANDING.json');
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
console.log('Not checking symlinks on non-darwin platform');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const appPath = path.resolve(__dirname, '..', '..', 'out', utils.getOutDir(), 'Electron.app');
|
||||
const appPath = path.resolve(__dirname, '..', '..', 'out', utils.getOutDir(), `${branding.product_name}.app`);
|
||||
const visited = new Set();
|
||||
const traverse = (p) => {
|
||||
if (visited.has(p)) return;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "components/content_settings/core/common/content_settings_pattern.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/fuses.h"
|
||||
#include "extensions/common/constants.h"
|
||||
#include "ipc/ipc_buildflags.h"
|
||||
#include "sandbox/policy/switches.h"
|
||||
@@ -420,6 +421,20 @@ void ElectronMainDelegate::PreBrowserMain() {
|
||||
#endif
|
||||
}
|
||||
|
||||
base::StringPiece ElectronMainDelegate::GetBrowserV8SnapshotFilename() {
|
||||
const base::CommandLine* command_line =
|
||||
base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type =
|
||||
command_line->GetSwitchValueASCII(::switches::kProcessType);
|
||||
bool load_browser_process_specific_v8_snapshot =
|
||||
process_type.empty() &&
|
||||
electron::fuses::IsLoadBrowserProcessSpecificV8SnapshotEnabled();
|
||||
if (load_browser_process_specific_v8_snapshot) {
|
||||
return "browser_v8_context_snapshot.bin";
|
||||
}
|
||||
return ContentMainDelegate::GetBrowserV8SnapshotFilename();
|
||||
}
|
||||
|
||||
content::ContentBrowserClient*
|
||||
ElectronMainDelegate::CreateContentBrowserClient() {
|
||||
browser_client_ = std::make_unique<ElectronBrowserClient>();
|
||||
|
||||
@@ -30,6 +30,8 @@ class ElectronMainDelegate : public content::ContentMainDelegate {
|
||||
ElectronMainDelegate(const ElectronMainDelegate&) = delete;
|
||||
ElectronMainDelegate& operator=(const ElectronMainDelegate&) = delete;
|
||||
|
||||
base::StringPiece GetBrowserV8SnapshotFilename() override;
|
||||
|
||||
protected:
|
||||
// content::ContentMainDelegate:
|
||||
bool BasicStartupComplete(int* exit_code) override;
|
||||
|
||||
@@ -88,8 +88,11 @@ class DataPipeReader {
|
||||
if (result == MOJO_RESULT_OK) { // success
|
||||
remaining_size_ -= length;
|
||||
head_ += length;
|
||||
if (remaining_size_ == 0)
|
||||
if (remaining_size_ == 0) {
|
||||
OnSuccess();
|
||||
} else {
|
||||
handle_watcher_.ArmOrNotify();
|
||||
}
|
||||
} else if (result == MOJO_RESULT_SHOULD_WAIT) { // IO pending
|
||||
handle_watcher_.ArmOrNotify();
|
||||
} else { // error
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "shell/browser/api/electron_api_desktop_capturer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -24,12 +25,125 @@
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
|
||||
#if defined(USE_OZONE)
|
||||
#include "ui/ozone/buildflags.h"
|
||||
#if BUILDFLAG(OZONE_PLATFORM_X11)
|
||||
#define USE_OZONE_PLATFORM_X11
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
|
||||
#include "ui/display/win/display_info.h"
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
#if defined(USE_OZONE_PLATFORM_X11)
|
||||
#include "base/logging.h"
|
||||
#include "ui/base/x/x11_display_util.h"
|
||||
#include "ui/base/x/x11_util.h"
|
||||
#include "ui/display/util/edid_parser.h" // nogncheck
|
||||
#include "ui/gfx/x/randr.h"
|
||||
#include "ui/gfx/x/x11_atom_cache.h"
|
||||
#include "ui/gfx/x/xproto_util.h"
|
||||
#endif // defined(USE_OZONE_PLATFORM_X11)
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
// Private function in ui/base/x/x11_display_util.cc
|
||||
std::map<x11::RandR::Output, int> GetMonitors(int version,
|
||||
x11::RandR* randr,
|
||||
x11::Window window) {
|
||||
std::map<x11::RandR::Output, int> output_to_monitor;
|
||||
if (version >= 105) {
|
||||
if (auto reply = randr->GetMonitors({window}).Sync()) {
|
||||
for (size_t monitor = 0; monitor < reply->monitors.size(); monitor++) {
|
||||
for (x11::RandR::Output output : reply->monitors[monitor].outputs)
|
||||
output_to_monitor[output] = monitor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output_to_monitor;
|
||||
}
|
||||
// Get the EDID data from the |output| and stores to |edid|.
|
||||
// Private function in ui/base/x/x11_display_util.cc
|
||||
std::vector<uint8_t> GetEDIDProperty(x11::RandR* randr,
|
||||
x11::RandR::Output output) {
|
||||
constexpr const char kRandrEdidProperty[] = "EDID";
|
||||
auto future = randr->GetOutputProperty(x11::RandR::GetOutputPropertyRequest{
|
||||
.output = output,
|
||||
.property = x11::GetAtom(kRandrEdidProperty),
|
||||
.long_length = 128});
|
||||
auto response = future.Sync();
|
||||
std::vector<uint8_t> edid;
|
||||
if (response && response->format == 8 && response->type != x11::Atom::None)
|
||||
edid = std::move(response->data);
|
||||
return edid;
|
||||
}
|
||||
|
||||
// Find the mapping from monitor name atom to the display identifier
|
||||
// that the screen API uses. Based on the logic in BuildDisplaysFromXRandRInfo
|
||||
// in ui/base/x/x11_display_util.cc
|
||||
std::map<int32_t, uint32_t> MonitorAtomIdToDisplayId() {
|
||||
auto* connection = x11::Connection::Get();
|
||||
auto& randr = connection->randr();
|
||||
auto x_root_window = ui::GetX11RootWindow();
|
||||
int version = ui::GetXrandrVersion();
|
||||
|
||||
std::map<int32_t, uint32_t> monitor_atom_to_display;
|
||||
|
||||
auto resources = randr.GetScreenResourcesCurrent({x_root_window}).Sync();
|
||||
if (!resources) {
|
||||
LOG(ERROR) << "XRandR returned no displays; don't know how to map ids";
|
||||
return monitor_atom_to_display;
|
||||
}
|
||||
|
||||
std::map<x11::RandR::Output, int> output_to_monitor =
|
||||
GetMonitors(version, &randr, x_root_window);
|
||||
auto monitors_reply = randr.GetMonitors({x_root_window}).Sync();
|
||||
|
||||
for (size_t i = 0; i < resources->outputs.size(); i++) {
|
||||
x11::RandR::Output output_id = resources->outputs[i];
|
||||
auto output_info =
|
||||
randr.GetOutputInfo({output_id, resources->config_timestamp}).Sync();
|
||||
if (!output_info)
|
||||
continue;
|
||||
|
||||
if (output_info->connection != x11::RandR::RandRConnection::Connected)
|
||||
continue;
|
||||
|
||||
if (output_info->crtc == static_cast<x11::RandR::Crtc>(0))
|
||||
continue;
|
||||
|
||||
auto crtc =
|
||||
randr.GetCrtcInfo({output_info->crtc, resources->config_timestamp})
|
||||
.Sync();
|
||||
if (!crtc)
|
||||
continue;
|
||||
display::EdidParser edid_parser(
|
||||
GetEDIDProperty(&randr, static_cast<x11::RandR::Output>(output_id)));
|
||||
auto output_32 = static_cast<uint32_t>(output_id);
|
||||
int64_t display_id =
|
||||
output_32 > 0xff ? 0 : edid_parser.GetIndexBasedDisplayId(output_32);
|
||||
// It isn't ideal, but if we can't parse the EDID data, fall back on the
|
||||
// display number.
|
||||
if (!display_id)
|
||||
display_id = i;
|
||||
|
||||
// Find the mapping between output identifier and the monitor name atom
|
||||
// Note this isn't the atom string, but the numeric atom identifier,
|
||||
// since this is what the WebRTC system uses as the display identifier
|
||||
auto output_monitor_iter = output_to_monitor.find(output_id);
|
||||
if (output_monitor_iter != output_to_monitor.end()) {
|
||||
x11::Atom atom =
|
||||
monitors_reply->monitors[output_monitor_iter->second].name;
|
||||
monitor_atom_to_display[static_cast<int32_t>(atom)] = display_id;
|
||||
}
|
||||
}
|
||||
|
||||
return monitor_atom_to_display;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace gin {
|
||||
|
||||
template <>
|
||||
@@ -180,10 +294,22 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
|
||||
for (auto& source : screen_sources) {
|
||||
source.display_id = base::NumberToString(source.media_list_source.id.id);
|
||||
}
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
#if defined(USE_OZONE_PLATFORM_X11)
|
||||
// On Linux, with X11, the source id is the numeric value of the
|
||||
// display name atom and the display id is either the EDID or the
|
||||
// loop index when that display was found (see
|
||||
// BuildDisplaysFromXRandRInfo in ui/base/x/x11_display_util.cc)
|
||||
std::map<int32_t, uint32_t> monitor_atom_to_display_id =
|
||||
MonitorAtomIdToDisplayId();
|
||||
for (auto& source : screen_sources) {
|
||||
auto display_id_iter =
|
||||
monitor_atom_to_display_id.find(source.media_list_source.id.id);
|
||||
if (display_id_iter != monitor_atom_to_display_id.end())
|
||||
source.display_id = base::NumberToString(display_id_iter->second);
|
||||
}
|
||||
#endif // defined(USE_OZONE_PLATFORM_X11)
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome
|
||||
// only supports capturing the entire desktop on Linux. Revisit this if
|
||||
// individual screen support is added.
|
||||
std::move(screen_sources.begin(), screen_sources.end(),
|
||||
std::back_inserter(captured_sources_));
|
||||
}
|
||||
|
||||
@@ -143,6 +143,10 @@
|
||||
#include "shell/browser/osr/osr_web_contents_view.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#endif
|
||||
|
||||
#if !BUILDFLAG(IS_MAC)
|
||||
#include "ui/aura/window.h"
|
||||
#else
|
||||
@@ -173,9 +177,8 @@
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "printing/backend/win_helper.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif // BUILDFLAG(ENABLE_PRINTING)
|
||||
|
||||
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
|
||||
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
|
||||
@@ -1315,7 +1318,7 @@ void WebContents::EnterFullscreenModeForTab(
|
||||
auto callback =
|
||||
base::BindRepeating(&WebContents::OnEnterFullscreenModeForTab,
|
||||
base::Unretained(this), requesting_frame, options);
|
||||
permission_helper->RequestFullscreenPermission(callback);
|
||||
permission_helper->RequestFullscreenPermission(requesting_frame, callback);
|
||||
}
|
||||
|
||||
void WebContents::OnEnterFullscreenModeForTab(
|
||||
@@ -1384,11 +1387,6 @@ bool WebContents::HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebContents::OnGoToEntryOffset(int offset) {
|
||||
GoToOffset(offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebContents::FindReply(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
int number_of_matches,
|
||||
@@ -2412,14 +2410,6 @@ void WebContents::OpenDevTools(gin::Arguments* args) {
|
||||
!owner_window()) {
|
||||
state = "detach";
|
||||
}
|
||||
bool activate = true;
|
||||
if (args && args->Length() == 1) {
|
||||
gin_helper::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("mode", &state);
|
||||
options.Get("activate", &activate);
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
auto* win = static_cast<NativeWindowViews*>(owner_window());
|
||||
@@ -2429,6 +2419,15 @@ void WebContents::OpenDevTools(gin::Arguments* args) {
|
||||
state = "detach";
|
||||
#endif
|
||||
|
||||
bool activate = true;
|
||||
if (args && args->Length() == 1) {
|
||||
gin_helper::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("mode", &state);
|
||||
options.Get("activate", &activate);
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK(inspectable_web_contents_);
|
||||
inspectable_web_contents_->SetDockState(state);
|
||||
inspectable_web_contents_->ShowDevTools(activate);
|
||||
|
||||
@@ -532,7 +532,6 @@ class WebContents : public ExclusiveAccessContext,
|
||||
content::RenderWidgetHost* render_widget_host) override;
|
||||
bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
||||
const content::ContextMenuParams& params) override;
|
||||
bool OnGoToEntryOffset(int offset) override;
|
||||
void FindReply(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
int number_of_matches,
|
||||
|
||||
@@ -298,6 +298,12 @@ GURL WebFrameMain::URL() const {
|
||||
return render_frame_->GetLastCommittedURL();
|
||||
}
|
||||
|
||||
std::string WebFrameMain::Origin() const {
|
||||
if (!CheckRenderFrame())
|
||||
return std::string();
|
||||
return render_frame_->GetLastCommittedOrigin().Serialize();
|
||||
}
|
||||
|
||||
blink::mojom::PageVisibilityState WebFrameMain::VisibilityState() const {
|
||||
if (!CheckRenderFrame())
|
||||
return blink::mojom::PageVisibilityState::kHidden;
|
||||
@@ -387,6 +393,7 @@ v8::Local<v8::ObjectTemplate> WebFrameMain::FillObjectTemplate(
|
||||
.SetProperty("processId", &WebFrameMain::ProcessID)
|
||||
.SetProperty("routingId", &WebFrameMain::RoutingID)
|
||||
.SetProperty("url", &WebFrameMain::URL)
|
||||
.SetProperty("origin", &WebFrameMain::Origin)
|
||||
.SetProperty("visibilityState", &WebFrameMain::VisibilityState)
|
||||
.SetProperty("top", &WebFrameMain::Top)
|
||||
.SetProperty("parent", &WebFrameMain::Parent)
|
||||
|
||||
@@ -108,6 +108,7 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
|
||||
int ProcessID() const;
|
||||
int RoutingID() const;
|
||||
GURL URL() const;
|
||||
std::string Origin() const;
|
||||
blink::mojom::PageVisibilityState VisibilityState() const;
|
||||
|
||||
content::RenderFrameHost* Top() const;
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "content/public/browser/tts_controller.h"
|
||||
#include "content/public/browser/tts_platform.h"
|
||||
#include "content/public/browser/url_loader_request_interceptor.h"
|
||||
#include "content/public/browser/weak_document_ptr.h"
|
||||
#include "content/public/common/content_descriptors.h"
|
||||
#include "content/public/common/content_paths.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
@@ -987,7 +988,7 @@ void ElectronBrowserClient::WebNotificationAllowed(
|
||||
return;
|
||||
}
|
||||
permission_helper->RequestWebNotificationPermission(
|
||||
base::BindOnce(std::move(callback), web_contents->IsAudioMuted()));
|
||||
rfh, base::BindOnce(std::move(callback), web_contents->IsAudioMuted()));
|
||||
}
|
||||
|
||||
void ElectronBrowserClient::RenderProcessHostDestroyed(
|
||||
@@ -1022,6 +1023,7 @@ void OnOpenExternal(const GURL& escaped_url, bool allowed) {
|
||||
|
||||
void HandleExternalProtocolInUI(
|
||||
const GURL& url,
|
||||
content::WeakDocumentPtr document_ptr,
|
||||
content::WebContents::OnceGetter web_contents_getter,
|
||||
bool has_user_gesture) {
|
||||
content::WebContents* web_contents = std::move(web_contents_getter).Run();
|
||||
@@ -1033,9 +1035,18 @@ void HandleExternalProtocolInUI(
|
||||
if (!permission_helper)
|
||||
return;
|
||||
|
||||
content::RenderFrameHost* rfh = document_ptr.AsRenderFrameHostIfValid();
|
||||
if (!rfh) {
|
||||
// If the render frame host is not valid it means it was a top level
|
||||
// navigation and the frame has already been disposed of. In this case we
|
||||
// take the current main frame and declare it responsible for the
|
||||
// transition.
|
||||
rfh = web_contents->GetPrimaryMainFrame();
|
||||
}
|
||||
|
||||
GURL escaped_url(base::EscapeExternalHandlerValue(url.spec()));
|
||||
auto callback = base::BindOnce(&OnOpenExternal, escaped_url);
|
||||
permission_helper->RequestOpenExternalPermission(std::move(callback),
|
||||
permission_helper->RequestOpenExternalPermission(rfh, std::move(callback),
|
||||
has_user_gesture, url);
|
||||
}
|
||||
|
||||
@@ -1055,6 +1066,9 @@ bool ElectronBrowserClient::HandleExternalProtocol(
|
||||
content::GetUIThreadTaskRunner({})->PostTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&HandleExternalProtocolInUI, url,
|
||||
initiator_document
|
||||
? initiator_document->GetWeakDocumentPtr()
|
||||
: content::WeakDocumentPtr(),
|
||||
std::move(web_contents_getter), has_user_gesture));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
#include "components/os_crypt/keychain_password_mac.h"
|
||||
#include "services/device/public/cpp/geolocation/geolocation_manager.h"
|
||||
#include "shell/browser/ui/cocoa/views_delegate_mac.h"
|
||||
#else
|
||||
@@ -482,6 +483,9 @@ void ElectronBrowserMainParts::WillRunMainMessageLoop(
|
||||
}
|
||||
|
||||
void ElectronBrowserMainParts::PostCreateMainMessageLoop() {
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
|
||||
std::string app_name = electron::Browser::Get()->GetName();
|
||||
#endif
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
auto shutdown_cb =
|
||||
base::BindOnce(base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
|
||||
@@ -492,7 +496,6 @@ void ElectronBrowserMainParts::PostCreateMainMessageLoop() {
|
||||
// Set up crypt config. This needs to be done before anything starts the
|
||||
// network service, as the raw encryption key needs to be shared with the
|
||||
// network service for encrypted cookie storage.
|
||||
std::string app_name = electron::Browser::Get()->GetName();
|
||||
const base::CommandLine& command_line =
|
||||
*base::CommandLine::ForCurrentProcess();
|
||||
std::unique_ptr<os_crypt::Config> config =
|
||||
@@ -509,6 +512,10 @@ void ElectronBrowserMainParts::PostCreateMainMessageLoop() {
|
||||
base::PathService::Get(DIR_SESSION_DATA, &config->user_data_path);
|
||||
OSCrypt::SetConfig(std::move(config));
|
||||
#endif
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
KeychainPassword::GetServiceName() = app_name + " Safe Storage";
|
||||
KeychainPassword::GetAccountName() = app_name;
|
||||
#endif
|
||||
#if BUILDFLAG(IS_POSIX)
|
||||
// Exit in response to SIGINT, SIGTERM, etc.
|
||||
InstallShutdownSignalHandlers(
|
||||
|
||||
@@ -99,14 +99,14 @@ bool GetRegistryDescriptionFromExtension(const std::string& file_ext,
|
||||
// Set up a filter for a Save/Open dialog, |ext_desc| as the text descriptions
|
||||
// of the |file_ext| types (optional), and (optionally) the default 'All Files'
|
||||
// view. The purpose of the filter is to show only files of a particular type in
|
||||
// a Windows Save/Open dialog box. The resulting filter is returned. The filter
|
||||
// a Windows Save/Open dialog box. The resulting filter is returned. The filters
|
||||
// created here are:
|
||||
// 1. only files that have 'file_ext' as their extension
|
||||
// 2. all files (only added if 'include_all_files' is true)
|
||||
// If a description is not provided for a file extension, it will be retrieved
|
||||
// from the registry. If the file extension does not exist in the registry, a
|
||||
// default description will be created (e.g. "qqq" yields "QQQ File").
|
||||
// Copied from ui/shell_dialogs/select_file_dialog_win.cc
|
||||
// Modified from ui/shell_dialogs/select_file_dialog_win.cc
|
||||
file_dialog::Filters FormatFilterForExtensions(
|
||||
const std::vector<std::string>& file_ext,
|
||||
const std::vector<std::string>& ext_desc,
|
||||
@@ -168,6 +168,10 @@ file_dialog::Filters FormatFilterForExtensions(
|
||||
base::ReplaceChars(desc, "*", base::StringPiece(), &desc);
|
||||
}
|
||||
|
||||
// Remove the preceeding '.' character from the extension.
|
||||
size_t ext_index = ext.find_first_not_of('.');
|
||||
if (ext_index != std::string::npos)
|
||||
ext = ext.substr(ext_index);
|
||||
result.push_back({desc, {ext}});
|
||||
}
|
||||
|
||||
|
||||
@@ -42,10 +42,6 @@
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
#include "components/os_crypt/keychain_password_mac.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
#include "components/os_crypt/key_storage_config_linux.h"
|
||||
#endif
|
||||
@@ -288,12 +284,6 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(
|
||||
base::FeatureList::IsEnabled(features::kAsyncDns),
|
||||
default_secure_dns_mode, doh_config, additional_dns_query_types_enabled);
|
||||
|
||||
std::string app_name = electron::Browser::Get()->GetName();
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
KeychainPassword::GetServiceName() = app_name + " Safe Storage";
|
||||
KeychainPassword::GetAccountName() = app_name;
|
||||
#endif
|
||||
|
||||
// The OSCrypt keys are process bound, so if network service is out of
|
||||
// process, send it the required key.
|
||||
if (content::IsOutOfProcessNetworkService() &&
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 20,1,2,0
|
||||
PRODUCTVERSION 20,1,2,0
|
||||
FILEVERSION 20,3,3,0
|
||||
PRODUCTVERSION 20,3,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "20.1.2"
|
||||
VALUE "FileVersion", "20.3.3"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "20.1.2"
|
||||
VALUE "ProductVersion", "20.3.3"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -68,16 +68,18 @@ device::mojom::SerialPortManager* ElectronSerialDelegate::GetPortManager(
|
||||
return GetChooserContext(frame)->GetPortManager();
|
||||
}
|
||||
|
||||
void ElectronSerialDelegate::AddObserver(content::RenderFrameHost* frame,
|
||||
Observer* observer) {
|
||||
void ElectronSerialDelegate::AddObserver(
|
||||
content::RenderFrameHost* frame,
|
||||
content::SerialDelegate::Observer* observer) {
|
||||
observer_list_.AddObserver(observer);
|
||||
auto* chooser_context = GetChooserContext(frame);
|
||||
if (!port_observation_.IsObserving())
|
||||
port_observation_.Observe(chooser_context);
|
||||
}
|
||||
|
||||
void ElectronSerialDelegate::RemoveObserver(content::RenderFrameHost* frame,
|
||||
Observer* observer) {
|
||||
void ElectronSerialDelegate::RemoveObserver(
|
||||
content::RenderFrameHost* frame,
|
||||
content::SerialDelegate::Observer* observer) {
|
||||
observer_list_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@ class ElectronSerialDelegate : public content::SerialDelegate,
|
||||
device::mojom::SerialPortManager* GetPortManager(
|
||||
content::RenderFrameHost* frame) override;
|
||||
void AddObserver(content::RenderFrameHost* frame,
|
||||
Observer* observer) override;
|
||||
content::SerialDelegate::Observer* observer) override;
|
||||
void RemoveObserver(content::RenderFrameHost* frame,
|
||||
Observer* observer) override;
|
||||
content::SerialDelegate::Observer* observer) override;
|
||||
void RevokePortPermissionWebInitiated(
|
||||
content::RenderFrameHost* frame,
|
||||
const base::UnguessableToken& token) override;
|
||||
|
||||
@@ -182,18 +182,27 @@ bool ElectronBundleMover::IsCurrentAppInApplicationsFolder() {
|
||||
return IsInApplicationsFolder([[NSBundle mainBundle] bundlePath]);
|
||||
}
|
||||
|
||||
NSString* resolvePath(NSString* path) {
|
||||
NSString* standardizedPath = [path stringByStandardizingPath];
|
||||
char resolved[PATH_MAX];
|
||||
if (realpath([standardizedPath UTF8String], resolved) == NULL)
|
||||
return path;
|
||||
return @(resolved);
|
||||
}
|
||||
|
||||
bool ElectronBundleMover::IsInApplicationsFolder(NSString* bundlePath) {
|
||||
// Check all the normal Application directories
|
||||
NSArray* applicationDirs = NSSearchPathForDirectoriesInDomains(
|
||||
NSApplicationDirectory, NSAllDomainsMask, true);
|
||||
NSString* resolvedBundlePath = resolvePath(bundlePath);
|
||||
for (NSString* appDir in applicationDirs) {
|
||||
if ([bundlePath hasPrefix:appDir])
|
||||
if ([resolvedBundlePath hasPrefix:appDir])
|
||||
return true;
|
||||
}
|
||||
|
||||
// Also, handle the case that the user has some other Application directory
|
||||
// (perhaps on a separate data partition).
|
||||
if ([[bundlePath pathComponents] containsObject:@"Applications"])
|
||||
if ([[resolvedBundlePath pathComponents] containsObject:@"Applications"])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
- (NSDragOperation)draggingSession:(NSDraggingSession*)session
|
||||
sourceOperationMaskForDraggingContext:(NSDraggingContext)context {
|
||||
return NSDragOperationEvery;
|
||||
return context == NSDraggingContextOutsideApplication ? NSDragOperationCopy
|
||||
: NSDragOperationEvery;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -70,7 +71,7 @@ void DragFileItems(const std::vector<base::FilePath>& files,
|
||||
NSEvent* dragEvent =
|
||||
[NSEvent mouseEventWithType:NSEventTypeLeftMouseDragged
|
||||
location:position
|
||||
modifierFlags:NSEventMaskLeftMouseDragged
|
||||
modifierFlags:0
|
||||
timestamp:eventTime
|
||||
windowNumber:[[native_view window] windowNumber]
|
||||
context:nil
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Modified from chrome/browser/ui/views/frame/windows_10_caption_button.cc
|
||||
// Modified from chrome/browser/ui/views/frame/windows_caption_button.cc
|
||||
|
||||
#include "shell/browser/ui/views/win_caption_button.h"
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "shell/browser/ui/views/win_frame_view.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/strings/grit/ui_strings.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/layout/flex_layout.h"
|
||||
#include "ui/views/view_class_properties.h"
|
||||
|
||||
@@ -128,6 +129,8 @@ void WinCaptionButtonContainer::AddedToWidget() {
|
||||
UpdateButtons();
|
||||
|
||||
if (frame_view_->window()->IsWindowControlsOverlayEnabled()) {
|
||||
SetBackground(views::CreateSolidBackground(
|
||||
frame_view_->window()->overlay_button_color()));
|
||||
SetPaintToLayer();
|
||||
}
|
||||
}
|
||||
@@ -156,10 +159,11 @@ void WinCaptionButtonContainer::UpdateButtons() {
|
||||
const bool is_touch = ui::TouchUiController::Get()->touch_ui();
|
||||
restore_button_->SetEnabled(!is_touch);
|
||||
|
||||
// The maximize button should only be enabled if the window is
|
||||
// maximizable *and* touch mode is disabled.
|
||||
// In touch mode, windows cannot be taken out of fullscreen or tiled mode, so
|
||||
// the maximize/restore button should be disabled, unless the window is not
|
||||
// maximized.
|
||||
const bool maximizable = frame_view_->window()->IsMaximizable();
|
||||
maximize_button_->SetEnabled(!is_touch && maximizable);
|
||||
maximize_button_->SetEnabled(!(is_touch && is_maximized) && maximizable);
|
||||
|
||||
const bool closable = frame_view_->window()->IsClosable();
|
||||
close_button_->SetEnabled(closable);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ui/display/win/dpi.h"
|
||||
#include "ui/display/win/screen_win.h"
|
||||
#include "ui/gfx/geometry/dip_util.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
#include "ui/views/win/hwnd_util.h"
|
||||
|
||||
@@ -58,6 +59,8 @@ void WinFrameView::InvalidateCaptionButtons() {
|
||||
if (!caption_button_container_)
|
||||
return;
|
||||
|
||||
caption_button_container_->SetBackground(
|
||||
views::CreateSolidBackground(window()->overlay_button_color()));
|
||||
caption_button_container_->InvalidateLayout();
|
||||
caption_button_container_->SchedulePaint();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ void DrawRect(gfx::Canvas* canvas,
|
||||
|
||||
void DrawRoundRect(gfx::Canvas* canvas,
|
||||
const gfx::Rect& rect,
|
||||
int radius,
|
||||
float radius,
|
||||
const cc::PaintFlags& flags) {
|
||||
gfx::RectF rect_f(rect);
|
||||
float stroke_half_width = flags.getStrokeWidth() / 2;
|
||||
@@ -74,7 +74,7 @@ void WinIconPainter::PaintMaximizeIcon(gfx::Canvas* canvas,
|
||||
void WinIconPainter::PaintRestoreIcon(gfx::Canvas* canvas,
|
||||
const gfx::Rect& symbol_rect,
|
||||
const cc::PaintFlags& flags) {
|
||||
const int separation = std::floor(2 * canvas->image_scale());
|
||||
const int separation = base::ClampFloor(2 * canvas->image_scale());
|
||||
gfx::Rect icon_rect = symbol_rect;
|
||||
icon_rect.Inset(gfx::Insets::TLBR(separation, 0, 0, separation));
|
||||
|
||||
@@ -113,14 +113,14 @@ void Win11IconPainter::PaintMaximizeIcon(gfx::Canvas* canvas,
|
||||
cc::PaintFlags paint_flags = flags;
|
||||
paint_flags.setAntiAlias(true);
|
||||
|
||||
const float corner_radius = 2 * canvas->image_scale();
|
||||
const float corner_radius = canvas->image_scale();
|
||||
DrawRoundRect(canvas, symbol_rect, corner_radius, flags);
|
||||
}
|
||||
|
||||
void Win11IconPainter::PaintRestoreIcon(gfx::Canvas* canvas,
|
||||
const gfx::Rect& symbol_rect,
|
||||
const cc::PaintFlags& flags) {
|
||||
const int separation = std::floor(2 * canvas->image_scale());
|
||||
const int separation = base::ClampFloor(2 * canvas->image_scale());
|
||||
gfx::Rect icon_rect = symbol_rect;
|
||||
icon_rect.Inset(gfx::Insets::TLBR(separation, 0, 0, separation));
|
||||
|
||||
@@ -128,14 +128,11 @@ void Win11IconPainter::PaintRestoreIcon(gfx::Canvas* canvas,
|
||||
paint_flags.setAntiAlias(true);
|
||||
|
||||
// Bottom left ("in front") rounded square.
|
||||
const float bottom_rect_radius = 1 * canvas->image_scale();
|
||||
const float bottom_rect_radius = canvas->image_scale();
|
||||
DrawRoundRect(canvas, icon_rect, bottom_rect_radius, flags);
|
||||
|
||||
// Top right ("behind") top+right edges of rounded square (2.5x).
|
||||
icon_rect.Offset(separation, -separation);
|
||||
// Apply inset to left+bottom edges since we don't draw arcs for those edges
|
||||
constexpr int top_rect_inset = 1;
|
||||
icon_rect.Inset(gfx::Insets::TLBR(0, top_rect_inset, top_rect_inset, 0));
|
||||
|
||||
const float top_rect_radius = 2.5f * canvas->image_scale();
|
||||
DrawRoundRectEdges(canvas, icon_rect, top_rect_radius, flags);
|
||||
|
||||
@@ -61,16 +61,16 @@ WebContentsPermissionHelper::WebContentsPermissionHelper(
|
||||
WebContentsPermissionHelper::~WebContentsPermissionHelper() = default;
|
||||
|
||||
void WebContentsPermissionHelper::RequestPermission(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
blink::PermissionType permission,
|
||||
base::OnceCallback<void(bool)> callback,
|
||||
bool user_gesture,
|
||||
const base::DictionaryValue* details) {
|
||||
auto* rfh = web_contents_->GetMainFrame();
|
||||
auto* permission_manager = static_cast<ElectronPermissionManager*>(
|
||||
web_contents_->GetBrowserContext()->GetPermissionControllerDelegate());
|
||||
auto origin = web_contents_->GetLastCommittedURL();
|
||||
permission_manager->RequestPermissionWithDetails(
|
||||
permission, rfh, origin, false, details,
|
||||
permission, requesting_frame, origin, false, details,
|
||||
base::BindOnce(&OnPermissionResponse, std::move(callback)));
|
||||
}
|
||||
|
||||
@@ -86,8 +86,10 @@ bool WebContentsPermissionHelper::CheckPermission(
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestFullscreenPermission(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
base::OnceCallback<void(bool)> callback) {
|
||||
RequestPermission(
|
||||
requesting_frame,
|
||||
static_cast<blink::PermissionType>(PermissionType::FULLSCREEN),
|
||||
std::move(callback));
|
||||
}
|
||||
@@ -113,13 +115,17 @@ void WebContentsPermissionHelper::RequestMediaAccessPermission(
|
||||
|
||||
// The permission type doesn't matter here, AUDIO_CAPTURE/VIDEO_CAPTURE
|
||||
// are presented as same type in content_converter.h.
|
||||
RequestPermission(blink::PermissionType::AUDIO_CAPTURE, std::move(callback),
|
||||
RequestPermission(content::RenderFrameHost::FromID(request.render_process_id,
|
||||
request.render_frame_id),
|
||||
blink::PermissionType::AUDIO_CAPTURE, std::move(callback),
|
||||
false, &details);
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestWebNotificationPermission(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
base::OnceCallback<void(bool)> callback) {
|
||||
RequestPermission(blink::PermissionType::NOTIFICATIONS, std::move(callback));
|
||||
RequestPermission(requesting_frame, blink::PermissionType::NOTIFICATIONS,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestPointerLockPermission(
|
||||
@@ -128,6 +134,7 @@ void WebContentsPermissionHelper::RequestPointerLockPermission(
|
||||
base::OnceCallback<void(content::WebContents*, bool, bool, bool)>
|
||||
callback) {
|
||||
RequestPermission(
|
||||
web_contents_->GetPrimaryMainFrame(),
|
||||
static_cast<blink::PermissionType>(PermissionType::POINTER_LOCK),
|
||||
base::BindOnce(std::move(callback), web_contents_, user_gesture,
|
||||
last_unlocked_by_target),
|
||||
@@ -135,12 +142,14 @@ void WebContentsPermissionHelper::RequestPointerLockPermission(
|
||||
}
|
||||
|
||||
void WebContentsPermissionHelper::RequestOpenExternalPermission(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
base::OnceCallback<void(bool)> callback,
|
||||
bool user_gesture,
|
||||
const GURL& url) {
|
||||
base::DictionaryValue details;
|
||||
details.SetString("externalURL", url.spec());
|
||||
RequestPermission(
|
||||
requesting_frame,
|
||||
static_cast<blink::PermissionType>(PermissionType::OPEN_EXTERNAL),
|
||||
std::move(callback), user_gesture, &details);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ class WebContentsPermissionHelper
|
||||
};
|
||||
|
||||
// Asynchronous Requests
|
||||
void RequestFullscreenPermission(base::OnceCallback<void(bool)> callback);
|
||||
void RequestFullscreenPermission(content::RenderFrameHost* requesting_frame,
|
||||
base::OnceCallback<void(bool)> callback);
|
||||
void RequestMediaAccessPermission(const content::MediaStreamRequest& request,
|
||||
content::MediaResponseCallback callback);
|
||||
void RequestPointerLockPermission(
|
||||
@@ -42,8 +43,10 @@ class WebContentsPermissionHelper
|
||||
base::OnceCallback<void(content::WebContents*, bool, bool, bool)>
|
||||
callback);
|
||||
void RequestWebNotificationPermission(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
base::OnceCallback<void(bool)> callback);
|
||||
void RequestOpenExternalPermission(base::OnceCallback<void(bool)> callback,
|
||||
void RequestOpenExternalPermission(content::RenderFrameHost* requesting_frame,
|
||||
base::OnceCallback<void(bool)> callback,
|
||||
bool user_gesture,
|
||||
const GURL& url);
|
||||
|
||||
@@ -56,7 +59,8 @@ class WebContentsPermissionHelper
|
||||
explicit WebContentsPermissionHelper(content::WebContents* web_contents);
|
||||
friend class content::WebContentsUserData<WebContentsPermissionHelper>;
|
||||
|
||||
void RequestPermission(blink::PermissionType permission,
|
||||
void RequestPermission(content::RenderFrameHost* requesting_frame,
|
||||
blink::PermissionType permission,
|
||||
base::OnceCallback<void(bool)> callback,
|
||||
bool user_gesture = false,
|
||||
const base::DictionaryValue* details = nullptr);
|
||||
|
||||
@@ -491,19 +491,22 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||
flags |= node::EnvironmentFlags::kNoStartDebugSignalHandler;
|
||||
}
|
||||
|
||||
v8::TryCatch try_catch(isolate);
|
||||
env = node::CreateEnvironment(
|
||||
isolate_data_, context, args, exec_args,
|
||||
static_cast<node::EnvironmentFlags::Flags>(flags));
|
||||
{
|
||||
v8::TryCatch try_catch(isolate);
|
||||
env = node::CreateEnvironment(
|
||||
isolate_data_, context, args, exec_args,
|
||||
static_cast<node::EnvironmentFlags::Flags>(flags));
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
std::string err_msg =
|
||||
"Failed to initialize node environment in process: " + process_type;
|
||||
v8::Local<v8::Message> message = try_catch.Message();
|
||||
std::string msg;
|
||||
if (!message.IsEmpty() && gin::ConvertFromV8(isolate, message->Get(), &msg))
|
||||
err_msg += " , with error: " + msg;
|
||||
LOG(ERROR) << err_msg;
|
||||
if (try_catch.HasCaught()) {
|
||||
std::string err_msg =
|
||||
"Failed to initialize node environment in process: " + process_type;
|
||||
v8::Local<v8::Message> message = try_catch.Message();
|
||||
std::string msg;
|
||||
if (!message.IsEmpty() &&
|
||||
gin::ConvertFromV8(isolate, message->Get(), &msg))
|
||||
err_msg += " , with error: " + msg;
|
||||
LOG(ERROR) << err_msg;
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK(env);
|
||||
|
||||
@@ -14,8 +14,7 @@ import { promisify } from 'util';
|
||||
describe('powerMonitor', () => {
|
||||
let logindMock: any, dbusMockPowerMonitor: any, getCalls: any, emitSignal: any, reset: any;
|
||||
|
||||
// TODO(deepak1556): Enable on arm64 after upgrade, it crashes at the moment.
|
||||
ifdescribe(process.platform === 'linux' && process.arch !== 'arm64' && process.env.DBUS_SYSTEM_BUS_ADDRESS != null)('when powerMonitor module is loaded with dbus mock', () => {
|
||||
ifdescribe(process.platform === 'linux' && process.env.DBUS_SYSTEM_BUS_ADDRESS != null)('when powerMonitor module is loaded with dbus mock', () => {
|
||||
before(async () => {
|
||||
const systemBus = dbus.systemBus();
|
||||
const loginService = systemBus.getService('org.freedesktop.login1');
|
||||
|
||||
@@ -4,7 +4,7 @@ import { safeStorage } from 'electron/main';
|
||||
import { expect } from 'chai';
|
||||
import { emittedOnce } from './events-helpers';
|
||||
import { ifdescribe } from './spec-helpers';
|
||||
import * as fs from 'fs';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
/* isEncryptionAvailable returns false in Linux when running CI due to a mocked dbus. This stops
|
||||
* Chrome from reaching the system's keyring or libsecret. When running the tests with config.store
|
||||
@@ -36,8 +36,8 @@ describe('safeStorage module', () => {
|
||||
ifdescribe(process.platform !== 'linux')('safeStorage module', () => {
|
||||
after(async () => {
|
||||
const pathToEncryptedString = path.resolve(__dirname, 'fixtures', 'api', 'safe-storage', 'encrypted.txt');
|
||||
if (fs.existsSync(pathToEncryptedString)) {
|
||||
await fs.unlinkSync(pathToEncryptedString);
|
||||
if (await fs.pathExists(pathToEncryptedString)) {
|
||||
await fs.remove(pathToEncryptedString);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -529,6 +529,50 @@ describe('session module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ses.getBlobData2()', () => {
|
||||
const scheme = 'cors-blob';
|
||||
const protocol = session.defaultSession.protocol;
|
||||
const url = `${scheme}://host`;
|
||||
after(async () => {
|
||||
await protocol.unregisterProtocol(scheme);
|
||||
});
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
it('returns blob data for uuid', (done) => {
|
||||
const content = `<html>
|
||||
<script>
|
||||
let fd = new FormData();
|
||||
fd.append("data", new Blob(new Array(65_537).fill('a')));
|
||||
fetch('${url}', {method:'POST', body: fd });
|
||||
</script>
|
||||
</html>`;
|
||||
|
||||
protocol.registerStringProtocol(scheme, (request, callback) => {
|
||||
try {
|
||||
if (request.method === 'GET') {
|
||||
callback({ data: content, mimeType: 'text/html' });
|
||||
} else if (request.method === 'POST') {
|
||||
const uuid = request.uploadData![1].blobUUID;
|
||||
expect(uuid).to.be.a('string');
|
||||
session.defaultSession.getBlobData(uuid!).then(result => {
|
||||
try {
|
||||
const data = new Array(65_537).fill('a');
|
||||
expect(result.toString()).to.equal(data.join(''));
|
||||
done();
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
const w = new BrowserWindow({ show: false });
|
||||
w.loadURL(url);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ses.setCertificateVerifyProc(callback)', () => {
|
||||
let server: http.Server;
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ import { expect } from 'chai';
|
||||
import * as http from 'http';
|
||||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
import { BrowserWindow, WebFrameMain, webFrameMain, ipcMain } from 'electron/main';
|
||||
import { BrowserWindow, WebFrameMain, webFrameMain, ipcMain, app, WebContents } from 'electron/main';
|
||||
import { closeAllWindows } from './window-helpers';
|
||||
import { emittedOnce, emittedNTimes } from './events-helpers';
|
||||
import { AddressInfo } from 'net';
|
||||
import { ifit, waitUntil } from './spec-helpers';
|
||||
import { defer, ifit, waitUntil } from './spec-helpers';
|
||||
|
||||
describe('webFrameMain module', () => {
|
||||
const fixtures = path.resolve(__dirname, '..', 'spec-main', 'fixtures');
|
||||
@@ -39,7 +39,7 @@ describe('webFrameMain module', () => {
|
||||
let webFrame: WebFrameMain;
|
||||
|
||||
beforeEach(async () => {
|
||||
w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
|
||||
webFrame = w.webContents.mainFrame;
|
||||
});
|
||||
@@ -88,8 +88,8 @@ describe('webFrameMain module', () => {
|
||||
});
|
||||
|
||||
describe('cross-origin', () => {
|
||||
let serverA = null as unknown as Server;
|
||||
let serverB = null as unknown as Server;
|
||||
let serverA: Server;
|
||||
let serverB: Server;
|
||||
|
||||
before(async () => {
|
||||
serverA = await createServer();
|
||||
@@ -112,7 +112,7 @@ describe('webFrameMain module', () => {
|
||||
|
||||
describe('WebFrame.url', () => {
|
||||
it('should report correct address for each subframe', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
|
||||
const webFrame = w.webContents.mainFrame;
|
||||
|
||||
@@ -122,9 +122,59 @@ describe('webFrameMain module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('WebFrame.origin', () => {
|
||||
it('should be null for a fresh WebContents', () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
expect(w.webContents.mainFrame.origin).to.equal('null');
|
||||
});
|
||||
|
||||
it('should be file:// for file frames', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(fixtures, 'blank.html'));
|
||||
expect(w.webContents.mainFrame.origin).to.equal('file://');
|
||||
});
|
||||
|
||||
it('should be http:// for an http frame', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
const s = await createServer();
|
||||
defer(() => s.server.close());
|
||||
await w.loadURL(s.url);
|
||||
expect(w.webContents.mainFrame.origin).to.equal(s.url.replace(/\/$/, ''));
|
||||
});
|
||||
|
||||
it('should show parent origin when child page is about:blank', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(fixtures, 'blank.html'));
|
||||
const webContentsCreated: Promise<[unknown, WebContents]> = emittedOnce(app, 'web-contents-created') as any;
|
||||
expect(w.webContents.mainFrame.origin).to.equal('file://');
|
||||
await w.webContents.executeJavaScript('window.open("", null, "show=false"), null');
|
||||
const [, childWebContents] = await webContentsCreated;
|
||||
expect(childWebContents.mainFrame.origin).to.equal('file://');
|
||||
});
|
||||
|
||||
it('should show parent frame\'s origin when about:blank child window opened through cross-origin subframe', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
const serverA = await createServer();
|
||||
const serverB = await createServer();
|
||||
defer(() => {
|
||||
serverA.server.close();
|
||||
serverB.server.close();
|
||||
});
|
||||
await w.loadURL(serverA.url + '?frameSrc=' + encodeURIComponent(serverB.url));
|
||||
const { mainFrame } = w.webContents;
|
||||
expect(mainFrame.origin).to.equal(serverA.url.replace(/\/$/, ''));
|
||||
const [childFrame] = mainFrame.frames;
|
||||
expect(childFrame.origin).to.equal(serverB.url.replace(/\/$/, ''));
|
||||
const webContentsCreated: Promise<[unknown, WebContents]> = emittedOnce(app, 'web-contents-created') as any;
|
||||
await childFrame.executeJavaScript('window.open("", null, "show=false"), null');
|
||||
const [, childWebContents] = await webContentsCreated;
|
||||
expect(childWebContents.mainFrame.origin).to.equal(childFrame.origin);
|
||||
});
|
||||
});
|
||||
|
||||
describe('WebFrame IDs', () => {
|
||||
it('has properties for various identifiers', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||
const webFrame = w.webContents.mainFrame;
|
||||
expect(webFrame).to.have.ownProperty('url').that.is.a('string');
|
||||
@@ -154,7 +204,7 @@ describe('webFrameMain module', () => {
|
||||
|
||||
describe('WebFrame.executeJavaScript', () => {
|
||||
it('can inject code into any subframe', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
|
||||
const webFrame = w.webContents.mainFrame;
|
||||
|
||||
@@ -165,7 +215,7 @@ describe('webFrameMain module', () => {
|
||||
});
|
||||
|
||||
it('can resolve promise', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||
const webFrame = w.webContents.mainFrame;
|
||||
const p = () => webFrame.executeJavaScript('new Promise(resolve => setTimeout(resolve(42), 2000));');
|
||||
@@ -174,7 +224,7 @@ describe('webFrameMain module', () => {
|
||||
});
|
||||
|
||||
it('can reject with error', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||
const webFrame = w.webContents.mainFrame;
|
||||
const p = () => webFrame.executeJavaScript('new Promise((r,e) => setTimeout(e("error!"), 500));');
|
||||
@@ -195,7 +245,7 @@ describe('webFrameMain module', () => {
|
||||
});
|
||||
|
||||
it('can reject when script execution fails', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||
const webFrame = w.webContents.mainFrame;
|
||||
const p = () => webFrame.executeJavaScript('console.log(test)');
|
||||
@@ -205,7 +255,7 @@ describe('webFrameMain module', () => {
|
||||
|
||||
describe('WebFrame.reload', () => {
|
||||
it('reloads a frame', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||
const webFrame = w.webContents.mainFrame;
|
||||
|
||||
@@ -238,7 +288,7 @@ describe('webFrameMain module', () => {
|
||||
let w: BrowserWindow;
|
||||
|
||||
beforeEach(async () => {
|
||||
w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
w = new BrowserWindow({ show: false });
|
||||
});
|
||||
|
||||
// TODO(jkleinsc) fix this flaky test on linux
|
||||
@@ -301,7 +351,7 @@ describe('webFrameMain module', () => {
|
||||
});
|
||||
|
||||
it('can find each frame from navigation events', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
||||
const w = new BrowserWindow({ show: false });
|
||||
|
||||
// frame-with-frame-container.html, frame-with-frame.html, frame.html
|
||||
const didFrameFinishLoad = emittedNTimes(w.webContents, 'did-frame-finish-load', 3);
|
||||
|
||||
@@ -1491,6 +1491,34 @@ describe('chromium features', () => {
|
||||
expect((w.webContents as any).length()).to.equal(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('window.history.back', () => {
|
||||
it('should not allow sandboxed iframe to modify main frame state', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
w.loadURL('data:text/html,<iframe sandbox="allow-scripts"></iframe>');
|
||||
await Promise.all([
|
||||
emittedOnce(w.webContents, 'navigation-entry-committed'),
|
||||
emittedOnce(w.webContents, 'did-frame-navigate'),
|
||||
emittedOnce(w.webContents, 'did-navigate')
|
||||
]);
|
||||
|
||||
w.webContents.executeJavaScript('window.history.pushState(1, "")');
|
||||
await Promise.all([
|
||||
emittedOnce(w.webContents, 'navigation-entry-committed'),
|
||||
emittedOnce(w.webContents, 'did-navigate-in-page')
|
||||
]);
|
||||
|
||||
(w.webContents as any).once('navigation-entry-committed', () => {
|
||||
expect.fail('Unexpected navigation-entry-committed');
|
||||
});
|
||||
w.webContents.once('did-navigate-in-page', () => {
|
||||
expect.fail('Unexpected did-navigate-in-page');
|
||||
});
|
||||
await w.webContents.mainFrame.frames[0].executeJavaScript('window.history.back()');
|
||||
expect(await w.webContents.executeJavaScript('window.history.state')).to.equal(1);
|
||||
expect((w.webContents as any).getActiveIndex()).to.equal(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('chrome://media-internals', () => {
|
||||
|
||||
@@ -183,4 +183,16 @@ describe('modules support', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('esm', () => {
|
||||
it('can load the built-in "electron" module via ESM import', async () => {
|
||||
await expect(import('electron')).to.eventually.be.ok();
|
||||
});
|
||||
|
||||
it('the built-in "electron" module loaded via ESM import has the same exports as the CJS module', async () => {
|
||||
const esmElectron = await import('electron');
|
||||
const cjsElectron = require('electron');
|
||||
expect(Object.keys(esmElectron)).to.deep.equal(Object.keys(cjsElectron));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user