mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -605,8 +605,10 @@ step-mksnapshot-build: &step-mksnapshot-build
|
||||
if [ "`uname`" != "Darwin" ]; then
|
||||
if [ "$TARGET_ARCH" == "arm" ]; then
|
||||
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/mksnapshot
|
||||
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/v8_context_snapshot_generator
|
||||
elif [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/mksnapshot
|
||||
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/v8_context_snapshot_generator
|
||||
else
|
||||
electron/script/strip-binaries.py --file $PWD/out/Default/mksnapshot
|
||||
electron/script/strip-binaries.py --file $PWD/out/Default/v8_context_snapshot_generator
|
||||
|
||||
13
BUILD.gn
13
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",
|
||||
]
|
||||
@@ -1355,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)",
|
||||
]
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
8.2.4
|
||||
8.3.3
|
||||
@@ -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()
|
||||
@@ -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",
|
||||
|
||||
@@ -564,11 +564,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 +675,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 +683,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 +1090,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 +1168,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 +1179,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
|
||||
@@ -1104,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_
|
||||
|
||||
@@ -1120,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_
|
||||
|
||||
@@ -1162,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_
|
||||
|
||||
@@ -1186,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
|
||||
@@ -1607,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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -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`,
|
||||
@@ -366,6 +366,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 +883,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 +979,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 +1062,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 +1079,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 +1092,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 +1698,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.
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -442,14 +442,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');
|
||||
|
||||
@@ -232,7 +232,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 +267,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 +364,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|.
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -11,12 +11,9 @@ 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 = {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -126,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 +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.4",
|
||||
"version": "8.3.3",
|
||||
"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);
|
||||
}
|
||||
|
||||
@@ -93,3 +93,21 @@ 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
|
||||
|
||||
@@ -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*
|
||||
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 @@ CGEventRef MediaKeysListenerImpl::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
|
||||
|
||||
@@ -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)
|
||||
@@ -0,0 +1,144 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Wed, 29 Apr 2020 13:36:00 -0700
|
||||
Subject: Never let a non-zero-size pixel snap to zero size
|
||||
|
||||
The logic for LayoutUnit::SnapSizeToPixel maps the size to
|
||||
the closest pixel align edge given a location. When a size of
|
||||
width less than 1 happens to straddle a pixel aligned edge this
|
||||
forces the size to zero.
|
||||
|
||||
Force the size to always be non-zero if the input size is non-zero,
|
||||
and change PhysicalRect to use the LayoutRect snapping to get
|
||||
correct cull rects.
|
||||
|
||||
Bug: 793785
|
||||
Change-Id: Ia4c30d10c389fb4677006441aac9ee380a7c2f41
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1948057
|
||||
Commit-Queue: Stephen Chenney <schenney@chromium.org>
|
||||
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#726516}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/geometry/layout_unit.h b/third_party/blink/renderer/platform/geometry/layout_unit.h
|
||||
index eaaff017795237c83b9eb06e8cb70f8598ec5664..8ffe3e11501c005edb233130b231c33e6e79000b 100644
|
||||
--- a/third_party/blink/renderer/platform/geometry/layout_unit.h
|
||||
+++ b/third_party/blink/renderer/platform/geometry/layout_unit.h
|
||||
@@ -723,7 +723,12 @@ inline float& operator/=(float& a, const LayoutUnit& b) {
|
||||
|
||||
inline int SnapSizeToPixel(LayoutUnit size, LayoutUnit location) {
|
||||
LayoutUnit fraction = location.Fraction();
|
||||
- return (fraction + size).Round() - fraction.Round();
|
||||
+ int result = (fraction + size).Round() - fraction.Round();
|
||||
+ if (UNLIKELY(result == 0 &&
|
||||
+ std::abs(size.ToFloat()) > LayoutUnit::Epsilon() * 4)) {
|
||||
+ return size > 0 ? 1 : -1;
|
||||
+ }
|
||||
+ return result;
|
||||
}
|
||||
|
||||
inline int RoundToInt(LayoutUnit value) {
|
||||
diff --git a/third_party/blink/renderer/platform/geometry/layout_unit_test.cc b/third_party/blink/renderer/platform/geometry/layout_unit_test.cc
|
||||
index db1fa1f610f195eb7933ab044c26c3b2bae84120..05d4a2f762ede01f712470363ed118f7b37925a4 100644
|
||||
--- a/third_party/blink/renderer/platform/geometry/layout_unit_test.cc
|
||||
+++ b/third_party/blink/renderer/platform/geometry/layout_unit_test.cc
|
||||
@@ -155,8 +155,20 @@ TEST(LayoutUnitTest, LayoutUnitSnapSizeToPixel) {
|
||||
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.99)));
|
||||
EXPECT_EQ(2, SnapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1)));
|
||||
|
||||
- EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(0.5), LayoutUnit(1.5)));
|
||||
- EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(0.99), LayoutUnit(1.5)));
|
||||
+ // 0.046875 is 3/64, lower than 4 * LayoutUnit::Epsilon()
|
||||
+ EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(0.046875), LayoutUnit(0)));
|
||||
+ // 0.078125 is 5/64, higher than 4 * LayoutUnit::Epsilon()
|
||||
+ EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(0.078125), LayoutUnit(0)));
|
||||
+
|
||||
+ // Negative versions
|
||||
+ EXPECT_EQ(0, SnapSizeToPixel(LayoutUnit(-0.046875), LayoutUnit(0)));
|
||||
+ EXPECT_EQ(-1, SnapSizeToPixel(LayoutUnit(-0.078125), LayoutUnit(0)));
|
||||
+
|
||||
+ // The next 2 would snap to zero but for the requirement that we not snap
|
||||
+ // sizes greater than 4 * LayoutUnit::Epsilon() to 0.
|
||||
+ EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(0.5), LayoutUnit(1.5)));
|
||||
+ EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(0.99), LayoutUnit(1.5)));
|
||||
+
|
||||
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.0), LayoutUnit(1.5)));
|
||||
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.49), LayoutUnit(1.5)));
|
||||
EXPECT_EQ(1, SnapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1.5)));
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/thin-element-render-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/thin-element-render-ref.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0d5851d5544f9692d0761dc92c23b6b2b546b4d3
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/thin-element-render-ref.html
|
||||
@@ -0,0 +1,31 @@
|
||||
+<!DOCTYPE html>
|
||||
+<title>Reference: Thin elements should paint even at small size</title>
|
||||
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
|
||||
+<html>
|
||||
+ <head>
|
||||
+ <style>
|
||||
+ .disappearing-border {
|
||||
+ height:1px;
|
||||
+ width:100%;
|
||||
+ border-top:1px solid black;
|
||||
+ }
|
||||
+
|
||||
+ .disappearing-box {
|
||||
+ height:1px;
|
||||
+ width:100%;
|
||||
+ background-color: black;
|
||||
+ }
|
||||
+
|
||||
+ body {
|
||||
+ margin: 0px;
|
||||
+ padding: 0px;
|
||||
+ box-sizing: border-box;
|
||||
+ }
|
||||
+ </style>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <div class="disappearing-border"></div>
|
||||
+ <div style="height:6.5px;"></div>
|
||||
+ <div class="disappearing-box"></div>
|
||||
+</body>
|
||||
+</html>
|
||||
\ No newline at end of file
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/thin-element-render.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/thin-element-render.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fa587360a6d2625c8f02cd7f0eba54b3bb09a1f1
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/thin-element-render.html
|
||||
@@ -0,0 +1,33 @@
|
||||
+<!DOCTYPE html>
|
||||
+<title>Thin elements should still paint even at small size.</title>
|
||||
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
|
||||
+<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#width-height-keywords">
|
||||
+<link rel="match" href="thin-element-render-ref.html">
|
||||
+<html>
|
||||
+ <head>
|
||||
+ <style>
|
||||
+ .disappearing-border {
|
||||
+ height:0.25px;
|
||||
+ width:100%;
|
||||
+ border-top: 0.25px solid black;
|
||||
+ }
|
||||
+
|
||||
+ .disappearing-box {
|
||||
+ height:0.25px;
|
||||
+ width:100%;
|
||||
+ background-color: black;
|
||||
+ }
|
||||
+
|
||||
+ body {
|
||||
+ margin: 0px;
|
||||
+ padding: 0px;
|
||||
+ box-sizing: border-box;
|
||||
+ }
|
||||
+ </style>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <div class="disappearing-border"></div>
|
||||
+ <div style="height:8px;"></div>
|
||||
+ <div class="disappearing-box"></div>
|
||||
+</body>
|
||||
+</html>
|
||||
\ No newline at end of file
|
||||
@@ -0,0 +1,359 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Harald Alvestrand <hta@chromium.org>
|
||||
Date: Wed, 22 Apr 2020 08:05:36 +0000
|
||||
Subject: Reland "Onstate handler is allowed to close a PeerConnection."
|
||||
|
||||
This reverts commit 94b16e2f5a5e99aec0c62754c31de2d297becf2d.
|
||||
|
||||
Reason for revert: Also landing fix from crbug.com/1071329
|
||||
Original change's description:
|
||||
> Revert "Onstate handler is allowed to close a PeerConnection."
|
||||
>
|
||||
> This reverts commit 9a2bc8e9cf63e70d47a443c673ae00d2b03ffc4f.
|
||||
>
|
||||
> Reason for revert: https://crbug.com/1073213
|
||||
>
|
||||
> Original change's description:
|
||||
> > Onstate handler is allowed to close a PeerConnection.
|
||||
> >
|
||||
> > (cherry picked from commit 919dd0c1244afdb269d023dd178bec8caec372ab)
|
||||
> >
|
||||
> > Bug: chromium:1068084
|
||||
> > Change-Id: Icd3f70b6784ac22ef4e3bc1c99233f51145a917f
|
||||
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2146542
|
||||
> > Commit-Queue: Harald Alvestrand <hta@chromium.org>
|
||||
> > Reviewed-by: Guido Urdaneta <guidou@chromium.org>
|
||||
> > Cr-Original-Commit-Position: refs/heads/master@{#759242}
|
||||
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2156993
|
||||
> > Reviewed-by: Harald Alvestrand <hta@chromium.org>
|
||||
> > Cr-Commit-Position: refs/branch-heads/4103@{#250}
|
||||
> > Cr-Branched-From: 8ad47e8d21f6866e4a37f47d83a860d41debf514-refs/heads/master@{#756066}
|
||||
>
|
||||
> TBR=hta@chromium.org
|
||||
>
|
||||
> Change-Id: If7400e9b7d02898bfadb31d31da2bf1a5df39801
|
||||
> No-Presubmit: true
|
||||
> No-Tree-Checks: true
|
||||
> No-Try: true
|
||||
> Bug: chromium:1068084, chromium:1073213
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2159619
|
||||
> Reviewed-by: Carlos Knippschild <carlosk@chromium.org>
|
||||
> Commit-Queue: Carlos Knippschild <carlosk@chromium.org>
|
||||
> Cr-Commit-Position: refs/branch-heads/4103@{#262}
|
||||
> Cr-Branched-From: 8ad47e8d21f6866e4a37f47d83a860d41debf514-refs/heads/master@{#756066}
|
||||
|
||||
TBR=hta@chromium.org,carlosk@chromium.org
|
||||
|
||||
Change-Id: I7b6f58a11a83accc3cb14dcf3df637ea295a8d6e
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
No-Try: true
|
||||
Bug: chromium:1068084, chromium:1073213
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2159715
|
||||
Reviewed-by: Harald Alvestrand <hta@chromium.org>
|
||||
Commit-Queue: Harald Alvestrand <hta@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4103@{#271}
|
||||
Cr-Branched-From: 8ad47e8d21f6866e4a37f47d83a860d41debf514-refs/heads/master@{#756066}
|
||||
|
||||
diff --git a/third_party/blink/public/platform/web_rtc_peer_connection_handler.h b/third_party/blink/public/platform/web_rtc_peer_connection_handler.h
|
||||
index e1dd0f950d8a7391207e249242cd7b0e8d09a31a..1ad77dc31815a85e79d2e1cc5ce91cebd36a182e 100644
|
||||
--- a/third_party/blink/public/platform/web_rtc_peer_connection_handler.h
|
||||
+++ b/third_party/blink/public/platform/web_rtc_peer_connection_handler.h
|
||||
@@ -81,6 +81,15 @@ class WebRTCPeerConnectionHandler {
|
||||
virtual bool Initialize(
|
||||
const webrtc::PeerConnectionInterface::RTCConfiguration&,
|
||||
const WebMediaConstraints&) = 0;
|
||||
+
|
||||
+ virtual void Stop() = 0;
|
||||
+ // This function should be called when the object is taken out of service.
|
||||
+ // There might be functions that need to return through the object, so it
|
||||
+ // cannot be deleted yet, but no new operations should be allowed.
|
||||
+ // All references to the object except the owning reference are deleted
|
||||
+ // by this function.
|
||||
+ virtual void StopAndUnregister() = 0;
|
||||
+
|
||||
virtual void AssociateWithFrame(WebLocalFrame*) {}
|
||||
|
||||
// Unified Plan: The list of transceivers after the createOffer() call.
|
||||
@@ -144,7 +153,6 @@ class WebRTCPeerConnectionHandler {
|
||||
// In Unified Plan: Returns OK() with the updated transceiver state.
|
||||
virtual webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>>
|
||||
RemoveTrack(RTCRtpSenderPlatform*) = 0;
|
||||
- virtual void Stop() = 0;
|
||||
|
||||
// Returns a pointer to the underlying native PeerConnection object.
|
||||
virtual webrtc::PeerConnectionInterface* NativePeerConnection() = 0;
|
||||
diff --git a/third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h b/third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h
|
||||
index cfe440ac5e77dce9582ee053e61a74569448993b..4a7181f90d41aaf80ed3ff26fb0364fd78827c71 100644
|
||||
--- a/third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h
|
||||
+++ b/third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h
|
||||
@@ -84,7 +84,7 @@ class BLINK_PLATFORM_EXPORT WebRTCPeerConnectionHandlerClient {
|
||||
virtual void DidAddRemoteDataChannel(
|
||||
scoped_refptr<webrtc::DataChannelInterface>) = 0;
|
||||
virtual void DidNoteInterestingUsage(int usage_pattern) = 0;
|
||||
- virtual void ReleasePeerConnectionHandler() = 0;
|
||||
+ virtual void UnregisterPeerConnectionHandler() = 0;
|
||||
virtual void ClosePeerConnection();
|
||||
};
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.cc
|
||||
index beb724770432ff6d492c002cf14e05d9593887a8..b2c2b211da242afaf0845f245156c8114000aedb 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.cc
|
||||
@@ -395,6 +395,7 @@ MockWebRTCPeerConnectionHandler::CreateDataChannel(
|
||||
}
|
||||
|
||||
void MockWebRTCPeerConnectionHandler::Stop() {}
|
||||
+void MockWebRTCPeerConnectionHandler::StopAndUnregister() {}
|
||||
|
||||
webrtc::PeerConnectionInterface*
|
||||
MockWebRTCPeerConnectionHandler::NativePeerConnection() {
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.h b/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.h
|
||||
index 4fe3325eaeb3ef4bb7ce2186387513f96db3c913..c6b020707134e0628d6de28b29d354bf29fe24b1 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler.h
|
||||
@@ -27,6 +27,8 @@ class MockWebRTCPeerConnectionHandler : public WebRTCPeerConnectionHandler {
|
||||
|
||||
bool Initialize(const webrtc::PeerConnectionInterface::RTCConfiguration&,
|
||||
const WebMediaConstraints&) override;
|
||||
+ void Stop() override;
|
||||
+ void StopAndUnregister() override;
|
||||
|
||||
WebVector<std::unique_ptr<RTCRtpTransceiverPlatform>> CreateOffer(
|
||||
RTCSessionDescriptionRequest*,
|
||||
@@ -73,7 +75,6 @@ class MockWebRTCPeerConnectionHandler : public WebRTCPeerConnectionHandler {
|
||||
scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
|
||||
const WebString& label,
|
||||
const webrtc::DataChannelInit&) override;
|
||||
- void Stop() override;
|
||||
webrtc::PeerConnectionInterface* NativePeerConnection() override;
|
||||
void RunSynchronousOnceClosureOnSignalingThread(
|
||||
base::OnceClosure closure,
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h b/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h
|
||||
index 34345c9a3a81f1cd62b69743de2d597e36372591..6cb5ae5c9d67ae3e986eb29e8bb97d615a7d322d 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h
|
||||
@@ -63,7 +63,7 @@ class MockWebRTCPeerConnectionHandlerClient
|
||||
MOCK_METHOD1(DidAddRemoteDataChannel,
|
||||
void(scoped_refptr<webrtc::DataChannelInterface>));
|
||||
MOCK_METHOD1(DidNoteInterestingUsage, void(int));
|
||||
- MOCK_METHOD0(ReleasePeerConnectionHandler, void());
|
||||
+ MOCK_METHOD0(UnregisterPeerConnectionHandler, void());
|
||||
|
||||
// Move-only arguments do not play nicely with MOCK, the workaround is to
|
||||
// EXPECT_CALL with these instead.
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
index 6a70d3ba1f3c4ea263f07584110860265ff35162..8568a08d1380e844b27cc35919165357ba1b5c44 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
@@ -800,9 +800,11 @@ RTCPeerConnection::~RTCPeerConnection() {
|
||||
}
|
||||
|
||||
void RTCPeerConnection::Dispose() {
|
||||
- // Promptly clears a raw reference from content/ to an on-heap object
|
||||
+ // Promptly clears the handler's pointer to |this|
|
||||
// so that content/ doesn't access it in a lazy sweeping phase.
|
||||
- peer_handler_.reset();
|
||||
+ if (peer_handler_) {
|
||||
+ peer_handler_->StopAndUnregister();
|
||||
+ }
|
||||
|
||||
// UMA for CallSetupStates. This metric is reported regardless of whether or
|
||||
// not getUserMedia() has been called in this document.
|
||||
@@ -3066,7 +3068,7 @@ void RTCPeerConnection::DidNoteInterestingUsage(int usage_pattern) {
|
||||
.Record(document->UkmRecorder());
|
||||
}
|
||||
|
||||
-void RTCPeerConnection::ReleasePeerConnectionHandler() {
|
||||
+void RTCPeerConnection::UnregisterPeerConnectionHandler() {
|
||||
if (stopped_)
|
||||
return;
|
||||
|
||||
@@ -3074,7 +3076,7 @@ void RTCPeerConnection::ReleasePeerConnectionHandler() {
|
||||
ice_connection_state_ = webrtc::PeerConnectionInterface::kIceConnectionClosed;
|
||||
signaling_state_ = webrtc::PeerConnectionInterface::SignalingState::kClosed;
|
||||
|
||||
- peer_handler_.reset();
|
||||
+ peer_handler_->StopAndUnregister();
|
||||
dispatch_scheduled_events_task_handle_.Cancel();
|
||||
feature_handle_for_scheduler_.reset();
|
||||
}
|
||||
@@ -3094,7 +3096,7 @@ ExecutionContext* RTCPeerConnection::GetExecutionContext() const {
|
||||
}
|
||||
|
||||
void RTCPeerConnection::ContextDestroyed(ExecutionContext*) {
|
||||
- ReleasePeerConnectionHandler();
|
||||
+ UnregisterPeerConnectionHandler();
|
||||
}
|
||||
|
||||
void RTCPeerConnection::ChangeSignalingState(
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
|
||||
index d756173ba4beb88a73018e54e263d42b55fd0db1..e5112d52c14c1b2416824c4f4616383f4f8743eb 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
|
||||
@@ -309,7 +309,7 @@ class MODULES_EXPORT RTCPeerConnection final
|
||||
void DidAddRemoteDataChannel(
|
||||
scoped_refptr<webrtc::DataChannelInterface> channel) override;
|
||||
void DidNoteInterestingUsage(int usage_pattern) override;
|
||||
- void ReleasePeerConnectionHandler() override;
|
||||
+ void UnregisterPeerConnectionHandler() override;
|
||||
void ClosePeerConnection() override;
|
||||
|
||||
// EventTarget
|
||||
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 6745fc1ae9746a3f9949f856b1501c48e85b5260..5b237e73a43f741aa0beb1ebffac31a1af711413 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
|
||||
@@ -1007,6 +1007,7 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler(
|
||||
: initialize_called_(false),
|
||||
client_(client),
|
||||
is_closed_(false),
|
||||
+ is_unregistered_(false),
|
||||
dependency_factory_(dependency_factory),
|
||||
track_adapter_map_(
|
||||
base::MakeRefCounted<blink::WebRtcMediaStreamTrackAdapterMap>(
|
||||
@@ -1019,6 +1020,12 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler(
|
||||
}
|
||||
|
||||
RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
|
||||
+ if (!is_unregistered_) {
|
||||
+ StopAndUnregister();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void RTCPeerConnectionHandler::StopAndUnregister() {
|
||||
DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
Stop();
|
||||
@@ -1029,6 +1036,10 @@ RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
|
||||
|
||||
UMA_HISTOGRAM_COUNTS_10000("WebRTC.NumDataChannelsPerPeerConnection",
|
||||
num_data_channels_created_);
|
||||
+ // Clear the pointer to client_ so that it does not interfere with
|
||||
+ // garbage collection.
|
||||
+ client_ = nullptr;
|
||||
+ is_unregistered_ = true;
|
||||
}
|
||||
|
||||
void RTCPeerConnectionHandler::AssociateWithFrame(blink::WebLocalFrame* frame) {
|
||||
@@ -2131,6 +2142,10 @@ void RTCPeerConnectionHandler::OnSignalingChange(
|
||||
peer_connection_tracker_->TrackSignalingStateChange(this, stable_state);
|
||||
if (!is_closed_)
|
||||
client_->DidChangeSignalingState(stable_state);
|
||||
+ // The callback may have closed the PC. If so, do not continue.
|
||||
+ if (is_closed_ || !client_) {
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
previous_signaling_state_ = new_state;
|
||||
if (peer_connection_tracker_)
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
|
||||
index 1aa9ffa273be0e52e0c37268a78abf16b165b041..171d71e3ad69849d3bc5c3cc6d7c505f395df26a 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
|
||||
@@ -107,6 +107,9 @@ class MODULES_EXPORT RTCPeerConnectionHandler
|
||||
server_configuration,
|
||||
const blink::WebMediaConstraints& options) override;
|
||||
|
||||
+ void Stop() override;
|
||||
+ void StopAndUnregister() override;
|
||||
+
|
||||
blink::WebVector<std::unique_ptr<RTCRtpTransceiverPlatform>> CreateOffer(
|
||||
blink::RTCSessionDescriptionRequest* request,
|
||||
const blink::WebMediaConstraints& options) override;
|
||||
@@ -162,7 +165,6 @@ class MODULES_EXPORT RTCPeerConnectionHandler
|
||||
scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
|
||||
const blink::WebString& label,
|
||||
const webrtc::DataChannelInit& init) override;
|
||||
- void Stop() override;
|
||||
webrtc::PeerConnectionInterface* NativePeerConnection() override;
|
||||
void RunSynchronousOnceClosureOnSignalingThread(
|
||||
base::OnceClosure closure,
|
||||
@@ -339,14 +341,18 @@ class MODULES_EXPORT RTCPeerConnectionHandler
|
||||
// first call fails.
|
||||
bool initialize_called_;
|
||||
|
||||
- // |client_| is a weak pointer to the blink object (blink::RTCPeerConnection)
|
||||
+ // |client_| is a raw pointer to the blink object (blink::RTCPeerConnection)
|
||||
// that owns this object.
|
||||
- // It is valid for the lifetime of this object.
|
||||
- blink::WebRTCPeerConnectionHandlerClient* const client_;
|
||||
+ // It is valid for the lifetime of this object, but is cleared when
|
||||
+ // StopAndUnregister() is called, in order to make sure it doesn't
|
||||
+ // interfere with garbage collection of the owner object.
|
||||
+ blink::WebRTCPeerConnectionHandlerClient* client_;
|
||||
// True if this PeerConnection has been closed.
|
||||
// After the PeerConnection has been closed, this object may no longer
|
||||
// forward callbacks to blink.
|
||||
bool is_closed_;
|
||||
+ // True if StopAndUnregister has been called.
|
||||
+ bool is_unregistered_;
|
||||
|
||||
// Transition from kHaveLocalOffer to kHaveRemoteOffer indicates implicit
|
||||
// rollback in which case we need to also make visiting of kStable observable.
|
||||
diff --git a/third_party/blink/web_tests/fast/peerconnection/resources/statechange-iframe-destroy-child.html b/third_party/blink/web_tests/fast/peerconnection/resources/statechange-iframe-destroy-child.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c7e4ae5071d478329f66a6a70016a2705fff16a5
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/fast/peerconnection/resources/statechange-iframe-destroy-child.html
|
||||
@@ -0,0 +1,30 @@
|
||||
+<html>
|
||||
+<script>
|
||||
+'use strict;'
|
||||
+
|
||||
+let cnt = 0;
|
||||
+
|
||||
+function causeIssue() {
|
||||
+ youConnection = new RTCPeerConnection({});
|
||||
+
|
||||
+ youConnection.onsignalingstatechange = ev => {
|
||||
+ if(cnt==1) {
|
||||
+ parent.trigger();
|
||||
+ }
|
||||
+ cnt++;
|
||||
+ };
|
||||
+ var offerOptions = {
|
||||
+ offerToReceiveVideo: 1
|
||||
+ };
|
||||
+
|
||||
+ youConnection.createOffer(offerOptions)
|
||||
+ .then(function(offer){
|
||||
+ youConnection.setLocalDescription(offer);
|
||||
+ // Cause an implicit rollback.
|
||||
+ youConnection.setRemoteDescription(offer);
|
||||
+ });
|
||||
+}
|
||||
+
|
||||
+causeIssue();
|
||||
+</script>
|
||||
+</html>
|
||||
diff --git a/third_party/blink/web_tests/fast/peerconnection/statechange-iframe-destroy-parent.html b/third_party/blink/web_tests/fast/peerconnection/statechange-iframe-destroy-parent.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fcadc791fda05794362de0c1ff4352e258a6baeb
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/fast/peerconnection/statechange-iframe-destroy-parent.html
|
||||
@@ -0,0 +1,24 @@
|
||||
+<html>
|
||||
+ <script src="../../resources/testharness.js"></script>
|
||||
+ <script src="../../resources/testharnessreport.js"></script>
|
||||
+ <iframe id="ifr">
|
||||
+ </iframe>
|
||||
+<script>
|
||||
+
|
||||
+let triggered = null;
|
||||
+
|
||||
+function trigger()
|
||||
+{
|
||||
+ ifr.remove();
|
||||
+ triggered();
|
||||
+}
|
||||
+
|
||||
+promise_test(t => {
|
||||
+ ifr.src = "resources/statechange-iframe-destroy-child.html";
|
||||
+ return new Promise(resolve => {
|
||||
+ triggered = resolve;
|
||||
+ });
|
||||
+}, 'Remove iframe from a statechange callback invoked from iframe');
|
||||
+
|
||||
+</script>
|
||||
+</html>
|
||||
20
patches/chromium/remove_menu_window_task_item.patch
Normal file
20
patches/chromium/remove_menu_window_task_item.patch
Normal file
@@ -0,0 +1,20 @@
|
||||
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: remove menu window from taskbar
|
||||
|
||||
Refs https://chromium-review.googlesource.com/c/chromium/src/+/2245941
|
||||
|
||||
diff --git a/ui/views/widget/widget_hwnd_utils.cc b/ui/views/widget/widget_hwnd_utils.cc
|
||||
index 40e66a212e3ea158b61f11d804a3c1644023b2d7..89f5b62f95dfec59bacf79f33895438039fac1c5 100644
|
||||
--- a/ui/views/widget/widget_hwnd_utils.cc
|
||||
+++ b/ui/views/widget/widget_hwnd_utils.cc
|
||||
@@ -118,6 +118,8 @@ void CalculateWindowStylesFromInitParams(
|
||||
else
|
||||
*style |= WS_BORDER;
|
||||
}
|
||||
+ if (!params.force_show_in_taskbar)
|
||||
+ *ex_style |= WS_EX_TOOLWINDOW;
|
||||
break;
|
||||
case Widget::InitParams::TYPE_TOOLTIP:
|
||||
*style |= WS_POPUP;
|
||||
@@ -1,9 +1,13 @@
|
||||
{
|
||||
"src/electron/patches/chromium": "src",
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/boringssl": "src/third_party/boringssl/src",
|
||||
|
||||
"src/electron/patches/v8": "src/v8",
|
||||
|
||||
"src/electron/patches/node": "src/third_party/electron_node"
|
||||
"src/electron/patches/node": "src/third_party/electron_node",
|
||||
|
||||
"src/electron/patches/usrsctp": "src/third_party/usrsctp/usrsctplib"
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ inherit_electron_crashpad_pipe_name_in_child_process.patch
|
||||
fixme_revert_crypto_add_support_for_rsa-pss_keys.patch
|
||||
fix_extern_the_nativemoduleenv_and_options_parser_for_debug_builds.patch
|
||||
chore_read_nobrowserglobals_from_global_not_process.patch
|
||||
chore_split_createenvironment_into_createenvironment_and.patch
|
||||
chore_handle_default_configuration_not_being_set_in_the_electron_env.patch
|
||||
fsevents-stop-using-fsevents-to-watch-files.patch
|
||||
fsevents-regression-in-watching.patch
|
||||
@@ -41,3 +40,9 @@ fix_don_t_use_node-controlled_preparestacktrace.patch
|
||||
fix_remove_uses_of_node_use_v8_platform.patch
|
||||
fix_call_initializecontextruntime_in_initializecontext.patch
|
||||
refactor_transferrablemodule_is_deprecated_use_compiledwasmmodule.patch
|
||||
fix_don_t_preparemainexecution_twice.patch
|
||||
tls_emit_session_after_verifying_certificate.patch
|
||||
http2_implement_support_for_max_settings_entries.patch
|
||||
deps_update_nghttp2_to_1_40_0.patch
|
||||
deps_update_nghttp2_to_1_41_0.patch
|
||||
napi_fix_memory_corruption_vulnerability.patch
|
||||
|
||||
@@ -882,10 +882,10 @@ index 0000000000000000000000000000000000000000..f13b471d17128468bed06e66bd03a2ea
|
||||
+}
|
||||
diff --git a/filenames.json b/filenames.json
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..bfe6555be5239c6d9cad59e8b845638d50f31ee3
|
||||
index 0000000000000000000000000000000000000000..76356ebaee56307b55e9da590d8c819f72599930
|
||||
--- /dev/null
|
||||
+++ b/filenames.json
|
||||
@@ -0,0 +1,447 @@
|
||||
@@ -0,0 +1,446 @@
|
||||
+// This file is automatically generated by generate_gn_filenames_json.py
|
||||
+// DO NOT EDIT
|
||||
+{
|
||||
@@ -955,7 +955,6 @@ index 0000000000000000000000000000000000000000..bfe6555be5239c6d9cad59e8b845638d
|
||||
+ }
|
||||
+ ],
|
||||
+ "library_files": [
|
||||
+ "lib/internal/bootstrap/environment.js",
|
||||
+ "lib/internal/bootstrap/loaders.js",
|
||||
+ "lib/internal/bootstrap/node.js",
|
||||
+ "lib/internal/bootstrap/pre_execution.js",
|
||||
|
||||
@@ -38,7 +38,7 @@ index fabaea75686161f488a03349e07049a513b98fad..5a6b01dc12fb77d5f8c26a1153ead2a1
|
||||
|
||||
bool Exists(const char* id);
|
||||
diff --git a/tools/js2c.py b/tools/js2c.py
|
||||
index 752344d68c3f63b4c5e491b33d4576ed48f8b74f..a6f0805048e3c3f4dd81ce6e90b684c48e52b67c 100755
|
||||
index 752344d68c3f63b4c5e491b33d4576ed48f8b74f..dc3946e3ac579134dd26e5855a1db0a7ed44e405 100755
|
||||
--- a/tools/js2c.py
|
||||
+++ b/tools/js2c.py
|
||||
@@ -187,13 +187,15 @@ namespace native_module {{
|
||||
@@ -100,14 +100,14 @@ index 752344d68c3f63b4c5e491b33d4576ed48f8b74f..a6f0805048e3c3f4dd81ce6e90b684c4
|
||||
- definitions.append(config_def)
|
||||
+ # Electron: Expose fs module without asar support.
|
||||
+ if filename == 'lib/fs.js':
|
||||
+ # Node's 'fs' and 'internal/fs/streams' have a lazy-loaded circular
|
||||
+ # dependency. So to expose the unmodified Node 'fs' functionality here,
|
||||
+ # we have to copy both 'fs' *and* 'internal/fs/streams' and modify the
|
||||
+ # Node's 'fs' and 'internal/fs/<filename> have lazy-loaded circular
|
||||
+ # dependencies. So to expose the unmodified Node 'fs' functionality here,
|
||||
+ # we have to copy both 'fs' *and* 'internal/fs/<filename>' files and modify the
|
||||
+ # copies to depend on each other instead of on our asarified 'fs' code.
|
||||
+ # See https://github.com/electron/electron/pull/16028 for more.
|
||||
+ AddModule('lib/original-fs.js', consts, macros, definitions, initializers, lambda _: ReadFile(filename).replace("require('internal/fs/streams')", "require('internal/original-fs/streams')"))
|
||||
+ elif filename == 'lib/internal/fs/streams.js':
|
||||
+ AddModule('lib/internal/original-fs/streams.js', consts, macros, definitions, initializers, lambda _: ReadFile(filename).replace("require('fs')", "require('original-fs')"))
|
||||
+ AddModule('lib/original-fs.js', consts, macros, definitions, initializers, lambda _: ReadFile(filename).replace("require('internal/fs/", "require('internal/original-fs/"))
|
||||
+ elif filename.startswith('lib/internal/fs/'):
|
||||
+ original_fs_filename = filename.replace('internal/fs/', 'internal/original-fs/')
|
||||
+ AddModule(original_fs_filename, consts, macros, definitions, initializers, lambda _: ReadFile(filename).replace("require('fs')", "require('original-fs')"))
|
||||
+
|
||||
+ config_size = 0
|
||||
+ if not only_js:
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@slack-corp.com>
|
||||
Date: Wed, 17 Jul 2019 14:45:59 -0700
|
||||
Subject: chore: split CreateEnvironment into CreateEnvironment and
|
||||
BootstrapEnvironment
|
||||
|
||||
This allows us to run operations on a created but not yet bootstrapped
|
||||
environment such as setting up an InspectorAgent
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index ae26cb7e9ef55fc0b965e28de4686aec87f42522..50886f4a998f1e7f346a6b7fad91ce49c3a7cdff 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -263,7 +263,8 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
|
||||
int argc,
|
||||
const char* const* argv,
|
||||
int exec_argc,
|
||||
- const char* const* exec_argv) {
|
||||
+ const char* const* exec_argv,
|
||||
+ bool bootstrap) {
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
HandleScope handle_scope(isolate);
|
||||
Context::Scope context_scope(context);
|
||||
@@ -281,9 +282,16 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
|
||||
Environment::kOwnsProcessState |
|
||||
Environment::kOwnsInspector));
|
||||
env->InitializeLibuv(per_process::v8_is_profiling);
|
||||
- if (env->RunBootstrapping().IsEmpty()) {
|
||||
+ if (bootstrap && !BootstrapEnvironment(env)) {
|
||||
return nullptr;
|
||||
}
|
||||
+ return env;
|
||||
+}
|
||||
+
|
||||
+bool BootstrapEnvironment(Environment* env) {
|
||||
+ if (env->RunBootstrapping().IsEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
std::vector<Local<String>> parameters = {
|
||||
env->require_string(),
|
||||
@@ -296,9 +304,10 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
|
||||
if (ExecuteBootstrapper(
|
||||
env, "internal/bootstrap/environment", ¶meters, &arguments)
|
||||
.IsEmpty()) {
|
||||
- return nullptr;
|
||||
+ return false;
|
||||
}
|
||||
- return env;
|
||||
+
|
||||
+ return true;
|
||||
}
|
||||
|
||||
void FreeEnvironment(Environment* env) {
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 80a27dc734a81a7ca8d888d1d55fc8d24a536280..9c6dcbf7014f7cf87f7f66886cbf255978c244fa 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -326,7 +326,9 @@ NODE_EXTERN Environment* CreateEnvironment(IsolateData* isolate_data,
|
||||
int argc,
|
||||
const char* const* argv,
|
||||
int exec_argc,
|
||||
- const char* const* exec_argv);
|
||||
+ const char* const* exec_argv,
|
||||
+ bool bootstrap = true);
|
||||
+NODE_EXTERN bool BootstrapEnvironment(Environment* env);
|
||||
|
||||
NODE_EXTERN void LoadEnvironment(Environment* env);
|
||||
NODE_EXTERN void FreeEnvironment(Environment* env);
|
||||
9820
patches/node/deps_update_nghttp2_to_1_40_0.patch
Normal file
9820
patches/node/deps_update_nghttp2_to_1_40_0.patch
Normal file
File diff suppressed because it is too large
Load Diff
494
patches/node/deps_update_nghttp2_to_1_41_0.patch
Normal file
494
patches/node/deps_update_nghttp2_to_1_41_0.patch
Normal file
@@ -0,0 +1,494 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: James M Snell <jasnell@gmail.com>
|
||||
Date: Mon, 27 Apr 2020 09:27:49 -0700
|
||||
Subject: deps: update nghttp2 to 1.41.0
|
||||
|
||||
Fixes: https://hackerone.com/reports/446662
|
||||
CVE-ID: CVE-2020-11080
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/204
|
||||
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
||||
|
||||
diff --git a/deps/nghttp2/lib/CMakeLists.txt b/deps/nghttp2/lib/CMakeLists.txt
|
||||
deleted file mode 100644
|
||||
index 4e3f5da0f9f00afb272de2e110d0e101c075fc01..0000000000000000000000000000000000000000
|
||||
--- a/deps/nghttp2/lib/CMakeLists.txt
|
||||
+++ /dev/null
|
||||
@@ -1,76 +0,0 @@
|
||||
-add_subdirectory(includes)
|
||||
-
|
||||
-include_directories(
|
||||
- "${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
- "${CMAKE_CURRENT_BINARY_DIR}/includes"
|
||||
-)
|
||||
-
|
||||
-add_definitions(-DBUILDING_NGHTTP2)
|
||||
-
|
||||
-set(NGHTTP2_SOURCES
|
||||
- nghttp2_pq.c nghttp2_map.c nghttp2_queue.c
|
||||
- nghttp2_frame.c
|
||||
- nghttp2_buf.c
|
||||
- nghttp2_stream.c nghttp2_outbound_item.c
|
||||
- nghttp2_session.c nghttp2_submit.c
|
||||
- nghttp2_helper.c
|
||||
- nghttp2_npn.c
|
||||
- nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c
|
||||
- nghttp2_version.c
|
||||
- nghttp2_priority_spec.c
|
||||
- nghttp2_option.c
|
||||
- nghttp2_callbacks.c
|
||||
- nghttp2_mem.c
|
||||
- nghttp2_http.c
|
||||
- nghttp2_rcbuf.c
|
||||
- nghttp2_debug.c
|
||||
-)
|
||||
-
|
||||
-set(NGHTTP2_RES "")
|
||||
-
|
||||
-if(WIN32)
|
||||
- configure_file(
|
||||
- version.rc.in
|
||||
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
||||
- @ONLY)
|
||||
-
|
||||
- set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
-endif()
|
||||
-
|
||||
-# Public shared library
|
||||
-if(ENABLE_SHARED_LIB)
|
||||
- add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
- set_target_properties(nghttp2 PROPERTIES
|
||||
- COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
- VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
- C_VISIBILITY_PRESET hidden
|
||||
- )
|
||||
- target_include_directories(nghttp2 INTERFACE
|
||||
- "${CMAKE_CURRENT_BINARY_DIR}/includes"
|
||||
- "${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
- )
|
||||
-
|
||||
- install(TARGETS nghttp2
|
||||
- ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
- LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
- RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
-endif()
|
||||
-
|
||||
-if(HAVE_CUNIT OR ENABLE_STATIC_LIB)
|
||||
- # Static library (for unittests because of symbol visibility)
|
||||
- add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
||||
- set_target_properties(nghttp2_static PROPERTIES
|
||||
- COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
- VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
- ARCHIVE_OUTPUT_NAME nghttp2_static
|
||||
- )
|
||||
- target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
- if(ENABLE_STATIC_LIB)
|
||||
- install(TARGETS nghttp2_static
|
||||
- DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
- endif()
|
||||
-endif()
|
||||
-
|
||||
-
|
||||
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
||||
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h
|
||||
index e3aeb9fed31ecc11e068a42e656c307575b4f024..9be6eea5c02257ac12522e43829f47b3f371b857 100644
|
||||
--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h
|
||||
+++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h
|
||||
@@ -228,6 +228,13 @@ typedef struct {
|
||||
*/
|
||||
#define NGHTTP2_CLIENT_MAGIC_LEN 24
|
||||
|
||||
+/**
|
||||
+ * @macro
|
||||
+ *
|
||||
+ * The default max number of settings per SETTINGS frame
|
||||
+ */
|
||||
+#define NGHTTP2_DEFAULT_MAX_SETTINGS 32
|
||||
+
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
@@ -398,6 +405,11 @@ typedef enum {
|
||||
* receives an other type of frame.
|
||||
*/
|
||||
NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
|
||||
+ /**
|
||||
+ * When a local endpoint receives too many settings entries
|
||||
+ * in a single SETTINGS frame.
|
||||
+ */
|
||||
+ NGHTTP2_ERR_TOO_MANY_SETTINGS = -537,
|
||||
/**
|
||||
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
|
||||
* under unexpected condition and processing was terminated (e.g.,
|
||||
@@ -2659,6 +2671,17 @@ NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_max_outbound_ack(nghttp2_option *option,
|
||||
size_t val);
|
||||
|
||||
+/**
|
||||
+ * @function
|
||||
+ *
|
||||
+ * This function sets the maximum number of SETTINGS entries per
|
||||
+ * SETTINGS frame that will be accepted. If more than those entries
|
||||
+ * are received, the peer is considered to be misbehaving and session
|
||||
+ * will be closed. The default value is 32.
|
||||
+ */
|
||||
+NGHTTP2_EXTERN void nghttp2_option_set_max_settings(nghttp2_option *option,
|
||||
+ size_t val);
|
||||
+
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h
|
||||
index 45d21e2645c6cf8be52e445b3ab8862c08597d85..795a44c1e86863119e33e09309d7305e579af132 100644
|
||||
--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h
|
||||
+++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h
|
||||
@@ -29,7 +29,7 @@
|
||||
* @macro
|
||||
* Version number of the nghttp2 library release
|
||||
*/
|
||||
-#define NGHTTP2_VERSION "1.40.0"
|
||||
+#define NGHTTP2_VERSION "1.41.0"
|
||||
|
||||
/**
|
||||
* @macro
|
||||
@@ -37,6 +37,6 @@
|
||||
* release. This is a 24 bit number with 8 bits for major number, 8 bits
|
||||
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
|
||||
*/
|
||||
-#define NGHTTP2_VERSION_NUM 0x012800
|
||||
+#define NGHTTP2_VERSION_NUM 0x012900
|
||||
|
||||
#endif /* NGHTTP2VER_H */
|
||||
diff --git a/deps/nghttp2/lib/nghttp2_helper.c b/deps/nghttp2/lib/nghttp2_helper.c
|
||||
index 91136a61986014706b091d177e6abdf88f6444e3..0bd5414723d73688a2a546f9036c3d910ef3e53c 100644
|
||||
--- a/deps/nghttp2/lib/nghttp2_helper.c
|
||||
+++ b/deps/nghttp2/lib/nghttp2_helper.c
|
||||
@@ -334,6 +334,8 @@ const char *nghttp2_strerror(int error_code) {
|
||||
case NGHTTP2_ERR_FLOODED:
|
||||
return "Flooding was detected in this HTTP/2 session, and it must be "
|
||||
"closed";
|
||||
+ case NGHTTP2_ERR_TOO_MANY_SETTINGS:
|
||||
+ return "SETTINGS frame contained more than the maximum allowed entries";
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
diff --git a/deps/nghttp2/lib/nghttp2_option.c b/deps/nghttp2/lib/nghttp2_option.c
|
||||
index e53f22d367f84a11792721d38a1cdc1a538e2a03..34348e6606ccf4206048f3f2f76d75a2ec366cc8 100644
|
||||
--- a/deps/nghttp2/lib/nghttp2_option.c
|
||||
+++ b/deps/nghttp2/lib/nghttp2_option.c
|
||||
@@ -121,3 +121,8 @@ void nghttp2_option_set_max_outbound_ack(nghttp2_option *option, size_t val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_MAX_OUTBOUND_ACK;
|
||||
option->max_outbound_ack = val;
|
||||
}
|
||||
+
|
||||
+void nghttp2_option_set_max_settings(nghttp2_option *option, size_t val) {
|
||||
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_SETTINGS;
|
||||
+ option->max_settings = val;
|
||||
+}
|
||||
diff --git a/deps/nghttp2/lib/nghttp2_option.h b/deps/nghttp2/lib/nghttp2_option.h
|
||||
index 1f740aaa6e364ed5a8df4804cff307ef36970b0b..939729fdcd5b6ec11078aef0d9b51e45270092a3 100644
|
||||
--- a/deps/nghttp2/lib/nghttp2_option.h
|
||||
+++ b/deps/nghttp2/lib/nghttp2_option.h
|
||||
@@ -67,6 +67,7 @@ typedef enum {
|
||||
NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
|
||||
NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
|
||||
NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
|
||||
+ NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
|
||||
} nghttp2_option_flag;
|
||||
|
||||
/**
|
||||
@@ -85,6 +86,10 @@ struct nghttp2_option {
|
||||
* NGHTTP2_OPT_MAX_OUTBOUND_ACK
|
||||
*/
|
||||
size_t max_outbound_ack;
|
||||
+ /**
|
||||
+ * NGHTTP2_OPT_MAX_SETTINGS
|
||||
+ */
|
||||
+ size_t max_settings;
|
||||
/**
|
||||
* Bitwise OR of nghttp2_option_flag to determine that which fields
|
||||
* are specified.
|
||||
diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c
|
||||
index 9df3d6f32938a692191abbad915e028a9669d24d..39f81f498cda798bcd18926414d7297f34361d2b 100644
|
||||
--- a/deps/nghttp2/lib/nghttp2_session.c
|
||||
+++ b/deps/nghttp2/lib/nghttp2_session.c
|
||||
@@ -458,6 +458,7 @@ static int session_new(nghttp2_session **session_ptr,
|
||||
|
||||
(*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
|
||||
(*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM;
|
||||
+ (*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS;
|
||||
|
||||
if (option) {
|
||||
if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
|
||||
@@ -521,6 +522,11 @@ static int session_new(nghttp2_session **session_ptr,
|
||||
if (option->opt_set_mask & NGHTTP2_OPT_MAX_OUTBOUND_ACK) {
|
||||
(*session_ptr)->max_outbound_ack = option->max_outbound_ack;
|
||||
}
|
||||
+
|
||||
+ if ((option->opt_set_mask & NGHTTP2_OPT_MAX_SETTINGS) &&
|
||||
+ option->max_settings) {
|
||||
+ (*session_ptr)->max_settings = option->max_settings;
|
||||
+ }
|
||||
}
|
||||
|
||||
rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
|
||||
@@ -2494,14 +2500,6 @@ static int session_update_stream_consumed_size(nghttp2_session *session,
|
||||
static int session_update_connection_consumed_size(nghttp2_session *session,
|
||||
size_t delta_size);
|
||||
|
||||
-static int session_update_recv_connection_window_size(nghttp2_session *session,
|
||||
- size_t delta_size);
|
||||
-
|
||||
-static int session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
- nghttp2_stream *stream,
|
||||
- size_t delta_size,
|
||||
- int send_window_update);
|
||||
-
|
||||
/*
|
||||
* Called after a frame is sent. This function runs
|
||||
* on_frame_send_callback and handles stream closure upon END_STREAM
|
||||
@@ -2735,7 +2733,7 @@ static int session_after_frame_sent1(nghttp2_session *session) {
|
||||
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
||||
rv = session_update_connection_consumed_size(session, 0);
|
||||
} else {
|
||||
- rv = session_update_recv_connection_window_size(session, 0);
|
||||
+ rv = nghttp2_session_update_recv_connection_window_size(session, 0);
|
||||
}
|
||||
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
@@ -2761,7 +2759,8 @@ static int session_after_frame_sent1(nghttp2_session *session) {
|
||||
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
||||
rv = session_update_stream_consumed_size(session, stream, 0);
|
||||
} else {
|
||||
- rv = session_update_recv_stream_window_size(session, stream, 0, 1);
|
||||
+ rv =
|
||||
+ nghttp2_session_update_recv_stream_window_size(session, stream, 0, 1);
|
||||
}
|
||||
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
@@ -5019,22 +5018,10 @@ static int adjust_recv_window_size(int32_t *recv_window_size_ptr, size_t delta,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Accumulates received bytes |delta_size| for stream-level flow
|
||||
- * control and decides whether to send WINDOW_UPDATE to that stream.
|
||||
- * If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, WINDOW_UPDATE will not
|
||||
- * be sent.
|
||||
- *
|
||||
- * This function returns 0 if it succeeds, or one of the following
|
||||
- * negative error codes:
|
||||
- *
|
||||
- * NGHTTP2_ERR_NOMEM
|
||||
- * Out of memory.
|
||||
- */
|
||||
-static int session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
- nghttp2_stream *stream,
|
||||
- size_t delta_size,
|
||||
- int send_window_update) {
|
||||
+int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
+ nghttp2_stream *stream,
|
||||
+ size_t delta_size,
|
||||
+ int send_window_update) {
|
||||
int rv;
|
||||
rv = adjust_recv_window_size(&stream->recv_window_size, delta_size,
|
||||
stream->local_window_size);
|
||||
@@ -5063,20 +5050,8 @@ static int session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Accumulates received bytes |delta_size| for connection-level flow
|
||||
- * control and decides whether to send WINDOW_UPDATE to the
|
||||
- * connection. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set,
|
||||
- * WINDOW_UPDATE will not be sent.
|
||||
- *
|
||||
- * This function returns 0 if it succeeds, or one of the following
|
||||
- * negative error codes:
|
||||
- *
|
||||
- * NGHTTP2_ERR_NOMEM
|
||||
- * Out of memory.
|
||||
- */
|
||||
-static int session_update_recv_connection_window_size(nghttp2_session *session,
|
||||
- size_t delta_size) {
|
||||
+int nghttp2_session_update_recv_connection_window_size(nghttp2_session *session,
|
||||
+ size_t delta_size) {
|
||||
int rv;
|
||||
rv = adjust_recv_window_size(&session->recv_window_size, delta_size,
|
||||
session->local_window_size);
|
||||
@@ -5678,6 +5653,12 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
break;
|
||||
}
|
||||
|
||||
+ /* Check the settings flood counter early to be safe */
|
||||
+ if (session->obq_flood_counter_ >= session->max_outbound_ack &&
|
||||
+ !(iframe->frame.hd.flags & NGHTTP2_FLAG_ACK)) {
|
||||
+ return NGHTTP2_ERR_FLOODED;
|
||||
+ }
|
||||
+
|
||||
iframe->state = NGHTTP2_IB_READ_SETTINGS;
|
||||
|
||||
if (iframe->payloadleft) {
|
||||
@@ -5688,6 +5669,16 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
iframe->max_niv =
|
||||
iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
|
||||
|
||||
+ if (iframe->max_niv - 1 > session->max_settings) {
|
||||
+ rv = nghttp2_session_terminate_session_with_reason(
|
||||
+ session, NGHTTP2_ENHANCE_YOUR_CALM,
|
||||
+ "SETTINGS: too many setting entries");
|
||||
+ if (nghttp2_is_fatal(rv)) {
|
||||
+ return rv;
|
||||
+ }
|
||||
+ return (ssize_t)inlen;
|
||||
+ }
|
||||
+
|
||||
iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
|
||||
iframe->max_niv);
|
||||
|
||||
@@ -6454,7 +6445,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
/* Pad Length field is subject to flow control */
|
||||
- rv = session_update_recv_connection_window_size(session, readlen);
|
||||
+ rv = nghttp2_session_update_recv_connection_window_size(session, readlen);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@@ -6477,7 +6468,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
|
||||
stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
|
||||
if (stream) {
|
||||
- rv = session_update_recv_stream_window_size(
|
||||
+ rv = nghttp2_session_update_recv_stream_window_size(
|
||||
session, stream, readlen,
|
||||
iframe->payloadleft ||
|
||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
|
||||
@@ -6524,7 +6515,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (readlen > 0) {
|
||||
ssize_t data_readlen;
|
||||
|
||||
- rv = session_update_recv_connection_window_size(session, readlen);
|
||||
+ rv = nghttp2_session_update_recv_connection_window_size(session,
|
||||
+ readlen);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@@ -6533,7 +6525,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
return (ssize_t)inlen;
|
||||
}
|
||||
|
||||
- rv = session_update_recv_stream_window_size(
|
||||
+ rv = nghttp2_session_update_recv_stream_window_size(
|
||||
session, stream, readlen,
|
||||
iframe->payloadleft ||
|
||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
|
||||
@@ -6634,7 +6626,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (readlen > 0) {
|
||||
/* Update connection-level flow control window for ignored
|
||||
DATA frame too */
|
||||
- rv = session_update_recv_connection_window_size(session, readlen);
|
||||
+ rv = nghttp2_session_update_recv_connection_window_size(session,
|
||||
+ readlen);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@@ -7454,6 +7447,11 @@ static int nghttp2_session_upgrade_internal(nghttp2_session *session,
|
||||
if (settings_payloadlen % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
+ /* SETTINGS frame contains too many settings */
|
||||
+ if (settings_payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH
|
||||
+ > session->max_settings) {
|
||||
+ return NGHTTP2_ERR_TOO_MANY_SETTINGS;
|
||||
+ }
|
||||
rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload,
|
||||
settings_payloadlen, mem);
|
||||
if (rv != 0) {
|
||||
diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h
|
||||
index 90ead9c0395b4f1e42f94daadae57928e6c38df3..07bfbb6c90c8df07c0de4909bb72ff4942d15763 100644
|
||||
--- a/deps/nghttp2/lib/nghttp2_session.h
|
||||
+++ b/deps/nghttp2/lib/nghttp2_session.h
|
||||
@@ -267,6 +267,8 @@ struct nghttp2_session {
|
||||
/* The maximum length of header block to send. Calculated by the
|
||||
same way as nghttp2_hd_deflate_bound() does. */
|
||||
size_t max_send_header_block_length;
|
||||
+ /* The maximum number of settings accepted per SETTINGS frame. */
|
||||
+ size_t max_settings;
|
||||
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
|
||||
uint32_t next_stream_id;
|
||||
/* The last stream ID this session initiated. For client session,
|
||||
@@ -898,4 +900,36 @@ int nghttp2_session_terminate_session_with_reason(nghttp2_session *session,
|
||||
uint32_t error_code,
|
||||
const char *reason);
|
||||
|
||||
+/*
|
||||
+ * Accumulates received bytes |delta_size| for connection-level flow
|
||||
+ * control and decides whether to send WINDOW_UPDATE to the
|
||||
+ * connection. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set,
|
||||
+ * WINDOW_UPDATE will not be sent.
|
||||
+ *
|
||||
+ * This function returns 0 if it succeeds, or one of the following
|
||||
+ * negative error codes:
|
||||
+ *
|
||||
+ * NGHTTP2_ERR_NOMEM
|
||||
+ * Out of memory.
|
||||
+ */
|
||||
+int nghttp2_session_update_recv_connection_window_size(nghttp2_session *session,
|
||||
+ size_t delta_size);
|
||||
+
|
||||
+/*
|
||||
+ * Accumulates received bytes |delta_size| for stream-level flow
|
||||
+ * control and decides whether to send WINDOW_UPDATE to that stream.
|
||||
+ * If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, WINDOW_UPDATE will not
|
||||
+ * be sent.
|
||||
+ *
|
||||
+ * This function returns 0 if it succeeds, or one of the following
|
||||
+ * negative error codes:
|
||||
+ *
|
||||
+ * NGHTTP2_ERR_NOMEM
|
||||
+ * Out of memory.
|
||||
+ */
|
||||
+int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
+ nghttp2_stream *stream,
|
||||
+ size_t delta_size,
|
||||
+ int send_window_update);
|
||||
+
|
||||
#endif /* NGHTTP2_SESSION_H */
|
||||
diff --git a/deps/nghttp2/lib/nghttp2_submit.c b/deps/nghttp2/lib/nghttp2_submit.c
|
||||
index f604eff5c9017fc272ac876d255d522303826d5e..744a49cf6098ec656a72553aa6f6f25240749109 100644
|
||||
--- a/deps/nghttp2/lib/nghttp2_submit.c
|
||||
+++ b/deps/nghttp2/lib/nghttp2_submit.c
|
||||
@@ -450,6 +450,13 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
+
|
||||
+ if (window_size_increment > 0) {
|
||||
+ return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||
+ window_size_increment);
|
||||
+ }
|
||||
+
|
||||
+ return nghttp2_session_update_recv_connection_window_size(session, 0);
|
||||
} else {
|
||||
stream = nghttp2_session_get_stream(session, stream_id);
|
||||
|
||||
@@ -476,11 +483,14 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
- }
|
||||
|
||||
- if (window_size_increment > 0) {
|
||||
- return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||
- window_size_increment);
|
||||
+ if (window_size_increment > 0) {
|
||||
+ return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||
+ window_size_increment);
|
||||
+ }
|
||||
+
|
||||
+ return nghttp2_session_update_recv_stream_window_size(session, stream, 0,
|
||||
+ 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -5,10 +5,10 @@ Subject: fix: call InitializeContextRuntime in InitializeContext
|
||||
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 50886f4a998f1e7f346a6b7fad91ce49c3a7cdff..6ec07527ad7a806f889d884507e9def1cf68b4c8 100644
|
||||
index ae26cb7e9ef55fc0b965e28de4686aec87f42522..05282ebb4414c9f1757763fd68893bf0c6005279 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -371,8 +371,6 @@ Local<Context> NewContext(Isolate* isolate,
|
||||
@@ -362,8 +362,6 @@ Local<Context> NewContext(Isolate* isolate,
|
||||
return Local<Context>();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ index 50886f4a998f1e7f346a6b7fad91ce49c3a7cdff..6ec07527ad7a806f889d884507e9def1
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -457,6 +455,11 @@ bool InitializeContext(Local<Context> context) {
|
||||
@@ -448,6 +446,11 @@ bool InitializeContext(Local<Context> context) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
61
patches/node/fix_don_t_preparemainexecution_twice.patch
Normal file
61
patches/node/fix_don_t_preparemainexecution_twice.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Tue, 2 Jun 2020 17:04:54 -0500
|
||||
Subject: fix: don't prepareMainExecution twice
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In https://github.com/nodejs/node/pull/26788 (v12.0.0), Node.js added a
|
||||
bootstrapper to `CreateEnvironment`, which would prepare the main thread
|
||||
for execution any time an embedder created a new environment. However, this
|
||||
caused an unfortunate doubling-up effect; Node.js also ran bootstrapping
|
||||
(called `prepareMainThreadExecution`) for all other execution paths
|
||||
(like the repl, the actual main module, eval, etc).
|
||||

|
||||
To fix this, we can just remove bootstrapping code from `CreateEnvironment`.
|
||||

|
||||
|
||||
diff --git a/lib/internal/bootstrap/environment.js b/lib/internal/bootstrap/environment.js
|
||||
deleted file mode 100644
|
||||
index 79a67dae378202ee377f2f138560b74f673af6e4..0000000000000000000000000000000000000000
|
||||
--- a/lib/internal/bootstrap/environment.js
|
||||
+++ /dev/null
|
||||
@@ -1,13 +0,0 @@
|
||||
-'use strict';
|
||||
-
|
||||
-// This runs necessary preparations to prepare a complete Node.js context
|
||||
-// that depends on run time states.
|
||||
-// It is currently only intended for preparing contexts for embedders.
|
||||
-
|
||||
-/* global markBootstrapComplete */
|
||||
-const {
|
||||
- prepareMainThreadExecution
|
||||
-} = require('internal/bootstrap/pre_execution');
|
||||
-
|
||||
-prepareMainThreadExecution();
|
||||
-markBootstrapComplete();
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 05282ebb4414c9f1757763fd68893bf0c6005279..862b67f425ff43756093460cbeac214fdfe8ed84 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -285,19 +285,6 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
- std::vector<Local<String>> parameters = {
|
||||
- env->require_string(),
|
||||
- FIXED_ONE_BYTE_STRING(env->isolate(), "markBootstrapComplete")};
|
||||
- std::vector<Local<Value>> arguments = {
|
||||
- env->native_module_require(),
|
||||
- env->NewFunctionTemplate(MarkBootstrapComplete)
|
||||
- ->GetFunction(env->context())
|
||||
- .ToLocalChecked()};
|
||||
- if (ExecuteBootstrapper(
|
||||
- env, "internal/bootstrap/environment", ¶meters, &arguments)
|
||||
- .IsEmpty()) {
|
||||
- return nullptr;
|
||||
- }
|
||||
return env;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: James M Snell <jasnell@gmail.com>
|
||||
Date: Mon, 27 Apr 2020 10:47:58 -0700
|
||||
Subject: http2: implement support for max settings entries
|
||||
|
||||
Adds the maxSettings option to limit the number of settings
|
||||
entries allowed per SETTINGS frame. Default 32
|
||||
|
||||
Signed-off-by: James M Snell <jasnell@gmail.com>
|
||||
|
||||
Fixes: https://hackerone.com/reports/446662
|
||||
CVE-ID: CVE-2020-11080
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/206
|
||||
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
|
||||
|
||||
diff --git a/doc/api/http2.md b/doc/api/http2.md
|
||||
index c37cc41d422384db6360d75d6b564e1e08c0a714..764c4b74ee013d7a3330599b09afea64a08180a1 100644
|
||||
--- a/doc/api/http2.md
|
||||
+++ b/doc/api/http2.md
|
||||
@@ -1958,6 +1958,8 @@ changes:
|
||||
* `options` {Object}
|
||||
* `maxDeflateDynamicTableSize` {number} Sets the maximum dynamic table size
|
||||
for deflating header fields. **Default:** `4Kib`.
|
||||
+ * `maxSettings` {number} Sets the maximum number of settings entries per
|
||||
+ `SETTINGS` frame. The minimum value allowed is `1`. **Default:** `32`.
|
||||
* `maxSessionMemory`{number} Sets the maximum memory that the `Http2Session`
|
||||
is permitted to use. The value is expressed in terms of number of megabytes,
|
||||
e.g. `1` equal 1 megabyte. The minimum value allowed is `1`.
|
||||
@@ -2073,6 +2075,8 @@ changes:
|
||||
**Default:** `false`.
|
||||
* `maxDeflateDynamicTableSize` {number} Sets the maximum dynamic table size
|
||||
for deflating header fields. **Default:** `4Kib`.
|
||||
+ * `maxSettings` {number} Sets the maximum number of settings entries per
|
||||
+ `SETTINGS` frame. The minimum value allowed is `1`. **Default:** `32`.
|
||||
* `maxSessionMemory`{number} Sets the maximum memory that the `Http2Session`
|
||||
is permitted to use. The value is expressed in terms of number of megabytes,
|
||||
e.g. `1` equal 1 megabyte. The minimum value allowed is `1`. This is a
|
||||
@@ -2154,6 +2158,9 @@ server.listen(80);
|
||||
<!-- YAML
|
||||
added: v8.4.0
|
||||
changes:
|
||||
+ - version: REPLACEME
|
||||
+ pr-url: https://github.com/nodejs-private/node-private/pull/204
|
||||
+ description: Added `maxSettings` option with a default of 32.
|
||||
- version: v8.9.3
|
||||
pr-url: https://github.com/nodejs/node/pull/17105
|
||||
description: Added the `maxOutstandingPings` option with a default limit of
|
||||
@@ -2168,6 +2175,8 @@ changes:
|
||||
* `options` {Object}
|
||||
* `maxDeflateDynamicTableSize` {number} Sets the maximum dynamic table size
|
||||
for deflating header fields. **Default:** `4Kib`.
|
||||
+ * `maxSettings` {number} Sets the maximum number of settings entries per
|
||||
+ `SETTINGS` frame. The minimum value allowed is `1`. **Default:** `32`.
|
||||
* `maxSessionMemory`{number} Sets the maximum memory that the `Http2Session`
|
||||
is permitted to use. The value is expressed in terms of number of megabytes,
|
||||
e.g. `1` equal 1 megabyte. The minimum value allowed is `1`.
|
||||
diff --git a/lib/internal/http2/util.js b/lib/internal/http2/util.js
|
||||
index 9cc2a30897b6aed9760b619f98d518fc6ee3ed2a..69a9ea2c64158d26362f6df39e146bcdd4b0dc43 100644
|
||||
--- a/lib/internal/http2/util.js
|
||||
+++ b/lib/internal/http2/util.js
|
||||
@@ -194,7 +194,8 @@ const IDX_OPTIONS_MAX_HEADER_LIST_PAIRS = 5;
|
||||
const IDX_OPTIONS_MAX_OUTSTANDING_PINGS = 6;
|
||||
const IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS = 7;
|
||||
const IDX_OPTIONS_MAX_SESSION_MEMORY = 8;
|
||||
-const IDX_OPTIONS_FLAGS = 9;
|
||||
+const IDX_OPTIONS_MAX_SETTINGS = 9;
|
||||
+const IDX_OPTIONS_FLAGS = 10;
|
||||
|
||||
function updateOptionsBuffer(options) {
|
||||
var flags = 0;
|
||||
@@ -243,6 +244,11 @@ function updateOptionsBuffer(options) {
|
||||
optionsBuffer[IDX_OPTIONS_MAX_SESSION_MEMORY] =
|
||||
Math.max(1, options.maxSessionMemory);
|
||||
}
|
||||
+ if (typeof options.maxSettings === 'number') {
|
||||
+ flags |= (1 << IDX_OPTIONS_MAX_SETTINGS);
|
||||
+ optionsBuffer[IDX_OPTIONS_MAX_SETTINGS] =
|
||||
+ Math.max(1, options.maxSettings);
|
||||
+ }
|
||||
optionsBuffer[IDX_OPTIONS_FLAGS] = flags;
|
||||
}
|
||||
|
||||
diff --git a/src/node_http2.cc b/src/node_http2.cc
|
||||
index 358c687768d61682943dbb04ee3bd32c051c321f..cac64a8c885b0363202e7f00b415fe969e4552d3 100644
|
||||
--- a/src/node_http2.cc
|
||||
+++ b/src/node_http2.cc
|
||||
@@ -202,6 +202,12 @@ Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
|
||||
if (flags & (1 << IDX_OPTIONS_MAX_SESSION_MEMORY)) {
|
||||
SetMaxSessionMemory(buffer[IDX_OPTIONS_MAX_SESSION_MEMORY] * 1e6);
|
||||
}
|
||||
+
|
||||
+ if (flags & (1 << IDX_OPTIONS_MAX_SETTINGS)) {
|
||||
+ nghttp2_option_set_max_settings(
|
||||
+ options_,
|
||||
+ static_cast<size_t>(buffer[IDX_OPTIONS_MAX_SETTINGS]));
|
||||
+ }
|
||||
}
|
||||
|
||||
void Http2Session::Http2Settings::Init() {
|
||||
diff --git a/src/node_http2_state.h b/src/node_http2_state.h
|
||||
index 692299a187f60a5e5b7d045b9894abc435a29de8..fd8f1c56607b1457f921382f729abfc6c63bfb0d 100644
|
||||
--- a/src/node_http2_state.h
|
||||
+++ b/src/node_http2_state.h
|
||||
@@ -52,6 +52,7 @@ namespace http2 {
|
||||
IDX_OPTIONS_MAX_OUTSTANDING_PINGS,
|
||||
IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS,
|
||||
IDX_OPTIONS_MAX_SESSION_MEMORY,
|
||||
+ IDX_OPTIONS_MAX_SETTINGS,
|
||||
IDX_OPTIONS_FLAGS
|
||||
};
|
||||
|
||||
diff --git a/test/parallel/test-http2-max-settings.js b/test/parallel/test-http2-max-settings.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2eae223d21bcc7388cb15969b6a3934acc6b3a7f
|
||||
--- /dev/null
|
||||
+++ b/test/parallel/test-http2-max-settings.js
|
||||
@@ -0,0 +1,35 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+if (!common.hasCrypto)
|
||||
+ common.skip('missing crypto');
|
||||
+
|
||||
+const http2 = require('http2');
|
||||
+
|
||||
+const server = http2.createServer({ maxSettings: 1 });
|
||||
+
|
||||
+// TODO(@jasnell): There is still a session event
|
||||
+// emitted on the server side but it will be destroyed
|
||||
+// immediately after creation and there will be no
|
||||
+// stream created.
|
||||
+server.on('session', common.mustCall((session) => {
|
||||
+ session.on('stream', common.mustNotCall());
|
||||
+ session.on('remoteSettings', common.mustNotCall());
|
||||
+}));
|
||||
+server.on('stream', common.mustNotCall());
|
||||
+
|
||||
+server.listen(0, common.mustCall(() => {
|
||||
+ // Specify two settings entries when a max of 1 is allowed.
|
||||
+ // Connection should error immediately.
|
||||
+ const client = http2.connect(
|
||||
+ `http://localhost:${server.address().port}`, {
|
||||
+ settings: {
|
||||
+ // The actual settings values do not matter.
|
||||
+ headerTableSize: 1000,
|
||||
+ enablePush: false,
|
||||
+ } });
|
||||
+
|
||||
+ client.on('error', common.mustCall(() => {
|
||||
+ server.close();
|
||||
+ }));
|
||||
+}));
|
||||
diff --git a/test/parallel/test-http2-util-update-options-buffer.js b/test/parallel/test-http2-util-update-options-buffer.js
|
||||
index d9cfa0784926aeb720fccc28f0c1257bf35ac30e..9587d93d3bcbc84aafa669d2c95841df8bacc010 100644
|
||||
--- a/test/parallel/test-http2-util-update-options-buffer.js
|
||||
+++ b/test/parallel/test-http2-util-update-options-buffer.js
|
||||
@@ -22,7 +22,8 @@ const IDX_OPTIONS_MAX_HEADER_LIST_PAIRS = 5;
|
||||
const IDX_OPTIONS_MAX_OUTSTANDING_PINGS = 6;
|
||||
const IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS = 7;
|
||||
const IDX_OPTIONS_MAX_SESSION_MEMORY = 8;
|
||||
-const IDX_OPTIONS_FLAGS = 9;
|
||||
+const IDX_OPTIONS_MAX_SETTINGS = 9;
|
||||
+const IDX_OPTIONS_FLAGS = 10;
|
||||
|
||||
{
|
||||
updateOptionsBuffer({
|
||||
@@ -34,7 +35,8 @@ const IDX_OPTIONS_FLAGS = 9;
|
||||
maxHeaderListPairs: 6,
|
||||
maxOutstandingPings: 7,
|
||||
maxOutstandingSettings: 8,
|
||||
- maxSessionMemory: 9
|
||||
+ maxSessionMemory: 9,
|
||||
+ maxSettings: 10,
|
||||
});
|
||||
|
||||
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE], 1);
|
||||
@@ -46,6 +48,7 @@ const IDX_OPTIONS_FLAGS = 9;
|
||||
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_PINGS], 7);
|
||||
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS], 8);
|
||||
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_SESSION_MEMORY], 9);
|
||||
+ strictEqual(optionsBuffer[IDX_OPTIONS_MAX_SETTINGS], 10);
|
||||
|
||||
const flags = optionsBuffer[IDX_OPTIONS_FLAGS];
|
||||
|
||||
@@ -57,6 +60,7 @@ const IDX_OPTIONS_FLAGS = 9;
|
||||
ok(flags & (1 << IDX_OPTIONS_MAX_HEADER_LIST_PAIRS));
|
||||
ok(flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_PINGS));
|
||||
ok(flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS));
|
||||
+ ok(flags & (1 << IDX_OPTIONS_MAX_SETTINGS));
|
||||
}
|
||||
|
||||
{
|
||||
125
patches/node/napi_fix_memory_corruption_vulnerability.patch
Normal file
125
patches/node/napi_fix_memory_corruption_vulnerability.patch
Normal file
@@ -0,0 +1,125 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= <tniessen@tnie.de>
|
||||
Date: Mon, 27 Jan 2020 13:38:36 -0400
|
||||
Subject: napi: fix memory corruption vulnerability
|
||||
|
||||
Fixes: https://hackerone.com/reports/784186
|
||||
CVE-ID: CVE-2020-8174
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/195
|
||||
Reviewed-By: Anna Henningsen <anna@addaleax.net>
|
||||
Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
|
||||
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
|
||||
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
|
||||
Reviewed-By: Rich Trott <rtrott@gmail.com>
|
||||
|
||||
diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc
|
||||
index a87af79a8908321a3f080fb32f9afc62695dcf07..a92bdfec2073f3107a170244ab5183c5263a62da 100644
|
||||
--- a/src/js_native_api_v8.cc
|
||||
+++ b/src/js_native_api_v8.cc
|
||||
@@ -2067,7 +2067,7 @@ napi_status napi_get_value_string_latin1(napi_env env,
|
||||
if (!buf) {
|
||||
CHECK_ARG(env, result);
|
||||
*result = val.As<v8::String>()->Length();
|
||||
- } else {
|
||||
+ } else if (bufsize != 0) {
|
||||
int copied =
|
||||
val.As<v8::String>()->WriteOneByte(env->isolate,
|
||||
reinterpret_cast<uint8_t*>(buf),
|
||||
@@ -2079,6 +2079,8 @@ napi_status napi_get_value_string_latin1(napi_env env,
|
||||
if (result != nullptr) {
|
||||
*result = copied;
|
||||
}
|
||||
+ } else if (result != nullptr) {
|
||||
+ *result = 0;
|
||||
}
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
@@ -2106,7 +2108,7 @@ napi_status napi_get_value_string_utf8(napi_env env,
|
||||
if (!buf) {
|
||||
CHECK_ARG(env, result);
|
||||
*result = val.As<v8::String>()->Utf8Length(env->isolate);
|
||||
- } else {
|
||||
+ } else if (bufsize != 0) {
|
||||
int copied = val.As<v8::String>()->WriteUtf8(
|
||||
env->isolate,
|
||||
buf,
|
||||
@@ -2118,6 +2120,8 @@ napi_status napi_get_value_string_utf8(napi_env env,
|
||||
if (result != nullptr) {
|
||||
*result = copied;
|
||||
}
|
||||
+ } else if (result != nullptr) {
|
||||
+ *result = 0;
|
||||
}
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
@@ -2146,7 +2150,7 @@ napi_status napi_get_value_string_utf16(napi_env env,
|
||||
CHECK_ARG(env, result);
|
||||
// V8 assumes UTF-16 length is the same as the number of characters.
|
||||
*result = val.As<v8::String>()->Length();
|
||||
- } else {
|
||||
+ } else if (bufsize != 0) {
|
||||
int copied = val.As<v8::String>()->Write(env->isolate,
|
||||
reinterpret_cast<uint16_t*>(buf),
|
||||
0,
|
||||
@@ -2157,6 +2161,8 @@ napi_status napi_get_value_string_utf16(napi_env env,
|
||||
if (result != nullptr) {
|
||||
*result = copied;
|
||||
}
|
||||
+ } else if (result != nullptr) {
|
||||
+ *result = 0;
|
||||
}
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
diff --git a/test/js-native-api/test_string/test.js b/test/js-native-api/test_string/test.js
|
||||
index 1be34212a11c3f163e4b5c444c5320afd09976a5..b03cd0b361204466c673473d2d46dfde31857272 100644
|
||||
--- a/test/js-native-api/test_string/test.js
|
||||
+++ b/test/js-native-api/test_string/test.js
|
||||
@@ -81,3 +81,5 @@ assert.throws(() => {
|
||||
assert.throws(() => {
|
||||
test_string.TestLargeUtf16();
|
||||
}, /^Error: Invalid argument$/);
|
||||
+
|
||||
+test_string.TestMemoryCorruption(' '.repeat(64 * 1024));
|
||||
diff --git a/test/js-native-api/test_string/test_string.c b/test/js-native-api/test_string/test_string.c
|
||||
index 471678c251677afc81b9c14e47fa5a278d4d696b..e840feeacf2110e330e56fc2d47b0132eb0efc6a 100644
|
||||
--- a/test/js-native-api/test_string/test_string.c
|
||||
+++ b/test/js-native-api/test_string/test_string.c
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <limits.h> // INT_MAX
|
||||
+#include <string.h>
|
||||
#include <js_native_api.h>
|
||||
#include "../common.h"
|
||||
|
||||
@@ -244,6 +245,24 @@ static napi_value TestLargeUtf16(napi_env env, napi_callback_info info) {
|
||||
return output;
|
||||
}
|
||||
|
||||
+static napi_value TestMemoryCorruption(napi_env env, napi_callback_info info) {
|
||||
+ size_t argc = 1;
|
||||
+ napi_value args[1];
|
||||
+ NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
+
|
||||
+ NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
|
||||
+
|
||||
+ char buf[10] = { 0 };
|
||||
+ NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], buf, 0, NULL));
|
||||
+
|
||||
+ char zero[10] = { 0 };
|
||||
+ if (memcmp(buf, zero, sizeof(buf)) != 0) {
|
||||
+ NAPI_CALL(env, napi_throw_error(env, NULL, "Buffer overwritten"));
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
EXTERN_C_START
|
||||
napi_value Init(napi_env env, napi_value exports) {
|
||||
napi_property_descriptor properties[] = {
|
||||
@@ -258,6 +277,7 @@ napi_value Init(napi_env env, napi_value exports) {
|
||||
DECLARE_NAPI_PROPERTY("TestLargeUtf8", TestLargeUtf8),
|
||||
DECLARE_NAPI_PROPERTY("TestLargeLatin1", TestLargeLatin1),
|
||||
DECLARE_NAPI_PROPERTY("TestLargeUtf16", TestLargeUtf16),
|
||||
+ DECLARE_NAPI_PROPERTY("TestMemoryCorruption", TestMemoryCorruption),
|
||||
};
|
||||
|
||||
NAPI_CALL(env, napi_define_properties(
|
||||
201
patches/node/tls_emit_session_after_verifying_certificate.patch
Normal file
201
patches/node/tls_emit_session_after_verifying_certificate.patch
Normal file
@@ -0,0 +1,201 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Fedor Indutny <fedor@indutny.com>
|
||||
Date: Tue, 17 Mar 2020 20:51:38 -0700
|
||||
Subject: tls: emit `session` after verifying certificate
|
||||
|
||||
Prior to this patch `session` event was emitted after `secure` event on
|
||||
TLSSocket, but before `secureConnect` event. This is problematic for
|
||||
`https.Agent` because it must cache session only after verifying the
|
||||
remote peer's certificate.
|
||||
|
||||
Connecting to a server that presents an invalid certificate resulted
|
||||
in the session being cached after the handshake with the server and
|
||||
evicted right after a certifiate validation error and socket's
|
||||
destruction. A request initiated during this narrow window would pick
|
||||
the faulty session, send it to the malicious server and skip the
|
||||
verification of the server's certificate.
|
||||
|
||||
Fixes: https://hackerone.com/reports/811502
|
||||
CVE-ID: CVE-2020-8172
|
||||
PR-URL: https://github.com/nodejs-private/node-private/pull/200
|
||||
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
|
||||
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
|
||||
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
|
||||
|
||||
diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js
|
||||
index 9c3fe656a7ce806381bc18a33102820b7967d6e5..6c124e7223e567ec3e0323938fabe7b54c9f4b76 100644
|
||||
--- a/lib/_tls_wrap.js
|
||||
+++ b/lib/_tls_wrap.js
|
||||
@@ -67,6 +67,8 @@ const kHandshakeTimeout = Symbol('handshake-timeout');
|
||||
const kRes = Symbol('res');
|
||||
const kSNICallback = Symbol('snicallback');
|
||||
const kEnableTrace = Symbol('enableTrace');
|
||||
+const kPendingSession = Symbol('pendingSession');
|
||||
+const kIsVerified = Symbol('verified');
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
@@ -250,7 +252,11 @@ function requestOCSPDone(socket) {
|
||||
function onnewsessionclient(sessionId, session) {
|
||||
debug('client emit session');
|
||||
const owner = this[owner_symbol];
|
||||
- owner.emit('session', session);
|
||||
+ if (owner[kIsVerified]) {
|
||||
+ owner.emit('session', session);
|
||||
+ } else {
|
||||
+ owner[kPendingSession] = session;
|
||||
+ }
|
||||
}
|
||||
|
||||
function onnewsession(sessionId, session) {
|
||||
@@ -388,6 +394,8 @@ function TLSSocket(socket, opts) {
|
||||
this.authorized = false;
|
||||
this.authorizationError = null;
|
||||
this[kRes] = null;
|
||||
+ this[kIsVerified] = false;
|
||||
+ this[kPendingSession] = null;
|
||||
|
||||
var wrap;
|
||||
if ((socket instanceof net.Socket && socket._handle) || !socket) {
|
||||
@@ -557,6 +565,8 @@ TLSSocket.prototype._destroySSL = function _destroySSL() {
|
||||
this.ssl._secureContext.context = null;
|
||||
}
|
||||
this.ssl = null;
|
||||
+ this[kPendingSession] = null;
|
||||
+ this[kIsVerified] = false;
|
||||
};
|
||||
|
||||
// Constructor guts, arbitrarily factored out.
|
||||
@@ -1350,6 +1360,12 @@ function onConnectSecure() {
|
||||
this.emit('secureConnect');
|
||||
}
|
||||
|
||||
+ this[kIsVerified] = true;
|
||||
+ const session = this[kPendingSession];
|
||||
+ this[kPendingSession] = null;
|
||||
+ if (session)
|
||||
+ this.emit('session', session);
|
||||
+
|
||||
this.removeListener('end', onConnectEnd);
|
||||
}
|
||||
|
||||
diff --git a/test/parallel/test-https-agent-session-injection.js b/test/parallel/test-https-agent-session-injection.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..cb9358b1b1700925e893fa9680fc734b35fb699c
|
||||
--- /dev/null
|
||||
+++ b/test/parallel/test-https-agent-session-injection.js
|
||||
@@ -0,0 +1,59 @@
|
||||
+'use strict';
|
||||
+const common = require('../common');
|
||||
+const assert = require('assert');
|
||||
+
|
||||
+if (!common.hasCrypto)
|
||||
+ common.skip('missing crypto');
|
||||
+
|
||||
+const https = require('https');
|
||||
+const fixtures = require('../common/fixtures');
|
||||
+
|
||||
+const options = {
|
||||
+ key: fixtures.readKey('agent1-key.pem'),
|
||||
+
|
||||
+ // NOTE: Certificate Common Name is 'agent1'
|
||||
+ cert: fixtures.readKey('agent1-cert.pem'),
|
||||
+
|
||||
+ // NOTE: TLS 1.3 creates new session ticket **after** handshake so
|
||||
+ // `getSession()` output will be different even if the session was reused
|
||||
+ // during the handshake.
|
||||
+ secureProtocol: 'TLSv1_2_method'
|
||||
+};
|
||||
+
|
||||
+const ca = [ fixtures.readKey('ca1-cert.pem') ];
|
||||
+
|
||||
+const server = https.createServer(options, function(req, res) {
|
||||
+ res.end('ok');
|
||||
+}).listen(0, common.mustCall(function() {
|
||||
+ const port = this.address().port;
|
||||
+
|
||||
+ const req = https.get({
|
||||
+ port,
|
||||
+ path: '/',
|
||||
+ ca,
|
||||
+ servername: 'nodejs.org',
|
||||
+ }, common.mustNotCall(() => {}));
|
||||
+
|
||||
+ req.on('error', common.mustCall((err) => {
|
||||
+ assert.strictEqual(
|
||||
+ err.message,
|
||||
+ 'Hostname/IP does not match certificate\'s altnames: ' +
|
||||
+ 'Host: nodejs.org. is not cert\'s CN: agent1');
|
||||
+
|
||||
+ const second = https.get({
|
||||
+ port,
|
||||
+ path: '/',
|
||||
+ ca,
|
||||
+ servername: 'nodejs.org',
|
||||
+ }, common.mustNotCall(() => {}));
|
||||
+
|
||||
+ second.on('error', common.mustCall((err) => {
|
||||
+ server.close();
|
||||
+
|
||||
+ assert.strictEqual(
|
||||
+ err.message,
|
||||
+ 'Hostname/IP does not match certificate\'s altnames: ' +
|
||||
+ 'Host: nodejs.org. is not cert\'s CN: agent1');
|
||||
+ }));
|
||||
+ }));
|
||||
+}));
|
||||
diff --git a/test/parallel/test-tls-secure-session.js b/test/parallel/test-tls-secure-session.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b4b9638a2ccc7a27f63285f42e825fbf342e435d
|
||||
--- /dev/null
|
||||
+++ b/test/parallel/test-tls-secure-session.js
|
||||
@@ -0,0 +1,46 @@
|
||||
+'use strict';
|
||||
+const common = require('../common');
|
||||
+if (!common.hasCrypto)
|
||||
+ common.skip('missing crypto');
|
||||
+const fixtures = require('../common/fixtures');
|
||||
+const assert = require('assert');
|
||||
+const tls = require('tls');
|
||||
+
|
||||
+const options = {
|
||||
+ key: fixtures.readKey('agent1-key.pem'),
|
||||
+
|
||||
+ // NOTE: Certificate Common Name is 'agent1'
|
||||
+ cert: fixtures.readKey('agent1-cert.pem'),
|
||||
+
|
||||
+ // NOTE: TLS 1.3 creates new session ticket **after** handshake so
|
||||
+ // `getSession()` output will be different even if the session was reused
|
||||
+ // during the handshake.
|
||||
+ secureProtocol: 'TLSv1_2_method'
|
||||
+};
|
||||
+
|
||||
+const server = tls.createServer(options, common.mustCall((socket) => {
|
||||
+ socket.end();
|
||||
+})).listen(0, common.mustCall(() => {
|
||||
+ let connected = false;
|
||||
+ let session = null;
|
||||
+
|
||||
+ const client = tls.connect({
|
||||
+ rejectUnauthorized: false,
|
||||
+ port: server.address().port,
|
||||
+ }, common.mustCall(() => {
|
||||
+ assert(!connected);
|
||||
+ assert(!session);
|
||||
+
|
||||
+ connected = true;
|
||||
+ }));
|
||||
+
|
||||
+ client.on('session', common.mustCall((newSession) => {
|
||||
+ assert(connected);
|
||||
+ assert(!session);
|
||||
+
|
||||
+ session = newSession;
|
||||
+
|
||||
+ client.end();
|
||||
+ server.close();
|
||||
+ }));
|
||||
+}));
|
||||
1
patches/usrsctp/.patches
Normal file
1
patches/usrsctp/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-e89fe66d0473.patch
|
||||
57
patches/usrsctp/cherry-pick-e89fe66d0473.patch
Normal file
57
patches/usrsctp/cherry-pick-e89fe66d0473.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Tuexen <tuexen@fh-muenster.de>
|
||||
Date: Fri, 10 Apr 2020 00:43:45 +0000
|
||||
Subject: Improve input validation when processing AUTH chunks
|
||||
|
||||
Cherry picked from:
|
||||
https://chromium.googlesource.com/external/github.com/sctplab/usrsctp/+/b218e8957d7af0b07ee3ca74caded05ada8d1df9
|
||||
https://chromium.googlesource.com/external/github.com/sctplab/usrsctp/+/e89fe66d04735dcfc6bfda1648fbe68008da6277
|
||||
|
||||
Bug: 1073602
|
||||
|
||||
diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c
|
||||
index c62bb8506dc0fb86112f35e0b66d08c198e8f9bd..4e53dfb27ec597a8f6ac99c329bc80b9d7306836 100755
|
||||
--- a/usrsctplib/netinet/sctp_input.c
|
||||
+++ b/usrsctplib/netinet/sctp_input.c
|
||||
@@ -2178,7 +2178,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
|
||||
int init_offset, initack_offset, initack_limit;
|
||||
int retval;
|
||||
int error = 0;
|
||||
- uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
|
||||
+ uint8_t auth_chunk_buf[SCTP_CHUNK_BUFFER_SIZE];
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
struct socket *so;
|
||||
|
||||
@@ -2373,8 +2373,11 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
|
||||
if (auth_skipped) {
|
||||
struct sctp_auth_chunk *auth;
|
||||
|
||||
- auth = (struct sctp_auth_chunk *)
|
||||
- sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf);
|
||||
+ if (auth_len <= SCTP_CHUNK_BUFFER_SIZE) {
|
||||
+ auth = (struct sctp_auth_chunk *)sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf);
|
||||
+ } else {
|
||||
+ auth = NULL;
|
||||
+ }
|
||||
if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) {
|
||||
/* auth HMAC failed, dump the assoc and packet */
|
||||
SCTPDBG(SCTP_DEBUG_AUTH1,
|
||||
@@ -4846,11 +4849,13 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
|
||||
if (auth_skipped && (stcb != NULL)) {
|
||||
struct sctp_auth_chunk *auth;
|
||||
|
||||
- auth = (struct sctp_auth_chunk *)
|
||||
- sctp_m_getptr(m, auth_offset,
|
||||
- auth_len, chunk_buf);
|
||||
- got_auth = 1;
|
||||
- auth_skipped = 0;
|
||||
+ if (auth_len <= SCTP_CHUNK_BUFFER_SIZE) {
|
||||
+ auth = (struct sctp_auth_chunk *)sctp_m_getptr(m, auth_offset, auth_len, chunk_buf);
|
||||
+ got_auth = 1;
|
||||
+ auth_skipped = 0;
|
||||
+ } else {
|
||||
+ auth = NULL;
|
||||
+ }
|
||||
if ((auth == NULL) || sctp_handle_auth(stcb, auth, m,
|
||||
auth_offset)) {
|
||||
/* auth HMAC failed so dump it */
|
||||
@@ -10,3 +10,6 @@ revert_cleanup_switch_offset_of_to_offsetof_where_possible.patch
|
||||
objects_fix_memory_leak_in_prototypeusers_add.patch
|
||||
fix_build_deprecated_attirbute_for_older_msvc_versions.patch
|
||||
use_context_of_then_function_for_promiseresolvethenablejob.patch
|
||||
merged_regexp_reserve_space_for_all_registers_in_interpreter.patch
|
||||
cherry-pick-d4ddf645c3ca.patch
|
||||
turn_some_dchecks_into_checks_in_schedule_methods.patch
|
||||
|
||||
30
patches/v8/cherry-pick-d4ddf645c3ca.patch
Normal file
30
patches/v8/cherry-pick-d4ddf645c3ca.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Tue, 5 May 2020 14:19:52 +0200
|
||||
Subject: fix bug in DeadCodeElimination
|
||||
|
||||
Bug: chromium:1076708
|
||||
Change-Id: I88a5eae0e562e32f1915deff3c4150ec4be14c6c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2181266
|
||||
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
|
||||
Commit-Queue: Georg Neis <neis@chromium.org>
|
||||
Auto-Submit: Tobias Tebbi <tebbi@chromium.org>
|
||||
Reviewed-by: Georg Neis <neis@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#67564}
|
||||
|
||||
diff --git a/src/compiler/dead-code-elimination.cc b/src/compiler/dead-code-elimination.cc
|
||||
index f39e6cabfbeb3e4fdd95a36d619c14adb6d5d956..bab6b7b506e368b7b4219015cc34a84b156ccd2d 100644
|
||||
--- a/src/compiler/dead-code-elimination.cc
|
||||
+++ b/src/compiler/dead-code-elimination.cc
|
||||
@@ -317,7 +317,10 @@ Reduction DeadCodeElimination::ReduceDeoptimizeOrReturnOrTerminateOrTailCall(
|
||||
node->opcode() == IrOpcode::kTailCall);
|
||||
Reduction reduction = PropagateDeadControl(node);
|
||||
if (reduction.Changed()) return reduction;
|
||||
- if (FindDeadInput(node) != nullptr) {
|
||||
+ // Terminate nodes are not part of actual control flow, so they should never
|
||||
+ // be replaced with Throw.
|
||||
+ if (node->opcode() != IrOpcode::kTerminate &&
|
||||
+ FindDeadInput(node) != nullptr) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node, 0);
|
||||
Node* control = NodeProperties::GetControlInput(node, 0);
|
||||
if (effect->opcode() != IrOpcode::kUnreachable) {
|
||||
@@ -0,0 +1,81 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakob Gruber <jgruber@chromium.org>
|
||||
Date: Mon, 6 Apr 2020 15:48:53 +0200
|
||||
Subject: Merged: [regexp] Reserve space for all registers in interpreter
|
||||
|
||||
This is a minimal version of https://crrev.com/c/2135642 intended for
|
||||
backmerges.
|
||||
|
||||
Ensure that the interpreter has space for all required registers.
|
||||
|
||||
(cherry picked from commit 30658b6b1b672e535e6046fa84674882e29b2279)
|
||||
|
||||
Tbr: leszeks@chromium.org
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Treechecks: true
|
||||
Bug: chromium:1067270
|
||||
Change-Id: Iefd016b4845fb8698d1e0ef5f6a03df0e66aa576
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2137403
|
||||
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#67013}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2144052
|
||||
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/8.1@{#61}
|
||||
Cr-Branched-From: a4dcd39d521d14c4b1cac020812e44ee04a7f244-refs/heads/8.1.307@{#1}
|
||||
Cr-Branched-From: f22c213304ec3542df87019aed0909b7dafeaa93-refs/heads/master@{#66031}
|
||||
|
||||
diff --git a/src/regexp/regexp-interpreter.cc b/src/regexp/regexp-interpreter.cc
|
||||
index adea0cf7c0951bd707cfd05dc3b69a34b55efa77..c0d4435d380f880f2d6890d3ac783944518560e2 100644
|
||||
--- a/src/regexp/regexp-interpreter.cc
|
||||
+++ b/src/regexp/regexp-interpreter.cc
|
||||
@@ -1045,8 +1045,29 @@ IrregexpInterpreter::Result IrregexpInterpreter::MatchForCallFromJs(
|
||||
return IrregexpInterpreter::RETRY;
|
||||
}
|
||||
|
||||
- return Match(isolate, regexp_obj, subject_string, registers, registers_length,
|
||||
- start_position, call_origin);
|
||||
+ // In generated code, registers are allocated on the stack. The given
|
||||
+ // `registers` argument is only guaranteed to hold enough space for permanent
|
||||
+ // registers (i.e. for captures), and not for temporary registers used only
|
||||
+ // during matcher execution. We match that behavior in the interpreter by
|
||||
+ // using a SmallVector as internal register storage.
|
||||
+ static constexpr int kBaseRegisterArraySize = 64; // Arbitrary.
|
||||
+ const int internal_register_count =
|
||||
+ Smi::ToInt(regexp_obj.DataAt(JSRegExp::kIrregexpMaxRegisterCountIndex));
|
||||
+ base::SmallVector<int, kBaseRegisterArraySize> internal_registers(
|
||||
+ internal_register_count);
|
||||
+
|
||||
+ Result result =
|
||||
+ Match(isolate, regexp_obj, subject_string, internal_registers.data(),
|
||||
+ internal_register_count, start_position, call_origin);
|
||||
+
|
||||
+ // Copy capture registers to the output array.
|
||||
+ if (result == IrregexpInterpreter::SUCCESS) {
|
||||
+ CHECK_GE(internal_registers.size(), registers_length);
|
||||
+ MemCopy(registers, internal_registers.data(),
|
||||
+ registers_length * sizeof(registers[0]));
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
}
|
||||
|
||||
IrregexpInterpreter::Result IrregexpInterpreter::MatchForCallFromRuntime(
|
||||
diff --git a/test/mjsunit/regress/regress-1067270.js b/test/mjsunit/regress/regress-1067270.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..1c6eddf505aa55e622df9d7116ea7fbb2f516713
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/regress/regress-1067270.js
|
||||
@@ -0,0 +1,11 @@
|
||||
+// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+//
|
||||
+// Flags: --allow-natives-syntax
|
||||
+
|
||||
+const needle = Array(1802).join(" +") + Array(16884).join("A");
|
||||
+const string = "A";
|
||||
+
|
||||
+assertEquals(string.search(needle), -1);
|
||||
+assertEquals(string.search(needle), -1);
|
||||
@@ -0,0 +1,108 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Georg Neis <neis@chromium.org>
|
||||
Date: Tue, 5 May 2020 20:11:02 +0200
|
||||
Subject: Turn some DCHECKs into CHECKs in Schedule methods
|
||||
|
||||
Bug: chromium:1076708
|
||||
Change-Id: I7f065791310606e11fe89936a36f0fe7cb0d38e7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2182639
|
||||
Auto-Submit: Georg Neis <neis@chromium.org>
|
||||
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
|
||||
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#67576}
|
||||
|
||||
diff --git a/src/compiler/schedule.cc b/src/compiler/schedule.cc
|
||||
index 8bdcef511b6ad9e42e54661e8b676170ac6ebe69..cc3243cb2e1b2080c208f8d4c72e1f450e33cf7c 100644
|
||||
--- a/src/compiler/schedule.cc
|
||||
+++ b/src/compiler/schedule.cc
|
||||
@@ -218,7 +218,7 @@ void Schedule::AddNode(BasicBlock* block, Node* node) {
|
||||
}
|
||||
|
||||
void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
block->set_control(BasicBlock::kGoto);
|
||||
AddSuccessor(block, succ);
|
||||
}
|
||||
@@ -243,7 +243,7 @@ bool IsPotentiallyThrowingCall(IrOpcode::Value opcode) {
|
||||
|
||||
void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
|
||||
BasicBlock* exception_block) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
DCHECK(IsPotentiallyThrowingCall(call->opcode()));
|
||||
block->set_control(BasicBlock::kCall);
|
||||
AddSuccessor(block, success_block);
|
||||
@@ -253,7 +253,7 @@ void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
|
||||
|
||||
void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
|
||||
BasicBlock* fblock) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
|
||||
block->set_control(BasicBlock::kBranch);
|
||||
AddSuccessor(block, tblock);
|
||||
@@ -263,7 +263,7 @@ void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
|
||||
|
||||
void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
|
||||
size_t succ_count) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
|
||||
block->set_control(BasicBlock::kSwitch);
|
||||
for (size_t index = 0; index < succ_count; ++index) {
|
||||
@@ -273,28 +273,28 @@ void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
|
||||
}
|
||||
|
||||
void Schedule::AddTailCall(BasicBlock* block, Node* input) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
block->set_control(BasicBlock::kTailCall);
|
||||
SetControlInput(block, input);
|
||||
if (block != end()) AddSuccessor(block, end());
|
||||
}
|
||||
|
||||
void Schedule::AddReturn(BasicBlock* block, Node* input) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
block->set_control(BasicBlock::kReturn);
|
||||
SetControlInput(block, input);
|
||||
if (block != end()) AddSuccessor(block, end());
|
||||
}
|
||||
|
||||
void Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
block->set_control(BasicBlock::kDeoptimize);
|
||||
SetControlInput(block, input);
|
||||
if (block != end()) AddSuccessor(block, end());
|
||||
}
|
||||
|
||||
void Schedule::AddThrow(BasicBlock* block, Node* input) {
|
||||
- DCHECK_EQ(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, block->control());
|
||||
block->set_control(BasicBlock::kThrow);
|
||||
SetControlInput(block, input);
|
||||
if (block != end()) AddSuccessor(block, end());
|
||||
@@ -302,8 +302,8 @@ void Schedule::AddThrow(BasicBlock* block, Node* input) {
|
||||
|
||||
void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
|
||||
BasicBlock* tblock, BasicBlock* fblock) {
|
||||
- DCHECK_NE(BasicBlock::kNone, block->control());
|
||||
- DCHECK_EQ(BasicBlock::kNone, end->control());
|
||||
+ CHECK_NE(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, end->control());
|
||||
end->set_control(block->control());
|
||||
block->set_control(BasicBlock::kBranch);
|
||||
MoveSuccessors(block, end);
|
||||
@@ -317,8 +317,8 @@ void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
|
||||
|
||||
void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
|
||||
BasicBlock** succ_blocks, size_t succ_count) {
|
||||
- DCHECK_NE(BasicBlock::kNone, block->control());
|
||||
- DCHECK_EQ(BasicBlock::kNone, end->control());
|
||||
+ CHECK_NE(BasicBlock::kNone, block->control());
|
||||
+ CHECK_EQ(BasicBlock::kNone, end->control());
|
||||
end->set_control(block->control());
|
||||
block->set_control(BasicBlock::kSwitch);
|
||||
MoveSuccessors(block, end);
|
||||
@@ -93,17 +93,14 @@ int NodeMain(int argc, char* argv[]) {
|
||||
node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform());
|
||||
CHECK_NE(nullptr, isolate_data);
|
||||
|
||||
node::Environment* env =
|
||||
node::CreateEnvironment(isolate_data, gin_env.context(), argc, argv,
|
||||
exec_argc, exec_argv, false);
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
isolate_data, gin_env.context(), argc, argv, exec_argc, exec_argv);
|
||||
CHECK_NE(nullptr, env);
|
||||
|
||||
// Enable support for v8 inspector.
|
||||
NodeDebugger node_debugger(env);
|
||||
node_debugger.Start();
|
||||
|
||||
node::BootstrapEnvironment(env);
|
||||
|
||||
gin_helper::Dictionary process(gin_env.isolate(), env->process_object());
|
||||
|
||||
gin_env.isolate()->SetAllowWasmCodeGenerationCallback(
|
||||
|
||||
@@ -1415,8 +1415,8 @@ void App::BuildPrototype(v8::Isolate* isolate,
|
||||
base::BindRepeating(&Browser::GetVersion, browser))
|
||||
.SetMethod("setVersion",
|
||||
base::BindRepeating(&Browser::SetVersion, browser))
|
||||
.SetMethod("_getName", base::BindRepeating(&Browser::GetName, browser))
|
||||
.SetMethod("_setName", base::BindRepeating(&Browser::SetName, browser))
|
||||
.SetMethod("getName", base::BindRepeating(&Browser::GetName, browser))
|
||||
.SetMethod("setName", base::BindRepeating(&Browser::SetName, browser))
|
||||
.SetMethod("isReady", base::BindRepeating(&Browser::is_ready, browser))
|
||||
.SetMethod("whenReady", base::BindRepeating(&Browser::WhenReady, browser))
|
||||
.SetMethod("addRecentDocument",
|
||||
@@ -1437,20 +1437,15 @@ void App::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod(
|
||||
"getApplicationNameForProtocol",
|
||||
base::BindRepeating(&Browser::GetApplicationNameForProtocol, browser))
|
||||
.SetMethod("_setBadgeCount",
|
||||
.SetMethod("setBadgeCount",
|
||||
base::BindRepeating(&Browser::SetBadgeCount, browser))
|
||||
.SetMethod("_getBadgeCount",
|
||||
.SetMethod("getBadgeCount",
|
||||
base::BindRepeating(&Browser::GetBadgeCount, browser))
|
||||
.SetMethod("getLoginItemSettings", &App::GetLoginItemSettings)
|
||||
.SetMethod("setLoginItemSettings",
|
||||
base::BindRepeating(&Browser::SetLoginItemSettings, browser))
|
||||
.SetMethod("isEmojiPanelSupported",
|
||||
base::BindRepeating(&Browser::IsEmojiPanelSupported, browser))
|
||||
.SetProperty("badgeCount",
|
||||
base::BindRepeating(&Browser::GetBadgeCount, browser),
|
||||
base::BindRepeating(&Browser::SetBadgeCount, browser))
|
||||
.SetProperty("name", base::BindRepeating(&Browser::GetName, browser),
|
||||
base::BindRepeating(&Browser::SetName, browser))
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("hide", base::BindRepeating(&Browser::Hide, browser))
|
||||
.SetMethod("show", base::BindRepeating(&Browser::Show, browser))
|
||||
@@ -1475,9 +1470,6 @@ void App::BuildPrototype(v8::Isolate* isolate,
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
.SetMethod("showEmojiPanel",
|
||||
base::BindRepeating(&Browser::ShowEmojiPanel, browser))
|
||||
.SetProperty("accessibilitySupportEnabled",
|
||||
&App::IsAccessibilitySupportEnabled,
|
||||
&App::SetAccessibilitySupportEnabled)
|
||||
#endif
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("setUserTasks",
|
||||
@@ -1504,9 +1496,9 @@ void App::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("requestSingleInstanceLock", &App::RequestSingleInstanceLock)
|
||||
.SetMethod("releaseSingleInstanceLock", &App::ReleaseSingleInstanceLock)
|
||||
.SetMethod("relaunch", &App::Relaunch)
|
||||
.SetMethod("_isAccessibilitySupportEnabled",
|
||||
.SetMethod("isAccessibilitySupportEnabled",
|
||||
&App::IsAccessibilitySupportEnabled)
|
||||
.SetMethod("_setAccessibilitySupportEnabled",
|
||||
.SetMethod("setAccessibilitySupportEnabled",
|
||||
&App::SetAccessibilitySupportEnabled)
|
||||
.SetMethod("disableHardwareAcceleration",
|
||||
&App::DisableHardwareAcceleration)
|
||||
|
||||
@@ -28,7 +28,9 @@ bool RegisteringMediaKeyForUntrustedClient(const ui::Accelerator& accelerator) {
|
||||
if (base::mac::IsAtLeastOS10_14()) {
|
||||
constexpr ui::KeyboardCode mediaKeys[] = {
|
||||
ui::VKEY_MEDIA_PLAY_PAUSE, ui::VKEY_MEDIA_NEXT_TRACK,
|
||||
ui::VKEY_MEDIA_PREV_TRACK, ui::VKEY_MEDIA_STOP};
|
||||
ui::VKEY_MEDIA_PREV_TRACK, ui::VKEY_MEDIA_STOP,
|
||||
ui::VKEY_VOLUME_UP, ui::VKEY_VOLUME_DOWN,
|
||||
ui::VKEY_VOLUME_MUTE};
|
||||
|
||||
if (std::find(std::begin(mediaKeys), std::end(mediaKeys),
|
||||
accelerator.key_code()) != std::end(mediaKeys)) {
|
||||
@@ -59,7 +61,7 @@ GlobalShortcut::~GlobalShortcut() {
|
||||
void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||
if (accelerator_callback_map_.find(accelerator) ==
|
||||
accelerator_callback_map_.end()) {
|
||||
// This should never occur, because if it does, GlobalGlobalShortcutListener
|
||||
// This should never occur, because if it does, GlobalShortcutListener
|
||||
// notifies us with wrong accelerator.
|
||||
NOTREACHED();
|
||||
return;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "net/http/http_auth_handler_factory.h"
|
||||
#include "net/http/http_auth_preferences.h"
|
||||
#include "net/http/http_cache.h"
|
||||
#include "net/http/http_util.h"
|
||||
#include "services/network/network_service.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "shell/browser/api/electron_api_cookies.h"
|
||||
@@ -548,12 +549,14 @@ v8::Local<v8::Promise> Session::ClearAuthCache() {
|
||||
}
|
||||
|
||||
void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params =
|
||||
network::mojom::HttpAuthDynamicParams::New();
|
||||
auth_dynamic_params->server_allowlist = domains;
|
||||
auth_dynamic_params->enable_negotiate_port =
|
||||
base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
electron::switches::kEnableAuthNegotiatePort);
|
||||
command_line->HasSwitch(electron::switches::kEnableAuthNegotiatePort);
|
||||
auth_dynamic_params->ntlm_v2_enabled =
|
||||
!command_line->HasSwitch(electron::switches::kDisableNTLMv2);
|
||||
content::GetNetworkService()->ConfigureHttpAuthPrefs(
|
||||
std::move(auth_dynamic_params));
|
||||
}
|
||||
@@ -561,9 +564,16 @@ void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
|
||||
void Session::SetUserAgent(const std::string& user_agent,
|
||||
mate::Arguments* args) {
|
||||
browser_context_->SetUserAgent(user_agent);
|
||||
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
|
||||
->GetNetworkContext()
|
||||
->SetUserAgent(user_agent);
|
||||
auto* network_context = content::BrowserContext::GetDefaultStoragePartition(
|
||||
browser_context_.get())
|
||||
->GetNetworkContext();
|
||||
network_context->SetUserAgent(user_agent);
|
||||
|
||||
std::string accept_lang;
|
||||
if (args->GetNext(&accept_lang)) {
|
||||
network_context->SetAcceptLanguage(
|
||||
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang));
|
||||
}
|
||||
}
|
||||
|
||||
std::string Session::GetUserAgent() {
|
||||
|
||||
@@ -100,17 +100,12 @@ void SystemPreferences::BuildPrototype(
|
||||
.SetMethod("removeUserDefault", &SystemPreferences::RemoveUserDefault)
|
||||
.SetMethod("isSwipeTrackingFromScrollEventsEnabled",
|
||||
&SystemPreferences::IsSwipeTrackingFromScrollEventsEnabled)
|
||||
.SetMethod("_getEffectiveAppearance",
|
||||
.SetMethod("getEffectiveAppearance",
|
||||
&SystemPreferences::GetEffectiveAppearance)
|
||||
.SetMethod("_getAppLevelAppearance",
|
||||
.SetMethod("getAppLevelAppearance",
|
||||
&SystemPreferences::GetAppLevelAppearance)
|
||||
.SetMethod("_setAppLevelAppearance",
|
||||
.SetMethod("setAppLevelAppearance",
|
||||
&SystemPreferences::SetAppLevelAppearance)
|
||||
.SetProperty("appLevelAppearance",
|
||||
&SystemPreferences::GetAppLevelAppearance,
|
||||
&SystemPreferences::SetAppLevelAppearance)
|
||||
.SetProperty("effectiveAppearance",
|
||||
&SystemPreferences::GetEffectiveAppearance)
|
||||
.SetMethod("getSystemColor", &SystemPreferences::GetSystemColor)
|
||||
.SetMethod("canPromptTouchID", &SystemPreferences::CanPromptTouchID)
|
||||
.SetMethod("promptTouchID", &SystemPreferences::PromptTouchID)
|
||||
|
||||
@@ -683,10 +683,16 @@ void TopLevelWindow::SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> value) {
|
||||
gin::V8ToString(isolate, object->GetConstructorName()) == "Menu" &&
|
||||
gin::ConvertFromV8(isolate, value, &menu) && !menu.IsEmpty()) {
|
||||
menu_.Reset(isolate, menu.ToV8());
|
||||
window_->SetMenu(menu->model());
|
||||
|
||||
// We only want to update the menu if the menu has a non-zero item count,
|
||||
// or we risk crashes.
|
||||
if (menu->model()->GetItemCount() == 0) {
|
||||
RemoveMenu();
|
||||
} else {
|
||||
window_->SetMenu(menu->model());
|
||||
}
|
||||
} else if (value->IsNull()) {
|
||||
menu_.Reset();
|
||||
window_->SetMenu(nullptr);
|
||||
RemoveMenu();
|
||||
} else {
|
||||
isolate->ThrowException(
|
||||
v8::Exception::TypeError(gin::StringToV8(isolate, "Invalid Menu")));
|
||||
@@ -1124,30 +1130,18 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setSheetOffset", &TopLevelWindow::SetSheetOffset)
|
||||
.SetMethod("moveAbove", &TopLevelWindow::MoveAbove)
|
||||
.SetMethod("moveTop", &TopLevelWindow::MoveTop)
|
||||
.SetMethod("_setResizable", &TopLevelWindow::SetResizable)
|
||||
.SetMethod("_isResizable", &TopLevelWindow::IsResizable)
|
||||
.SetProperty("resizable", &TopLevelWindow::IsResizable,
|
||||
&TopLevelWindow::SetResizable)
|
||||
.SetMethod("_setMovable", &TopLevelWindow::SetMovable)
|
||||
.SetMethod("_isMovable", &TopLevelWindow::IsMovable)
|
||||
.SetProperty("movable", &TopLevelWindow::IsMovable,
|
||||
&TopLevelWindow::SetMovable)
|
||||
.SetMethod("_setMinimizable", &TopLevelWindow::SetMinimizable)
|
||||
.SetMethod("_isMinimizable", &TopLevelWindow::IsMinimizable)
|
||||
.SetProperty("minimizable", &TopLevelWindow::IsMinimizable,
|
||||
&TopLevelWindow::SetMinimizable)
|
||||
.SetMethod("_setMaximizable", &TopLevelWindow::SetMaximizable)
|
||||
.SetMethod("_isMaximizable", &TopLevelWindow::IsMaximizable)
|
||||
.SetProperty("maximizable", &TopLevelWindow::IsMaximizable,
|
||||
&TopLevelWindow::SetMaximizable)
|
||||
.SetMethod("_setFullScreenable", &TopLevelWindow::SetFullScreenable)
|
||||
.SetMethod("_isFullScreenable", &TopLevelWindow::IsFullScreenable)
|
||||
.SetProperty("fullScreenable", &TopLevelWindow::IsFullScreenable,
|
||||
&TopLevelWindow::SetFullScreenable)
|
||||
.SetMethod("_setClosable", &TopLevelWindow::SetClosable)
|
||||
.SetMethod("_isClosable", &TopLevelWindow::IsClosable)
|
||||
.SetProperty("closable", &TopLevelWindow::IsClosable,
|
||||
&TopLevelWindow::SetClosable)
|
||||
.SetMethod("setResizable", &TopLevelWindow::SetResizable)
|
||||
.SetMethod("isResizable", &TopLevelWindow::IsResizable)
|
||||
.SetMethod("setMovable", &TopLevelWindow::SetMovable)
|
||||
.SetMethod("isMovable", &TopLevelWindow::IsMovable)
|
||||
.SetMethod("setMinimizable", &TopLevelWindow::SetMinimizable)
|
||||
.SetMethod("isMinimizable", &TopLevelWindow::IsMinimizable)
|
||||
.SetMethod("setMaximizable", &TopLevelWindow::SetMaximizable)
|
||||
.SetMethod("isMaximizable", &TopLevelWindow::IsMaximizable)
|
||||
.SetMethod("setFullScreenable", &TopLevelWindow::SetFullScreenable)
|
||||
.SetMethod("isFullScreenable", &TopLevelWindow::IsFullScreenable)
|
||||
.SetMethod("setClosable", &TopLevelWindow::SetClosable)
|
||||
.SetMethod("isClosable", &TopLevelWindow::IsClosable)
|
||||
.SetMethod("setAlwaysOnTop", &TopLevelWindow::SetAlwaysOnTop)
|
||||
.SetMethod("isAlwaysOnTop", &TopLevelWindow::IsAlwaysOnTop)
|
||||
.SetMethod("center", &TopLevelWindow::Center)
|
||||
@@ -1220,10 +1214,8 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
&TopLevelWindow::IsExcludedFromShownWindowsMenu,
|
||||
&TopLevelWindow::SetExcludedFromShownWindowsMenu)
|
||||
#endif
|
||||
.SetMethod("_setAutoHideMenuBar", &TopLevelWindow::SetAutoHideMenuBar)
|
||||
.SetMethod("_isMenuBarAutoHide", &TopLevelWindow::IsMenuBarAutoHide)
|
||||
.SetProperty("autoHideMenuBar", &TopLevelWindow::IsMenuBarAutoHide,
|
||||
&TopLevelWindow::SetAutoHideMenuBar)
|
||||
.SetMethod("setAutoHideMenuBar", &TopLevelWindow::SetAutoHideMenuBar)
|
||||
.SetMethod("isMenuBarAutoHide", &TopLevelWindow::IsMenuBarAutoHide)
|
||||
.SetMethod("setMenuBarVisibility", &TopLevelWindow::SetMenuBarVisibility)
|
||||
.SetMethod("isMenuBarVisible", &TopLevelWindow::IsMenuBarVisible)
|
||||
.SetMethod("setAspectRatio", &TopLevelWindow::SetAspectRatio)
|
||||
|
||||
@@ -134,8 +134,6 @@ class JSChunkedDataPipeGetter : public gin::Wrappable<JSChunkedDataPipeGetter>,
|
||||
data_producer_ = std::make_unique<mojo::DataPipeProducer>(std::move(pipe));
|
||||
|
||||
v8::HandleScope handle_scope(isolate_);
|
||||
v8::MicrotasksScope script_scope(isolate_,
|
||||
v8::MicrotasksScope::kRunMicrotasks);
|
||||
auto maybe_wrapper = GetWrapper(isolate_);
|
||||
v8::Local<v8::Value> wrapper;
|
||||
if (!maybe_wrapper.ToLocal(&wrapper)) {
|
||||
@@ -347,6 +345,7 @@ mate::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) {
|
||||
request->attach_same_site_cookies = true;
|
||||
opts.Get("method", &request->method);
|
||||
opts.Get("url", &request->url);
|
||||
opts.Get("referrer", &request->referrer);
|
||||
std::map<std::string, std::string> extra_headers;
|
||||
if (opts.Get("extraHeaders", &extra_headers)) {
|
||||
for (const auto& it : extra_headers) {
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/gfx_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/language_util.h"
|
||||
#include "shell/common/mouse_util.h"
|
||||
#include "shell/common/native_mate_converters/blink_converter.h"
|
||||
#include "shell/common/native_mate_converters/content_converter.h"
|
||||
@@ -520,7 +521,24 @@ void WebContents::InitWithSessionAndOptions(
|
||||
managed_web_contents()->GetView()->SetDelegate(this);
|
||||
|
||||
auto* prefs = web_contents()->GetMutableRendererPrefs();
|
||||
prefs->accept_languages = g_browser_process->GetApplicationLocale();
|
||||
|
||||
// Collect preferred languages from OS and browser process.
|
||||
// accept_languages effects HTTP header, navigator.languages,
|
||||
// and CJK fallback font selection.
|
||||
//
|
||||
// Note that an application locale set to the browser
|
||||
// process might be different with the one set to the preference
|
||||
// list. (e.g. overridden with --lang)
|
||||
std::string accept_languages =
|
||||
g_browser_process->GetApplicationLocale() + ",";
|
||||
for (auto const& language : electron::GetPreferredLanguages()) {
|
||||
if (language == g_browser_process->GetApplicationLocale()) {
|
||||
continue;
|
||||
}
|
||||
accept_languages += language + ",";
|
||||
}
|
||||
accept_languages.pop_back();
|
||||
prefs->accept_languages = accept_languages;
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_WIN)
|
||||
// Update font settings.
|
||||
@@ -2641,10 +2659,8 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("_goForward", &WebContents::GoForward)
|
||||
.SetMethod("_goToOffset", &WebContents::GoToOffset)
|
||||
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
||||
.SetMethod("_setUserAgent", &WebContents::SetUserAgent)
|
||||
.SetMethod("_getUserAgent", &WebContents::GetUserAgent)
|
||||
.SetProperty("userAgent", &WebContents::GetUserAgent,
|
||||
&WebContents::SetUserAgent)
|
||||
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
|
||||
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
|
||||
.SetMethod("savePage", &WebContents::SavePage)
|
||||
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
||||
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
||||
@@ -2655,10 +2671,8 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
|
||||
.SetMethod("inspectElement", &WebContents::InspectElement)
|
||||
.SetMethod("setIgnoreMenuShortcuts", &WebContents::SetIgnoreMenuShortcuts)
|
||||
.SetMethod("_setAudioMuted", &WebContents::SetAudioMuted)
|
||||
.SetMethod("_isAudioMuted", &WebContents::IsAudioMuted)
|
||||
.SetProperty("audioMuted", &WebContents::IsAudioMuted,
|
||||
&WebContents::SetAudioMuted)
|
||||
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
|
||||
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
|
||||
.SetMethod("isCurrentlyAudible", &WebContents::IsCurrentlyAudible)
|
||||
.SetMethod("undo", &WebContents::Undo)
|
||||
.SetMethod("redo", &WebContents::Redo)
|
||||
@@ -2689,20 +2703,14 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("startPainting", &WebContents::StartPainting)
|
||||
.SetMethod("stopPainting", &WebContents::StopPainting)
|
||||
.SetMethod("isPainting", &WebContents::IsPainting)
|
||||
.SetMethod("_setFrameRate", &WebContents::SetFrameRate)
|
||||
.SetMethod("_getFrameRate", &WebContents::GetFrameRate)
|
||||
.SetProperty("frameRate", &WebContents::GetFrameRate,
|
||||
&WebContents::SetFrameRate)
|
||||
.SetMethod("setFrameRate", &WebContents::SetFrameRate)
|
||||
.SetMethod("getFrameRate", &WebContents::GetFrameRate)
|
||||
#endif
|
||||
.SetMethod("invalidate", &WebContents::Invalidate)
|
||||
.SetMethod("_setZoomLevel", &WebContents::SetZoomLevel)
|
||||
.SetMethod("_getZoomLevel", &WebContents::GetZoomLevel)
|
||||
.SetProperty("zoomLevel", &WebContents::GetZoomLevel,
|
||||
&WebContents::SetZoomLevel)
|
||||
.SetMethod("_setZoomFactor", &WebContents::SetZoomFactor)
|
||||
.SetMethod("_getZoomFactor", &WebContents::GetZoomFactor)
|
||||
.SetProperty("zoomFactor", &WebContents::GetZoomFactor,
|
||||
&WebContents::SetZoomFactor)
|
||||
.SetMethod("setZoomLevel", &WebContents::SetZoomLevel)
|
||||
.SetMethod("getZoomLevel", &WebContents::GetZoomLevel)
|
||||
.SetMethod("setZoomFactor", &WebContents::SetZoomFactor)
|
||||
.SetMethod("getZoomFactor", &WebContents::GetZoomFactor)
|
||||
.SetMethod("getType", &WebContents::GetType)
|
||||
.SetMethod("_getPreloadPaths", &WebContents::GetPreloadPaths)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
|
||||
@@ -54,7 +54,7 @@ class Browser : public WindowListObserver {
|
||||
void Shutdown();
|
||||
|
||||
// Focus the application.
|
||||
void Focus();
|
||||
void Focus(mate::Arguments* args);
|
||||
|
||||
// Returns the version of the executable (or bundle).
|
||||
std::string GetVersion() const;
|
||||
|
||||
@@ -84,7 +84,7 @@ bool SetDefaultWebClient(const std::string& protocol) {
|
||||
return ran_ok && exit_code == EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void Browser::Focus() {
|
||||
void Browser::Focus(mate::Arguments* args) {
|
||||
// Focus on the first visible window.
|
||||
for (auto* const window : WindowList::GetWindows()) {
|
||||
if (window->IsVisible()) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user