mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
173 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4bd63b420 | ||
|
|
6acb443b91 | ||
|
|
d3e5b791a5 | ||
|
|
96bd258b0f | ||
|
|
23d0d409b4 | ||
|
|
ad94c7472e | ||
|
|
f3df14c7ae | ||
|
|
bd1c7487ba | ||
|
|
bc4d3dc578 | ||
|
|
05ef36db59 | ||
|
|
b852f1de13 | ||
|
|
3e36f7a245 | ||
|
|
d623e7cd44 | ||
|
|
42435fcad8 | ||
|
|
bd90898181 | ||
|
|
c20701b600 | ||
|
|
8272ea5b5f | ||
|
|
6317ef75a1 | ||
|
|
e5cb1872f5 | ||
|
|
25e3fadd56 | ||
|
|
6adf6b8b7d | ||
|
|
d67ff0fe0e | ||
|
|
49e63948b7 | ||
|
|
8dae8da778 | ||
|
|
b762563257 | ||
|
|
9ccf1b569b | ||
|
|
653bb602e2 | ||
|
|
94a5b304d0 | ||
|
|
a22384c9ff | ||
|
|
96eeddd46b | ||
|
|
7a776198db | ||
|
|
93a9512ce1 | ||
|
|
843dd5c33f | ||
|
|
b812e78f51 | ||
|
|
b080dab28c | ||
|
|
c451a90cfb | ||
|
|
b32ffe0ab2 | ||
|
|
adfc0f55bc | ||
|
|
6852bfb86e | ||
|
|
6d3e56d70f | ||
|
|
f70161856c | ||
|
|
736749522b | ||
|
|
9964e3f389 | ||
|
|
8c4c4fb4f0 | ||
|
|
0565d22597 | ||
|
|
87fd06bc96 | ||
|
|
4079d60021 | ||
|
|
6cc75d9f92 | ||
|
|
af5be47aa7 | ||
|
|
b2454eeb52 | ||
|
|
1ee98b4a73 | ||
|
|
e74a402976 | ||
|
|
8e5a88799c | ||
|
|
0b846b2f13 | ||
|
|
25539dcb73 | ||
|
|
2a4aaa9661 | ||
|
|
793da44151 | ||
|
|
4c28b23b06 | ||
|
|
952603d9ae | ||
|
|
32b45e7783 | ||
|
|
514c1e6d4b | ||
|
|
67b04b4040 | ||
|
|
415387cc2c | ||
|
|
0826770b20 | ||
|
|
c2e22abf08 | ||
|
|
9c28c8f637 | ||
|
|
478d405d42 | ||
|
|
0b616b3e2e | ||
|
|
49711d12f8 | ||
|
|
fe56f1dda6 | ||
|
|
f10c8e6dd5 | ||
|
|
27c1fc87e3 | ||
|
|
be08ff1665 | ||
|
|
547e50c699 | ||
|
|
a06170648c | ||
|
|
88fdf8ccf5 | ||
|
|
d12be5d392 | ||
|
|
e62cd6a5fa | ||
|
|
c412f7ddf1 | ||
|
|
0afec38c81 | ||
|
|
38f0a8e85b | ||
|
|
0aa7b7f712 | ||
|
|
23bd9166d7 | ||
|
|
c374f20fd1 | ||
|
|
b5839f42a2 | ||
|
|
2dcfefa577 | ||
|
|
b045ee77af | ||
|
|
32c2736c07 | ||
|
|
91d1bd651e | ||
|
|
c8177f8418 | ||
|
|
b8c086613f | ||
|
|
2e80a2e447 | ||
|
|
936a1659f6 | ||
|
|
d7289cbb55 | ||
|
|
aab0c66817 | ||
|
|
e671c2c053 | ||
|
|
c7778a8f2f | ||
|
|
c35803aee1 | ||
|
|
9f2fc5d72c | ||
|
|
a65fe57342 | ||
|
|
473219bfbe | ||
|
|
a8196fbc18 | ||
|
|
6b8ca86459 | ||
|
|
7290d77cdc | ||
|
|
426d45cd85 | ||
|
|
79298d37cd | ||
|
|
2a44b1a20f | ||
|
|
6f331e4f6a | ||
|
|
dc71541641 | ||
|
|
a4de4793dd | ||
|
|
f7509d590c | ||
|
|
42ab97f905 | ||
|
|
faf2871efe | ||
|
|
ea4e92f64d | ||
|
|
15d792aded | ||
|
|
70f05a1579 | ||
|
|
2d40fad79e | ||
|
|
edabc96e75 | ||
|
|
4a45196ff1 | ||
|
|
0bd661bd99 | ||
|
|
b9e709039e | ||
|
|
c63430c5d0 | ||
|
|
60bcf42edf | ||
|
|
d5f9654c12 | ||
|
|
d2fb214a54 | ||
|
|
6294f811a7 | ||
|
|
30ae6f45a4 | ||
|
|
60ef8ac58d | ||
|
|
6c42564337 | ||
|
|
479fc57cef | ||
|
|
b2fb14fd48 | ||
|
|
d8f90444aa | ||
|
|
045331666c | ||
|
|
0ac42125d2 | ||
|
|
ce04014739 | ||
|
|
19bd97d80c | ||
|
|
ea2e34c4c3 | ||
|
|
5f6498d13a | ||
|
|
e3c1292548 | ||
|
|
b3e53839a4 | ||
|
|
f3e9f10cad | ||
|
|
2c8927a9a2 | ||
|
|
c6786aed26 | ||
|
|
5b3b09fb7f | ||
|
|
9f5924c5ea | ||
|
|
25f5d764ac | ||
|
|
941c72fcfe | ||
|
|
663d389925 | ||
|
|
b8e3477092 | ||
|
|
035c784b6c | ||
|
|
8faf8a3535 | ||
|
|
331125d35a | ||
|
|
7316ebde79 | ||
|
|
c3340ad21c | ||
|
|
1e84816c96 | ||
|
|
58c6ea5de8 | ||
|
|
34be80602c | ||
|
|
ce40be475b | ||
|
|
5f7bd36119 | ||
|
|
0f19193afd | ||
|
|
06b3b0ea15 | ||
|
|
32f973b010 | ||
|
|
ad2c2a055b | ||
|
|
3069ef3827 | ||
|
|
d70b1c68fe | ||
|
|
3ba4a35c9c | ||
|
|
2c4c1a3dd9 | ||
|
|
a4d8974556 | ||
|
|
b7d4759c19 | ||
|
|
d6ecc65df3 | ||
|
|
98b67cdb69 | ||
|
|
eb37822e03 | ||
|
|
8751f485c5 |
File diff suppressed because it is too large
Load Diff
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,3 +1,4 @@
|
||||
# `git apply` and friends don't understand CRLF, even on windows. Force those
|
||||
# files to be checked out with LF endings even if core.autocrlf is true.
|
||||
*.patch text eol=lf
|
||||
patches/**/.patches merge=union
|
||||
|
||||
14
BUILD.gn
14
BUILD.gn
@@ -358,6 +358,7 @@ source_set("electron_lib") {
|
||||
"shell/common/api:mojo",
|
||||
"//base:base_static",
|
||||
"//base/allocator:buildflags",
|
||||
"//chrome/app:command_ids",
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
"//chrome/services/printing/public/mojom",
|
||||
"//components/certificate_transparency",
|
||||
@@ -549,6 +550,16 @@ source_set("electron_lib") {
|
||||
|
||||
sources += filenames.lib_sources_nss
|
||||
sources += [
|
||||
"shell/browser/ui/gtk/app_indicator_icon.cc",
|
||||
"shell/browser/ui/gtk/app_indicator_icon.h",
|
||||
"shell/browser/ui/gtk/app_indicator_icon_menu.cc",
|
||||
"shell/browser/ui/gtk/app_indicator_icon_menu.h",
|
||||
"shell/browser/ui/gtk/gtk_status_icon.cc",
|
||||
"shell/browser/ui/gtk/gtk_status_icon.h",
|
||||
"shell/browser/ui/gtk/menu_util.cc",
|
||||
"shell/browser/ui/gtk/menu_util.h",
|
||||
"shell/browser/ui/gtk/status_icon.cc",
|
||||
"shell/browser/ui/gtk/status_icon.h",
|
||||
"shell/browser/ui/gtk_util.cc",
|
||||
"shell/browser/ui/gtk_util.h",
|
||||
]
|
||||
@@ -829,6 +840,7 @@ if (is_mac) {
|
||||
|
||||
include_dirs = [ "." ]
|
||||
sources = filenames.framework_sources
|
||||
libs = []
|
||||
|
||||
if (enable_osr) {
|
||||
libs += [ "IOSurface.framework" ]
|
||||
@@ -1354,7 +1366,7 @@ dist_zip("electron_chromedriver_zip") {
|
||||
|
||||
mksnapshot_deps = [
|
||||
":licenses",
|
||||
"//tools/v8_context_snapshot:v8_context_snapshot_generator",
|
||||
"//tools/v8_context_snapshot:v8_context_snapshot_generator($v8_snapshot_toolchain)",
|
||||
"//v8:mksnapshot($v8_snapshot_toolchain)",
|
||||
]
|
||||
|
||||
|
||||
4
DEPS
4
DEPS
@@ -11,7 +11,7 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'80.0.3987.158',
|
||||
'80.0.3987.165',
|
||||
'node_version':
|
||||
'v12.13.0',
|
||||
'nan_version':
|
||||
@@ -152,3 +152,5 @@ hooks = [
|
||||
recursedeps = [
|
||||
'src',
|
||||
]
|
||||
|
||||
# Touch DEPS to bust cache
|
||||
|
||||
@@ -1 +1 @@
|
||||
8.2.0
|
||||
8.5.0
|
||||
34
appveyor.yml
34
appveyor.yml
@@ -77,15 +77,39 @@ build_script:
|
||||
%GCLIENT_EXTRA_ARGS%
|
||||
"https://github.com/electron/electron"
|
||||
- gclient sync --with_branch_heads --with_tags --ignore_locks --break_repo_locks
|
||||
- ps: >-
|
||||
if ($env:SAVE_GCLIENT_SRC -eq 'true') {
|
||||
# archive current source for future use
|
||||
# only run on x64/woa to avoid contention saving
|
||||
if ($(7z a $zipfile src -xr!android_webview -xr!electron -xr'!*\.git' -xr!third_party\WebKit\LayoutTests! -xr!third_party\blink\web_tests -xr!third_party\blink\perf_tests -slp -t7z -mmt=30;$LASTEXITCODE -ne 0)) {
|
||||
Write-warning "Could not save source to shared drive; continuing anyway"
|
||||
}
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
git clone https://github.com/electron/build-tools.git
|
||||
cd build-tools
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
|
||||
$env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
$env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
cd ..
|
||||
.\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
}
|
||||
- cd src
|
||||
- ps: $env:BUILD_CONFIG_PATH="//electron/build/args/%GN_CONFIG%.gn"
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS% cc_wrapper=\"%SCCACHE_PATH%\""
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- if DEFINED GN_GOMA_FILE (gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% ") else (gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS% cc_wrapper=\"%SCCACHE_PATH%\"")
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron:manifests
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- ninja -C out/Default electron:electron_app
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\Users\electron\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\Users\electron\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
@@ -94,7 +118,7 @@ build_script:
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- cmd /C %SCCACHE_PATH% --show-stats
|
||||
- if "%GN_CONFIG%"=="testing" ( python %LOCAL_GOMA_DIR%\goma_ctl.py stat )
|
||||
- appveyor PushArtifact out/Default/dist.zip
|
||||
- appveyor PushArtifact out/Default/shell_browser_ui_unittests.exe
|
||||
- appveyor PushArtifact out/Default/chromedriver.zip
|
||||
|
||||
@@ -88,5 +88,6 @@ steps:
|
||||
- powershell: |
|
||||
Get-Process | Where Name –Like "electron*" | Stop-Process
|
||||
Get-Process | Where Name –Like "MicrosoftEdge*" | Stop-Process
|
||||
Get-Process | Where Name –Like "msedge*" | Stop-Process
|
||||
displayName: 'Kill processes left running from last test run'
|
||||
condition: always()
|
||||
@@ -27,5 +27,4 @@ dawn_enable_vulkan_validation_layers = false
|
||||
|
||||
is_cfi = false
|
||||
|
||||
# TODO: disabled due to crashes. re-enable.
|
||||
enable_osr = false
|
||||
enable_osr = true
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
|
||||
@@ -9,6 +10,9 @@ config.output = {
|
||||
filename: path.basename(outPath)
|
||||
}
|
||||
|
||||
const { wrapInitWithProfilingTimeout } = config;
|
||||
delete config.wrapInitWithProfilingTimeout;
|
||||
|
||||
webpack(config, (err, stats) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
@@ -17,6 +21,18 @@ webpack(config, (err, stats) => {
|
||||
console.error(stats.toString('normal'))
|
||||
process.exit(1)
|
||||
} else {
|
||||
if (wrapInitWithProfilingTimeout) {
|
||||
const contents = fs.readFileSync(outPath, 'utf8');
|
||||
const newContents = `function ___electron_webpack_init__() {
|
||||
${contents}
|
||||
};
|
||||
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
|
||||
setTimeout(___electron_webpack_init__, 0);
|
||||
} else {
|
||||
___electron_webpack_init__();
|
||||
}`;
|
||||
fs.writeFileSync(outPath, newContents);
|
||||
}
|
||||
process.exit(0)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -24,7 +24,8 @@ module.exports = ({
|
||||
alwaysHasNode,
|
||||
loadElectronFromAlternateTarget,
|
||||
targetDeletesNodeGlobals,
|
||||
target
|
||||
target,
|
||||
wrapInitWithProfilingTimeout
|
||||
}) => {
|
||||
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
|
||||
if (!fs.existsSync(entry)) {
|
||||
@@ -39,6 +40,7 @@ module.exports = ({
|
||||
output: {
|
||||
filename: `${target}.bundle.js`
|
||||
},
|
||||
wrapInitWithProfilingTimeout,
|
||||
resolve: {
|
||||
alias: {
|
||||
'@electron/internal': path.resolve(electronRoot, 'lib'),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'renderer',
|
||||
alwaysHasNode: true,
|
||||
targetDeletesNodeGlobals: true
|
||||
targetDeletesNodeGlobals: true,
|
||||
wrapInitWithProfilingTimeout: true
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'sandboxed_renderer',
|
||||
alwaysHasNode: false
|
||||
alwaysHasNode: false,
|
||||
wrapInitWithProfilingTimeout: true,
|
||||
})
|
||||
|
||||
@@ -16,6 +16,7 @@ template("webpack_build") {
|
||||
inputs = [
|
||||
invoker.config_file,
|
||||
"//electron/build/webpack/webpack.config.base.js",
|
||||
"//electron/build/webpack/run-compiler.js",
|
||||
"//electron/tsconfig.json",
|
||||
"//electron/yarn.lock",
|
||||
"//electron/typings/internal-ambient.d.ts",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
|
||||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
|
||||
let mainWindow: BrowserWindow | null = null;
|
||||
|
||||
@@ -31,12 +32,11 @@ function isTrustedSender (webContents: Electron.WebContents) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const parsedUrl = new URL(webContents.getURL());
|
||||
const urlPath = process.platform === 'win32'
|
||||
// Strip the prefixed "/" that occurs on windows
|
||||
? path.resolve(parsedUrl.pathname.substr(1))
|
||||
: parsedUrl.pathname;
|
||||
return parsedUrl.protocol === 'file:' && urlPath === indexPath;
|
||||
try {
|
||||
return url.fileURLToPath(webContents.getURL()) === indexPath;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.handle('bootstrap', (event) => {
|
||||
|
||||
@@ -368,6 +368,25 @@ Returns:
|
||||
|
||||
Emitted when the renderer process of `webContents` crashes or is killed.
|
||||
|
||||
#### Event: 'render-process-gone'
|
||||
|
||||
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-failure` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
|
||||
Emitted when the renderer process unexpectedly dissapears. This is normally
|
||||
because it was crashed or killed.
|
||||
|
||||
### Event: 'accessibility-support-changed' _macOS_ _Windows_
|
||||
|
||||
Returns:
|
||||
@@ -564,11 +583,17 @@ Returns `Promise<void>` - fulfilled when Electron is initialized.
|
||||
May be used as a convenient alternative to checking `app.isReady()`
|
||||
and subscribing to the `ready` event if the app is not ready yet.
|
||||
|
||||
### `app.focus()`
|
||||
### `app.focus([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `steal` Boolean _macOS_ - Make the receiver the active app even if another app is
|
||||
currently active.
|
||||
|
||||
On Linux, focuses on the first visible window. On macOS, makes the application
|
||||
the active app. On Windows, focuses on the application's first window.
|
||||
|
||||
You should seek to use the `steal` option as sparingly as possible.
|
||||
|
||||
### `app.hide()` _macOS_
|
||||
|
||||
Hides all application windows without minimizing them.
|
||||
@@ -669,8 +694,6 @@ to the npm modules spec. You should usually also specify a `productName`
|
||||
field, which is your application's full capitalized name, and which will be
|
||||
preferred over `name` by Electron.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.setName(name)`
|
||||
|
||||
* `name` String
|
||||
@@ -679,8 +702,6 @@ Overrides the current application's name.
|
||||
|
||||
**Note:** This function overrides the name used internally by Electron; it does not affect the name that the OS uses.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.getLocale()`
|
||||
|
||||
Returns `String` - The current application locale. Possible return values are documented [here](locales.md).
|
||||
@@ -1088,14 +1109,10 @@ On macOS, it shows on the dock icon. On Linux, it only works for Unity launcher.
|
||||
**Note:** Unity launcher requires the existence of a `.desktop` file to work,
|
||||
for more information please read [Desktop Environment Integration][unity-requirement].
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.getBadgeCount()` _Linux_ _macOS_
|
||||
|
||||
Returns `Integer` - The current value displayed in the counter badge.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.isUnityRunning()` _Linux_
|
||||
|
||||
Returns `Boolean` - Whether the current desktop environment is Unity launcher.
|
||||
@@ -1170,8 +1187,6 @@ technologies, such as screen readers, has been detected. See
|
||||
https://www.chromium.org/developers/design-documents/accessibility for more
|
||||
details.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.setAccessibilitySupportEnabled(enabled)` _macOS_ _Windows_
|
||||
|
||||
* `enabled` Boolean - Enable or disable [accessibility tree](https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree) rendering
|
||||
@@ -1183,8 +1198,6 @@ This API must be called after the `ready` event is emitted.
|
||||
|
||||
**Note:** Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.showAboutPanel()`
|
||||
|
||||
Show the app's about panel options. These options can be overridden with `app.setAboutPanelOptions(options)`.
|
||||
|
||||
@@ -388,6 +388,15 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
visible to users.
|
||||
* `spellcheck` Boolean (optional) - Whether to enable the builtin spellchecker.
|
||||
Default is `false`.
|
||||
* `enableWebSQL` Boolean (optional) - Whether to enable the [WebSQL api](https://www.w3.org/TR/webdatabase/).
|
||||
Default is `true`.
|
||||
* `v8CacheOptions` String (optional) - Enforces the v8 code caching policy
|
||||
used by blink. Accepted values are
|
||||
* `none` - Disables code caching
|
||||
* `code` - Heuristic based code caching
|
||||
* `bypassHeatCheck` - Bypass code caching heuristics but with lazy compilation
|
||||
* `bypassHeatCheckAndEagerCompile` - Same as above except compilation is eager.
|
||||
Default policy is `code`.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -626,6 +635,12 @@ Returns:
|
||||
|
||||
Emitted on 3-finger swipe. Possible directions are `up`, `right`, `down`, `left`.
|
||||
|
||||
The method underlying this event is built to handle older macOS-style trackpad swiping,
|
||||
where the content on the screen doesn't move with the swipe. Most macOS trackpads are not
|
||||
configured to allow this kind of swiping anymore, so in order for it to emit properly the
|
||||
'Swipe between pages' preference in `System Preferences > Trackpad > More Gestures` must be
|
||||
set to 'Swipe with two or three fingers'.
|
||||
|
||||
#### Event: 'rotate-gesture' _macOS_
|
||||
|
||||
Returns:
|
||||
@@ -1046,7 +1061,7 @@ Disable or enable the window.
|
||||
|
||||
#### `win.isEnabled()`
|
||||
|
||||
Returns Boolean - whether the window is enabled.
|
||||
Returns `Boolean` - whether the window is enabled.
|
||||
|
||||
#### `win.setSize(width, height[, animate])`
|
||||
|
||||
@@ -1098,15 +1113,11 @@ Returns `Integer[]` - Contains the window's maximum width and height.
|
||||
|
||||
* `resizable` Boolean
|
||||
|
||||
Sets whether the window can be manually resized by user.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
Sets whether the window can be manually resized by the user.
|
||||
|
||||
#### `win.isResizable()`
|
||||
|
||||
Returns `Boolean` - Whether the window can be manually resized by user.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
Returns `Boolean` - Whether the window can be manually resized by the user.
|
||||
|
||||
#### `win.setMovable(movable)` _macOS_ _Windows_
|
||||
|
||||
@@ -1114,41 +1125,29 @@ Returns `Boolean` - Whether the window can be manually resized by user.
|
||||
|
||||
Sets whether the window can be moved by user. On Linux does nothing.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `win.isMovable()` _macOS_ _Windows_
|
||||
|
||||
Returns `Boolean` - Whether the window can be moved by user.
|
||||
|
||||
On Linux always returns `true`.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `win.setMinimizable(minimizable)` _macOS_ _Windows_
|
||||
|
||||
* `minimizable` Boolean
|
||||
|
||||
Sets whether the window can be manually minimized by user. On Linux does
|
||||
nothing.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
Sets whether the window can be manually minimized by user. On Linux does nothing.
|
||||
|
||||
#### `win.isMinimizable()` _macOS_ _Windows_
|
||||
|
||||
Returns `Boolean` - Whether the window can be manually minimized by user
|
||||
Returns `Boolean` - Whether the window can be manually minimized by the user.
|
||||
|
||||
On Linux always returns `true`.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `win.setMaximizable(maximizable)` _macOS_ _Windows_
|
||||
|
||||
* `maximizable` Boolean
|
||||
|
||||
Sets whether the window can be manually maximized by user. On Linux does
|
||||
nothing.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
Sets whether the window can be manually maximized by user. On Linux does nothing.
|
||||
|
||||
#### `win.isMaximizable()` _macOS_ _Windows_
|
||||
|
||||
@@ -1156,23 +1155,15 @@ Returns `Boolean` - Whether the window can be manually maximized by user.
|
||||
|
||||
On Linux always returns `true`.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `win.setFullScreenable(fullscreenable)`
|
||||
|
||||
* `fullscreenable` Boolean
|
||||
|
||||
Sets whether the maximize/zoom window button toggles fullscreen mode or
|
||||
maximizes the window.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
Sets whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.
|
||||
|
||||
#### `win.isFullScreenable()`
|
||||
|
||||
Returns `Boolean` - Whether the maximize/zoom window button toggles fullscreen mode or
|
||||
maximizes the window.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
Returns `Boolean` - Whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.
|
||||
|
||||
#### `win.setClosable(closable)` _macOS_ _Windows_
|
||||
|
||||
@@ -1180,16 +1171,12 @@ maximizes the window.
|
||||
|
||||
Sets whether the window can be manually closed by user. On Linux does nothing.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `win.isClosable()` _macOS_ _Windows_
|
||||
|
||||
Returns `Boolean` - Whether the window can be manually closed by user.
|
||||
|
||||
On Linux always returns `true`.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `win.setAlwaysOnTop(flag[, level][, relativeLevel])`
|
||||
|
||||
* `flag` Boolean
|
||||
@@ -1601,23 +1588,17 @@ This cannot be called when `titleBarStyle` is set to `customButtonsOnHover`.
|
||||
Sets whether the window menu bar should hide itself automatically. Once set the
|
||||
menu bar will only show when users press the single `Alt` key.
|
||||
|
||||
If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't
|
||||
hide it immediately.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't hide it immediately.
|
||||
|
||||
#### `win.isMenuBarAutoHide()`
|
||||
|
||||
Returns `Boolean` - Whether menu bar automatically hides itself.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `win.setMenuBarVisibility(visible)` _Windows_ _Linux_
|
||||
|
||||
* `visible` Boolean
|
||||
|
||||
Sets whether the menu bar should be visible. If the menu bar is auto-hide, users
|
||||
can still bring up the menu bar by pressing the single `Alt` key.
|
||||
Sets whether the menu bar should be visible. If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single `Alt` key.
|
||||
|
||||
#### `win.isMenuBarVisible()`
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ Disables the disk cache for HTTP requests.
|
||||
|
||||
Disable HTTP/2 and SPDY/3.1 protocols.
|
||||
|
||||
### --disable-ntlm-v2
|
||||
|
||||
Disables NTLM v2 for posix platforms, no effect elsewhere.
|
||||
|
||||
## --lang
|
||||
|
||||
Set a custom locale.
|
||||
|
||||
@@ -38,6 +38,9 @@ Get a set of category groups. The category groups can change as new code paths
|
||||
are reached. See also the [list of built-in tracing
|
||||
categories](https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/builtin_categories.h).
|
||||
|
||||
> **NOTE:** Electron adds a non-default tracing category called `"electron"`.
|
||||
> This category can be used to capture Electron-specific tracing events.
|
||||
|
||||
### `contentTracing.startRecording(options)`
|
||||
|
||||
* `options` ([TraceConfig](structures/trace-config.md) | [TraceCategoriesAndOptions](structures/trace-categories-and-options.md))
|
||||
|
||||
@@ -52,6 +52,8 @@ Returns:
|
||||
* `method` String - Method name.
|
||||
* `params` any - Event parameters defined by the 'parameters'
|
||||
attribute in the remote debugging protocol.
|
||||
* `sessionId` String - Unique identifier of attached debugging session,
|
||||
will match the value sent from `debugger.sendCommand`.
|
||||
|
||||
Emitted whenever the debugging target issues an instrumentation event.
|
||||
|
||||
@@ -74,11 +76,16 @@ Returns `Boolean` - Whether a debugger is attached to the `webContents`.
|
||||
|
||||
Detaches the debugger from the `webContents`.
|
||||
|
||||
#### `debugger.sendCommand(method[, commandParams])`
|
||||
#### `debugger.sendCommand(method[, commandParams, sessionId])`
|
||||
|
||||
* `method` String - Method name, should be one of the methods defined by the
|
||||
[remote debugging protocol][rdp].
|
||||
* `commandParams` any (optional) - JSON object with request parameters.
|
||||
* `sessionId` String (optional) - send command to the target with associated
|
||||
debugging session id. The initial value can be obtained by sending
|
||||
[Target.attachToTarget][attachToTarget] message.
|
||||
|
||||
[attachToTarget]: https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-attachToTarget
|
||||
|
||||
Returns `Promise<any>` - A promise that resolves with the response defined by
|
||||
the 'returns' attribute of the command description in the remote debugging protocol
|
||||
|
||||
@@ -269,6 +269,7 @@ Shows a message box, it will block the process until the message box is closed.
|
||||
It returns the index of the clicked button.
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
|
||||
If `browserWindow` is not shown dialog will not be attached to it. In such case It will be displayed as independed window.
|
||||
|
||||
### `dialog.showMessageBox([browserWindow, ]options)`
|
||||
|
||||
|
||||
@@ -82,16 +82,12 @@ The API is only available in session's `will-download` callback function.
|
||||
If user doesn't set the save path via the API, Electron will use the original
|
||||
routine to determine the save path; this usually prompts a save dialog.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md): use the `savePath` property instead.**
|
||||
|
||||
#### `downloadItem.getSavePath()`
|
||||
|
||||
Returns `String` - The save path of the download item. This will be either the path
|
||||
set via `downloadItem.setSavePath(path)` or the path selected from the shown
|
||||
save dialog.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md): use the `savePath` property instead.**
|
||||
|
||||
#### `downloadItem.setSaveDialogOptions(options)`
|
||||
|
||||
* `options` SaveDialogOptions - Set the save file dialog options. This object has the same
|
||||
|
||||
@@ -128,3 +128,14 @@ the one downloaded by `npm install`. Usage:
|
||||
```sh
|
||||
export ELECTRON_OVERRIDE_DIST_PATH=/Users/username/projects/electron/out/Debug
|
||||
```
|
||||
|
||||
## Set By Electron
|
||||
|
||||
Electron sets some variables in your environment at runtime.
|
||||
|
||||
### `ORIGINAL_XDG_CURRENT_DESKTOP`
|
||||
|
||||
This variable is set to the value of `XDG_CURRENT_DESKTOP` that your application
|
||||
originally launched with. Electron sometimes modifies the value of `XDG_CURRENT_DESKTOP`
|
||||
to affect other logic within Chromium so if you want access to the _original_ value
|
||||
you should look up this environment variable instead.
|
||||
|
||||
@@ -12,7 +12,7 @@ See [`Menu`](menu.md) for examples.
|
||||
* `click` Function (optional) - Will be called with
|
||||
`click(menuItem, browserWindow, event)` when the menu item is clicked.
|
||||
* `menuItem` MenuItem
|
||||
* `browserWindow` [BrowserWindow](browser-window.md)
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) | undefined - This will not be defined if no window is open.
|
||||
* `event` [KeyboardEvent](structures/keyboard-event.md)
|
||||
* `role` String (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `close`, `minimize`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
`click` property will be ignored. See [roles](#roles).
|
||||
@@ -69,6 +69,7 @@ a `type`.
|
||||
The `role` property can have following values:
|
||||
|
||||
* `undo`
|
||||
* `about` - Trigger a native about panel (custom message box on Window, which does not provide its own).
|
||||
* `redo`
|
||||
* `cut`
|
||||
* `copy`
|
||||
@@ -94,7 +95,6 @@ The `role` property can have following values:
|
||||
The following additional roles are available on _macOS_:
|
||||
|
||||
* `appMenu` - Whole default "App" menu (About, Services, etc.)
|
||||
* `about` - Map to the `orderFrontStandardAboutPanel` action.
|
||||
* `hide` - Map to the `hide` action.
|
||||
* `hideOthers` - Map to the `hideOtherApplications` action.
|
||||
* `unhide` - Map to the `unhideAllApplications` action.
|
||||
|
||||
@@ -45,9 +45,3 @@ The Electron team is currently undergoing an initiative to convert separate gett
|
||||
* `isMacTemplateImage`
|
||||
* `SystemPreferences` module
|
||||
* `appLevelAppearance`
|
||||
* `webContents` module
|
||||
* `audioMuted`
|
||||
* `frameRate`
|
||||
* `userAgent`
|
||||
* `zoomFactor`
|
||||
* `zoomLevel`
|
||||
|
||||
@@ -276,14 +276,10 @@ Returns [`Size`](structures/size.md)
|
||||
|
||||
Marks the image as a template image.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `image.isTemplateImage()`
|
||||
|
||||
Returns `Boolean` - Whether the image is a template image.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `image.crop(rect)`
|
||||
|
||||
* `rect` [Rectangle](structures/rectangle.md) - The area of the image to crop.
|
||||
|
||||
@@ -24,11 +24,11 @@ app.on('ready', () => {
|
||||
|
||||
The `powerMonitor` module emits the following events:
|
||||
|
||||
### Event: 'suspend'
|
||||
### Event: 'suspend' _Linux_ _Windows_
|
||||
|
||||
Emitted when the system is suspending.
|
||||
|
||||
### Event: 'resume'
|
||||
### Event: 'resume' _Linux_ _Windows_
|
||||
|
||||
Emitted when system is resuming.
|
||||
|
||||
|
||||
4
docs/api/structures/new-window-event.md
Normal file
4
docs/api/structures/new-window-event.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# NewWindowEvent Object extends `Event`
|
||||
|
||||
* `newGuest` BrowserWindow (optional)
|
||||
|
||||
@@ -360,7 +360,7 @@ Returns `Boolean` - `true` if an inverted color scheme (a high contrast color sc
|
||||
|
||||
Returns `Boolean` - `true` if a high contrast theme is active, `false` otherwise.
|
||||
|
||||
**Depreacted:** Should use the new [`nativeTheme.shouldUseHighContrastColors`](native-theme.md#nativethemeshouldusehighcontrastcolors-macos-windows-readonly) API.
|
||||
**Deprecated:** Should use the new [`nativeTheme.shouldUseHighContrastColors`](native-theme.md#nativethemeshouldusehighcontrastcolors-macos-windows-readonly) API.
|
||||
|
||||
### `systemPreferences.getEffectiveAppearance()` _macOS_
|
||||
|
||||
@@ -369,8 +369,6 @@ Returns `String` - Can be `dark`, `light` or `unknown`.
|
||||
Gets the macOS appearance setting that is currently applied to your application,
|
||||
maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `systemPreferences.getAppLevelAppearance()` _macOS_ _Deprecated_
|
||||
|
||||
Returns `String` | `null` - Can be `dark`, `light` or `unknown`.
|
||||
@@ -379,8 +377,6 @@ Gets the macOS appearance setting that you have declared you want for
|
||||
your application, maps to [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc).
|
||||
You can use the `setAppLevelAppearance` API to set this value.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `systemPreferences.setAppLevelAppearance(appearance)` _macOS_ _Deprecated_
|
||||
|
||||
* `appearance` String | null - Can be `dark` or `light`
|
||||
@@ -388,8 +384,6 @@ You can use the `setAppLevelAppearance` API to set this value.
|
||||
Sets the appearance setting for your application, this should override the
|
||||
system default and override the value of `getEffectiveAppearance`.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `systemPreferences.canPromptTouchID()` _macOS_
|
||||
|
||||
Returns `Boolean` - whether or not this device has the ability to use Touch ID.
|
||||
@@ -422,7 +416,7 @@ This API itself will not protect your user data; rather, it is a mechanism to al
|
||||
|
||||
Returns `Boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.
|
||||
|
||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
|
||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _Windows_ _macOS_
|
||||
|
||||
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
|
||||
|
||||
@@ -432,6 +426,9 @@ This user consent was not required on macOS 10.13 High Sierra or lower so this m
|
||||
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
|
||||
macOS 10.15 Catalina or higher requires consent for `screen` access.
|
||||
|
||||
Windows 10 has a global setting controlling `microphone` and `camera` access for all win32 applications.
|
||||
It will always return `granted` for `screen` and for all media types on older versions of Windows.
|
||||
|
||||
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
|
||||
|
||||
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.
|
||||
|
||||
@@ -138,7 +138,7 @@ Emitted when page receives favicon urls.
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `event` NewWindowEvent
|
||||
* `url` String
|
||||
* `frameName` String
|
||||
* `disposition` String - Can be `default`, `foreground-tab`, `background-tab`,
|
||||
@@ -334,6 +334,24 @@ Returns:
|
||||
|
||||
Emitted when the renderer process crashes or is killed.
|
||||
|
||||
#### Event: 'render-process-gone'
|
||||
|
||||
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-failure` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
|
||||
Emitted when the renderer process unexpectedly dissapears. This is normally
|
||||
because it was crashed or killed.
|
||||
|
||||
#### Event: 'unresponsive'
|
||||
|
||||
Emitted when the web page becomes unresponsive.
|
||||
@@ -366,6 +384,7 @@ Returns:
|
||||
* `key` String - Equivalent to [KeyboardEvent.key][keyboardevent].
|
||||
* `code` String - Equivalent to [KeyboardEvent.code][keyboardevent].
|
||||
* `isAutoRepeat` Boolean - Equivalent to [KeyboardEvent.repeat][keyboardevent].
|
||||
* `isComposing` Boolean - Equivalent to [KeyboardEvent.isComposing][keyboardevent].
|
||||
* `shift` Boolean - Equivalent to [KeyboardEvent.shiftKey][keyboardevent].
|
||||
* `control` Boolean - Equivalent to [KeyboardEvent.controlKey][keyboardevent].
|
||||
* `alt` Boolean - Equivalent to [KeyboardEvent.altKey][keyboardevent].
|
||||
@@ -882,10 +901,10 @@ Returns `String` - The URL of the current web page.
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('http://github.com')
|
||||
|
||||
let currentURL = win.webContents.getURL()
|
||||
console.log(currentURL)
|
||||
win.loadURL('http://github.com').then(() => {
|
||||
const currentURL = win.webContents.getURL()
|
||||
console.log(currentURL)
|
||||
})
|
||||
```
|
||||
|
||||
#### `contents.getTitle()`
|
||||
@@ -978,14 +997,10 @@ Returns `Boolean` - Whether the renderer process has crashed.
|
||||
|
||||
Overrides the user agent for this web page.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.getUserAgent()`
|
||||
|
||||
Returns `String` - The user agent for this web page.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.insertCSS(css[, options])`
|
||||
|
||||
* `css` String
|
||||
@@ -1065,14 +1080,10 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
|
||||
Mute the audio on the current web page.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.isAudioMuted()`
|
||||
|
||||
Returns `Boolean` - Whether this page has been muted.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.isCurrentlyAudible()`
|
||||
|
||||
Returns `Boolean` - Whether audio is currently playing.
|
||||
@@ -1086,14 +1097,10 @@ zoom percent divided by 100, so 300% = 3.0.
|
||||
|
||||
The factor must be greater than 0.0.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.getZoomFactor()`
|
||||
|
||||
Returns `Number` - the current zoom factor.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.setZoomLevel(level)`
|
||||
|
||||
* `level` Number - Zoom level.
|
||||
@@ -1103,14 +1110,10 @@ increment above or below represents zooming 20% larger or smaller to default
|
||||
limits of 300% and 50% of original size, respectively. The formula for this is
|
||||
`scale := 1.2 ^ level`.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.getZoomLevel()`
|
||||
|
||||
Returns `Number` - the current zoom level.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.setVisualZoomLevelLimits(minimumLevel, maximumLevel)`
|
||||
|
||||
* `minimumLevel` Number
|
||||
@@ -1713,14 +1716,10 @@ Returns `Boolean` - If *offscreen rendering* is enabled returns whether it is cu
|
||||
If *offscreen rendering* is enabled sets the frame rate to the specified number.
|
||||
Only values between 1 and 60 are accepted.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.getFrameRate()`
|
||||
|
||||
Returns `Integer` - If *offscreen rendering* is enabled returns the current frame rate.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
#### `contents.invalidate()`
|
||||
|
||||
Schedules a full repaint of the window this web contents is in.
|
||||
@@ -1826,7 +1825,7 @@ A [`WebContents`](web-contents.md) instance that might own this `WebContents`.
|
||||
|
||||
#### `contents.devToolsWebContents` _Readonly_
|
||||
|
||||
A `WebContents` of DevTools for this `WebContents`.
|
||||
A `WebContents | null` property that represents the of DevTools `WebContents` associated with a given `WebContents`.
|
||||
|
||||
**Note:** Users should never store this object because it may become `null`
|
||||
when the DevTools has been closed.
|
||||
|
||||
@@ -154,10 +154,14 @@ this limitation.
|
||||
* `userGesture` Boolean (optional) - Default is `false`.
|
||||
|
||||
Returns `Promise<any>` - A promise that resolves with the result of the executed code
|
||||
or is rejected if the result of the code is a rejected promise.
|
||||
or is rejected if execution could not start.
|
||||
|
||||
Works like `executeJavaScript` but evaluates `scripts` in an isolated context.
|
||||
|
||||
Note that when the execution of script fails, the returned promise will not
|
||||
reject and the `result` would be `undefined`. This is because Chromium does not
|
||||
dispatch errors of isolated worlds to foreign worlds.
|
||||
|
||||
### `webFrame.setIsolatedWorldInfo(worldId, info)`
|
||||
* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default world, `999` is the world used by Electrons `contextIsolation` feature. Chrome extensions reserve the range of IDs in `[1 << 20, 1 << 29)`. You can provide any integer here.
|
||||
* `info` Object
|
||||
|
||||
@@ -54,7 +54,9 @@ template("electron_extra_paks") {
|
||||
output = "${invoker.output_dir}/resources.pak"
|
||||
sources = [
|
||||
"$root_gen_dir/components/components_resources.pak",
|
||||
"$root_gen_dir/content/browser/resources/media/media_internals_resources.pak",
|
||||
"$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/mojo/public/js/mojo_bindings_resources.pak",
|
||||
"$root_gen_dir/net/net_resources.pak",
|
||||
@@ -65,7 +67,9 @@ template("electron_extra_paks") {
|
||||
deps = [
|
||||
"//components/resources",
|
||||
"//content:resources",
|
||||
"//content/browser/resources/media:media_internals_resources",
|
||||
"//content/browser/tracing:resources",
|
||||
"//content/browser/webrtc/resources",
|
||||
"//electron:resources",
|
||||
"//mojo/public/js:resources",
|
||||
"//net:net_resources",
|
||||
|
||||
@@ -96,6 +96,7 @@ auto_filenames = {
|
||||
"docs/api/structures/mime-typed-buffer.md",
|
||||
"docs/api/structures/mouse-input-event.md",
|
||||
"docs/api/structures/mouse-wheel-input-event.md",
|
||||
"docs/api/structures/new-window-event.md",
|
||||
"docs/api/structures/notification-action.md",
|
||||
"docs/api/structures/point.md",
|
||||
"docs/api/structures/printer-info.md",
|
||||
@@ -177,11 +178,8 @@ auto_filenames = {
|
||||
isolated_bundle_deps = [
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/isolated_renderer/init.js",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/web-view/web-view-constants.ts",
|
||||
"lib/renderer/web-view/web-view-element.ts",
|
||||
"lib/renderer/window-setup.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
@@ -191,6 +189,7 @@ auto_filenames = {
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/content_script/init.js",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/chrome-api.ts",
|
||||
"lib/renderer/extensions/event.ts",
|
||||
"lib/renderer/extensions/i18n.ts",
|
||||
|
||||
@@ -389,6 +389,8 @@ filenames = {
|
||||
"shell/browser/ui/views/submenu_button.h",
|
||||
"shell/browser/ui/views/win_frame_view.cc",
|
||||
"shell/browser/ui/views/win_frame_view.h",
|
||||
"shell/browser/ui/win/dialog_thread.cc",
|
||||
"shell/browser/ui/win/dialog_thread.h",
|
||||
"shell/browser/ui/win/electron_desktop_native_widget_aura.cc",
|
||||
"shell/browser/ui/win/electron_desktop_native_widget_aura.h",
|
||||
"shell/browser/ui/win/electron_desktop_window_tree_host_win.cc",
|
||||
@@ -518,6 +520,10 @@ filenames = {
|
||||
"shell/common/key_weak_map.h",
|
||||
"shell/common/keyboard_util.cc",
|
||||
"shell/common/keyboard_util.h",
|
||||
"shell/common/language_util.h",
|
||||
"shell/common/language_util_linux.cc",
|
||||
"shell/common/language_util_mac.mm",
|
||||
"shell/common/language_util_win.cc",
|
||||
"shell/common/mac/main_application_bundle.h",
|
||||
"shell/common/mac/main_application_bundle.mm",
|
||||
"shell/common/mouse_util.cc",
|
||||
@@ -568,8 +574,6 @@ filenames = {
|
||||
"shell/common/skia_util.h",
|
||||
"shell/renderer/api/context_bridge/object_cache.cc",
|
||||
"shell/renderer/api/context_bridge/object_cache.h",
|
||||
"shell/renderer/api/context_bridge/render_frame_function_store.cc",
|
||||
"shell/renderer/api/context_bridge/render_frame_function_store.h",
|
||||
"shell/renderer/api/electron_api_context_bridge.cc",
|
||||
"shell/renderer/api/electron_api_context_bridge.h",
|
||||
"shell/renderer/api/electron_api_renderer_ipc.cc",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import { deprecate, Menu } from 'electron';
|
||||
import { Menu } from 'electron';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const bindings = process.electronBinding('app');
|
||||
@@ -17,6 +17,29 @@ let dockMenu: Electron.Menu | null = null;
|
||||
Object.setPrototypeOf(App.prototype, EventEmitter.prototype);
|
||||
EventEmitter.call(app as any);
|
||||
|
||||
// Properties.
|
||||
|
||||
const nativeASGetter = app.isAccessibilitySupportEnabled;
|
||||
const nativeASSetter = app.setAccessibilitySupportEnabled;
|
||||
Object.defineProperty(App.prototype, 'accessibilitySupportEnabled', {
|
||||
get: () => nativeASGetter.call(app),
|
||||
set: (enabled) => nativeASSetter.call(app, enabled)
|
||||
});
|
||||
|
||||
const nativeBCGetter = app.getBadgeCount;
|
||||
const nativeBCSetter = app.setBadgeCount;
|
||||
Object.defineProperty(App.prototype, 'badgeCount', {
|
||||
get: () => nativeBCGetter.call(app),
|
||||
set: (count) => nativeBCSetter.call(app, count)
|
||||
});
|
||||
|
||||
const nativeNGetter = app.getName;
|
||||
const nativeNSetter = app.setName;
|
||||
Object.defineProperty(App.prototype, 'name', {
|
||||
get: () => nativeNGetter.call(app),
|
||||
set: (name) => nativeNSetter.call(app, name)
|
||||
});
|
||||
|
||||
Object.assign(app, {
|
||||
commandLine: {
|
||||
hasSwitch: (theSwitch: string) => commandLine.hasSwitch(String(theSwitch)),
|
||||
@@ -112,11 +135,6 @@ for (const name of events) {
|
||||
});
|
||||
}
|
||||
|
||||
// Property Deprecations
|
||||
deprecate.fnToProperty(App.prototype, 'accessibilitySupportEnabled', '_isAccessibilitySupportEnabled', '_setAccessibilitySupportEnabled');
|
||||
deprecate.fnToProperty(App.prototype, 'badgeCount', '_getBadgeCount', '_setBadgeCount');
|
||||
deprecate.fnToProperty(App.prototype, 'name', '_getName', '_setName');
|
||||
|
||||
// Wrappers for native classes.
|
||||
const { DownloadItem } = process.electronBinding('download_item');
|
||||
Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype);
|
||||
|
||||
@@ -92,6 +92,43 @@ BrowserWindow.prototype._init = function () {
|
||||
return this.webContents.devToolsWebContents;
|
||||
}
|
||||
});
|
||||
|
||||
// Properties
|
||||
|
||||
Object.defineProperty(this, 'autoHideMenuBar', {
|
||||
get: () => this.isMenuBarAutoHide(),
|
||||
set: (autoHide) => this.setAutoHideMenuBar(autoHide)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'minimizable', {
|
||||
get: () => this.isMinimizable(),
|
||||
set: (min) => this.setMinimizable(min)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'maximizable', {
|
||||
get: () => this.isMaximizable(),
|
||||
set: (max) => this.setMaximizable(max)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'resizable', {
|
||||
get: () => this.isResizable(),
|
||||
set: (res) => this.setResizable(res)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'fullScreenable', {
|
||||
get: () => this.isFullScreenable(),
|
||||
set: (full) => this.setFullScreenable(full)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'closable', {
|
||||
get: () => this.isClosable(),
|
||||
set: (close) => this.setClosable(close)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'movable', {
|
||||
get: () => this.isMovable(),
|
||||
set: (move) => this.setMovable(move)
|
||||
});
|
||||
};
|
||||
|
||||
const isBrowserWindow = (win) => {
|
||||
@@ -185,13 +222,4 @@ Object.assign(BrowserWindow.prototype, {
|
||||
}
|
||||
});
|
||||
|
||||
// Deprecations
|
||||
deprecate.fnToProperty(BrowserWindow.prototype, 'autoHideMenuBar', '_isMenuBarAutoHide', '_setAutoHideMenuBar');
|
||||
deprecate.fnToProperty(BrowserWindow.prototype, 'minimizable', '_isMinimizable', '_setMinimizable');
|
||||
deprecate.fnToProperty(BrowserWindow.prototype, 'maximizable', '_isMaximizable', '_setMaximizable');
|
||||
deprecate.fnToProperty(BrowserWindow.prototype, 'resizable', '_isResizable', '_setResizable');
|
||||
deprecate.fnToProperty(BrowserWindow.prototype, 'fullScreenable', '_isFullScreenable', '_setFullScreenable');
|
||||
deprecate.fnToProperty(BrowserWindow.prototype, 'closable', '_isClosable', '_setClosable');
|
||||
deprecate.fnToProperty(BrowserWindow.prototype, 'movable', '_isMovable', '_setMovable');
|
||||
|
||||
module.exports = BrowserWindow;
|
||||
|
||||
@@ -249,7 +249,11 @@ module.exports = {
|
||||
},
|
||||
|
||||
showCertificateTrustDialog: function (window, options) {
|
||||
if (window && window.constructor !== BrowserWindow) options = window;
|
||||
if (window && window.constructor !== BrowserWindow) {
|
||||
options = window;
|
||||
window = null;
|
||||
}
|
||||
|
||||
if (options == null || typeof options !== 'object') {
|
||||
throw new TypeError('options must be an object');
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ const roles = {
|
||||
about: {
|
||||
get label () {
|
||||
return isLinux ? 'About' : `About ${app.name}`;
|
||||
}
|
||||
},
|
||||
...(isWindows && { appMethod: 'showAboutPanel' })
|
||||
},
|
||||
close: {
|
||||
label: isMac ? 'Close Window' : 'Close',
|
||||
@@ -70,7 +71,7 @@ const roles = {
|
||||
},
|
||||
pasteandmatchstyle: {
|
||||
label: 'Paste and Match Style',
|
||||
accelerator: 'Shift+CommandOrControl+V',
|
||||
accelerator: isMac ? 'Cmd+Option+Shift+V' : 'Shift+CommandOrControl+V',
|
||||
webContentsMethod: 'pasteAndMatchStyle',
|
||||
registerAccelerator: false
|
||||
},
|
||||
|
||||
@@ -371,6 +371,7 @@ class ClientRequest extends Writable {
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
this._urlLoaderOptions.referrer = this._urlLoaderOptions.extraHeaders.referer || '';
|
||||
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) };
|
||||
this._urlLoader = new URLLoader(opts);
|
||||
this._urlLoader.on('response-started', (event, finalUrl, responseHead) => {
|
||||
|
||||
@@ -6,21 +6,20 @@ const { systemPreferences, SystemPreferences } = process.electronBinding('system
|
||||
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype);
|
||||
EventEmitter.call(systemPreferences);
|
||||
|
||||
if ('appLevelAppearance' in systemPreferences) {
|
||||
deprecate.fnToProperty(
|
||||
SystemPreferences.prototype,
|
||||
'appLevelAppearance',
|
||||
'_getAppLevelAppearance',
|
||||
'_setAppLevelAppearance'
|
||||
);
|
||||
if ('getAppLevelAppearance' in systemPreferences) {
|
||||
const nativeALAGetter = systemPreferences.getAppLevelAppearance;
|
||||
const nativeALASetter = systemPreferences.setAppLevelAppearance;
|
||||
Object.defineProperty(SystemPreferences.prototype, 'appLevelAppearance', {
|
||||
get: () => nativeALAGetter.call(systemPreferences),
|
||||
set: (appearance) => nativeALASetter.call(systemPreferences, appearance)
|
||||
});
|
||||
}
|
||||
|
||||
if ('effectiveAppearance' in systemPreferences) {
|
||||
deprecate.fnToProperty(
|
||||
SystemPreferences.prototype,
|
||||
'effectiveAppearance',
|
||||
'_getEffectiveAppearance'
|
||||
);
|
||||
if ('getEffectiveAppearance' in systemPreferences) {
|
||||
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
|
||||
Object.defineProperty(SystemPreferences.prototype, 'effectiveAppearance', {
|
||||
get: () => nativeEAGetter.call(systemPreferences)
|
||||
});
|
||||
}
|
||||
|
||||
SystemPreferences.prototype.isDarkMode = deprecate.moveAPI(
|
||||
|
||||
@@ -389,6 +389,10 @@ WebContents.prototype._init = function () {
|
||||
app.emit('renderer-process-crashed', event, this, ...args);
|
||||
});
|
||||
|
||||
this.on('render-process-gone', (event, ...args) => {
|
||||
app.emit('render-process-gone', event, this, ...args);
|
||||
});
|
||||
|
||||
// The devtools requests the webContents to reload.
|
||||
this.on('devtools-reload-page', function () {
|
||||
this.reload();
|
||||
@@ -429,6 +433,11 @@ WebContents.prototype._init = function () {
|
||||
const referrer = { url: '', policy: 'default' };
|
||||
internalWindowOpen(event, url, referrer, frameName, disposition, options);
|
||||
});
|
||||
|
||||
const prefs = this.getWebPreferences() || {};
|
||||
if (prefs.webviewTag && prefs.contextIsolation) {
|
||||
electron.deprecate.log('Security Warning: A WebContents was just created with both webviewTag and contextIsolation enabled. This combination is fundamentally less secure and effectively bypasses the protections of contextIsolation. We strongly recommend you move away from webviews to OOPIF or BrowserView in order for your app to be more secure');
|
||||
}
|
||||
}
|
||||
|
||||
this.on('login', (event, ...args) => {
|
||||
@@ -437,14 +446,34 @@ WebContents.prototype._init = function () {
|
||||
|
||||
const event = process.electronBinding('event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
};
|
||||
|
||||
// Deprecations
|
||||
deprecate.fnToProperty(WebContents.prototype, 'audioMuted', '_isAudioMuted', '_setAudioMuted');
|
||||
deprecate.fnToProperty(WebContents.prototype, 'userAgent', '_getUserAgent', '_setUserAgent');
|
||||
deprecate.fnToProperty(WebContents.prototype, 'zoomLevel', '_getZoomLevel', '_setZoomLevel');
|
||||
deprecate.fnToProperty(WebContents.prototype, 'zoomFactor', '_getZoomFactor', '_setZoomFactor');
|
||||
deprecate.fnToProperty(WebContents.prototype, 'frameRate', '_getFrameRate', '_setFrameRate');
|
||||
// Properties
|
||||
|
||||
Object.defineProperty(this, 'audioMuted', {
|
||||
get: () => this.isAudioMuted(),
|
||||
set: (muted) => this.setAudioMuted(muted)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'userAgent', {
|
||||
get: () => this.getUserAgent(),
|
||||
set: (agent) => this.setUserAgent(agent)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'zoomLevel', {
|
||||
get: () => this.getZoomLevel(),
|
||||
set: (level) => this.setZoomLevel(level)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'zoomFactor', {
|
||||
get: () => this.getZoomFactor(),
|
||||
set: (factor) => this.setZoomFactor(factor)
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'frameRate', {
|
||||
get: () => this.getFrameRate(),
|
||||
set: (rate) => this.setFrameRate(rate)
|
||||
});
|
||||
};
|
||||
|
||||
// JavaScript wrapper of Debugger.
|
||||
const { Debugger } = process.electronBinding('debugger');
|
||||
|
||||
@@ -32,6 +32,7 @@ const supportedWebViewEvents = [
|
||||
'focus-change',
|
||||
'close',
|
||||
'crashed',
|
||||
'render-process-gone',
|
||||
'plugin-crashed',
|
||||
'destroyed',
|
||||
'page-title-updated',
|
||||
@@ -232,7 +233,8 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
|
||||
['nodeIntegration', false],
|
||||
['enableRemoteModule', false],
|
||||
['sandbox', true],
|
||||
['nodeIntegrationInSubFrames', false]
|
||||
['nodeIntegrationInSubFrames', false],
|
||||
['enableWebSQL', false]
|
||||
]);
|
||||
|
||||
// Inherit certain option values from embedder
|
||||
@@ -266,6 +268,9 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
|
||||
// Remove an guest-embedder relationship.
|
||||
const detachGuest = function (embedder, guestInstanceId) {
|
||||
const guestInstance = guestInstances[guestInstanceId];
|
||||
|
||||
if (!guestInstance) return;
|
||||
|
||||
if (embedder !== guestInstance.embedder) {
|
||||
return;
|
||||
}
|
||||
@@ -360,6 +365,10 @@ handleMessage('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, embed
|
||||
}
|
||||
});
|
||||
|
||||
handleMessageSync('ELECTRON_GUEST_VIEW_MANAGER_DETACH_GUEST', function (event, guestInstanceId) {
|
||||
return detachGuest(event.sender, guestInstanceId);
|
||||
});
|
||||
|
||||
// this message is sent by the actual <webview>
|
||||
ipcMainInternal.on('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', function (event, focus, guestInstanceId) {
|
||||
const guest = getGuest(guestInstanceId);
|
||||
|
||||
@@ -19,7 +19,8 @@ const inheritedWebPreferences = new Map([
|
||||
['enableRemoteModule', false],
|
||||
['sandbox', true],
|
||||
['webviewTag', false],
|
||||
['nodeIntegrationInSubFrames', false]
|
||||
['nodeIntegrationInSubFrames', false],
|
||||
['enableWebSQL', false]
|
||||
]);
|
||||
|
||||
// Copy attribute of |parent| to |child| if it is not defined in |child|.
|
||||
@@ -188,6 +189,14 @@ const canAccessWindow = function (sender, target) {
|
||||
|
||||
// Routed window.open messages with raw options
|
||||
ipcMainInternal.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, frameName, features) => {
|
||||
// This should only be allowed for senders that have nativeWindowOpen: false
|
||||
{
|
||||
const webPreferences = event.sender.getLastWebPreferences();
|
||||
if (webPreferences.nativeWindowOpen || webPreferences.sandbox) {
|
||||
event.returnValue = null;
|
||||
throw new Error('GUEST_WINDOW_MANAGER_WINDOW_OPEN denied: expected native window.open');
|
||||
}
|
||||
}
|
||||
if (url == null || url === '') url = 'about:blank';
|
||||
if (frameName == null) frameName = '';
|
||||
if (features == null) features = '';
|
||||
@@ -195,7 +204,7 @@ ipcMainInternal.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, fra
|
||||
const options = {};
|
||||
|
||||
const ints = ['x', 'y', 'width', 'height', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight', 'zoomFactor'];
|
||||
const webPreferences = ['zoomFactor', 'nodeIntegration', 'enableRemoteModule', 'preload', 'javascript', 'contextIsolation', 'webviewTag'];
|
||||
const webPreferences = ['zoomFactor', 'nodeIntegration', 'enableRemoteModule', 'javascript', 'contextIsolation', 'webviewTag'];
|
||||
const disposition = 'new-window';
|
||||
|
||||
// Used to store additional features
|
||||
|
||||
@@ -186,6 +186,7 @@ function currentPlatformSupportsAppIndicator () {
|
||||
}
|
||||
|
||||
// Workaround for electron/electron#5050 and electron/electron#9046
|
||||
process.env.ORIGINAL_XDG_CURRENT_DESKTOP = process.env.XDG_CURRENT_DESKTOP;
|
||||
if (currentPlatformSupportsAppIndicator()) {
|
||||
process.env.XDG_CURRENT_DESKTOP = 'Unity';
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@ import { EventEmitter } from 'events';
|
||||
import objectsRegistry from './objects-registry';
|
||||
import { ipcMainInternal } from '../ipc-main-internal';
|
||||
import * as guestViewManager from '@electron/internal/browser/guest-view-manager';
|
||||
import { isPromise, isSerializableObject } from '@electron/internal/common/type-utils';
|
||||
import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const eventBinding = process.electronBinding('event');
|
||||
const features = process.electronBinding('features');
|
||||
const { NativeImage } = process.electronBinding('native_image');
|
||||
|
||||
if (!features.isRemoteModuleEnabled()) {
|
||||
throw new Error('remote module is disabled');
|
||||
@@ -114,6 +115,9 @@ type MetaType = {
|
||||
} | {
|
||||
type: 'promise',
|
||||
then: MetaType
|
||||
} | {
|
||||
type: 'nativeimage'
|
||||
value: electron.NativeImage
|
||||
}
|
||||
|
||||
// Convert a real value into meta data.
|
||||
@@ -124,6 +128,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
|
||||
// Recognize certain types of objects.
|
||||
if (value instanceof Buffer) {
|
||||
type = 'buffer';
|
||||
} else if (value instanceof NativeImage) {
|
||||
type = 'nativeimage';
|
||||
} else if (Array.isArray(value)) {
|
||||
type = 'array';
|
||||
} else if (value instanceof Error) {
|
||||
@@ -147,6 +153,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
|
||||
type,
|
||||
members: value.map((el: any) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
|
||||
};
|
||||
} else if (type === 'nativeimage') {
|
||||
return { type, value: serialize(value) };
|
||||
} else if (type === 'object' || type === 'function') {
|
||||
return {
|
||||
type,
|
||||
@@ -234,7 +242,10 @@ type MetaTypeFromRenderer = {
|
||||
} | {
|
||||
type: 'object',
|
||||
name: string,
|
||||
members: { name: string, value: MetaTypeFromRenderer }[]
|
||||
members: {
|
||||
name: string,
|
||||
value: MetaTypeFromRenderer
|
||||
}[]
|
||||
} | {
|
||||
type: 'function-with-return-value',
|
||||
value: MetaTypeFromRenderer
|
||||
@@ -243,6 +254,14 @@ type MetaTypeFromRenderer = {
|
||||
id: number,
|
||||
location: string,
|
||||
length: number
|
||||
} | {
|
||||
type: 'nativeimage',
|
||||
value: {
|
||||
size: electron.Size,
|
||||
buffer: Buffer,
|
||||
scaleFactor: number,
|
||||
dataURL: string
|
||||
}[]
|
||||
}
|
||||
|
||||
const fakeConstructor = (constructor: Function, name: string) =>
|
||||
@@ -260,6 +279,8 @@ const fakeConstructor = (constructor: Function, name: string) =>
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: number, contextId: string, args: any[]) {
|
||||
const metaToValue = function (meta: MetaTypeFromRenderer): any {
|
||||
switch (meta.type) {
|
||||
case 'nativeimage':
|
||||
return deserialize(meta.value);
|
||||
case 'value':
|
||||
return meta.value;
|
||||
case 'remote-object':
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const { deprecate } = require('electron');
|
||||
const { NativeImage, nativeImage } = process.electronBinding('native_image');
|
||||
|
||||
deprecate.fnToProperty(NativeImage.prototype, 'isMacTemplateImage', '_isTemplateImage', '_setTemplateImage');
|
||||
const { nativeImage } = process.electronBinding('native_image');
|
||||
|
||||
module.exports = nativeImage;
|
||||
|
||||
@@ -572,7 +572,7 @@
|
||||
};
|
||||
|
||||
const { readdir } = fs;
|
||||
fs.readdir = function (pathArgument, options, callback) {
|
||||
fs.readdir = function (pathArgument, options = {}, callback) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument);
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
@@ -594,13 +594,29 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.withFileTypes) {
|
||||
const dirents = [];
|
||||
for (const file of files) {
|
||||
const stats = archive.stat(file);
|
||||
if (stats.isFile) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE));
|
||||
} else if (stats.isDirectory) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR));
|
||||
} else if (stats.isLink) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK));
|
||||
}
|
||||
}
|
||||
nextTick(callback, [null, dirents]);
|
||||
return;
|
||||
}
|
||||
|
||||
nextTick(callback, [null, files]);
|
||||
};
|
||||
|
||||
fs.promises.readdir = util.promisify(fs.readdir);
|
||||
|
||||
const { readdirSync } = fs;
|
||||
fs.readdirSync = function (pathArgument, options) {
|
||||
fs.readdirSync = function (pathArgument, options = {}) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument);
|
||||
if (!isAsar) return readdirSync.apply(this, arguments);
|
||||
|
||||
@@ -614,6 +630,21 @@
|
||||
throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
}
|
||||
|
||||
if (options.withFileTypes) {
|
||||
const dirents = [];
|
||||
for (const file of files) {
|
||||
const stats = archive.stat(file);
|
||||
if (stats.isFile) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE));
|
||||
} else if (stats.isDirectory) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR));
|
||||
} else if (stats.isLink) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK));
|
||||
}
|
||||
}
|
||||
return dirents;
|
||||
}
|
||||
|
||||
return files;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ const serializableTypes = [
|
||||
ArrayBuffer
|
||||
];
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#Supported_types
|
||||
export function isSerializableObject (value: any) {
|
||||
return value === null || ArrayBuffer.isView(value) || serializableTypes.some(type => value instanceof type);
|
||||
}
|
||||
@@ -33,14 +34,55 @@ const objectMap = function (source: Object, mapper: (value: any) => any) {
|
||||
return Object.fromEntries(targetEntries);
|
||||
};
|
||||
|
||||
function serializeNativeImage (image: any) {
|
||||
const representations = [];
|
||||
const scaleFactors = image.getScaleFactors();
|
||||
|
||||
// Use Buffer when there's only one representation for better perf.
|
||||
// This avoids compressing to/from PNG where it's not necessary to
|
||||
// ensure uniqueness of dataURLs (since there's only one).
|
||||
if (scaleFactors.length === 1) {
|
||||
const scaleFactor = scaleFactors[0];
|
||||
const size = image.getSize(scaleFactor);
|
||||
const buffer = image.toBitmap({ scaleFactor });
|
||||
representations.push({ scaleFactor, size, buffer });
|
||||
} else {
|
||||
// Construct from dataURLs to ensure that they are not lost in creation.
|
||||
for (const scaleFactor of scaleFactors) {
|
||||
const size = image.getSize(scaleFactor);
|
||||
const dataURL = image.toDataURL({ scaleFactor });
|
||||
representations.push({ scaleFactor, size, dataURL });
|
||||
}
|
||||
}
|
||||
return { __ELECTRON_SERIALIZED_NativeImage__: true, representations };
|
||||
}
|
||||
|
||||
function deserializeNativeImage (value: any) {
|
||||
const image = nativeImage.createEmpty();
|
||||
|
||||
// Use Buffer when there's only one representation for better perf.
|
||||
// This avoids compressing to/from PNG where it's not necessary to
|
||||
// ensure uniqueness of dataURLs (since there's only one).
|
||||
if (value.representations.length === 1) {
|
||||
const { buffer, size, scaleFactor } = value.representations[0];
|
||||
const { width, height } = size;
|
||||
image.addRepresentation({ buffer, scaleFactor, width, height });
|
||||
} else {
|
||||
// Construct from dataURLs to ensure that they are not lost in creation.
|
||||
for (const rep of value.representations) {
|
||||
const { dataURL, size, scaleFactor } = rep;
|
||||
const { width, height } = size;
|
||||
image.addRepresentation({ dataURL, scaleFactor, width, height });
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
export function serialize (value: any): any {
|
||||
if (value instanceof NativeImage) {
|
||||
return {
|
||||
buffer: value.toBitmap(),
|
||||
size: value.getSize(),
|
||||
__ELECTRON_SERIALIZED_NativeImage__: true
|
||||
};
|
||||
} else if (Array.isArray(value)) {
|
||||
return serializeNativeImage(value);
|
||||
} if (Array.isArray(value)) {
|
||||
return value.map(serialize);
|
||||
} else if (isSerializableObject(value)) {
|
||||
return value;
|
||||
@@ -53,7 +95,7 @@ export function serialize (value: any): any {
|
||||
|
||||
export function deserialize (value: any): any {
|
||||
if (value && value.__ELECTRON_SERIALIZED_NativeImage__) {
|
||||
return nativeImage.createFromBitmap(value.buffer, value.size);
|
||||
return deserializeNativeImage(value);
|
||||
} else if (Array.isArray(value)) {
|
||||
return value.map(deserialize);
|
||||
} else if (isSerializableObject(value)) {
|
||||
|
||||
@@ -6,10 +6,6 @@ process.electronBinding = require('@electron/internal/common/electron-binding-se
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
|
||||
// The `lib/renderer/ipc-renderer-internal.js` module looks for the ipc object in the
|
||||
// "ipc-internal" hidden value
|
||||
v8Util.setHiddenValue(global, 'ipc-internal', v8Util.getHiddenValue(isolatedWorld, 'ipc-internal'));
|
||||
|
||||
const webViewImpl = v8Util.getHiddenValue(isolatedWorld, 'web-view-impl');
|
||||
|
||||
if (webViewImpl) {
|
||||
@@ -17,11 +13,3 @@ if (webViewImpl) {
|
||||
const { setupWebView } = require('@electron/internal/renderer/web-view/web-view-element');
|
||||
setupWebView(v8Util, webViewImpl);
|
||||
}
|
||||
|
||||
const isolatedWorldArgs = v8Util.getHiddenValue(isolatedWorld, 'isolated-world-args');
|
||||
|
||||
if (isolatedWorldArgs) {
|
||||
const { guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen } = isolatedWorldArgs;
|
||||
const { windowSetup } = require('@electron/internal/renderer/window-setup');
|
||||
windowSetup(guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen);
|
||||
}
|
||||
|
||||
@@ -11,10 +11,22 @@ const contextBridge = {
|
||||
exposeInMainWorld: (key: string, api: Record<string, any>) => {
|
||||
checkContextIsolationEnabled();
|
||||
return binding.exposeAPIInMainWorld(key, api);
|
||||
},
|
||||
debugGC: () => binding._debugGCMaps({})
|
||||
}
|
||||
};
|
||||
|
||||
if (!binding._debugGCMaps) delete contextBridge.debugGC;
|
||||
|
||||
export default contextBridge;
|
||||
|
||||
export const internalContextBridge = {
|
||||
contextIsolationEnabled,
|
||||
overrideGlobalValueFromIsolatedWorld: (keys: string[], value: any) => {
|
||||
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, false);
|
||||
},
|
||||
overrideGlobalValueWithDynamicPropsFromIsolatedWorld: (keys: string[], value: any) => {
|
||||
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, true);
|
||||
},
|
||||
overrideGlobalPropertyFromIsolatedWorld: (keys: string[], getter: Function, setter?: Function) => {
|
||||
return binding._overrideGlobalPropertyFromIsolatedWorld(keys, getter, setter || null);
|
||||
},
|
||||
isInMainWorld: () => binding._isCalledFromMainWorld() as boolean,
|
||||
isInIsolatedWorld: () => binding._isCalledFromIsolatedWorld() as boolean
|
||||
};
|
||||
|
||||
@@ -5,28 +5,30 @@ const v8Util = process.electronBinding('v8_util');
|
||||
const ipcRenderer = v8Util.getHiddenValue<Electron.IpcRenderer>(global, 'ipc');
|
||||
const internal = false;
|
||||
|
||||
ipcRenderer.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
if (!ipcRenderer.send) {
|
||||
ipcRenderer.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
|
||||
ipcRenderer.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
ipcRenderer.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
|
||||
ipcRenderer.sendToHost = function (channel, ...args) {
|
||||
return ipc.sendToHost(channel, args);
|
||||
};
|
||||
ipcRenderer.sendToHost = function (channel, ...args) {
|
||||
return ipc.sendToHost(channel, args);
|
||||
};
|
||||
|
||||
ipcRenderer.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
ipcRenderer.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
|
||||
ipcRenderer.invoke = async function (channel, ...args) {
|
||||
const { error, result } = await ipc.invoke(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
ipcRenderer.invoke = async function (channel, ...args) {
|
||||
const { error, result } = await ipc.invoke(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export default ipcRenderer;
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const { hasSwitch } = process.electronBinding('command_line');
|
||||
const { NativeImage } = process.electronBinding('native_image');
|
||||
|
||||
const { CallbacksRegistry } = require('@electron/internal/renderer/remote/callbacks-registry');
|
||||
const { isPromise, isSerializableObject } = require('@electron/internal/common/type-utils');
|
||||
const { isPromise, isSerializableObject, serialize, deserialize } = require('@electron/internal/common/type-utils');
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||
|
||||
const callbacksRegistry = new CallbacksRegistry();
|
||||
@@ -33,7 +34,9 @@ function wrapArgs (args, visited = new Set()) {
|
||||
};
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
if (value instanceof NativeImage) {
|
||||
return { type: 'nativeimage', value: serialize(value) };
|
||||
} else if (Array.isArray(value)) {
|
||||
visited.add(value);
|
||||
const meta = {
|
||||
type: 'array',
|
||||
@@ -213,6 +216,7 @@ function metaToValue (meta) {
|
||||
const types = {
|
||||
value: () => meta.value,
|
||||
array: () => meta.members.map((member) => metaToValue(member)),
|
||||
nativeimage: () => deserialize(meta.value),
|
||||
buffer: () => Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength),
|
||||
promise: () => Promise.resolve({ then: metaToValue(meta.then) }),
|
||||
error: () => metaToError(meta),
|
||||
|
||||
@@ -5,26 +5,28 @@ const v8Util = process.electronBinding('v8_util');
|
||||
export const ipcRendererInternal = v8Util.getHiddenValue<Electron.IpcRendererInternal>(global, 'ipc-internal');
|
||||
const internal = true;
|
||||
|
||||
ipcRendererInternal.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
if (!ipcRendererInternal.send) {
|
||||
ipcRendererInternal.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
ipcRendererInternal.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args)[0];
|
||||
};
|
||||
|
||||
ipcRendererInternal.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
ipcRendererInternal.sendTo = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, false, webContentsId, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.sendToAll = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, true, webContentsId, channel, args);
|
||||
};
|
||||
ipcRendererInternal.sendToAll = function (webContentsId, channel, ...args) {
|
||||
return ipc.sendTo(internal, true, webContentsId, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[]) {
|
||||
const { error, result } = await ipc.invoke<T>(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[]) {
|
||||
const { error, result } = await ipc.invoke<T>(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -110,9 +110,14 @@ export function attachGuest (
|
||||
ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', embedderFrameId, elementInstanceId, guestInstanceId, params);
|
||||
}
|
||||
|
||||
export function detachGuest (guestInstanceId: number) {
|
||||
return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_DETACH_GUEST', guestInstanceId);
|
||||
}
|
||||
|
||||
export const guestViewInternalModule = {
|
||||
deregisterEvents,
|
||||
createGuest,
|
||||
createGuestSync,
|
||||
attachGuest
|
||||
attachGuest,
|
||||
detachGuest
|
||||
};
|
||||
|
||||
@@ -66,6 +66,9 @@ const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof
|
||||
return;
|
||||
}
|
||||
guestViewInternal.deregisterEvents(internal.viewInstanceId);
|
||||
if (internal.guestInstanceId) {
|
||||
guestViewInternal.detachGuest(internal.guestInstanceId);
|
||||
}
|
||||
internal.elementAttached = false;
|
||||
this.internalInstanceId = 0;
|
||||
internal.reset();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { internalContextBridge } from '@electron/internal/renderer/api/context-bridge';
|
||||
|
||||
// This file implements the following APIs:
|
||||
// - window.history.back()
|
||||
// - window.history.forward()
|
||||
// - window.history.go()
|
||||
// - window.history.length
|
||||
const { contextIsolationEnabled, isInIsolatedWorld } = internalContextBridge;
|
||||
const shouldUseContextBridge = contextIsolationEnabled && isInIsolatedWorld();
|
||||
|
||||
// This file implements the following APIs over the ctx bridge:
|
||||
// - window.open()
|
||||
// - window.opener.blur()
|
||||
// - window.opener.close()
|
||||
@@ -13,7 +13,12 @@ import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-inte
|
||||
// - window.opener.focus()
|
||||
// - window.opener.location
|
||||
// - window.opener.print()
|
||||
// - window.opener.closed
|
||||
// - window.opener.postMessage()
|
||||
// - window.history.back()
|
||||
// - window.history.forward()
|
||||
// - window.history.go()
|
||||
// - window.history.length
|
||||
// - window.prompt()
|
||||
// - document.hidden
|
||||
// - document.visibilityState
|
||||
@@ -30,13 +35,13 @@ const toString = (value: any) => {
|
||||
|
||||
const windowProxies = new Map<number, BrowserWindowProxy>();
|
||||
|
||||
const getOrCreateProxy = (guestId: number) => {
|
||||
const getOrCreateProxy = (guestId: number): SafelyBoundBrowserWindowProxy => {
|
||||
let proxy = windowProxies.get(guestId);
|
||||
if (proxy == null) {
|
||||
proxy = new BrowserWindowProxy(guestId);
|
||||
windowProxies.set(guestId, proxy);
|
||||
}
|
||||
return proxy;
|
||||
return proxy.getSafe();
|
||||
};
|
||||
|
||||
const removeProxy = (guestId: number) => {
|
||||
@@ -64,6 +69,8 @@ class LocationProxy {
|
||||
*/
|
||||
private static ProxyProperty<T> (target: LocationProxy, propertyKey: LocationProperties) {
|
||||
Object.defineProperty(target, propertyKey, {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: function (this: LocationProxy): T | string {
|
||||
const guestURL = this.getGuestURL();
|
||||
const value = guestURL ? guestURL[propertyKey] : '';
|
||||
@@ -82,6 +89,30 @@ class LocationProxy {
|
||||
});
|
||||
}
|
||||
|
||||
public getSafe = () => {
|
||||
const that = this;
|
||||
return {
|
||||
get href () { return that.href; },
|
||||
set href (newValue) { that.href = newValue; },
|
||||
get hash () { return that.hash; },
|
||||
set hash (newValue) { that.hash = newValue; },
|
||||
get host () { return that.host; },
|
||||
set host (newValue) { that.host = newValue; },
|
||||
get hostname () { return that.hostname; },
|
||||
set hostname (newValue) { that.hostname = newValue; },
|
||||
get origin () { return that.origin; },
|
||||
set origin (newValue) { that.origin = newValue; },
|
||||
get pathname () { return that.pathname; },
|
||||
set pathname (newValue) { that.pathname = newValue; },
|
||||
get port () { return that.port; },
|
||||
set port (newValue) { that.port = newValue; },
|
||||
get protocol () { return that.protocol; },
|
||||
set protocol (newValue) { that.protocol = newValue; },
|
||||
get search () { return that.search; },
|
||||
set search (newValue) { that.search = newValue; }
|
||||
};
|
||||
}
|
||||
|
||||
constructor (guestId: number) {
|
||||
// eslint will consider the constructor "useless"
|
||||
// unless we assign them in the body. It's fine, that's what
|
||||
@@ -95,7 +126,11 @@ class LocationProxy {
|
||||
}
|
||||
|
||||
private getGuestURL (): URL | null {
|
||||
const urlString = this._invokeWebContentsMethodSync('getURL') as string;
|
||||
const maybeURL = this._invokeWebContentsMethodSync('getURL') as string;
|
||||
|
||||
// When there's no previous frame the url will be blank, so accountfor that here
|
||||
// to prevent url parsing errors on an empty string.
|
||||
const urlString = maybeURL !== '' ? maybeURL : 'about:blank';
|
||||
try {
|
||||
return new URL(urlString);
|
||||
} catch (e) {
|
||||
@@ -114,6 +149,17 @@ class LocationProxy {
|
||||
}
|
||||
}
|
||||
|
||||
interface SafelyBoundBrowserWindowProxy {
|
||||
location: WindowProxy['location'];
|
||||
blur: WindowProxy['blur'];
|
||||
close: WindowProxy['close'];
|
||||
eval: typeof eval; // eslint-disable-line no-eval
|
||||
focus: WindowProxy['focus'];
|
||||
print: WindowProxy['print'];
|
||||
postMessage: WindowProxy['postMessage'];
|
||||
closed: boolean;
|
||||
}
|
||||
|
||||
class BrowserWindowProxy {
|
||||
public closed: boolean = false
|
||||
|
||||
@@ -124,7 +170,7 @@ class BrowserWindowProxy {
|
||||
// so for now, we'll have to make do with an "any" in the mix.
|
||||
// https://github.com/Microsoft/TypeScript/issues/2521
|
||||
public get location (): LocationProxy | any {
|
||||
return this._location;
|
||||
return this._location.getSafe();
|
||||
}
|
||||
public set location (url: string | any) {
|
||||
url = resolveURL(url, this.location.href);
|
||||
@@ -141,27 +187,48 @@ class BrowserWindowProxy {
|
||||
});
|
||||
}
|
||||
|
||||
public close () {
|
||||
public getSafe = (): SafelyBoundBrowserWindowProxy => {
|
||||
const that = this;
|
||||
return {
|
||||
postMessage: this.postMessage,
|
||||
blur: this.blur,
|
||||
close: this.close,
|
||||
focus: this.focus,
|
||||
print: this.print,
|
||||
eval: this.eval,
|
||||
get location () {
|
||||
return that.location;
|
||||
},
|
||||
set location (url: string | any) {
|
||||
that.location = url;
|
||||
},
|
||||
get closed () {
|
||||
return that.closed;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public close = () => {
|
||||
this._invokeWindowMethod('destroy');
|
||||
}
|
||||
|
||||
public focus () {
|
||||
public focus = () => {
|
||||
this._invokeWindowMethod('focus');
|
||||
}
|
||||
|
||||
public blur () {
|
||||
public blur = () => {
|
||||
this._invokeWindowMethod('blur');
|
||||
}
|
||||
|
||||
public print () {
|
||||
public print = () => {
|
||||
this._invokeWebContentsMethod('print');
|
||||
}
|
||||
|
||||
public postMessage (message: any, targetOrigin: string) {
|
||||
public postMessage = (message: any, targetOrigin: string) => {
|
||||
ipcRendererInternal.invoke('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', this.guestId, message, toString(targetOrigin), window.location.origin);
|
||||
}
|
||||
|
||||
public eval (code: string) {
|
||||
public eval = (code: string) => {
|
||||
this._invokeWebContentsMethod('executeJavaScript', code);
|
||||
}
|
||||
|
||||
@@ -182,9 +249,11 @@ export const windowSetup = (
|
||||
window.close = function () {
|
||||
ipcRendererInternal.sendSync('ELECTRON_BROWSER_WINDOW_CLOSE');
|
||||
};
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['close'], window.close);
|
||||
}
|
||||
|
||||
if (!usesNativeWindowOpen) {
|
||||
// TODO(MarshallOfSound): Make compatible with ctx isolation without hole-punch
|
||||
// Make the browser window or guest view emit "new-window" event.
|
||||
(window as any).open = function (url?: string, frameName?: string, features?: string) {
|
||||
if (url != null && url !== '') {
|
||||
@@ -197,16 +266,19 @@ export const windowSetup = (
|
||||
return null;
|
||||
}
|
||||
};
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['open'], window.open);
|
||||
}
|
||||
|
||||
if (openerId != null) {
|
||||
window.opener = getOrCreateProxy(openerId);
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['opener'], window.opener);
|
||||
}
|
||||
|
||||
// But we do not support prompt().
|
||||
window.prompt = function () {
|
||||
throw new Error('prompt() is and will not be supported.');
|
||||
};
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['prompt'], window.prompt);
|
||||
|
||||
if (!usesNativeWindowOpen || openerId != null) {
|
||||
ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
|
||||
@@ -233,20 +305,25 @@ export const windowSetup = (
|
||||
window.history.back = function () {
|
||||
ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK');
|
||||
};
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['history', 'back'], window.history.back);
|
||||
|
||||
window.history.forward = function () {
|
||||
ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_FORWARD');
|
||||
};
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['history', 'forward'], window.history.forward);
|
||||
|
||||
window.history.go = function (offset: number) {
|
||||
ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_TO_OFFSET', +offset);
|
||||
};
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['history', 'go'], window.history.go);
|
||||
|
||||
const getHistoryLength = () => ipcRendererInternal.sendSync('ELECTRON_NAVIGATION_CONTROLLER_LENGTH');
|
||||
Object.defineProperty(window.history, 'length', {
|
||||
get: function () {
|
||||
return ipcRendererInternal.sendSync('ELECTRON_NAVIGATION_CONTROLLER_LENGTH');
|
||||
}
|
||||
get: getHistoryLength,
|
||||
set () {}
|
||||
});
|
||||
// TODO(MarshallOfSound): Fix so that the internal context bridge can override a non-configurable property
|
||||
// if (shouldUseContextBridge) internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['history', 'length'], getHistoryLength);
|
||||
}
|
||||
|
||||
if (guestInstanceId != null) {
|
||||
@@ -268,16 +345,16 @@ export const windowSetup = (
|
||||
});
|
||||
|
||||
// Make document.hidden and document.visibilityState return the correct value.
|
||||
const getDocumentHidden = () => cachedVisibilityState !== 'visible';
|
||||
Object.defineProperty(document, 'hidden', {
|
||||
get: function () {
|
||||
return cachedVisibilityState !== 'visible';
|
||||
}
|
||||
get: getDocumentHidden
|
||||
});
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['document', 'hidden'], getDocumentHidden);
|
||||
|
||||
const getDocumentVisibilityState = () => cachedVisibilityState;
|
||||
Object.defineProperty(document, 'visibilityState', {
|
||||
get: function () {
|
||||
return cachedVisibilityState;
|
||||
}
|
||||
get: getDocumentVisibilityState
|
||||
});
|
||||
if (shouldUseContextBridge) internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['document', 'visibilityState'], getDocumentVisibilityState);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -114,6 +114,12 @@ function preloadRequire (module) {
|
||||
// Process command line arguments.
|
||||
const { hasSwitch } = process.electronBinding('command_line');
|
||||
|
||||
// Similar to nodes --expose-internals flag, this exposes electronBinding so
|
||||
// that tests can call it to get access to some test only bindings
|
||||
if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
preloadProcess.electronBinding = process.electronBinding;
|
||||
}
|
||||
|
||||
const contextIsolation = hasSwitch('context-isolation');
|
||||
const isHiddenPage = hasSwitch('hidden-page');
|
||||
const usesNativeWindowOpen = true;
|
||||
|
||||
@@ -23,6 +23,8 @@ source_set("native_mate") {
|
||||
"native_mate/function_template.cc",
|
||||
"native_mate/function_template.h",
|
||||
"native_mate/handle.h",
|
||||
"native_mate/microtasks_scope.cc",
|
||||
"native_mate/microtasks_scope.h",
|
||||
"native_mate/object_template_builder.cc",
|
||||
"native_mate/object_template_builder_deprecated.h",
|
||||
"native_mate/persistent_dictionary.cc",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/microtasks_scope.h"
|
||||
#include "native_mate/wrappable_base.h"
|
||||
#include "shell/common/gin_helper/destroyable.h"
|
||||
#include "shell/common/gin_helper/error_thrower.h"
|
||||
@@ -194,8 +195,7 @@ class Invoker<IndicesHolder<indices...>, ArgTypes...>
|
||||
|
||||
template <typename ReturnType>
|
||||
void DispatchToCallback(base::Callback<ReturnType(ArgTypes...)> callback) {
|
||||
v8::MicrotasksScope script_scope(args_->isolate(),
|
||||
v8::MicrotasksScope::kRunMicrotasks);
|
||||
mate::MicrotasksScope microtasks_scope(args_->isolate(), true);
|
||||
args_->Return(
|
||||
callback.Run(std::move(ArgumentHolder<indices, ArgTypes>::value)...));
|
||||
}
|
||||
@@ -204,8 +204,7 @@ class Invoker<IndicesHolder<indices...>, ArgTypes...>
|
||||
// expression to foo. As a result, we must specialize the case of Callbacks
|
||||
// that have the void return type.
|
||||
void DispatchToCallback(base::Callback<void(ArgTypes...)> callback) {
|
||||
v8::MicrotasksScope script_scope(args_->isolate(),
|
||||
v8::MicrotasksScope::kRunMicrotasks);
|
||||
mate::MicrotasksScope microtasks_scope(args_->isolate(), true);
|
||||
callback.Run(std::move(ArgumentHolder<indices, ArgTypes>::value)...);
|
||||
}
|
||||
|
||||
|
||||
22
native_mate/native_mate/microtasks_scope.cc
Normal file
22
native_mate/native_mate/microtasks_scope.cc
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2020 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "native_mate/microtasks_scope.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
MicrotasksScope::MicrotasksScope(v8::Isolate* isolate,
|
||||
bool ignore_browser_checkpoint) {
|
||||
if (v8::Locker::IsActive()) {
|
||||
if (!ignore_browser_checkpoint)
|
||||
v8::MicrotasksScope::PerformCheckpoint(isolate);
|
||||
} else {
|
||||
v8_microtasks_scope_ = std::make_unique<v8::MicrotasksScope>(
|
||||
isolate, v8::MicrotasksScope::kRunMicrotasks);
|
||||
}
|
||||
}
|
||||
|
||||
MicrotasksScope::~MicrotasksScope() = default;
|
||||
|
||||
} // namespace mate
|
||||
31
native_mate/native_mate/microtasks_scope.h
Normal file
31
native_mate/native_mate/microtasks_scope.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2020 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef NATIVE_MATE_NATIVE_MATE_MICROTASKS_SCOPE_H_
|
||||
#define NATIVE_MATE_NATIVE_MATE_MICROTASKS_SCOPE_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
// In the browser process runs v8::MicrotasksScope::PerformCheckpoint
|
||||
// In the render process creates a v8::MicrotasksScope.
|
||||
class MicrotasksScope {
|
||||
public:
|
||||
explicit MicrotasksScope(v8::Isolate* isolate,
|
||||
bool ignore_browser_checkpoint = false);
|
||||
~MicrotasksScope();
|
||||
|
||||
private:
|
||||
std::unique_ptr<v8::MicrotasksScope> v8_microtasks_scope_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MicrotasksScope);
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // NATIVE_MATE_NATIVE_MATE_MICROTASKS_SCOPE_H_
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "8.2.0",
|
||||
"version": "8.5.0",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
1
patches/angle/.patches
Normal file
1
patches/angle/.patches
Normal file
@@ -0,0 +1 @@
|
||||
update_the_active_texture_cache_before_changing_the_texture_binding.patch
|
||||
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Fri, 27 Mar 2020 12:24:52 -0400
|
||||
Subject: Update the active texture cache before changing the texture binding.
|
||||
|
||||
When a new texture is bound, the texture binding state is updated before
|
||||
updating the active texture cache. With this ordering, it is possible to delete
|
||||
the currently bound texture when the binding changes and then use-after-free it
|
||||
when updating the active texture cache.
|
||||
|
||||
BUG=angleproject:1065186
|
||||
|
||||
Change-Id: Id6d56b6c6db423755b195cda1e5cf1bcb1ee7aee
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2124588
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
|
||||
index 3fab8404046846e5b8ed6253139537360e83c409..c6c6ee75ebf554ce47cfcef218dca6a22075a4aa 100644
|
||||
--- a/src/libANGLE/State.cpp
|
||||
+++ b/src/libANGLE/State.cpp
|
||||
@@ -1138,14 +1138,14 @@ void State::setActiveSampler(unsigned int active)
|
||||
|
||||
void State::setSamplerTexture(const Context *context, TextureType type, Texture *texture)
|
||||
{
|
||||
- mSamplerTextures[type][mActiveSampler].set(context, texture);
|
||||
-
|
||||
if (mProgram && mProgram->getActiveSamplersMask()[mActiveSampler] &&
|
||||
mProgram->getActiveSamplerTypes()[mActiveSampler] == type)
|
||||
{
|
||||
updateActiveTexture(context, mActiveSampler, texture);
|
||||
}
|
||||
|
||||
+ mSamplerTextures[type][mActiveSampler].set(context, texture);
|
||||
+
|
||||
mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
expose_ripemd160.patch
|
||||
expose_aes-cfb.patch
|
||||
fix_add_RSA-PSS_keygen_functions.patch
|
||||
fix_add_RSA-PSS_keygen_functions.patch
|
||||
|
||||
@@ -90,3 +90,33 @@ fix_route_mouse_event_navigations_through_the_web_contents_delegate.patch
|
||||
feat_add_support_for_overriding_the_base_spellchecker_download_url.patch
|
||||
os_metrics_mac.patch
|
||||
feat_allow_embedders_to_add_observers_on_created_hunspell.patch
|
||||
feat_enable_offscreen_rendering_with_viz_compositor.patch
|
||||
when_suspending_context_don_t_clear_handlers.patch
|
||||
use_keepselfalive_on_audiocontext_to_keep_it_alive_until_rendering.patch
|
||||
never_let_a_non-zero-size_pixel_snap_to_zero_size.patch
|
||||
cherry-pick-826a4af58b3d.patch
|
||||
cherry-pick-686d1bfbcb8f.patch
|
||||
cherry-pick-7101418f85a0.patch
|
||||
cherry-pick-38990b7d56e6.patch
|
||||
cherry-pick-67864c214770.patch
|
||||
cherry-pick-86c02c5dcd37.patch
|
||||
fix_hunspell_crash.patch
|
||||
avoid_nullptr_dereference_in_rtcpeerconnectionhandler.patch
|
||||
reland_onstate_handler_is_allowed_to_close_a_peerconnection.patch
|
||||
fix_swap_global_proxies_before_initializing_the_windows_proxies.patch
|
||||
fix_default_to_ntlm_v2_in_network_service.patch
|
||||
a11y_allows_klistboxoption_as_an_item_to_kgroup.patch
|
||||
fix_handling_non_client_pointer_events_from_pen_on_windows_10.patch
|
||||
a11y_iterate_all_descendants_for_getselectioncount.patch
|
||||
allow_ime_to_insert_zero-length_composition_string.patch
|
||||
cherry-pick-eac3d9283d11.patch
|
||||
remove_menu_window_task_item.patch
|
||||
backport_1063177.patch
|
||||
backport_1019161.patch
|
||||
avoid_using_x11_shm_for_remote_connections.patch
|
||||
backport_1065122.patch
|
||||
backport_1074317.patch
|
||||
backport_1090543.patch
|
||||
backport_1081722.patch
|
||||
backport_1073409.patch
|
||||
backport_1074340.patch
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Julie Jeongeun Kim <jkim@igalia.com>
|
||||
Date: Fri, 3 Apr 2020 19:22:20 +0000
|
||||
Subject: a11y: Allows kListBoxOption as an item to kGroup
|
||||
|
||||
This CL adds ListBoxOption role as an item for Group role in
|
||||
AXNode::SetRoleMatchesItemRole() since Group role could have
|
||||
ListBoxOption as an item[1]. With this change, when the parent
|
||||
of ListBoxOption is a group role, PosInSet and SetSize has
|
||||
proper values.
|
||||
|
||||
[1]https://w3c.github.io/aria-practices/examples/listbox/listbox-grouped.html
|
||||
|
||||
Bug: 1066632
|
||||
Change-Id: I23cf0c34ee479d6e8ee33b3f9e327def820527e1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2134037
|
||||
Commit-Queue: Dominic Mazzoni <dmazzoni@chromium.org>
|
||||
Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#756360}
|
||||
|
||||
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc
|
||||
index df021746aab26a61096922e902815931af4621dc..d4451bbb638b42164fe8ec9f4c37a0d93efd8aa3 100644
|
||||
--- a/ui/accessibility/ax_node.cc
|
||||
+++ b/ui/accessibility/ax_node.cc
|
||||
@@ -778,6 +778,7 @@ bool AXNode::SetRoleMatchesItemRole(const AXNode* ordered_set) const {
|
||||
return item_role == ax::mojom::Role::kListItem ||
|
||||
item_role == ax::mojom::Role::kMenuItem ||
|
||||
item_role == ax::mojom::Role::kMenuItemRadio ||
|
||||
+ item_role == ax::mojom::Role::kListBoxOption ||
|
||||
item_role == ax::mojom::Role::kTreeItem;
|
||||
case ax::mojom::Role::kMenu:
|
||||
return item_role == ax::mojom::Role::kMenuItem ||
|
||||
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc
|
||||
index 84952172938446254e53c2ee11cba37433d0e991..91a7be0f349116dc48cbe543104a6e7828ddf2e8 100644
|
||||
--- a/ui/accessibility/ax_tree_unittest.cc
|
||||
+++ b/ui/accessibility/ax_tree_unittest.cc
|
||||
@@ -3549,6 +3549,43 @@ TEST(AXTreeTest, TestSetSizePosInSetMenuItemValidChildOfMenuListPopup) {
|
||||
EXPECT_OPTIONAL_EQ(2, item2->GetSetSize());
|
||||
}
|
||||
|
||||
+TEST(AXTreeTest, TestSetSizePostInSetListBoxOptionWithGroup) {
|
||||
+ AXTreeUpdate initial_state;
|
||||
+ initial_state.root_id = 1;
|
||||
+ initial_state.nodes.resize(7);
|
||||
+ initial_state.nodes[0].id = 1;
|
||||
+ initial_state.nodes[0].child_ids = {2, 3};
|
||||
+ initial_state.nodes[0].role = ax::mojom::Role::kListBox;
|
||||
+ initial_state.nodes[1].id = 2;
|
||||
+ initial_state.nodes[1].child_ids = {4, 5};
|
||||
+ initial_state.nodes[1].role = ax::mojom::Role::kGroup;
|
||||
+ initial_state.nodes[2].id = 3;
|
||||
+ initial_state.nodes[2].child_ids = {6, 7};
|
||||
+ initial_state.nodes[2].role = ax::mojom::Role::kGroup;
|
||||
+ initial_state.nodes[3].id = 4;
|
||||
+ initial_state.nodes[3].role = ax::mojom::Role::kListBoxOption;
|
||||
+ initial_state.nodes[4].id = 5;
|
||||
+ initial_state.nodes[4].role = ax::mojom::Role::kListBoxOption;
|
||||
+ initial_state.nodes[5].id = 6;
|
||||
+ initial_state.nodes[5].role = ax::mojom::Role::kListBoxOption;
|
||||
+ initial_state.nodes[6].id = 7;
|
||||
+ initial_state.nodes[6].role = ax::mojom::Role::kListBoxOption;
|
||||
+ AXTree tree(initial_state);
|
||||
+
|
||||
+ AXNode* listbox_option1 = tree.GetFromId(4);
|
||||
+ EXPECT_OPTIONAL_EQ(1, listbox_option1->GetPosInSet());
|
||||
+ EXPECT_OPTIONAL_EQ(2, listbox_option1->GetSetSize());
|
||||
+ AXNode* listbox_option2 = tree.GetFromId(5);
|
||||
+ EXPECT_OPTIONAL_EQ(2, listbox_option2->GetPosInSet());
|
||||
+ EXPECT_OPTIONAL_EQ(2, listbox_option2->GetSetSize());
|
||||
+ AXNode* listbox_option3 = tree.GetFromId(6);
|
||||
+ EXPECT_OPTIONAL_EQ(1, listbox_option3->GetPosInSet());
|
||||
+ EXPECT_OPTIONAL_EQ(2, listbox_option3->GetSetSize());
|
||||
+ AXNode* listbox_option4 = tree.GetFromId(7);
|
||||
+ EXPECT_OPTIONAL_EQ(2, listbox_option4->GetPosInSet());
|
||||
+ EXPECT_OPTIONAL_EQ(2, listbox_option4->GetSetSize());
|
||||
+}
|
||||
+
|
||||
TEST(AXTreeTest, OnNodeWillBeDeletedHasValidUnignoredParent) {
|
||||
AXTreeUpdate initial_state;
|
||||
initial_state.root_id = 1;
|
||||
@@ -0,0 +1,393 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Julie Jeongeun Kim <jkim@igalia.com>
|
||||
Date: Fri, 10 Apr 2020 05:50:17 +0000
|
||||
Subject: a11y: Iterate all descendants for GetSelectionCount
|
||||
|
||||
This CL iterates all descendants for GetSelectionCount and
|
||||
GetSelectedChild. When listbox has group children, it should
|
||||
iterates their children as well to check the select state.
|
||||
|
||||
Bug: 1058961
|
||||
Change-Id: Ib6459bf6f47023d4258ef4c2f2dc545739d7a61b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2115211
|
||||
Commit-Queue: Julie Kim <jkim@igalia.com>
|
||||
Reviewed-by: Nektarios Paisios <nektar@chromium.org>
|
||||
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
|
||||
Reviewed-by: Joanmarie Diggs <jdiggs@igalia.com>
|
||||
Cr-Commit-Position: refs/heads/master@{#758140}
|
||||
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
|
||||
index 86ce9de34a5286b1c3990c4aab614450e1d6fb63..88528364e148284b7e45958451a65497c295f256 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
|
||||
@@ -1435,19 +1435,10 @@ AtkObject* RefSelection(AtkSelection* selection, gint requested_child_index) {
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
- int child_count = obj->GetChildCount();
|
||||
- gint selected_count = 0;
|
||||
- for (int i = 0; i < child_count; ++i) {
|
||||
- AtkObject* child = obj->ChildAtIndex(i);
|
||||
- AXPlatformNodeAuraLinux* child_ax_node =
|
||||
- AtkObjectToAXPlatformNodeAuraLinux(child);
|
||||
- if (!child_ax_node)
|
||||
- continue;
|
||||
-
|
||||
- if (child_ax_node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
|
||||
- if (selected_count == requested_child_index)
|
||||
- return static_cast<AtkObject*>(g_object_ref(child));
|
||||
- ++selected_count;
|
||||
+ if (auto* selected_child = obj->GetSelectedItem(requested_child_index)) {
|
||||
+ if (AtkObject* atk_object = selected_child->GetNativeViewAccessible()) {
|
||||
+ g_object_ref(atk_object);
|
||||
+ return atk_object;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1460,19 +1451,7 @@ gint GetSelectionCount(AtkSelection* selection) {
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
- int child_count = obj->GetChildCount();
|
||||
- gint selected_count = 0;
|
||||
- for (int i = 0; i < child_count; ++i) {
|
||||
- AXPlatformNodeAuraLinux* child =
|
||||
- AtkObjectToAXPlatformNodeAuraLinux(obj->ChildAtIndex(i));
|
||||
- if (!child)
|
||||
- continue;
|
||||
-
|
||||
- if (child->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected))
|
||||
- ++selected_count;
|
||||
- }
|
||||
-
|
||||
- return selected_count;
|
||||
+ return obj->GetSelectionCount();
|
||||
}
|
||||
|
||||
gboolean IsChildSelected(AtkSelection* selection, gint index) {
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc b/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
|
||||
index f17dbeda08917ef636f1f4342011394f076cee35..eb61fc1c1224e8a2ca94929e07f24bfa7dc41691 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
|
||||
@@ -1853,6 +1853,8 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkSelectionInterface) {
|
||||
AXNodeData root;
|
||||
root.id = 1;
|
||||
root.role = ax::mojom::Role::kListBox;
|
||||
+ root.AddState(ax::mojom::State::kFocusable);
|
||||
+ root.AddState(ax::mojom::State::kMultiselectable);
|
||||
root.child_ids.push_back(2);
|
||||
root.child_ids.push_back(3);
|
||||
root.child_ids.push_back(4);
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
|
||||
index d705cd927ed816208b22106e5beb30c550c55ca3..bf9dc27604ff5ae7f88c8fd734ec26c699e7bc04 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_base.cc
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
|
||||
@@ -92,7 +92,7 @@ int AXPlatformNodeBase::GetChildCount() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-gfx::NativeViewAccessible AXPlatformNodeBase::ChildAtIndex(int index) {
|
||||
+gfx::NativeViewAccessible AXPlatformNodeBase::ChildAtIndex(int index) const {
|
||||
if (delegate_)
|
||||
return delegate_->ChildAtIndex(index);
|
||||
return nullptr;
|
||||
@@ -701,8 +701,8 @@ bool AXPlatformNodeBase::HasCaret() {
|
||||
return focus_object->IsDescendantOf(this);
|
||||
}
|
||||
|
||||
-bool AXPlatformNodeBase::IsLeaf() {
|
||||
- if (GetChildCount() == 0)
|
||||
+bool AXPlatformNodeBase::IsLeaf() const {
|
||||
+ if (!GetChildCount())
|
||||
return true;
|
||||
|
||||
// These types of objects may have children that we use as internal
|
||||
@@ -1868,9 +1868,73 @@ ui::TextAttributeList AXPlatformNodeBase::ComputeTextAttributes() const {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
+int AXPlatformNodeBase::GetSelectionCount() const {
|
||||
+ int max_items = GetMaxSelectableItems();
|
||||
+ if (!max_items)
|
||||
+ return 0;
|
||||
+ return GetSelectedItems(max_items);
|
||||
+}
|
||||
+
|
||||
+AXPlatformNodeBase* AXPlatformNodeBase::GetSelectedItem(
|
||||
+ int selected_index) const {
|
||||
+ DCHECK_GE(selected_index, 0);
|
||||
+ int max_items = GetMaxSelectableItems();
|
||||
+ if (max_items == 0)
|
||||
+ return nullptr;
|
||||
+ if (selected_index >= max_items)
|
||||
+ return nullptr;
|
||||
+
|
||||
+ std::vector<AXPlatformNodeBase*> selected_children;
|
||||
+ int requested_count = selected_index + 1;
|
||||
+ int returned_count = GetSelectedItems(requested_count, &selected_children);
|
||||
+
|
||||
+ if (returned_count <= selected_index)
|
||||
+ return nullptr;
|
||||
+
|
||||
+ DCHECK(!selected_children.empty());
|
||||
+ DCHECK_LT(selected_index, static_cast<int>(selected_children.size()));
|
||||
+ return selected_children[selected_index];
|
||||
+}
|
||||
+
|
||||
+int AXPlatformNodeBase::GetSelectedItems(
|
||||
+ int max_items,
|
||||
+ std::vector<AXPlatformNodeBase*>* out_selected_items) const {
|
||||
+ int selected_count = 0;
|
||||
+ // TODO(Nektar): Remove const_cast by making all tree traversal methods const.
|
||||
+ for (AXPlatformNodeBase* child =
|
||||
+ const_cast<AXPlatformNodeBase*>(this)->GetFirstChild();
|
||||
+ child && selected_count < max_items; child = child->GetNextSibling()) {
|
||||
+ if (!IsItemLike(child->GetData().role)) {
|
||||
+ selected_count += child->GetSelectedItems(max_items - selected_count,
|
||||
+ out_selected_items);
|
||||
+ } else if (child->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
|
||||
+ selected_count++;
|
||||
+ if (out_selected_items)
|
||||
+ out_selected_items->emplace_back(child);
|
||||
+ }
|
||||
+ }
|
||||
+ return selected_count;
|
||||
+}
|
||||
+
|
||||
void AXPlatformNodeBase::SanitizeTextAttributeValue(const std::string& input,
|
||||
std::string* output) const {
|
||||
DCHECK(output);
|
||||
}
|
||||
|
||||
+int AXPlatformNodeBase::GetMaxSelectableItems() const {
|
||||
+ if (!GetData().HasState(ax::mojom::State::kFocusable))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (IsLeaf())
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!IsContainerWithSelectableChildren(GetData().role))
|
||||
+ return 0;
|
||||
+
|
||||
+ int max_items = 1;
|
||||
+ if (GetData().HasState(ax::mojom::State::kMultiselectable))
|
||||
+ max_items = std::numeric_limits<int>::max();
|
||||
+ return max_items;
|
||||
+}
|
||||
+
|
||||
} // namespace ui
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h
|
||||
index 2bee9a7e3108963847486139d40a087428323fbb..98a72c6be316803618f74ae0766e1fd24515509a 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_base.h
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_base.h
|
||||
@@ -57,7 +57,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
|
||||
gfx::NativeViewAccessible GetFocus();
|
||||
gfx::NativeViewAccessible GetParent() const;
|
||||
int GetChildCount() const;
|
||||
- gfx::NativeViewAccessible ChildAtIndex(int index);
|
||||
+ gfx::NativeViewAccessible ChildAtIndex(int index) const;
|
||||
|
||||
// This needs to be implemented for each platform.
|
||||
virtual int GetIndexInParent();
|
||||
@@ -202,7 +202,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
|
||||
// The definition of a leaf may vary depending on the platform,
|
||||
// but a leaf node should never have children that are focusable or
|
||||
// that might send notifications.
|
||||
- bool IsLeaf();
|
||||
+ bool IsLeaf() const;
|
||||
|
||||
bool IsInvisibleOrIgnored() const;
|
||||
|
||||
@@ -275,6 +275,24 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
|
||||
|
||||
ui::TextAttributeList ComputeTextAttributes() const;
|
||||
|
||||
+ // Get the number of items selected. It checks kMultiselectable and
|
||||
+ // kFocusable. and uses GetSelectedItems to get the selected number.
|
||||
+ int GetSelectionCount() const;
|
||||
+
|
||||
+ // If this object is a container that supports selectable children, returns
|
||||
+ // the selected item at the provided index.
|
||||
+ AXPlatformNodeBase* GetSelectedItem(int selected_index) const;
|
||||
+
|
||||
+ // If this object is a container that supports selectable children,
|
||||
+ // returns the number of selected items in this container.
|
||||
+ // |out_selected_items| could be set to nullptr if the caller just
|
||||
+ // needs to know the number of items selected.
|
||||
+ // |max_items| represents the number that the caller expects as a
|
||||
+ // maximum. For a single selection list box, it will be 1.
|
||||
+ int GetSelectedItems(
|
||||
+ int max_items,
|
||||
+ std::vector<AXPlatformNodeBase*>* out_selected_items = nullptr) const;
|
||||
+
|
||||
//
|
||||
// Delegate. This is a weak reference which owns |this|.
|
||||
//
|
||||
@@ -412,6 +430,11 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
|
||||
|
||||
std::string GetInvalidValue() const;
|
||||
|
||||
+ // Based on the characteristics of this object, such as its role and the
|
||||
+ // presence of a multiselectable attribute, returns the maximum number of
|
||||
+ // selectable children that this object could potentially contain.
|
||||
+ int GetMaxSelectableItems() const;
|
||||
+
|
||||
AXHypertext hypertext_;
|
||||
|
||||
private:
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_unittest.cc b/ui/accessibility/platform/ax_platform_node_unittest.cc
|
||||
index 9950894e9fbb30b79b392ffe782dd31f75bd7f52..d8bfc0ed9c2b20c64dd15f3c6c2ef8cfaa87c510 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_unittest.cc
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_unittest.cc
|
||||
@@ -379,13 +379,13 @@ AXTreeUpdate AXPlatformNodeTest::BuildListBox(
|
||||
bool option_1_is_selected,
|
||||
bool option_2_is_selected,
|
||||
bool option_3_is_selected,
|
||||
- ax::mojom::State additional_state /* ax::mojom::State::kNone */) {
|
||||
+ const std::vector<ax::mojom::State>& additional_state) {
|
||||
AXNodeData listbox;
|
||||
listbox.id = 1;
|
||||
listbox.SetName("ListBox");
|
||||
listbox.role = ax::mojom::Role::kListBox;
|
||||
- if (additional_state != ax::mojom::State::kNone)
|
||||
- listbox.AddState(additional_state);
|
||||
+ for (auto state : additional_state)
|
||||
+ listbox.AddState(state);
|
||||
|
||||
AXNodeData option_1;
|
||||
option_1.id = 2;
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_unittest.h b/ui/accessibility/platform/ax_platform_node_unittest.h
|
||||
index b512b5a79f103bf4524a7467f4ae60d8036054b6..2b5392f589b26795cc3971be297257b1c2ece615 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_unittest.h
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_unittest.h
|
||||
@@ -58,10 +58,11 @@ class AXPlatformNodeTest : public testing::Test, public AXTreeManager {
|
||||
AXTreeUpdate Build3X3Table();
|
||||
AXTreeUpdate BuildAriaColumnAndRowCountGrids();
|
||||
|
||||
- AXTreeUpdate BuildListBox(bool option_1_is_selected,
|
||||
- bool option_2_is_selected,
|
||||
- bool option_3_is_selected,
|
||||
- ax::mojom::State additional_state);
|
||||
+ AXTreeUpdate BuildListBox(
|
||||
+ bool option_1_is_selected,
|
||||
+ bool option_2_is_selected,
|
||||
+ bool option_3_is_selected,
|
||||
+ const std::vector<ax::mojom::State>& additional_state);
|
||||
|
||||
std::unique_ptr<AXTree> tree_;
|
||||
};
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
|
||||
index 6b70f5eed20290141adc659b71900536ef052bb2..232eff3c4af371eaa7026f2a14953c947b2bda7a 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_win.cc
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
|
||||
@@ -2148,15 +2148,10 @@ IFACEMETHODIMP AXPlatformNodeWin::GetSelection(SAFEARRAY** result) {
|
||||
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTION_GETSELECTION);
|
||||
UIA_VALIDATE_CALL_1_ARG(result);
|
||||
|
||||
- std::vector<AXPlatformNodeWin*> selected_children;
|
||||
- LONG child_count = GetDelegate()->GetChildCount();
|
||||
- for (LONG i = 0; i < child_count; ++i) {
|
||||
- auto* child = static_cast<AXPlatformNodeWin*>(
|
||||
- FromNativeViewAccessible(GetDelegate()->ChildAtIndex(i)));
|
||||
- DCHECK(child);
|
||||
- if (child->GetData().GetBoolAttribute(ax::mojom::BoolAttribute::kSelected))
|
||||
- selected_children.push_back(child);
|
||||
- }
|
||||
+ std::vector<AXPlatformNodeBase*> selected_children;
|
||||
+ int max_items = GetMaxSelectableItems();
|
||||
+ if (max_items)
|
||||
+ GetSelectedItems(max_items, &selected_children);
|
||||
|
||||
LONG selected_children_count = selected_children.size();
|
||||
*result = SafeArrayCreateVector(VT_UNKNOWN, 0, selected_children_count);
|
||||
@@ -2164,9 +2159,10 @@ IFACEMETHODIMP AXPlatformNodeWin::GetSelection(SAFEARRAY** result) {
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for (LONG i = 0; i < selected_children_count; ++i) {
|
||||
+ AXPlatformNodeWin* children =
|
||||
+ static_cast<AXPlatformNodeWin*>(selected_children[i]);
|
||||
HRESULT hr = SafeArrayPutElement(
|
||||
- *result, &i,
|
||||
- static_cast<IRawElementProviderSimple*>(selected_children[i]));
|
||||
+ *result, &i, static_cast<IRawElementProviderSimple*>(children));
|
||||
if (FAILED(hr)) {
|
||||
SafeArrayDestroy(*result);
|
||||
*result = nullptr;
|
||||
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
|
||||
index 31ebeaaae3ea801add4e7f8a609649de425ead04..e64aa75a2dd98ce2968ba314f78423058488cbd7 100644
|
||||
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
|
||||
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
|
||||
@@ -4532,8 +4532,7 @@ TEST_F(AXPlatformNodeWinTest, TestUIANavigate) {
|
||||
TEST_F(AXPlatformNodeWinTest, TestISelectionProviderCanSelectMultipleDefault) {
|
||||
Init(BuildListBox(/*option_1_is_selected*/ false,
|
||||
/*option_2_is_selected*/ false,
|
||||
- /*option_3_is_selected*/ false,
|
||||
- /*additional_state*/ ax::mojom::State::kNone));
|
||||
+ /*option_3_is_selected*/ false, {}));
|
||||
|
||||
ComPtr<ISelectionProvider> selection_provider(
|
||||
QueryInterfaceFromNode<ISelectionProvider>(GetRootNode()));
|
||||
@@ -4545,10 +4544,12 @@ TEST_F(AXPlatformNodeWinTest, TestISelectionProviderCanSelectMultipleDefault) {
|
||||
}
|
||||
|
||||
TEST_F(AXPlatformNodeWinTest, TestISelectionProviderCanSelectMultipleTrue) {
|
||||
+ const std::vector<ax::mojom::State> state = {
|
||||
+ ax::mojom::State::kMultiselectable, ax::mojom::State::kFocusable};
|
||||
Init(BuildListBox(/*option_1_is_selected*/ false,
|
||||
/*option_2_is_selected*/ false,
|
||||
/*option_3_is_selected*/ false,
|
||||
- /*additional_state*/ ax::mojom::State::kMultiselectable));
|
||||
+ /*additional_state*/ state));
|
||||
|
||||
ComPtr<ISelectionProvider> selection_provider(
|
||||
QueryInterfaceFromNode<ISelectionProvider>(GetRootNode()));
|
||||
@@ -4564,7 +4565,7 @@ TEST_F(AXPlatformNodeWinTest,
|
||||
Init(BuildListBox(/*option_1_is_selected*/ false,
|
||||
/*option_2_is_selected*/ false,
|
||||
/*option_3_is_selected*/ false,
|
||||
- /*additional_state*/ ax::mojom::State::kNone));
|
||||
+ /*additional_state*/ {}));
|
||||
|
||||
ComPtr<ISelectionProvider> selection_provider(
|
||||
QueryInterfaceFromNode<ISelectionProvider>(GetRootNode()));
|
||||
@@ -4579,7 +4580,7 @@ TEST_F(AXPlatformNodeWinTest, TestISelectionProviderIsSelectionRequiredTrue) {
|
||||
Init(BuildListBox(/*option_1_is_selected*/ false,
|
||||
/*option_2_is_selected*/ false,
|
||||
/*option_3_is_selected*/ false,
|
||||
- /*additional_state*/ ax::mojom::State::kRequired));
|
||||
+ /*additional_state*/ {ax::mojom::State::kRequired}));
|
||||
|
||||
ComPtr<ISelectionProvider> selection_provider(
|
||||
QueryInterfaceFromNode<ISelectionProvider>(GetRootNode()));
|
||||
@@ -4594,7 +4595,7 @@ TEST_F(AXPlatformNodeWinTest, TestISelectionProviderGetSelectionNoneSelected) {
|
||||
Init(BuildListBox(/*option_1_is_selected*/ false,
|
||||
/*option_2_is_selected*/ false,
|
||||
/*option_3_is_selected*/ false,
|
||||
- /*additional_state*/ ax::mojom::State::kNone));
|
||||
+ /*additional_state*/ {ax::mojom::State::kFocusable}));
|
||||
|
||||
ComPtr<ISelectionProvider> selection_provider(
|
||||
QueryInterfaceFromNode<ISelectionProvider>(GetRootNode()));
|
||||
@@ -4620,7 +4621,7 @@ TEST_F(AXPlatformNodeWinTest,
|
||||
Init(BuildListBox(/*option_1_is_selected*/ false,
|
||||
/*option_2_is_selected*/ true,
|
||||
/*option_3_is_selected*/ false,
|
||||
- /*additional_state*/ ax::mojom::State::kNone));
|
||||
+ /*additional_state*/ {ax::mojom::State::kFocusable}));
|
||||
|
||||
ComPtr<ISelectionProvider> selection_provider(
|
||||
QueryInterfaceFromNode<ISelectionProvider>(GetRootNode()));
|
||||
@@ -4652,10 +4653,12 @@ TEST_F(AXPlatformNodeWinTest,
|
||||
|
||||
TEST_F(AXPlatformNodeWinTest,
|
||||
TestISelectionProviderGetSelectionMultipleItemsSelected) {
|
||||
+ const std::vector<ax::mojom::State> state = {
|
||||
+ ax::mojom::State::kMultiselectable, ax::mojom::State::kFocusable};
|
||||
Init(BuildListBox(/*option_1_is_selected*/ true,
|
||||
/*option_2_is_selected*/ true,
|
||||
/*option_3_is_selected*/ true,
|
||||
- /*additional_state*/ ax::mojom::State::kNone));
|
||||
+ /*additional_state*/ state));
|
||||
|
||||
ComPtr<ISelectionProvider> selection_provider(
|
||||
QueryInterfaceFromNode<ISelectionProvider>(GetRootNode()));
|
||||
@@ -0,0 +1,142 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Siye Liu <siliu@microsoft.com>
|
||||
Date: Mon, 8 Jun 2020 21:19:00 +0000
|
||||
Subject: Allow IME to insert zero-length composition string.
|
||||
|
||||
Some IMEs and Windows OS dictation will either insert zero-length text
|
||||
or delete existing composition text to commit active composition.
|
||||
Therefore, we should allow IMEs to cancel composition by committing zero
|
||||
length text.
|
||||
|
||||
Bug: 1091069
|
||||
Change-Id: I99cb213dc2ba1965abfa88ccf6858b89bd7e82df
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2233234
|
||||
Commit-Queue: Siye Liu <siliu@microsoft.com>
|
||||
Reviewed-by: Yohei Yukawa <yukawa@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#776198}
|
||||
|
||||
diff --git a/ui/base/ime/win/tsf_text_store.cc b/ui/base/ime/win/tsf_text_store.cc
|
||||
index 4c8552a427c2a559ee1f3753af2ef000e9fe4a8c..7642bb5a92dad553044ace1e17e33b5815e6217f 100644
|
||||
--- a/ui/base/ime/win/tsf_text_store.cc
|
||||
+++ b/ui/base/ime/win/tsf_text_store.cc
|
||||
@@ -612,9 +612,7 @@ STDMETHODIMP TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) {
|
||||
// 3. User commits current composition text.
|
||||
if (((new_composition_start > last_composition_start &&
|
||||
text_input_client_->HasCompositionText()) ||
|
||||
- (wparam_keydown_fired_ == 0 && !has_composition_range_ &&
|
||||
- !text_input_client_->HasCompositionText()) ||
|
||||
- (wparam_keydown_fired_ != 0 && !has_composition_range_)) &&
|
||||
+ !has_composition_range_) &&
|
||||
text_input_client_) {
|
||||
CommitTextAndEndCompositionIfAny(last_composition_start,
|
||||
new_composition_start);
|
||||
@@ -1314,8 +1312,11 @@ void TSFTextStore::CommitTextAndEndCompositionIfAny(size_t old_size,
|
||||
: new_committed_string_size);
|
||||
// TODO(crbug.com/978678): Unify the behavior of
|
||||
// |TextInputClient::InsertText(text)| for the empty text.
|
||||
- if (!new_committed_string.empty())
|
||||
+ if (!new_committed_string.empty()) {
|
||||
text_input_client_->InsertText(new_committed_string);
|
||||
+ } else {
|
||||
+ text_input_client_->ClearCompositionText();
|
||||
+ }
|
||||
// Notify accessibility about this committed composition
|
||||
text_input_client_->SetActiveCompositionForAccessibility(
|
||||
replace_text_range_, new_committed_string,
|
||||
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc
|
||||
index 7909ade63ab752a3d0d450347bba15dc205ee466..77c5eb051e646401eaf22ca1753ef71c585fbc76 100644
|
||||
--- a/ui/base/ime/win/tsf_text_store_unittest.cc
|
||||
+++ b/ui/base/ime/win/tsf_text_store_unittest.cc
|
||||
@@ -3139,5 +3139,92 @@ TEST_F(TSFTextStoreTest, RegressionTest5) {
|
||||
EXPECT_EQ(S_OK, result);
|
||||
}
|
||||
|
||||
+// regression tests for crbug.com/1091069.
|
||||
+// We should allow inserting empty compositon string to cancel composition.
|
||||
+class RegressionTest8Callback : public TSFTextStoreTestCallback {
|
||||
+ public:
|
||||
+ explicit RegressionTest8Callback(TSFTextStore* text_store)
|
||||
+ : TSFTextStoreTestCallback(text_store) {}
|
||||
+
|
||||
+ HRESULT LockGranted1(DWORD flags) {
|
||||
+ SetTextTest(0, 0, L"bbbb", S_OK);
|
||||
+ SetSelectionTest(0, 4, S_OK);
|
||||
+
|
||||
+ text_spans()->clear();
|
||||
+ ImeTextSpan text_span_1;
|
||||
+ text_span_1.start_offset = 0;
|
||||
+ text_span_1.end_offset = 4;
|
||||
+ text_span_1.underline_color = SK_ColorBLACK;
|
||||
+ text_span_1.thickness = ImeTextSpan::Thickness::kThin;
|
||||
+ text_span_1.background_color = SK_ColorTRANSPARENT;
|
||||
+ text_spans()->push_back(text_span_1);
|
||||
+
|
||||
+ *edit_flag() = true;
|
||||
+ *composition_start() = 0;
|
||||
+ composition_range()->set_start(0);
|
||||
+ composition_range()->set_end(4);
|
||||
+ *has_composition_range() = true;
|
||||
+
|
||||
+ text_store_->OnKeyTraceDown(65u, 1966081u);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ void SetCompositionText1(const ui::CompositionText& composition) {
|
||||
+ EXPECT_EQ(L"bbbb", composition.text);
|
||||
+ EXPECT_EQ(0u, composition.selection.start());
|
||||
+ EXPECT_EQ(4u, composition.selection.end());
|
||||
+ ASSERT_EQ(1u, composition.ime_text_spans.size());
|
||||
+ EXPECT_EQ(0u, composition.ime_text_spans[0].start_offset);
|
||||
+ EXPECT_EQ(4u, composition.ime_text_spans[0].end_offset);
|
||||
+ SetHasCompositionText(true);
|
||||
+ }
|
||||
+
|
||||
+ HRESULT LockGranted2(DWORD flags) {
|
||||
+ GetTextTest(0, -1, L"bbbb", 4);
|
||||
+ SetTextTest(0, 4, L"", S_OK);
|
||||
+
|
||||
+ text_spans()->clear();
|
||||
+ *edit_flag() = true;
|
||||
+ *composition_start() = 0;
|
||||
+ composition_range()->set_start(0);
|
||||
+ composition_range()->set_end(0);
|
||||
+
|
||||
+ *has_composition_range() = false;
|
||||
+ text_store_->OnKeyTraceUp(65u, 1966081u);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ void ClearCompositionText2() { EXPECT_EQ(false, *has_composition_range()); }
|
||||
+
|
||||
+ private:
|
||||
+ DISALLOW_COPY_AND_ASSIGN(RegressionTest8Callback);
|
||||
+};
|
||||
+
|
||||
+TEST_F(TSFTextStoreTest, RegressionTest8) {
|
||||
+ RegressionTest8Callback callback(text_store_.get());
|
||||
+ EXPECT_CALL(text_input_client_, SetCompositionText(_))
|
||||
+ .WillOnce(
|
||||
+ Invoke(&callback, &RegressionTest8Callback::SetCompositionText1));
|
||||
+
|
||||
+ EXPECT_CALL(text_input_client_, ClearCompositionText())
|
||||
+ .WillOnce(
|
||||
+ Invoke(&callback, &RegressionTest8Callback::ClearCompositionText2));
|
||||
+
|
||||
+ EXPECT_CALL(*sink_, OnLockGranted(_))
|
||||
+ .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted1))
|
||||
+ .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted2));
|
||||
+
|
||||
+ ON_CALL(text_input_client_, HasCompositionText())
|
||||
+ .WillByDefault(
|
||||
+ Invoke(&callback, &TSFTextStoreTestCallback::HasCompositionText));
|
||||
+
|
||||
+ HRESULT result = kInvalidResult;
|
||||
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
|
||||
+ EXPECT_EQ(S_OK, result);
|
||||
+ result = kInvalidResult;
|
||||
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
|
||||
+ EXPECT_EQ(S_OK, result);
|
||||
+}
|
||||
+
|
||||
} // namespace
|
||||
} // namespace ui
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel McArdle <dmcardle@chromium.org>
|
||||
Date: Thu, 16 Apr 2020 20:18:47 +0000
|
||||
Subject: Avoid nullptr dereference in RTCPeerConnectionHandler
|
||||
|
||||
Bug: 1071327
|
||||
Change-Id: Icf4189905dc5c95854b5af4b3e5e25e0607dd39e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2153325
|
||||
Reviewed-by: Harald Alvestrand <hta@chromium.org>
|
||||
Commit-Queue: Dan McArdle <dmcardle@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#759775}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
index 9457fb951fed176c54f9e792ea5f71cb73f5bbba..6745fc1ae9746a3f9949f856b1501c48e85b5260 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
@@ -2304,7 +2304,8 @@ void RTCPeerConnectionHandler::OnRemoveReceiverPlanB(uintptr_t receiver_id) {
|
||||
|
||||
void RTCPeerConnectionHandler::OnModifySctpTransport(
|
||||
blink::WebRTCSctpTransportSnapshot state) {
|
||||
- client_->DidModifySctpTransport(state);
|
||||
+ if (client_)
|
||||
+ client_->DidModifySctpTransport(state);
|
||||
}
|
||||
|
||||
void RTCPeerConnectionHandler::OnModifyTransceivers(
|
||||
@@ -2431,7 +2432,8 @@ void RTCPeerConnectionHandler::OnIceCandidateError(const String& host_candidate,
|
||||
}
|
||||
|
||||
void RTCPeerConnectionHandler::OnInterestingUsage(int usage_pattern) {
|
||||
- client_->DidNoteInterestingUsage(usage_pattern);
|
||||
+ if (client_)
|
||||
+ client_->DidNoteInterestingUsage(usage_pattern);
|
||||
}
|
||||
|
||||
webrtc::SessionDescriptionInterface*
|
||||
@@ -0,0 +1,99 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Anderson <thomasanderson@chromium.org>
|
||||
Date: Mon, 6 Jan 2020 18:05:20 +0000
|
||||
Subject: Avoid using X11 SHM for remote connections
|
||||
|
||||
For remote connections, SHM doesn't work, but the MIT-SHM extension may
|
||||
still be available, so we need to do an explicit check before trying to
|
||||
use SHM.
|
||||
|
||||
BUG=1035803
|
||||
|
||||
Change-Id: I189ab94b82922572e52b717dc2043b8404745dec
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1980971
|
||||
Commit-Queue: Sadrul Chowdhury <sadrul@chromium.org>
|
||||
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
|
||||
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#728564}
|
||||
|
||||
diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn
|
||||
index 7b8a4f8a6126cd9516cbef7ed7d1aca57839d632..5269237d5872120cb520b1f0518ee037f7accfa2 100644
|
||||
--- a/ui/base/x/BUILD.gn
|
||||
+++ b/ui/base/x/BUILD.gn
|
||||
@@ -53,6 +53,7 @@ jumbo_component("x") {
|
||||
deps = [
|
||||
"//base",
|
||||
"//base:i18n",
|
||||
+ "//net",
|
||||
"//skia",
|
||||
"//ui/base:hit_test",
|
||||
"//ui/display/util",
|
||||
diff --git a/ui/base/x/x11_shm_image_pool_base.cc b/ui/base/x/x11_shm_image_pool_base.cc
|
||||
index 8505b6297f67cea7f8bf36c89414fad9c3108190..486762aa01d56b51864f418ccf68b77d7610fe23 100644
|
||||
--- a/ui/base/x/x11_shm_image_pool_base.cc
|
||||
+++ b/ui/base/x/x11_shm_image_pool_base.cc
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "build/build_config.h"
|
||||
+#include "net/base/url_util.h"
|
||||
#include "ui/events/platform/platform_event_dispatcher.h"
|
||||
#include "ui/events/platform/platform_event_source.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
@@ -54,8 +55,31 @@ std::size_t MaxShmSegmentSize() {
|
||||
return max_size;
|
||||
}
|
||||
|
||||
+bool IsRemoteHost(const std::string& name) {
|
||||
+ if (name.empty())
|
||||
+ return false;
|
||||
+
|
||||
+ return !net::HostStringIsLocalhost(name);
|
||||
+}
|
||||
+
|
||||
+bool ShouldUseMitShm(XDisplay* display) {
|
||||
+ // MIT-SHM may be available on remote connetions, but it will be unusable. Do
|
||||
+ // a best-effort check to see if the host is remote to disable the SHM
|
||||
+ // codepath. It may be possible in contrived cases for there to be a
|
||||
+ // false-positive, but in that case we'll just fallback to the non-SHM
|
||||
+ // codepath.
|
||||
+ char* display_string = DisplayString(display);
|
||||
+ char* host = nullptr;
|
||||
+ int display_id = 0;
|
||||
+ int screen = 0;
|
||||
+ if (xcb_parse_display(display_string, &host, &display_id, &screen)) {
|
||||
+ std::string name = host;
|
||||
+ free(host);
|
||||
+ if (IsRemoteHost(name))
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
#if !defined(OS_CHROMEOS)
|
||||
-bool ShouldUseMitShm() {
|
||||
std::unique_ptr<base::Environment> env = base::Environment::Create();
|
||||
|
||||
// Used by QT.
|
||||
@@ -73,10 +97,10 @@ bool ShouldUseMitShm() {
|
||||
// Used by GTK.
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoXshm))
|
||||
return false;
|
||||
+#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
-#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -118,10 +142,8 @@ bool XShmImagePoolBase::Resize(const gfx::Size& pixel_size) {
|
||||
if (!event_task_runner_)
|
||||
return false;
|
||||
|
||||
-#if !defined(OS_CHROMEOS)
|
||||
- if (!ShouldUseMitShm())
|
||||
+ if (!ShouldUseMitShm(display_))
|
||||
return false;
|
||||
-#endif
|
||||
|
||||
if (!ui::QueryShmSupport())
|
||||
return false;
|
||||
91
patches/chromium/backport_1019161.patch
Normal file
91
patches/chromium/backport_1019161.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andrey Belenko <anbelen@microsoft.com>
|
||||
Date: Fri, 3 Jul 2020 17:27:20 +0200
|
||||
Subject: Backport 1019161
|
||||
(https://chromium-review.googlesource.com/c/chromium/src/+/2125690)
|
||||
|
||||
diff --git a/extensions/browser/service_worker_task_queue.cc b/extensions/browser/service_worker_task_queue.cc
|
||||
index dedb8c39f7db8c416540cdb930683778c2a9a5a5..3519926a06a35b375e13695d59fafce0c7f49c81 100644
|
||||
--- a/extensions/browser/service_worker_task_queue.cc
|
||||
+++ b/extensions/browser/service_worker_task_queue.cc
|
||||
@@ -170,8 +170,17 @@ void ServiceWorkerTaskQueue::DidStartWorkerFail(
|
||||
DCHECK(!base::Contains(pending_tasks_, context_id));
|
||||
return;
|
||||
}
|
||||
- // TODO(lazyboy): Handle failure cases.
|
||||
- DCHECK(false) << "DidStartWorkerFail: " << context_id.first.extension_id();
|
||||
+
|
||||
+ if (g_test_observer) {
|
||||
+ g_test_observer->DidStartWorkerFail(context_id.first.extension_id(),
|
||||
+ pending_tasks_[context_id].size());
|
||||
+ }
|
||||
+
|
||||
+ pending_tasks_.erase(context_id);
|
||||
+ // TODO(https://crbug/1062936): Needs more thought: extension would be in
|
||||
+ // perma-broken state after this as the registration wouldn't be stored if
|
||||
+ // this happens.
|
||||
+ LOG(ERROR) << "DidStartWorkerFail " << context_id.first.extension_id();
|
||||
}
|
||||
|
||||
void ServiceWorkerTaskQueue::DidInitializeServiceWorkerContext(
|
||||
@@ -530,6 +539,16 @@ ServiceWorkerTaskQueue::GetOrCreateWorkerState(const WorkerKey& worker_key) {
|
||||
return &(iter->second);
|
||||
}
|
||||
|
||||
+size_t ServiceWorkerTaskQueue::GetNumPendingTasksForTest(
|
||||
+ const LazyContextId& lazy_context_id) {
|
||||
+ auto current_sequence = GetCurrentSequence(lazy_context_id.extension_id());
|
||||
+ if (!current_sequence)
|
||||
+ return 0u;
|
||||
+ const SequencedContextId context_id(lazy_context_id, *current_sequence);
|
||||
+ auto iter = pending_tasks_.find(context_id);
|
||||
+ return iter == pending_tasks_.end() ? 0u : iter->second.size();
|
||||
+}
|
||||
+
|
||||
ServiceWorkerTaskQueue::WorkerState* ServiceWorkerTaskQueue::GetWorkerState(
|
||||
const WorkerKey& worker_key) {
|
||||
auto iter = worker_state_map_.find(worker_key);
|
||||
diff --git a/extensions/browser/service_worker_task_queue.h b/extensions/browser/service_worker_task_queue.h
|
||||
index 2e5e215bd193098fe4b183a60df5d3c6d1dc8d19..953a72d3c4fe0ce396e0399c890518068f9dbde7 100644
|
||||
--- a/extensions/browser/service_worker_task_queue.h
|
||||
+++ b/extensions/browser/service_worker_task_queue.h
|
||||
@@ -121,7 +121,9 @@ class ServiceWorkerTaskQueue : public KeyedService,
|
||||
// |will_register_service_worker| is true if a Service Worker will be
|
||||
// registered.
|
||||
virtual void OnActivateExtension(const ExtensionId& extension_id,
|
||||
- bool will_register_service_worker) = 0;
|
||||
+ bool will_register_service_worker) {}
|
||||
+ virtual void DidStartWorkerFail(const ExtensionId& extension_id,
|
||||
+ size_t num_pending_tasks) {}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TestObserver);
|
||||
@@ -129,6 +131,8 @@ class ServiceWorkerTaskQueue : public KeyedService,
|
||||
|
||||
static void SetObserverForTest(TestObserver* observer);
|
||||
|
||||
+ size_t GetNumPendingTasksForTest(const LazyContextId& lazy_context_id);
|
||||
+
|
||||
private:
|
||||
// Unique identifier for an extension's activation->deactivation span.
|
||||
using ActivationSequence = int;
|
||||
diff --git a/extensions/browser/service_worker_task_queue_factory.cc b/extensions/browser/service_worker_task_queue_factory.cc
|
||||
index b62d2c1c1e31414a3b26160c95cfcc6996995dff..29ff874ef47be3f7172bda276a7dba519a2f1b9b 100644
|
||||
--- a/extensions/browser/service_worker_task_queue_factory.cc
|
||||
+++ b/extensions/browser/service_worker_task_queue_factory.cc
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
||||
#include "extensions/browser/extension_registry_factory.h"
|
||||
+#include "extensions/browser/process_manager_factory.h"
|
||||
#include "extensions/browser/service_worker_task_queue.h"
|
||||
|
||||
using content::BrowserContext;
|
||||
@@ -28,6 +29,7 @@ ServiceWorkerTaskQueueFactory::ServiceWorkerTaskQueueFactory()
|
||||
"ServiceWorkerTaskQueue",
|
||||
BrowserContextDependencyManager::GetInstance()) {
|
||||
DependsOn(ExtensionRegistryFactory::GetInstance());
|
||||
+ DependsOn(ProcessManagerFactory::GetInstance());
|
||||
}
|
||||
|
||||
ServiceWorkerTaskQueueFactory::~ServiceWorkerTaskQueueFactory() {}
|
||||
139
patches/chromium/backport_1063177.patch
Normal file
139
patches/chromium/backport_1063177.patch
Normal file
@@ -0,0 +1,139 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andrey Belenko <anbelen@microsoft.com>
|
||||
Date: Fri, 3 Jul 2020 17:05:10 +0200
|
||||
Subject: Backport 1063177
|
||||
(https://chromium-review.googlesource.com/c/chromium/src/+/2111393/)
|
||||
|
||||
diff --git a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
|
||||
index b4e340f3a865b79a9c8a1aa38fd86eb4db043c3c..2579f39d4b2f10b665f95febe2c69409188529ff 100644
|
||||
--- a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
|
||||
+++ b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
|
||||
@@ -7,9 +7,11 @@
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
+#include "base/barrier_closure.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/logging.h"
|
||||
+#include "base/memory/ref_counted.h"
|
||||
#include "base/metrics/histogram_functions.h"
|
||||
#include "base/metrics/histogram_macros.h"
|
||||
#include "base/stl_util.h"
|
||||
@@ -31,49 +33,57 @@ namespace {
|
||||
namespace dnr_api = extensions::api::declarative_net_request;
|
||||
|
||||
// A class to help in re-indexing multiple rulesets.
|
||||
-class ReindexHelper {
|
||||
+class ReindexHelper : public base::RefCountedThreadSafe<ReindexHelper> {
|
||||
public:
|
||||
- // Starts re-indexing rulesets. Must be called on the extension file task
|
||||
- // runner.
|
||||
using ReindexCallback = base::OnceCallback<void(LoadRequestData)>;
|
||||
- static void Start(LoadRequestData data, ReindexCallback callback) {
|
||||
- auto* helper = new ReindexHelper(std::move(data), std::move(callback));
|
||||
- helper->Start();
|
||||
- }
|
||||
-
|
||||
- private:
|
||||
- // We manage our own lifetime.
|
||||
ReindexHelper(LoadRequestData data, ReindexCallback callback)
|
||||
: data_(std::move(data)), callback_(std::move(callback)) {}
|
||||
- ~ReindexHelper() = default;
|
||||
-
|
||||
+
|
||||
+ // Starts re-indexing rulesets. Must be called on the extension file task
|
||||
+ // runner.
|
||||
void Start() {
|
||||
DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
|
||||
|
||||
- // Post tasks to reindex individual rulesets.
|
||||
- bool did_post_task = false;
|
||||
+ std::vector<RulesetInfo*> rulesets_to_reindex;
|
||||
+
|
||||
for (auto& ruleset : data_.rulesets) {
|
||||
if (ruleset.did_load_successfully())
|
||||
continue;
|
||||
|
||||
- // Using Unretained is safe since this class manages its own lifetime and
|
||||
- // |this| won't be deleted until the |callback| returns.
|
||||
- auto callback = base::BindOnce(&ReindexHelper::OnReindexCompleted,
|
||||
- base::Unretained(this), &ruleset);
|
||||
- callback_count_++;
|
||||
- did_post_task = true;
|
||||
- ruleset.source().IndexAndPersistJSONRuleset(&decoder_,
|
||||
- std::move(callback));
|
||||
+ rulesets_to_reindex.push_back(&ruleset);
|
||||
}
|
||||
|
||||
- // It's possible that the callbacks return synchronously and we are deleted
|
||||
- // at this point. Hence don't use any member variables here. Also, if we
|
||||
- // don't post any task, we'll leak. Ensure that's not the case.
|
||||
- DCHECK(did_post_task);
|
||||
+ // |done_closure| will be invoked once |barrier_closure| is run
|
||||
+ // |rulesets_to_reindex.size()| times.
|
||||
+ base::OnceClosure done_closure =
|
||||
+ base::BindOnce(&ReindexHelper::OnAllRulesetsReindexed, this);
|
||||
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
|
||||
+ rulesets_to_reindex.size(), std::move(done_closure));
|
||||
+
|
||||
+ // Post tasks to reindex individual rulesets.
|
||||
+ for (RulesetInfo* ruleset : rulesets_to_reindex) {
|
||||
+ auto callback = base::BindOnce(&ReindexHelper::OnReindexCompleted, this,
|
||||
+ ruleset, barrier_closure);
|
||||
+ ruleset->source().IndexAndPersistJSONRuleset(&decoder_,
|
||||
+ std::move(callback));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ friend class base::RefCountedThreadSafe<ReindexHelper>;
|
||||
+ ~ReindexHelper() = default;
|
||||
+
|
||||
+ // Callback invoked when reindexing of all rulesets is completed.
|
||||
+ void OnAllRulesetsReindexed() {
|
||||
+ DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
|
||||
+
|
||||
+ // Our job is done.
|
||||
+ std::move(callback_).Run(std::move(data_));
|
||||
}
|
||||
|
||||
// Callback invoked when a single ruleset is re-indexed.
|
||||
void OnReindexCompleted(RulesetInfo* ruleset,
|
||||
+ base::OnceClosure done_closure,
|
||||
IndexAndPersistJSONRulesetResult result) {
|
||||
DCHECK(ruleset);
|
||||
|
||||
@@ -105,19 +115,11 @@ class ReindexHelper {
|
||||
"Extensions.DeclarativeNetRequest.RulesetReindexSuccessful",
|
||||
reindexing_success);
|
||||
|
||||
- callback_count_--;
|
||||
- DCHECK_GE(callback_count_, 0);
|
||||
-
|
||||
- if (callback_count_ == 0) {
|
||||
- // Our job is done.
|
||||
- std::move(callback_).Run(std::move(data_));
|
||||
- delete this;
|
||||
- }
|
||||
+ std::move(done_closure).Run();
|
||||
}
|
||||
|
||||
LoadRequestData data_;
|
||||
ReindexCallback callback_;
|
||||
- int callback_count_ = 0;
|
||||
|
||||
// We use a single shared Data Decoder service instance to process all of the
|
||||
// rulesets for this ReindexHelper.
|
||||
@@ -362,7 +364,10 @@ void FileSequenceHelper::LoadRulesets(
|
||||
auto reindex_callback =
|
||||
base::BindOnce(&FileSequenceHelper::OnRulesetsReindexed,
|
||||
weak_factory_.GetWeakPtr(), std::move(ui_callback));
|
||||
- ReindexHelper::Start(std::move(load_data), std::move(reindex_callback));
|
||||
+
|
||||
+ auto reindex_helper = base::MakeRefCounted<ReindexHelper>(
|
||||
+ std::move(load_data), std::move(reindex_callback));
|
||||
+ reindex_helper->Start();
|
||||
}
|
||||
|
||||
void FileSequenceHelper::UpdateDynamicRules(
|
||||
98
patches/chromium/backport_1065122.patch
Normal file
98
patches/chromium/backport_1065122.patch
Normal file
@@ -0,0 +1,98 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: fix: add some crash debugging checks
|
||||
|
||||
[1065122] [High]: heap-use-after-free : ui::AXTreeSerializerblink::WebAXObject,content::AXContentNodeData,content::AXContentTreeData::LeastCommonAncestor
|
||||
Backport https://chromium.googlesource.com/chromium/src/+/e0a661af6c2c7346183c47b106afecb01adbfa2e
|
||||
|
||||
diff --git a/ui/accessibility/ax_tree_serializer.h b/ui/accessibility/ax_tree_serializer.h
|
||||
index d0cd8be8dbf3c15ce2a2c84446f5042819686b9a..8791c58789cef10a31799d57287860ba8e60af94 100644
|
||||
--- a/ui/accessibility/ax_tree_serializer.h
|
||||
+++ b/ui/accessibility/ax_tree_serializer.h
|
||||
@@ -180,6 +180,8 @@ class AXTreeSerializer {
|
||||
// like when Reset() is called.
|
||||
void InternalReset();
|
||||
|
||||
+ ClientTreeNode* GetClientTreeNodeParent(ClientTreeNode* obj);
|
||||
+
|
||||
// The tree source.
|
||||
AXTreeSource<AXSourceNode, AXNodeData, AXTreeData>* tree_;
|
||||
|
||||
@@ -269,7 +271,7 @@ AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::LeastCommonAncestor(
|
||||
std::vector<ClientTreeNode*> client_ancestors;
|
||||
while (client_node) {
|
||||
client_ancestors.push_back(client_node);
|
||||
- client_node = client_node->parent;
|
||||
+ client_node = GetClientTreeNodeParent(client_node);
|
||||
}
|
||||
|
||||
// Start at the root. Keep going until the source ancestor chain and
|
||||
@@ -304,9 +306,12 @@ AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::LeastCommonAncestor(
|
||||
// that we're inside of an invalid subtree that all needs to be
|
||||
// re-serialized, so the LCA should be higher.
|
||||
ClientTreeNode* client_node = ClientTreeNodeById(tree_->GetId(node));
|
||||
- while (
|
||||
- tree_->IsValid(node) &&
|
||||
- (!client_node || (client_node->parent && client_node->parent->invalid))) {
|
||||
+ while (tree_->IsValid(node)) {
|
||||
+ if (client_node) {
|
||||
+ ClientTreeNode* parent = GetClientTreeNodeParent(client_node);
|
||||
+ if (!parent || !parent->invalid)
|
||||
+ break;
|
||||
+ }
|
||||
node = tree_->GetParent(node);
|
||||
if (tree_->IsValid(node))
|
||||
client_node = ClientTreeNodeById(tree_->GetId(node));
|
||||
@@ -326,12 +331,13 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::
|
||||
int child_id = tree_->GetId(child);
|
||||
ClientTreeNode* client_child = ClientTreeNodeById(child_id);
|
||||
if (client_child) {
|
||||
- if (!client_child->parent) {
|
||||
+ ClientTreeNode* parent = client_child->parent;
|
||||
+ if (!parent) {
|
||||
// If the client child has no parent, it must have been the
|
||||
// previous root node, so there is no LCA and we can exit early.
|
||||
*out_lca = tree_->GetNull();
|
||||
return true;
|
||||
- } else if (client_child->parent->id != id) {
|
||||
+ } else if (parent->id != id) {
|
||||
// If the client child's parent is not this node, update the LCA
|
||||
// and return true (reparenting was found).
|
||||
*out_lca = LeastCommonAncestor(*out_lca, client_child);
|
||||
@@ -362,6 +368,19 @@ AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::ClientTreeNodeById(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
|
||||
+ClientTreeNode*
|
||||
+AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::GetClientTreeNodeParent(
|
||||
+ ClientTreeNode* obj) {
|
||||
+ ClientTreeNode* parent = obj->parent;
|
||||
+#if DCHECK_IS_ON()
|
||||
+ if (!parent)
|
||||
+ return nullptr;
|
||||
+ DCHECK(ClientTreeNodeById(parent->id)) << "Parent not in id map.";
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ return parent;
|
||||
+}
|
||||
+
|
||||
template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
|
||||
bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::SerializeChanges(
|
||||
AXSourceNode node,
|
||||
@@ -545,8 +564,13 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::
|
||||
// above. If this happens, reset and return an error.
|
||||
|
||||
ClientTreeNode* client_child = ClientTreeNodeById(new_child_id);
|
||||
- if (client_child && client_child->parent != client_node) {
|
||||
- DVLOG(1) << "Reparenting detected";
|
||||
+ if (client_child && GetClientTreeNodeParent(client_child) != client_node) {
|
||||
+ DVLOG(1) << "Illegal reparenting detected";
|
||||
+#if defined(ADDRESS_SANITIZER)
|
||||
+ // Wrapping this in ADDRESS_SANITIZER will cause it to run on
|
||||
+ // clusterfuzz, which should help us narrow down the issue.
|
||||
+ NOTREACHED() << "Illegal reparenting detected";
|
||||
+#endif
|
||||
Reset();
|
||||
return false;
|
||||
}
|
||||
52
patches/chromium/backport_1073409.patch
Normal file
52
patches/chromium/backport_1073409.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: fix: use parseHTMLSubset() in chrome://histograms.
|
||||
|
||||
[1073409] [Low] [CVE-2020-6535]: XSS on chrome://histograms/ with a compromised renderer
|
||||
Backport https://chromium.googlesource.com/chromium/src/+/9a31a7ea51e0c7548f4ed77f5007e4a924ef0fbb
|
||||
|
||||
diff --git a/content/browser/resources/histograms/BUILD.gn b/content/browser/resources/histograms/BUILD.gn
|
||||
index 9b67dcd52b2599855eb21b86b29a294094b22003..08c7f14373fa097bf540c60301d3802685affe0e 100644
|
||||
--- a/content/browser/resources/histograms/BUILD.gn
|
||||
+++ b/content/browser/resources/histograms/BUILD.gn
|
||||
@@ -13,6 +13,7 @@ js_type_check("closure_compile") {
|
||||
js_library("histograms_internals") {
|
||||
deps = [
|
||||
"//ui/webui/resources/js:cr",
|
||||
+ "//ui/webui/resources/js:parse_html_subset",
|
||||
"//ui/webui/resources/js:util",
|
||||
]
|
||||
}
|
||||
diff --git a/content/browser/resources/histograms/histograms_internals.html b/content/browser/resources/histograms/histograms_internals.html
|
||||
index 37e45404843d70bd2621fffc6f5f4e4e69786005..b997e6d2ff88f86c00bf4e4a099cd4999d66c061 100644
|
||||
--- a/content/browser/resources/histograms/histograms_internals.html
|
||||
+++ b/content/browser/resources/histograms/histograms_internals.html
|
||||
@@ -8,6 +8,7 @@
|
||||
<script src="chrome://resources/js/cr.js"></script>
|
||||
<script src="chrome://resources/js/promise_resolver.js"></script>
|
||||
<script src="chrome://resources/js/util.js"></script>
|
||||
+ <script src="chrome://resources/js/parse_html_subset.js"></script>
|
||||
<script src="histograms_internals.js"></script>
|
||||
<title>Histograms</title>
|
||||
</head>
|
||||
diff --git a/content/browser/resources/histograms/histograms_internals.js b/content/browser/resources/histograms/histograms_internals.js
|
||||
index 24c55fb23c9f390a484572fe098e0cdcc79bc4ac..b70641ed43512391e4b75383b68196ba99590638 100644
|
||||
--- a/content/browser/resources/histograms/histograms_internals.js
|
||||
+++ b/content/browser/resources/histograms/histograms_internals.js
|
||||
@@ -24,9 +24,12 @@ function addHistograms(histograms) {
|
||||
htmlOutput += histogram;
|
||||
}
|
||||
|
||||
- // NOTE: This is generally unsafe due to XSS attacks. Make sure |htmlOutput|
|
||||
- // cannot be modified by an external party.
|
||||
- $('histograms').innerHTML = htmlOutput;
|
||||
+ // The following HTML tags are coming from
|
||||
+ // |HistogramsMessageHandler::HandleRequestHistograms|.
|
||||
+ const sanitizedHTML = parseHtmlSubset(`<span>${htmlOutput}</span>`, [
|
||||
+ 'PRE', 'H4', 'BR', 'HR'
|
||||
+ ]).firstChild.innerHTML;
|
||||
+ $('histograms').innerHTML = sanitizedHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
89
patches/chromium/backport_1074317.patch
Normal file
89
patches/chromium/backport_1074317.patch
Normal file
@@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: fix: stop leaking cross-origin post-redirect data using StackTrace
|
||||
|
||||
[1074317] [High] [CVE-2020-6511]: Security: The CSP reports and stacktraces of errors leaks post-redirect URL for <script>
|
||||
Backport https://chromium.googlesource.com/chromium/src/+/0b707cbaa2cb806162797be55caf9f8074fbdccf
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/script_source_code.cc b/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
|
||||
index afd83f83ae79f3ce1d017868144af1d4468d5c53..51efddac8feae2cd53699bd47a65dd11fe8f664f 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
|
||||
|
||||
+#include "base/feature_list.h"
|
||||
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
|
||||
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
|
||||
|
||||
@@ -47,8 +48,16 @@ String SourceMapUrlFromResponse(const ResourceResponse& response) {
|
||||
return response.HttpHeaderField(http_names::kXSourceMap);
|
||||
}
|
||||
|
||||
+const base::Feature kUnsafeScriptReportPostRedirectURL{
|
||||
+ "UnsafeScriptReportPostRedirectURL", base::FEATURE_DISABLED_BY_DEFAULT};
|
||||
+
|
||||
} // namespace
|
||||
|
||||
+// static
|
||||
+bool ScriptSourceCode::UsePostRedirectURL() {
|
||||
+ return base::FeatureList::IsEnabled(kUnsafeScriptReportPostRedirectURL);
|
||||
+}
|
||||
+
|
||||
ScriptSourceCode::ScriptSourceCode(
|
||||
const ParkableString& source,
|
||||
ScriptSourceLocationType source_location_type,
|
||||
@@ -84,8 +93,9 @@ ScriptSourceCode::ScriptSourceCode(ScriptStreamer* streamer,
|
||||
cache_handler_(resource->CacheHandler()),
|
||||
streamer_(streamer),
|
||||
not_streaming_reason_(reason),
|
||||
- url_(
|
||||
- StripFragmentIdentifier(resource->GetResponse().CurrentRequestUrl())),
|
||||
+ url_(StripFragmentIdentifier(
|
||||
+ UsePostRedirectURL() ? resource->GetResponse().CurrentRequestUrl()
|
||||
+ : resource->Url())),
|
||||
source_map_url_(SourceMapUrlFromResponse(resource->GetResponse())),
|
||||
start_position_(TextPosition::MinimumPosition()),
|
||||
source_location_type_(ScriptSourceLocationType::kExternalFile) {
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/script_source_code.h b/third_party/blink/renderer/bindings/core/v8/script_source_code.h
|
||||
index 8fe2bd4e487ff6a67cbe6a3cfb9e00bd5a85da32..41023cec3603a67dba15b71c4b2e3ba12f222f8a 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/script_source_code.h
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/script_source_code.h
|
||||
@@ -49,6 +49,20 @@ class CORE_EXPORT ScriptSourceCode final {
|
||||
DISALLOW_NEW();
|
||||
|
||||
public:
|
||||
+ // Return whether chrome should use the request URL or the response URL as the
|
||||
+ // 'url' of the script. This can be observed in:
|
||||
+ // 1) The 'source-file' in CSP violations reports.
|
||||
+ // 2) The URL(s) in javascript stack traces.
|
||||
+ // 3) How relative source map are resolved.
|
||||
+ //
|
||||
+ // This returns false by default. This corresponds to the current
|
||||
+ // specification and matches Firefox behavior. This also avoids leaking
|
||||
+ // post-redirect data cross-origin. See https://crbug.com/1074317.
|
||||
+ //
|
||||
+ // This can be enabled using the switch:
|
||||
+ // --enable-features=UnsafeScriptReportPostRedirectURL
|
||||
+ static bool UsePostRedirectURL();
|
||||
+
|
||||
// For inline scripts.
|
||||
ScriptSourceCode(
|
||||
const String& source,
|
||||
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
|
||||
index b476e7490aa0a6192ead83184668c6ae7d254431..3f8c36324ce1801fa7fc41973aa682b45be3c4c0 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
|
||||
@@ -266,7 +266,9 @@ void WorkerGlobalScope::ImportScriptsInternal(const Vector<String>& urls,
|
||||
source_code.length(), handler ? handler->GetCodeCacheSize() : 0);
|
||||
ScriptController()->Evaluate(
|
||||
ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown,
|
||||
- handler, response_url),
|
||||
+ handler,
|
||||
+ ScriptSourceCode::UsePostRedirectURL() ? response_url
|
||||
+ : complete_url),
|
||||
sanitize_script_errors, &error_event, GetV8CacheOptions());
|
||||
if (error_event) {
|
||||
ScriptController()->RethrowExceptionFromImportedScript(error_event,
|
||||
21
patches/chromium/backport_1074340.patch
Normal file
21
patches/chromium/backport_1074340.patch
Normal file
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: fix: uninitialized frame policy issue in javascript url
|
||||
|
||||
[1074340] [Low] [CVE-2020-6526]: Security: javascript URI sandbox flags aren't propagated in a blank string case
|
||||
Backport https://chromium.googlesource.com/chromium/src/+/45bcb4d547a5efecae80f4c9a48cef854af91d7f
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
|
||||
index 363375fe3150b8ab55a3ce8c32b2511b24c34135..6311d5262d994d725078eafbbdeb23c0c186c37f 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
|
||||
@@ -297,6 +297,8 @@ void ScriptController::ExecuteJavaScriptURL(
|
||||
WebFeature::kReplaceDocumentViaJavaScriptURL);
|
||||
auto params = std::make_unique<WebNavigationParams>();
|
||||
params->url = GetFrame()->GetDocument()->Url();
|
||||
+ if (auto* owner = GetFrame()->Owner())
|
||||
+ params->frame_policy = owner->GetFramePolicy();
|
||||
|
||||
String result = ToCoreString(v8::Local<v8::String>::Cast(v8_result));
|
||||
WebNavigationParams::FillStaticResponse(params.get(), "text/html", "UTF-8",
|
||||
30
patches/chromium/backport_1081722.patch
Normal file
30
patches/chromium/backport_1081722.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: fix: replace memcopy with memmove for overlapping copies
|
||||
|
||||
[1081722] [Medium] [CVE-2020-6524]: Security: memcpy-param-overlap in AudioBuffer::copyFromChannel
|
||||
Backport https://chromium.googlesource.com/chromium/src/+/2be9b1c27fb97e8a82e068794fc0fba555182c03
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
|
||||
index f173f1bbf32d5ba09d16b5c3f5e7755a2023f240..45fcdb53d9fe92b7256e7ac915a0fae3f23a58b5 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
|
||||
@@ -255,7 +255,7 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination,
|
||||
DCHECK_LE(count, channel_data->deprecatedLengthAsUnsigned());
|
||||
DCHECK_LE(buffer_offset + count, channel_data->deprecatedLengthAsUnsigned());
|
||||
|
||||
- memcpy(dst, src + buffer_offset, count * sizeof(*src));
|
||||
+ memmove(dst, src + buffer_offset, count * sizeof(*src));
|
||||
}
|
||||
|
||||
void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
|
||||
@@ -299,7 +299,7 @@ void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
|
||||
DCHECK_LE(buffer_offset + count, channel_data->deprecatedLengthAsUnsigned());
|
||||
DCHECK_LE(count, source.View()->deprecatedLengthAsUnsigned());
|
||||
|
||||
- memcpy(dst + buffer_offset, src, count * sizeof(*dst));
|
||||
+ memmove(dst + buffer_offset, src, count * sizeof(*dst));
|
||||
}
|
||||
|
||||
void AudioBuffer::Zero() {
|
||||
32
patches/chromium/backport_1090543.patch
Normal file
32
patches/chromium/backport_1090543.patch
Normal file
@@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: fix: guard against UaF in NavigationRequest
|
||||
|
||||
[1090543] [High]: heap-use-after-free : content::NavigationRequest::OnWillProcessResponseProcessed
|
||||
Backport https://chromium.googlesource.com/chromium/src/+/8a7c8c1affd3b03a41c6f79afa8ebce4168ded5b
|
||||
|
||||
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
|
||||
index bba7dc934cd43df41949ed5b2adc70e152b77627..d5290c54ed88e3dd2cd736535d5954316ee663a8 100644
|
||||
--- a/content/browser/frame_host/navigation_request.cc
|
||||
+++ b/content/browser/frame_host/navigation_request.cc
|
||||
@@ -3012,11 +3012,19 @@ void NavigationRequest::OnWillProcessResponseProcessed(
|
||||
DCHECK(processing_navigation_throttle_);
|
||||
processing_navigation_throttle_ = false;
|
||||
if (result.action() == NavigationThrottle::PROCEED) {
|
||||
+ base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
|
||||
+
|
||||
// If the navigation is done processing the response, then it's ready to
|
||||
// commit. Inform observers that the navigation is now ready to commit,
|
||||
// unless it is not set to commit (204/205s/downloads).
|
||||
if (render_frame_host_)
|
||||
ReadyToCommitNavigation(false);
|
||||
+
|
||||
+ // The call above might block on showing a user dialog. The interaction of
|
||||
+ // the user with this dialog might result in the WebContents owning this
|
||||
+ // NavigationRequest to be destroyed. Return if this is the case.
|
||||
+ if (!weak_self)
|
||||
+ return;
|
||||
} else {
|
||||
state_ = CANCELING;
|
||||
}
|
||||
@@ -5,10 +5,10 @@ Subject: can_create_window.patch
|
||||
|
||||
|
||||
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
|
||||
index bbd42aad3d42311dfff47e725a5deddb4ed04134..797ee4073cfc7b78038d0c007922783a55b89683 100644
|
||||
index 050531a82b48797012adbf6fe49ab5741a38d989..8a02ff83c8e40d641530211ef944b62b09a03ac8 100644
|
||||
--- a/content/browser/frame_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/frame_host/render_frame_host_impl.cc
|
||||
@@ -4375,6 +4375,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -4379,6 +4379,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
last_committed_origin_, params->window_container_type,
|
||||
params->target_url, params->referrer.To<Referrer>(),
|
||||
params->frame_name, params->disposition, *params->features,
|
||||
|
||||
77
patches/chromium/cherry-pick-38990b7d56e6.patch
Normal file
77
patches/chromium/cherry-pick-38990b7d56e6.patch
Normal file
@@ -0,0 +1,77 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Date: Tue, 21 Apr 2020 23:51:25 +0000
|
||||
Subject: Fix bug when BytesProvider replies with invalid data.
|
||||
|
||||
Bug: 1072983
|
||||
Change-Id: Ideaa0a67680375e770995880a4b8d2014b51d642
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2159583
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#761203}
|
||||
|
||||
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
|
||||
index 1cc34f91e01530754635a27cd6481e367b0a4d4e..b6a12a5c43d0129f6c1dcfe93fbd684ba4f5dc2e 100644
|
||||
--- a/storage/browser/blob/blob_registry_impl.cc
|
||||
+++ b/storage/browser/blob/blob_registry_impl.cc
|
||||
@@ -432,6 +432,10 @@ void BlobRegistryImpl::BlobUnderConstruction::TransportComplete(
|
||||
// try to delete |this| again afterwards.
|
||||
auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
|
||||
+ // Store the bad_message_callback_, so we can invoke it if needed, after
|
||||
+ // notifying about the blob being finished.
|
||||
+ auto bad_message_callback = std::move(bad_message_callback_);
|
||||
+
|
||||
// The blob might no longer have any references, in which case it may no
|
||||
// longer exist. If that happens just skip calling Complete.
|
||||
// TODO(mek): Stop building sooner if a blob is no longer referenced.
|
||||
@@ -445,7 +449,7 @@ void BlobRegistryImpl::BlobUnderConstruction::TransportComplete(
|
||||
// BlobTransportStrategy might have already reported a BadMessage on the
|
||||
// BytesProvider binding, but just to be safe, also report one on the
|
||||
// BlobRegistry binding itself.
|
||||
- std::move(bad_message_callback_)
|
||||
+ std::move(bad_message_callback)
|
||||
.Run("Received invalid data while transporting blob");
|
||||
}
|
||||
if (weak_this)
|
||||
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc
|
||||
index 8cbcc69ec6dc6bd368fdb59a3797e412b286e342..2060676987e267a0d55878a27f6a1b53fe6790b1 100644
|
||||
--- a/storage/browser/blob/blob_registry_impl_unittest.cc
|
||||
+++ b/storage/browser/blob/blob_registry_impl_unittest.cc
|
||||
@@ -770,6 +770,36 @@ TEST_F(BlobRegistryImplTest, Register_ValidBytesAsReply) {
|
||||
EXPECT_EQ(0u, BlobsUnderConstruction());
|
||||
}
|
||||
|
||||
+TEST_F(BlobRegistryImplTest, Register_InvalidBytesAsReply) {
|
||||
+ const std::string kId = "id";
|
||||
+ const std::string kData = "hello";
|
||||
+
|
||||
+ std::vector<blink::mojom::DataElementPtr> elements;
|
||||
+ elements.push_back(
|
||||
+ blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
|
||||
+ kData.size(), base::nullopt, CreateBytesProvider(""))));
|
||||
+
|
||||
+ mojo::PendingRemote<blink::mojom::Blob> blob;
|
||||
+ EXPECT_TRUE(registry_->Register(blob.InitWithNewPipeAndPassReceiver(), kId,
|
||||
+ "", "", std::move(elements)));
|
||||
+
|
||||
+ std::unique_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId);
|
||||
+ WaitForBlobCompletion(handle.get());
|
||||
+
|
||||
+ EXPECT_TRUE(handle->IsBroken());
|
||||
+ ASSERT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS,
|
||||
+ handle->GetBlobStatus());
|
||||
+
|
||||
+ EXPECT_EQ(1u, reply_request_count_);
|
||||
+ EXPECT_EQ(0u, stream_request_count_);
|
||||
+ EXPECT_EQ(0u, file_request_count_);
|
||||
+ EXPECT_EQ(0u, BlobsUnderConstruction());
|
||||
+
|
||||
+ // Expect 2 bad messages, one for the bad reply by the bytes provider, and one
|
||||
+ // for the original register call.
|
||||
+ EXPECT_EQ(2u, bad_messages_.size());
|
||||
+}
|
||||
+
|
||||
TEST_F(BlobRegistryImplTest, Register_ValidBytesAsStream) {
|
||||
const std::string kId = "id";
|
||||
const std::string kData =
|
||||
82
patches/chromium/cherry-pick-67864c214770.patch
Normal file
82
patches/chromium/cherry-pick-67864c214770.patch
Normal file
@@ -0,0 +1,82 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Cheng <dcheng@chromium.org>
|
||||
Date: Fri, 10 Apr 2020 00:43:45 +0000
|
||||
Subject: Use std::deque to store the stack of currently executing tasks
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The stack of currently executing stacks includes a PendingTask field. A
|
||||
pointer to this field is stored in TLS. However, std::vector does not
|
||||
guarantee pointer stability on resize.
|
||||
|
||||
(cherry picked from commit c34431a597aba8f4374975217d97a73eaf7d1f18)
|
||||
|
||||
Bug: 1064891
|
||||
Change-Id: I04eb06c9521722f08fd72826f552cedaffe61b53
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2146349
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Sami Kyöstilä <skyostil@chromium.org>
|
||||
Reviewed-by: François Doray <fdoray@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#759017}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2158048
|
||||
Cr-Commit-Position: refs/branch-heads/4044@{#970}
|
||||
Cr-Branched-From: a6d9daf149a473ceea37f629c41d4527bf2055bd-refs/heads/master@{#737173}
|
||||
|
||||
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc
|
||||
index f719a33fff0c98dc7113b4b094bc46809dc66c00..ed951d323a1c7025d99a04d4481abc1f68dfb017 100644
|
||||
--- a/base/task/sequence_manager/sequence_manager_impl.cc
|
||||
+++ b/base/task/sequence_manager/sequence_manager_impl.cc
|
||||
@@ -50,13 +50,6 @@ const scoped_refptr<SequencedTaskRunner>& GetNullTaskRunner() {
|
||||
|
||||
} // namespace
|
||||
|
||||
-// This controls how big the the initial for
|
||||
-// |MainThreadOnly::task_execution_stack| should be. We don't expect to see
|
||||
-// depths of more than 2 unless cooperative scheduling is used on Blink, where
|
||||
-// we might get up to 6. Anyway 10 was chosen because it's a round number
|
||||
-// greater than current anticipated usage.
|
||||
-static constexpr const size_t kInitialTaskExecutionStackReserveCount = 10;
|
||||
-
|
||||
std::unique_ptr<SequenceManager> CreateSequenceManagerOnCurrentThread(
|
||||
SequenceManager::Settings settings) {
|
||||
return internal::SequenceManagerImpl::CreateOnCurrentThread(
|
||||
@@ -267,7 +260,6 @@ SequenceManagerImpl::MainThreadOnly::MainThreadOnly(
|
||||
random_generator = std::mt19937_64(RandUint64());
|
||||
uniform_distribution = std::uniform_real_distribution<double>(0.0, 1.0);
|
||||
}
|
||||
- task_execution_stack.reserve(kInitialTaskExecutionStackReserveCount);
|
||||
}
|
||||
|
||||
SequenceManagerImpl::MainThreadOnly::~MainThreadOnly() = default;
|
||||
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h
|
||||
index ddd0a580eb71300f6ec68903ff1467808707ec82..e2819c68fd2f3c19940e0f26248835abd1e55fda 100644
|
||||
--- a/base/task/sequence_manager/sequence_manager_impl.h
|
||||
+++ b/base/task/sequence_manager/sequence_manager_impl.h
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef BASE_TASK_SEQUENCE_MANAGER_SEQUENCE_MANAGER_IMPL_H_
|
||||
#define BASE_TASK_SEQUENCE_MANAGER_SEQUENCE_MANAGER_IMPL_H_
|
||||
|
||||
+#include <deque>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -12,7 +13,6 @@
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
-#include <vector>
|
||||
|
||||
#include "base/atomic_sequence_num.h"
|
||||
#include "base/cancelable_callback.h"
|
||||
@@ -308,7 +308,9 @@ class BASE_EXPORT SequenceManagerImpl
|
||||
bool nesting_observer_registered_ = false;
|
||||
|
||||
// Due to nested runloops more than one task can be executing concurrently.
|
||||
- std::vector<ExecutingTask> task_execution_stack;
|
||||
+ // Note that this uses std::deque for pointer stability, since pointers to
|
||||
+ // objects in this container are stored in TLS.
|
||||
+ std::deque<ExecutingTask> task_execution_stack;
|
||||
|
||||
Observer* observer = nullptr; // NOT OWNED
|
||||
|
||||
144
patches/chromium/cherry-pick-686d1bfbcb8f.patch
Normal file
144
patches/chromium/cherry-pick-686d1bfbcb8f.patch
Normal file
@@ -0,0 +1,144 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rouslan Solomakhin <rouslan@chromium.org>
|
||||
Date: Wed, 15 Apr 2020 23:03:07 +0000
|
||||
Subject: Browser context owned callback.
|
||||
|
||||
Before this patch, an unowned function pointer would be invoked
|
||||
asynchronously with a reference to the possibly freed reference to the
|
||||
browser context, which could cause use after free in certain
|
||||
circumstances.
|
||||
|
||||
This patch makes the browser context own the callback and binds the
|
||||
function with a weak pointer, so freeing the browser context invalidates
|
||||
the weak pointer, which cancels the callback execution.
|
||||
|
||||
After this patch, freeing the browser context aborts the asynchronous
|
||||
callback that dereferences the browser context, so the use after free
|
||||
is prevented.
|
||||
|
||||
TBR=rouslan@chromium.org
|
||||
|
||||
(cherry picked from commit 2d0aad1e7602a7076d86772cc159b891cf2cf03b)
|
||||
|
||||
Bug: 1065298
|
||||
Change-Id: Id6de3099a55c4505e94a8a6d21fb25d6d2b34c6c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2144311
|
||||
Reviewed-by: Danyao Wang <danyao@chromium.org>
|
||||
Commit-Queue: Rouslan Solomakhin <rouslan@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#758404}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2151474
|
||||
Reviewed-by: Rouslan Solomakhin <rouslan@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4044@{#942}
|
||||
Cr-Branched-From: a6d9daf149a473ceea37f629c41d4527bf2055bd-refs/heads/master@{#737173}
|
||||
|
||||
diff --git a/content/browser/payments/payment_app_provider_impl.cc b/content/browser/payments/payment_app_provider_impl.cc
|
||||
index 3b813cb22c15e85c9e0da1b0060a4514e6522db5..83c26a3e1801dc780d83ee34136ca1513e343339 100644
|
||||
--- a/content/browser/payments/payment_app_provider_impl.cc
|
||||
+++ b/content/browser/payments/payment_app_provider_impl.cc
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "base/metrics/histogram_macros.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
+#include "base/supports_user_data.h"
|
||||
#include "base/task/post_task.h"
|
||||
#include "base/token.h"
|
||||
#include "content/browser/payments/payment_app_context_impl.h"
|
||||
@@ -432,28 +433,65 @@ void OnInstallPaymentApp(
|
||||
}
|
||||
}
|
||||
|
||||
-void CheckPermissionForPaymentApps(
|
||||
- BrowserContext* browser_context,
|
||||
- PaymentAppProvider::GetAllPaymentAppsCallback callback,
|
||||
- PaymentAppProvider::PaymentApps apps) {
|
||||
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
+// Callbacks for checking permissions asynchronously. Owned by the browser
|
||||
+// context to avoid using the browser context after it has been freed. Deleted
|
||||
+// after the callback is invoked.
|
||||
+// Sample usage:
|
||||
+// PostTask(&PermissionChecker::CheckPermissionForPaymentApps,
|
||||
+// PermissionChecker::Create(browser_context), std::move(callback));
|
||||
+class PermissionChecker : public base::SupportsUserData::Data {
|
||||
+ public:
|
||||
+ static base::WeakPtr<PermissionChecker> Create(
|
||||
+ BrowserContext* browser_context) {
|
||||
+ auto owned = std::make_unique<PermissionChecker>(browser_context);
|
||||
+ auto weak_pointer_result = owned->weak_ptr_factory_.GetWeakPtr();
|
||||
+ void* key = owned.get();
|
||||
+ browser_context->SetUserData(key, std::move(owned));
|
||||
+ return weak_pointer_result;
|
||||
+ }
|
||||
+
|
||||
+ // Do not use this method directly! Use the static PermissionChecker::Create()
|
||||
+ // method instead. (The constructor must be public for std::make_unique<> in
|
||||
+ // the Create() method.)
|
||||
+ explicit PermissionChecker(BrowserContext* browser_context)
|
||||
+ : browser_context_(browser_context) {}
|
||||
+ ~PermissionChecker() override = default;
|
||||
+
|
||||
+ // Disallow copy and assign.
|
||||
+ PermissionChecker(const PermissionChecker& other) = delete;
|
||||
+ PermissionChecker& operator=(const PermissionChecker& other) = delete;
|
||||
+
|
||||
+ void CheckPermissionForPaymentApps(
|
||||
+ PaymentAppProvider::GetAllPaymentAppsCallback callback,
|
||||
+ PaymentAppProvider::PaymentApps apps) {
|
||||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
- PermissionController* permission_controller =
|
||||
- BrowserContext::GetPermissionController(browser_context);
|
||||
- DCHECK(permission_controller);
|
||||
-
|
||||
- PaymentAppProvider::PaymentApps permitted_apps;
|
||||
- for (auto& app : apps) {
|
||||
- GURL origin = app.second->scope.GetOrigin();
|
||||
- if (permission_controller->GetPermissionStatus(
|
||||
- PermissionType::PAYMENT_HANDLER, origin, origin) ==
|
||||
- blink::mojom::PermissionStatus::GRANTED) {
|
||||
- permitted_apps[app.first] = std::move(app.second);
|
||||
+ PermissionController* permission_controller =
|
||||
+ BrowserContext::GetPermissionController(browser_context_);
|
||||
+ DCHECK(permission_controller);
|
||||
+
|
||||
+ PaymentAppProvider::PaymentApps permitted_apps;
|
||||
+ for (auto& app : apps) {
|
||||
+ GURL origin = app.second->scope.GetOrigin();
|
||||
+ if (permission_controller->GetPermissionStatus(
|
||||
+ PermissionType::PAYMENT_HANDLER, origin, origin) ==
|
||||
+ blink::mojom::PermissionStatus::GRANTED) {
|
||||
+ permitted_apps[app.first] = std::move(app.second);
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ std::move(callback).Run(std::move(permitted_apps));
|
||||
+
|
||||
+ // Deletes this PermissionChecker object.
|
||||
+ browser_context_->RemoveUserData(/*key=*/this);
|
||||
}
|
||||
|
||||
- std::move(callback).Run(std::move(permitted_apps));
|
||||
-}
|
||||
+ private:
|
||||
+ // Owns this PermissionChecker object, so it's always valid.
|
||||
+ BrowserContext* browser_context_;
|
||||
+
|
||||
+ base::WeakPtrFactory<PermissionChecker> weak_ptr_factory_{this};
|
||||
+};
|
||||
|
||||
void AbortInvokePaymentApp(BrowserContext* browser_context,
|
||||
PaymentEventResponseType reason) {
|
||||
@@ -606,9 +644,11 @@ void PaymentAppProviderImpl::GetAllPaymentApps(
|
||||
|
||||
RunOrPostTaskOnThread(
|
||||
FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
|
||||
- base::BindOnce(&GetAllPaymentAppsOnCoreThread, payment_app_context,
|
||||
- base::BindOnce(&CheckPermissionForPaymentApps,
|
||||
- browser_context, std::move(callback))));
|
||||
+ base::BindOnce(
|
||||
+ &GetAllPaymentAppsOnCoreThread, payment_app_context,
|
||||
+ base::BindOnce(&PermissionChecker::CheckPermissionForPaymentApps,
|
||||
+ PermissionChecker::Create(browser_context),
|
||||
+ std::move(callback))));
|
||||
}
|
||||
|
||||
void PaymentAppProviderImpl::InvokePaymentApp(
|
||||
191
patches/chromium/cherry-pick-7101418f85a0.patch
Normal file
191
patches/chromium/cherry-pick-7101418f85a0.patch
Normal file
@@ -0,0 +1,191 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mason Freed <masonfreed@chromium.org>
|
||||
Date: Mon, 20 Apr 2020 21:57:52 +0000
|
||||
Subject: Fix customized built-in element constructor behavior
|
||||
|
||||
This CL implements two changes:
|
||||
1. It fixes the implementation to better match the spec for the
|
||||
"create an element for the token" [1] algorithm. Prior to this CL,
|
||||
step 7 of that algorithm was skipping directly to step 6 of the
|
||||
"create an element" [2] algorithm, skipping over step 5 for
|
||||
customized built-in elements. This is now fixed. This case is
|
||||
illustrated by the issue and example at [3] and [4]. This becomes
|
||||
the first test in customized-built-in-constructor-exceptions.html.
|
||||
|
||||
2. It updates the comments to match the new behavior discussed in [3]
|
||||
and the [5] spec PR, which changes the return value in the case
|
||||
that a customized built-in element constructor throws an exception.
|
||||
With the change above, that is actually already the behavior. So
|
||||
this is just a comment change. Two new tests are added to
|
||||
customized-built-in-constructor-exceptions.html.
|
||||
|
||||
[1] https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token
|
||||
[2] https://dom.spec.whatwg.org/#concept-create-element
|
||||
[3] https://github.com/whatwg/html/issues/5084
|
||||
[4] https://crbug.com/1024866
|
||||
[5] https://github.com/whatwg/dom/pull/797
|
||||
|
||||
Bug: 1071059, 1024866
|
||||
Change-Id: I814c81991eb5e83501304bcb3d2da476743aef52
|
||||
Cq-Do-Not-Cancel-Tryjobs: true
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2152986
|
||||
Commit-Queue: Mason Freed <masonfreed@chromium.org>
|
||||
Auto-Submit: Mason Freed <masonfreed@chromium.org>
|
||||
Reviewed-by: Kent Tamura <tkent@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#760705}
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
|
||||
index 075b20837c75f736d4580e2b17b0568e0c36e48c..363ccb5f7c919ee1990b27684bc89c1cd4a805af 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
|
||||
@@ -137,6 +137,7 @@ HTMLElement* ScriptCustomElementDefinition::HandleCreateElementSyncException(
|
||||
HTMLElement* ScriptCustomElementDefinition::CreateAutonomousCustomElementSync(
|
||||
Document& document,
|
||||
const QualifiedName& tag_name) {
|
||||
+ DCHECK(CustomElement::ShouldCreateCustomElement(tag_name)) << tag_name;
|
||||
if (!script_state_->ContextIsValid())
|
||||
return CustomElement::CreateFailedElement(document, tag_name);
|
||||
ScriptState::Scope scope(script_state_);
|
||||
diff --git a/third_party/blink/renderer/core/html/custom/custom_element.cc b/third_party/blink/renderer/core/html/custom/custom_element.cc
|
||||
index d21c582052cbf861b792ec6f44e418cc25f3a8cc..1edcd4e60009c9f994c0711a8d373d771b4e8965 100644
|
||||
--- a/third_party/blink/renderer/core/html/custom/custom_element.cc
|
||||
+++ b/third_party/blink/renderer/core/html/custom/custom_element.cc
|
||||
@@ -205,7 +205,8 @@ Element* CustomElement::CreateUncustomizedOrUndefinedElement(
|
||||
|
||||
HTMLElement* CustomElement::CreateFailedElement(Document& document,
|
||||
const QualifiedName& tag_name) {
|
||||
- DCHECK(ShouldCreateCustomElement(tag_name));
|
||||
+ CHECK(ShouldCreateCustomElement(tag_name))
|
||||
+ << "HTMLUnknownElement with built-in tag name: " << tag_name;
|
||||
|
||||
// "create an element for a token":
|
||||
// https://html.spec.whatwg.org/C/#create-an-element-for-the-token
|
||||
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_definition.cc b/third_party/blink/renderer/core/html/custom/custom_element_definition.cc
|
||||
index 6126e0d04c48e8f7cebe8dbf39418599fcfcb84e..3341f49f48de367cbe4f736c4acac09c5d59ddbd 100644
|
||||
--- a/third_party/blink/renderer/core/html/custom/custom_element_definition.cc
|
||||
+++ b/third_party/blink/renderer/core/html/custom/custom_element_definition.cc
|
||||
@@ -142,14 +142,19 @@ HTMLElement* CustomElementDefinition::CreateElement(
|
||||
result->SetCustomElementState(CustomElementState::kUndefined);
|
||||
result->SetIsValue(Descriptor().GetName());
|
||||
|
||||
- // 5.3. If the synchronous custom elements flag is set, upgrade
|
||||
- // element using definition.
|
||||
- // 5.4. Otherwise, enqueue a custom element upgrade reaction given
|
||||
- // result and definition.
|
||||
- if (!flags.IsAsyncCustomElements())
|
||||
+ if (!flags.IsAsyncCustomElements()) {
|
||||
+ // 5.3 If the synchronous custom elements flag is set, then run this step
|
||||
+ // while catching any exceptions:
|
||||
+ // 1. Upgrade element using definition.
|
||||
+ // If this step threw an exception, then:
|
||||
+ // 1. Report the exception.
|
||||
+ // 2. Set result's custom element state to "failed".
|
||||
Upgrade(*result);
|
||||
- else
|
||||
+ } else {
|
||||
+ // 5.4. Otherwise, enqueue a custom element upgrade reaction given
|
||||
+ // result and definition.
|
||||
EnqueueUpgradeReaction(*result);
|
||||
+ }
|
||||
return To<HTMLElement>(result);
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
|
||||
index e5b8596cb60c8baf9c6d1a18d0c788985f8790b8..e98bb816eaa6f63b672a69425ea338e9521713d0 100644
|
||||
--- a/third_party/blink/renderer/core/html/parser/html_construction_site.cc
|
||||
+++ b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
|
||||
@@ -919,8 +919,11 @@ Element* HTMLConstructionSite::CreateElement(
|
||||
// reactions stack."
|
||||
CEReactionsScope reactions;
|
||||
|
||||
- // 7.
|
||||
- element = definition->CreateAutonomousCustomElementSync(document, tag_name);
|
||||
+ // 7. Let element be the result of creating an element given document,
|
||||
+ // localName, given namespace, null, and is. If will execute script is true,
|
||||
+ // set the synchronous custom elements flag; otherwise, leave it unset.
|
||||
+ element =
|
||||
+ definition->CreateElement(document, tag_name, GetCreateElementFlags());
|
||||
|
||||
// "8. Append each attribute in the given token to element." We don't use
|
||||
// setAttributes here because the custom element constructor may have
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/customized-built-in-constructor-exceptions.html b/third_party/blink/web_tests/external/wpt/custom-elements/customized-built-in-constructor-exceptions.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..32729bdb6bb2c82f54c074c7609ff5c79883a37a
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/customized-built-in-constructor-exceptions.html
|
||||
@@ -0,0 +1,75 @@
|
||||
+<!DOCTYPE html>
|
||||
+<title>Customized built-in element constructor behavior</title>
|
||||
+<meta name='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'>
|
||||
+<link rel='help' href='https://dom.spec.whatwg.org/#concept-create-element'>
|
||||
+<script src='/resources/testharness.js'></script>
|
||||
+<script src='/resources/testharnessreport.js'></script>
|
||||
+
|
||||
+<script>
|
||||
+setup({allow_uncaught_exception : true});
|
||||
+
|
||||
+class MyCustomParagraph extends HTMLParagraphElement {
|
||||
+ constructor() {
|
||||
+ super();
|
||||
+ this.textContent = 'PASS';
|
||||
+ }
|
||||
+}
|
||||
+customElements.define('custom-p', MyCustomParagraph, { extends: 'p' });
|
||||
+</script>
|
||||
+<p id=targetp is='custom-p'></p>
|
||||
+<script>
|
||||
+test(t => {
|
||||
+ let target = document.getElementById('targetp');
|
||||
+ assert_true(!!target);
|
||||
+ assert_equals(target.localName, 'p');
|
||||
+ assert_true(target instanceof MyCustomParagraph);
|
||||
+ assert_true(target instanceof HTMLParagraphElement);
|
||||
+ assert_equals(target.childNodes.length, 1);
|
||||
+ assert_equals(target.textContent, 'PASS');
|
||||
+}, 'Appending children in customized built-in constructor should work');
|
||||
+</script>
|
||||
+
|
||||
+
|
||||
+<script>
|
||||
+class MyCustomVideo extends HTMLVideoElement {
|
||||
+ constructor() {
|
||||
+ super();
|
||||
+ throw new Error();
|
||||
+ }
|
||||
+}
|
||||
+customElements.define('custom-video', MyCustomVideo, { extends: 'video' });
|
||||
+</script>
|
||||
+<video id=targetvideo is='custom-video'> <source></source> </video>
|
||||
+<script>
|
||||
+test(t => {
|
||||
+ let target = document.getElementById('targetvideo');
|
||||
+ assert_true(!!target);
|
||||
+ assert_equals(target.localName, 'video');
|
||||
+ assert_true(target instanceof MyCustomVideo);
|
||||
+ assert_true(target instanceof HTMLVideoElement);
|
||||
+ assert_equals(target.children.length, 1);
|
||||
+}, 'Throwing exception in customized built-in constructor should not crash and should return correct element type (video)');
|
||||
+</script>
|
||||
+
|
||||
+
|
||||
+<script>
|
||||
+class MyCustomForm extends HTMLFormElement {
|
||||
+ constructor() {
|
||||
+ super();
|
||||
+ throw new Error();
|
||||
+ }
|
||||
+}
|
||||
+customElements.define('custom-form', MyCustomForm, { extends: 'form' });
|
||||
+</script>
|
||||
+<form id=targetform is='custom-form'> <label></label><input> </form>
|
||||
+<script>
|
||||
+test(t => {
|
||||
+ let target = document.getElementById('targetform');
|
||||
+ assert_true(!!target);
|
||||
+ assert_equals(target.localName, 'form');
|
||||
+ assert_true(target instanceof MyCustomForm);
|
||||
+ assert_true(target instanceof HTMLFormElement);
|
||||
+ assert_equals(target.children.length, 2);
|
||||
+}, 'Throwing exception in customized built-in constructor should not crash and should return correct element type (form)');
|
||||
+</script>
|
||||
+
|
||||
50
patches/chromium/cherry-pick-826a4af58b3d.patch
Normal file
50
patches/chromium/cherry-pick-826a4af58b3d.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mustafa Emre Acer <meacer@chromium.org>
|
||||
Date: Fri, 10 Apr 2020 00:43:45 +0000
|
||||
Subject: Don't decode invalid punycode in URL formatter
|
||||
|
||||
TBR=meacer@chromium.org
|
||||
|
||||
(cherry picked from commit 50c6e900fc4170a14154cbfea57ade2aa50990b5)
|
||||
|
||||
Bug: 1063566
|
||||
Change-Id: I631ba68718cf69c5972555d7826b089e27fa5150
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2137872
|
||||
Reviewed-by: Peter Kasting <pkasting@chromium.org>
|
||||
Commit-Queue: Peter Kasting <pkasting@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#756819}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2144830
|
||||
Reviewed-by: Mustafa Emre Acer <meacer@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4103@{#62}
|
||||
Cr-Branched-From: 8ad47e8d21f6866e4a37f47d83a860d41debf514-refs/heads/master@{#756066}
|
||||
|
||||
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
|
||||
index f695e5c403cbcb020b2ef8016fb513ba1b8d97d1..ffd06415c9afd54c008d86f817cb0e704de87601 100644
|
||||
--- a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
|
||||
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
|
||||
@@ -55,6 +55,8 @@ const IDNTestCase kIdnCases[] = {
|
||||
{"www.google.com.", L"www.google.com.", true},
|
||||
{".", L".", true},
|
||||
{"", L"", true},
|
||||
+ // Invalid IDN
|
||||
+ {"xn--example-.com", L"xn--example-.com", false},
|
||||
// IDN
|
||||
// Hanzi (Traditional Chinese)
|
||||
{"xn--1lq90ic7f1rc.cn", L"\x5317\x4eac\x5927\x5b78.cn", true},
|
||||
diff --git a/components/url_formatter/url_formatter.cc b/components/url_formatter/url_formatter.cc
|
||||
index 58cadb980bb877c933e37457b1ab0883357ece47..d7cc2ea441c916fb77a520f8fe440cff042b6aab 100644
|
||||
--- a/components/url_formatter/url_formatter.cc
|
||||
+++ b/components/url_formatter/url_formatter.cc
|
||||
@@ -408,9 +408,11 @@ bool IDNToUnicodeOneComponent(const base::char16* comp,
|
||||
return false;
|
||||
|
||||
// Early return if the input cannot be an IDN component.
|
||||
+ // Valid punycode must not end with a dash.
|
||||
static const base::char16 kIdnPrefix[] = {'x', 'n', '-', '-'};
|
||||
if (comp_len <= base::size(kIdnPrefix) ||
|
||||
- memcmp(comp, kIdnPrefix, sizeof(kIdnPrefix)) != 0) {
|
||||
+ memcmp(comp, kIdnPrefix, sizeof(kIdnPrefix)) != 0 ||
|
||||
+ comp[comp_len - 1] == '-') {
|
||||
out->append(comp, comp_len);
|
||||
return false;
|
||||
}
|
||||
237
patches/chromium/cherry-pick-86c02c5dcd37.patch
Normal file
237
patches/chromium/cherry-pick-86c02c5dcd37.patch
Normal file
@@ -0,0 +1,237 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Matthias=20K=C3=B6rber?= <koerber@google.com>
|
||||
Date: Tue, 14 Apr 2020 16:55:14 +0000
|
||||
Subject: Fixed requesting invalid country codes from CountryData.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Change-Id: Id0ce647400bdce2eb4cdd358432b7c647f880570
|
||||
Bug: 1062861
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2122057
|
||||
Reviewed-by: Matthias Körber <koerber@google.com>
|
||||
Reviewed-by: Dominic Battré <battre@chromium.org>
|
||||
Reviewed-by: Vadym Doroshenko <dvadym@chromium.org>
|
||||
Commit-Queue: Matthias Körber <koerber@google.com>
|
||||
Cr-Commit-Position: refs/heads/master@{#758887}
|
||||
|
||||
diff --git a/components/autofill/core/browser/geo/autofill_country.cc b/components/autofill/core/browser/geo/autofill_country.cc
|
||||
index 4eb8f2b1a609deb314efd9b37578be9fa803ac67..961b1dc7a19f23c6f2cf9f831f5d544cc19cd211 100644
|
||||
--- a/components/autofill/core/browser/geo/autofill_country.cc
|
||||
+++ b/components/autofill/core/browser/geo/autofill_country.cc
|
||||
@@ -25,13 +25,28 @@ const size_t kLocaleCapacity =
|
||||
|
||||
AutofillCountry::AutofillCountry(const std::string& country_code,
|
||||
const std::string& locale) {
|
||||
- auto result =
|
||||
- CountryDataMap::GetInstance()->country_data().find(country_code);
|
||||
- DCHECK(result != CountryDataMap::GetInstance()->country_data().end());
|
||||
- const CountryData& data = result->second;
|
||||
+ CountryDataMap* country_data_map = CountryDataMap::GetInstance();
|
||||
|
||||
- country_code_ = country_code;
|
||||
- name_ = l10n_util::GetDisplayNameForCountry(country_code, locale);
|
||||
+ // If the country code is an alias (e.g. "GB" for "UK") expand the country
|
||||
+ // code.
|
||||
+ country_code_ = country_data_map->HasCountryCodeAlias(country_code)
|
||||
+ ? country_data_map->GetCountryCodeForAlias(country_code)
|
||||
+ : country_code;
|
||||
+
|
||||
+ // If there is no entry in the |CountryDataMap| for the
|
||||
+ // |country_code_for_country_data| use the country code derived from the
|
||||
+ // locale. This reverts to US.
|
||||
+ country_data_map->HasCountryData(country_code_)
|
||||
+ ? country_code_
|
||||
+ : CountryCodeForLocale(locale);
|
||||
+
|
||||
+ // Acquire the country address data.
|
||||
+ const CountryData& data = country_data_map->GetCountryData(country_code_);
|
||||
+
|
||||
+ // Translate the country name by the supplied local.
|
||||
+ name_ = l10n_util::GetDisplayNameForCountry(country_code_, locale);
|
||||
+
|
||||
+ // Get the localized strings associate with the address fields.
|
||||
postal_code_label_ = l10n_util::GetStringUTF16(data.postal_code_label_id);
|
||||
state_label_ = l10n_util::GetStringUTF16(data.state_label_id);
|
||||
address_required_fields_ = data.address_required_fields;
|
||||
diff --git a/components/autofill/core/browser/geo/autofill_country_unittest.cc b/components/autofill/core/browser/geo/autofill_country_unittest.cc
|
||||
index 8f3994de4f5d8b924cc47a989d86676ed01bd760..94315c13967f1ce640bba01a555f8b418af97ad3 100644
|
||||
--- a/components/autofill/core/browser/geo/autofill_country_unittest.cc
|
||||
+++ b/components/autofill/core/browser/geo/autofill_country_unittest.cc
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "base/android/build_info.h"
|
||||
#endif
|
||||
|
||||
+using autofill::CountryDataMap;
|
||||
using base::ASCIIToUTF16;
|
||||
|
||||
namespace autofill {
|
||||
@@ -30,6 +31,11 @@ TEST(AutofillCountryTest, AutofillCountry) {
|
||||
EXPECT_EQ("US", united_states_es.country_code());
|
||||
EXPECT_EQ(ASCIIToUTF16("Estados Unidos"), united_states_es.name());
|
||||
|
||||
+ AutofillCountry great_britain_uk_alias("UK", "en_GB");
|
||||
+ EXPECT_EQ("GB", great_britain_uk_alias.country_code());
|
||||
+ EXPECT_EQ("GB", great_britain_uk_alias.country_code());
|
||||
+ EXPECT_EQ(ASCIIToUTF16("United Kingdom"), great_britain_uk_alias.name());
|
||||
+
|
||||
AutofillCountry canada_en("CA", "en_US");
|
||||
EXPECT_EQ("CA", canada_en.country_code());
|
||||
EXPECT_EQ(ASCIIToUTF16("Canada"), canada_en.name());
|
||||
@@ -74,4 +80,27 @@ TEST(AutofillCountryTest, AllCountryCodesHaveCountryName) {
|
||||
}
|
||||
}
|
||||
|
||||
+// Test alias mappings for falsely existing country codes.
|
||||
+TEST(AutofillCountryTest, AliasMappingsForCountryData) {
|
||||
+ CountryDataMap* country_data_map = CountryDataMap::GetInstance();
|
||||
+
|
||||
+ // There should be country data for the "GB".
|
||||
+ EXPECT_TRUE(country_data_map->HasCountryData("GB"));
|
||||
+
|
||||
+ // Check the correctness of the alias definitions.
|
||||
+ EXPECT_TRUE(country_data_map->HasCountryCodeAlias("UK"));
|
||||
+ EXPECT_FALSE(country_data_map->HasCountryCodeAlias("does_not_exist"));
|
||||
+
|
||||
+ // Query not existing mapping.
|
||||
+ auto expected_country_code = std::string();
|
||||
+ auto actual_country_code =
|
||||
+ country_data_map->GetCountryCodeForAlias("does_not_exist");
|
||||
+ EXPECT_EQ(expected_country_code, actual_country_code);
|
||||
+
|
||||
+ // GB should map the UK.
|
||||
+ expected_country_code = "GB";
|
||||
+ actual_country_code = country_data_map->GetCountryCodeForAlias("UK");
|
||||
+ EXPECT_EQ(expected_country_code, actual_country_code);
|
||||
+}
|
||||
+
|
||||
} // namespace autofill
|
||||
diff --git a/components/autofill/core/browser/geo/country_data.cc b/components/autofill/core/browser/geo/country_data.cc
|
||||
index 1fe65ecf65323ce1917cb786b63d10ea4a7ac0b7..ec78e723ca71972d32ba00c2b46de9673fe91f46 100644
|
||||
--- a/components/autofill/core/browser/geo/country_data.cc
|
||||
+++ b/components/autofill/core/browser/geo/country_data.cc
|
||||
@@ -19,6 +19,17 @@ struct StaticCountryData {
|
||||
CountryData country_data;
|
||||
};
|
||||
|
||||
+// Alias definitions record for CountryData requests. A request for
|
||||
+// |country_code_alias| is served with the |CountryData| for
|
||||
+// |country_code_target|.
|
||||
+struct StaticCountryCodeAliasData {
|
||||
+ char country_code_alias[3];
|
||||
+ char country_code_target[3];
|
||||
+};
|
||||
+
|
||||
+// Alias definitions.
|
||||
+const StaticCountryCodeAliasData kCountryCodeAliases[] = {{"UK", "GB"}};
|
||||
+
|
||||
// Maps country codes to localized label string identifiers. Keep this sorted
|
||||
// by country code.
|
||||
// This list is comprized of countries appearing in both
|
||||
@@ -790,7 +801,7 @@ std::vector<std::string> GetCountryCodes() {
|
||||
return country_codes;
|
||||
}
|
||||
|
||||
-std::map<std::string, CountryData> GetCountryData() {
|
||||
+std::map<std::string, CountryData> GetCountryDataMap() {
|
||||
std::map<std::string, CountryData> country_data;
|
||||
// Add all the countries we have explicit data for.
|
||||
for (const auto& static_data : kCountryData) {
|
||||
@@ -813,6 +824,18 @@ std::map<std::string, CountryData> GetCountryData() {
|
||||
return country_data;
|
||||
}
|
||||
|
||||
+std::map<std::string, std::string> GetCountryCodeAliasMap() {
|
||||
+ std::map<std::string, std::string> country_code_aliases;
|
||||
+ // Create mappings for the aliases defined in |kCountryCodeAliases|.
|
||||
+ for (const auto& static_alias_data : kCountryCodeAliases) {
|
||||
+ // Insert the alias.
|
||||
+ country_code_aliases.insert(
|
||||
+ std::make_pair(std::string(static_alias_data.country_code_alias),
|
||||
+ std::string(static_alias_data.country_code_target)));
|
||||
+ }
|
||||
+ return country_code_aliases;
|
||||
+}
|
||||
+
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@@ -821,8 +844,38 @@ CountryDataMap* CountryDataMap::GetInstance() {
|
||||
}
|
||||
|
||||
CountryDataMap::CountryDataMap()
|
||||
- : country_data_(GetCountryData()), country_codes_(GetCountryCodes()) {}
|
||||
+ : country_data_(GetCountryDataMap()),
|
||||
+ country_code_aliases_(GetCountryCodeAliasMap()),
|
||||
+ country_codes_(GetCountryCodes()) {}
|
||||
|
||||
CountryDataMap::~CountryDataMap() = default;
|
||||
|
||||
+bool CountryDataMap::HasCountryData(const std::string& country_code) const {
|
||||
+ return country_data_.count(country_code) > 0;
|
||||
+}
|
||||
+
|
||||
+const CountryData& CountryDataMap::GetCountryData(
|
||||
+ const std::string& country_code) const {
|
||||
+ auto lookup = country_data_.find(country_code);
|
||||
+ if (lookup != country_data_.end())
|
||||
+ return lookup->second;
|
||||
+ // If there is no entry for country_code return the entry for the US.
|
||||
+ return country_data_.find("US")->second;
|
||||
+}
|
||||
+
|
||||
+bool CountryDataMap::HasCountryCodeAlias(
|
||||
+ const std::string& country_code_alias) const {
|
||||
+ return country_code_aliases_.count(country_code_alias) > 0;
|
||||
+}
|
||||
+
|
||||
+const std::string CountryDataMap::GetCountryCodeForAlias(
|
||||
+ const std::string& country_code_alias) const {
|
||||
+ auto lookup = country_code_aliases_.find(country_code_alias);
|
||||
+ if (lookup != country_code_aliases_.end()) {
|
||||
+ DCHECK(HasCountryData(lookup->second));
|
||||
+ return lookup->second;
|
||||
+ }
|
||||
+ return std::string();
|
||||
+}
|
||||
+
|
||||
} // namespace autofill
|
||||
diff --git a/components/autofill/core/browser/geo/country_data.h b/components/autofill/core/browser/geo/country_data.h
|
||||
index b6a9497594b1c22a5521a9c40fab2decae449c3f..8266102deadd40e5f2b9b24703123f59034a9781 100644
|
||||
--- a/components/autofill/core/browser/geo/country_data.h
|
||||
+++ b/components/autofill/core/browser/geo/country_data.h
|
||||
@@ -58,10 +58,23 @@ class CountryDataMap {
|
||||
public:
|
||||
static CountryDataMap* GetInstance();
|
||||
|
||||
- const std::map<std::string, CountryData>& country_data() {
|
||||
- return country_data_;
|
||||
- }
|
||||
+ // Returns true if a |CountryData| entry for the supplied |country_code|
|
||||
+ // exists.
|
||||
+ bool HasCountryData(const std::string& country_code) const;
|
||||
|
||||
+ // Returns true if there is a country code alias for |country_code|.
|
||||
+ bool HasCountryCodeAlias(const std::string& country_code_alias) const;
|
||||
+
|
||||
+ // Returns the country code for a country code alias. If no alias definition
|
||||
+ // is present return an empty string.
|
||||
+ const std::string GetCountryCodeForAlias(
|
||||
+ const std::string& country_code_alias) const;
|
||||
+
|
||||
+ // Lookup the |CountryData| for the supplied |country_code|. If no entry
|
||||
+ // exists, return the data for the US as a best guess.
|
||||
+ const CountryData& GetCountryData(const std::string& country_code) const;
|
||||
+
|
||||
+ // Return a constant reference to a vector of all country codes.
|
||||
const std::vector<std::string>& country_codes() { return country_codes_; }
|
||||
|
||||
private:
|
||||
@@ -70,6 +83,7 @@ class CountryDataMap {
|
||||
friend struct base::DefaultSingletonTraits<CountryDataMap>;
|
||||
|
||||
const std::map<std::string, CountryData> country_data_;
|
||||
+ const std::map<std::string, std::string> country_code_aliases_;
|
||||
const std::vector<std::string> country_codes_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CountryDataMap);
|
||||
257
patches/chromium/cherry-pick-eac3d9283d11.patch
Normal file
257
patches/chromium/cherry-pick-eac3d9283d11.patch
Normal file
@@ -0,0 +1,257 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Kreichgauer <martinkr@google.com>
|
||||
Date: Wed, 3 Jun 2020 21:07:08 +0000
|
||||
Subject: Revert "fido: add FidoDiscoveryFactory::ResetRequestState()"
|
||||
|
||||
This reverts commit 9f151687295d2547bc3d7c1542b80505552f0f87.
|
||||
|
||||
Reason for revert: The original change makes an invalid assumptions
|
||||
about the lifetime of FidoDiscoveryFactory (crbug/1087158). Instances of
|
||||
FidoDiscoveryFactory generally belong to the
|
||||
AuthenticatorRequestClientDelegate and as such should outlive the
|
||||
WebAuthn request. As an exception, instances obtained via
|
||||
AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride() may be
|
||||
unregistered and freed before the request finishes.
|
||||
|
||||
This revert is safe because the caBLE data reset by ResetRequestState
|
||||
(a) only gets set in the first place if the
|
||||
WebAuthenticationPhoneSupport flag is on (which is default-off); and (b)
|
||||
gets set anew for every single request, so it will never be reused
|
||||
across requests.
|
||||
|
||||
Bug: 1087158
|
||||
|
||||
Original change's description:
|
||||
> fido: add FidoDiscoveryFactory::ResetRequestState()
|
||||
>
|
||||
> FidoDiscoveryFactory instances generally outlive a WebAuthn request, but
|
||||
> some of the state is specific to a single request (caBLE pairing and QR
|
||||
> code generation keys). This is currently not an issue, because
|
||||
> AuthenticatorCommon explicitly resets all that state at the beginning of
|
||||
> the request. But I worry that we accidentally break that and leak state
|
||||
> between requests. To mitigate, introduce an explicit ResetRequestState
|
||||
> function and call it in AuthenticatorCommon::Cleanup().
|
||||
>
|
||||
> Change-Id: I8333a3b14d189d7977cde17cbfe44b4b8dcf6ee2
|
||||
> Reviewed-on:
|
||||
> https://chromium-review.googlesource.com/c/chromium/src/+/1793792
|
||||
> Commit-Queue: Martin Kreichgauer <martinkr@chromium.org>
|
||||
> Reviewed-by: Nina Satragno <nsatragno@chromium.org>
|
||||
> Reviewed-by: Adam Langley <agl@chromium.org>
|
||||
> Cr-Commit-Position: refs/heads/master@{#696593}
|
||||
|
||||
Change-Id: I3b1ea46b9b1d5912cbc7ab9a82851e5132335ea8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2228136
|
||||
Reviewed-by: Nina Satragno <nsatragno@chromium.org>
|
||||
Reviewed-by: Adam Langley <agl@chromium.org>
|
||||
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
|
||||
Cr-Commit-Position: refs/heads/master@{#774784}
|
||||
|
||||
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
|
||||
index cea81abea6f8059ff09de9c9a55c305446a0b661..7721eac960bd69351bd6963871f9f1bb96756915 100644
|
||||
--- a/content/browser/webauth/authenticator_common.cc
|
||||
+++ b/content/browser/webauth/authenticator_common.cc
|
||||
@@ -579,13 +579,12 @@ AuthenticatorCommon::CreateRequestDelegate(std::string relying_party_id) {
|
||||
|
||||
void AuthenticatorCommon::StartMakeCredentialRequest(
|
||||
bool allow_skipping_pin_touch) {
|
||||
- discovery_factory_ =
|
||||
+ device::FidoDiscoveryFactory* discovery_factory =
|
||||
AuthenticatorEnvironmentImpl::GetInstance()->GetDiscoveryFactoryOverride(
|
||||
static_cast<RenderFrameHostImpl*>(render_frame_host_)
|
||||
->frame_tree_node());
|
||||
- if (!discovery_factory_) {
|
||||
- discovery_factory_ = request_delegate_->GetDiscoveryFactory();
|
||||
- }
|
||||
+ if (!discovery_factory)
|
||||
+ discovery_factory = request_delegate_->GetDiscoveryFactory();
|
||||
|
||||
if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
|
||||
std::vector<device::CableDiscoveryData> cable_pairings =
|
||||
@@ -597,13 +596,13 @@ void AuthenticatorCommon::StartMakeCredentialRequest(
|
||||
if (request_delegate_->SetCableTransportInfo(
|
||||
/*cable_extension_provided=*/false, have_paired_phones,
|
||||
qr_generator_key)) {
|
||||
- discovery_factory_->set_cable_data(cable_pairings,
|
||||
- std::move(qr_generator_key));
|
||||
+ discovery_factory->set_cable_data(cable_pairings,
|
||||
+ std::move(qr_generator_key));
|
||||
}
|
||||
}
|
||||
|
||||
request_ = std::make_unique<device::MakeCredentialRequestHandler>(
|
||||
- connector_, discovery_factory_,
|
||||
+ connector_, discovery_factory,
|
||||
GetTransports(caller_origin_, transports_),
|
||||
*ctap_make_credential_request_, *authenticator_selection_criteria_,
|
||||
allow_skipping_pin_touch,
|
||||
@@ -634,13 +633,12 @@ void AuthenticatorCommon::StartMakeCredentialRequest(
|
||||
|
||||
void AuthenticatorCommon::StartGetAssertionRequest(
|
||||
bool allow_skipping_pin_touch) {
|
||||
- discovery_factory_ =
|
||||
+ device::FidoDiscoveryFactory* discovery_factory =
|
||||
AuthenticatorEnvironmentImpl::GetInstance()->GetDiscoveryFactoryOverride(
|
||||
static_cast<RenderFrameHostImpl*>(render_frame_host_)
|
||||
->frame_tree_node());
|
||||
- if (!discovery_factory_) {
|
||||
- discovery_factory_ = request_delegate_->GetDiscoveryFactory();
|
||||
- }
|
||||
+ if (!discovery_factory)
|
||||
+ discovery_factory = request_delegate_->GetDiscoveryFactory();
|
||||
|
||||
std::vector<device::CableDiscoveryData> cable_pairings;
|
||||
bool have_cable_extension = false;
|
||||
@@ -664,12 +662,12 @@ void AuthenticatorCommon::StartGetAssertionRequest(
|
||||
if ((!cable_pairings.empty() || qr_generator_key.has_value()) &&
|
||||
request_delegate_->SetCableTransportInfo(
|
||||
have_cable_extension, have_paired_phones, qr_generator_key)) {
|
||||
- discovery_factory_->set_cable_data(std::move(cable_pairings),
|
||||
- std::move(qr_generator_key));
|
||||
+ discovery_factory->set_cable_data(std::move(cable_pairings),
|
||||
+ std::move(qr_generator_key));
|
||||
}
|
||||
|
||||
request_ = std::make_unique<device::GetAssertionRequestHandler>(
|
||||
- connector_, discovery_factory_,
|
||||
+ connector_, discovery_factory,
|
||||
GetTransports(caller_origin_, transports_), *ctap_get_assertion_request_,
|
||||
allow_skipping_pin_touch,
|
||||
base::BindOnce(&AuthenticatorCommon::OnSignResponse,
|
||||
@@ -1528,15 +1526,6 @@ void AuthenticatorCommon::Cleanup() {
|
||||
|
||||
timer_->Stop();
|
||||
request_.reset();
|
||||
- if (discovery_factory_) {
|
||||
- // The FidoDiscoveryFactory instance may have been obtained via
|
||||
- // AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride() (in unit
|
||||
- // tests or when WebDriver injected a virtual authenticator), in which case
|
||||
- // it may be long-lived and handle more than one request. Hence, we need to
|
||||
- // reset all per-request state before deleting its pointer.
|
||||
- discovery_factory_->ResetRequestState();
|
||||
- discovery_factory_ = nullptr;
|
||||
- }
|
||||
request_delegate_.reset();
|
||||
make_credential_response_callback_.Reset();
|
||||
get_assertion_response_callback_.Reset();
|
||||
diff --git a/content/browser/webauth/authenticator_common.h b/content/browser/webauth/authenticator_common.h
|
||||
index a7879a77f337e9d31afb954c2fc397cedb74256f..bd241cc8fc34ce9d831ce5fcfb97fbd6997237f0 100644
|
||||
--- a/content/browser/webauth/authenticator_common.h
|
||||
+++ b/content/browser/webauth/authenticator_common.h
|
||||
@@ -194,7 +194,6 @@ class CONTENT_EXPORT AuthenticatorCommon {
|
||||
RenderFrameHost* const render_frame_host_;
|
||||
service_manager::Connector* connector_ = nullptr;
|
||||
base::flat_set<device::FidoTransportProtocol> transports_;
|
||||
- device::FidoDiscoveryFactory* discovery_factory_ = nullptr;
|
||||
std::unique_ptr<device::FidoRequestHandlerBase> request_;
|
||||
blink::mojom::Authenticator::MakeCredentialCallback
|
||||
make_credential_response_callback_;
|
||||
diff --git a/device/fido/fido_discovery_factory.cc b/device/fido/fido_discovery_factory.cc
|
||||
index 05d5f211b17021ac3397fd79b7f210bdf6681def..dc404ba31c2158887c3f946aecba33fb672189f0 100644
|
||||
--- a/device/fido/fido_discovery_factory.cc
|
||||
+++ b/device/fido/fido_discovery_factory.cc
|
||||
@@ -46,10 +46,6 @@ std::unique_ptr<FidoDiscoveryBase> CreateUsbFidoDiscovery(
|
||||
FidoDiscoveryFactory::FidoDiscoveryFactory() = default;
|
||||
FidoDiscoveryFactory::~FidoDiscoveryFactory() = default;
|
||||
|
||||
-void FidoDiscoveryFactory::ResetRequestState() {
|
||||
- request_state_ = {};
|
||||
-}
|
||||
-
|
||||
std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create(
|
||||
FidoTransportProtocol transport,
|
||||
service_manager::Connector* connector) {
|
||||
@@ -59,13 +55,10 @@ std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create(
|
||||
case FidoTransportProtocol::kBluetoothLowEnergy:
|
||||
return std::make_unique<FidoBleDiscovery>();
|
||||
case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
|
||||
- if (request_state_.cable_data_.has_value() ||
|
||||
- request_state_.qr_generator_key_.has_value()) {
|
||||
+ if (cable_data_.has_value() || qr_generator_key_.has_value()) {
|
||||
return std::make_unique<FidoCableDiscovery>(
|
||||
- request_state_.cable_data_.value_or(
|
||||
- std::vector<CableDiscoveryData>()),
|
||||
- request_state_.qr_generator_key_,
|
||||
- request_state_.cable_pairing_callback_);
|
||||
+ cable_data_.value_or(std::vector<CableDiscoveryData>()),
|
||||
+ qr_generator_key_, cable_pairing_callback_);
|
||||
}
|
||||
return nullptr;
|
||||
case FidoTransportProtocol::kNearFieldCommunication:
|
||||
@@ -88,14 +81,14 @@ std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create(
|
||||
void FidoDiscoveryFactory::set_cable_data(
|
||||
std::vector<CableDiscoveryData> cable_data,
|
||||
base::Optional<QRGeneratorKey> qr_generator_key) {
|
||||
- request_state_.cable_data_ = std::move(cable_data);
|
||||
- request_state_.qr_generator_key_ = std::move(qr_generator_key);
|
||||
+ cable_data_ = std::move(cable_data);
|
||||
+ qr_generator_key_ = std::move(qr_generator_key);
|
||||
}
|
||||
|
||||
void FidoDiscoveryFactory::set_cable_pairing_callback(
|
||||
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>
|
||||
pairing_callback) {
|
||||
- request_state_.cable_pairing_callback_.emplace(std::move(pairing_callback));
|
||||
+ cable_pairing_callback_.emplace(std::move(pairing_callback));
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -121,7 +114,4 @@ FidoDiscoveryFactory::MaybeCreateWinWebAuthnApiDiscovery() {
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
-FidoDiscoveryFactory::RequestState::RequestState() = default;
|
||||
-FidoDiscoveryFactory::RequestState::~RequestState() = default;
|
||||
-
|
||||
} // namespace device
|
||||
diff --git a/device/fido/fido_discovery_factory.h b/device/fido/fido_discovery_factory.h
|
||||
index 63133e7dc2bca9dc763881d74ca1e017f5799df7..3723225f316e4766d96b24f135980321bb0e5308 100644
|
||||
--- a/device/fido/fido_discovery_factory.h
|
||||
+++ b/device/fido/fido_discovery_factory.h
|
||||
@@ -38,18 +38,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
|
||||
FidoDiscoveryFactory();
|
||||
virtual ~FidoDiscoveryFactory();
|
||||
|
||||
- // Resets all fields that are only meaningful for the duration of a single
|
||||
- // request to a safe default.
|
||||
- //
|
||||
- // The "regular" FidoDiscoveryFactory is owned by the
|
||||
- // AuthenticatorClientRequestDelegate and lives only for a single request.
|
||||
- // Instances returned from
|
||||
- // AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride(), which are
|
||||
- // used in unit tests or by the WebDriver virtual authenticators, are
|
||||
- // long-lived and may handle multiple WebAuthn requests. Hence, they will be
|
||||
- // reset at the beginning of each new request.
|
||||
- void ResetRequestState();
|
||||
-
|
||||
// Instantiates a FidoDiscoveryBase for the given transport.
|
||||
//
|
||||
// FidoTransportProtocol::kUsbHumanInterfaceDevice requires specifying a
|
||||
@@ -89,22 +77,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
private:
|
||||
- // RequestState holds configuration data that is only meaningful for a
|
||||
- // single WebAuthn request.
|
||||
- struct RequestState {
|
||||
- RequestState();
|
||||
- ~RequestState();
|
||||
- base::Optional<std::vector<CableDiscoveryData>> cable_data_;
|
||||
- base::Optional<QRGeneratorKey> qr_generator_key_;
|
||||
- base::Optional<
|
||||
- base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>>
|
||||
- cable_pairing_callback_;
|
||||
- };
|
||||
-
|
||||
- RequestState request_state_;
|
||||
#if defined(OS_MACOSX)
|
||||
base::Optional<fido::mac::AuthenticatorConfig> mac_touch_id_config_;
|
||||
#endif // defined(OS_MACOSX)
|
||||
+ base::Optional<std::vector<CableDiscoveryData>> cable_data_;
|
||||
+ base::Optional<QRGeneratorKey> qr_generator_key_;
|
||||
+ base::Optional<
|
||||
+ base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>>
|
||||
+ cable_pairing_callback_;
|
||||
#if defined(OS_WIN)
|
||||
WinWebAuthnApi* win_webauthn_api_ = nullptr;
|
||||
#endif // defined(OS_WIN)
|
||||
@@ -3,17 +3,8 @@ From: Jeremy Apthorp <jeremya@chromium.org>
|
||||
Date: Wed, 10 Oct 2018 15:07:34 -0700
|
||||
Subject: command-ismediakey.patch
|
||||
|
||||
Override MediaKeysListener::IsMediaKeycode to also listen for Volume Up, Volume Down,
|
||||
and Mute. We also need to patch out Chromium's usage of RemoteCommandCenterDelegate, as
|
||||
it uses MPRemoteCommandCenter. MPRemoteCommandCenter makes it such that GlobalShortcuts
|
||||
in Electron will not work as intended, because by design an app does not receive remote
|
||||
control events until it begins playing audio. This means that a media shortcut would not kick
|
||||
into effect until you, for example, began playing a YouTube video which sort of defeats the
|
||||
purpose of GlobalShortcuts.
|
||||
|
||||
At the moment there is no upstream possibility for this; but perhaps Chromium may
|
||||
consider some kind of switch, enabled by default, which would conditionally choose to avoid usage of
|
||||
RemoteCommandCenterDelegate on macOS.
|
||||
Override MediaKeysListener::IsMediaKeycode and associated functions to also listen for
|
||||
Volume Up, Volume Down, and Mute.
|
||||
|
||||
diff --git a/chrome/browser/extensions/global_shortcut_listener_win.cc b/chrome/browser/extensions/global_shortcut_listener_win.cc
|
||||
index c5125495b4d178ffb18be4d2d9670f7556412cbd..cddb321abb938c667a4a2089f87eab999510e9b1 100644
|
||||
@@ -73,18 +64,10 @@ index 1145e1f3d79482b5bb468c3128431ac674310e5f..e319e7a3e34e05b0e96d4a2dbb456355
|
||||
|
||||
} // namespace ui
|
||||
diff --git a/ui/base/accelerators/media_keys_listener_mac.mm b/ui/base/accelerators/media_keys_listener_mac.mm
|
||||
index 85378bb565de617b1bd611d28c8714361747a357..d67d558b91b49835dfa927893093948093c54f7a 100644
|
||||
index 85378bb565de617b1bd611d28c8714361747a357..36de4c0b0353be2418dacd388e92d7c38a7ee139 100644
|
||||
--- a/ui/base/accelerators/media_keys_listener_mac.mm
|
||||
+++ b/ui/base/accelerators/media_keys_listener_mac.mm
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <IOKit/hidsystem/ev_keymap.h>
|
||||
|
||||
#include "base/containers/flat_set.h"
|
||||
+#include "electron/buildflags/buildflags.h"
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
#include "ui/base/accelerators/system_media_controls_media_keys_listener.h"
|
||||
|
||||
@@ -32,6 +33,12 @@ KeyboardCode MediaKeyCodeToKeyboardCode(int key_code) {
|
||||
@@ -32,6 +32,12 @@ KeyboardCode MediaKeyCodeToKeyboardCode(int key_code) {
|
||||
case NX_KEYTYPE_NEXT:
|
||||
case NX_KEYTYPE_FAST:
|
||||
return VKEY_MEDIA_NEXT_TRACK;
|
||||
@@ -97,7 +80,7 @@ index 85378bb565de617b1bd611d28c8714361747a357..d67d558b91b49835dfa9278930939480
|
||||
}
|
||||
return VKEY_UNKNOWN;
|
||||
}
|
||||
@@ -192,7 +199,10 @@ static CGEventRef EventTapCallback(CGEventTapProxy proxy,
|
||||
@@ -192,7 +198,10 @@ CGEventRef MediaKeysListenerImpl::EventTapCallback(CGEventTapProxy proxy,
|
||||
int key_code = (data1 & 0xFFFF0000) >> 16;
|
||||
if (key_code != NX_KEYTYPE_PLAY && key_code != NX_KEYTYPE_NEXT &&
|
||||
key_code != NX_KEYTYPE_PREVIOUS && key_code != NX_KEYTYPE_FAST &&
|
||||
@@ -109,3 +92,31 @@ index 85378bb565de617b1bd611d28c8714361747a357..d67d558b91b49835dfa9278930939480
|
||||
return event;
|
||||
}
|
||||
|
||||
diff --git a/ui/base/accelerators/system_media_controls_media_keys_listener.cc b/ui/base/accelerators/system_media_controls_media_keys_listener.cc
|
||||
index 9d6084ceaccfd071549e63e3015f55ef292312ec..846210b04d6e2e193413c643296938ec550f6d25 100644
|
||||
--- a/ui/base/accelerators/system_media_controls_media_keys_listener.cc
|
||||
+++ b/ui/base/accelerators/system_media_controls_media_keys_listener.cc
|
||||
@@ -65,6 +65,11 @@ bool SystemMediaControlsMediaKeysListener::StartWatchingMediaKey(
|
||||
case VKEY_MEDIA_STOP:
|
||||
service_->SetIsStopEnabled(true);
|
||||
break;
|
||||
+ case VKEY_VOLUME_DOWN:
|
||||
+ case VKEY_VOLUME_UP:
|
||||
+ case VKEY_VOLUME_MUTE:
|
||||
+ // Do nothing.
|
||||
+ break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
@@ -97,6 +102,11 @@ void SystemMediaControlsMediaKeysListener::StopWatchingMediaKey(
|
||||
case VKEY_MEDIA_STOP:
|
||||
service_->SetIsStopEnabled(false);
|
||||
break;
|
||||
+ case VKEY_VOLUME_DOWN:
|
||||
+ case VKEY_VOLUME_UP:
|
||||
+ case VKEY_VOLUME_MUTE:
|
||||
+ // Do nothing.
|
||||
+ break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ index a947db5fb562fb4ccbfb94df88f460f1da9451f4..77c816b2c5e98a4546c74d9358dfcf3f
|
||||
|
||||
gfx::ColorSpace::TransferID transfer_id =
|
||||
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc
|
||||
index c383d42c986aa29fcdfc2009901ed452ef480b55..1b8d0818155a407eb42c3f785e9609fe7bfa3dc7 100644
|
||||
index c383d42c986aa29fcdfc2009901ed452ef480b55..cdc87912b7d646a95796c84b76d583033c64c4dc 100644
|
||||
--- a/ui/gfx/mac/io_surface.cc
|
||||
+++ b/ui/gfx/mac/io_surface.cc
|
||||
@@ -16,6 +16,7 @@
|
||||
@@ -321,33 +321,37 @@ index c383d42c986aa29fcdfc2009901ed452ef480b55..1b8d0818155a407eb42c3f785e9609fe
|
||||
|
||||
namespace gfx {
|
||||
|
||||
@@ -261,6 +262,11 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size,
|
||||
IOSurfaceSetValue(surface, CFSTR("IOSurfaceColorSpace"), kCGColorSpaceSRGB);
|
||||
} else {
|
||||
CGColorSpaceRef color_space = base::mac::GetSRGBColorSpace();
|
||||
+ auto* cmd_line = base::CommandLine::ForCurrentProcess();
|
||||
+ if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
|
||||
+ color_space = base::mac::GetSystemColorSpace();
|
||||
+ }
|
||||
+
|
||||
base::ScopedCFTypeRef<CFDataRef> color_space_icc(
|
||||
CGColorSpaceCopyICCProfile(color_space));
|
||||
IOSurfaceSetValue(surface, CFSTR("IOSurfaceColorSpace"), color_space_icc);
|
||||
@@ -277,6 +283,14 @@ bool IOSurfaceCanSetColorSpace(const ColorSpace& color_space) {
|
||||
|
||||
void IOSurfaceSetColorSpace(IOSurfaceRef io_surface,
|
||||
@@ -126,6 +127,14 @@ void IOSurfaceMachPortTraits::Release(mach_port_t port) {
|
||||
// Common method used by IOSurfaceSetColorSpace and IOSurfaceCanSetColorSpace.
|
||||
bool IOSurfaceSetColorSpace(IOSurfaceRef io_surface,
|
||||
const ColorSpace& color_space) {
|
||||
+ auto* cmd_line = base::CommandLine::ForCurrentProcess();
|
||||
+ if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
|
||||
+ base::ScopedCFTypeRef<CFDataRef> system_icc(
|
||||
+ CGColorSpaceCopyICCProfile(base::mac::GetSystemColorSpace()));
|
||||
+ IOSurfaceSetValue(io_surface, CFSTR("IOSurfaceColorSpace"), system_icc);
|
||||
+ return;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
if (!internal::IOSurfaceSetColorSpace(io_surface, color_space)) {
|
||||
DLOG(ERROR) << "Failed to set color space for IOSurface: "
|
||||
<< color_space.ToString();
|
||||
// Allow but ignore invalid color spaces.
|
||||
if (!color_space.IsValid())
|
||||
return true;
|
||||
@@ -256,6 +265,15 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size,
|
||||
DCHECK_EQ(kIOReturnSuccess, r);
|
||||
}
|
||||
|
||||
+ auto* cmd_line = base::CommandLine::ForCurrentProcess();
|
||||
+ if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
|
||||
+ CGColorSpaceRef color_space = base::mac::GetSystemColorSpace();
|
||||
+ base::ScopedCFTypeRef<CFDataRef> color_space_icc(
|
||||
+ CGColorSpaceCopyICCProfile(color_space));
|
||||
+ IOSurfaceSetValue(surface, CFSTR("IOSurfaceColorSpace"), color_space_icc);
|
||||
+ return surface;
|
||||
+ }
|
||||
+
|
||||
// Ensure that all IOSurfaces start as sRGB.
|
||||
if (__builtin_available(macos 10.12, *)) {
|
||||
IOSurfaceSetValue(surface, CFSTR("IOSurfaceColorSpace"), kCGColorSpaceSRGB);
|
||||
diff --git a/ui/gfx/switches.cc b/ui/gfx/switches.cc
|
||||
index ba3dbf23d1df7a3b0cc199054f36a88014daa0e7..f8a563a78cee2856da0f2ad556beba19b01a2e59 100644
|
||||
--- a/ui/gfx/switches.cc
|
||||
|
||||
@@ -9,7 +9,7 @@ diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/cont
|
||||
index 5bec9c5d258c06fe338c8abe3e233e0b9b937234..92d2fa2343d1272dcadfa37c07ed368d18488ef8 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
|
||||
@@ -477,7 +477,11 @@
|
||||
@@ -477,7 +477,11 @@ void RenderWidgetHostViewMac::WasOccluded() {
|
||||
return;
|
||||
|
||||
host()->WasHidden();
|
||||
|
||||
@@ -26,10 +26,10 @@ index d9175ae9661218b58e9b587ad3a9dbd540bfd384..ed178ea7b3d7f8039f47402bc08cae20
|
||||
}
|
||||
|
||||
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
|
||||
index 205181053803813b64497884bc93cfd857254866..bb9e6fba1cb0dd734c7aeb8dcd2eeadcd4b5d2da 100644
|
||||
index 205181053803813b64497884bc93cfd857254866..7b14086b43eeb86baa0f8471e15e7f6f19193889 100644
|
||||
--- a/ui/native_theme/native_theme.h
|
||||
+++ b/ui/native_theme/native_theme.h
|
||||
@@ -431,6 +431,22 @@ class NATIVE_THEME_EXPORT NativeTheme {
|
||||
@@ -431,6 +431,38 @@ class NATIVE_THEME_EXPORT NativeTheme {
|
||||
ColorId color_id,
|
||||
ColorScheme color_scheme = ColorScheme::kDefault) const = 0;
|
||||
|
||||
@@ -44,15 +44,31 @@ index 205181053803813b64497884bc93cfd857254866..bb9e6fba1cb0dd734c7aeb8dcd2eeadc
|
||||
+ }
|
||||
+
|
||||
+ void set_theme_source(ThemeSource theme_source) {
|
||||
+ bool original = ShouldUseDarkColors();
|
||||
+ bool original_dark_colors = ShouldUseDarkColors();
|
||||
+ PreferredColorScheme original_color_scheme = GetPreferredColorScheme();
|
||||
+
|
||||
+ theme_source_ = theme_source;
|
||||
+ if (ShouldUseDarkColors() != original) NotifyObservers();
|
||||
+
|
||||
+ bool changed = false;
|
||||
+ if (ShouldUseDarkColors() != original_dark_colors) {
|
||||
+ changed = true;
|
||||
+ }
|
||||
+
|
||||
+ PreferredColorScheme new_color_scheme = CalculatePreferredColorScheme();
|
||||
+ if (new_color_scheme != original_color_scheme) {
|
||||
+ set_preferred_color_scheme(new_color_scheme);
|
||||
+ changed = true;
|
||||
+ }
|
||||
+
|
||||
+ if (changed) {
|
||||
+ NotifyObservers();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// Returns a shared instance of the native theme that should be used for web
|
||||
// rendering. Do not use it in a normal application context (i.e. browser).
|
||||
// The returned object should not be deleted by the caller. This function is
|
||||
@@ -555,6 +571,8 @@ class NATIVE_THEME_EXPORT NativeTheme {
|
||||
@@ -555,6 +587,8 @@ class NATIVE_THEME_EXPORT NativeTheme {
|
||||
PreferredColorScheme preferred_color_scheme_ =
|
||||
PreferredColorScheme::kNoPreference;
|
||||
|
||||
@@ -62,10 +78,10 @@ index 205181053803813b64497884bc93cfd857254866..bb9e6fba1cb0dd734c7aeb8dcd2eeadc
|
||||
};
|
||||
|
||||
diff --git a/ui/native_theme/native_theme_dark_aura.cc b/ui/native_theme/native_theme_dark_aura.cc
|
||||
index a8fbfee3b13672902aac05fd5a65fa8ee81f9f7e..1be6369acf0b7c02a6f862636c2b2de1fbf8cb5a 100644
|
||||
index a8fbfee3b13672902aac05fd5a65fa8ee81f9f7e..80770f0e46641f0d4ea81c6fa6602a68c1f9b9a8 100644
|
||||
--- a/ui/native_theme/native_theme_dark_aura.cc
|
||||
+++ b/ui/native_theme/native_theme_dark_aura.cc
|
||||
@@ -20,6 +20,8 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id,
|
||||
@@ -20,12 +20,14 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id,
|
||||
}
|
||||
|
||||
bool NativeThemeDarkAura::ShouldUseDarkColors() const {
|
||||
@@ -74,6 +90,13 @@ index a8fbfee3b13672902aac05fd5a65fa8ee81f9f7e..1be6369acf0b7c02a6f862636c2b2de1
|
||||
return true;
|
||||
}
|
||||
|
||||
NativeTheme::PreferredColorScheme NativeThemeDarkAura::GetPreferredColorScheme()
|
||||
const {
|
||||
- return NativeTheme::PreferredColorScheme::kDark;
|
||||
+ return ShouldUseDarkColors() ? NativeTheme::PreferredColorScheme::kDark : NativeTheme::PreferredColorScheme::kLight;
|
||||
}
|
||||
|
||||
NativeThemeDarkAura::NativeThemeDarkAura() : NativeThemeAura(false) {}
|
||||
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc
|
||||
index cff7681a4e0023a67edda37bf9865ab073b32549..83507081e0734b53fd37133014256243dda6864d 100644
|
||||
--- a/ui/native_theme/native_theme_win.cc
|
||||
|
||||
@@ -4,12 +4,11 @@ Date: Sun, 1 Mar 2020 16:33:55 -0800
|
||||
Subject: feat: allow embedders to add observers on created hunspell
|
||||
dictionaries
|
||||
|
||||
|
||||
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc
|
||||
index 0dc509bafcfab2637aab4ea55769cd06ad3492c9..3b1f02e354c5c5a85e9193859ca8e7497f02cf86 100644
|
||||
index 6a508168067b70822fabee5d50a5be7ac2ed15a5..5afbef4fb24441a850c45703b2d7a66b8f92abb1 100644
|
||||
--- a/chrome/browser/spellchecker/spellcheck_service.cc
|
||||
+++ b/chrome/browser/spellchecker/spellcheck_service.cc
|
||||
@@ -284,6 +284,9 @@ void SpellcheckService::LoadHunspellDictionaries() {
|
||||
@@ -266,6 +266,9 @@ void SpellcheckService::LoadHunspellDictionaries() {
|
||||
std::make_unique<SpellcheckHunspellDictionary>(dictionary, context_,
|
||||
this));
|
||||
hunspell_dictionaries_.back()->AddObserver(this);
|
||||
@@ -19,7 +18,7 @@ index 0dc509bafcfab2637aab4ea55769cd06ad3492c9..3b1f02e354c5c5a85e9193859ca8e749
|
||||
hunspell_dictionaries_.back()->Load();
|
||||
}
|
||||
|
||||
@@ -297,6 +300,20 @@ SpellcheckService::GetHunspellDictionaries() {
|
||||
@@ -279,6 +282,20 @@ SpellcheckService::GetHunspellDictionaries() {
|
||||
return hunspell_dictionaries_;
|
||||
}
|
||||
|
||||
@@ -41,10 +40,10 @@ index 0dc509bafcfab2637aab4ea55769cd06ad3492c9..3b1f02e354c5c5a85e9193859ca8e749
|
||||
std::string locale,
|
||||
std::string path,
|
||||
diff --git a/chrome/browser/spellchecker/spellcheck_service.h b/chrome/browser/spellchecker/spellcheck_service.h
|
||||
index 557a0a2a91821a595181481f92b2a2a06dcb1f50..59e24da4be927303df8c4aac87f50778c1c208b0 100644
|
||||
index d5af9d5829c362743e64a9f2fefdf58a340c4b9f..8c00b16996192a4b65f4794e0018b50559bbe1c1 100644
|
||||
--- a/chrome/browser/spellchecker/spellcheck_service.h
|
||||
+++ b/chrome/browser/spellchecker/spellcheck_service.h
|
||||
@@ -116,6 +116,8 @@ class SpellcheckService : public KeyedService,
|
||||
@@ -114,6 +114,8 @@ class SpellcheckService : public KeyedService,
|
||||
const std::vector<std::unique_ptr<SpellcheckHunspellDictionary>>&
|
||||
GetHunspellDictionaries();
|
||||
|
||||
@@ -53,7 +52,7 @@ index 557a0a2a91821a595181481f92b2a2a06dcb1f50..59e24da4be927303df8c4aac87f50778
|
||||
// Load a dictionary from a given path. Format specifies how the dictionary
|
||||
// is stored. Return value is true if successful.
|
||||
bool LoadExternalDictionary(std::string language,
|
||||
@@ -213,6 +215,8 @@ class SpellcheckService : public KeyedService,
|
||||
@@ -195,6 +197,8 @@ class SpellcheckService : public KeyedService,
|
||||
// A pointer to the BrowserContext which this service refers to.
|
||||
content::BrowserContext* context_;
|
||||
|
||||
|
||||
@@ -0,0 +1,636 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Dill <andy.dill@gmail.com>
|
||||
Date: Thu, 30 Jan 2020 09:36:07 -0800
|
||||
Subject: feat: enable off-screen rendering with viz compositor
|
||||
|
||||
This patch adds hooks in the relevant places that allow for off-screen
|
||||
rendering with the viz compositor by way of a custom HostDisplayClient
|
||||
and LayeredWindowUpdater.
|
||||
|
||||
diff --git a/components/viz/host/host_display_client.cc b/components/viz/host/host_display_client.cc
|
||||
index 3547ee865c220731a6b4be4c1b32ec899b3dd11f..715bfa4b5db5fc4beb83c26b1eedda82c87a245b 100644
|
||||
--- a/components/viz/host/host_display_client.cc
|
||||
+++ b/components/viz/host/host_display_client.cc
|
||||
@@ -43,9 +43,13 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams(
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined(OS_WIN)
|
||||
+void HostDisplayClient::IsOffscreen(IsOffscreenCallback callback) {
|
||||
+ std::move(callback).Run(false);
|
||||
+}
|
||||
+
|
||||
void HostDisplayClient::CreateLayeredWindowUpdater(
|
||||
mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) {
|
||||
+#if defined(OS_WIN)
|
||||
if (!NeedsToUseLayerWindow(widget_)) {
|
||||
DLOG(ERROR) << "HWND shouldn't be using a layered window";
|
||||
return;
|
||||
@@ -53,8 +57,12 @@ void HostDisplayClient::CreateLayeredWindowUpdater(
|
||||
|
||||
layered_window_updater_ =
|
||||
std::make_unique<LayeredWindowUpdaterImpl>(widget_, std::move(receiver));
|
||||
-}
|
||||
+#else
|
||||
+ CHECK(false) << "Chromium is calling CreateLayeredWindowUpdater for non-OSR "
|
||||
+ "windows on POSIX platforms, something is wrong with "
|
||||
+ "Electron's OSR implementation.";
|
||||
#endif
|
||||
+}
|
||||
|
||||
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
|
||||
void HostDisplayClient::DidCompleteSwapWithNewSize(const gfx::Size& size) {
|
||||
diff --git a/components/viz/host/host_display_client.h b/components/viz/host/host_display_client.h
|
||||
index cedf833d23589dc3157168cfc7e6d3bb12939f7a..4437a7875076ef5a99ddcd767036ec37c2d48d44 100644
|
||||
--- a/components/viz/host/host_display_client.h
|
||||
+++ b/components/viz/host/host_display_client.h
|
||||
@@ -31,17 +31,17 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient {
|
||||
mojo::PendingRemote<mojom::DisplayClient> GetBoundRemote(
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
|
||||
|
||||
- private:
|
||||
+ protected:
|
||||
// mojom::DisplayClient implementation:
|
||||
+ void IsOffscreen(IsOffscreenCallback callback) override;
|
||||
+
|
||||
#if defined(OS_MACOSX)
|
||||
void OnDisplayReceivedCALayerParams(
|
||||
const gfx::CALayerParams& ca_layer_params) override;
|
||||
#endif
|
||||
|
||||
-#if defined(OS_WIN)
|
||||
void CreateLayeredWindowUpdater(
|
||||
mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) override;
|
||||
-#endif
|
||||
|
||||
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
|
||||
void DidCompleteSwapWithNewSize(const gfx::Size& size) override;
|
||||
diff --git a/components/viz/host/layered_window_updater_impl.cc b/components/viz/host/layered_window_updater_impl.cc
|
||||
index b04f654fe820f821b18e059cdd40085fc2384c4e..ee22012b01ef92bb3b32b5b1081609a7bdfb0d93 100644
|
||||
--- a/components/viz/host/layered_window_updater_impl.cc
|
||||
+++ b/components/viz/host/layered_window_updater_impl.cc
|
||||
@@ -44,7 +44,9 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory(
|
||||
// |region|'s handle will close when it goes out of scope.
|
||||
}
|
||||
|
||||
-void LayeredWindowUpdaterImpl::Draw(DrawCallback draw_callback) {
|
||||
+void LayeredWindowUpdaterImpl::Draw(
|
||||
+ const gfx::Rect& damage_rect,
|
||||
+ DrawCallback draw_callback) {
|
||||
TRACE_EVENT0("viz", "LayeredWindowUpdaterImpl::Draw");
|
||||
|
||||
if (!canvas_) {
|
||||
diff --git a/components/viz/host/layered_window_updater_impl.h b/components/viz/host/layered_window_updater_impl.h
|
||||
index 1026b739d283f0fc252fa2af83a6d4cf51bc8553..fe562ab60ce98b8bb0c5080a6428deb319a4dd04 100644
|
||||
--- a/components/viz/host/layered_window_updater_impl.h
|
||||
+++ b/components/viz/host/layered_window_updater_impl.h
|
||||
@@ -35,7 +35,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl
|
||||
// mojom::LayeredWindowUpdater implementation.
|
||||
void OnAllocatedSharedMemory(const gfx::Size& pixel_size,
|
||||
base::UnsafeSharedMemoryRegion region) override;
|
||||
- void Draw(DrawCallback draw_callback) override;
|
||||
+ void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override;
|
||||
|
||||
private:
|
||||
const HWND hwnd_;
|
||||
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
|
||||
index ca67f58b73cc13b1e0895b17d69c9781c567afa1..cddf6d35eaa8fbe36844211dd9798605452d9e9a 100644
|
||||
--- a/components/viz/service/BUILD.gn
|
||||
+++ b/components/viz/service/BUILD.gn
|
||||
@@ -121,6 +121,8 @@ viz_component("service") {
|
||||
"display_embedder/output_surface_provider_impl.h",
|
||||
"display_embedder/server_shared_bitmap_manager.cc",
|
||||
"display_embedder/server_shared_bitmap_manager.h",
|
||||
+ "display_embedder/software_output_device_proxy.cc",
|
||||
+ "display_embedder/software_output_device_proxy.h",
|
||||
"display_embedder/software_output_surface.cc",
|
||||
"display_embedder/software_output_surface.h",
|
||||
"display_embedder/viz_process_context_provider.cc",
|
||||
diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.cc b/components/viz/service/display_embedder/output_surface_provider_impl.cc
|
||||
index 6f2eac863d1b82ea1739b369861ada2e626627de..1011080626807dd6baf6c08f9b704905cba4e3c8 100644
|
||||
--- a/components/viz/service/display_embedder/output_surface_provider_impl.cc
|
||||
+++ b/components/viz/service/display_embedder/output_surface_provider_impl.cc
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
|
||||
#include "components/viz/service/display_embedder/skia_output_surface_dependency_impl.h"
|
||||
#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
|
||||
+#include "components/viz/service/display_embedder/software_output_device_proxy.h"
|
||||
#include "components/viz/service/display_embedder/software_output_surface.h"
|
||||
#include "components/viz/service/display_embedder/viz_process_context_provider.h"
|
||||
#include "components/viz/service/gl/gpu_service_impl.h"
|
||||
@@ -33,6 +34,7 @@
|
||||
#include "gpu/ipc/scheduler_sequence.h"
|
||||
#include "gpu/ipc/service/gpu_channel_manager_delegate.h"
|
||||
#include "gpu/ipc/service/image_transport_surface.h"
|
||||
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
#include "ui/gl/gl_context.h"
|
||||
#include "ui/gl/init/gl_factory.h"
|
||||
@@ -227,6 +229,22 @@ OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
|
||||
if (headless_)
|
||||
return std::make_unique<SoftwareOutputDevice>();
|
||||
|
||||
+#if !defined(OS_MACOSX)
|
||||
+ {
|
||||
+ mojo::ScopedAllowSyncCallForTesting allow_sync;
|
||||
+ DCHECK(display_client);
|
||||
+ bool offscreen = false;
|
||||
+ if (display_client->IsOffscreen(&offscreen) && offscreen) {
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater;
|
||||
+ display_client->CreateLayeredWindowUpdater(
|
||||
+ mojo::MakeRequest(&layered_window_updater));
|
||||
+
|
||||
+ return std::make_unique<SoftwareOutputDeviceProxy>(
|
||||
+ std::move(layered_window_updater));
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
#if defined(OS_WIN)
|
||||
return CreateSoftwareOutputDeviceWin(surface_handle, &output_device_backing_,
|
||||
display_client);
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_mac.cc b/components/viz/service/display_embedder/software_output_device_mac.cc
|
||||
index b9357082293cc55650144ccbc8bada8fe6d1cac4..b4cb07e26d1504719f80e5835c1cb5f138b9f1ab 100644
|
||||
--- a/components/viz/service/display_embedder/software_output_device_mac.cc
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_mac.cc
|
||||
@@ -102,6 +102,8 @@ void SoftwareOutputDeviceMac::UpdateAndCopyBufferDamage(
|
||||
|
||||
SkCanvas* SoftwareOutputDeviceMac::BeginPaint(
|
||||
const gfx::Rect& new_damage_rect) {
|
||||
+ last_damage = new_damage_rect;
|
||||
+
|
||||
// Record the previous paint buffer.
|
||||
Buffer* previous_paint_buffer =
|
||||
buffer_queue_.empty() ? nullptr : buffer_queue_.back().get();
|
||||
@@ -184,6 +186,7 @@ void SoftwareOutputDeviceMac::EndPaint() {
|
||||
ca_layer_params.is_empty = false;
|
||||
ca_layer_params.scale_factor = scale_factor_;
|
||||
ca_layer_params.pixel_size = pixel_size_;
|
||||
+ ca_layer_params.damage = last_damage;
|
||||
ca_layer_params.io_surface_mach_port.reset(
|
||||
IOSurfaceCreateMachPort(current_paint_buffer_->io_surface));
|
||||
client_->SoftwareDeviceUpdatedCALayerParams(ca_layer_params);
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_mac.h b/components/viz/service/display_embedder/software_output_device_mac.h
|
||||
index f3867356e3d641416e00e6d115ae9ae2a0be90ab..b1d192d2b20ccb63fba07093101d745e5ffe86dd 100644
|
||||
--- a/components/viz/service/display_embedder/software_output_device_mac.h
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_mac.h
|
||||
@@ -56,6 +56,7 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice {
|
||||
void UpdateAndCopyBufferDamage(Buffer* previous_paint_buffer,
|
||||
const SkRegion& new_damage_rect);
|
||||
|
||||
+ gfx::Rect last_damage;
|
||||
gfx::Size pixel_size_;
|
||||
float scale_factor_ = 1;
|
||||
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_proxy.cc b/components/viz/service/display_embedder/software_output_device_proxy.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4efea02f80f8b6818291321a7c63f0f4815a5b98
|
||||
--- /dev/null
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_proxy.cc
|
||||
@@ -0,0 +1,157 @@
|
||||
+// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "components/viz/service/display_embedder/software_output_device_proxy.h"
|
||||
+
|
||||
+#include "base/memory/unsafe_shared_memory_region.h"
|
||||
+#include "base/threading/thread_checker.h"
|
||||
+#include "base/trace_event/trace_event.h"
|
||||
+#include "components/viz/common/resources/resource_sizes.h"
|
||||
+#include "components/viz/service/display_embedder/output_device_backing.h"
|
||||
+#include "mojo/public/cpp/system/platform_handle.h"
|
||||
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
|
||||
+#include "skia/ext/platform_canvas.h"
|
||||
+#include "third_party/skia/include/core/SkCanvas.h"
|
||||
+#include "ui/gfx/skia_util.h"
|
||||
+
|
||||
+#if defined(OS_WIN)
|
||||
+#include "skia/ext/skia_utils_win.h"
|
||||
+#include "ui/gfx/gdi_util.h"
|
||||
+#include "ui/gfx/win/hwnd_util.h"
|
||||
+#else
|
||||
+#include "mojo/public/cpp/base/shared_memory_utils.h"
|
||||
+#endif
|
||||
+
|
||||
+namespace viz {
|
||||
+
|
||||
+SoftwareOutputDeviceBase::~SoftwareOutputDeviceBase() {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(!in_paint_);
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceBase::Resize(const gfx::Size& viewport_pixel_size,
|
||||
+ float scale_factor) {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(!in_paint_);
|
||||
+
|
||||
+ if (viewport_pixel_size_ == viewport_pixel_size)
|
||||
+ return;
|
||||
+
|
||||
+ viewport_pixel_size_ = viewport_pixel_size;
|
||||
+ ResizeDelegated();
|
||||
+}
|
||||
+
|
||||
+SkCanvas* SoftwareOutputDeviceBase::BeginPaint(
|
||||
+ const gfx::Rect& damage_rect) {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(!in_paint_);
|
||||
+
|
||||
+ damage_rect_ = damage_rect;
|
||||
+ in_paint_ = true;
|
||||
+ return BeginPaintDelegated();
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceBase::EndPaint() {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ DCHECK(in_paint_);
|
||||
+
|
||||
+ in_paint_ = false;
|
||||
+
|
||||
+ gfx::Rect intersected_damage_rect = damage_rect_;
|
||||
+ intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_));
|
||||
+ if (intersected_damage_rect.IsEmpty())
|
||||
+ return;
|
||||
+
|
||||
+ EndPaintDelegated(intersected_damage_rect);
|
||||
+}
|
||||
+
|
||||
+SoftwareOutputDeviceProxy::~SoftwareOutputDeviceProxy() = default;
|
||||
+
|
||||
+SoftwareOutputDeviceProxy::SoftwareOutputDeviceProxy(
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater)
|
||||
+ : layered_window_updater_(std::move(layered_window_updater)) {
|
||||
+ DCHECK(layered_window_updater_.is_bound());
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::OnSwapBuffers(
|
||||
+ SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback) {
|
||||
+ DCHECK(swap_ack_callback_.is_null());
|
||||
+
|
||||
+ // We aren't waiting on DrawAck() and can immediately run the callback.
|
||||
+ if (!waiting_on_draw_ack_) {
|
||||
+ task_runner_->PostTask(FROM_HERE,
|
||||
+ base::BindOnce(std::move(swap_ack_callback), viewport_pixel_size_));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ swap_ack_callback_ = std::move(swap_ack_callback);
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::ResizeDelegated() {
|
||||
+ canvas_.reset();
|
||||
+
|
||||
+ size_t required_bytes;
|
||||
+ if (!ResourceSizes::MaybeSizeInBytes(
|
||||
+ viewport_pixel_size_, ResourceFormat::RGBA_8888, &required_bytes)) {
|
||||
+ DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ base::UnsafeSharedMemoryRegion region =
|
||||
+ base::UnsafeSharedMemoryRegion::Create(required_bytes);
|
||||
+ if (!region.IsValid()) {
|
||||
+ DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ #if defined(WIN32)
|
||||
+ canvas_ = skia::CreatePlatformCanvasWithSharedSection(
|
||||
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
|
||||
+ region.GetPlatformHandle(), skia::CRASH_ON_FAILURE);
|
||||
+ #else
|
||||
+ shm_mapping_ = region.Map();
|
||||
+ if (!shm_mapping_.IsValid()) {
|
||||
+ DLOG(ERROR) << "Failed to map " << required_bytes << " bytes";
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ canvas_ = skia::CreatePlatformCanvasWithPixels(
|
||||
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
|
||||
+ static_cast<uint8_t*>(shm_mapping_.memory()), skia::CRASH_ON_FAILURE);
|
||||
+ #endif
|
||||
+
|
||||
+ // Transfer region ownership to the browser process.
|
||||
+ layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_,
|
||||
+ std::move(region));
|
||||
+}
|
||||
+
|
||||
+SkCanvas* SoftwareOutputDeviceProxy::BeginPaintDelegated() {
|
||||
+ return canvas_.get();
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::EndPaintDelegated(
|
||||
+ const gfx::Rect& damage_rect) {
|
||||
+ DCHECK(!waiting_on_draw_ack_);
|
||||
+
|
||||
+ if (!canvas_)
|
||||
+ return;
|
||||
+
|
||||
+ layered_window_updater_->Draw(damage_rect, base::BindOnce(
|
||||
+ &SoftwareOutputDeviceProxy::DrawAck, base::Unretained(this)));
|
||||
+ waiting_on_draw_ack_ = true;
|
||||
+
|
||||
+ TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceProxy::Draw", this);
|
||||
+}
|
||||
+
|
||||
+void SoftwareOutputDeviceProxy::DrawAck() {
|
||||
+ DCHECK(waiting_on_draw_ack_);
|
||||
+ DCHECK(!swap_ack_callback_.is_null());
|
||||
+
|
||||
+ TRACE_EVENT_ASYNC_END0("viz", "SoftwareOutputDeviceProxy::Draw", this);
|
||||
+
|
||||
+ waiting_on_draw_ack_ = false;
|
||||
+ std::move(swap_ack_callback_).Run(viewport_pixel_size_);
|
||||
+}
|
||||
+
|
||||
+} // namespace viz
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_proxy.h b/components/viz/service/display_embedder/software_output_device_proxy.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..48fa86caaab3c15764f105eb7ad2aecf2b89bf36
|
||||
--- /dev/null
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_proxy.h
|
||||
@@ -0,0 +1,90 @@
|
||||
+// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
|
||||
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
|
||||
+
|
||||
+#if defined(OS_WIN)
|
||||
+#include <windows.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <memory>
|
||||
+
|
||||
+#include "base/memory/shared_memory_mapping.h"
|
||||
+#include "base/threading/thread_checker.h"
|
||||
+#include "components/viz/host/host_display_client.h"
|
||||
+#include "components/viz/service/display/software_output_device.h"
|
||||
+#include "components/viz/service/viz_service_export.h"
|
||||
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
|
||||
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
|
||||
+
|
||||
+namespace viz {
|
||||
+
|
||||
+// Shared base class for SoftwareOutputDevice implementations.
|
||||
+class SoftwareOutputDeviceBase : public SoftwareOutputDevice {
|
||||
+ public:
|
||||
+ SoftwareOutputDeviceBase() = default;
|
||||
+ ~SoftwareOutputDeviceBase() override;
|
||||
+
|
||||
+ // SoftwareOutputDevice implementation.
|
||||
+ void Resize(const gfx::Size& viewport_pixel_size,
|
||||
+ float scale_factor) override;
|
||||
+ SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
|
||||
+ void EndPaint() override;
|
||||
+
|
||||
+ // Called from Resize() if |viewport_pixel_size_| has changed.
|
||||
+ virtual void ResizeDelegated() = 0;
|
||||
+
|
||||
+ // Called from BeginPaint() and should return an SkCanvas.
|
||||
+ virtual SkCanvas* BeginPaintDelegated() = 0;
|
||||
+
|
||||
+ // Called from EndPaint() if there is damage.
|
||||
+ virtual void EndPaintDelegated(const gfx::Rect& damage_rect) = 0;
|
||||
+
|
||||
+ private:
|
||||
+ bool in_paint_ = false;
|
||||
+
|
||||
+ THREAD_CHECKER(thread_checker_);
|
||||
+
|
||||
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceBase);
|
||||
+};
|
||||
+
|
||||
+// SoftwareOutputDevice implementation that draws indirectly. An implementation
|
||||
+// of mojom::LayeredWindowUpdater in the browser process handles the actual
|
||||
+// drawing. Pixel backing is in SharedMemory so no copying between processes
|
||||
+// is required.
|
||||
+class SoftwareOutputDeviceProxy : public SoftwareOutputDeviceBase {
|
||||
+ public:
|
||||
+ explicit SoftwareOutputDeviceProxy(
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater);
|
||||
+ ~SoftwareOutputDeviceProxy() override;
|
||||
+
|
||||
+ // SoftwareOutputDevice implementation.
|
||||
+ void OnSwapBuffers(SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback) override;
|
||||
+
|
||||
+ // SoftwareOutputDeviceBase implementation.
|
||||
+ void ResizeDelegated() override;
|
||||
+ SkCanvas* BeginPaintDelegated() override;
|
||||
+ void EndPaintDelegated(const gfx::Rect& rect) override;
|
||||
+
|
||||
+ private:
|
||||
+ // Runs |swap_ack_callback_| after draw has happened.
|
||||
+ void DrawAck();
|
||||
+
|
||||
+ mojom::LayeredWindowUpdaterPtr layered_window_updater_;
|
||||
+
|
||||
+ std::unique_ptr<SkCanvas> canvas_;
|
||||
+ bool waiting_on_draw_ack_ = false;
|
||||
+ SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback_;
|
||||
+
|
||||
+#if !defined(WIN32)
|
||||
+ base::WritableSharedMemoryMapping shm_mapping_;
|
||||
+#endif
|
||||
+
|
||||
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceProxy);
|
||||
+};
|
||||
+
|
||||
+} // namespace viz
|
||||
+
|
||||
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
|
||||
diff --git a/components/viz/service/display_embedder/software_output_device_win.cc b/components/viz/service/display_embedder/software_output_device_win.cc
|
||||
index bb07c338fac5251d62f52083b0cdf29f913c0426..e0ebb98d9a020dec059b9eae65d0e39c62b8dc57 100644
|
||||
--- a/components/viz/service/display_embedder/software_output_device_win.cc
|
||||
+++ b/components/viz/service/display_embedder/software_output_device_win.cc
|
||||
@@ -268,7 +268,7 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated(
|
||||
if (!canvas_)
|
||||
return;
|
||||
|
||||
- layered_window_updater_->Draw(base::BindOnce(
|
||||
+ layered_window_updater_->Draw(damage_rect, base::BindOnce(
|
||||
&SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this)));
|
||||
waiting_on_draw_ack_ = true;
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/sync_call_restrictions.h b/mojo/public/cpp/bindings/sync_call_restrictions.h
|
||||
index ac94eab98fd0f89de12db387c4718f2351ff4a92..b89d52a0c869c22147eb78f623a435920a6d34ec 100644
|
||||
--- a/mojo/public/cpp/bindings/sync_call_restrictions.h
|
||||
+++ b/mojo/public/cpp/bindings/sync_call_restrictions.h
|
||||
@@ -29,6 +29,7 @@ class HostContextFactoryPrivate;
|
||||
|
||||
namespace viz {
|
||||
class HostFrameSinkManager;
|
||||
+class GpuDisplayProvider;
|
||||
}
|
||||
|
||||
namespace mojo {
|
||||
@@ -82,6 +83,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions {
|
||||
// For preventing frame swaps of wrong size during resize on Windows.
|
||||
// (https://crbug.com/811945)
|
||||
friend class ui::HostContextFactoryPrivate;
|
||||
+ // For query of whether to use SoftwareOutputDevice or not
|
||||
+ friend class viz::GpuDisplayProvider;
|
||||
// END ALLOWED USAGE.
|
||||
|
||||
#if ENABLE_SYNC_CALL_RESTRICTIONS
|
||||
diff --git a/services/viz/privileged/mojom/compositing/display_private.mojom b/services/viz/privileged/mojom/compositing/display_private.mojom
|
||||
index be56099d186fce2ea867d83bcae642dafc5cf400..0c6c0d20edf8dad26d9737ca1120e9a66ea27e92 100644
|
||||
--- a/services/viz/privileged/mojom/compositing/display_private.mojom
|
||||
+++ b/services/viz/privileged/mojom/compositing/display_private.mojom
|
||||
@@ -76,12 +76,14 @@ interface DisplayPrivate {
|
||||
};
|
||||
|
||||
interface DisplayClient {
|
||||
+ [Sync]
|
||||
+ IsOffscreen() => (bool success);
|
||||
+
|
||||
[EnableIf=is_mac]
|
||||
OnDisplayReceivedCALayerParams(gfx.mojom.CALayerParams ca_layer_params);
|
||||
|
||||
// Creates a LayeredWindowUpdater implementation to draw into a layered
|
||||
// window.
|
||||
- [EnableIf=is_win]
|
||||
CreateLayeredWindowUpdater(pending_receiver<LayeredWindowUpdater> receiver);
|
||||
|
||||
// Notifies that a swap has occurred and provides information about the pixel
|
||||
diff --git a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
|
||||
index 6b7fbb6cf13dc8ee6ade0878a9a2c1efc5d4d3f1..e2af75168cb914a7b3b4a6c9b6a285498c3f8e72 100644
|
||||
--- a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
|
||||
+++ b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
|
||||
@@ -26,5 +26,5 @@ interface LayeredWindowUpdater {
|
||||
// Draws to the HWND by copying pixels from shared memory. Callback must be
|
||||
// called after draw operation is complete to signal shared memory can be
|
||||
// modified.
|
||||
- Draw() => ();
|
||||
+ Draw(gfx.mojom.Rect damage_rect) => ();
|
||||
};
|
||||
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
|
||||
index 5410ee7a65abc9888d9061e37daf2928a909a272..3faeea7bc605dd5ee71b1ad463255b078d9d18a6 100644
|
||||
--- a/ui/compositor/compositor.h
|
||||
+++ b/ui/compositor/compositor.h
|
||||
@@ -66,6 +66,7 @@ class GpuMemoryBufferManager;
|
||||
|
||||
namespace viz {
|
||||
class ContextProvider;
|
||||
+class HostDisplayClient;
|
||||
class HostFrameSinkManager;
|
||||
class LocalSurfaceIdAllocation;
|
||||
class RasterContextProvider;
|
||||
@@ -197,6 +198,15 @@ class COMPOSITOR_EXPORT ContextFactory {
|
||||
virtual bool SyncTokensRequiredForDisplayCompositor() = 0;
|
||||
};
|
||||
|
||||
+class COMPOSITOR_EXPORT CompositorDelegate {
|
||||
+ public:
|
||||
+ virtual std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient(
|
||||
+ ui::Compositor* compositor) = 0;
|
||||
+
|
||||
+ protected:
|
||||
+ virtual ~CompositorDelegate() {}
|
||||
+};
|
||||
+
|
||||
// Compositor object to take care of GPU painting.
|
||||
// A Browser compositor object is responsible for generating the final
|
||||
// displayable form of pixels comprising a single widget's contents. It draws an
|
||||
@@ -236,6 +246,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
|
||||
// Schedules a redraw of the layer tree associated with this compositor.
|
||||
void ScheduleDraw();
|
||||
|
||||
+ CompositorDelegate* delegate() const { return delegate_; }
|
||||
+ void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; }
|
||||
+
|
||||
// Sets the root of the layer tree drawn by this Compositor. The root layer
|
||||
// must have no parent. The compositor's root layer is reset if the root layer
|
||||
// is destroyed. NULL can be passed to reset the root layer, in which case the
|
||||
@@ -459,6 +472,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
|
||||
ui::ContextFactory* context_factory_;
|
||||
ui::ContextFactoryPrivate* context_factory_private_;
|
||||
|
||||
+ CompositorDelegate* delegate_ = nullptr;
|
||||
+
|
||||
// The root of the Layer tree drawn by this compositor.
|
||||
Layer* root_layer_ = nullptr;
|
||||
|
||||
diff --git a/ui/compositor/host/host_context_factory_private.cc b/ui/compositor/host/host_context_factory_private.cc
|
||||
index d8c278b99d09e663bba21da0e94b00ea77665349..6c2cd4e3e94df594b0aa2b91484dafea3a01fe65 100644
|
||||
--- a/ui/compositor/host/host_context_factory_private.cc
|
||||
+++ b/ui/compositor/host/host_context_factory_private.cc
|
||||
@@ -113,8 +113,13 @@ void HostContextFactoryPrivate::ConfigureCompositor(
|
||||
compositor_data.display_private.reset();
|
||||
root_params->display_private =
|
||||
compositor_data.display_private.BindNewEndpointAndPassReceiver();
|
||||
- compositor_data.display_client =
|
||||
- std::make_unique<HostDisplayClient>(compositor);
|
||||
+ if (compositor->delegate()) {
|
||||
+ compositor_data.display_client = compositor->delegate()->CreateHostDisplayClient(
|
||||
+ compositor);
|
||||
+ } else {
|
||||
+ compositor_data.display_client =
|
||||
+ std::make_unique<HostDisplayClient>(compositor);
|
||||
+ }
|
||||
root_params->display_client =
|
||||
compositor_data.display_client->GetBoundRemote(resize_task_runner_);
|
||||
|
||||
diff --git a/ui/gfx/ca_layer_params.h b/ui/gfx/ca_layer_params.h
|
||||
index 4014e64a75da88cf66c02e8adb71171c2666cab7..25e57784e1a1ffc546b003daa4cd0059c468432f 100644
|
||||
--- a/ui/gfx/ca_layer_params.h
|
||||
+++ b/ui/gfx/ca_layer_params.h
|
||||
@@ -6,6 +6,7 @@
|
||||
#define UI_GFX_CA_LAYER_PARAMS_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
+#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/gfx/gfx_export.h"
|
||||
|
||||
@@ -41,6 +42,8 @@ struct GFX_EXPORT CALayerParams {
|
||||
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port;
|
||||
#endif
|
||||
|
||||
+ gfx::Rect damage;
|
||||
+
|
||||
// The geometry of the frame.
|
||||
gfx::Size pixel_size;
|
||||
float scale_factor = 1.f;
|
||||
diff --git a/ui/gfx/mojom/ca_layer_params.mojom b/ui/gfx/mojom/ca_layer_params.mojom
|
||||
index a73b2e678ffe0a682d0aa5409724fb441768bec5..6c36626d204c77ef51278b9e8f6fc6ee24a7a9ab 100644
|
||||
--- a/ui/gfx/mojom/ca_layer_params.mojom
|
||||
+++ b/ui/gfx/mojom/ca_layer_params.mojom
|
||||
@@ -18,5 +18,6 @@ struct CALayerParams {
|
||||
bool is_empty;
|
||||
CALayerContent content;
|
||||
gfx.mojom.Size pixel_size;
|
||||
+ gfx.mojom.Rect damage;
|
||||
float scale_factor;
|
||||
};
|
||||
diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
|
||||
index 843d5c24ec33de07c12d4417eb111f91dbcd42fe..0ea594950fcd2686f1b07248dbc8ceb257d89dca 100644
|
||||
--- a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
|
||||
+++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
|
||||
@@ -52,6 +52,9 @@ bool StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams>::Read(
|
||||
if (!data.ReadPixelSize(&out->pixel_size))
|
||||
return false;
|
||||
|
||||
+ if (!data.ReadDamage(&out->damage))
|
||||
+ return false;
|
||||
+
|
||||
out->scale_factor = data.scale_factor();
|
||||
return true;
|
||||
}
|
||||
diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.h b/ui/gfx/mojom/ca_layer_params_mojom_traits.h
|
||||
index 4cac766eae3161baedac4202f694129cd90c80de..0821495ad22944d8856bb750cac8912a2f8328c3 100644
|
||||
--- a/ui/gfx/mojom/ca_layer_params_mojom_traits.h
|
||||
+++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.h
|
||||
@@ -20,6 +20,10 @@ struct StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams> {
|
||||
return ca_layer_params.pixel_size;
|
||||
}
|
||||
|
||||
+ static gfx::Rect damage(const gfx::CALayerParams& ca_layer_params) {
|
||||
+ return ca_layer_params.damage;
|
||||
+ }
|
||||
+
|
||||
static float scale_factor(const gfx::CALayerParams& ca_layer_params) {
|
||||
return ca_layer_params.scale_factor;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Mon, 1 Jun 2020 20:36:16 +0000
|
||||
Subject: fix: default to NTLM v2 in network service for POSIX platforms
|
||||
|
||||
NTLM always defaults to NTLM v2 at the //net layer for quite
|
||||
sometime now https://crbug.com/22532.
|
||||
|
||||
Change-Id: I4ea2dedc10c63a7c4e00101c0acc6d8a713c5054
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2222116
|
||||
Auto-Submit: Deepak Mohan <hop2deep@gmail.com>
|
||||
Reviewed-by: Tom Sepez <tsepez@chromium.org>
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#773809}
|
||||
|
||||
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom
|
||||
index 1cafd4440108ccb8fe7f4f7c3d43a661dd626f15..8fdb75f76f5d9f207265c316e03818f36bcafbaa 100644
|
||||
--- a/services/network/public/mojom/network_service.mojom
|
||||
+++ b/services/network/public/mojom/network_service.mojom
|
||||
@@ -113,7 +113,7 @@ struct HttpAuthDynamicParams {
|
||||
bool enable_negotiate_port = true;
|
||||
|
||||
// Whether NTLM V2 is enabled on POSIX platforms. No effect elsewhere.
|
||||
- bool ntlm_v2_enabled = false;
|
||||
+ bool ntlm_v2_enabled = true;
|
||||
|
||||
// The AccountManager AccountManagerget.AccountsByTypeAndFeatures on Android
|
||||
// when using Negotiate authentication.
|
||||
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: fix: handle non client pointer events from pen on Windows 10
|
||||
|
||||
Refs: https://github.com/electron/electron/issues/21440
|
||||
Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2237535
|
||||
|
||||
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
|
||||
index 1fd8da727592fec91056021ea9616996a8f54b92..8c069f0ca4d3a0702a254f766c93d4c6830a911d 100644
|
||||
--- a/ui/views/win/hwnd_message_handler.cc
|
||||
+++ b/ui/views/win/hwnd_message_handler.cc
|
||||
@@ -2005,6 +2005,15 @@ LRESULT HWNDMessageHandler::OnPointerEvent(UINT message,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ // Pen may also send non client pointer messages, treat them as normal
|
||||
+ // touch events so they can be properly handled.
|
||||
+ if (pointer_type == PT_PEN &&
|
||||
+ (message == WM_NCPOINTERDOWN ||
|
||||
+ message == WM_NCPOINTERUP ||
|
||||
+ message == WM_NCPOINTERUPDATE)) {
|
||||
+ pointer_type = PT_TOUCH;
|
||||
+ }
|
||||
+
|
||||
switch (pointer_type) {
|
||||
case PT_PEN:
|
||||
return HandlePointerEventTypePen(message, w_param, l_param);
|
||||
148
patches/chromium/fix_hunspell_crash.patch
Normal file
148
patches/chromium/fix_hunspell_crash.patch
Normal file
@@ -0,0 +1,148 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Thu, 4 Oct 2018 14:57:02 -0700
|
||||
Subject: Make sure hunspell file is not destroyed in UI thread
|
||||
|
||||
Submitted to Chromium at:
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/2206199/1
|
||||
|
||||
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
|
||||
index 67ec4e285d9bf6b9de300845b2c53bda435e5784..74d403aeb1739d0424874a702e64cfd8c3fe4fcb 100644
|
||||
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
|
||||
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
|
||||
@@ -91,21 +91,28 @@ bool SaveDictionaryData(std::unique_ptr<std::string> data,
|
||||
|
||||
} // namespace
|
||||
|
||||
-SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile() {
|
||||
-}
|
||||
+SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile(
|
||||
+ base::TaskRunner* task_runner) : task_runner_(task_runner) {}
|
||||
|
||||
SpellcheckHunspellDictionary::DictionaryFile::~DictionaryFile() {
|
||||
+ if (file.IsValid()) {
|
||||
+ task_runner_->PostTask(FROM_HERE,
|
||||
+ base::BindOnce(&CloseDictionary, std::move(file)));
|
||||
+ }
|
||||
}
|
||||
|
||||
SpellcheckHunspellDictionary::DictionaryFile::DictionaryFile(
|
||||
DictionaryFile&& other)
|
||||
- : path(other.path), file(std::move(other.file)) {}
|
||||
+ : path(other.path),
|
||||
+ file(std::move(other.file)),
|
||||
+ task_runner_(std::move(other.task_runner_)) {}
|
||||
|
||||
SpellcheckHunspellDictionary::DictionaryFile&
|
||||
SpellcheckHunspellDictionary::DictionaryFile::operator=(
|
||||
DictionaryFile&& other) {
|
||||
path = other.path;
|
||||
file = std::move(other.file);
|
||||
+ task_runner_ = std::move(other.task_runner_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -121,16 +128,10 @@ SpellcheckHunspellDictionary::SpellcheckHunspellDictionary(
|
||||
#if !defined(OS_ANDROID)
|
||||
spellcheck_service_(spellcheck_service),
|
||||
#endif
|
||||
- download_status_(DOWNLOAD_NONE) {
|
||||
-}
|
||||
+ download_status_(DOWNLOAD_NONE),
|
||||
+ dictionary_file_(task_runner_.get()) {}
|
||||
|
||||
SpellcheckHunspellDictionary::~SpellcheckHunspellDictionary() {
|
||||
- if (dictionary_file_.file.IsValid()) {
|
||||
- task_runner_->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&CloseDictionary, std::move(dictionary_file_.file)));
|
||||
- }
|
||||
-
|
||||
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
|
||||
// Disable the language from platform spellchecker.
|
||||
if (spellcheck::UseBrowserSpellChecker())
|
||||
@@ -324,7 +325,8 @@ void SpellcheckHunspellDictionary::DownloadDictionary(GURL url) {
|
||||
#if !defined(OS_ANDROID)
|
||||
// static
|
||||
SpellcheckHunspellDictionary::DictionaryFile
|
||||
-SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) {
|
||||
+SpellcheckHunspellDictionary::OpenDictionaryFile(base::TaskRunner* task_runner,
|
||||
+ const base::FilePath& path) {
|
||||
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
||||
base::BlockingType::MAY_BLOCK);
|
||||
|
||||
@@ -335,7 +337,7 @@ SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) {
|
||||
// For systemwide installations on Windows, the default directory may not
|
||||
// have permissions for download. In that case, the alternate directory for
|
||||
// download is chrome::DIR_USER_DATA.
|
||||
- DictionaryFile dictionary;
|
||||
+ DictionaryFile dictionary(task_runner);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Check if the dictionary exists in the fallback location. If so, use it
|
||||
@@ -377,7 +379,7 @@ SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) {
|
||||
// static
|
||||
SpellcheckHunspellDictionary::DictionaryFile
|
||||
SpellcheckHunspellDictionary::InitializeDictionaryLocation(
|
||||
- const std::string& language) {
|
||||
+ base::TaskRunner* task_runner, const std::string& language) {
|
||||
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
||||
base::BlockingType::MAY_BLOCK);
|
||||
|
||||
@@ -392,7 +394,7 @@ SpellcheckHunspellDictionary::InitializeDictionaryLocation(
|
||||
base::FilePath dict_path =
|
||||
spellcheck::GetVersionedFileName(language, dict_dir);
|
||||
|
||||
- return OpenDictionaryFile(dict_path);
|
||||
+ return OpenDictionaryFile(task_runner, dict_path);
|
||||
}
|
||||
|
||||
void SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete(
|
||||
@@ -480,7 +482,8 @@ void SpellcheckHunspellDictionary::PlatformSupportsLanguageComplete(
|
||||
#if !defined(OS_ANDROID) && BUILDFLAG(USE_RENDERER_SPELLCHECKER)
|
||||
base::PostTaskAndReplyWithResult(
|
||||
task_runner_.get(), FROM_HERE,
|
||||
- base::BindOnce(&InitializeDictionaryLocation, language_),
|
||||
+ base::BindOnce(&InitializeDictionaryLocation,
|
||||
+ base::RetainedRef(task_runner_.get()), language_),
|
||||
base::BindOnce(
|
||||
&SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
|
||||
index 633ec3a96b39824fc9bcf374e59eb80148a2ae27..bfb90905ee045d8f08dbd0b348204b41fd185f41 100644
|
||||
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
|
||||
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
|
||||
@@ -99,7 +99,7 @@ class SpellcheckHunspellDictionary
|
||||
// blocking sequence.
|
||||
struct DictionaryFile {
|
||||
public:
|
||||
- DictionaryFile();
|
||||
+ explicit DictionaryFile(base::TaskRunner* task_runner);
|
||||
~DictionaryFile();
|
||||
|
||||
DictionaryFile(DictionaryFile&& other);
|
||||
@@ -112,6 +112,9 @@ class SpellcheckHunspellDictionary
|
||||
base::File file;
|
||||
|
||||
private:
|
||||
+ // Task runner where the file is created.
|
||||
+ scoped_refptr<base::TaskRunner> task_runner_;
|
||||
+
|
||||
DISALLOW_COPY_AND_ASSIGN(DictionaryFile);
|
||||
};
|
||||
|
||||
@@ -126,11 +129,12 @@ class SpellcheckHunspellDictionary
|
||||
#if !defined(OS_ANDROID)
|
||||
// Figures out the location for the dictionary, verifies its contents, and
|
||||
// opens it.
|
||||
- static DictionaryFile OpenDictionaryFile(const base::FilePath& path);
|
||||
+ static DictionaryFile OpenDictionaryFile(base::TaskRunner* task_runner,
|
||||
+ const base::FilePath& path);
|
||||
|
||||
// Gets the default location for the dictionary file.
|
||||
static DictionaryFile InitializeDictionaryLocation(
|
||||
- const std::string& language);
|
||||
+ base::TaskRunner* task_runner, const std::string& language);
|
||||
|
||||
// The reply point for PostTaskAndReplyWithResult, called after the dictionary
|
||||
// file has been initialized.
|
||||
@@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Wed, 20 May 2020 13:48:51 -0700
|
||||
Subject: fix: swap global proxies before initializing the windows proxies
|
||||
|
||||
Electron's Context Isolation implementation has a side-effect of initializing
|
||||
the isolated worlds WindowProxy during the initialization of the main world
|
||||
WindowProxy as a result of creating the isolated world inside the DidCreateScriptContext
|
||||
hook. This results in an assertion failing in Chromium during a frame
|
||||
swap where it expects to be able to set a new global_proxy in the WindowProxy
|
||||
of the isolated world BEFORE it is initialized.
|
||||
|
||||
To meet this assumption this patch splits SetGlobalProxy into two calls,
|
||||
SetGlobalProxyWithoutInitializing and InitializeIfNeeded which has the same
|
||||
resultant effect but means that all of the global_proxy objects are set
|
||||
BEFORE any WindowProxy's are initialized.
|
||||
|
||||
This could probably be upstreamed as it doesn't affect the way Chromium works
|
||||
but also it has no benefit for them at this time.
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy.cc
|
||||
index 86076cb3f39cdca7dbf31c668b8aaafb44e42d39..e7108f9548e0f01863339b12f6bd5e51b951b3fc 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/window_proxy.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/window_proxy.cc
|
||||
@@ -109,10 +109,7 @@ v8::Local<v8::Object> WindowProxy::ReleaseGlobalProxy() {
|
||||
}
|
||||
|
||||
void WindowProxy::SetGlobalProxy(v8::Local<v8::Object> global_proxy) {
|
||||
- DCHECK_EQ(lifecycle_, Lifecycle::kContextIsUninitialized);
|
||||
-
|
||||
- CHECK(global_proxy_.IsEmpty());
|
||||
- global_proxy_.Set(isolate_, global_proxy);
|
||||
+ SetGlobalProxyWithoutInitializing(global_proxy);
|
||||
|
||||
// Initialize the window proxy now, to re-establish the connection between
|
||||
// the global object and the v8::Context. This is really only needed for a
|
||||
@@ -123,6 +120,13 @@ void WindowProxy::SetGlobalProxy(v8::Local<v8::Object> global_proxy) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
+void WindowProxy::SetGlobalProxyWithoutInitializing(v8::Local<v8::Object> global_proxy) {
|
||||
+ DCHECK_EQ(lifecycle_, Lifecycle::kContextIsUninitialized);
|
||||
+
|
||||
+ CHECK(global_proxy_.IsEmpty());
|
||||
+ global_proxy_.Set(isolate_, global_proxy);
|
||||
+}
|
||||
+
|
||||
// Create a new environment and setup the global object.
|
||||
//
|
||||
// The global object corresponds to a DOMWindow instance. However, to
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy.h b/third_party/blink/renderer/bindings/core/v8/window_proxy.h
|
||||
index 777bb67e5f7a1eb42438f91023a53c82fd041af2..3735f9b49899b4d36f005a3c2b741e3791ba0709 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/window_proxy.h
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/window_proxy.h
|
||||
@@ -157,6 +157,7 @@ class WindowProxy : public GarbageCollected<WindowProxy> {
|
||||
CORE_EXPORT v8::Local<v8::Object> GlobalProxyIfNotDetached();
|
||||
v8::Local<v8::Object> ReleaseGlobalProxy();
|
||||
void SetGlobalProxy(v8::Local<v8::Object>);
|
||||
+ void SetGlobalProxyWithoutInitializing(v8::Local<v8::Object>);
|
||||
|
||||
// TODO(dcheng): Temporarily exposed to avoid include cycles. Remove the need
|
||||
// for this and remove this getter.
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
|
||||
index b8054889808b39f216bd85b019e2b05660c828de..5306426d84209c428a59fec6b468f57fbddd1fed 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
|
||||
@@ -55,8 +55,11 @@ void WindowProxyManager::ReleaseGlobalProxies(
|
||||
|
||||
void WindowProxyManager::SetGlobalProxies(
|
||||
const GlobalProxyVector& global_proxies) {
|
||||
+ for (const auto& entry : global_proxies) {
|
||||
+ WindowProxyMaybeUninitialized(*entry.first)->SetGlobalProxyWithoutInitializing(entry.second);
|
||||
+ }
|
||||
for (const auto& entry : global_proxies)
|
||||
- WindowProxyMaybeUninitialized(*entry.first)->SetGlobalProxy(entry.second);
|
||||
+ WindowProxyMaybeUninitialized(*entry.first)->InitializeIfNeeded();
|
||||
}
|
||||
|
||||
WindowProxyManager::WindowProxyManager(Frame& frame, FrameType frame_type)
|
||||
@@ -12,7 +12,7 @@ diff --git a/chrome/browser/extensions/global_shortcut_listener_mac.mm b/chrome/
|
||||
index befe726af9c10b1563a7fc0bb77cc55f65943d5c..bac51f33f35f96fe4ecc764cf5ca887176642f74 100644
|
||||
--- a/chrome/browser/extensions/global_shortcut_listener_mac.mm
|
||||
+++ b/chrome/browser/extensions/global_shortcut_listener_mac.mm
|
||||
@@ -39,7 +39,7 @@
|
||||
@@ -39,7 +39,7 @@ GlobalShortcutListenerMac::GlobalShortcutListenerMac()
|
||||
// global MediaKeysListener to receive media keys.
|
||||
if (!content::MediaKeysListenerManager::IsMediaKeysListenerManagerEnabled()) {
|
||||
media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
|
||||
@@ -9,7 +9,7 @@ diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm
|
||||
index 2a83d4d8158422c1056725679309c6ced1e531bd..f52934712f8de78193127c426d02982b36e9d422 100644
|
||||
--- a/base/mac/foundation_util.mm
|
||||
+++ b/base/mac/foundation_util.mm
|
||||
@@ -27,7 +27,6 @@
|
||||
@@ -27,7 +27,6 @@ CFTypeID SecKeyGetTypeID();
|
||||
#if !defined(OS_IOS)
|
||||
CFTypeID SecACLGetTypeID();
|
||||
CFTypeID SecTrustedApplicationGetTypeID();
|
||||
@@ -17,7 +17,7 @@ index 2a83d4d8158422c1056725679309c6ced1e531bd..f52934712f8de78193127c426d02982b
|
||||
#endif
|
||||
} // extern "C"
|
||||
|
||||
@@ -316,8 +315,7 @@ void SetBaseBundleID(const char* new_base_bundle_id) {
|
||||
@@ -316,8 +315,7 @@ NSFont* CFToNSCast(CTFontRef cf_val) {
|
||||
const_cast<NSFont*>(reinterpret_cast<const NSFont*>(cf_val));
|
||||
DCHECK(!cf_val ||
|
||||
CTFontGetTypeID() == CFGetTypeID(cf_val) ||
|
||||
@@ -27,7 +27,7 @@ index 2a83d4d8158422c1056725679309c6ced1e531bd..f52934712f8de78193127c426d02982b
|
||||
return ns_val;
|
||||
}
|
||||
|
||||
@@ -385,9 +383,6 @@ CTFontRef NSToCFCast(NSFont* ns_val) {
|
||||
@@ -385,9 +383,6 @@ CFCast<CTFontRef>(const CFTypeRef& cf_val) {
|
||||
return (CTFontRef)(cf_val);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ index 94afefcee81b87c05bf9b1199d90d3d4b5ea84a6..2ec7f04c71824b47de1ddbf1f0e8625d
|
||||
extern "C" {
|
||||
|
||||
// Kill ring calls. Would be better to use NSKillRing.h, but that's not
|
||||
@@ -39,38 +40,53 @@
|
||||
@@ -39,38 +40,53 @@ NSString* _NSYankFromKillRing();
|
||||
void _NSNewKillRingSequence();
|
||||
void _NSSetKillRingToYankedState();
|
||||
}
|
||||
@@ -92,7 +92,7 @@ index 8f4ae94bc1d8188d041654c50511f3346eee79de..fa06f47abbff3dcda937bf0b794f616e
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -95,10 +97,12 @@ void _NSDrawCarbonThemeListBox(NSRect frame,
|
||||
@@ -95,10 +97,12 @@ bool ThemePainterMac::PaintTextField(const Node* node,
|
||||
// behavior change while remaining a fragile solution.
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=658085#c3
|
||||
if (!use_ns_text_field_cell) {
|
||||
@@ -105,7 +105,7 @@ index 8f4ae94bc1d8188d041654c50511f3346eee79de..fa06f47abbff3dcda937bf0b794f616e
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -186,10 +190,12 @@ void _NSDrawCarbonThemeListBox(NSRect frame,
|
||||
@@ -186,10 +190,12 @@ bool ThemePainterMac::PaintTextArea(const Node* node,
|
||||
const IntRect& r) {
|
||||
ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
|
||||
LocalCurrentGraphicsContext local_context(paint_info.context, r);
|
||||
|
||||
@@ -18,7 +18,7 @@ index 1ffb647e85e00ff60d84234e47f5d7d385f65245..439cc6df5e0cc1ec3732d6f2a2e00d54
|
||||
@interface NSWindow (PrivateBrowserNativeWidgetAPI)
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
|
||||
@end
|
||||
@@ -69,10 +70,13 @@ - (NSRect)_draggableFrame NS_DEPRECATED_MAC(10_10, 10_11) {
|
||||
@@ -69,10 +70,13 @@
|
||||
|
||||
@end
|
||||
|
||||
@@ -32,7 +32,7 @@ index 1ffb647e85e00ff60d84234e47f5d7d385f65245..439cc6df5e0cc1ec3732d6f2a2e00d54
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle {
|
||||
// - NSThemeFrame and its subclasses will be nil if it's missing at runtime.
|
||||
if ([BrowserWindowFrame class])
|
||||
@@ -87,6 +91,8 @@ - (BOOL)_usesCustomDrawing {
|
||||
@@ -87,6 +91,8 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ index 8416c7c6e052dafb2aad61c0bd3224c36e945d23..cd356beda023ab2409b16d58ca38c70b
|
||||
@interface NSWindow (PrivateAPI)
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
|
||||
@end
|
||||
@@ -18,8 +20,12 @@ - (CGFloat)_titlebarHeight {
|
||||
@@ -18,8 +20,12 @@
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -67,7 +67,7 @@ index 8416c7c6e052dafb2aad61c0bd3224c36e945d23..cd356beda023ab2409b16d58ca38c70b
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle {
|
||||
if ([NativeWidgetMacFramelessNSWindowFrame class]) {
|
||||
return [NativeWidgetMacFramelessNSWindowFrame class];
|
||||
@@ -27,4 +33,6 @@ + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle {
|
||||
@@ -27,4 +33,6 @@
|
||||
return [super frameViewClassForStyleMask:windowStyle];
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ index 576ef14c1d67ce7f4a1b2095124d1d302440635c..dd068fc339b80c3e99d89e6d7cc73db8
|
||||
- (BOOL)hasKeyAppearance;
|
||||
- (long long)_resizeDirectionForMouseLocation:(CGPoint)location;
|
||||
- (BOOL)_isConsideredOpenForPersistentState;
|
||||
@@ -57,6 +59,8 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event {
|
||||
@@ -57,6 +59,8 @@
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -117,7 +117,7 @@ index 576ef14c1d67ce7f4a1b2095124d1d302440635c..dd068fc339b80c3e99d89e6d7cc73db8
|
||||
@implementation NativeWidgetMacNSWindowTitledFrame
|
||||
- (void)mouseDown:(NSEvent*)event {
|
||||
if (self.window.isMovable)
|
||||
@@ -78,6 +82,8 @@ - (BOOL)usesCustomDrawing {
|
||||
@@ -78,6 +82,8 @@
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -126,7 +126,7 @@ index 576ef14c1d67ce7f4a1b2095124d1d302440635c..dd068fc339b80c3e99d89e6d7cc73db8
|
||||
@implementation NativeWidgetMacNSWindow {
|
||||
@private
|
||||
base::scoped_nsobject<CommandDispatcher> commandDispatcher_;
|
||||
@@ -159,6 +165,8 @@ - (BOOL)hasViewsMenuActive {
|
||||
@@ -159,6 +165,8 @@
|
||||
|
||||
// NSWindow overrides.
|
||||
|
||||
@@ -135,7 +135,7 @@ index 576ef14c1d67ce7f4a1b2095124d1d302440635c..dd068fc339b80c3e99d89e6d7cc73db8
|
||||
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
if (windowStyle & NSWindowStyleMaskTitled) {
|
||||
if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
|
||||
@@ -170,6 +178,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
@@ -170,6 +178,8 @@
|
||||
return [super frameViewClassForStyleMask:windowStyle];
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user