mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
38 Commits
v26.0.0-be
...
v26.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6649ffb61 | ||
|
|
5da1b91546 | ||
|
|
1047532f1d | ||
|
|
054b99634c | ||
|
|
6838404ecb | ||
|
|
ee01054bb5 | ||
|
|
51b074eb5e | ||
|
|
2e27e273ed | ||
|
|
86fc724d97 | ||
|
|
c676293bf4 | ||
|
|
1afcffef53 | ||
|
|
04994de9e6 | ||
|
|
9dea18c1db | ||
|
|
ad76ef17f0 | ||
|
|
3d760afa36 | ||
|
|
0f2df2bf9b | ||
|
|
64c5505b36 | ||
|
|
ad385bf1ce | ||
|
|
0a478f9ef0 | ||
|
|
92c4697662 | ||
|
|
ceb5230395 | ||
|
|
c09ebeac14 | ||
|
|
5f1ada46f5 | ||
|
|
ca899eb3cb | ||
|
|
c709e04bed | ||
|
|
f9e35e4aaa | ||
|
|
d2ca670f3f | ||
|
|
4930f71a76 | ||
|
|
1c458c5eaf | ||
|
|
9c028cd279 | ||
|
|
fd8d4a8b94 | ||
|
|
35126e06b6 | ||
|
|
3e239efd99 | ||
|
|
66f42b3256 | ||
|
|
4586a40bfd | ||
|
|
3c467224d5 | ||
|
|
759329dc62 | ||
|
|
ac867a1b95 |
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'116.0.5845.49',
|
||||
'116.0.5845.97',
|
||||
'node_version':
|
||||
'v18.16.1',
|
||||
'nan_version':
|
||||
|
||||
@@ -187,6 +187,30 @@ for:
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only PR"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (-not(Test-Path $artifact_file)) {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
@@ -203,32 +227,16 @@ for:
|
||||
on_finish:
|
||||
# Uncomment this lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only PR"
|
||||
} else {
|
||||
$artifacts_to_upload = @('dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip')
|
||||
foreach($artifact_name in $artifacts_to_upload) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (Test-Path $artifact_file) {
|
||||
appveyor-retry appveyor PushArtifact $artifact_file
|
||||
} else {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
}
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
|
||||
61
appveyor.yml
61
appveyor.yml
@@ -185,6 +185,30 @@ for:
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only PR"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (-not(Test-Path $artifact_file)) {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
@@ -201,33 +225,16 @@ for:
|
||||
on_finish:
|
||||
# Uncomment this lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only PR"
|
||||
} else {
|
||||
$artifacts_to_upload = @('dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip')
|
||||
foreach($artifact_name in $artifacts_to_upload) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (Test-Path $artifact_file) {
|
||||
appveyor-retry appveyor PushArtifact $artifact_file
|
||||
} else {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
}
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
|
||||
@@ -413,18 +413,7 @@ Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `details` Object
|
||||
* `reason` string - The reason the render process is gone. Possible values:
|
||||
* `clean-exit` - Process exited with an exit code of zero
|
||||
* `abnormal-exit` - Process exited with a non-zero exit code
|
||||
* `killed` - Process was sent a SIGTERM or otherwise killed externally
|
||||
* `crashed` - Process crashed
|
||||
* `oom` - Process ran out of memory
|
||||
* `launch-failed` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
* `exitCode` Integer - The exit code of the process, unless `reason` is
|
||||
`launch-failed`, in which case `exitCode` will be a platform-specific
|
||||
launch failure error code.
|
||||
* `details` [RenderProcessGoneDetails](structures/render-process-gone-details.md)
|
||||
|
||||
Emitted when the renderer process unexpectedly disappears. This is normally
|
||||
because it was crashed or killed.
|
||||
|
||||
@@ -820,10 +820,14 @@ win.setBounds({ width: 100 })
|
||||
console.log(win.getBounds())
|
||||
```
|
||||
|
||||
**Note:** On macOS, the y-coordinate value cannot be smaller than the [Tray](tray.md) height. The tray height has changed over time and depends on the operating system, but is between 20-40px. Passing a value lower than the tray height will result in a window that is flush to the tray.
|
||||
|
||||
#### `win.getBounds()`
|
||||
|
||||
Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `Object`.
|
||||
|
||||
**Note:** On macOS, the y-coordinate value returned will be at minimum the [Tray](tray.md) height. For example, calling `win.setBounds({ x: 25, y: 20, width: 800, height: 600 })` with a tray height of 38 means that `win.getBounds()` will return `{ x: 25, y: 38, width: 800, height: 600 }`.
|
||||
|
||||
#### `win.getBackgroundColor()`
|
||||
|
||||
Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.
|
||||
|
||||
@@ -116,14 +116,20 @@ Ignore the connections limit for `domains` list separated by `,`.
|
||||
|
||||
### --js-flags=`flags`
|
||||
|
||||
Specifies the flags passed to the Node.js engine. It has to be passed when starting
|
||||
Electron if you want to enable the `flags` in the main process.
|
||||
Specifies the flags passed to the [V8 engine](https://v8.dev). In order to enable the `flags` in the main process,
|
||||
this switch must be passed on startup.
|
||||
|
||||
```sh
|
||||
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
|
||||
```
|
||||
|
||||
See the [Node.js documentation][node-cli] or run `node --help` in your terminal for a list of available flags. Additionally, run `node --v8-options` to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.
|
||||
Run `node --v8-options` or `electron --js-flags="--help"` in your terminal for the list of available flags. These can be used to enable early-stage JavaScript features, or log and manipulate garbage collection, among other things.
|
||||
|
||||
For example, to trace V8 optimization and deoptimization:
|
||||
|
||||
```sh
|
||||
$ electron --js-flags="--trace-opt --trace-deopt" your-app
|
||||
```
|
||||
|
||||
### --lang
|
||||
|
||||
@@ -241,19 +247,25 @@ Electron supports some of the [CLI flags][node-cli] supported by Node.js.
|
||||
|
||||
**Note:** Passing unsupported command line switches to Electron when it is not running in `ELECTRON_RUN_AS_NODE` will have no effect.
|
||||
|
||||
### --inspect-brk\[=\[host:]port]
|
||||
### `--inspect-brk\[=\[host:]port]`
|
||||
|
||||
Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229.
|
||||
|
||||
Aliased to `--debug-brk=[host:]port`.
|
||||
|
||||
### --inspect-port=\[host:]port
|
||||
#### `--inspect-brk-node[=[host:]port]`
|
||||
|
||||
Activate inspector on `host:port` and break at start of the first internal
|
||||
JavaScript script executed when the inspector is available.
|
||||
Default `host:port` is `127.0.0.1:9229`.
|
||||
|
||||
### `--inspect-port=\[host:]port`
|
||||
|
||||
Set the `host:port` to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Default host is `127.0.0.1`.
|
||||
|
||||
Aliased to `--debug-port=[host:]port`.
|
||||
|
||||
### --inspect\[=\[host:]port]
|
||||
### `--inspect\[=\[host:]port]`
|
||||
|
||||
Activate inspector on `host:port`. Default is `127.0.0.1:9229`.
|
||||
|
||||
@@ -263,12 +275,37 @@ See the [Debugging the Main Process][debugging-main-process] guide for more deta
|
||||
|
||||
Aliased to `--debug[=[host:]port`.
|
||||
|
||||
### --inspect-publish-uid=stderr,http
|
||||
### `--inspect-publish-uid=stderr,http`
|
||||
|
||||
Specify ways of the inspector web socket url exposure.
|
||||
|
||||
By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.
|
||||
|
||||
### `--no-deprecation`
|
||||
|
||||
Silence deprecation warnings.
|
||||
|
||||
### `--throw-deprecation`
|
||||
|
||||
Throw errors for deprecations.
|
||||
|
||||
### `--trace-deprecation`
|
||||
|
||||
Print stack traces for deprecations.
|
||||
|
||||
### `--trace-warnings`
|
||||
|
||||
Print stack traces for process warnings (including deprecations).
|
||||
|
||||
### `--dns-result-order=order`
|
||||
|
||||
Set the default value of the `verbatim` parameter in the Node.js [`dns.lookup()`](https://nodejs.org/api/dns.html#dnslookuphostname-options-callback) and [`dnsPromises.lookup()`](https://nodejs.org/api/dns.html#dnspromiseslookuphostname-options) functions. The value could be:
|
||||
|
||||
* `ipv4first`: sets default `verbatim` `false`.
|
||||
* `verbatim`: sets default `verbatim` `true`.
|
||||
|
||||
The default is `verbatim` and `dns.setDefaultResultOrder()` have higher priority than `--dns-result-order`.
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: command-line.md#commandlineappendswitchswitch-value
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
|
||||
@@ -91,8 +91,9 @@ The following events of `chrome.runtime` are supported:
|
||||
|
||||
### `chrome.storage`
|
||||
|
||||
Only `chrome.storage.local` is supported; `chrome.storage.sync` and
|
||||
`chrome.storage.managed` are not.
|
||||
The following methods of `chrome.storage` are supported:
|
||||
|
||||
- `chrome.storage.local`
|
||||
|
||||
### `chrome.tabs`
|
||||
|
||||
@@ -101,6 +102,8 @@ The following methods of `chrome.tabs` are supported:
|
||||
- `chrome.tabs.sendMessage`
|
||||
- `chrome.tabs.reload`
|
||||
- `chrome.tabs.executeScript`
|
||||
- `chrome.tabs.query` (partial support)
|
||||
- supported properties: `url`, `title`, `audible`, `active`, `muted`.
|
||||
- `chrome.tabs.update` (partial support)
|
||||
- supported properties: `url`, `muted`.
|
||||
|
||||
@@ -117,6 +120,9 @@ The following methods of `chrome.management` are supported:
|
||||
- `chrome.management.getSelf`
|
||||
- `chrome.management.getPermissionWarningsById`
|
||||
- `chrome.management.getPermissionWarningsByManifest`
|
||||
|
||||
The following events of `chrome.management` are supported:
|
||||
|
||||
- `chrome.management.onEnabled`
|
||||
- `chrome.management.onDisabled`
|
||||
|
||||
|
||||
13
docs/api/structures/render-process-gone-details.md
Normal file
13
docs/api/structures/render-process-gone-details.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# RenderProcessGoneDetails Object
|
||||
|
||||
* `reason` string - The reason the render process is gone. Possible values:
|
||||
* `clean-exit` - Process exited with an exit code of zero
|
||||
* `abnormal-exit` - Process exited with a non-zero exit code
|
||||
* `killed` - Process was sent a SIGTERM or otherwise killed externally
|
||||
* `crashed` - Process crashed
|
||||
* `oom` - Process ran out of memory
|
||||
* `launch-failed` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
* `exitCode` Integer - The exit code of the process, unless `reason` is
|
||||
`launch-failed`, in which case `exitCode` will be a platform-specific
|
||||
launch failure error code.
|
||||
@@ -435,7 +435,7 @@ Returns an object with system animation settings.
|
||||
|
||||
## Properties
|
||||
|
||||
### `systemPreferences.appLevelAppearance` _macOS_
|
||||
### `systemPreferences.appLevelAppearance` _macOS_ _Deprecated_
|
||||
|
||||
A `string` property that can be `dark`, `light` or `unknown`. It determines the macOS appearance setting for
|
||||
your application. This maps to values in: [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc). Setting this will override the
|
||||
|
||||
@@ -479,18 +479,7 @@ checking `reason === 'killed'` when you switch to that event.
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `reason` string - The reason the render process is gone. Possible values:
|
||||
* `clean-exit` - Process exited with an exit code of zero
|
||||
* `abnormal-exit` - Process exited with a non-zero exit code
|
||||
* `killed` - Process was sent a SIGTERM or otherwise killed externally
|
||||
* `crashed` - Process crashed
|
||||
* `oom` - Process ran out of memory
|
||||
* `launch-failed` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
* `exitCode` Integer - The exit code of the process, unless `reason` is
|
||||
`launch-failed`, in which case `exitCode` will be a platform-specific
|
||||
launch failure error code.
|
||||
* `details` [RenderProcessGoneDetails](structures/render-process-gone-details.md)
|
||||
|
||||
Emitted when the renderer process unexpectedly disappears. This is normally
|
||||
because it was crashed or killed.
|
||||
|
||||
@@ -983,9 +983,22 @@ ipcRenderer.on('ping', () => {
|
||||
})
|
||||
```
|
||||
|
||||
### Event: 'crashed'
|
||||
### Event: 'crashed' _Deprecated_
|
||||
|
||||
Fired when the renderer process is crashed.
|
||||
Fired when the renderer process crashes or is killed.
|
||||
|
||||
**Deprecated:** This event is superceded by the `render-process-gone` event
|
||||
which contains more information about why the render process disappeared. It
|
||||
isn't always because it crashed.
|
||||
|
||||
### Event: 'render-process-gone'
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` [RenderProcessGoneDetails](structures/render-process-gone-details.md)
|
||||
|
||||
Fired when the renderer process unexpectedly disappears. This is normally
|
||||
because it was crashed or killed.
|
||||
|
||||
### Event: 'plugin-crashed'
|
||||
|
||||
|
||||
@@ -21,6 +21,59 @@ macOS 10.13 (High Sierra) and macOS 10.14 (Mojave) are no longer supported by [C
|
||||
Older versions of Electron will continue to run on these operating systems, but macOS 10.15 (Catalina)
|
||||
or later will be required to run Electron v27.0.0 and higher.
|
||||
|
||||
## Planned Breaking API Changes (26.0)
|
||||
|
||||
### Deprecated: `webContents.getPrinters`
|
||||
|
||||
The `webContents.getPrinters` method has been deprecated. Use
|
||||
`webContents.getPrintersAsync` instead.
|
||||
|
||||
```js
|
||||
const w = new BrowserWindow({ show: false })
|
||||
|
||||
// Deprecated
|
||||
console.log(w.webContents.getPrinters())
|
||||
// Replace with
|
||||
w.webContents.getPrintersAsync().then((printers) => {
|
||||
console.log(printers)
|
||||
})
|
||||
```
|
||||
|
||||
### Deprecated: `systemPreferences.{get,set}AppLevelAppearance` and `systemPreferences.appLevelAppearance`
|
||||
|
||||
The `systemPreferences.getAppLevelAppearance` and `systemPreferences.setAppLevelAppearance`
|
||||
methods have been deprecated, as well as the `systemPreferences.appLevelAppearance` property.
|
||||
Use the `nativeTheme` module instead.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.getAppLevelAppearance()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseDarkColors
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.appLevelAppearance
|
||||
// Replace with
|
||||
nativeTheme.shouldUseDarkColors
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.setAppLevelAppearance('dark')
|
||||
// Replace with
|
||||
nativeTheme.themeSource = 'dark'
|
||||
```
|
||||
|
||||
### Deprecated: `alternate-selected-control-text` value for `systemPreferences.getColor`
|
||||
|
||||
The `alternate-selected-control-text` value for `systemPreferences.getColor`
|
||||
has been deprecated. Use `selected-content-background` instead.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.getColor('alternate-selected-control-text')
|
||||
// Replace with
|
||||
systemPreferences.getColor('selected-content-background')
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (25.0)
|
||||
|
||||
### Deprecated: `protocol.{register,intercept}{Buffer,String,Stream,File,Http}Protocol`
|
||||
|
||||
@@ -9,10 +9,11 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
|
||||
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | TBD | M116 | TBD | ✅ |
|
||||
| 27.0.0 | 2023-Aug-17 | 2023-Sep-13 | 2023-Oct-10 | TBD | M118 | TBD | ✅ |
|
||||
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | 2024-Feb-27 | M116 | v18.16 | ✅ |
|
||||
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2024-Jan-02 | M114 | v18.15 | ✅ |
|
||||
| 24.0.0 | 2022-Feb-09 | 2023-Mar-07 | 2023-Apr-04 | 2023-Oct-10 | M112 | v18.14 | ✅ |
|
||||
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-15 | M110 | v18.12 | ✅ |
|
||||
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-15 | M110 | v18.12 | 🚫 |
|
||||
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | 2023-Oct-10 | M108 | v16.17 | ✅ |
|
||||
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | 2023-Apr-04 | M106 | v16.16 | 🚫 |
|
||||
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | 2023-Feb-07 | M104 | v16.15 | 🚫 |
|
||||
|
||||
@@ -61,6 +61,7 @@ template("electron_extra_paks") {
|
||||
"$root_gen_dir/content/browser/tracing/tracing_resources.pak",
|
||||
"$root_gen_dir/content/browser/webrtc/resources/webrtc_internals_resources.pak",
|
||||
"$root_gen_dir/content/content_resources.pak",
|
||||
"$root_gen_dir/content/gpu_resources.pak",
|
||||
"$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
|
||||
"$root_gen_dir/net/net_resources.pak",
|
||||
"$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
|
||||
@@ -74,6 +75,7 @@ template("electron_extra_paks") {
|
||||
"//chrome/common:resources",
|
||||
"//components/resources",
|
||||
"//content:content_resources",
|
||||
"//content/browser/resources/gpu:resources",
|
||||
"//content/browser/resources/media:resources",
|
||||
"//content/browser/tracing:resources",
|
||||
"//content/browser/webrtc/resources",
|
||||
@@ -174,6 +176,7 @@ template("electron_paks") {
|
||||
}
|
||||
|
||||
source_patterns = [
|
||||
"${root_gen_dir}/chrome/chromium_strings_",
|
||||
"${root_gen_dir}/chrome/locale_settings_",
|
||||
"${root_gen_dir}/chrome/platform_locale_settings_",
|
||||
"${root_gen_dir}/chrome/generated_resources_",
|
||||
@@ -189,6 +192,7 @@ template("electron_paks") {
|
||||
"${root_gen_dir}/ui/strings/ui_strings_",
|
||||
]
|
||||
deps = [
|
||||
"//chrome/app:chromium_strings",
|
||||
"//chrome/app:generated_resources",
|
||||
"//chrome/app/resources:locale_settings",
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
|
||||
@@ -115,6 +115,7 @@ auto_filenames = {
|
||||
"docs/api/structures/protocol-response.md",
|
||||
"docs/api/structures/rectangle.md",
|
||||
"docs/api/structures/referrer.md",
|
||||
"docs/api/structures/render-process-gone-details.md",
|
||||
"docs/api/structures/resolved-endpoint.md",
|
||||
"docs/api/structures/resolved-host.md",
|
||||
"docs/api/structures/scrubber-item.md",
|
||||
|
||||
@@ -508,6 +508,7 @@ filenames = {
|
||||
"shell/browser/web_contents_preferences.h",
|
||||
"shell/browser/web_contents_zoom_controller.cc",
|
||||
"shell/browser/web_contents_zoom_controller.h",
|
||||
"shell/browser/web_contents_zoom_observer.h",
|
||||
"shell/browser/web_view_guest_delegate.cc",
|
||||
"shell/browser/web_view_guest_delegate.h",
|
||||
"shell/browser/web_view_manager.cc",
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
import * as deprecate from '@electron/internal/common/deprecate';
|
||||
|
||||
const { systemPreferences } = process._linkedBinding('electron_browser_system_preferences');
|
||||
|
||||
if ('getAppLevelAppearance' in systemPreferences) {
|
||||
const nativeALAGetter = systemPreferences.getAppLevelAppearance;
|
||||
const nativeALASetter = systemPreferences.setAppLevelAppearance;
|
||||
const warnALA = deprecate.warnOnce('appLevelAppearance');
|
||||
const warnALAGetter = deprecate.warnOnce('getAppLevelAppearance function');
|
||||
const warnALASetter = deprecate.warnOnce('setAppLevelAppearance function');
|
||||
Object.defineProperty(systemPreferences, 'appLevelAppearance', {
|
||||
get: () => nativeALAGetter.call(systemPreferences),
|
||||
set: (appearance) => nativeALASetter.call(systemPreferences, appearance)
|
||||
get: () => {
|
||||
warnALA();
|
||||
return nativeALAGetter.call(systemPreferences);
|
||||
},
|
||||
set: (appearance) => {
|
||||
warnALA();
|
||||
nativeALASetter.call(systemPreferences, appearance);
|
||||
}
|
||||
});
|
||||
systemPreferences.getAppLevelAppearance = () => {
|
||||
warnALAGetter();
|
||||
return nativeALAGetter.call(systemPreferences);
|
||||
};
|
||||
systemPreferences.setAppLevelAppearance = (appearance) => {
|
||||
warnALASetter();
|
||||
nativeALASetter.call(systemPreferences, appearance);
|
||||
};
|
||||
}
|
||||
|
||||
if ('getEffectiveAppearance' in systemPreferences) {
|
||||
|
||||
3
patches/angle/.patches
Normal file
3
patches/angle/.patches
Normal file
@@ -0,0 +1,3 @@
|
||||
cherry-pick-285c7712c506.patch
|
||||
cherry-pick-2bf945775fe6.patch
|
||||
cherry-pick-cafe56b591ed.patch
|
||||
153
patches/angle/cherry-pick-285c7712c506.patch
Normal file
153
patches/angle/cherry-pick-285c7712c506.patch
Normal file
@@ -0,0 +1,153 @@
|
||||
From 285c7712c50654e3d7238b059c4631bc91285514 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Thu, 13 Jul 2023 15:23:49 -0400
|
||||
Subject: [PATCH] M116: Translator: Unconditionally limit variable sizes
|
||||
|
||||
... instead of just for WebGL. This is to avoid hitting driver bugs
|
||||
that were prevented with this check for WebGL on a compromised renderer
|
||||
that can create non-WebGL contexts.
|
||||
|
||||
Bug: chromium:1464682
|
||||
Change-Id: I2b1c5a8c51f06225f5f850109d30778d97e574c7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4717371
|
||||
Reviewed-by: Roman Lavrov <romanl@google.com>
|
||||
---
|
||||
|
||||
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
|
||||
index 7b1ac4e..383feeb 100644
|
||||
--- a/src/compiler/translator/Compiler.cpp
|
||||
+++ b/src/compiler/translator/Compiler.cpp
|
||||
@@ -397,9 +397,10 @@
|
||||
|
||||
bool TCompiler::shouldLimitTypeSizes() const
|
||||
{
|
||||
- // WebGL shaders limit the size of variables' types in shaders,
|
||||
- // including arrays, structs and interface blocks.
|
||||
- return IsWebGLBasedSpec(mShaderSpec);
|
||||
+ // Prevent unrealistically large variable sizes in shaders. This works around driver bugs
|
||||
+ // around int-size limits (such as 2GB). The limits are generously large enough that no real
|
||||
+ // shader should ever hit it.
|
||||
+ return true;
|
||||
}
|
||||
|
||||
bool TCompiler::Init(const ShBuiltInResources &resources)
|
||||
diff --git a/src/compiler/translator/ValidateTypeSizeLimitations.cpp b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
index 2a033ad..19a4821 100644
|
||||
--- a/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
+++ b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
@@ -23,10 +23,10 @@
|
||||
// Arbitrarily enforce that all types declared with a size in bytes of over 2 GB will cause
|
||||
// compilation failure.
|
||||
//
|
||||
-// For local and global variables, the limit is much lower (1MB) as that much memory won't fit in
|
||||
+// For local and global variables, the limit is much lower (16MB) as that much memory won't fit in
|
||||
// the GPU registers anyway.
|
||||
constexpr size_t kMaxVariableSizeInBytes = static_cast<size_t>(2) * 1024 * 1024 * 1024;
|
||||
-constexpr size_t kMaxPrivateVariableSizeInBytes = static_cast<size_t>(1) * 1024 * 1024;
|
||||
+constexpr size_t kMaxPrivateVariableSizeInBytes = static_cast<size_t>(16) * 1024 * 1024;
|
||||
|
||||
// Traverses intermediate tree to ensure that the shader does not
|
||||
// exceed certain implementation-defined limits on the sizes of types.
|
||||
diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp
|
||||
index a91f8b0..a866b25 100644
|
||||
--- a/src/compiler/translator/util.cpp
|
||||
+++ b/src/compiler/translator/util.cpp
|
||||
@@ -282,6 +282,9 @@
|
||||
|
||||
return kBoolGLType[type.getNominalSize() - 1];
|
||||
|
||||
+ case EbtYuvCscStandardEXT:
|
||||
+ return GL_UNSIGNED_INT;
|
||||
+
|
||||
case EbtSampler2D:
|
||||
return GL_SAMPLER_2D;
|
||||
case EbtSampler3D:
|
||||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
index 9ae56f5..a8d2ce4 100644
|
||||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
@@ -5284,8 +5284,8 @@
|
||||
|
||||
constexpr char kVSArrayTooLarge[] =
|
||||
R"(varying vec4 color;
|
||||
-// 1 MB / 32 aligned bytes per mat2 = 32768
|
||||
-const int array_size = 32769;
|
||||
+// 16 MB / 32 aligned bytes per mat2 = 524288
|
||||
+const int array_size = 524289;
|
||||
void main()
|
||||
{
|
||||
mat2 array[array_size];
|
||||
@@ -5297,7 +5297,7 @@
|
||||
|
||||
constexpr char kVSArrayMuchTooLarge[] =
|
||||
R"(varying vec4 color;
|
||||
-const int array_size = 55600;
|
||||
+const int array_size = 757000;
|
||||
void main()
|
||||
{
|
||||
mat2 array[array_size];
|
||||
@@ -5361,9 +5361,9 @@
|
||||
constexpr char kTooLargeGlobalMemory1[] =
|
||||
R"(precision mediump float;
|
||||
|
||||
-// 1 MB / 16 bytes per vec4 = 65536
|
||||
-vec4 array[32768];
|
||||
-vec4 array2[32769];
|
||||
+// 16 MB / 16 bytes per vec4 = 1048576
|
||||
+vec4 array[524288];
|
||||
+vec4 array2[524289];
|
||||
|
||||
void main()
|
||||
{
|
||||
@@ -5376,9 +5376,9 @@
|
||||
constexpr char kTooLargeGlobalMemory2[] =
|
||||
R"(precision mediump float;
|
||||
|
||||
-// 1 MB / 16 bytes per vec4 = 65536
|
||||
-vec4 array[32767];
|
||||
-vec4 array2[32767];
|
||||
+// 16 MB / 16 bytes per vec4 = 1048576
|
||||
+vec4 array[524287];
|
||||
+vec4 array2[524287];
|
||||
vec4 x, y, z;
|
||||
|
||||
void main()
|
||||
@@ -5392,12 +5392,12 @@
|
||||
constexpr char kTooLargeGlobalAndLocalMemory1[] =
|
||||
R"(precision mediump float;
|
||||
|
||||
-// 1 MB / 16 bytes per vec4 = 65536
|
||||
-vec4 array[32768];
|
||||
+// 16 MB / 16 bytes per vec4 = 1048576
|
||||
+vec4 array[524288];
|
||||
|
||||
void main()
|
||||
{
|
||||
- vec4 array2[32769];
|
||||
+ vec4 array2[524289];
|
||||
if (array[0].x + array[1].x == 2.0)
|
||||
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
else
|
||||
@@ -5408,18 +5408,18 @@
|
||||
constexpr char kTooLargeGlobalAndLocalMemory2[] =
|
||||
R"(precision mediump float;
|
||||
|
||||
-// 1 MB / 16 bytes per vec4 = 65536
|
||||
-vec4 array[32768];
|
||||
+// 16 MB / 16 bytes per vec4 = 1048576
|
||||
+vec4 array[524288];
|
||||
|
||||
float f()
|
||||
{
|
||||
- vec4 array2[16384];
|
||||
+ vec4 array2[524288];
|
||||
return array2[0].x;
|
||||
}
|
||||
|
||||
float g()
|
||||
{
|
||||
- vec4 array3[16383];
|
||||
+ vec4 array3[524287];
|
||||
return array3[0].x;
|
||||
}
|
||||
|
||||
197
patches/angle/cherry-pick-2bf945775fe6.patch
Normal file
197
patches/angle/cherry-pick-2bf945775fe6.patch
Normal file
@@ -0,0 +1,197 @@
|
||||
From 2bf945775fe634eb9e420c2263dae6043bbb5ece Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Fri, 14 Jul 2023 12:30:15 -0400
|
||||
Subject: [PATCH] M116: Translator: Limit variable sizes vs uint overflow
|
||||
|
||||
Bug: chromium:1464680
|
||||
Change-Id: Iee41a2da7a7a330e6cc4d6da59a6e9836ee9dd36
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4717372
|
||||
Reviewed-by: Roman Lavrov <romanl@google.com>
|
||||
---
|
||||
|
||||
diff --git a/src/compiler/translator/ValidateTypeSizeLimitations.cpp b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
index 19a4821..f0ff9cb 100644
|
||||
--- a/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
+++ b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "compiler/translator/ValidateTypeSizeLimitations.h"
|
||||
|
||||
#include "angle_gl.h"
|
||||
+#include "common/mathutil.h"
|
||||
#include "compiler/translator/Diagnostics.h"
|
||||
#include "compiler/translator/Symbol.h"
|
||||
#include "compiler/translator/SymbolTable.h"
|
||||
@@ -113,7 +114,8 @@
|
||||
|
||||
void validateTotalPrivateVariableSize()
|
||||
{
|
||||
- if (mTotalPrivateVariablesSize > kMaxPrivateVariableSizeInBytes)
|
||||
+ if (mTotalPrivateVariablesSize.ValueOrDefault(std::numeric_limits<size_t>::max()) >
|
||||
+ kMaxPrivateVariableSizeInBytes)
|
||||
{
|
||||
mDiagnostics->error(
|
||||
TSourceLoc{},
|
||||
@@ -231,7 +233,7 @@
|
||||
TDiagnostics *mDiagnostics;
|
||||
std::vector<int> mLoopSymbolIds;
|
||||
|
||||
- size_t mTotalPrivateVariablesSize;
|
||||
+ angle::base::CheckedNumeric<size_t> mTotalPrivateVariablesSize;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
index a8d2ce4..542d49f 100644
|
||||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
@@ -5426,7 +5426,7 @@
|
||||
float h()
|
||||
{
|
||||
vec4 value;
|
||||
- float value2
|
||||
+ float value2;
|
||||
return value.x + value2;
|
||||
}
|
||||
|
||||
@@ -5438,6 +5438,131 @@
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
})";
|
||||
|
||||
+ constexpr char kTooLargeGlobalMemoryOverflow[] =
|
||||
+ R"(precision mediump float;
|
||||
+
|
||||
+// 16 MB / 16 bytes per vec4 = 1048576
|
||||
+// Create 256 arrays so each is small, but the total overflows a 32-bit number
|
||||
+vec4 array[1048576], array2[1048576], array3[1048576], array4[1048576], array5[1048576];
|
||||
+vec4 array6[1048576], array7[1048576], array8[1048576], array9[1048576], array10[1048576];
|
||||
+vec4 array11[1048576], array12[1048576], array13[1048576], array14[1048576], array15[1048576];
|
||||
+vec4 array16[1048576], array17[1048576], array18[1048576], array19[1048576], array20[1048576];
|
||||
+vec4 array21[1048576], array22[1048576], array23[1048576], array24[1048576], array25[1048576];
|
||||
+vec4 array26[1048576], array27[1048576], array28[1048576], array29[1048576], array30[1048576];
|
||||
+vec4 array31[1048576], array32[1048576], array33[1048576], array34[1048576], array35[1048576];
|
||||
+vec4 array36[1048576], array37[1048576], array38[1048576], array39[1048576], array40[1048576];
|
||||
+vec4 array41[1048576], array42[1048576], array43[1048576], array44[1048576], array45[1048576];
|
||||
+vec4 array46[1048576], array47[1048576], array48[1048576], array49[1048576], array50[1048576];
|
||||
+vec4 array51[1048576], array52[1048576], array53[1048576], array54[1048576], array55[1048576];
|
||||
+vec4 array56[1048576], array57[1048576], array58[1048576], array59[1048576], array60[1048576];
|
||||
+vec4 array61[1048576], array62[1048576], array63[1048576], array64[1048576], array65[1048576];
|
||||
+vec4 array66[1048576], array67[1048576], array68[1048576], array69[1048576], array70[1048576];
|
||||
+vec4 array71[1048576], array72[1048576], array73[1048576], array74[1048576], array75[1048576];
|
||||
+vec4 array76[1048576], array77[1048576], array78[1048576], array79[1048576], array80[1048576];
|
||||
+vec4 array81[1048576], array82[1048576], array83[1048576], array84[1048576], array85[1048576];
|
||||
+vec4 array86[1048576], array87[1048576], array88[1048576], array89[1048576], array90[1048576];
|
||||
+vec4 array91[1048576], array92[1048576], array93[1048576], array94[1048576], array95[1048576];
|
||||
+vec4 array96[1048576], array97[1048576], array98[1048576], array99[1048576], array100[1048576];
|
||||
+vec4 array101[1048576], array102[1048576], array103[1048576], array104[1048576], array105[1048576];
|
||||
+vec4 array106[1048576], array107[1048576], array108[1048576], array109[1048576], array110[1048576];
|
||||
+vec4 array111[1048576], array112[1048576], array113[1048576], array114[1048576], array115[1048576];
|
||||
+vec4 array116[1048576], array117[1048576], array118[1048576], array119[1048576], array120[1048576];
|
||||
+vec4 array121[1048576], array122[1048576], array123[1048576], array124[1048576], array125[1048576];
|
||||
+vec4 array126[1048576], array127[1048576], array128[1048576], array129[1048576], array130[1048576];
|
||||
+vec4 array131[1048576], array132[1048576], array133[1048576], array134[1048576], array135[1048576];
|
||||
+vec4 array136[1048576], array137[1048576], array138[1048576], array139[1048576], array140[1048576];
|
||||
+vec4 array141[1048576], array142[1048576], array143[1048576], array144[1048576], array145[1048576];
|
||||
+vec4 array146[1048576], array147[1048576], array148[1048576], array149[1048576], array150[1048576];
|
||||
+vec4 array151[1048576], array152[1048576], array153[1048576], array154[1048576], array155[1048576];
|
||||
+vec4 array156[1048576], array157[1048576], array158[1048576], array159[1048576], array160[1048576];
|
||||
+vec4 array161[1048576], array162[1048576], array163[1048576], array164[1048576], array165[1048576];
|
||||
+vec4 array166[1048576], array167[1048576], array168[1048576], array169[1048576], array170[1048576];
|
||||
+vec4 array171[1048576], array172[1048576], array173[1048576], array174[1048576], array175[1048576];
|
||||
+vec4 array176[1048576], array177[1048576], array178[1048576], array179[1048576], array180[1048576];
|
||||
+vec4 array181[1048576], array182[1048576], array183[1048576], array184[1048576], array185[1048576];
|
||||
+vec4 array186[1048576], array187[1048576], array188[1048576], array189[1048576], array190[1048576];
|
||||
+vec4 array191[1048576], array192[1048576], array193[1048576], array194[1048576], array195[1048576];
|
||||
+vec4 array196[1048576], array197[1048576], array198[1048576], array199[1048576], array200[1048576];
|
||||
+vec4 array201[1048576], array202[1048576], array203[1048576], array204[1048576], array205[1048576];
|
||||
+vec4 array206[1048576], array207[1048576], array208[1048576], array209[1048576], array210[1048576];
|
||||
+vec4 array211[1048576], array212[1048576], array213[1048576], array214[1048576], array215[1048576];
|
||||
+vec4 array216[1048576], array217[1048576], array218[1048576], array219[1048576], array220[1048576];
|
||||
+vec4 array221[1048576], array222[1048576], array223[1048576], array224[1048576], array225[1048576];
|
||||
+vec4 array226[1048576], array227[1048576], array228[1048576], array229[1048576], array230[1048576];
|
||||
+vec4 array231[1048576], array232[1048576], array233[1048576], array234[1048576], array235[1048576];
|
||||
+vec4 array236[1048576], array237[1048576], array238[1048576], array239[1048576], array240[1048576];
|
||||
+vec4 array241[1048576], array242[1048576], array243[1048576], array244[1048576], array245[1048576];
|
||||
+vec4 array246[1048576], array247[1048576], array248[1048576], array249[1048576], array250[1048576];
|
||||
+vec4 array251[1048576], array252[1048576], array253[1048576], array254[1048576], array255[1048576];
|
||||
+vec4 array256[1048576];
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ float f = array[0].x; f += array2[0].x; f += array3[0].x; f += array4[0].x; f += array5[0].x;
|
||||
+ f += array6[0].x; f += array7[0].x; f += array8[0].x; f += array9[0].x; f += array10[0].x;
|
||||
+ f += array11[0].x; f += array12[0].x; f += array13[0].x; f += array14[0].x; f += array15[0].x;
|
||||
+ f += array16[0].x; f += array17[0].x; f += array18[0].x; f += array19[0].x; f += array20[0].x;
|
||||
+ f += array21[0].x; f += array22[0].x; f += array23[0].x; f += array24[0].x; f += array25[0].x;
|
||||
+ f += array26[0].x; f += array27[0].x; f += array28[0].x; f += array29[0].x; f += array30[0].x;
|
||||
+ f += array31[0].x; f += array32[0].x; f += array33[0].x; f += array34[0].x; f += array35[0].x;
|
||||
+ f += array36[0].x; f += array37[0].x; f += array38[0].x; f += array39[0].x; f += array40[0].x;
|
||||
+ f += array41[0].x; f += array42[0].x; f += array43[0].x; f += array44[0].x; f += array45[0].x;
|
||||
+ f += array46[0].x; f += array47[0].x; f += array48[0].x; f += array49[0].x; f += array50[0].x;
|
||||
+ f += array51[0].x; f += array52[0].x; f += array53[0].x; f += array54[0].x; f += array55[0].x;
|
||||
+ f += array56[0].x; f += array57[0].x; f += array58[0].x; f += array59[0].x; f += array60[0].x;
|
||||
+ f += array61[0].x; f += array62[0].x; f += array63[0].x; f += array64[0].x; f += array65[0].x;
|
||||
+ f += array66[0].x; f += array67[0].x; f += array68[0].x; f += array69[0].x; f += array70[0].x;
|
||||
+ f += array71[0].x; f += array72[0].x; f += array73[0].x; f += array74[0].x; f += array75[0].x;
|
||||
+ f += array76[0].x; f += array77[0].x; f += array78[0].x; f += array79[0].x; f += array80[0].x;
|
||||
+ f += array81[0].x; f += array82[0].x; f += array83[0].x; f += array84[0].x; f += array85[0].x;
|
||||
+ f += array86[0].x; f += array87[0].x; f += array88[0].x; f += array89[0].x; f += array90[0].x;
|
||||
+ f += array91[0].x; f += array92[0].x; f += array93[0].x; f += array94[0].x; f += array95[0].x;
|
||||
+ f += array96[0].x; f += array97[0].x; f += array98[0].x; f += array99[0].x; f += array100[0].x;
|
||||
+ f += array101[0].x; f += array102[0].x; f += array103[0].x; f += array104[0].x;
|
||||
+ f += array105[0].x; f += array106[0].x; f += array107[0].x; f += array108[0].x;
|
||||
+ f += array109[0].x; f += array110[0].x; f += array111[0].x; f += array112[0].x;
|
||||
+ f += array113[0].x; f += array114[0].x; f += array115[0].x; f += array116[0].x;
|
||||
+ f += array117[0].x; f += array118[0].x; f += array119[0].x; f += array120[0].x;
|
||||
+ f += array121[0].x; f += array122[0].x; f += array123[0].x; f += array124[0].x;
|
||||
+ f += array125[0].x; f += array126[0].x; f += array127[0].x; f += array128[0].x;
|
||||
+ f += array129[0].x; f += array130[0].x; f += array131[0].x; f += array132[0].x;
|
||||
+ f += array133[0].x; f += array134[0].x; f += array135[0].x; f += array136[0].x;
|
||||
+ f += array137[0].x; f += array138[0].x; f += array139[0].x; f += array140[0].x;
|
||||
+ f += array141[0].x; f += array142[0].x; f += array143[0].x; f += array144[0].x;
|
||||
+ f += array145[0].x; f += array146[0].x; f += array147[0].x; f += array148[0].x;
|
||||
+ f += array149[0].x; f += array150[0].x; f += array151[0].x; f += array152[0].x;
|
||||
+ f += array153[0].x; f += array154[0].x; f += array155[0].x; f += array156[0].x;
|
||||
+ f += array157[0].x; f += array158[0].x; f += array159[0].x; f += array160[0].x;
|
||||
+ f += array161[0].x; f += array162[0].x; f += array163[0].x; f += array164[0].x;
|
||||
+ f += array165[0].x; f += array166[0].x; f += array167[0].x; f += array168[0].x;
|
||||
+ f += array169[0].x; f += array170[0].x; f += array171[0].x; f += array172[0].x;
|
||||
+ f += array173[0].x; f += array174[0].x; f += array175[0].x; f += array176[0].x;
|
||||
+ f += array177[0].x; f += array178[0].x; f += array179[0].x; f += array180[0].x;
|
||||
+ f += array181[0].x; f += array182[0].x; f += array183[0].x; f += array184[0].x;
|
||||
+ f += array185[0].x; f += array186[0].x; f += array187[0].x; f += array188[0].x;
|
||||
+ f += array189[0].x; f += array190[0].x; f += array191[0].x; f += array192[0].x;
|
||||
+ f += array193[0].x; f += array194[0].x; f += array195[0].x; f += array196[0].x;
|
||||
+ f += array197[0].x; f += array198[0].x; f += array199[0].x; f += array200[0].x;
|
||||
+ f += array201[0].x; f += array202[0].x; f += array203[0].x; f += array204[0].x;
|
||||
+ f += array205[0].x; f += array206[0].x; f += array207[0].x; f += array208[0].x;
|
||||
+ f += array209[0].x; f += array210[0].x; f += array211[0].x; f += array212[0].x;
|
||||
+ f += array213[0].x; f += array214[0].x; f += array215[0].x; f += array216[0].x;
|
||||
+ f += array217[0].x; f += array218[0].x; f += array219[0].x; f += array220[0].x;
|
||||
+ f += array221[0].x; f += array222[0].x; f += array223[0].x; f += array224[0].x;
|
||||
+ f += array225[0].x; f += array226[0].x; f += array227[0].x; f += array228[0].x;
|
||||
+ f += array229[0].x; f += array230[0].x; f += array231[0].x; f += array232[0].x;
|
||||
+ f += array233[0].x; f += array234[0].x; f += array235[0].x; f += array236[0].x;
|
||||
+ f += array237[0].x; f += array238[0].x; f += array239[0].x; f += array240[0].x;
|
||||
+ f += array241[0].x; f += array242[0].x; f += array243[0].x; f += array244[0].x;
|
||||
+ f += array245[0].x; f += array246[0].x; f += array247[0].x; f += array248[0].x;
|
||||
+ f += array249[0].x; f += array250[0].x; f += array251[0].x; f += array252[0].x;
|
||||
+ f += array253[0].x; f += array254[0].x; f += array255[0].x; f += array256[0].x;
|
||||
+ if (f == 2.0)
|
||||
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
+ else
|
||||
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
+})";
|
||||
+
|
||||
GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemory1);
|
||||
EXPECT_EQ(0u, program);
|
||||
|
||||
@@ -5449,6 +5574,9 @@
|
||||
|
||||
program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalAndLocalMemory2);
|
||||
EXPECT_EQ(0u, program);
|
||||
+
|
||||
+ program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemoryOverflow);
|
||||
+ EXPECT_EQ(0u, program);
|
||||
}
|
||||
|
||||
// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
|
||||
286
patches/angle/cherry-pick-cafe56b591ed.patch
Normal file
286
patches/angle/cherry-pick-cafe56b591ed.patch
Normal file
@@ -0,0 +1,286 @@
|
||||
From cafe56b591edb77f041be70b58cac3a61565644a Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Fri, 23 Jun 2023 14:46:28 -0400
|
||||
Subject: [PATCH] M116: GL: Ensure all instanced attributes have a buffer with data
|
||||
|
||||
Apple OpenGL drivers sometimes crash when given an instanced draw with
|
||||
a buffer that has never been given data.
|
||||
|
||||
It's not efficient to check if the attribute is both zero-sized and
|
||||
instanced so just ensure that every time a zero-sized buffer is bound
|
||||
to an attribute, it gets initialized with some data.
|
||||
|
||||
Bug: chromium:1456243
|
||||
Change-Id: I66b7c7017843153db2df3bc50010cba765d03c5f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4642048
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 4e6124dae892690204f8e5996aeaad14f45e0a97)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4727452
|
||||
---
|
||||
|
||||
diff --git a/include/platform/FeaturesGL_autogen.h b/include/platform/FeaturesGL_autogen.h
|
||||
index aa0565c..2f6e094 100644
|
||||
--- a/include/platform/FeaturesGL_autogen.h
|
||||
+++ b/include/platform/FeaturesGL_autogen.h
|
||||
@@ -501,6 +501,12 @@
|
||||
"supportsShaderPixelLocalStorageEXT", FeatureCategory::OpenGLFeatures,
|
||||
"Backend GL context supports EXT_shader_pixel_local_storage extension", &members,
|
||||
"http://anglebug.com/7279"};
|
||||
+
|
||||
+ FeatureInfo ensureNonEmptyBufferIsBoundForDraw = {
|
||||
+ "ensureNonEmptyBufferIsBoundForDraw", FeatureCategory::OpenGLFeatures,
|
||||
+ "Apple OpenGL drivers crash when drawing with a zero-sized buffer bound using a non-zero "
|
||||
+ "divisor.",
|
||||
+ &members, "http://crbug.com/1456243"};
|
||||
};
|
||||
|
||||
inline FeaturesGL::FeaturesGL() = default;
|
||||
diff --git a/include/platform/gl_features.json b/include/platform/gl_features.json
|
||||
index 032f29a..b358cea 100644
|
||||
--- a/include/platform/gl_features.json
|
||||
+++ b/include/platform/gl_features.json
|
||||
@@ -699,6 +699,14 @@
|
||||
"Backend GL context supports EXT_shader_pixel_local_storage extension"
|
||||
],
|
||||
"issue": "http://anglebug.com/7279"
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "ensure_non_empty_buffer_is_bound_for_draw",
|
||||
+ "category": "Features",
|
||||
+ "description": [
|
||||
+ "Apple OpenGL drivers crash when drawing with a zero-sized buffer bound using a non-zero divisor."
|
||||
+ ],
|
||||
+ "issue": "http://crbug.com/1456243"
|
||||
}
|
||||
]
|
||||
}
|
||||
diff --git a/scripts/code_generation_hashes/ANGLE_features.json b/scripts/code_generation_hashes/ANGLE_features.json
|
||||
index d4576c2..503001c 100644
|
||||
--- a/scripts/code_generation_hashes/ANGLE_features.json
|
||||
+++ b/scripts/code_generation_hashes/ANGLE_features.json
|
||||
@@ -2,7 +2,7 @@
|
||||
"include/platform/FeaturesD3D_autogen.h":
|
||||
"9923fb44d0a6f31948d0c8f46ee1d9e2",
|
||||
"include/platform/FeaturesGL_autogen.h":
|
||||
- "a795a806d71b0e6d1f9e6d95c6e11971",
|
||||
+ "fef16ab3946346a2a7d5b76bb39471a4",
|
||||
"include/platform/FeaturesMtl_autogen.h":
|
||||
"407426c8874de9295482ace9c94bd812",
|
||||
"include/platform/FeaturesVk_autogen.h":
|
||||
@@ -16,13 +16,13 @@
|
||||
"include/platform/gen_features.py":
|
||||
"062989f7a8f3ff3b383f98fc8908dc33",
|
||||
"include/platform/gl_features.json":
|
||||
- "3335055a70e35ebb7bf74c6d7c58897b",
|
||||
+ "c9aead89696e7fd0c8bfe5c5ca85ca63",
|
||||
"include/platform/mtl_features.json":
|
||||
"c66d170e7a8eb3448030f4c423ed0133",
|
||||
"include/platform/vk_features.json":
|
||||
"416bbb28b9fa1a3c4ef141f243c0a9e6",
|
||||
"util/angle_features_autogen.cpp":
|
||||
- "73169f63c755192c3b4bd27d6f4096ca",
|
||||
+ "288daaec490eb816883d744f108d74c9",
|
||||
"util/angle_features_autogen.h":
|
||||
- "7aa8120eb8f8fd335946b8c27074745d"
|
||||
+ "daf25d3e4ffea143d1c082416513f7e7"
|
||||
}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/libANGLE/renderer/gl/BufferGL.cpp b/src/libANGLE/renderer/gl/BufferGL.cpp
|
||||
index c99fd5d..9651838 100644
|
||||
--- a/src/libANGLE/renderer/gl/BufferGL.cpp
|
||||
+++ b/src/libANGLE/renderer/gl/BufferGL.cpp
|
||||
@@ -296,6 +296,11 @@
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
+size_t BufferGL::getBufferSize() const
|
||||
+{
|
||||
+ return mBufferSize;
|
||||
+}
|
||||
+
|
||||
GLuint BufferGL::getBufferID() const
|
||||
{
|
||||
return mBufferID;
|
||||
diff --git a/src/libANGLE/renderer/gl/BufferGL.h b/src/libANGLE/renderer/gl/BufferGL.h
|
||||
index 7b57594..fe9138e 100644
|
||||
--- a/src/libANGLE/renderer/gl/BufferGL.h
|
||||
+++ b/src/libANGLE/renderer/gl/BufferGL.h
|
||||
@@ -56,6 +56,7 @@
|
||||
bool primitiveRestartEnabled,
|
||||
gl::IndexRange *outRange) override;
|
||||
|
||||
+ size_t getBufferSize() const;
|
||||
GLuint getBufferID() const;
|
||||
|
||||
private:
|
||||
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
|
||||
index dc981de..fda9099 100644
|
||||
--- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp
|
||||
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
|
||||
@@ -646,6 +646,7 @@
|
||||
|
||||
angle::Result VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attribIndex)
|
||||
{
|
||||
+ const angle::FeaturesGL &features = GetFeaturesGL(context);
|
||||
|
||||
const VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);
|
||||
|
||||
@@ -687,8 +688,16 @@
|
||||
// is not NULL.
|
||||
|
||||
StateManagerGL *stateManager = GetStateManagerGL(context);
|
||||
- GLuint bufferId = GetNativeBufferID(arrayBuffer);
|
||||
+ BufferGL *bufferGL = GetImplAs<BufferGL>(arrayBuffer);
|
||||
+ GLuint bufferId = bufferGL->getBufferID();
|
||||
stateManager->bindBuffer(gl::BufferBinding::Array, bufferId);
|
||||
+ if (features.ensureNonEmptyBufferIsBoundForDraw.enabled && bufferGL->getBufferSize() == 0)
|
||||
+ {
|
||||
+ constexpr uint32_t data = 0;
|
||||
+ ANGLE_TRY(bufferGL->setData(context, gl::BufferBinding::Array, &data, sizeof(data),
|
||||
+ gl::BufferUsage::StaticDraw));
|
||||
+ ASSERT(bufferGL->getBufferSize() > 0);
|
||||
+ }
|
||||
ANGLE_TRY(callVertexAttribPointer(context, static_cast<GLuint>(attribIndex), attrib,
|
||||
binding.getStride(), binding.getOffset()));
|
||||
|
||||
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
|
||||
index 6911247..ab2a608 100644
|
||||
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
|
||||
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
|
||||
@@ -2465,6 +2465,9 @@
|
||||
// EXT_shader_pixel_local_storage
|
||||
ANGLE_FEATURE_CONDITION(features, supportsShaderPixelLocalStorageEXT,
|
||||
functions->hasGLESExtension("GL_EXT_shader_pixel_local_storage"));
|
||||
+
|
||||
+ // http://crbug.com/1456243
|
||||
+ ANGLE_FEATURE_CONDITION(features, ensureNonEmptyBufferIsBoundForDraw, IsApple() || IsAndroid());
|
||||
}
|
||||
|
||||
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
|
||||
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
|
||||
index 59ec7c2..44ff3e4 100644
|
||||
--- a/src/tests/angle_end2end_tests_expectations.txt
|
||||
+++ b/src/tests/angle_end2end_tests_expectations.txt
|
||||
@@ -380,6 +380,7 @@
|
||||
7294 WIN D3D11 : StateChangeTestES3.StencilWriteMask/* = SKIP
|
||||
7316 WIN D3D11 : StateChangeTestES3.StencilTestAndFunc/* = SKIP
|
||||
7329 WIN D3D11 : StateChangeTestES3.PrimitiveRestart/* = SKIP
|
||||
+1456243 WIN D3D11 : WebGL2CompatibilityTest.DrawWithZeroSizedBuffer/* = SKIP
|
||||
|
||||
// Android
|
||||
6095 ANDROID GLES : GLSLTest_ES3.InitGlobalComplexConstant/* = SKIP
|
||||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
index 7dc56cd..bd7ecd1 100644
|
||||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
@@ -1632,10 +1632,10 @@
|
||||
|
||||
constexpr GLuint kMaxIntAsGLuint = static_cast<GLuint>(std::numeric_limits<GLint>::max());
|
||||
constexpr GLuint kIndexData[] = {
|
||||
- kMaxIntAsGLuint,
|
||||
- kMaxIntAsGLuint + 1,
|
||||
- kMaxIntAsGLuint + 2,
|
||||
- kMaxIntAsGLuint + 3,
|
||||
+ kMaxIntAsGLuint,
|
||||
+ kMaxIntAsGLuint + 1,
|
||||
+ kMaxIntAsGLuint + 2,
|
||||
+ kMaxIntAsGLuint + 3,
|
||||
};
|
||||
|
||||
GLBuffer indexBuffer;
|
||||
@@ -3687,8 +3687,8 @@
|
||||
|
||||
constexpr float readPixelsData[] = {-5000.0f, 0.0f, 0.0f, 1.0f};
|
||||
const GLushort textureData[] = {
|
||||
- gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
- gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
+ gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
+ gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
|
||||
for (auto extension : FloatingPointTextureExtensions)
|
||||
{
|
||||
@@ -3748,8 +3748,8 @@
|
||||
|
||||
constexpr float readPixelsData[] = {7108.0f, -10.0f, 0.0f, 1.0f};
|
||||
const GLushort textureData[] = {
|
||||
- gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
- gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
+ gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
+ gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
|
||||
for (auto extension : FloatingPointTextureExtensions)
|
||||
{
|
||||
@@ -3811,8 +3811,8 @@
|
||||
|
||||
constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, 1.0f};
|
||||
const GLushort textureData[] = {
|
||||
- gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
- gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
+ gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
+ gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
|
||||
for (auto extension : FloatingPointTextureExtensions)
|
||||
{
|
||||
@@ -3874,8 +3874,8 @@
|
||||
|
||||
constexpr float readPixelsData[] = {7000.0f, 100.0f, 33.0f, -1.0f};
|
||||
const GLushort textureData[] = {
|
||||
- gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
- gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
+ gl::float32ToFloat16(readPixelsData[0]), gl::float32ToFloat16(readPixelsData[1]),
|
||||
+ gl::float32ToFloat16(readPixelsData[2]), gl::float32ToFloat16(readPixelsData[3])};
|
||||
|
||||
for (auto extension : FloatingPointTextureExtensions)
|
||||
{
|
||||
@@ -5803,6 +5803,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
+// Test for a mishandling of instanced vertex attributes with zero-sized buffers bound on Apple
|
||||
+// OpenGL drivers.
|
||||
+TEST_P(WebGL2CompatibilityTest, DrawWithZeroSizedBuffer)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
|
||||
+ glUseProgram(program);
|
||||
+
|
||||
+ GLBuffer buffer;
|
||||
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
+
|
||||
+ GLint posLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
|
||||
+ glEnableVertexAttribArray(posLocation);
|
||||
+
|
||||
+ glVertexAttribDivisor(posLocation, 1);
|
||||
+ glVertexAttribPointer(posLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 9,
|
||||
+ reinterpret_cast<void *>(0x41424344));
|
||||
+
|
||||
+ glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
+}
|
||||
+
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(WebGLCompatibilityTest);
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2CompatibilityTest);
|
||||
diff --git a/util/angle_features_autogen.cpp b/util/angle_features_autogen.cpp
|
||||
index adb9610..a060dd2 100644
|
||||
--- a/util/angle_features_autogen.cpp
|
||||
+++ b/util/angle_features_autogen.cpp
|
||||
@@ -118,6 +118,7 @@
|
||||
{Feature::EnablePrecisionQualifiers, "enablePrecisionQualifiers"},
|
||||
{Feature::EnablePreRotateSurfaces, "enablePreRotateSurfaces"},
|
||||
{Feature::EnableProgramBinaryForCapture, "enableProgramBinaryForCapture"},
|
||||
+ {Feature::EnsureNonEmptyBufferIsBoundForDraw, "ensureNonEmptyBufferIsBoundForDraw"},
|
||||
{Feature::ExpandIntegerPowExpressions, "expandIntegerPowExpressions"},
|
||||
{Feature::ExplicitlyEnablePerSampleShading, "explicitlyEnablePerSampleShading"},
|
||||
{Feature::ExposeNonConformantExtensionsAndVersions, "exposeNonConformantExtensionsAndVersions"},
|
||||
diff --git a/util/angle_features_autogen.h b/util/angle_features_autogen.h
|
||||
index 3d8c47f..4064425 100644
|
||||
--- a/util/angle_features_autogen.h
|
||||
+++ b/util/angle_features_autogen.h
|
||||
@@ -112,6 +112,7 @@
|
||||
EnablePrecisionQualifiers,
|
||||
EnablePreRotateSurfaces,
|
||||
EnableProgramBinaryForCapture,
|
||||
+ EnsureNonEmptyBufferIsBoundForDraw,
|
||||
ExpandIntegerPowExpressions,
|
||||
ExplicitlyEnablePerSampleShading,
|
||||
ExposeNonConformantExtensionsAndVersions,
|
||||
@@ -79,7 +79,7 @@ index 1cada05806cb35a82822507f708d43979d97de61..f8e063397b161b7501308945a7df9fb8
|
||||
if (World().IsMainWorld()) {
|
||||
probe::DidCreateMainWorldContext(GetFrame());
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
index fb229297df448dbe48e5b0ef2978bce2a8affc83..892d971c749b5bf7499c2fc246bc9d5fe5b63b79 100644
|
||||
index 62e611ec3ac95eac88d4665d2640429e9d833594..7bf646d6cd8eaf29267b6136de0952e2545ec503 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
@@ -319,6 +319,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
@@ -92,7 +92,7 @@ index fb229297df448dbe48e5b0ef2978bce2a8affc83..892d971c749b5bf7499c2fc246bc9d5f
|
||||
int32_t world_id) = 0;
|
||||
virtual bool AllowScriptExtensions() = 0;
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
index fa8c26e31341b2b53879a8760ad8314a569374c6..76ba9e3761d85acdaeeb017f52e24efc3d40e9b7 100644
|
||||
index dbf7fd73a855f7d45eeeeff17582696aac66ff0d..9b489f661f524f380523e38518345e9b22eb8dec 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
@@ -283,6 +283,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
|
||||
@@ -110,7 +110,7 @@ index fa8c26e31341b2b53879a8760ad8314a569374c6..76ba9e3761d85acdaeeb017f52e24efc
|
||||
v8::Local<v8::Context> context,
|
||||
int32_t world_id) {
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
index 9f6a7e8337a4ade6b902d36919bee58f5e461790..9a73f4ceb6111b7e8bcb607b4e8eb96ebbfb0d42 100644
|
||||
index 28e1c00e05e74d5a79f32897e57a854ff14ce7a9..1cd704b1bb53eaf226d1c72c97e3f765a4b1f10e 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
@@ -84,6 +84,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
|
||||
@@ -123,10 +123,10 @@ index 9f6a7e8337a4ade6b902d36919bee58f5e461790..9a73f4ceb6111b7e8bcb607b4e8eb96e
|
||||
int32_t world_id) override;
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
index 6b695ab181bc7e8a8b6ecb48ca56145ddc63d6e8..4955c7246498139a20be290a48eee234de44530e 100644
|
||||
index 1934ca82e3e26e0f5c4f2f7b417df6bcd6e66abf..1277b858f2d5b4b0a0dd1c97282eff0d763cdc2b 100644
|
||||
--- a/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
@@ -401,6 +401,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
@@ -403,6 +403,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
|
||||
void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) override {}
|
||||
|
||||
@@ -33,10 +33,10 @@ index 884bccba58c66861b43b3b50a7535cba543302e2..82e7bf534aa6b998cee8df53be3ca7db
|
||||
"//base",
|
||||
"//build:branding_buildflags",
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index 93184ddac697404d22156015e039b710813ce3a5..0a92a4dac5ce0b2d95ae7f45b76bf45e83420d6b 100644
|
||||
index 01194da83fe3f14c5f84671a186ed01fdbd2dc1e..191766f5e9cf2a0f3c43a6abb2d7e0139d1b666c 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -4615,7 +4615,7 @@ static_library("browser") {
|
||||
@@ -4618,7 +4618,7 @@ static_library("browser") {
|
||||
|
||||
# On Windows, the hashes are embedded in //chrome:chrome_initial rather
|
||||
# than here in :chrome_dll.
|
||||
@@ -46,10 +46,10 @@ index 93184ddac697404d22156015e039b710813ce3a5..0a92a4dac5ce0b2d95ae7f45b76bf45e
|
||||
sources += [ "certificate_viewer_stub.cc" ]
|
||||
}
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index a6b47cee220af2083461bf8c25e9b37defae9c1f..ac514a50b6c7d19acf94da04d2ead46275b7d105 100644
|
||||
index fcd0db1b08e08663e59d1426fb888f5b8d7cf3f5..9cccf671e8f5a804365c68dfdc1aade0de28d1c0 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -6587,7 +6587,6 @@ test("unit_tests") {
|
||||
@@ -6588,7 +6588,6 @@ test("unit_tests") {
|
||||
|
||||
deps += [
|
||||
"//chrome:other_version",
|
||||
@@ -57,7 +57,7 @@ index a6b47cee220af2083461bf8c25e9b37defae9c1f..ac514a50b6c7d19acf94da04d2ead462
|
||||
"//chrome//services/util_win:unit_tests",
|
||||
"//chrome/app:chrome_dll_resources",
|
||||
"//chrome/app:win_unit_tests",
|
||||
@@ -6613,6 +6612,10 @@ test("unit_tests") {
|
||||
@@ -6614,6 +6613,10 @@ test("unit_tests") {
|
||||
"//ui/resources",
|
||||
]
|
||||
|
||||
@@ -68,7 +68,7 @@ index a6b47cee220af2083461bf8c25e9b37defae9c1f..ac514a50b6c7d19acf94da04d2ead462
|
||||
ldflags = [
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
@@ -7539,7 +7542,6 @@ test("unit_tests") {
|
||||
@@ -7541,7 +7544,6 @@ test("unit_tests") {
|
||||
}
|
||||
|
||||
deps += [
|
||||
@@ -76,7 +76,7 @@ index a6b47cee220af2083461bf8c25e9b37defae9c1f..ac514a50b6c7d19acf94da04d2ead462
|
||||
"//chrome/browser/apps:icon_standardizer",
|
||||
"//chrome/browser/apps/app_service",
|
||||
"//chrome/browser/apps/app_service:test_support",
|
||||
@@ -7626,6 +7628,10 @@ test("unit_tests") {
|
||||
@@ -7628,6 +7630,10 @@ test("unit_tests") {
|
||||
"//ui/webui/resources/js/browser_command:mojo_bindings",
|
||||
]
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ index 65714a5dca013794527640645d8eb2ce36049ac6..b2df50b4cd64816ddf9c5b7e222c47b6
|
||||
|
||||
public_deps = [
|
||||
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
|
||||
index dd42e72891b3cc5f32d8b69dba7cb9230efd033a..c8c6770a2382904edbffba0682b36747595f8754 100644
|
||||
index 027fa679e34298ec627282796355b6284876520f..14fc5a7c899145872d0df98d7eab019a320da984 100644
|
||||
--- a/content/test/BUILD.gn
|
||||
+++ b/content/test/BUILD.gn
|
||||
@@ -475,6 +475,7 @@ static_library("test_support") {
|
||||
|
||||
@@ -9,7 +9,7 @@ potentially prevent a window from being created.
|
||||
TODO(loc): this patch is currently broken.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 9f7b9d04cefd48539d8c62cb74c3aac084e116e6..0faa1fba5cea7e301b7497aca5838f761d9e02bd 100644
|
||||
index 23f8f5f1042cbc85e630d57e26624963d9cbc71c..544f2bcf906ad40769e5961d97211fbba549d03a 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -7836,6 +7836,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -21,10 +21,10 @@ index 9f7b9d04cefd48539d8c62cb74c3aac084e116e6..0faa1fba5cea7e301b7497aca5838f76
|
||||
&no_javascript_access);
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 4efa2e72fdc340624ce888e93ffd4359e20c0973..5018e17e0f56efd54529ef3e9ae1de5e223aed68 100644
|
||||
index c9b13be94c531a528cdbc8046d80d43fe704ef36..4b53b6060e6d7aae818a3d81faa0a1ae673ea59e 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -4206,6 +4206,12 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -4212,6 +4212,12 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
|
||||
auto* new_contents_impl = new_contents.get();
|
||||
|
||||
@@ -37,7 +37,7 @@ index 4efa2e72fdc340624ce888e93ffd4359e20c0973..5018e17e0f56efd54529ef3e9ae1de5e
|
||||
// If the new frame has a name, make sure any SiteInstances that can find
|
||||
// this named frame have proxies for it. Must be called after
|
||||
// SetSessionStorageNamespace, since this calls CreateRenderView, which uses
|
||||
@@ -4247,12 +4253,6 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -4253,12 +4259,6 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
AddWebContentsDestructionObserver(new_contents_impl);
|
||||
}
|
||||
|
||||
|
||||
@@ -218,10 +218,10 @@ index 4e32d708ecf4afd3913d86ec1602ef2dc9a60998..1dd2f50fba1387b5eeb554dd540957d7
|
||||
void AddNewContents(content::WebContents* source,
|
||||
std::unique_ptr<content::WebContents> new_contents,
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 865414f0994a4e29f297532538486f780edd51d3..3a60a59497571a33bba8efa7654a32403ab99978 100644
|
||||
index d4dd0e24538b2282de207a63aef7486c30525ed9..1d1aac31f051e17d10c2f776c685dd74958cb35f 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -4113,8 +4113,7 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -4119,8 +4119,7 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
|
||||
if (delegate_ && delegate_->IsWebContentsCreationOverridden(
|
||||
source_site_instance, params.window_container_type,
|
||||
|
||||
@@ -8,7 +8,7 @@ Allow registering custom protocols to handle service worker main script fetching
|
||||
Refs https://bugs.chromium.org/p/chromium/issues/detail?id=996511
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
|
||||
index 698c94642b98b03570fef8f7a5956486eacacbdc..7983abad9a78a115dfd7b9513c6f57be2cd40811 100644
|
||||
index 6fbb7d75b9bf37371a7d40a1849c606bb17f5df8..a69b304809e09d85df62365087f01fbab6376048 100644
|
||||
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
|
||||
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
|
||||
@@ -1839,6 +1839,26 @@ ServiceWorkerContextWrapper::GetLoaderFactoryForBrowserInitiatedRequest(
|
||||
@@ -36,7 +36,7 @@ index 698c94642b98b03570fef8f7a5956486eacacbdc..7983abad9a78a115dfd7b9513c6f57be
|
||||
+ }
|
||||
+
|
||||
if (auto* config = content::WebUIConfigMap::GetInstance().GetConfig(
|
||||
browser_context(), scope_origin)) {
|
||||
browser_context(), scope)) {
|
||||
// If this is a Service Worker for a WebUI, the WebUI's URLDataSource
|
||||
@@ -1858,9 +1878,7 @@ ServiceWorkerContextWrapper::GetLoaderFactoryForBrowserInitiatedRequest(
|
||||
features::kEnableServiceWorkersForChromeScheme) &&
|
||||
|
||||
@@ -35,10 +35,10 @@ index 256f599f8ad93578a7b56697070b1d0630b04897..3c1723ed20ab6a673df7e0ebf0119c21
|
||||
// If we are likely to software composite the resource, we use sRGB because
|
||||
// software compositing is unable to perform color conversion.
|
||||
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
|
||||
index 0d966e045669ee0423d6a486fa8e619938a32de2..1e46ecc1aa8447b3fd0f4e5a66f92ca5ef148887 100644
|
||||
index 7ddbd0ac756c4374d938b422623ea21c7d5c3daf..eb76e4ba51f1ff30b094c941adf776437f7d7b42 100644
|
||||
--- a/cc/trees/layer_tree_settings.h
|
||||
+++ b/cc/trees/layer_tree_settings.h
|
||||
@@ -96,6 +96,8 @@ class CC_EXPORT LayerTreeSettings {
|
||||
@@ -104,6 +104,8 @@ class CC_EXPORT LayerTreeSettings {
|
||||
bool use_rgba_4444 = false;
|
||||
bool unpremultiply_and_dither_low_bit_depth_tiles = false;
|
||||
|
||||
@@ -148,10 +148,10 @@ index 318005b66e04ed03ce6d44931d9360c0e009cb94..0d622fddb95720141ccf8a285ace4714
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
|
||||
index 2a31606b1f5814d57ffe59026cc5735fa7cee597..272ae9f414f8d0873e30479b5bfd237c13a69dd9 100644
|
||||
index e8efcceb7aefbedb6b02bfef9defb52c6dc68f0e..8aa9f586bbe3f33b4ba433b7d177a4217ac877d7 100644
|
||||
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
|
||||
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
|
||||
@@ -25,6 +25,7 @@
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
|
||||
#include "ui/base/ui_base_features.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
@@ -159,7 +159,7 @@ index 2a31606b1f5814d57ffe59026cc5735fa7cee597..272ae9f414f8d0873e30479b5bfd237c
|
||||
#include "ui/native_theme/native_theme_features.h"
|
||||
#include "ui/native_theme/overlay_scrollbar_constants_aura.h"
|
||||
|
||||
@@ -210,6 +211,9 @@ cc::LayerTreeSettings GenerateLayerTreeSettings(
|
||||
@@ -230,6 +231,9 @@ cc::LayerTreeSettings GenerateLayerTreeSettings(
|
||||
settings.main_frame_before_activation_enabled =
|
||||
cmd.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation);
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@ index 0ab8187b0db8ae6db46d81738f653a2bc4c566f6..de3d55e85c22317f7f9375eb94d0d5d4
|
||||
|
||||
} // namespace net
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index 0ffa0ec042bd59de5d28fad53dee2b6321d64b18..a6570cb144952a1bb7eca124bb4cbb33e249ef15 100644
|
||||
index 2d823eeb8a09d4bca7a800558cd6123df8950576..0c04ff37f77f9ef1ca53339d892db6ea7a4d5aff 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -1491,6 +1491,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
@@ -1502,6 +1502,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
std::move(network_conditions));
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ index 0ffa0ec042bd59de5d28fad53dee2b6321d64b18..a6570cb144952a1bb7eca124bb4cbb33
|
||||
// This may only be called on NetworkContexts created with the constructor
|
||||
// that calls MakeURLRequestContext().
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index f10414f382b48ecc162b22d9638d948e3e719733..47d13dbe9efd501efabe096607e53cb80744cd42 100644
|
||||
index 07c516a63a391fd9eec2d2f6b9868c5da9d8f5c5..65f2c721f3d793126ead04dc812e2372b4399627 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -316,6 +316,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: fix: allow guest webcontents to enter fullscreen
|
||||
This can be upstreamed, a guest webcontents can't technically become the focused webContents. This DCHECK should allow all guest webContents to request fullscreen entrance.
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 0582143a5466afb3ba618e848ff23ffa23e5ca70..7a7f74778d0d9118d01a2dc8b916fada56a8dfaa 100644
|
||||
index 699e13391bd408aff3c862820d531c968e05743a..4ae175782ac6d7a705af0760b24843fd16ab0871 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3633,7 +3633,7 @@ void WebContentsImpl::EnterFullscreenMode(
|
||||
@@ -3639,7 +3639,7 @@ void WebContentsImpl::EnterFullscreenMode(
|
||||
OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::EnterFullscreenMode");
|
||||
DCHECK(CanEnterFullscreenMode(requesting_frame, options));
|
||||
DCHECK(requesting_frame->IsActive());
|
||||
|
||||
@@ -17,10 +17,10 @@ policy->CanCommitOriginAndUrl.
|
||||
Upstreamed at https://chromium-review.googlesource.com/c/chromium/src/+/3856266.
|
||||
|
||||
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
|
||||
index 76a53ed5fcae948a3b2e950d484ffebd1939fd6c..fdce51afdbb8759fb52bf2ae570de3e4da7dd752 100644
|
||||
index a09b5bc4973fc3abdfc02627be515f7eaf87f2c1..15eabc215f6d31450c788145f99cd1e88cce6d89 100644
|
||||
--- a/content/browser/renderer_host/navigation_request.cc
|
||||
+++ b/content/browser/renderer_host/navigation_request.cc
|
||||
@@ -7345,10 +7345,11 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
|
||||
@@ -7428,10 +7428,11 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
|
||||
if (IsForMhtmlSubframe())
|
||||
return origin_with_debug_info;
|
||||
|
||||
@@ -37,10 +37,10 @@ index 76a53ed5fcae948a3b2e950d484ffebd1939fd6c..fdce51afdbb8759fb52bf2ae570de3e4
|
||||
}
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
|
||||
index 710c6d8c0a78f5d8dce6c6e936a61979f4ee904b..7b7d71bf27cde4f2cede2baeb52f87fd49645f61 100644
|
||||
index f2a1f119815728fb8b4d2c595369f78981f2347e..2bf7e3f851abf3f5979fb5fbc0d2d829e4c90190 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.h
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.h
|
||||
@@ -2936,6 +2936,17 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
@@ -2937,6 +2937,17 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
// last committed document.
|
||||
CookieChangeListener::CookieChangeInfo GetCookieChangeInfo();
|
||||
|
||||
@@ -58,7 +58,7 @@ index 710c6d8c0a78f5d8dce6c6e936a61979f4ee904b..7b7d71bf27cde4f2cede2baeb52f87fd
|
||||
// Sets a ResourceCache in the renderer. `this` must be active and there must
|
||||
// be no pending navigation. `remote` must have the same and process
|
||||
// isolation policy.
|
||||
@@ -3313,17 +3324,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
@@ -3314,17 +3325,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
// relevant.
|
||||
void ResetWaitingState();
|
||||
|
||||
|
||||
@@ -45,10 +45,10 @@ index ed0641b888c6421b1791c086466bd9c158e9109d..3760b3823d5af3325017bb53f5b1d38e
|
||||
// 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 7a7f74778d0d9118d01a2dc8b916fada56a8dfaa..96bd0573473d9f401791125cd18cb24e76fab0db 100644
|
||||
index 4ae175782ac6d7a705af0760b24843fd16ab0871..81ea4f9b8e559d380ad4a8a9ddd9b5edca014207 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -8163,7 +8163,7 @@ void WebContentsImpl::OnFocusedElementChangedInFrame(
|
||||
@@ -8169,7 +8169,7 @@ void WebContentsImpl::OnFocusedElementChangedInFrame(
|
||||
"WebContentsImpl::OnFocusedElementChangedInFrame",
|
||||
"render_frame_host", frame);
|
||||
RenderWidgetHostViewBase* root_view =
|
||||
|
||||
@@ -98,7 +98,7 @@ index bc24bbc46d829946da255a74947dc3e5d4685dd3..c5a02b325dae7beb8ebebca49c93b8aa
|
||||
mojom::blink::WantResultOption,
|
||||
mojom::blink::PromiseResultOption);
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
index 4a40473c167290328b6c2c0e9029c3d7c073fe44..f91e9eaab57aef9c202be8342281fa7d65fcbb8b 100644
|
||||
index 57e1e45f9c8aa0dbae982ab4e921d2a785841c22..e2cdf0c00cf165cbd8f7f2279ddffcd2b71c0fda 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
@@ -935,6 +935,7 @@ void LocalFrameMojoHandler::JavaScriptExecuteRequestInIsolatedWorld(
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: frame_host_manager.patch
|
||||
Allows embedder to intercept site instances created by chromium.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
index cd9f74588e69a09e875807fea8680d584eb70ab4..71f5203ebd239f71f528e3c067786e5817b9c8ac 100644
|
||||
index c63f0f796dea518d04a85e7aa29d6c97bfc8c6dc..835e04d1223f185380c3cb5f9f50b7179f982a1c 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
@@ -4002,6 +4002,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
|
||||
@@ -4046,6 +4046,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
|
||||
request->ResetStateForSiteInstanceChange();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ This adds a callback from the network service that's used to implement
|
||||
session.setCertificateVerifyCallback.
|
||||
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index d553d31e90ca7f3ea9a540d0eda7aaa6801f007b..0ffa0ec042bd59de5d28fad53dee2b6321d64b18 100644
|
||||
index 4156311dfec3f86f95e3a0b56190090e4de9a8a0..2d823eeb8a09d4bca7a800558cd6123df8950576 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -142,6 +142,11 @@
|
||||
@@ -122,7 +122,7 @@ index d553d31e90ca7f3ea9a540d0eda7aaa6801f007b..0ffa0ec042bd59de5d28fad53dee2b63
|
||||
constexpr uint32_t NetworkContext::kMaxOutstandingRequestsPerProcess;
|
||||
|
||||
NetworkContext::PendingCertVerify::PendingCertVerify() = default;
|
||||
@@ -756,6 +854,13 @@ void NetworkContext::SetClient(
|
||||
@@ -764,6 +862,13 @@ void NetworkContext::SetClient(
|
||||
client_.Bind(std::move(client));
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ index d553d31e90ca7f3ea9a540d0eda7aaa6801f007b..0ffa0ec042bd59de5d28fad53dee2b63
|
||||
void NetworkContext::CreateURLLoaderFactory(
|
||||
mojo::PendingReceiver<mojom::URLLoaderFactory> receiver,
|
||||
mojom::URLLoaderFactoryParamsPtr params) {
|
||||
@@ -2289,6 +2394,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
|
||||
@@ -2300,6 +2405,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
|
||||
std::move(cert_verifier));
|
||||
cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_.get());
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
@@ -147,7 +147,7 @@ index d553d31e90ca7f3ea9a540d0eda7aaa6801f007b..0ffa0ec042bd59de5d28fad53dee2b63
|
||||
|
||||
builder.SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index 9cac607573e5411c6dd8c2a6309ae78c2a1784f4..f10414f382b48ecc162b22d9638d948e3e719733 100644
|
||||
index 6fe92667a76415a10fbd4756dcf58245c73752ed..07c516a63a391fd9eec2d2f6b9868c5da9d8f5c5 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -114,6 +114,7 @@ class URLMatcher;
|
||||
|
||||
@@ -44,10 +44,10 @@ index 2d705b183b1014a6f8dc89672b327d619ac52b1a..7107c17a8f36688d245b4cad5ee92dfc
|
||||
|
||||
void RenderWidgetHostImpl::ShowContextMenuAtPoint(
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 5018e17e0f56efd54529ef3e9ae1de5e223aed68..865414f0994a4e29f297532538486f780edd51d3 100644
|
||||
index 4b53b6060e6d7aae818a3d81faa0a1ae673ea59e..d4dd0e24538b2282de207a63aef7486c30525ed9 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -4798,6 +4798,11 @@ TextInputManager* WebContentsImpl::GetTextInputManager() {
|
||||
@@ -4804,6 +4804,11 @@ TextInputManager* WebContentsImpl::GetTextInputManager() {
|
||||
return text_input_manager_.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ is needed for OSR.
|
||||
Originally landed in https://github.com/electron/libchromiumcontent/pull/226.
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 3a60a59497571a33bba8efa7654a32403ab99978..0582143a5466afb3ba618e848ff23ffa23e5ca70 100644
|
||||
index 1d1aac31f051e17d10c2f776c685dd74958cb35f..699e13391bd408aff3c862820d531c968e05743a 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3242,6 +3242,13 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
|
||||
@@ -3248,6 +3248,13 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
|
||||
params.main_frame_name, GetOpener(), primary_main_frame_policy,
|
||||
base::UnguessableToken::Create());
|
||||
|
||||
@@ -26,7 +26,7 @@ index 3a60a59497571a33bba8efa7654a32403ab99978..0582143a5466afb3ba618e848ff23ffa
|
||||
std::unique_ptr<WebContentsViewDelegate> delegate =
|
||||
GetContentClient()->browser()->GetWebContentsViewDelegate(this);
|
||||
|
||||
@@ -3252,6 +3259,7 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
|
||||
@@ -3258,6 +3265,7 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
|
||||
view_ = CreateWebContentsView(this, std::move(delegate),
|
||||
&render_view_host_delegate_view_);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ Note that we also need to manually update embedder's
|
||||
`api::WebContents::IsFullscreenForTabOrPending` value.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 0faa1fba5cea7e301b7497aca5838f761d9e02bd..b87ce268fd12e7bcedd0739548a14d6c6aedbc1d 100644
|
||||
index 544f2bcf906ad40769e5961d97211fbba549d03a..2c5a63a85ba37573182ab9b8731f70948c2cc0e6 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -7053,6 +7053,17 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||
|
||||
@@ -37,3 +37,4 @@ chore_remove_--no-harmony-atomics_related_code.patch
|
||||
fix_account_for_createexternalizablestring_v8_global.patch
|
||||
fix_wunreachable-code_warning_in_ares_init_rand_engine.patch
|
||||
fix_do_not_resolve_electron_entrypoints.patch
|
||||
dns_expose_getdefaultresultorder.patch
|
||||
|
||||
141
patches/node/dns_expose_getdefaultresultorder.patch
Normal file
141
patches/node/dns_expose_getdefaultresultorder.patch
Normal file
@@ -0,0 +1,141 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: btea <2356281422@qq.com>
|
||||
Date: Wed, 26 Apr 2023 16:56:04 +0800
|
||||
Subject: dns: expose getDefaultResultOrder
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/46973
|
||||
Fixes: https://github.com/nodejs/node/issues/46919
|
||||
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
||||
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
|
||||
|
||||
diff --git a/doc/api/dns.md b/doc/api/dns.md
|
||||
index 59a56c7d1c2aa87b4786c5b6397978b195af1f83..2bb997bb0a2b4ebdbb9ae5625762e8c3184ace8d 100644
|
||||
--- a/doc/api/dns.md
|
||||
+++ b/doc/api/dns.md
|
||||
@@ -792,6 +792,18 @@ priority than [`--dns-result-order`][]. When using [worker threads][],
|
||||
[`dns.setDefaultResultOrder()`][] from the main thread won't affect the default
|
||||
dns orders in workers.
|
||||
|
||||
+## `dns.getDefaultResultOrder()`
|
||||
+
|
||||
+<!-- YAML
|
||||
+added: REPLACEME
|
||||
+-->
|
||||
+
|
||||
+Get the default value for `verbatim` in [`dns.lookup()`][] and
|
||||
+[`dnsPromises.lookup()`][]. The value could be:
|
||||
+
|
||||
+* `ipv4first`: for `verbatim` defaulting to `false`.
|
||||
+* `verbatim`: for `verbatim` defaulting to `true`.
|
||||
+
|
||||
## `dns.setServers(servers)`
|
||||
|
||||
<!-- YAML
|
||||
@@ -1351,6 +1363,14 @@ higher priority than [`--dns-result-order`][]. When using [worker threads][],
|
||||
[`dnsPromises.setDefaultResultOrder()`][] from the main thread won't affect the
|
||||
default dns orders in workers.
|
||||
|
||||
+### `dnsPromises.getDefaultResultOrder()`
|
||||
+
|
||||
+<!-- YAML
|
||||
+added: REPLACEME
|
||||
+-->
|
||||
+
|
||||
+Get the value of `dnsOrder`.
|
||||
+
|
||||
### `dnsPromises.setServers(servers)`
|
||||
|
||||
<!-- YAML
|
||||
diff --git a/lib/dns.js b/lib/dns.js
|
||||
index c0e6a3332e4d21d85279955ea0514548cc4fd171..ae0e14bab3097d7170d47adedf4fff8ca8871c93 100644
|
||||
--- a/lib/dns.js
|
||||
+++ b/lib/dns.js
|
||||
@@ -38,6 +38,7 @@ const {
|
||||
validateHints,
|
||||
emitInvalidHostnameWarning,
|
||||
getDefaultVerbatim,
|
||||
+ getDefaultResultOrder,
|
||||
setDefaultResultOrder,
|
||||
errorCodes: dnsErrorCodes,
|
||||
} = require('internal/dns/utils');
|
||||
@@ -305,6 +306,7 @@ module.exports = {
|
||||
lookupService,
|
||||
|
||||
Resolver,
|
||||
+ getDefaultResultOrder,
|
||||
setDefaultResultOrder,
|
||||
setServers: defaultResolverSetServers,
|
||||
|
||||
diff --git a/lib/internal/dns/promises.js b/lib/internal/dns/promises.js
|
||||
index 494c7ecb242c7b5f14ef136c2caf07711c11f9a5..df41d1267ef4215a44d5119afb01dbbb1211a2c3 100644
|
||||
--- a/lib/internal/dns/promises.js
|
||||
+++ b/lib/internal/dns/promises.js
|
||||
@@ -14,6 +14,7 @@ const {
|
||||
emitInvalidHostnameWarning,
|
||||
getDefaultVerbatim,
|
||||
errorCodes: dnsErrorCodes,
|
||||
+ getDefaultResultOrder,
|
||||
setDefaultResultOrder,
|
||||
setDefaultResolver,
|
||||
} = require('internal/dns/utils');
|
||||
@@ -335,6 +336,7 @@ module.exports = {
|
||||
lookup,
|
||||
lookupService,
|
||||
Resolver,
|
||||
+ getDefaultResultOrder,
|
||||
setDefaultResultOrder,
|
||||
setServers: defaultResolverSetServers,
|
||||
|
||||
diff --git a/lib/internal/dns/utils.js b/lib/internal/dns/utils.js
|
||||
index e2b96011df94f20874aa2a39a7daf29bd8efa85e..56b2b3930b2f6e928eae8b9ab8047a08d6083441 100644
|
||||
--- a/lib/internal/dns/utils.js
|
||||
+++ b/lib/internal/dns/utils.js
|
||||
@@ -283,6 +283,10 @@ function setDefaultResultOrder(value) {
|
||||
dnsOrder = value;
|
||||
}
|
||||
|
||||
+function getDefaultResultOrder() {
|
||||
+ return dnsOrder;
|
||||
+}
|
||||
+
|
||||
function createResolverClass(resolver) {
|
||||
const resolveMap = ObjectCreate(null);
|
||||
|
||||
@@ -345,6 +349,7 @@ module.exports = {
|
||||
validateTries,
|
||||
emitInvalidHostnameWarning,
|
||||
getDefaultVerbatim,
|
||||
+ getDefaultResultOrder,
|
||||
setDefaultResultOrder,
|
||||
errorCodes,
|
||||
createResolverClass,
|
||||
diff --git a/test/internet/test-dns-getDefaultResultOrder.js b/test/internet/test-dns-getDefaultResultOrder.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ae176f1264508b847ae5dd18f2593d607b2f1a98
|
||||
--- /dev/null
|
||||
+++ b/test/internet/test-dns-getDefaultResultOrder.js
|
||||
@@ -0,0 +1,24 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+
|
||||
+const assert = require('assert');
|
||||
+const dns = require('dns');
|
||||
+
|
||||
+dns.setDefaultResultOrder('ipv4first');
|
||||
+let dnsOrder = dns.getDefaultResultOrder();
|
||||
+assert.ok(dnsOrder === 'ipv4first');
|
||||
+dns.setDefaultResultOrder('verbatim');
|
||||
+dnsOrder = dns.getDefaultResultOrder();
|
||||
+assert.ok(dnsOrder === 'verbatim');
|
||||
+
|
||||
+{
|
||||
+ (async function() {
|
||||
+ const result = await dns.promises.lookup('localhost');
|
||||
+ const result1 = await dns.promises.lookup('localhost', { verbatim: true });
|
||||
+ assert.ok(result !== undefined);
|
||||
+ assert.ok(result1 !== undefined);
|
||||
+ assert.ok(result.address === result1.address);
|
||||
+ assert.ok(result.family === result1.family);
|
||||
+ })().then(common.mustCall());
|
||||
+}
|
||||
@@ -6,19 +6,42 @@ Subject: fix: do not resolve electron entrypoints
|
||||
This wastes fs cycles and can result in strange behavior if this path actually exists on disk
|
||||
|
||||
diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js
|
||||
index 5a50d5d6afab6e6648f72a1c0efa1df4cd80bcd9..0be45309028b00a6957ee473322a9452a7fa7d67 100644
|
||||
index 5a50d5d6afab6e6648f72a1c0efa1df4cd80bcd9..ebc9999358ccf16689dc02322eb1aeb86355f39b 100644
|
||||
--- a/lib/internal/modules/run_main.js
|
||||
+++ b/lib/internal/modules/run_main.js
|
||||
@@ -13,6 +13,12 @@ const {
|
||||
@@ -3,6 +3,7 @@
|
||||
const {
|
||||
ObjectCreate,
|
||||
StringPrototypeEndsWith,
|
||||
+ StringPrototypeStartsWith,
|
||||
} = primordials;
|
||||
const CJSLoader = require('internal/modules/cjs/loader');
|
||||
const { Module, toRealPath, readPackageScope } = CJSLoader;
|
||||
@@ -13,6 +14,13 @@ const {
|
||||
} = require('internal/modules/esm/handle_process_exit');
|
||||
|
||||
function resolveMainPath(main) {
|
||||
+ // For built-in modules used as the main entry point we _never_
|
||||
+ // want to waste cycles resolving them to file paths on disk
|
||||
+ // that actually might exist
|
||||
+ if (typeof main === 'string' && main.startsWith('electron/js2c')) {
|
||||
+ if (typeof main === 'string' && StringPrototypeStartsWith(main, 'electron/js2c')) {
|
||||
+ return main;
|
||||
+ }
|
||||
+
|
||||
// Note extension resolution for the main entry point can be deprecated in a
|
||||
// future major.
|
||||
// Module._findPath is monkey-patchable here.
|
||||
@@ -28,6 +36,13 @@ function resolveMainPath(main) {
|
||||
}
|
||||
|
||||
function shouldUseESMLoader(mainPath) {
|
||||
+ // For built-in modules used as the main entry point we _never_
|
||||
+ // want to waste cycles resolving them to file paths on disk
|
||||
+ // that actually might exist
|
||||
+ if (typeof mainPath === 'string' && StringPrototypeStartsWith(mainPath, 'electron/js2c')) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* @type {string[]} userLoaders A list of custom loaders registered by the user
|
||||
* (or an empty list when none have been registered).
|
||||
|
||||
@@ -2,3 +2,4 @@ fix_fallback_to_x11_capturer_on_wayland.patch
|
||||
cherry-pick-0e9556a90cec.patch
|
||||
fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch
|
||||
pipewire_capturer_increase_buffer_size_to_avoid_buffer_overflow.patch
|
||||
prevent_sdp_munging_of_duplicate_ssrcs.patch
|
||||
|
||||
51
patches/webrtc/prevent_sdp_munging_of_duplicate_ssrcs.patch
Normal file
51
patches/webrtc/prevent_sdp_munging_of_duplicate_ssrcs.patch
Normal file
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: VerteDinde <vertedinde@electronjs.org>
|
||||
Date: Tue, 15 Aug 2023 19:03:11 -0700
|
||||
Subject: Prevent SDP munging of duplicate SSRCs
|
||||
|
||||
BUG=chromium:1459124
|
||||
|
||||
Change-Id: Ifa901955b79dc9ff40d198bc367e89a8a535c3e2
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/311802
|
||||
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
|
||||
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
|
||||
Reviewed-by: Florent Castelli <orphis@webrtc.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#40447}
|
||||
|
||||
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc
|
||||
index 4874444eae1406cfb61e3bc94031dd51694b1009..6f2bbdc33217fddfbd863d7abe2af67a927cdd20 100644
|
||||
--- a/pc/sdp_offer_answer.cc
|
||||
+++ b/pc/sdp_offer_answer.cc
|
||||
@@ -1760,7 +1760,7 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
|
||||
if (type == SdpType::kOffer) {
|
||||
// TODO(bugs.webrtc.org/4676) - Handle CreateChannel failure, as new local
|
||||
// description is applied. Restore back to old description.
|
||||
- RTCError error = CreateChannels(*local_description()->description());
|
||||
+ error = CreateChannels(*local_description()->description());
|
||||
if (!error.ok()) {
|
||||
RTC_LOG(LS_ERROR) << error.message() << " (" << SdpTypeToString(type)
|
||||
<< ")";
|
||||
@@ -1792,6 +1792,23 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
|
||||
// SCTP sids.
|
||||
AllocateSctpSids();
|
||||
|
||||
+ // Validate SSRCs, we do not allow duplicates.
|
||||
+ if (ConfiguredForMedia()) {
|
||||
+ std::set<uint32_t> used_ssrcs;
|
||||
+ for (const auto& content : local_description()->description()->contents()) {
|
||||
+ for (const auto& stream : content.media_description()->streams()) {
|
||||
+ for (uint32_t ssrc : stream.ssrcs) {
|
||||
+ auto result = used_ssrcs.insert(ssrc);
|
||||
+ if (!result.second) {
|
||||
+ LOG_AND_RETURN_ERROR(
|
||||
+ RTCErrorType::INVALID_PARAMETER,
|
||||
+ "Duplicate ssrc " + rtc::ToString(ssrc) + " is not allowed");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (IsUnifiedPlan()) {
|
||||
if (ConfiguredForMedia()) {
|
||||
// We must use List and not ListInternal here because
|
||||
@@ -50,10 +50,10 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Initialize Node.js cli options to pass to Node.js
|
||||
// Preparse Node.js cli options to pass to Node.js
|
||||
// See https://nodejs.org/api/cli.html#cli_options
|
||||
int SetNodeCliFlags() {
|
||||
// Options that are unilaterally disallowed
|
||||
void ExitIfContainsDisallowedFlags(const std::vector<std::string>& argv) {
|
||||
// Options that are unilaterally disallowed.
|
||||
static constexpr auto disallowed = base::MakeFixedFlatSet<base::StringPiece>({
|
||||
"--enable-fips",
|
||||
"--force-fips",
|
||||
@@ -62,40 +62,18 @@ int SetNodeCliFlags() {
|
||||
"--use-openssl-ca",
|
||||
});
|
||||
|
||||
const auto argv = base::CommandLine::ForCurrentProcess()->argv();
|
||||
std::vector<std::string> args;
|
||||
|
||||
// TODO(codebytere): We need to set the first entry in args to the
|
||||
// process name owing to src/node_options-inl.h#L286-L290 but this is
|
||||
// redundant and so should be refactored upstream.
|
||||
args.reserve(argv.size() + 1);
|
||||
args.emplace_back("electron");
|
||||
|
||||
for (const auto& arg : argv) {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
const auto& option = base::WideToUTF8(arg);
|
||||
#else
|
||||
const auto& option = arg;
|
||||
#endif
|
||||
const auto stripped = base::StringPiece(option).substr(0, option.find('='));
|
||||
if (disallowed.contains(stripped)) {
|
||||
LOG(ERROR) << "The Node.js cli flag " << stripped
|
||||
const auto key = base::StringPiece(arg).substr(0, arg.find('='));
|
||||
if (disallowed.contains(key)) {
|
||||
LOG(ERROR) << "The Node.js cli flag " << key
|
||||
<< " is not supported in Electron";
|
||||
// Node.js returns 9 from ProcessGlobalArgs for any errors encountered
|
||||
// when setting up cli flags and env vars. Since we're outlawing these
|
||||
// flags (making them errors) return 9 here for consistency.
|
||||
return 9;
|
||||
} else {
|
||||
args.push_back(option);
|
||||
// flags (making them errors) exit with the same error code for
|
||||
// consistency.
|
||||
exit(9);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> errors;
|
||||
|
||||
// Node.js itself will output parsing errors to
|
||||
// console so we don't need to handle that ourselves
|
||||
return ProcessGlobalArgs(&args, nullptr, &errors,
|
||||
node::kDisallowedInEnvironment);
|
||||
}
|
||||
|
||||
#if IS_MAS_BUILD()
|
||||
@@ -116,7 +94,11 @@ v8::Local<v8::Value> GetParameters(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
int NodeMain(int argc, char* argv[]) {
|
||||
base::CommandLine::Init(argc, argv);
|
||||
bool initialized = base::CommandLine::Init(argc, argv);
|
||||
if (!initialized) {
|
||||
LOG(ERROR) << "Failed to initialize CommandLine";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
v8_crashpad_support::SetUp();
|
||||
@@ -153,15 +135,13 @@ int NodeMain(int argc, char* argv[]) {
|
||||
// Explicitly register electron's builtin bindings.
|
||||
NodeBindings::RegisterBuiltinBindings();
|
||||
|
||||
// Parse and set Node.js cli flags.
|
||||
int flags_exit_code = SetNodeCliFlags();
|
||||
if (flags_exit_code != 0)
|
||||
exit(flags_exit_code);
|
||||
|
||||
// Hack around with the argv pointer. Used for process.title = "blah".
|
||||
argv = uv_setup_args(argc, argv);
|
||||
|
||||
// Parse Node.js cli flags and strip out disallowed options.
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
ExitIfContainsDisallowedFlags(args);
|
||||
|
||||
std::unique_ptr<node::InitializationResult> result =
|
||||
node::InitializeOncePerProcess(
|
||||
args,
|
||||
|
||||
@@ -779,8 +779,8 @@ void BaseWindow::AddBrowserView(gin::Handle<BrowserView> browser_view) {
|
||||
void BaseWindow::RemoveBrowserView(gin::Handle<BrowserView> browser_view) {
|
||||
auto iter = browser_views_.find(browser_view->ID());
|
||||
if (iter != browser_views_.end()) {
|
||||
window_->RemoveBrowserView(browser_view->view());
|
||||
window_->RemoveDraggableRegionProvider(browser_view.get());
|
||||
window_->RemoveBrowserView(browser_view->view());
|
||||
browser_view->SetOwnerWindow(nullptr);
|
||||
iter->second.Reset();
|
||||
browser_views_.erase(iter);
|
||||
|
||||
@@ -4443,6 +4443,16 @@ WebContents* WebContents::FromID(int32_t id) {
|
||||
return GetAllWebContents().Lookup(id);
|
||||
}
|
||||
|
||||
// static
|
||||
std::list<WebContents*> WebContents::GetWebContentsList() {
|
||||
std::list<WebContents*> list;
|
||||
for (auto iter = base::IDMap<WebContents*>::iterator(&GetAllWebContents());
|
||||
!iter.IsAtEnd(); iter.Advance()) {
|
||||
list.push_back(iter.GetCurrentValue());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// static
|
||||
gin::WrapperInfo WebContents::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ class WebContents : public ExclusiveAccessContext,
|
||||
// if there is no associated wrapper.
|
||||
static WebContents* From(content::WebContents* web_contents);
|
||||
static WebContents* FromID(int32_t id);
|
||||
static std::list<WebContents*> GetWebContentsList();
|
||||
|
||||
// Get the V8 wrapper of the |web_contents|, or create one if not existed.
|
||||
//
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "gin/wrappable.h"
|
||||
#include "mojo/public/cpp/bindings/connector.h"
|
||||
#include "mojo/public/cpp/bindings/message.h"
|
||||
#include "shell/common/gin_helper/cleaned_up_at_exit.h"
|
||||
#include "third_party/blink/public/common/messaging/message_port_channel.h"
|
||||
#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
|
||||
|
||||
@@ -23,7 +24,9 @@ class Handle;
|
||||
namespace electron {
|
||||
|
||||
// A non-blink version of blink::MessagePort.
|
||||
class MessagePort : public gin::Wrappable<MessagePort>, mojo::MessageReceiver {
|
||||
class MessagePort : public gin::Wrappable<MessagePort>,
|
||||
public gin_helper::CleanedUpAtExit,
|
||||
public mojo::MessageReceiver {
|
||||
public:
|
||||
~MessagePort() override;
|
||||
static gin::Handle<MessagePort> Create(v8::Isolate* isolate);
|
||||
|
||||
@@ -580,7 +580,7 @@ void ElectronBrowserContext::DisplayMediaDeviceChosen(
|
||||
blink::MediaStreamDevice video_device(request.video_type, id, name);
|
||||
video_device.display_media_info = DesktopMediaIDToDisplayMediaInformation(
|
||||
nullptr, url::Origin::Create(request.security_origin),
|
||||
content::DesktopMediaID::Parse(request.requested_video_device_id));
|
||||
content::DesktopMediaID::Parse(video_device.id));
|
||||
devices.video_device = video_device;
|
||||
} else if (result_dict.Get("video", &rfh)) {
|
||||
auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
|
||||
@@ -592,7 +592,7 @@ void ElectronBrowserContext::DisplayMediaDeviceChosen(
|
||||
base::UTF16ToUTF8(web_contents->GetTitle()));
|
||||
video_device.display_media_info = DesktopMediaIDToDisplayMediaInformation(
|
||||
web_contents, url::Origin::Create(request.security_origin),
|
||||
content::DesktopMediaID::Parse(request.requested_video_device_id));
|
||||
content::DesktopMediaID::Parse(video_device.id));
|
||||
devices.video_device = video_device;
|
||||
} else {
|
||||
gin_helper::ErrorThrower(args->isolate())
|
||||
|
||||
@@ -211,11 +211,11 @@ ElectronBrowserMainParts* ElectronBrowserMainParts::self_ = nullptr;
|
||||
|
||||
ElectronBrowserMainParts::ElectronBrowserMainParts()
|
||||
: fake_browser_process_(std::make_unique<BrowserProcessImpl>()),
|
||||
browser_(std::make_unique<Browser>()),
|
||||
node_bindings_(
|
||||
NodeBindings::Create(NodeBindings::BrowserEnvironment::kBrowser)),
|
||||
electron_bindings_(
|
||||
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())) {
|
||||
node_bindings_{
|
||||
NodeBindings::Create(NodeBindings::BrowserEnvironment::kBrowser)},
|
||||
electron_bindings_{
|
||||
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())},
|
||||
browser_{std::make_unique<Browser>()} {
|
||||
DCHECK(!self_) << "Cannot have two ElectronBrowserMainParts";
|
||||
self_ = this;
|
||||
}
|
||||
|
||||
@@ -157,11 +157,20 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {
|
||||
// Before then, we just exit() without any intermediate steps.
|
||||
absl::optional<int> exit_code_;
|
||||
|
||||
std::unique_ptr<JavascriptEnvironment> js_env_;
|
||||
std::unique_ptr<Browser> browser_;
|
||||
std::unique_ptr<NodeBindings> node_bindings_;
|
||||
|
||||
// depends-on: node_bindings_
|
||||
std::unique_ptr<ElectronBindings> electron_bindings_;
|
||||
|
||||
// depends-on: node_bindings_
|
||||
std::unique_ptr<JavascriptEnvironment> js_env_;
|
||||
|
||||
// depends-on: js_env_'s isolate
|
||||
std::unique_ptr<NodeEnvironment> node_env_;
|
||||
|
||||
// depends-on: js_env_'s isolate
|
||||
std::unique_ptr<Browser> browser_;
|
||||
|
||||
std::unique_ptr<IconManager> icon_manager_;
|
||||
std::unique_ptr<base::FieldTrialList> field_trial_list_;
|
||||
|
||||
|
||||
@@ -37,10 +37,13 @@ void ElectronRuntimeAPIDelegate::ReloadExtension(
|
||||
bool ElectronRuntimeAPIDelegate::CheckForUpdates(
|
||||
const std::string& extension_id,
|
||||
UpdateCheckCallback callback) {
|
||||
LOG(INFO) << "chrome.runtime.requestUpdateCheck is not supported in Electron";
|
||||
return false;
|
||||
}
|
||||
|
||||
void ElectronRuntimeAPIDelegate::OpenURL(const GURL& uninstall_url) {}
|
||||
void ElectronRuntimeAPIDelegate::OpenURL(const GURL& uninstall_url) {
|
||||
LOG(INFO) << "chrome.runtime.openURL is not supported in Electron";
|
||||
}
|
||||
|
||||
bool ElectronRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) {
|
||||
const char* os = update_client::UpdateQueryParams::GetOS();
|
||||
@@ -74,9 +77,6 @@ bool ElectronRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) {
|
||||
const char* nacl_arch = update_client::UpdateQueryParams::GetNaclArch();
|
||||
if (strcmp(nacl_arch, "arm") == 0) {
|
||||
info->nacl_arch = extensions::api::runtime::PlatformNaclArch::kArm;
|
||||
} else if (strcmp(nacl_arch, "arm64") == 0) {
|
||||
// Use ARM for ARM64 NaCl, as ARM64 NaCl is not available.
|
||||
info->nacl_arch = extensions::api::runtime::PlatformNaclArch::kArm;
|
||||
} else if (strcmp(nacl_arch, "x86-32") == 0) {
|
||||
info->nacl_arch = extensions::api::runtime::PlatformNaclArch::kX86_32;
|
||||
} else if (strcmp(nacl_arch, "x86-64") == 0) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/strings/pattern.h"
|
||||
#include "chrome/common/url_constants.h"
|
||||
#include "components/url_formatter/url_fixer.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
@@ -16,7 +17,9 @@
|
||||
#include "extensions/common/mojom/host_id.mojom.h"
|
||||
#include "extensions/common/permissions/permissions_data.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/browser/web_contents_zoom_controller.h"
|
||||
#include "shell/browser/window_list.h"
|
||||
#include "shell/common/extensions/api/tabs.h"
|
||||
#include "third_party/blink/public/common/page/page_zoom.h"
|
||||
#include "url/gurl.h"
|
||||
@@ -39,24 +42,40 @@ void ZoomModeToZoomSettings(WebContentsZoomController::ZoomMode zoom_mode,
|
||||
api::tabs::ZoomSettings* zoom_settings) {
|
||||
DCHECK(zoom_settings);
|
||||
switch (zoom_mode) {
|
||||
case WebContentsZoomController::ZoomMode::kDefault:
|
||||
case WebContentsZoomController::ZOOM_MODE_DEFAULT:
|
||||
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
|
||||
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN;
|
||||
break;
|
||||
case WebContentsZoomController::ZoomMode::kIsolated:
|
||||
case WebContentsZoomController::ZOOM_MODE_ISOLATED:
|
||||
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
|
||||
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
|
||||
break;
|
||||
case WebContentsZoomController::ZoomMode::kManual:
|
||||
case WebContentsZoomController::ZOOM_MODE_MANUAL:
|
||||
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_MANUAL;
|
||||
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
|
||||
break;
|
||||
case WebContentsZoomController::ZoomMode::kDisabled:
|
||||
case WebContentsZoomController::ZOOM_MODE_DISABLED:
|
||||
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_DISABLED;
|
||||
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if either |boolean| is disengaged, or if |boolean| and
|
||||
// |value| are equal. This function is used to check if a tab's parameters match
|
||||
// those of the browser.
|
||||
bool MatchesBool(const absl::optional<bool>& boolean, bool value) {
|
||||
return !boolean || *boolean == value;
|
||||
}
|
||||
|
||||
api::tabs::MutedInfo CreateMutedInfo(content::WebContents* contents) {
|
||||
DCHECK(contents);
|
||||
api::tabs::MutedInfo info;
|
||||
info.muted = contents->IsAudioMuted();
|
||||
info.reason = api::tabs::MUTED_INFO_REASON_USER;
|
||||
return info;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ExecuteCodeInTabFunction::ExecuteCodeInTabFunction() : execute_tab_id_(-1) {}
|
||||
@@ -206,6 +225,94 @@ ExtensionFunction::ResponseAction TabsReloadFunction::Run() {
|
||||
return RespondNow(NoArguments());
|
||||
}
|
||||
|
||||
ExtensionFunction::ResponseAction TabsQueryFunction::Run() {
|
||||
absl::optional<tabs::Query::Params> params =
|
||||
tabs::Query::Params::Create(args());
|
||||
EXTENSION_FUNCTION_VALIDATE(params);
|
||||
|
||||
URLPatternSet url_patterns;
|
||||
if (params->query_info.url) {
|
||||
std::vector<std::string> url_pattern_strings;
|
||||
if (params->query_info.url->as_string)
|
||||
url_pattern_strings.push_back(*params->query_info.url->as_string);
|
||||
else if (params->query_info.url->as_strings)
|
||||
url_pattern_strings.swap(*params->query_info.url->as_strings);
|
||||
// It is o.k. to use URLPattern::SCHEME_ALL here because this function does
|
||||
// not grant access to the content of the tabs, only to seeing their URLs
|
||||
// and meta data.
|
||||
std::string error;
|
||||
if (!url_patterns.Populate(url_pattern_strings, URLPattern::SCHEME_ALL,
|
||||
true, &error)) {
|
||||
return RespondNow(Error(std::move(error)));
|
||||
}
|
||||
}
|
||||
|
||||
std::string title = params->query_info.title.value_or(std::string());
|
||||
absl::optional<bool> audible = params->query_info.audible;
|
||||
absl::optional<bool> muted = params->query_info.muted;
|
||||
|
||||
base::Value::List result;
|
||||
|
||||
// Filter out webContents that don't belong to the current browser context.
|
||||
auto* bc = browser_context();
|
||||
auto all_contents = electron::api::WebContents::GetWebContentsList();
|
||||
all_contents.remove_if([&bc](electron::api::WebContents* wc) {
|
||||
return (bc != wc->web_contents()->GetBrowserContext());
|
||||
});
|
||||
|
||||
for (auto* contents : all_contents) {
|
||||
if (!contents || !contents->web_contents())
|
||||
continue;
|
||||
|
||||
auto* wc = contents->web_contents();
|
||||
|
||||
// Match webContents audible value.
|
||||
if (!MatchesBool(audible, wc->IsCurrentlyAudible()))
|
||||
continue;
|
||||
|
||||
// Match webContents muted value.
|
||||
if (!MatchesBool(muted, wc->IsAudioMuted()))
|
||||
continue;
|
||||
|
||||
// Match webContents active status.
|
||||
if (!MatchesBool(params->query_info.active, contents->IsFocused()))
|
||||
continue;
|
||||
|
||||
if (!title.empty() || !url_patterns.is_empty()) {
|
||||
// "title" and "url" properties are considered privileged data and can
|
||||
// only be checked if the extension has the "tabs" permission or it has
|
||||
// access to the WebContents's origin. Otherwise, this tab is considered
|
||||
// not matched.
|
||||
if (!extension()->permissions_data()->HasAPIPermissionForTab(
|
||||
contents->ID(), mojom::APIPermissionID::kTab) &&
|
||||
!extension()->permissions_data()->HasHostPermission(wc->GetURL())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Match webContents title.
|
||||
if (!title.empty() &&
|
||||
!base::MatchPattern(wc->GetTitle(), base::UTF8ToUTF16(title)))
|
||||
continue;
|
||||
|
||||
// Match webContents url.
|
||||
if (!url_patterns.is_empty() && !url_patterns.MatchesURL(wc->GetURL()))
|
||||
continue;
|
||||
}
|
||||
|
||||
tabs::Tab tab;
|
||||
tab.id = contents->ID();
|
||||
tab.title = base::UTF16ToUTF8(wc->GetTitle());
|
||||
tab.url = wc->GetLastCommittedURL().spec();
|
||||
tab.active = contents->IsFocused();
|
||||
tab.audible = contents->IsCurrentlyAudible();
|
||||
tab.muted_info = CreateMutedInfo(wc);
|
||||
|
||||
result.Append(tab.ToValue());
|
||||
}
|
||||
|
||||
return RespondNow(WithArguments(std::move(result)));
|
||||
}
|
||||
|
||||
ExtensionFunction::ResponseAction TabsGetFunction::Run() {
|
||||
absl::optional<tabs::Get::Params> params = tabs::Get::Params::Create(args());
|
||||
EXTENSION_FUNCTION_VALIDATE(params);
|
||||
@@ -216,12 +323,18 @@ ExtensionFunction::ResponseAction TabsGetFunction::Run() {
|
||||
return RespondNow(Error("No such tab"));
|
||||
|
||||
tabs::Tab tab;
|
||||
|
||||
tab.id = tab_id;
|
||||
// TODO(nornagon): in Chrome, the tab URL is only available to extensions
|
||||
// that have the "tabs" (or "activeTab") permission. We should do the same
|
||||
// permission check here.
|
||||
tab.url = contents->web_contents()->GetLastCommittedURL().spec();
|
||||
|
||||
// "title" and "url" properties are considered privileged data and can
|
||||
// only be checked if the extension has the "tabs" permission or it has
|
||||
// access to the WebContents's origin.
|
||||
auto* wc = contents->web_contents();
|
||||
if (extension()->permissions_data()->HasAPIPermissionForTab(
|
||||
contents->ID(), mojom::APIPermissionID::kTab) ||
|
||||
extension()->permissions_data()->HasHostPermission(wc->GetURL())) {
|
||||
tab.url = wc->GetLastCommittedURL().spec();
|
||||
tab.title = base::UTF16ToUTF8(wc->GetTitle());
|
||||
}
|
||||
|
||||
tab.active = contents->IsFocused();
|
||||
|
||||
@@ -321,24 +434,24 @@ ExtensionFunction::ResponseAction TabsSetZoomSettingsFunction::Run() {
|
||||
// Determine the correct internal zoom mode to set |web_contents| to from the
|
||||
// user-specified |zoom_settings|.
|
||||
WebContentsZoomController::ZoomMode zoom_mode =
|
||||
WebContentsZoomController::ZoomMode::kDefault;
|
||||
WebContentsZoomController::ZOOM_MODE_DEFAULT;
|
||||
switch (params->zoom_settings.mode) {
|
||||
case tabs::ZOOM_SETTINGS_MODE_NONE:
|
||||
case tabs::ZOOM_SETTINGS_MODE_AUTOMATIC:
|
||||
switch (params->zoom_settings.scope) {
|
||||
case tabs::ZOOM_SETTINGS_SCOPE_NONE:
|
||||
case tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN:
|
||||
zoom_mode = WebContentsZoomController::ZoomMode::kDefault;
|
||||
zoom_mode = WebContentsZoomController::ZOOM_MODE_DEFAULT;
|
||||
break;
|
||||
case tabs::ZOOM_SETTINGS_SCOPE_PER_TAB:
|
||||
zoom_mode = WebContentsZoomController::ZoomMode::kIsolated;
|
||||
zoom_mode = WebContentsZoomController::ZOOM_MODE_ISOLATED;
|
||||
}
|
||||
break;
|
||||
case tabs::ZOOM_SETTINGS_MODE_MANUAL:
|
||||
zoom_mode = WebContentsZoomController::ZoomMode::kManual;
|
||||
zoom_mode = WebContentsZoomController::ZOOM_MODE_MANUAL;
|
||||
break;
|
||||
case tabs::ZOOM_SETTINGS_MODE_DISABLED:
|
||||
zoom_mode = WebContentsZoomController::ZoomMode::kDisabled;
|
||||
zoom_mode = WebContentsZoomController::ZOOM_MODE_DISABLED;
|
||||
}
|
||||
|
||||
contents->GetZoomController()->SetZoomMode(zoom_mode);
|
||||
@@ -502,10 +615,22 @@ ExtensionFunction::ResponseValue TabsUpdateFunction::GetResult() {
|
||||
|
||||
auto* api_web_contents = electron::api::WebContents::From(web_contents_);
|
||||
tab.id = (api_web_contents ? api_web_contents->ID() : -1);
|
||||
// TODO(nornagon): in Chrome, the tab URL is only available to extensions
|
||||
// that have the "tabs" (or "activeTab") permission. We should do the same
|
||||
// permission check here.
|
||||
tab.url = web_contents_->GetLastCommittedURL().spec();
|
||||
|
||||
// "title" and "url" properties are considered privileged data and can
|
||||
// only be checked if the extension has the "tabs" permission or it has
|
||||
// access to the WebContents's origin.
|
||||
if (extension()->permissions_data()->HasAPIPermissionForTab(
|
||||
api_web_contents->ID(), mojom::APIPermissionID::kTab) ||
|
||||
extension()->permissions_data()->HasHostPermission(
|
||||
web_contents_->GetURL())) {
|
||||
tab.url = web_contents_->GetLastCommittedURL().spec();
|
||||
tab.title = base::UTF16ToUTF8(web_contents_->GetTitle());
|
||||
}
|
||||
|
||||
if (api_web_contents)
|
||||
tab.active = api_web_contents->IsFocused();
|
||||
tab.muted_info = CreateMutedInfo(web_contents_);
|
||||
tab.audible = web_contents_->IsCurrentlyAudible();
|
||||
|
||||
return ArgumentList(tabs::Get::Results::Create(std::move(tab)));
|
||||
}
|
||||
|
||||
@@ -55,6 +55,14 @@ class TabsReloadFunction : public ExtensionFunction {
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.reload", TABS_RELOAD)
|
||||
};
|
||||
|
||||
class TabsQueryFunction : public ExtensionFunction {
|
||||
~TabsQueryFunction() override {}
|
||||
|
||||
ResponseAction Run() override;
|
||||
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.query", TABS_QUERY)
|
||||
};
|
||||
|
||||
class TabsGetFunction : public ExtensionFunction {
|
||||
~TabsGetFunction() override {}
|
||||
|
||||
|
||||
@@ -104,9 +104,10 @@ gin::IsolateHolder CreateIsolateHolder(v8::Isolate* isolate) {
|
||||
|
||||
JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop,
|
||||
bool setup_wasm_streaming)
|
||||
: isolate_(Initialize(event_loop, setup_wasm_streaming)),
|
||||
isolate_holder_(CreateIsolateHolder(isolate_)),
|
||||
locker_(isolate_) {
|
||||
: isolate_holder_{CreateIsolateHolder(
|
||||
Initialize(event_loop, setup_wasm_streaming))},
|
||||
isolate_{isolate_holder_.isolate()},
|
||||
locker_{isolate_} {
|
||||
isolate_->Enter();
|
||||
|
||||
v8::HandleScope scope(isolate_);
|
||||
|
||||
@@ -43,8 +43,12 @@ class JavascriptEnvironment {
|
||||
v8::Isolate* Initialize(uv_loop_t* event_loop, bool setup_wasm_streaming);
|
||||
std::unique_ptr<node::MultiIsolatePlatform> platform_;
|
||||
|
||||
raw_ptr<v8::Isolate> isolate_;
|
||||
gin::IsolateHolder isolate_holder_;
|
||||
|
||||
// owned-by: isolate_holder_
|
||||
const raw_ptr<v8::Isolate> isolate_;
|
||||
|
||||
// depends-on: isolate_
|
||||
v8::Locker locker_;
|
||||
|
||||
std::unique_ptr<MicrotasksRunner> microtasks_runner_;
|
||||
|
||||
@@ -814,7 +814,7 @@ bool NativeWindowMac::MoveAbove(const std::string& sourceId) {
|
||||
if (!webrtc::GetWindowOwnerPid(window_id))
|
||||
return false;
|
||||
|
||||
if (!parent()) {
|
||||
if (!parent() || is_modal()) {
|
||||
[window_ orderWindow:NSWindowAbove relativeTo:window_id];
|
||||
} else {
|
||||
NSWindow* other_window = [NSApp windowWithWindowNumber:window_id];
|
||||
@@ -825,10 +825,11 @@ bool NativeWindowMac::MoveAbove(const std::string& sourceId) {
|
||||
}
|
||||
|
||||
void NativeWindowMac::MoveTop() {
|
||||
if (!parent())
|
||||
if (!parent() || is_modal()) {
|
||||
[window_ orderWindow:NSWindowAbove relativeTo:0];
|
||||
else
|
||||
} else {
|
||||
ReorderChildWindowAbove(window_, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetResizable(bool resizable) {
|
||||
|
||||
@@ -234,6 +234,10 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
|
||||
|
||||
if (title_bar_style_ != TitleBarStyle::kNormal)
|
||||
set_has_frame(false);
|
||||
|
||||
// If the taskbar is re-created after we start up, we have to rebuild all of
|
||||
// our buttons.
|
||||
taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
||||
#endif
|
||||
|
||||
if (enable_larger_than_screen())
|
||||
|
||||
@@ -315,6 +315,10 @@ class NativeWindowViews : public NativeWindow,
|
||||
// Controls Overlay if enabled on Windows.
|
||||
SkColor overlay_button_color_;
|
||||
SkColor overlay_symbol_color_;
|
||||
|
||||
// The message ID of the "TaskbarCreated" message, sent to us when we need to
|
||||
// reset our thumbar buttons.
|
||||
UINT taskbar_created_message_ = 0;
|
||||
#endif
|
||||
|
||||
// Handles unhandled keyboard messages coming back from the renderer process.
|
||||
|
||||
@@ -221,6 +221,12 @@ bool NativeWindowViews::PreHandleMSG(UINT message,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message == taskbar_created_message_) {
|
||||
// We need to reset all of our buttons because the taskbar went away.
|
||||
taskbar_host_.RestoreThumbarButtons(GetAcceleratedWidget());
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
// Screen readers send WM_GETOBJECT in order to get the accessibility
|
||||
// object, so take this opportunity to push Chromium into accessible
|
||||
|
||||
@@ -616,6 +616,9 @@ void InspectableWebContents::AddDevToolsExtensionsToClient() {
|
||||
extension_info.Set("exposeExperimentalAPIs",
|
||||
extension->permissions_data()->HasAPIPermission(
|
||||
extensions::mojom::APIPermissionID::kExperimental));
|
||||
extension_info.Set("allowFileAccess",
|
||||
(extension->creation_flags() &
|
||||
extensions::Extension::ALLOW_FILE_ACCESS) != 0);
|
||||
results.Append(std::move(extension_info));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ InspectableWebContentsViewMac::InspectableWebContentsViewMac(
|
||||
initWithInspectableWebContentsViewMac:this]) {}
|
||||
|
||||
InspectableWebContentsViewMac::~InspectableWebContentsViewMac() {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:view_];
|
||||
CloseDevTools();
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,12 @@
|
||||
NSStatusItem* item = [[NSStatusBar systemStatusBar]
|
||||
statusItemWithLength:NSVariableStatusItemLength];
|
||||
statusItem_.reset([item retain]);
|
||||
[[statusItem_ button] addSubview:self]; // inject custom view
|
||||
[[statusItem_ button] addSubview:self];
|
||||
|
||||
// We need to set the target and action on the button, otherwise
|
||||
// VoiceOver doesn't know where to send the select action.
|
||||
[[statusItem_ button] setTarget:self];
|
||||
[[statusItem_ button] setAction:@selector(mouseDown:)];
|
||||
[self updateDimensions];
|
||||
}
|
||||
return self;
|
||||
@@ -191,6 +196,25 @@
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent*)event {
|
||||
// If |event| does not respond to locationInWindow, we've
|
||||
// arrived here from VoiceOver, which does not pass an event.
|
||||
// Create a synthetic event to pass to the click handler.
|
||||
if (![event respondsToSelector:@selector(locationInWindow)]) {
|
||||
event = [NSEvent mouseEventWithType:NSEventTypeRightMouseDown
|
||||
location:NSMakePoint(0, 0)
|
||||
modifierFlags:0
|
||||
timestamp:NSApp.currentEvent.timestamp
|
||||
windowNumber:0
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:1
|
||||
pressure:1.0];
|
||||
|
||||
// We also need to explicitly call the click handler here, since
|
||||
// VoiceOver won't trigger mouseUp.
|
||||
[self handleClickNotifications:event];
|
||||
}
|
||||
|
||||
trayIcon_->NotifyMouseDown(
|
||||
gfx::ScreenPointFromNSPoint([event locationInWindow]),
|
||||
ui::EventFlagsFromModifiers([event modifierFlags]));
|
||||
|
||||
@@ -150,7 +150,13 @@ void ClientFrameViewLinux::Init(NativeWindowViews* window,
|
||||
}
|
||||
|
||||
gfx::Insets ClientFrameViewLinux::GetBorderDecorationInsets() const {
|
||||
return frame_provider_->GetFrameThicknessDip();
|
||||
const auto insets = frame_provider_->GetFrameThicknessDip();
|
||||
// We shouldn't draw frame decorations for the tiled edges.
|
||||
// See https://wayland.app/protocols/xdg-shell#xdg_toplevel:enum:state
|
||||
return gfx::Insets::TLBR(tiled_edges().top ? 0 : insets.top(),
|
||||
tiled_edges().left ? 0 : insets.left(),
|
||||
tiled_edges().bottom ? 0 : insets.bottom(),
|
||||
tiled_edges().right ? 0 : insets.right());
|
||||
}
|
||||
|
||||
gfx::Insets ClientFrameViewLinux::GetInputInsets() const {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/navigation_details.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "content/public/browser/navigation_handle.h"
|
||||
@@ -16,72 +17,122 @@
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
#include "content/public/common/page_type.h"
|
||||
#include "net/base/url_util.h"
|
||||
#include "shell/browser/web_contents_zoom_observer.h"
|
||||
#include "third_party/blink/public/common/page/page_zoom.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
const double kPageZoomEpsilon = 0.001;
|
||||
|
||||
} // namespace
|
||||
|
||||
WebContentsZoomController::WebContentsZoomController(
|
||||
content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
content::WebContentsUserData<WebContentsZoomController>(*web_contents) {
|
||||
default_zoom_factor_ = kPageZoomEpsilon;
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
host_zoom_map_ = content::HostZoomMap::GetForWebContents(web_contents);
|
||||
zoom_level_ = host_zoom_map_->GetDefaultZoomLevel();
|
||||
default_zoom_factor_ = kPageZoomEpsilon;
|
||||
|
||||
zoom_subscription_ = host_zoom_map_->AddZoomLevelChangedCallback(
|
||||
base::BindRepeating(&WebContentsZoomController::OnZoomLevelChanged,
|
||||
base::Unretained(this)));
|
||||
|
||||
UpdateState(std::string());
|
||||
}
|
||||
|
||||
WebContentsZoomController::~WebContentsZoomController() = default;
|
||||
WebContentsZoomController::~WebContentsZoomController() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
for (auto& observer : observers_) {
|
||||
observer.OnZoomControllerDestroyed(this);
|
||||
}
|
||||
}
|
||||
|
||||
void WebContentsZoomController::AddObserver(
|
||||
WebContentsZoomController::Observer* observer) {
|
||||
void WebContentsZoomController::AddObserver(WebContentsZoomObserver* observer) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
observers_.AddObserver(observer);
|
||||
}
|
||||
|
||||
void WebContentsZoomController::RemoveObserver(
|
||||
WebContentsZoomController::Observer* observer) {
|
||||
WebContentsZoomObserver* observer) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
void WebContentsZoomController::SetEmbedderZoomController(
|
||||
WebContentsZoomController* controller) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
embedder_zoom_controller_ = controller;
|
||||
}
|
||||
|
||||
void WebContentsZoomController::SetZoomLevel(double level) {
|
||||
if (!web_contents()->GetPrimaryMainFrame()->IsRenderFrameLive() ||
|
||||
blink::PageZoomValuesEqual(GetZoomLevel(), level) ||
|
||||
zoom_mode_ == ZoomMode::kDisabled)
|
||||
return;
|
||||
bool WebContentsZoomController::SetZoomLevel(double level) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
content::NavigationEntry* entry =
|
||||
web_contents()->GetController().GetLastCommittedEntry();
|
||||
// Cannot zoom in disabled mode. Also, don't allow changing zoom level on
|
||||
// a crashed tab, an error page or an interstitial page.
|
||||
if (zoom_mode_ == ZOOM_MODE_DISABLED ||
|
||||
!web_contents()->GetPrimaryMainFrame()->IsRenderFrameLive())
|
||||
return false;
|
||||
|
||||
content::GlobalRenderFrameHostId rfh_id =
|
||||
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
||||
// Do not actually rescale the page in manual mode.
|
||||
if (zoom_mode_ == ZOOM_MODE_MANUAL) {
|
||||
// If the zoom level hasn't changed, early out to avoid sending an event.
|
||||
if (blink::PageZoomValuesEqual(zoom_level_, level))
|
||||
return true;
|
||||
|
||||
if (zoom_mode_ == ZoomMode::kManual) {
|
||||
double old_zoom_level = zoom_level_;
|
||||
zoom_level_ = level;
|
||||
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomLevelChanged(web_contents(), level, true);
|
||||
ZoomChangedEventData zoom_change_data(web_contents(), old_zoom_level,
|
||||
zoom_level_, false /* temporary */,
|
||||
zoom_mode_);
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(zoom_change_data);
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
content::HostZoomMap* zoom_map =
|
||||
content::HostZoomMap::GetForWebContents(web_contents());
|
||||
if (zoom_mode_ == ZoomMode::kIsolated ||
|
||||
DCHECK(zoom_map);
|
||||
DCHECK(!event_data_);
|
||||
event_data_ = std::make_unique<ZoomChangedEventData>(
|
||||
web_contents(), GetZoomLevel(), level, false /* temporary */, zoom_mode_);
|
||||
|
||||
content::GlobalRenderFrameHostId rfh_id =
|
||||
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
||||
if (zoom_mode_ == ZOOM_MODE_ISOLATED ||
|
||||
zoom_map->UsesTemporaryZoomLevel(rfh_id)) {
|
||||
zoom_map->SetTemporaryZoomLevel(rfh_id, level);
|
||||
// Notify observers of zoom level changes.
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomLevelChanged(web_contents(), level, true);
|
||||
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level_, level,
|
||||
true /* temporary */, zoom_mode_);
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(zoom_change_data);
|
||||
} else {
|
||||
content::HostZoomMap::SetZoomLevel(web_contents(), level);
|
||||
|
||||
// Notify observers of zoom level changes.
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomLevelChanged(web_contents(), level, false);
|
||||
if (!entry) {
|
||||
// If we exit without triggering an update, we should clear event_data_,
|
||||
// else we may later trigger a DCHECK(event_data_).
|
||||
event_data_.reset();
|
||||
return false;
|
||||
}
|
||||
std::string host =
|
||||
net::GetHostOrSpecFromURL(content::HostZoomMap::GetURLFromEntry(entry));
|
||||
zoom_map->SetZoomLevelForHost(host, level);
|
||||
}
|
||||
|
||||
DCHECK(!event_data_);
|
||||
return true;
|
||||
}
|
||||
|
||||
double WebContentsZoomController::GetZoomLevel() {
|
||||
return zoom_mode_ == ZoomMode::kManual
|
||||
double WebContentsZoomController::GetZoomLevel() const {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
return zoom_mode_ == ZOOM_MODE_MANUAL
|
||||
? zoom_level_
|
||||
: content::HostZoomMap::GetZoomLevel(web_contents());
|
||||
}
|
||||
@@ -95,32 +146,44 @@ double WebContentsZoomController::GetDefaultZoomFactor() {
|
||||
}
|
||||
|
||||
void WebContentsZoomController::SetTemporaryZoomLevel(double level) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
content::GlobalRenderFrameHostId old_rfh_id_ =
|
||||
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
||||
host_zoom_map_->SetTemporaryZoomLevel(old_rfh_id_, level);
|
||||
|
||||
// Notify observers of zoom level changes.
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomLevelChanged(web_contents(), level, true);
|
||||
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level_, level,
|
||||
true /* temporary */, zoom_mode_);
|
||||
for (WebContentsZoomObserver& observer : observers_)
|
||||
observer.OnZoomChanged(zoom_change_data);
|
||||
}
|
||||
|
||||
bool WebContentsZoomController::UsesTemporaryZoomLevel() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
content::GlobalRenderFrameHostId rfh_id =
|
||||
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
||||
return host_zoom_map_->UsesTemporaryZoomLevel(rfh_id);
|
||||
}
|
||||
|
||||
void WebContentsZoomController::SetZoomMode(ZoomMode new_mode) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
if (new_mode == zoom_mode_)
|
||||
return;
|
||||
|
||||
content::HostZoomMap* zoom_map =
|
||||
content::HostZoomMap::GetForWebContents(web_contents());
|
||||
DCHECK(zoom_map);
|
||||
content::GlobalRenderFrameHostId rfh_id =
|
||||
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
||||
double original_zoom_level = GetZoomLevel();
|
||||
|
||||
DCHECK(!event_data_);
|
||||
event_data_ = std::make_unique<ZoomChangedEventData>(
|
||||
web_contents(), original_zoom_level, original_zoom_level,
|
||||
false /* temporary */, new_mode);
|
||||
|
||||
switch (new_mode) {
|
||||
case ZoomMode::kDefault: {
|
||||
case ZOOM_MODE_DEFAULT: {
|
||||
content::NavigationEntry* entry =
|
||||
web_contents()->GetController().GetLastCommittedEntry();
|
||||
|
||||
@@ -135,6 +198,7 @@ void WebContentsZoomController::SetZoomMode(ZoomMode new_mode) {
|
||||
// the correct zoom level.
|
||||
double origin_zoom_level =
|
||||
zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), host);
|
||||
event_data_->new_zoom_level = origin_zoom_level;
|
||||
zoom_map->SetTemporaryZoomLevel(rfh_id, origin_zoom_level);
|
||||
} else {
|
||||
// The host will need a level prior to removing the temporary level.
|
||||
@@ -147,101 +211,128 @@ void WebContentsZoomController::SetZoomMode(ZoomMode new_mode) {
|
||||
zoom_map->ClearTemporaryZoomLevel(rfh_id);
|
||||
break;
|
||||
}
|
||||
case ZoomMode::kIsolated: {
|
||||
// Unless the zoom mode was |ZoomMode::kDisabled| before this call, the
|
||||
case ZOOM_MODE_ISOLATED: {
|
||||
// Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the
|
||||
// page needs an initial isolated zoom back to the same level it was at
|
||||
// in the other mode.
|
||||
if (zoom_mode_ != ZoomMode::kDisabled) {
|
||||
if (zoom_mode_ != ZOOM_MODE_DISABLED) {
|
||||
zoom_map->SetTemporaryZoomLevel(rfh_id, original_zoom_level);
|
||||
} else {
|
||||
// When we don't call any HostZoomMap set functions, we send the event
|
||||
// manually.
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomLevelChanged(web_contents(), original_zoom_level,
|
||||
false);
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(*event_data_);
|
||||
event_data_.reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZoomMode::kManual: {
|
||||
// Unless the zoom mode was |ZoomMode::kDisabled| before this call, the
|
||||
case ZOOM_MODE_MANUAL: {
|
||||
// Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the
|
||||
// page needs to be resized to the default zoom. While in manual mode,
|
||||
// the zoom level is handled independently.
|
||||
if (zoom_mode_ != ZoomMode::kDisabled) {
|
||||
if (zoom_mode_ != ZOOM_MODE_DISABLED) {
|
||||
zoom_map->SetTemporaryZoomLevel(rfh_id, GetDefaultZoomLevel());
|
||||
zoom_level_ = original_zoom_level;
|
||||
} else {
|
||||
// When we don't call any HostZoomMap set functions, we send the event
|
||||
// manually.
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomLevelChanged(web_contents(), original_zoom_level,
|
||||
false);
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(*event_data_);
|
||||
event_data_.reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZoomMode::kDisabled: {
|
||||
case ZOOM_MODE_DISABLED: {
|
||||
// The page needs to be zoomed back to default before disabling the zoom
|
||||
zoom_map->SetTemporaryZoomLevel(rfh_id, GetDefaultZoomLevel());
|
||||
double new_zoom_level = GetDefaultZoomLevel();
|
||||
event_data_->new_zoom_level = new_zoom_level;
|
||||
zoom_map->SetTemporaryZoomLevel(rfh_id, new_zoom_level);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Any event data we've stored should have been consumed by this point.
|
||||
DCHECK(!event_data_);
|
||||
|
||||
zoom_mode_ = new_mode;
|
||||
}
|
||||
|
||||
void WebContentsZoomController::ResetZoomModeOnNavigationIfNeeded(
|
||||
const GURL& url) {
|
||||
if (zoom_mode_ != ZoomMode::kIsolated && zoom_mode_ != ZoomMode::kManual)
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
if (zoom_mode_ != ZOOM_MODE_ISOLATED && zoom_mode_ != ZOOM_MODE_MANUAL)
|
||||
return;
|
||||
|
||||
content::GlobalRenderFrameHostId rfh_id =
|
||||
web_contents()->GetPrimaryMainFrame()->GetGlobalId();
|
||||
content::HostZoomMap* zoom_map =
|
||||
content::HostZoomMap::GetForWebContents(web_contents());
|
||||
zoom_level_ = zoom_map->GetDefaultZoomLevel();
|
||||
double old_zoom_level = zoom_map->GetZoomLevel(web_contents());
|
||||
double new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme(
|
||||
url.scheme(), net::GetHostOrSpecFromURL(url));
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomLevelChanged(web_contents(), new_zoom_level, false);
|
||||
zoom_map->ClearTemporaryZoomLevel(rfh_id);
|
||||
zoom_mode_ = ZoomMode::kDefault;
|
||||
event_data_ = std::make_unique<ZoomChangedEventData>(
|
||||
web_contents(), old_zoom_level, new_zoom_level, false, ZOOM_MODE_DEFAULT);
|
||||
// The call to ClearTemporaryZoomLevel() doesn't generate any events from
|
||||
// HostZoomMap, but the call to UpdateState() at the end of
|
||||
// DidFinishNavigation will notify our observers.
|
||||
// Note: it's possible the render_process/frame ids have disappeared (e.g.
|
||||
// if we navigated to a new origin), but this won't cause a problem in the
|
||||
// call below.
|
||||
zoom_map->ClearTemporaryZoomLevel(
|
||||
web_contents()->GetPrimaryMainFrame()->GetGlobalId());
|
||||
zoom_mode_ = ZOOM_MODE_DEFAULT;
|
||||
}
|
||||
|
||||
void WebContentsZoomController::DidFinishNavigation(
|
||||
content::NavigationHandle* navigation_handle) {
|
||||
if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted())
|
||||
return;
|
||||
|
||||
if (navigation_handle->IsErrorPage()) {
|
||||
content::HostZoomMap::SendErrorPageZoomLevelRefresh(web_contents());
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
if (!navigation_handle->IsInPrimaryMainFrame() ||
|
||||
!navigation_handle->HasCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResetZoomModeOnNavigationIfNeeded(navigation_handle->GetURL());
|
||||
SetZoomFactorOnNavigationIfNeeded(navigation_handle->GetURL());
|
||||
if (navigation_handle->IsErrorPage())
|
||||
content::HostZoomMap::SendErrorPageZoomLevelRefresh(web_contents());
|
||||
|
||||
if (!navigation_handle->IsSameDocument()) {
|
||||
ResetZoomModeOnNavigationIfNeeded(navigation_handle->GetURL());
|
||||
SetZoomFactorOnNavigationIfNeeded(navigation_handle->GetURL());
|
||||
}
|
||||
|
||||
// If the main frame's content has changed, the new page may have a different
|
||||
// zoom level from the old one.
|
||||
UpdateState(std::string());
|
||||
DCHECK(!event_data_);
|
||||
}
|
||||
|
||||
void WebContentsZoomController::WebContentsDestroyed() {
|
||||
for (Observer& observer : observers_)
|
||||
observer.OnZoomControllerWebContentsDestroyed();
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
// At this point we should no longer be sending any zoom events with this
|
||||
// WebContents.
|
||||
for (auto& observer : observers_) {
|
||||
observer.OnZoomControllerDestroyed(this);
|
||||
}
|
||||
|
||||
observers_.Clear();
|
||||
embedder_zoom_controller_ = nullptr;
|
||||
}
|
||||
|
||||
void WebContentsZoomController::RenderFrameHostChanged(
|
||||
content::RenderFrameHost* old_host,
|
||||
content::RenderFrameHost* new_host) {
|
||||
// If our associated HostZoomMap changes, update our event subscription.
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
// If our associated HostZoomMap changes, update our subscription.
|
||||
content::HostZoomMap* new_host_zoom_map =
|
||||
content::HostZoomMap::GetForWebContents(web_contents());
|
||||
if (new_host_zoom_map == host_zoom_map_)
|
||||
return;
|
||||
|
||||
host_zoom_map_ = new_host_zoom_map;
|
||||
zoom_subscription_ = host_zoom_map_->AddZoomLevelChangedCallback(
|
||||
base::BindRepeating(&WebContentsZoomController::OnZoomLevelChanged,
|
||||
base::Unretained(this)));
|
||||
}
|
||||
|
||||
void WebContentsZoomController::SetZoomFactorOnNavigationIfNeeded(
|
||||
const GURL& url) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
if (blink::PageZoomValuesEqual(GetDefaultZoomFactor(), kPageZoomEpsilon))
|
||||
return;
|
||||
|
||||
@@ -276,6 +367,42 @@ void WebContentsZoomController::SetZoomFactorOnNavigationIfNeeded(
|
||||
SetZoomLevel(zoom_level);
|
||||
}
|
||||
|
||||
void WebContentsZoomController::OnZoomLevelChanged(
|
||||
const content::HostZoomMap::ZoomLevelChange& change) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
UpdateState(change.host);
|
||||
}
|
||||
|
||||
void WebContentsZoomController::UpdateState(const std::string& host) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
// If |host| is empty, all observers should be updated.
|
||||
if (!host.empty()) {
|
||||
// Use the navigation entry's URL instead of the WebContents' so virtual
|
||||
// URLs work (e.g. chrome://settings). http://crbug.com/153950
|
||||
content::NavigationEntry* entry =
|
||||
web_contents()->GetController().GetLastCommittedEntry();
|
||||
if (!entry || host != net::GetHostOrSpecFromURL(
|
||||
content::HostZoomMap::GetURLFromEntry(entry))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (event_data_) {
|
||||
// For state changes initiated within the ZoomController, information about
|
||||
// the change should be sent.
|
||||
ZoomChangedEventData zoom_change_data = *event_data_;
|
||||
event_data_.reset();
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(zoom_change_data);
|
||||
} else {
|
||||
double zoom_level = GetZoomLevel();
|
||||
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level,
|
||||
zoom_level, false, zoom_mode_);
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(zoom_change_data);
|
||||
}
|
||||
}
|
||||
|
||||
WEB_CONTENTS_USER_DATA_KEY_IMPL(WebContentsZoomController);
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -14,40 +14,49 @@
|
||||
|
||||
namespace electron {
|
||||
|
||||
class WebContentsZoomObserver;
|
||||
|
||||
// Manages the zoom changes of WebContents.
|
||||
class WebContentsZoomController
|
||||
: public content::WebContentsObserver,
|
||||
public content::WebContentsUserData<WebContentsZoomController> {
|
||||
public:
|
||||
class Observer : public base::CheckedObserver {
|
||||
public:
|
||||
virtual void OnZoomLevelChanged(content::WebContents* web_contents,
|
||||
double level,
|
||||
bool is_temporary) {}
|
||||
virtual void OnZoomControllerWebContentsDestroyed() {}
|
||||
|
||||
protected:
|
||||
~Observer() override {}
|
||||
};
|
||||
|
||||
// Defines how zoom changes are handled.
|
||||
enum class ZoomMode {
|
||||
enum ZoomMode {
|
||||
// Results in default zoom behavior, i.e. zoom changes are handled
|
||||
// automatically and on a per-origin basis, meaning that other tabs
|
||||
// navigated to the same origin will also zoom.
|
||||
kDefault,
|
||||
ZOOM_MODE_DEFAULT,
|
||||
// Results in zoom changes being handled automatically, but on a per-tab
|
||||
// basis. Tabs in this zoom mode will not be affected by zoom changes in
|
||||
// other tabs, and vice versa.
|
||||
kIsolated,
|
||||
ZOOM_MODE_ISOLATED,
|
||||
// Overrides the automatic handling of zoom changes. The |onZoomChange|
|
||||
// event will still be dispatched, but the page will not actually be zoomed.
|
||||
// These zoom changes can be handled manually by listening for the
|
||||
// |onZoomChange| event. Zooming in this mode is also on a per-tab basis.
|
||||
kManual,
|
||||
ZOOM_MODE_MANUAL,
|
||||
// Disables all zooming in this tab. The tab will revert to the default
|
||||
// zoom level, and all attempted zoom changes will be ignored.
|
||||
kDisabled,
|
||||
ZOOM_MODE_DISABLED,
|
||||
};
|
||||
|
||||
struct ZoomChangedEventData {
|
||||
ZoomChangedEventData(content::WebContents* web_contents,
|
||||
double old_zoom_level,
|
||||
double new_zoom_level,
|
||||
bool temporary,
|
||||
WebContentsZoomController::ZoomMode zoom_mode)
|
||||
: web_contents(web_contents),
|
||||
old_zoom_level(old_zoom_level),
|
||||
new_zoom_level(new_zoom_level),
|
||||
temporary(temporary),
|
||||
zoom_mode(zoom_mode) {}
|
||||
raw_ptr<content::WebContents> web_contents;
|
||||
double old_zoom_level;
|
||||
double new_zoom_level;
|
||||
bool temporary;
|
||||
WebContentsZoomController::ZoomMode zoom_mode;
|
||||
};
|
||||
|
||||
explicit WebContentsZoomController(content::WebContents* web_contents);
|
||||
@@ -58,24 +67,29 @@ class WebContentsZoomController
|
||||
WebContentsZoomController& operator=(const WebContentsZoomController&) =
|
||||
delete;
|
||||
|
||||
void AddObserver(Observer* observer);
|
||||
void RemoveObserver(Observer* observer);
|
||||
void AddObserver(WebContentsZoomObserver* observer);
|
||||
void RemoveObserver(WebContentsZoomObserver* observer);
|
||||
|
||||
void SetEmbedderZoomController(WebContentsZoomController* controller);
|
||||
|
||||
// Methods for managing zoom levels.
|
||||
void SetZoomLevel(double level);
|
||||
double GetZoomLevel();
|
||||
// Gets the current zoom level by querying HostZoomMap (if not in manual zoom
|
||||
// mode) or from the ZoomController local value otherwise.
|
||||
double GetZoomLevel() const;
|
||||
|
||||
// Sets the zoom level through HostZoomMap.
|
||||
// Returns true on success.
|
||||
bool SetZoomLevel(double zoom_level);
|
||||
|
||||
void SetDefaultZoomFactor(double factor);
|
||||
double GetDefaultZoomFactor();
|
||||
|
||||
// Sets the temporary zoom level through HostZoomMap.
|
||||
void SetTemporaryZoomLevel(double level);
|
||||
bool UsesTemporaryZoomLevel();
|
||||
|
||||
// Sets the zoom mode, which defines zoom behavior (see enum ZoomMode).
|
||||
void SetZoomMode(ZoomMode zoom_mode);
|
||||
|
||||
void ResetZoomModeOnNavigationIfNeeded(const GURL& url);
|
||||
|
||||
ZoomMode zoom_mode() const { return zoom_mode_; }
|
||||
|
||||
// Convenience method to get default zoom level. Implemented here for
|
||||
@@ -86,8 +100,9 @@ class WebContentsZoomController
|
||||
}
|
||||
|
||||
protected:
|
||||
// content::WebContentsObserver:
|
||||
void DidFinishNavigation(content::NavigationHandle* handle) override;
|
||||
// content::WebContentsObserver overrides:
|
||||
void DidFinishNavigation(
|
||||
content::NavigationHandle* navigation_handle) override;
|
||||
void WebContentsDestroyed() override;
|
||||
void RenderFrameHostChanged(content::RenderFrameHost* old_host,
|
||||
content::RenderFrameHost* new_host) override;
|
||||
@@ -95,29 +110,40 @@ class WebContentsZoomController
|
||||
private:
|
||||
friend class content::WebContentsUserData<WebContentsZoomController>;
|
||||
|
||||
// Called after a navigation has committed to set default zoom factor.
|
||||
void ResetZoomModeOnNavigationIfNeeded(const GURL& url);
|
||||
void SetZoomFactorOnNavigationIfNeeded(const GURL& url);
|
||||
void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change);
|
||||
|
||||
// Updates the zoom icon and zoom percentage based on current values and
|
||||
// notifies the observer if changes have occurred. |host| may be empty,
|
||||
// meaning the change should apply to ~all sites. If it is not empty, the
|
||||
// change only affects sites with the given host.
|
||||
void UpdateState(const std::string& host);
|
||||
|
||||
// The current zoom mode.
|
||||
ZoomMode zoom_mode_ = ZoomMode::kDefault;
|
||||
ZoomMode zoom_mode_ = ZOOM_MODE_DEFAULT;
|
||||
|
||||
// Current zoom level.
|
||||
double zoom_level_ = 1.0;
|
||||
// The current zoom level.
|
||||
double zoom_level_;
|
||||
|
||||
// kZoomFactor.
|
||||
double default_zoom_factor_ = 0;
|
||||
|
||||
const double kPageZoomEpsilon = 0.001;
|
||||
// The current default zoom factor.
|
||||
double default_zoom_factor_;
|
||||
|
||||
int old_process_id_ = -1;
|
||||
int old_view_id_ = -1;
|
||||
|
||||
std::unique_ptr<ZoomChangedEventData> event_data_;
|
||||
|
||||
raw_ptr<WebContentsZoomController> embedder_zoom_controller_ = nullptr;
|
||||
|
||||
base::ObserverList<Observer> observers_;
|
||||
// Observer receiving notifications on state changes.
|
||||
base::ObserverList<WebContentsZoomObserver> observers_;
|
||||
|
||||
// Keep track of the HostZoomMap we're currently subscribed to.
|
||||
raw_ptr<content::HostZoomMap> host_zoom_map_;
|
||||
|
||||
base::CallbackListSubscription zoom_subscription_;
|
||||
|
||||
WEB_CONTENTS_USER_DATA_KEY_DECL();
|
||||
};
|
||||
|
||||
|
||||
29
shell/browser/web_contents_zoom_observer.h
Normal file
29
shell/browser/web_contents_zoom_observer.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2023 Microsoft, GmbH
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_WEB_CONTENTS_ZOOM_OBSERVER_H_
|
||||
#define ELECTRON_SHELL_BROWSER_WEB_CONTENTS_ZOOM_OBSERVER_H_
|
||||
|
||||
#include "shell/browser/web_contents_zoom_controller.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
// Interface for objects that wish to be notified of changes in
|
||||
// WebContentsZoomController.
|
||||
class WebContentsZoomObserver : public base::CheckedObserver {
|
||||
public:
|
||||
// Fired when the ZoomController is destructed. Observers should deregister
|
||||
// themselves from the ZoomObserver in this event handler. Note that
|
||||
// ZoomController::FromWebContents() returns nullptr at this point already.
|
||||
virtual void OnZoomControllerDestroyed(
|
||||
WebContentsZoomController* zoom_controller) = 0;
|
||||
|
||||
// Notification that the zoom percentage has changed.
|
||||
virtual void OnZoomChanged(
|
||||
const WebContentsZoomController::ZoomChangedEventData& data) {}
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_WEB_CONTENTS_ZOOM_OBSERVER_H_
|
||||
@@ -73,23 +73,23 @@ content::WebContents* WebViewGuestDelegate::GetOwnerWebContents() {
|
||||
return embedder_web_contents_;
|
||||
}
|
||||
|
||||
void WebViewGuestDelegate::OnZoomLevelChanged(
|
||||
content::WebContents* web_contents,
|
||||
double level,
|
||||
bool is_temporary) {
|
||||
if (web_contents == GetOwnerWebContents()) {
|
||||
if (is_temporary) {
|
||||
api_web_contents_->GetZoomController()->SetTemporaryZoomLevel(level);
|
||||
void WebViewGuestDelegate::OnZoomChanged(
|
||||
const WebContentsZoomController::ZoomChangedEventData& data) {
|
||||
if (data.web_contents == GetOwnerWebContents()) {
|
||||
if (data.temporary) {
|
||||
api_web_contents_->GetZoomController()->SetTemporaryZoomLevel(
|
||||
data.new_zoom_level);
|
||||
} else {
|
||||
api_web_contents_->GetZoomController()->SetZoomLevel(level);
|
||||
api_web_contents_->GetZoomController()->SetZoomLevel(data.new_zoom_level);
|
||||
}
|
||||
// Change the default zoom factor to match the embedders' new zoom level.
|
||||
double zoom_factor = blink::PageZoomLevelToZoomFactor(level);
|
||||
double zoom_factor = blink::PageZoomLevelToZoomFactor(data.new_zoom_level);
|
||||
api_web_contents_->GetZoomController()->SetDefaultZoomFactor(zoom_factor);
|
||||
}
|
||||
}
|
||||
|
||||
void WebViewGuestDelegate::OnZoomControllerWebContentsDestroyed() {
|
||||
void WebViewGuestDelegate::OnZoomControllerDestroyed(
|
||||
WebContentsZoomController* zoom_controller) {
|
||||
ResetZoomController();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "content/public/browser/browser_plugin_guest_delegate.h"
|
||||
#include "shell/browser/web_contents_zoom_controller.h"
|
||||
#include "shell/browser/web_contents_zoom_observer.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -18,7 +19,7 @@ class WebContents;
|
||||
}
|
||||
|
||||
class WebViewGuestDelegate : public content::BrowserPluginGuestDelegate,
|
||||
public WebContentsZoomController::Observer {
|
||||
public WebContentsZoomObserver {
|
||||
public:
|
||||
WebViewGuestDelegate(content::WebContents* embedder,
|
||||
api::WebContents* api_web_contents);
|
||||
@@ -41,11 +42,11 @@ class WebViewGuestDelegate : public content::BrowserPluginGuestDelegate,
|
||||
base::WeakPtr<content::BrowserPluginGuestDelegate> GetGuestDelegateWeakPtr()
|
||||
final;
|
||||
|
||||
// WebContentsZoomController::Observer:
|
||||
void OnZoomLevelChanged(content::WebContents* web_contents,
|
||||
double level,
|
||||
bool is_temporary) override;
|
||||
void OnZoomControllerWebContentsDestroyed() override;
|
||||
// WebContentsZoomObserver:
|
||||
void OnZoomControllerDestroyed(
|
||||
WebContentsZoomController* zoom_controller) override;
|
||||
void OnZoomChanged(
|
||||
const WebContentsZoomController::ZoomChangedEventData& data) override;
|
||||
|
||||
private:
|
||||
void ResetZoomController();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/common/gin_converters/image_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
@@ -220,10 +221,18 @@ void Clipboard::WriteBookmark(const std::u16string& title,
|
||||
}
|
||||
|
||||
gfx::Image Clipboard::ReadImage(gin_helper::Arguments* args) {
|
||||
// The ReadPng uses thread pool which requires app ready.
|
||||
if (IsBrowserProcess() && !Browser::Get()->is_ready()) {
|
||||
args->ThrowError(
|
||||
"clipboard.readImage is available only after app ready in the main "
|
||||
"process");
|
||||
return gfx::Image();
|
||||
}
|
||||
|
||||
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
|
||||
absl::optional<gfx::Image> image;
|
||||
|
||||
base::RunLoop run_loop;
|
||||
base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
|
||||
base::RepeatingClosure callback = run_loop.QuitClosure();
|
||||
clipboard->ReadPng(
|
||||
GetClipboardBuffer(args),
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
"extension_types": ["extension"],
|
||||
"contexts": ["blessed_extension"]
|
||||
},
|
||||
"tabs.executeScript": {
|
||||
"max_manifest_version": 2
|
||||
},
|
||||
"tabs.insertCSS": {
|
||||
"max_manifest_version": 2
|
||||
},
|
||||
"tabs.removeCSS": {
|
||||
"max_manifest_version": 2
|
||||
},
|
||||
"extension": {
|
||||
"channel": "stable",
|
||||
"extension_types": ["extension"],
|
||||
@@ -14,7 +23,8 @@
|
||||
"disallow_for_service_workers": true
|
||||
},
|
||||
"extension.getURL": {
|
||||
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
|
||||
"contexts": ["blessed_extension", "unblessed_extension", "content_script"],
|
||||
"max_manifest_version": 2
|
||||
},
|
||||
"i18n": {
|
||||
"channel": "stable",
|
||||
|
||||
@@ -14,5 +14,9 @@
|
||||
"devtools_page": {
|
||||
"channel": "stable",
|
||||
"extension_types": ["extension"]
|
||||
},
|
||||
"minimum_chrome_version": {
|
||||
"channel": "stable",
|
||||
"extension_types": ["extension"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,5 +20,11 @@
|
||||
"extension_types": [
|
||||
"extension"
|
||||
]
|
||||
},
|
||||
"tabs": {
|
||||
"channel": "stable",
|
||||
"extension_types": [
|
||||
"extension"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
// Copyright 2012 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
[
|
||||
{
|
||||
"namespace": "i18n",
|
||||
"description": "Use the <code>chrome.i18n</code> infrastructure to implement internationalization across your whole app or extension.",
|
||||
"types": [
|
||||
{
|
||||
"id": "LanguageCode",
|
||||
"type": "string",
|
||||
"description": "An ISO language code such as <code>en</code> or <code>fr</code>. For a complete list of languages supported by this method, see <a href='http://src.chromium.org/viewvc/chrome/trunk/src/third_party/cld/languages/internal/languages.cc'>kLanguageInfoTable</a>. For an unknown language, <code>und</code> will be returned, which means that [percentage] of the text is unknown to CLD"
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"name": "getAcceptLanguages",
|
||||
"type": "function",
|
||||
"description": "Gets the accept-languages of the browser. This is different from the locale used by the browser; to get the locale, use $(ref:i18n.getUILanguage).",
|
||||
"parameters": [],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "languages",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "LanguageCode"
|
||||
},
|
||||
"description": "Array of LanguageCode"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "getMessage",
|
||||
"nocompile": true,
|
||||
"type": "function",
|
||||
"description": "Gets the localized string for the specified message. If the message is missing, this method returns an empty string (''). If the format of the <code>getMessage()</code> call is wrong — for example, <em>messageName</em> is not a string or the <em>substitutions</em> array has more than 9 elements — this method returns <code>undefined</code>.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "messageName",
|
||||
"description": "The name of the message, as specified in the <a href='i18n-messages'><code>messages.json</code></a> file."
|
||||
},
|
||||
{
|
||||
"type": "any",
|
||||
"name": "substitutions",
|
||||
"optional": true,
|
||||
"description": "Up to 9 substitution strings, if the message requires any."
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "options",
|
||||
"optional": true,
|
||||
"properties": {
|
||||
"escapeLt": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Escape <code><</code> in translation to <code>&lt;</code>. This applies only to the message itself, not to the placeholders. Developers might want to use this if the translation is used in an HTML context. Closure Templates used with Closure Compiler generate this automatically."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {
|
||||
"type": "string",
|
||||
"description": "Message localized for current locale."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "getUILanguage",
|
||||
"type": "function",
|
||||
"nocompile": true,
|
||||
"description": "Gets the browser UI language of the browser. This is different from $(ref:i18n.getAcceptLanguages) which returns the preferred user languages.",
|
||||
"parameters": [],
|
||||
"returns": {
|
||||
"type": "string",
|
||||
"description": "The browser UI language code such as en-US or fr-FR."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "detectLanguage",
|
||||
"type": "function",
|
||||
"nocompile": true,
|
||||
"description": "Detects the language of the provided text using CLD.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "text",
|
||||
"minimum": 0,
|
||||
"description": "User input string to be translated."
|
||||
}
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "object",
|
||||
"name": "result",
|
||||
"description": "LanguageDetectionResult object that holds detected langugae reliability and array of DetectedLanguage",
|
||||
"properties": {
|
||||
"isReliable": {
|
||||
"type": "boolean",
|
||||
"description": "CLD detected language reliability"
|
||||
},
|
||||
"languages": {
|
||||
"type": "array",
|
||||
"description": "array of detectedLanguage",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "DetectedLanguage object that holds detected ISO language code and its percentage in the input string",
|
||||
"properties": {
|
||||
"language": {
|
||||
"$ref": "LanguageCode"
|
||||
},
|
||||
"percentage": {
|
||||
"type": "integer",
|
||||
"description": "The percentage of the detected language"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"events": []
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Copyright 2015 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace resourcesPrivate {
|
||||
// chrome/browser/extensions/api/resources_private/resources_private_api.cc
|
||||
// for instructions on adding a new component to this API.
|
||||
//
|
||||
// |component| : Internal chrome component to get strings for.
|
||||
// |component| : Internal Chrome component to get strings for.
|
||||
// |callback| : Called with a dictionary mapping names to strings.
|
||||
static void getStrings(Component component,
|
||||
GetStringsCallback callback);
|
||||
[supportsPromises] static void getStrings(Component component,
|
||||
GetStringsCallback callback);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,13 +3,33 @@
|
||||
"namespace": "tabs",
|
||||
"description": "Use the <code>chrome.tabs</code> API to interact with the browser's tab system. You can use this API to create, modify, and rearrange tabs in the browser.",
|
||||
"types": [
|
||||
{ "id": "MutedInfoReason",
|
||||
{
|
||||
"id": "TabStatus",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"unloaded",
|
||||
"loading",
|
||||
"complete"
|
||||
],
|
||||
"description": "The tab's loading status."
|
||||
},
|
||||
{
|
||||
"id": "MutedInfoReason",
|
||||
"type": "string",
|
||||
"description": "An event that caused a muted state change.",
|
||||
"enum": [
|
||||
{"name": "user", "description": "A user input action set the muted state."},
|
||||
{"name": "capture", "description": "Tab capture was started, forcing a muted state change."},
|
||||
{"name": "extension", "description": "An extension, identified by the extensionId field, set the muted state."}
|
||||
{
|
||||
"name": "user",
|
||||
"description": "A user input action set the muted state."
|
||||
},
|
||||
{
|
||||
"name": "capture",
|
||||
"description": "Tab capture was started, forcing a muted state change."
|
||||
},
|
||||
{
|
||||
"name": "extension",
|
||||
"description": "An extension, identified by the extensionId field, set the muted state."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -37,29 +57,112 @@
|
||||
"id": "Tab",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {"type": "integer", "minimum": -1, "optional": true, "description": "The ID of the tab. Tab IDs are unique within a browser session. Under some circumstances a tab may not be assigned an ID; for example, when querying foreign tabs using the $(ref:sessions) API, in which case a session ID may be present. Tab ID can also be set to <code>chrome.tabs.TAB_ID_NONE</code> for apps and devtools windows."},
|
||||
// TODO(kalman): Investigate how this is ending up as -1 (based on window type? a bug?) and whether it should be optional instead.
|
||||
"index": {"type": "integer", "minimum": -1, "description": "The zero-based index of the tab within its window."},
|
||||
"groupId": {"type": "integer", "minimum": -1, "description": "The ID of the group that the tab belongs to."},
|
||||
"windowId": {"type": "integer", "minimum": 0, "description": "The ID of the window that contains the tab."},
|
||||
"openerTabId": {"type": "integer", "minimum": 0, "optional": true, "description": "The ID of the tab that opened this tab, if any. This property is only present if the opener tab still exists."},
|
||||
"selected": {"type": "boolean", "description": "Whether the tab is selected.", "deprecated": "Please use $(ref:tabs.Tab.highlighted)."},
|
||||
"highlighted": {"type": "boolean", "description": "Whether the tab is highlighted."},
|
||||
"active": {"type": "boolean", "description": "Whether the tab is active in its window. Does not necessarily mean the window is focused."},
|
||||
"pinned": {"type": "boolean", "description": "Whether the tab is pinned."},
|
||||
"audible": {"type": "boolean", "optional": true, "description": "Whether the tab has produced sound over the past couple of seconds (but it might not be heard if also muted). Equivalent to whether the 'speaker audio' indicator is showing."},
|
||||
"discarded": {"type": "boolean", "description": "Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory, but is still visible in the tab strip. Its content is reloaded the next time it is activated."},
|
||||
"autoDiscardable": {"type": "boolean", "description": "Whether the tab can be discarded automatically by the browser when resources are low."},
|
||||
"mutedInfo": {"$ref": "MutedInfo", "optional": true, "description": "The tab's muted state and the reason for the last state change."},
|
||||
"url": {"type": "string", "optional": true, "description": "The last committed URL of the main frame of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and may be an empty string if the tab has not yet committed. See also $(ref:Tab.pendingUrl)."},
|
||||
"pendingUrl": {"type": "string", "optional": true, "description": "The URL the tab is navigating to, before it has committed. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and there is a pending navigation."},
|
||||
"title": {"type": "string", "optional": true, "description": "The title of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission."},
|
||||
"favIconUrl": {"type": "string", "optional": true, "description": "The URL of the tab's favicon. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission. It may also be an empty string if the tab is loading."},
|
||||
"status": {"type": "string", "optional": true, "description": "Either <em>loading</em> or <em>complete</em>."},
|
||||
"incognito": {"type": "boolean", "description": "Whether the tab is in an incognito window."},
|
||||
"width": {"type": "integer", "optional": true, "description": "The width of the tab in pixels."},
|
||||
"height": {"type": "integer", "optional": true, "description": "The height of the tab in pixels."},
|
||||
"sessionId": {"type": "string", "optional": true, "description": "The session ID used to uniquely identify a tab obtained from the $(ref:sessions) API."}
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"minimum": -1,
|
||||
"optional": true,
|
||||
"description": "The ID of the tab. Tab IDs are unique within a browser session. Under some circumstances a tab may not be assigned an ID; for example, when querying foreign tabs using the $(ref:sessions) API, in which case a session ID may be present. Tab ID can also be set to <code>chrome.tabs.TAB_ID_NONE</code> for apps and devtools windows."
|
||||
},
|
||||
"index": {
|
||||
"type": "integer",
|
||||
"minimum": -1,
|
||||
"description": "The zero-based index of the tab within its window."
|
||||
},
|
||||
"groupId": {
|
||||
"type": "integer",
|
||||
"minimum": -1,
|
||||
"description": "The ID of the group that the tab belongs to."
|
||||
},
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The ID of the window that contains the tab."
|
||||
},
|
||||
"openerTabId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"optional": true,
|
||||
"description": "The ID of the tab that opened this tab, if any. This property is only present if the opener tab still exists."
|
||||
},
|
||||
"selected": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the tab is selected.",
|
||||
"deprecated": "Please use $(ref:tabs.Tab.highlighted)."
|
||||
},
|
||||
"highlighted": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the tab is highlighted."
|
||||
},
|
||||
"active": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the tab is active in its window. Does not necessarily mean the window is focused."
|
||||
},
|
||||
"pinned": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the tab is pinned."
|
||||
},
|
||||
"audible": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tab has produced sound over the past couple of seconds (but it might not be heard if also muted). Equivalent to whether the 'speaker audio' indicator is showing."
|
||||
},
|
||||
"discarded": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory, but is still visible in the tab strip. Its content is reloaded the next time it is activated."
|
||||
},
|
||||
"autoDiscardable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the tab can be discarded automatically by the browser when resources are low."
|
||||
},
|
||||
"mutedInfo": {
|
||||
"$ref": "MutedInfo",
|
||||
"optional": true,
|
||||
"description": "The tab's muted state and the reason for the last state change."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The last committed URL of the main frame of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and may be an empty string if the tab has not yet committed. See also $(ref:Tab.pendingUrl)."
|
||||
},
|
||||
"pendingUrl": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The URL the tab is navigating to, before it has committed. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and there is a pending navigation."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The title of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission."
|
||||
},
|
||||
"favIconUrl": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The URL of the tab's favicon. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission. It may also be an empty string if the tab is loading."
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "Either <em>loading</em> or <em>complete</em>."
|
||||
},
|
||||
"incognito": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the tab is in an incognito window."
|
||||
},
|
||||
"width": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "The width of the tab in pixels."
|
||||
},
|
||||
"height": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "The height of the tab in pixels."
|
||||
},
|
||||
"sessionId": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The session ID used to uniquely identify a tab obtained from the $(ref:sessions) API."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -117,6 +220,18 @@
|
||||
"description": "Used to return the default zoom level for the current tab in calls to tabs.getZoomSettings."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "WindowType",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"normal",
|
||||
"popup",
|
||||
"panel",
|
||||
"app",
|
||||
"devtools"
|
||||
],
|
||||
"description": "The type of window."
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
@@ -125,7 +240,13 @@
|
||||
"type": "function",
|
||||
"description": "Reload a tab.",
|
||||
"parameters": [
|
||||
{"type": "integer", "name": "tabId", "minimum": 0, "optional": true, "description": "The ID of the tab to reload; defaults to the selected tab of the current window."},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0,
|
||||
"optional": true,
|
||||
"description": "The ID of the tab to reload; defaults to the selected tab of the current window."
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "reloadProperties",
|
||||
@@ -134,12 +255,16 @@
|
||||
"bypassCache": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether using any local cache. Default is false."
|
||||
"description": "Whether to bypass local caching. Defaults to <code>false</code>."
|
||||
}
|
||||
}
|
||||
},
|
||||
{"type": "function", "name": "callback", "optional": true, "parameters": []}
|
||||
]
|
||||
}
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get",
|
||||
@@ -150,15 +275,17 @@
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{"name": "tab", "$ref": "Tab"}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tab",
|
||||
"$ref": "Tab"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "connect",
|
||||
@@ -175,12 +302,21 @@
|
||||
"type": "object",
|
||||
"name": "connectInfo",
|
||||
"properties": {
|
||||
"name": { "type": "string", "optional": true, "description": "Is passed into onConnect for content scripts that are listening for the connection event." },
|
||||
"name": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "Is passed into onConnect for content scripts that are listening for the connection event."
|
||||
},
|
||||
"frameId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"minimum": 0,
|
||||
"description": "Open a port to a specific <a href='webNavigation#frame_ids'>frame</a> identified by <code>frameId</code> instead of all frames in the tab."
|
||||
},
|
||||
"documentId": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "Open a port to a specific <a href='webNavigation#document_ids'>document</a> identified by <code>documentId</code> instead of all frames in the tab."
|
||||
}
|
||||
},
|
||||
"optional": true
|
||||
@@ -193,7 +329,9 @@
|
||||
},
|
||||
{
|
||||
"name": "executeScript",
|
||||
"deprecated": "Replaced by $(ref:scripting.executeScript) in Manifest V3.",
|
||||
"type": "function",
|
||||
"description": "Injects JavaScript code into a page. For details, see the <a href='content_scripts#pi'>programmatic injection</a> section of the content scripts doc.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
@@ -206,26 +344,25 @@
|
||||
"$ref": "extensionTypes.InjectDetails",
|
||||
"name": "details",
|
||||
"description": "Details of the script to run. Either the code or the file property must be set, but both may not be set at the same time."
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"description": "Called after all the JavaScript has been executed.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "result",
|
||||
"optional": true,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "any",
|
||||
"minimum": 0
|
||||
},
|
||||
"description": "The result of the script in every injected frame."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"description": "Called after all the JavaScript has been executed.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "result",
|
||||
"optional": true,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "any",
|
||||
"minimum": 0
|
||||
},
|
||||
"description": "The result of the script in every injected frame."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sendMessage",
|
||||
@@ -252,23 +389,27 @@
|
||||
"optional": true,
|
||||
"minimum": 0,
|
||||
"description": "Send a message to a specific <a href='webNavigation#frame_ids'>frame</a> identified by <code>frameId</code> instead of all frames in the tab."
|
||||
},
|
||||
"documentId": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "Send a message to a specific <a href='webNavigation#document_ids'>document</a> identified by <code>documentId</code> instead of all frames in the tab."
|
||||
}
|
||||
},
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "responseCallback",
|
||||
"optional": true,
|
||||
"parameters": [
|
||||
{
|
||||
"name": "response",
|
||||
"type": "any",
|
||||
"description": "The JSON response object sent by the handler of the message. If an error occurs while connecting to the specified tab, the callback is called with no arguments and $(ref:runtime.lastError) is set to the error message."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"parameters": [
|
||||
{
|
||||
"name": "response",
|
||||
"type": "any",
|
||||
"description": "The JSON response object sent by the handler of the message. If an error occurs while connecting to the specified tab, the callback is called with no arguments and $(ref:runtime.lastError) is set to the error message."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "setZoom",
|
||||
@@ -286,15 +427,14 @@
|
||||
"type": "number",
|
||||
"name": "zoomFactor",
|
||||
"description": "The new zoom factor. A value of <code>0</code> sets the tab to its current default zoom factor. Values greater than <code>0</code> specify a (possibly non-default) zoom factor for the tab."
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"description": "Called after the zoom factor has been changed.",
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"description": "Called after the zoom factor has been changed.",
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "getZoom",
|
||||
@@ -307,20 +447,19 @@
|
||||
"minimum": 0,
|
||||
"optional": true,
|
||||
"description": "The ID of the tab to get the current zoom factor from; defaults to the active tab of the current window."
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"description": "Called with the tab's current zoom factor after it has been fetched.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "number",
|
||||
"name": "zoomFactor",
|
||||
"description": "The tab's current zoom factor."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"description": "Called with the tab's current zoom factor after it has been fetched.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "number",
|
||||
"name": "zoomFactor",
|
||||
"description": "The tab's current zoom factor."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "setZoomSettings",
|
||||
@@ -338,15 +477,14 @@
|
||||
"$ref": "ZoomSettings",
|
||||
"name": "zoomSettings",
|
||||
"description": "Defines how zoom changes are handled and at what scope."
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"description": "Called after the zoom settings are changed.",
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"description": "Called after the zoom settings are changed.",
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "getZoomSettings",
|
||||
@@ -359,20 +497,137 @@
|
||||
"optional": true,
|
||||
"minimum": 0,
|
||||
"description": "The ID of the tab to get the current zoom settings from; defaults to the active tab of the current window."
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"description": "Called with the tab's current zoom settings.",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "ZoomSettings",
|
||||
"name": "zoomSettings",
|
||||
"description": "The tab's current zoom settings."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"description": "Called with the tab's current zoom settings.",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "ZoomSettings",
|
||||
"name": "zoomSettings",
|
||||
"description": "The tab's current zoom settings."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "query",
|
||||
"type": "function",
|
||||
"description": "Gets all tabs that have the specified properties, or all tabs if no properties are specified.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "object",
|
||||
"name": "queryInfo",
|
||||
"properties": {
|
||||
"active": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are active in their windows."
|
||||
},
|
||||
"pinned": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are pinned."
|
||||
},
|
||||
"audible": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are audible."
|
||||
},
|
||||
"muted": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are muted."
|
||||
},
|
||||
"highlighted": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are highlighted."
|
||||
},
|
||||
"discarded": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are discarded. A discarded tab is one whose content has been unloaded from memory, but is still visible in the tab strip. Its content is reloaded the next time it is activated."
|
||||
},
|
||||
"autoDiscardable": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs can be discarded automatically by the browser when resources are low."
|
||||
},
|
||||
"currentWindow": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are in the <a href='windows#current-window'>current window</a>."
|
||||
},
|
||||
"lastFocusedWindow": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether the tabs are in the last focused window."
|
||||
},
|
||||
"status": {
|
||||
"$ref": "TabStatus",
|
||||
"optional": true,
|
||||
"description": "The tab loading status."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "Match page titles against a pattern. This property is ignored if the extension does not have the <code>\"tabs\"</code> permission."
|
||||
},
|
||||
"url": {
|
||||
"choices": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"optional": true,
|
||||
"description": "Match tabs against one or more <a href='match_patterns'>URL patterns</a>. Fragment identifiers are not matched. This property is ignored if the extension does not have the <code>\"tabs\"</code> permission."
|
||||
},
|
||||
"groupId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"minimum": -1,
|
||||
"description": "The ID of the group that the tabs are in, or $(ref:tabGroups.TAB_GROUP_ID_NONE) for ungrouped tabs."
|
||||
},
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"minimum": -2,
|
||||
"description": "The ID of the parent window, or $(ref:windows.WINDOW_ID_CURRENT) for the <a href='windows#current-window'>current window</a>."
|
||||
},
|
||||
"windowType": {
|
||||
"$ref": "WindowType",
|
||||
"optional": true,
|
||||
"description": "The type of window the tabs are in."
|
||||
},
|
||||
"index": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"minimum": 0,
|
||||
"description": "The position of the tabs within their windows."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns_async": {
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "result",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "Tab"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "update",
|
||||
@@ -454,17 +709,28 @@
|
||||
"name": "onZoomChange",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is zoomed.",
|
||||
"parameters": [{
|
||||
"type": "object",
|
||||
"name": "ZoomChangeInfo",
|
||||
"properties": {
|
||||
"tabId": {"type": "integer", "minimum": 0},
|
||||
"oldZoomFactor": {"type": "number"},
|
||||
"newZoomFactor": {"type": "number"},
|
||||
"zoomSettings": {"$ref": "ZoomSettings"}
|
||||
"parameters": [
|
||||
{
|
||||
"type": "object",
|
||||
"name": "ZoomChangeInfo",
|
||||
"properties": {
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"oldZoomFactor": {
|
||||
"type": "number"
|
||||
},
|
||||
"newZoomFactor": {
|
||||
"type": "number"
|
||||
},
|
||||
"zoomSettings": {
|
||||
"$ref": "ZoomSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/containers/span.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/common/extensions/chrome_manifest_url_handlers.h"
|
||||
#include "chrome/common/extensions/manifest_handlers/minimum_chrome_version_checker.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/shell/common/extensions/api/generated_schemas.h"
|
||||
#include "extensions/common/alias.h"
|
||||
@@ -38,6 +39,8 @@ constexpr APIPermissionInfo::InitInfo permissions_to_register[] = {
|
||||
{mojom::APIPermissionID::kPdfViewerPrivate, "pdfViewerPrivate"},
|
||||
#endif
|
||||
{mojom::APIPermissionID::kManagement, "management"},
|
||||
{mojom::APIPermissionID::kTab, "tabs",
|
||||
APIPermissionInfo::kFlagRequiresManagementUIWarning},
|
||||
};
|
||||
base::span<const APIPermissionInfo::InitInfo> GetPermissionInfos() {
|
||||
return base::make_span(permissions_to_register);
|
||||
@@ -99,6 +102,8 @@ void ElectronExtensionsAPIProvider::RegisterManifestHandlers() {
|
||||
extensions::ManifestHandlerRegistry::Get();
|
||||
registry->RegisterHandler(
|
||||
std::make_unique<extensions::DevToolsPageHandler>());
|
||||
registry->RegisterHandler(
|
||||
std::make_unique<extensions::MinimumChromeVersionChecker>());
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -229,21 +229,34 @@ void ErrorMessageListener(v8::Local<v8::Message> message,
|
||||
}
|
||||
}
|
||||
|
||||
// Only allow DebugOptions in non-ELECTRON_RUN_AS_NODE mode.
|
||||
// Only allow a specific subset of options in non-ELECTRON_RUN_AS_NODE mode.
|
||||
// If node CLI inspect support is disabled, allow no debug options.
|
||||
bool IsAllowedDebugOption(base::StringPiece option) {
|
||||
bool IsAllowedOption(base::StringPiece option) {
|
||||
static constexpr auto debug_options =
|
||||
base::MakeFixedFlatSet<base::StringPiece>({
|
||||
"--debug",
|
||||
"--debug-brk",
|
||||
"--debug-port",
|
||||
"--inspect",
|
||||
"--inspect-brk",
|
||||
"--inspect-brk-node",
|
||||
"--inspect-port",
|
||||
"--inspect-publish-uid",
|
||||
});
|
||||
|
||||
// This should be aligned with what's possible to set via the process object.
|
||||
static constexpr auto options = base::MakeFixedFlatSet<base::StringPiece>({
|
||||
"--debug",
|
||||
"--debug-brk",
|
||||
"--debug-port",
|
||||
"--inspect",
|
||||
"--inspect-brk",
|
||||
"--inspect-brk-node",
|
||||
"--inspect-port",
|
||||
"--inspect-publish-uid",
|
||||
"--trace-warnings",
|
||||
"--trace-deprecation",
|
||||
"--throw-deprecation",
|
||||
"--no-deprecation",
|
||||
"--dns-result-order",
|
||||
});
|
||||
|
||||
return electron::fuses::IsNodeCliInspectEnabled() && options.contains(option);
|
||||
if (debug_options.contains(option))
|
||||
return electron::fuses::IsNodeCliInspectEnabled();
|
||||
|
||||
return options.contains(option);
|
||||
}
|
||||
|
||||
// Initialize NODE_OPTIONS to pass to Node.js
|
||||
@@ -378,7 +391,7 @@ bool NodeBindings::IsInitialized() {
|
||||
|
||||
// Initialize Node.js cli options to pass to Node.js
|
||||
// See https://nodejs.org/api/cli.html#cli_options
|
||||
void NodeBindings::SetNodeCliFlags() {
|
||||
std::vector<std::string> NodeBindings::ParseNodeCliFlags() {
|
||||
const auto argv = base::CommandLine::ForCurrentProcess()->argv();
|
||||
std::vector<std::string> args;
|
||||
|
||||
@@ -395,9 +408,8 @@ void NodeBindings::SetNodeCliFlags() {
|
||||
const auto& option = arg;
|
||||
#endif
|
||||
const auto stripped = base::StringPiece(option).substr(0, option.find('='));
|
||||
|
||||
// Only allow in no-op (--) option or DebugOptions
|
||||
if (IsAllowedDebugOption(stripped) || stripped == "--")
|
||||
// Only allow no-op or a small set of debug/trace related options.
|
||||
if (IsAllowedOption(stripped) || stripped == "--")
|
||||
args.push_back(option);
|
||||
}
|
||||
|
||||
@@ -408,16 +420,7 @@ void NodeBindings::SetNodeCliFlags() {
|
||||
args.push_back("--no-experimental-fetch");
|
||||
}
|
||||
|
||||
std::vector<std::string> errors;
|
||||
const int exit_code = ProcessGlobalArgs(&args, nullptr, &errors,
|
||||
node::kDisallowedInEnvironment);
|
||||
|
||||
const std::string err_str = "Error parsing Node.js cli flags ";
|
||||
if (exit_code != 0) {
|
||||
LOG(ERROR) << err_str;
|
||||
} else if (!errors.empty()) {
|
||||
LOG(ERROR) << err_str << base::JoinString(errors, " ");
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
void NodeBindings::Initialize(v8::Local<v8::Context> context) {
|
||||
@@ -433,13 +436,11 @@ void NodeBindings::Initialize(v8::Local<v8::Context> context) {
|
||||
// Explicitly register electron's builtin bindings.
|
||||
RegisterBuiltinBindings();
|
||||
|
||||
// Parse and set Node.js cli flags.
|
||||
SetNodeCliFlags();
|
||||
|
||||
auto env = base::Environment::Create();
|
||||
SetNodeOptions(env.get());
|
||||
|
||||
std::vector<std::string> argv = {"electron"};
|
||||
// Parse and set Node.js cli flags.
|
||||
std::vector<std::string> argv = ParseNodeCliFlags();
|
||||
std::vector<std::string> exec_argv;
|
||||
std::vector<std::string> errors;
|
||||
uint64_t process_flags = node::ProcessFlags::kNoFlags;
|
||||
|
||||
@@ -89,7 +89,7 @@ class NodeBindings {
|
||||
// Setup V8, libuv.
|
||||
void Initialize(v8::Local<v8::Context> context);
|
||||
|
||||
void SetNodeCliFlags();
|
||||
std::vector<std::string> ParseNodeCliFlags();
|
||||
|
||||
// Create the environment and load node.js.
|
||||
node::Environment* CreateEnvironment(v8::Handle<v8::Context> context,
|
||||
|
||||
@@ -1284,6 +1284,8 @@ describe('BrowserWindow module', () => {
|
||||
});
|
||||
|
||||
describe('BrowserWindow.moveTop()', () => {
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
it('should not steal focus', async () => {
|
||||
const posDelta = 50;
|
||||
const wShownInactive = once(w, 'show');
|
||||
@@ -1325,6 +1327,15 @@ describe('BrowserWindow module', () => {
|
||||
await closeWindow(otherWindow, { assertNotWindows: false });
|
||||
expect(BrowserWindow.getAllWindows()).to.have.lengthOf(1);
|
||||
});
|
||||
|
||||
it('should not crash when called on a modal child window', async () => {
|
||||
const shown = once(w, 'show');
|
||||
w.show();
|
||||
await shown;
|
||||
|
||||
const child = new BrowserWindow({ modal: true, parent: w });
|
||||
expect(() => { child.moveTop(); }).to.not.throw();
|
||||
});
|
||||
});
|
||||
|
||||
describe('BrowserWindow.moveAbove(mediaSourceId)', () => {
|
||||
|
||||
@@ -16,6 +16,11 @@ ifdescribe(process.platform !== 'win32' || process.arch !== 'arm64')('clipboard
|
||||
const readImage = clipboard.readImage();
|
||||
expect(readImage.toDataURL()).to.equal(i.toDataURL());
|
||||
});
|
||||
|
||||
it('works for empty image', () => {
|
||||
clipboard.writeText('Not an Image');
|
||||
expect(clipboard.readImage().isEmpty()).to.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
describe('clipboard.readText()', () => {
|
||||
|
||||
@@ -283,6 +283,29 @@ describe('setDisplayMediaRequestHandler', () => {
|
||||
expect(ok).to.be.true(message);
|
||||
});
|
||||
|
||||
it('returns a MediaStream with BrowserCaptureMediaStreamTrack when the current tab is selected', async () => {
|
||||
const ses = session.fromPartition('' + Math.random());
|
||||
let requestHandlerCalled = false;
|
||||
ses.setDisplayMediaRequestHandler((request, callback) => {
|
||||
requestHandlerCalled = true;
|
||||
callback({ video: w.webContents.mainFrame });
|
||||
});
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { session: ses } });
|
||||
await w.loadURL(serverUrl);
|
||||
const { ok, message } = await w.webContents.executeJavaScript(`
|
||||
navigator.mediaDevices.getDisplayMedia({
|
||||
preferCurrentTab: true,
|
||||
video: true,
|
||||
audio: false,
|
||||
}).then(stream => {
|
||||
const [videoTrack] = stream.getVideoTracks();
|
||||
return { ok: videoTrack instanceof BrowserCaptureMediaStreamTrack, message: null };
|
||||
}, e => ({ok: false, message: e.message}))
|
||||
`, true);
|
||||
expect(requestHandlerCalled).to.be.true();
|
||||
expect(ok).to.be.true(message);
|
||||
});
|
||||
|
||||
ifit(!(process.platform === 'darwin' && process.arch === 'x64'))('can supply a screen response to preferCurrentTab', async () => {
|
||||
const ses = session.fromPartition('' + Math.random());
|
||||
let requestHandlerCalled = false;
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import { setTimeout } from 'timers/promises';
|
||||
|
||||
import { expectDeprecationMessages } from './lib/deprecate-helpers';
|
||||
import { ifdescribe } from './lib/spec-helpers';
|
||||
import { closeAllWindows } from './lib/window-helpers';
|
||||
|
||||
@@ -61,11 +62,16 @@ describe('nativeTheme module', () => {
|
||||
});
|
||||
|
||||
ifdescribe(process.platform === 'darwin' && semver.gte(os.release(), '18.0.0'))('on macOS 10.14', () => {
|
||||
it('should update appLevelAppearance when set', () => {
|
||||
nativeTheme.themeSource = 'dark';
|
||||
expect(systemPreferences.appLevelAppearance).to.equal('dark');
|
||||
nativeTheme.themeSource = 'light';
|
||||
expect(systemPreferences.appLevelAppearance).to.equal('light');
|
||||
it('should update appLevelAppearance when set', async () => {
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
nativeTheme.themeSource = 'dark';
|
||||
expect(systemPreferences.appLevelAppearance).to.equal('dark');
|
||||
nativeTheme.themeSource = 'light';
|
||||
expect(systemPreferences.appLevelAppearance).to.equal('light');
|
||||
},
|
||||
"(electron) 'appLevelAppearance' is deprecated and will be removed."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { expect } from 'chai';
|
||||
import { systemPreferences } from 'electron/main';
|
||||
import { expectDeprecationMessages } from './lib/deprecate-helpers';
|
||||
import { ifdescribe } from './lib/spec-helpers';
|
||||
|
||||
describe('systemPreferences module', () => {
|
||||
@@ -174,9 +175,8 @@ describe('systemPreferences module', () => {
|
||||
}).to.throw(`Unknown color: ${color}`);
|
||||
});
|
||||
|
||||
it('returns a valid color', () => {
|
||||
it('returns a valid color', async () => {
|
||||
const colors = [
|
||||
'alternate-selected-control-text',
|
||||
'control-background',
|
||||
'control',
|
||||
'control-text',
|
||||
@@ -209,12 +209,20 @@ describe('systemPreferences module', () => {
|
||||
'unemphasized-selected-text',
|
||||
'window-background',
|
||||
'window-frame-text'
|
||||
];
|
||||
] as const;
|
||||
|
||||
colors.forEach(color => {
|
||||
const sysColor = systemPreferences.getColor(color as any);
|
||||
const sysColor = systemPreferences.getColor(color);
|
||||
expect(sysColor).to.be.a('string');
|
||||
});
|
||||
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
const sysColor = systemPreferences.getColor('alternate-selected-control-text');
|
||||
expect(sysColor).to.be.a('string');
|
||||
},
|
||||
"'alternate-selected-control-text' is deprecated as an input to getColor. Use 'selected-content-background' instead."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -233,15 +241,25 @@ describe('systemPreferences module', () => {
|
||||
});
|
||||
|
||||
describe('with functions', () => {
|
||||
it('returns a valid appearance', () => {
|
||||
const appearance = systemPreferences.getAppLevelAppearance();
|
||||
expect(options).to.include(appearance);
|
||||
it('returns a valid appearance', async () => {
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
const appearance = systemPreferences.getAppLevelAppearance();
|
||||
expect(options).to.include(appearance);
|
||||
},
|
||||
"(electron) 'getAppLevelAppearance function' is deprecated and will be removed."
|
||||
);
|
||||
});
|
||||
|
||||
it('can be changed', () => {
|
||||
systemPreferences.setAppLevelAppearance('dark');
|
||||
const appearance = systemPreferences.getAppLevelAppearance();
|
||||
expect(appearance).to.eql('dark');
|
||||
it('can be changed', async () => {
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
systemPreferences.setAppLevelAppearance('dark');
|
||||
const appearance = systemPreferences.getAppLevelAppearance();
|
||||
expect(appearance).to.eql('dark');
|
||||
},
|
||||
"(electron) 'setAppLevelAppearance function' is deprecated and will be removed."
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -257,6 +257,30 @@ describe('utilityProcess module', () => {
|
||||
child.stdout!.on('data', listener);
|
||||
});
|
||||
|
||||
it('supports changing dns verbatim with --dns-result-order', (done) => {
|
||||
const child = utilityProcess.fork(path.join(fixturesPath, 'dns-result-order.js'), [], {
|
||||
stdio: 'pipe',
|
||||
execArgv: ['--dns-result-order=ipv4first']
|
||||
});
|
||||
|
||||
let output = '';
|
||||
const cleanup = () => {
|
||||
child.stderr!.removeListener('data', listener);
|
||||
child.stdout!.removeListener('data', listener);
|
||||
child.once('exit', () => { done(); });
|
||||
child.kill();
|
||||
};
|
||||
|
||||
const listener = (data: Buffer) => {
|
||||
output += data;
|
||||
expect(output.trim()).to.contain('ipv4first', 'default verbatim should be ipv4first');
|
||||
cleanup();
|
||||
};
|
||||
|
||||
child.stderr!.on('data', listener);
|
||||
child.stdout!.on('data', listener);
|
||||
});
|
||||
|
||||
ifit(process.platform !== 'win32')('supports redirecting stdout to parent process', async () => {
|
||||
const result = 'Output from utility process';
|
||||
const appProcess = childProcess.spawn(process.execPath, [path.join(fixturesPath, 'inherit-stdout'), `--payload=${result}`]);
|
||||
|
||||
@@ -2028,10 +2028,32 @@ describe('chromium features', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('chrome://accessibility', () => {
|
||||
it('loads the page successfully', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadURL('chrome://accessibility');
|
||||
const pageExists = await w.webContents.executeJavaScript(
|
||||
"window.hasOwnProperty('chrome') && window.chrome.hasOwnProperty('send')"
|
||||
);
|
||||
expect(pageExists).to.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
describe('chrome://gpu', () => {
|
||||
it('loads the page successfully', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
await w.loadURL('chrome://gpu');
|
||||
const pageExists = await w.webContents.executeJavaScript(
|
||||
"window.hasOwnProperty('chrome') && window.chrome.hasOwnProperty('send')"
|
||||
);
|
||||
expect(pageExists).to.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
describe('chrome://media-internals', () => {
|
||||
it('loads the page successfully', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
w.loadURL('chrome://media-internals');
|
||||
await w.loadURL('chrome://media-internals');
|
||||
const pageExists = await w.webContents.executeJavaScript(
|
||||
"window.hasOwnProperty('chrome') && window.chrome.hasOwnProperty('send')"
|
||||
);
|
||||
@@ -2042,7 +2064,7 @@ describe('chromium features', () => {
|
||||
describe('chrome://webrtc-internals', () => {
|
||||
it('loads the page successfully', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
w.loadURL('chrome://webrtc-internals');
|
||||
await w.loadURL('chrome://webrtc-internals');
|
||||
const pageExists = await w.webContents.executeJavaScript(
|
||||
"window.hasOwnProperty('chrome') && window.chrome.hasOwnProperty('send')"
|
||||
);
|
||||
|
||||
@@ -69,6 +69,25 @@ describe('chrome extensions', () => {
|
||||
`)).to.eventually.have.property('id');
|
||||
});
|
||||
|
||||
it('supports minimum_chrome_version manifest key', async () => {
|
||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
session: customSession,
|
||||
sandbox: true
|
||||
}
|
||||
});
|
||||
|
||||
await w.loadURL('about:blank');
|
||||
|
||||
const extPath = path.join(fixtures, 'extensions', 'chrome-too-low-version');
|
||||
const load = customSession.loadExtension(extPath);
|
||||
await expect(load).to.eventually.be.rejectedWith(
|
||||
`Loading extension at ${extPath} failed with: This extension requires Chromium version 999 or greater.`
|
||||
);
|
||||
});
|
||||
|
||||
it('can open WebSQLDatabase in a background page', async () => {
|
||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, sandbox: true } });
|
||||
@@ -354,7 +373,7 @@ describe('chrome extensions', () => {
|
||||
const message = { method: 'executeScript', args: ['1 + 2'] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
const [, , responseString] = await once(w.webContents, 'console-message');
|
||||
const response = JSON.parse(responseString);
|
||||
|
||||
expect(response).to.equal(3);
|
||||
@@ -816,5 +835,238 @@ describe('chrome extensions', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('chrome.tabs', () => {
|
||||
let customSession: Session;
|
||||
let w = null as unknown as BrowserWindow;
|
||||
|
||||
before(async () => {
|
||||
customSession = session.fromPartition(`persist:${uuid.v4()}`);
|
||||
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-tabs', 'api-async'));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
session: customSession
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
it('getZoom', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'getZoom' };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.equal(1);
|
||||
});
|
||||
|
||||
it('setZoom', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'setZoom', args: [2] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.deep.equal(2);
|
||||
});
|
||||
|
||||
it('getZoomSettings', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'getZoomSettings' };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.deep.equal({
|
||||
defaultZoomFactor: 1,
|
||||
mode: 'automatic',
|
||||
scope: 'per-origin'
|
||||
});
|
||||
});
|
||||
|
||||
it('setZoomSettings', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'setZoomSettings', args: [{ mode: 'disabled' }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.deep.equal({
|
||||
defaultZoomFactor: 1,
|
||||
mode: 'disabled',
|
||||
scope: 'per-tab'
|
||||
});
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('returns tab properties', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'get' };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.have.property('url').that.is.a('string');
|
||||
expect(response).to.have.property('title').that.is.a('string');
|
||||
expect(response).to.have.property('active').that.is.a('boolean');
|
||||
expect(response).to.have.property('autoDiscardable').that.is.a('boolean');
|
||||
expect(response).to.have.property('discarded').that.is.a('boolean');
|
||||
expect(response).to.have.property('groupId').that.is.a('number');
|
||||
expect(response).to.have.property('highlighted').that.is.a('boolean');
|
||||
expect(response).to.have.property('id').that.is.a('number');
|
||||
expect(response).to.have.property('incognito').that.is.a('boolean');
|
||||
expect(response).to.have.property('index').that.is.a('number');
|
||||
expect(response).to.have.property('pinned').that.is.a('boolean');
|
||||
expect(response).to.have.property('selected').that.is.a('boolean');
|
||||
expect(response).to.have.property('windowId').that.is.a('number');
|
||||
});
|
||||
|
||||
it('does not return privileged properties without tabs permission', async () => {
|
||||
const noPrivilegeSes = session.fromPartition(`persist:${uuid.v4()}`);
|
||||
await noPrivilegeSes.loadExtension(path.join(fixtures, 'extensions', 'chrome-tabs', 'no-privileges'));
|
||||
|
||||
w = new BrowserWindow({ show: false, webPreferences: { session: noPrivilegeSes } });
|
||||
await w.loadURL(url);
|
||||
|
||||
w.webContents.executeJavaScript('window.postMessage(\'{}\', \'*\')');
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).not.to.have.property('url');
|
||||
expect(response).not.to.have.property('title');
|
||||
expect(response).to.have.property('active').that.is.a('boolean');
|
||||
expect(response).to.have.property('autoDiscardable').that.is.a('boolean');
|
||||
expect(response).to.have.property('discarded').that.is.a('boolean');
|
||||
expect(response).to.have.property('groupId').that.is.a('number');
|
||||
expect(response).to.have.property('highlighted').that.is.a('boolean');
|
||||
expect(response).to.have.property('id').that.is.a('number');
|
||||
expect(response).to.have.property('incognito').that.is.a('boolean');
|
||||
expect(response).to.have.property('index').that.is.a('number');
|
||||
expect(response).to.have.property('pinned').that.is.a('boolean');
|
||||
expect(response).to.have.property('selected').that.is.a('boolean');
|
||||
expect(response).to.have.property('windowId').that.is.a('number');
|
||||
});
|
||||
});
|
||||
|
||||
it('reload', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'reload' };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const consoleMessage = once(w.webContents, 'console-message');
|
||||
const finish = once(w.webContents, 'did-finish-load');
|
||||
|
||||
await Promise.all([consoleMessage, finish]).then(([[,, responseString]]) => {
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response.status).to.equal('reloaded');
|
||||
});
|
||||
});
|
||||
|
||||
it('update', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'update', args: [{ muted: true }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
const response = JSON.parse(responseString);
|
||||
|
||||
expect(response).to.have.property('url').that.is.a('string');
|
||||
expect(response).to.have.property('title').that.is.a('string');
|
||||
expect(response).to.have.property('active').that.is.a('boolean');
|
||||
expect(response).to.have.property('autoDiscardable').that.is.a('boolean');
|
||||
expect(response).to.have.property('discarded').that.is.a('boolean');
|
||||
expect(response).to.have.property('groupId').that.is.a('number');
|
||||
expect(response).to.have.property('highlighted').that.is.a('boolean');
|
||||
expect(response).to.have.property('id').that.is.a('number');
|
||||
expect(response).to.have.property('incognito').that.is.a('boolean');
|
||||
expect(response).to.have.property('index').that.is.a('number');
|
||||
expect(response).to.have.property('pinned').that.is.a('boolean');
|
||||
expect(response).to.have.property('selected').that.is.a('boolean');
|
||||
expect(response).to.have.property('windowId').that.is.a('number');
|
||||
expect(response).to.have.property('mutedInfo').that.is.a('object');
|
||||
const { mutedInfo } = response;
|
||||
expect(mutedInfo).to.deep.eq({
|
||||
muted: true,
|
||||
reason: 'user'
|
||||
});
|
||||
});
|
||||
|
||||
describe('query', () => {
|
||||
it('can query for a tab with specific properties', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
expect(w.webContents.isAudioMuted()).to.be.false('muted');
|
||||
w.webContents.setAudioMuted(true);
|
||||
expect(w.webContents.isAudioMuted()).to.be.true('not muted');
|
||||
|
||||
const message = { method: 'query', args: [{ muted: true }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [, , responseString] = await once(w.webContents, 'console-message');
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.have.lengthOf(1);
|
||||
|
||||
const tab = response[0];
|
||||
expect(tab.mutedInfo).to.deep.equal({
|
||||
muted: true,
|
||||
reason: 'user'
|
||||
});
|
||||
});
|
||||
|
||||
it('only returns tabs in the same session', async () => {
|
||||
await w.loadURL(url);
|
||||
w.webContents.setAudioMuted(true);
|
||||
|
||||
const sameSessionWin = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
session: customSession
|
||||
}
|
||||
});
|
||||
|
||||
sameSessionWin.webContents.setAudioMuted(true);
|
||||
|
||||
const newSession = session.fromPartition(`persist:${uuid.v4()}`);
|
||||
const differentSessionWin = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
session: newSession
|
||||
}
|
||||
});
|
||||
|
||||
differentSessionWin.webContents.setAudioMuted(true);
|
||||
|
||||
const message = { method: 'query', args: [{ muted: true }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [, , responseString] = await once(w.webContents, 'console-message');
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.have.lengthOf(2);
|
||||
for (const tab of response) {
|
||||
expect(tab.mutedInfo).to.deep.equal({
|
||||
muted: true,
|
||||
reason: 'user'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
3
spec/fixtures/api/utility-process/dns-result-order.js
vendored
Normal file
3
spec/fixtures/api/utility-process/dns-result-order.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
const dns = require('node:dns');
|
||||
console.log(dns.getDefaultResultOrder());
|
||||
process.exit(0);
|
||||
1
spec/fixtures/extensions/chrome-api/main.js
vendored
1
spec/fixtures/extensions/chrome-api/main.js
vendored
@@ -49,4 +49,5 @@ const dispatchTest = (event) => {
|
||||
const { method, args = [] } = JSON.parse(event.data);
|
||||
testMap[method](...args);
|
||||
};
|
||||
|
||||
window.addEventListener('message', dispatchTest, false);
|
||||
|
||||
65
spec/fixtures/extensions/chrome-tabs/api-async/background.js
vendored
Normal file
65
spec/fixtures/extensions/chrome-tabs/api-async/background.js
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/* global chrome */
|
||||
|
||||
const handleRequest = (request, sender, sendResponse) => {
|
||||
const { method, args = [] } = request;
|
||||
const tabId = sender.tab.id;
|
||||
|
||||
switch (method) {
|
||||
case 'getZoom': {
|
||||
chrome.tabs.getZoom(tabId).then(sendResponse);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'setZoom': {
|
||||
const [zoom] = args;
|
||||
chrome.tabs.setZoom(tabId, zoom).then(async () => {
|
||||
const updatedZoom = await chrome.tabs.getZoom(tabId);
|
||||
sendResponse(updatedZoom);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'getZoomSettings': {
|
||||
chrome.tabs.getZoomSettings(tabId).then(sendResponse);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'setZoomSettings': {
|
||||
const [settings] = args;
|
||||
chrome.tabs.setZoomSettings(tabId, { mode: settings.mode }).then(async () => {
|
||||
const zoomSettings = await chrome.tabs.getZoomSettings(tabId);
|
||||
sendResponse(zoomSettings);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'get': {
|
||||
chrome.tabs.get(tabId).then(sendResponse);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'query': {
|
||||
const [params] = args;
|
||||
chrome.tabs.query(params).then(sendResponse);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'reload': {
|
||||
chrome.tabs.reload(tabId).then(() => {
|
||||
sendResponse({ status: 'reloaded' });
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'update': {
|
||||
const [params] = args;
|
||||
chrome.tabs.update(tabId, params).then(sendResponse);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
handleRequest(request, sender, sendResponse);
|
||||
return true;
|
||||
});
|
||||
55
spec/fixtures/extensions/chrome-tabs/api-async/main.js
vendored
Normal file
55
spec/fixtures/extensions/chrome-tabs/api-async/main.js
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/* global chrome */
|
||||
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
sendResponse(request);
|
||||
});
|
||||
|
||||
const testMap = {
|
||||
getZoomSettings () {
|
||||
chrome.runtime.sendMessage({ method: 'getZoomSettings' }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
setZoomSettings (settings) {
|
||||
chrome.runtime.sendMessage({ method: 'setZoomSettings', args: [settings] }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
query (params) {
|
||||
chrome.runtime.sendMessage({ method: 'query', args: [params] }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
getZoom () {
|
||||
chrome.runtime.sendMessage({ method: 'getZoom', args: [] }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
setZoom (zoom) {
|
||||
chrome.runtime.sendMessage({ method: 'setZoom', args: [zoom] }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
get () {
|
||||
chrome.runtime.sendMessage({ method: 'get' }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
reload () {
|
||||
chrome.runtime.sendMessage({ method: 'reload' }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
},
|
||||
update (params) {
|
||||
chrome.runtime.sendMessage({ method: 'update', args: [params] }, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const dispatchTest = (event) => {
|
||||
const { method, args = [] } = JSON.parse(event.data);
|
||||
testMap[method](...args);
|
||||
};
|
||||
|
||||
window.addEventListener('message', dispatchTest, false);
|
||||
16
spec/fixtures/extensions/chrome-tabs/api-async/manifest.json
vendored
Normal file
16
spec/fixtures/extensions/chrome-tabs/api-async/manifest.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "api-async",
|
||||
"version": "1.0",
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [ "<all_urls>"],
|
||||
"js": ["main.js"],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"permissions": ["tabs"],
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"manifest_version": 3
|
||||
}
|
||||
6
spec/fixtures/extensions/chrome-tabs/no-privileges/background.js
vendored
Normal file
6
spec/fixtures/extensions/chrome-tabs/no-privileges/background.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/* global chrome */
|
||||
|
||||
chrome.runtime.onMessage.addListener((_request, sender, sendResponse) => {
|
||||
chrome.tabs.get(sender.tab.id).then(sendResponse);
|
||||
return true;
|
||||
});
|
||||
11
spec/fixtures/extensions/chrome-tabs/no-privileges/main.js
vendored
Normal file
11
spec/fixtures/extensions/chrome-tabs/no-privileges/main.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/* global chrome */
|
||||
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
sendResponse(request);
|
||||
});
|
||||
|
||||
window.addEventListener('message', () => {
|
||||
chrome.runtime.sendMessage({}, response => {
|
||||
console.log(JSON.stringify(response));
|
||||
});
|
||||
}, false);
|
||||
19
spec/fixtures/extensions/chrome-tabs/no-privileges/manifest.json
vendored
Normal file
19
spec/fixtures/extensions/chrome-tabs/no-privileges/manifest.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "no-privileges",
|
||||
"version": "1.0",
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"<all_urls>"
|
||||
],
|
||||
"js": [
|
||||
"main.js"
|
||||
],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"manifest_version": 3
|
||||
}
|
||||
1
spec/fixtures/extensions/chrome-too-low-version/main.js
vendored
Normal file
1
spec/fixtures/extensions/chrome-too-low-version/main.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
document.documentElement.style.backgroundColor = 'blue';
|
||||
14
spec/fixtures/extensions/chrome-too-low-version/manifest.json
vendored
Normal file
14
spec/fixtures/extensions/chrome-too-low-version/manifest.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "chrome-too-low-version",
|
||||
"version": "1.0",
|
||||
"minimum_chrome_version": "999",
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["main.js"],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"permissions": ["storage"],
|
||||
"manifest_version": 3
|
||||
}
|
||||
@@ -14,6 +14,11 @@ process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
|
||||
|
||||
const { app, protocol } = require('electron');
|
||||
|
||||
// Some Linux machines have broken hardware acceleration support.
|
||||
if (process.env.ELECTRON_TEST_DISABLE_HARDWARE_ACCELERATION) {
|
||||
app.disableHardwareAcceleration();
|
||||
}
|
||||
|
||||
v8.setFlagsFromString('--expose_gc');
|
||||
app.commandLine.appendSwitch('js-flags', '--expose_gc');
|
||||
// Prevent the spec runner quitting when the first window closes
|
||||
@@ -69,6 +74,14 @@ app.whenReady().then(async () => {
|
||||
reporterEnabled: process.env.MOCHA_MULTI_REPORTERS
|
||||
};
|
||||
}
|
||||
// The MOCHA_GREP and MOCHA_INVERT are used in some vendor builds for sharding
|
||||
// tests.
|
||||
if (process.env.MOCHA_GREP) {
|
||||
mochaOptions.grep = process.env.MOCHA_GREP;
|
||||
}
|
||||
if (process.env.MOCHA_INVERT) {
|
||||
mochaOptions.invert = process.env.MOCHA_INVERT === 'true';
|
||||
}
|
||||
const mocha = new Mocha(mochaOptions);
|
||||
|
||||
// Add a root hook on mocha to skip any tests that are disabled
|
||||
|
||||
26
spec/lib/deprecate-helpers.ts
Normal file
26
spec/lib/deprecate-helpers.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { expect } from 'chai';
|
||||
|
||||
export async function expectDeprecationMessages (func: () => any, ...expected: string[]) {
|
||||
const messages: string[] = [];
|
||||
|
||||
const originalWarn = console.warn;
|
||||
console.warn = (message) => {
|
||||
messages.push(message);
|
||||
};
|
||||
|
||||
const warningListener = (error: Error) => {
|
||||
messages.push(error.message);
|
||||
};
|
||||
|
||||
process.on('warning', warningListener);
|
||||
|
||||
try {
|
||||
return await func();
|
||||
} finally {
|
||||
// process.emitWarning seems to need us to wait a tick
|
||||
await new Promise(process.nextTick);
|
||||
console.warn = originalWarn;
|
||||
process.off('warning', warningListener);
|
||||
expect(messages).to.deep.equal(expected);
|
||||
}
|
||||
}
|
||||
@@ -280,7 +280,9 @@ describe('<webview> tag', function () {
|
||||
w.webContents.session.removeExtension('foo');
|
||||
|
||||
const extensionPath = path.join(__dirname, 'fixtures', 'devtools-extensions', 'foo');
|
||||
await w.webContents.session.loadExtension(extensionPath);
|
||||
await w.webContents.session.loadExtension(extensionPath, {
|
||||
allowFileAccess: true
|
||||
});
|
||||
|
||||
w.loadFile(path.join(__dirname, 'fixtures', 'pages', 'webview-devtools.html'));
|
||||
loadWebView(w.webContents, {
|
||||
|
||||
Reference in New Issue
Block a user