mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21258845f0 | ||
|
|
96bcadd290 | ||
|
|
ee1030e044 | ||
|
|
11d1bfa071 | ||
|
|
131be8cefd | ||
|
|
61b6ede68c | ||
|
|
c1c02e172e | ||
|
|
8c399548b5 | ||
|
|
118f8c4b88 | ||
|
|
8210faeb09 | ||
|
|
1c927dbbe8 | ||
|
|
56cb0d52b9 | ||
|
|
083913c738 | ||
|
|
b164a0506d | ||
|
|
494c3f8c04 | ||
|
|
f5321177e7 | ||
|
|
58f180201e | ||
|
|
767f98b213 | ||
|
|
c8da588479 | ||
|
|
d9538c7fd4 | ||
|
|
c51aec4911 | ||
|
|
73d9a14c6f | ||
|
|
02f9078c92 | ||
|
|
9a77e2b07b | ||
|
|
e2e85fb8fc | ||
|
|
4e68a33c60 | ||
|
|
6e1e2399c7 | ||
|
|
99413641d1 | ||
|
|
ab0f3fd8ff | ||
|
|
9ce16a44db | ||
|
|
f551883fb8 | ||
|
|
3ec9f58c8e | ||
|
|
a52eaeb6e1 | ||
|
|
08ce5bbd33 | ||
|
|
488fbfe469 | ||
|
|
705a9a39c4 | ||
|
|
d98b2a760c | ||
|
|
e48e899807 | ||
|
|
d84ef8bfb3 | ||
|
|
a8cdc21731 | ||
|
|
fc06c55bc0 | ||
|
|
f459315060 | ||
|
|
a4197c367d | ||
|
|
b11025a539 | ||
|
|
ede6cb7edf | ||
|
|
961ce1ded1 | ||
|
|
c6e2cca8bc | ||
|
|
f1f9a76579 | ||
|
|
1f21dfd838 | ||
|
|
5ba3bba53e | ||
|
|
f740afcc67 | ||
|
|
822fcfe030 | ||
|
|
85e4bffabd | ||
|
|
545aba8e16 | ||
|
|
574bd21696 | ||
|
|
bb149b0e93 | ||
|
|
a42ddbc98d | ||
|
|
14ae30aa9b | ||
|
|
e3a78f62b5 | ||
|
|
5bef67a468 | ||
|
|
a6f26b5788 | ||
|
|
54a7f6d865 | ||
|
|
de7ec574e2 | ||
|
|
bfa682dfa3 | ||
|
|
4baa634d7b | ||
|
|
3822bc8432 | ||
|
|
1acec5d48b | ||
|
|
31e8f75795 | ||
|
|
905bc4a946 | ||
|
|
9a48f2322f | ||
|
|
088bc334f0 | ||
|
|
8836c814b9 | ||
|
|
5b6e117041 | ||
|
|
845716019a | ||
|
|
308470c98d | ||
|
|
9a8ebbb471 | ||
|
|
c90f41d0c4 | ||
|
|
f275211555 | ||
|
|
5b04b64397 | ||
|
|
066f5136d5 | ||
|
|
c0cc008368 | ||
|
|
b8e7bcb621 | ||
|
|
170fb689c0 | ||
|
|
15b11599a2 | ||
|
|
621cc90674 | ||
|
|
7d791b7f46 | ||
|
|
4e61bc3cfd | ||
|
|
d82832d8bc | ||
|
|
7cb6f61af0 | ||
|
|
4ab2254879 |
@@ -57,6 +57,16 @@ parameters:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
linux-arm:
|
||||
resource_class: electronjs/linux-arm
|
||||
machine: true
|
||||
|
||||
linux-arm64:
|
||||
resource_class: electronjs/linux-arm64
|
||||
machine: true
|
||||
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
#
|
||||
@@ -69,7 +79,7 @@ parameters:
|
||||
# Build machines configs.
|
||||
docker-image: &docker-image
|
||||
docker:
|
||||
- image: electron.azurecr.io/build:4cec2c5ab66765caa724e37bae2bffb9b29722a5
|
||||
- image: electron.azurecr.io/build:d818f06a9b1540c7fd38f75ad5a2c493dd6843b6
|
||||
|
||||
machine-linux-medium: &machine-linux-medium
|
||||
<<: *docker-image
|
||||
@@ -225,6 +235,25 @@ step-maybe-notify-slack-success: &step-maybe-notify-slack-success
|
||||
fi
|
||||
when: on_success
|
||||
|
||||
step-maybe-cleanup-arm: &step-maybe-cleanup-arm
|
||||
run:
|
||||
name: Cleanup after testing
|
||||
command: |
|
||||
if [ "$TARGET_ARCH" == "arm64" ] &&[ "`uname`" == "Darwin" ]; then
|
||||
killall Electron || echo "No Electron processes left running"
|
||||
killall Safari || echo "No Safari processes left running"
|
||||
rm -rf ~/Library/Application\ Support/Electron*
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
elif [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
XVFB=/usr/bin/Xvfb
|
||||
/sbin/start-stop-daemon --stop --exec $XVFB || echo "Xvfb not running"
|
||||
pkill electron || echo "electron not running"
|
||||
rm -rf ~/.config/Electron*
|
||||
rm -rf ~/.config/electron*
|
||||
fi
|
||||
|
||||
when: always
|
||||
|
||||
step-checkout-electron: &step-checkout-electron
|
||||
checkout:
|
||||
path: src/electron
|
||||
@@ -308,6 +337,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
export GOMA_FALLBACK_ON_AUTH_FAILURE=true
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
@@ -668,6 +698,7 @@ step-persist-data-for-tests: &step-persist-data-for-tests
|
||||
- src/electron
|
||||
- src/third_party/electron_node
|
||||
- src/third_party/nan
|
||||
- src/cross-arch-snapshots
|
||||
|
||||
step-electron-dist-unzip: &step-electron-dist-unzip
|
||||
run:
|
||||
@@ -730,7 +761,11 @@ step-verify-mksnapshot: &step-verify-mksnapshot
|
||||
name: Verify mksnapshot
|
||||
command: |
|
||||
cd src
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/cross-arch-snapshots
|
||||
else
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
|
||||
fi
|
||||
|
||||
step-verify-chromedriver: &step-verify-chromedriver
|
||||
run:
|
||||
@@ -857,23 +892,6 @@ step-maybe-cross-arch-snapshot-store: &step-maybe-cross-arch-snapshot-store
|
||||
path: src/cross-arch-snapshots
|
||||
destination: cross-arch-snapshots
|
||||
|
||||
step-maybe-trigger-arm-test: &step-maybe-trigger-arm-test
|
||||
run:
|
||||
name: Trigger an arm test on VSTS if applicable
|
||||
command: |
|
||||
cd src
|
||||
# Only run for non-fork prs
|
||||
if [ "$TRIGGER_ARM_TEST" == "true" ] && [ -z "$CIRCLE_PR_NUMBER" ]; then
|
||||
#Trigger VSTS job, passing along CircleCI job number and branch to build
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
echo "Triggering electron-arm2-testing build on Azure DevOps"
|
||||
node electron/script/release/ci-release-build.js --job=electron-arm2-testing --ci=DevOps --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
|
||||
else
|
||||
echo "Triggering electron-$TARGET_ARCH-testing build on VSTS"
|
||||
node electron/script/release/ci-release-build.js --job=electron-$TARGET_ARCH-testing --ci=VSTS --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
|
||||
fi
|
||||
fi
|
||||
|
||||
step-maybe-generate-typescript-defs: &step-maybe-generate-typescript-defs
|
||||
run:
|
||||
name: Generate type declarations
|
||||
@@ -1288,8 +1306,14 @@ steps-tests: &steps-tests
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
|
||||
command: |
|
||||
cd src
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging --files $(circleci tests glob spec-main/*-spec.ts | circleci tests split))
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging --files $(circleci tests glob spec/*-spec.js | circleci tests split))
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
export ELECTRON_SKIP_NATIVE_MODULE_TESTS=true
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging)
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging)
|
||||
else
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging --files $(circleci tests glob spec-main/*-spec.ts | circleci tests split))
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging --files $(circleci tests glob spec/*-spec.js | circleci tests split))
|
||||
fi
|
||||
- run:
|
||||
name: Check test results existence
|
||||
command: |
|
||||
@@ -1310,6 +1334,8 @@ steps-tests: &steps-tests
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
- *step-maybe-cleanup-arm
|
||||
|
||||
steps-test-nan: &steps-test-nan
|
||||
steps:
|
||||
- attach_workspace:
|
||||
@@ -1582,9 +1608,6 @@ commands:
|
||||
steps:
|
||||
- *step-save-out-cache
|
||||
|
||||
# Trigger tests on arm hardware if needed
|
||||
- *step-maybe-trigger-arm-test
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
electron-publish:
|
||||
@@ -1912,7 +1935,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
@@ -1970,7 +1993,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
@@ -2358,6 +2381,24 @@ jobs:
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-verify-ffmpeg
|
||||
|
||||
linux-arm-testing-tests:
|
||||
executor: linux-arm
|
||||
environment:
|
||||
<<: *env-arm
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
<<: *steps-tests
|
||||
|
||||
linux-arm64-testing-tests:
|
||||
executor: linux-arm64
|
||||
environment:
|
||||
<<: *env-arm64
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
<<: *steps-tests
|
||||
|
||||
osx-testing-x64-tests:
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
@@ -2590,8 +2631,23 @@ workflows:
|
||||
- linux-ia32-testing
|
||||
|
||||
- linux-arm-testing
|
||||
- linux-arm-testing-tests:
|
||||
filters:
|
||||
branches:
|
||||
# Do not run this on forked pull requests
|
||||
ignore: /pull\/[0-9]+/
|
||||
requires:
|
||||
- linux-arm-testing
|
||||
|
||||
- linux-arm64-testing
|
||||
- linux-arm64-testing-tests:
|
||||
filters:
|
||||
branches:
|
||||
# Do not run this on forked pull requests
|
||||
ignore: /pull\/[0-9]+/
|
||||
requires:
|
||||
- linux-arm64-testing
|
||||
|
||||
- linux-arm64-testing-gn-check:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
|
||||
@@ -1 +1 @@
|
||||
12.0.11
|
||||
12.0.18
|
||||
@@ -21,6 +21,6 @@ except subprocess.CalledProcessError as e:
|
||||
+ "' failed with code '"
|
||||
+ str(e.returncode)
|
||||
+ "':\n"
|
||||
+ e.output
|
||||
+ e.output.decode('utf8')
|
||||
)
|
||||
sys.exit(e.returncode)
|
||||
|
||||
@@ -139,6 +139,8 @@ static_library("chrome") {
|
||||
|
||||
if (enable_color_chooser) {
|
||||
sources += [
|
||||
"//chrome/browser/devtools/devtools_eye_dropper.cc",
|
||||
"//chrome/browser/devtools/devtools_eye_dropper.h",
|
||||
"//chrome/browser/platform_util.cc",
|
||||
"//chrome/browser/platform_util.h",
|
||||
"//chrome/browser/ui/browser_dialogs.h",
|
||||
|
||||
@@ -24,7 +24,7 @@ The `dialog` module has the following methods:
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -87,7 +87,7 @@ dialog.showOpenDialogSync(mainWindow, {
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -112,7 +112,7 @@ Returns `Promise<Object>` - Resolve with an object containing the following:
|
||||
|
||||
* `canceled` Boolean - whether or not the dialog was canceled.
|
||||
* `filePaths` String[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
|
||||
|
||||
@@ -165,7 +165,7 @@ dialog.showOpenDialog(mainWindow, {
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box,
|
||||
defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
@@ -195,7 +195,7 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
* `nameFieldLabel` String (optional) _macOS_ - Custom label for the text
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box, defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
@@ -227,7 +227,7 @@ expanding and collapsing the dialog.
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
@@ -273,7 +273,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
* `colorDepth` Number - The number of bits per pixel.
|
||||
* `depthPerComponent` Number - The number of bits per color component.
|
||||
* `displayFrequency` Number - The display refresh rate.
|
||||
* `bounds` [Rectangle](rectangle.md)
|
||||
* `bounds` [Rectangle](rectangle.md) - the bounds of the display in DIP points.
|
||||
* `size` [Size](size.md)
|
||||
* `workArea` [Rectangle](rectangle.md)
|
||||
* `workArea` [Rectangle](rectangle.md) - the work area of the display in DIP points.
|
||||
* `workAreaSize` [Size](size.md)
|
||||
* `internal` Boolean - `true` for an internal display and `false` for an external display
|
||||
|
||||
|
||||
@@ -154,7 +154,6 @@ response are visible by the time this listener is fired.
|
||||
* `timestamp` Double
|
||||
* `statusLine` String
|
||||
* `statusCode` Integer
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `callback` Function
|
||||
* `headersReceivedResponse` Object
|
||||
|
||||
@@ -718,6 +718,10 @@ Corresponds to the points in time when the spinner of the tab starts spinning.
|
||||
|
||||
Corresponds to the points in time when the spinner of the tab stops spinning.
|
||||
|
||||
### Event: 'did-attach'
|
||||
|
||||
Fired when attached to the embedder web contents.
|
||||
|
||||
### Event: 'dom-ready'
|
||||
|
||||
Fired when document in the given frame is loaded.
|
||||
@@ -838,6 +842,19 @@ this purpose.
|
||||
|
||||
Calling `event.preventDefault()` does __NOT__ have any effect.
|
||||
|
||||
### Event: 'did-start-navigation'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `isInPlace` Boolean
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame (including main) starts navigating. `isInPlace` will be
|
||||
`true` for in-page navigations.
|
||||
|
||||
### Event: 'did-navigate'
|
||||
|
||||
Returns:
|
||||
@@ -850,6 +867,23 @@ This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-frame-navigate'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `httpResponseCode` Integer - -1 for non HTTP navigations
|
||||
* `httpStatusText` String - empty for non HTTP navigations,
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame navigation is done.
|
||||
|
||||
This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-navigate-in-page'
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -117,15 +117,18 @@ const mainWindow = new BrowserWindow({
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url === 'about:blank') {
|
||||
return {
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
backgroundColor: 'black',
|
||||
webPreferences: {
|
||||
preload: 'my-child-window-preload-script.js'
|
||||
action: 'allow',
|
||||
overrideBrowserWindowOptions: {
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
backgroundColor: 'black',
|
||||
webPreferences: {
|
||||
preload: 'my-child-window-preload-script.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
return { action: 'deny' }
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
Click on the title with the <pre>Command</pre> or <pre>Control</pre> key pressed.
|
||||
You should see a popup with the represented file at the top.
|
||||
</p>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,10 +4,7 @@ const os = require('os');
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
@@ -1,92 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>app.setAsDefaultProtocol Demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section>
|
||||
<header>
|
||||
<h1>
|
||||
Protocol Handler
|
||||
</h1>
|
||||
<h3>The <code>app</code> module provides methods for handling protocols.</h3>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a browser asks to be your default for viewing web pages.</p>
|
||||
<h1>App Default Protocol Demo</h1>
|
||||
|
||||
<p>Open the <a href="https://electronjs.org/docs/api/app">full app API documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> in your browser.</p>
|
||||
</header>
|
||||
<p>The protocol API allows us to register a custom protocol and intercept existing protocol requests.</p>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a
|
||||
browser asks to be your default for viewing web pages.</p>
|
||||
|
||||
<div >
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">Launch current page in browser
|
||||
<div class="demo-meta u-avoid-clicks">Supports: Win, macOS <span class="demo-meta-divider">|</span> Process: Main</div>
|
||||
</button>
|
||||
<section id='open-app-link'>
|
||||
<a href="electron-api-demos://open">Now... launch the app from a web link</a>
|
||||
</section>
|
||||
<div >
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app as the default for <code>electron-api-demos://</code>. The demo button above will launch a page in your default browser with a link. Click that link and it will re-launch this app.</p>
|
||||
<h5>Packaging</h5>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code> for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this app is below.</p>
|
||||
<h5>Renderer Process</h5>
|
||||
<pre><code>
|
||||
const {shell} = require('electron')
|
||||
const path = require('path')
|
||||
const protocolHandlerBtn = document.getElementById('protocol-handler')
|
||||
protocolHandlerBtn.addEventListener('click', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, '../../sections/system/protocol-link.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
</code></pre>
|
||||
<h5>Main Process</h5>
|
||||
<pre><code>
|
||||
const {app, dialog} = require('electron')
|
||||
const path = require('path')
|
||||
<p>Open the <a href="https://www.electronjs.org/docs/api/protocol">full protocol API documentation</a> in your
|
||||
browser.</p>
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
-----
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
<h3>Demo</h3>
|
||||
<p>
|
||||
First: Launch current page in browser
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">
|
||||
Click to Launch Browser
|
||||
</button>
|
||||
</p>
|
||||
|
||||
</code></pre>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</section>
|
||||
<p>
|
||||
Then: Launch the app from a web link!
|
||||
<a href="electron-fiddle://open">Click here to launch the app</a>
|
||||
</p>
|
||||
|
||||
----
|
||||
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app
|
||||
as the default for <code>electron-fiddle://</code>. The demo button above will launch a page in your default
|
||||
browser with a link. Click that link and it will re-launch this app.</p>
|
||||
|
||||
|
||||
<h3>Packaging</h3>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in
|
||||
development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code>
|
||||
for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you
|
||||
can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this
|
||||
app is below:</p>
|
||||
|
||||
<p>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
<p>
|
||||
|
||||
<!-- You can also require other files to run in this process -->
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,10 +1,39 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, dialog } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, shell } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
let mainWindow;
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle')
|
||||
}
|
||||
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
@@ -12,58 +41,23 @@ function createWindow () {
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
// Handle window controls via IPC
|
||||
ipcMain.on('shell:open', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// All of the Node.js APIs are available in the preload process.
|
||||
// It has the same sandbox as a Chrome extension.
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
// Set up context bridge between the renderer process and the main process
|
||||
contextBridge.exposeInMainWorld(
|
||||
'shell',
|
||||
{
|
||||
open: () => ipcRenderer.send('shell:open'),
|
||||
}
|
||||
)
|
||||
@@ -1,14 +1,8 @@
|
||||
const { shell } = require('electron')
|
||||
const path = require('path')
|
||||
// This file is required by the index.html file and will
|
||||
// be executed in the renderer process for that window.
|
||||
// All APIs exposed by the context bridge are available here.
|
||||
|
||||
const openInBrowserButton = document.getElementById('open-in-browser')
|
||||
const openAppLink = document.getElementById('open-app-link')
|
||||
// Hides openAppLink when loaded inside Electron
|
||||
openAppLink.style.display = 'none'
|
||||
|
||||
openInBrowserButton.addEventListener('click', () => {
|
||||
console.log('clicked')
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
// Binds the buttons to the context bridge API.
|
||||
document.getElementById('open-in-browser').addEventListener('click', () => {
|
||||
shell.open();
|
||||
});
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 32 KiB |
0
docs/images/versioning-sketch-2.png
Executable file → Normal file
0
docs/images/versioning-sketch-2.png
Executable file → Normal file
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
175
docs/tutorial/launch-app-from-url-in-another-app.md
Normal file
175
docs/tutorial/launch-app-from-url-in-another-app.md
Normal file
@@ -0,0 +1,175 @@
|
||||
---
|
||||
title: launch-app-from-URL-in-another-app
|
||||
description: This guide will take you through the process of setting your electron app as the default handler for a specific protocol.
|
||||
slug: launch-app-from-url-in-another-app
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Launching Your Electron App From A URL In Another App
|
||||
|
||||
## Overview
|
||||
|
||||
<!-- ✍ Update this section if you want to provide more details -->
|
||||
|
||||
This guide will take you through the process of setting your electron app as the default
|
||||
handler for a specific [protocol](https://www.electronjs.org/docs/api/protocol).
|
||||
|
||||
By the end of this tutorial, we will have set our app to intercept and handle
|
||||
any clicked URLs that start with a specific protocol. In this guide, the protocol
|
||||
we will use will be "`electron-fiddle://`".
|
||||
|
||||
## Examples
|
||||
|
||||
### Main Process (main.js)
|
||||
|
||||
First we will import the required modules from `electron`. These modules help control our application life and create a native browser window.
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow, shell } = require('electron')
|
||||
const path = require('path')
|
||||
```
|
||||
|
||||
Next, we will proceed to register our application to handle all "`electron-fiddle://`" protocols.
|
||||
|
||||
```js
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle')
|
||||
}
|
||||
```
|
||||
|
||||
We will now define the function in charge of creating our browser window and load our application's `index.html` file.
|
||||
|
||||
```js
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
```
|
||||
|
||||
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
|
||||
|
||||
This code will be different in WindowsOS compared to MacOS and Linux. This is due to Windows requiring additional code in order to open the contents of the protocol link within the same electron instance. Read more about this [here](https://www.electronjs.org/docs/api/app#apprequestsingleinstancelock).
|
||||
|
||||
### Windows code:
|
||||
|
||||
```js
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// handling the protocol. In this case, we choose to show an Error Box.
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### MacOS and Linux code:
|
||||
|
||||
```js
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// handling the protocol. In this case, we choose to show an Error Box.
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
```
|
||||
|
||||
Finally, we will add some additional code to handle when someone closes our application
|
||||
|
||||
```js
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
```
|
||||
|
||||
## Important Note:
|
||||
|
||||
### Packaging
|
||||
|
||||
This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS `plist` for the app is updated to include the new protocol handler. If you're using [`electron-packager`](https://github.com/electron/electron-packager) then you
|
||||
can add the flag `--extend-info` with a path to the `plist` you've created. The one for this app is below:
|
||||
|
||||
### Plist
|
||||
|
||||
```XML
|
||||
<p>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
<p>
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
After you start your electron app, you can now enter in a URL in your browser that contains the custom protocol, for example `"electron-fiddle://open"` and observe that the application will respond and show an error dialog box.
|
||||
|
||||
<!--
|
||||
Because Electron examples usually require multiple files (HTML, CSS, JS
|
||||
for the main and renderer process, etc.), we use this custom code block
|
||||
for Fiddle (https://www.electronjs.org/fiddle).
|
||||
Please modify any of the files in the referenced folder to fit your
|
||||
example.
|
||||
The content in this codeblock will not be rendered in the website so you
|
||||
can leave it empty.
|
||||
-->
|
||||
|
||||
```fiddle docs/fiddles/system/protocol-handler/launch-app-from-URL-in-another-app
|
||||
|
||||
```
|
||||
|
||||
<!-- ✍ Explanation of the code below -->
|
||||
@@ -130,14 +130,6 @@ if you exceed that limit.
|
||||
|
||||
[apple-notification-guidelines]: https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/
|
||||
|
||||
#### Advanced Notifications
|
||||
|
||||
Later versions of macOS allow for notifications with an input field, allowing the user
|
||||
to quickly reply to a notification. In order to send notifications with an input field,
|
||||
use the userland module [node-mac-notifier][node-mac-notifier].
|
||||
|
||||
[node-mac-notifier]: https://github.com/CharlieHess/node-mac-notifier
|
||||
|
||||
#### Do not disturb / Session State
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the userland module
|
||||
|
||||
@@ -120,9 +120,9 @@ file in the directory you executed it in. Both files can be analyzed using
|
||||
the Chrome Developer Tools, using the `Performance` and `Memory` tabs
|
||||
respectively.
|
||||
|
||||
![performance-cpu-prof]
|
||||
![Performance CPU Profile][performance-cpu-prof]
|
||||
|
||||
![performance-heap-prof]
|
||||
![Performance Heap Memory Profile][performance-heap-prof]
|
||||
|
||||
In this example, on the author's machine, we saw that loading `request` took
|
||||
almost half a second, whereas `node-fetch` took dramatically less memory
|
||||
|
||||
@@ -223,7 +223,7 @@ app.on('window-all-closed', function () {
|
||||
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
[window-all-closed]: ../api/app.md#event-window-all-closed
|
||||
[window-all-closed]: ../api/app.md#appquit
|
||||
[app-quit]: ../api/app.md#appquit
|
||||
|
||||
#### Open a window if none are open (macOS)
|
||||
|
||||
|
||||
@@ -20,23 +20,40 @@ To set the represented file of window, you can use the
|
||||
|
||||
## Example
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), add the following lines to the
|
||||
`main.js` file:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/represented-file'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const os = require('os');
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.setRepresentedFilename('/etc/passwd')
|
||||
win.setRepresentedFilename(os.homedir())
|
||||
win.setDocumentEdited(true)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
After launching the Electron application, click on the title with `Command` or
|
||||
`Control` key pressed. You should see a popup with the file you just defined:
|
||||
`Control` key pressed. You should see a popup with the represented file at the top.
|
||||
In this guide, this is the current user's home directory:
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -490,63 +490,83 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
}
|
||||
};
|
||||
|
||||
function fsReadFileAsar (pathArgument: string, options: any, callback: any) {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (pathInfo.isAsar) {
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = { encoding: null };
|
||||
} else if (typeof options === 'string') {
|
||||
options = { encoding: options };
|
||||
} else if (options === null || options === undefined) {
|
||||
options = { encoding: null };
|
||||
} else if (typeof options !== 'object') {
|
||||
throw new TypeError('Bad arguments');
|
||||
}
|
||||
|
||||
const { encoding } = options;
|
||||
const archive = getOrCreateArchive(asarPath);
|
||||
if (!archive) {
|
||||
const error = createError(AsarError.INVALID_ARCHIVE, { asarPath });
|
||||
nextTick(callback, [error]);
|
||||
return;
|
||||
}
|
||||
|
||||
const info = archive.getFileInfo(filePath);
|
||||
if (!info) {
|
||||
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
nextTick(callback, [error]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.size === 0) {
|
||||
nextTick(callback, [null, encoding ? '' : Buffer.alloc(0)]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.unpacked) {
|
||||
const realPath = archive.copyFileOut(filePath);
|
||||
return fs.readFile(realPath, options, callback);
|
||||
}
|
||||
|
||||
const buffer = Buffer.alloc(info.size);
|
||||
const fd = archive.getFd();
|
||||
if (!(fd >= 0)) {
|
||||
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
nextTick(callback, [error]);
|
||||
return;
|
||||
}
|
||||
|
||||
logASARAccess(asarPath, filePath, info.offset);
|
||||
fs.read(fd, buffer, 0, info.size, info.offset, (error: Error) => {
|
||||
callback(error, encoding ? buffer.toString(encoding) : buffer);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const { readFile } = fs;
|
||||
fs.readFile = function (pathArgument: string, options: any, callback: any) {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return readFile.apply(this, arguments);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = { encoding: null };
|
||||
} else if (typeof options === 'string') {
|
||||
options = { encoding: options };
|
||||
} else if (options === null || options === undefined) {
|
||||
options = { encoding: null };
|
||||
} else if (typeof options !== 'object') {
|
||||
throw new TypeError('Bad arguments');
|
||||
if (!pathInfo.isAsar) {
|
||||
return readFile.apply(this, arguments);
|
||||
}
|
||||
|
||||
const { encoding } = options;
|
||||
const archive = getOrCreateArchive(asarPath);
|
||||
if (!archive) {
|
||||
const error = createError(AsarError.INVALID_ARCHIVE, { asarPath });
|
||||
nextTick(callback, [error]);
|
||||
return;
|
||||
}
|
||||
|
||||
const info = archive.getFileInfo(filePath);
|
||||
if (!info) {
|
||||
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
nextTick(callback, [error]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.size === 0) {
|
||||
nextTick(callback, [null, encoding ? '' : Buffer.alloc(0)]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.unpacked) {
|
||||
const realPath = archive.copyFileOut(filePath);
|
||||
return fs.readFile(realPath, options, callback);
|
||||
}
|
||||
|
||||
const buffer = Buffer.alloc(info.size);
|
||||
const fd = archive.getFd();
|
||||
if (!(fd >= 0)) {
|
||||
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
nextTick(callback, [error]);
|
||||
return;
|
||||
}
|
||||
|
||||
logASARAccess(asarPath, filePath, info.offset);
|
||||
fs.read(fd, buffer, 0, info.size, info.offset, (error: Error) => {
|
||||
callback(error, encoding ? buffer.toString(encoding) : buffer);
|
||||
});
|
||||
return fsReadFileAsar(pathArgument, options, callback);
|
||||
};
|
||||
|
||||
fs.promises.readFile = util.promisify(fs.readFile);
|
||||
const { readFile: readFilePromise } = fs.promises;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
fs.promises.readFile = function (pathArgument: string, options: any) {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) {
|
||||
return readFilePromise.apply(this, arguments);
|
||||
}
|
||||
|
||||
const p = util.promisify(fsReadFileAsar);
|
||||
return p(pathArgument, options);
|
||||
};
|
||||
|
||||
const { readFileSync } = fs;
|
||||
fs.readFileSync = function (pathArgument: string, options: any) {
|
||||
|
||||
@@ -75,6 +75,7 @@ ipcMainInternal.on(
|
||||
|
||||
const browserWindowOptions = (event.sender as any)._callWindowOpenHandler(event, url, frameName, features);
|
||||
if (event.defaultPrevented) {
|
||||
event.returnValue = null;
|
||||
return;
|
||||
}
|
||||
const guest = openGuestWindow({
|
||||
|
||||
@@ -271,7 +271,7 @@ const warnAboutAllowedPopups = function () {
|
||||
|
||||
const warnAboutRemoteModuleWithRemoteContent = function (webPreferences?: Electron.WebPreferences) {
|
||||
if (!webPreferences || isLocalhost()) return;
|
||||
const remoteModuleEnabled = webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : true;
|
||||
const remoteModuleEnabled = webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : false;
|
||||
if (!remoteModuleEnabled) return;
|
||||
|
||||
if (getIsRemoteProtocol()) {
|
||||
@@ -298,7 +298,9 @@ const logSecurityWarnings = function (
|
||||
warnAboutEnableBlinkFeatures(webPreferences);
|
||||
warnAboutInsecureCSP();
|
||||
warnAboutAllowedPopups();
|
||||
warnAboutRemoteModuleWithRemoteContent(webPreferences);
|
||||
if (BUILDFLAG(ENABLE_REMOTE_MODULE)) {
|
||||
warnAboutRemoteModuleWithRemoteContent(webPreferences);
|
||||
}
|
||||
};
|
||||
|
||||
const getWebPreferences = async function () {
|
||||
|
||||
@@ -12,6 +12,9 @@ require('../common/reset-search-paths');
|
||||
// Import common settings.
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Export node bindings to global.
|
||||
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers') // eslint-disable-line
|
||||
global.module = new Module('electron/js2c/worker_init');
|
||||
@@ -32,4 +35,10 @@ if (self.location.protocol === 'file:') {
|
||||
// For backwards compatibility we fake these two paths here
|
||||
global.__filename = path.join(process.resourcesPath, 'electron.asar', 'worker', 'init.js');
|
||||
global.__dirname = path.join(process.resourcesPath, 'electron.asar', 'worker');
|
||||
|
||||
const appPath = hasSwitch('app-path') ? getSwitchValue('app-path') : null;
|
||||
if (appPath) {
|
||||
// Search for module under the app directory.
|
||||
global.module.paths = Module._nodeModulePaths(appPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "12.0.11",
|
||||
"version": "12.0.18",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
d3d11_skip_blits_if_there_is_no_intersection_of_dest_areas.patch
|
||||
cherry-pick-3d4f87ab5b9b.patch
|
||||
|
||||
59
patches/angle/cherry-pick-3d4f87ab5b9b.patch
Normal file
59
patches/angle/cherry-pick-3d4f87ab5b9b.patch
Normal file
@@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Thu, 20 May 2021 12:22:46 -0400
|
||||
Subject: D3D11: Fix respecifying 3D textures.
|
||||
|
||||
The missing check for the "Depth" dimension could lead to a bug
|
||||
where we would not recreate a texture when the dimension changed.
|
||||
|
||||
Bug: chromium:1210414
|
||||
Change-Id: Id59097ad14ae77ff80d27081f61786dad17a77ea
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2911032
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 2697358464cf20576701987f60300b6c4086c11e)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2937026
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
|
||||
index c502d00fac032ea708015bbbf4f51db2dc2b3c59..daa5c3abc3ab4f4460ec48d0aba9649cf66897ac 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
|
||||
@@ -223,8 +223,8 @@ bool Image11::redefine(gl::TextureType type,
|
||||
const gl::Extents &size,
|
||||
bool forceRelease)
|
||||
{
|
||||
- if (mWidth != size.width || mHeight != size.height || mInternalFormat != internalformat ||
|
||||
- forceRelease)
|
||||
+ if (mWidth != size.width || mHeight != size.height || mDepth != size.depth ||
|
||||
+ mInternalFormat != internalformat || forceRelease)
|
||||
{
|
||||
// End the association with the TextureStorage, since that data will be out of date.
|
||||
// Also reset mRecoveredFromStorageCount since this Image is getting completely redefined.
|
||||
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
|
||||
index b335d4901ef11b27e57d0ee6445b15ce5e7567fe..4b6046d4f8d3da97d70a837422c2ddd8d7599fc6 100644
|
||||
--- a/src/tests/gl_tests/MipmapTest.cpp
|
||||
+++ b/src/tests/gl_tests/MipmapTest.cpp
|
||||
@@ -2044,6 +2044,22 @@ void main()
|
||||
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::green);
|
||||
}
|
||||
|
||||
+// Tests respecifying 3D mipmaps.
|
||||
+TEST_P(MipmapTestES3, Generate3DMipmapRespecification)
|
||||
+{
|
||||
+ std::vector<GLColor> pixels(256 * 256 * 100, GLColor::black);
|
||||
+
|
||||
+ GLTexture texture;
|
||||
+ glBindTexture(GL_TEXTURE_3D, texture);
|
||||
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 256, 256, 100, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixels.data());
|
||||
+ glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA, 128, 128, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixels.data());
|
||||
+ glGenerateMipmap(GL_TEXTURE_3D);
|
||||
+
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MipmapTest);
|
||||
@@ -130,3 +130,20 @@ media_feeds_disable_media_feeds_and_related_features.patch
|
||||
remove_tabs_and_line_breaks_from_the_middle_of_app_names_when.patch
|
||||
autofill_fixed_refill_of_changed_form.patch
|
||||
x11_fix_window_enumeration_order_when_wm_doesn_t_set.patch
|
||||
cherry-pick-34d5af37f9ac.patch
|
||||
m90-lts_longtaskdetector_remove_container_mutation_during.patch
|
||||
m90-lts_reduce_memory_consumption_on.patch
|
||||
cherry-pick-b77b38a3380c.patch
|
||||
cherry-pick-910e9e40d376.patch
|
||||
cherry-pick-d9556a80a790.patch
|
||||
cherry-pick-ee6aee64e24c.patch
|
||||
webview_fullscreen.patch
|
||||
set_svgimage_page_after_document_install.patch
|
||||
cherry-pick-e60cc80ff744.patch
|
||||
cherry-pick-3feda0244490.patch
|
||||
cherry-pick-cd98d7c0dae9.patch
|
||||
replace_first_of_two_waitableevents_in_creditcardaccessmanager.patch
|
||||
cherry-pick-ac9dc1235e28.patch
|
||||
cherry-pick-4ce2abc17078.patch
|
||||
cherry-pick-e2123a8e0943.patch
|
||||
cherry-pick-1227933.patch
|
||||
|
||||
215
patches/chromium/cherry-pick-1227933.patch
Normal file
215
patches/chromium/cherry-pick-1227933.patch
Normal file
@@ -0,0 +1,215 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Koji Ishii <kojii@chromium.org>
|
||||
Date: Mon, 26 Jul 2021 07:09:18 +0000
|
||||
Subject: Fix nested inline box fragmentation
|
||||
|
||||
This patch fixes when nested inline boxes are fragmented in a
|
||||
line due to bidi reordering.
|
||||
|
||||
Before this change, the fragmented boxes are appended to the
|
||||
end of |box_data_list_|. Then when |NGInlineLayoutStateStack::
|
||||
CreateBoxFragments| creates inline boxes in the ascending
|
||||
order of |box_data_list_|, it failed to add the fragmented
|
||||
boxes into their parent inline boxes.
|
||||
|
||||
This is critical for out-of-flow positioned objects whose
|
||||
containing block is an inline box, because they expect to be
|
||||
propagated through all ancestor inline boxes.
|
||||
|
||||
|UpdateBoxDataFragmentRange| is a little tricky by appending
|
||||
to a vector it is iterating. Changing it to insert to the
|
||||
correct position makes the function even trickier. This patch
|
||||
changes it to add fragmented boxes to a separate vector, and
|
||||
let later process |UpdateFragmentedBoxDataEdges| to merge the
|
||||
vector to |box_data_list_|.
|
||||
|
||||
(cherry picked from commit 9c8a39c14a9c80556468593cddf436f5047a16ce)
|
||||
|
||||
Bug: 1227933, 1229999
|
||||
Change-Id: I7edcd209e1fdac06bab01b16d660383e7e9c37bd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3038308
|
||||
Commit-Queue: Koji Ishii <kojii@chromium.org>
|
||||
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#903356}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3053212
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Koji Ishii <kojii@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4577@{#145}
|
||||
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
|
||||
index b257014513cb881d4531694b86c05fd21edb6732..9a3f6f3af7839ebed24f7d8a32b7f95fba66cd9a 100644
|
||||
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
|
||||
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h"
|
||||
|
||||
+#include "base/containers/adapters.h"
|
||||
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
|
||||
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
|
||||
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
|
||||
@@ -387,13 +388,14 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
|
||||
box_data.fragment_start = box_data.fragment_end = 0;
|
||||
|
||||
// Scan children and update start/end from their box_data_index.
|
||||
- unsigned box_count = box_data_list_.size();
|
||||
+ Vector<BoxData> fragmented_boxes;
|
||||
for (unsigned index = 0; index < line_box->size();)
|
||||
- index = UpdateBoxDataFragmentRange(line_box, index);
|
||||
+ index = UpdateBoxDataFragmentRange(line_box, index, &fragmented_boxes);
|
||||
|
||||
- // If any inline fragmentation due to BiDi reorder, adjust box edges.
|
||||
- if (box_count != box_data_list_.size())
|
||||
- UpdateFragmentedBoxDataEdges();
|
||||
+ // If any inline fragmentation occurred due to BiDi reorder, append them and
|
||||
+ // adjust box edges.
|
||||
+ if (UNLIKELY(!fragmented_boxes.IsEmpty()))
|
||||
+ UpdateFragmentedBoxDataEdges(&fragmented_boxes);
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
// Check all BoxData have ranges.
|
||||
@@ -410,7 +412,8 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
|
||||
|
||||
unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
NGLogicalLineItems* line_box,
|
||||
- unsigned index) {
|
||||
+ unsigned index,
|
||||
+ Vector<BoxData>* fragmented_boxes) {
|
||||
// Find the first line box item that should create a box fragment.
|
||||
for (; index < line_box->size(); index++) {
|
||||
NGLogicalLineItem* start = &(*line_box)[index];
|
||||
@@ -438,7 +441,7 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
// It also changes other BoxData, but not the one we're dealing with here
|
||||
// because the update is limited only when its |box_data_index| is lower.
|
||||
while (end->box_data_index && end->box_data_index < box_data_index) {
|
||||
- UpdateBoxDataFragmentRange(line_box, index);
|
||||
+ UpdateBoxDataFragmentRange(line_box, index, fragmented_boxes);
|
||||
}
|
||||
|
||||
if (box_data_index != end->box_data_index)
|
||||
@@ -453,14 +456,9 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
} else {
|
||||
// This box is fragmented by BiDi reordering. Add a new BoxData for the
|
||||
// fragmented range.
|
||||
- box_data_list_[box_data_index - 1].fragmented_box_data_index =
|
||||
- box_data_list_.size();
|
||||
- // Do not use `emplace_back()` here because adding to |box_data_list_| may
|
||||
- // reallocate the buffer, but the `BoxData` ctor must run before the
|
||||
- // reallocation. Create a new instance and |push_back()| instead.
|
||||
- BoxData fragmented_box_data(box_data_list_[box_data_index - 1],
|
||||
- start_index, index);
|
||||
- box_data_list_.push_back(fragmented_box_data);
|
||||
+ BoxData& fragmented_box = fragmented_boxes->emplace_back(
|
||||
+ box_data_list_[box_data_index - 1], start_index, index);
|
||||
+ fragmented_box.fragmented_box_data_index = box_data_index;
|
||||
}
|
||||
// If this box has parent boxes, we need to process it again.
|
||||
if (box_data_list_[box_data_index - 1].parent_box_data_index)
|
||||
@@ -470,7 +468,43 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
return index;
|
||||
}
|
||||
|
||||
-void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges() {
|
||||
+void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges(
|
||||
+ Vector<BoxData>* fragmented_boxes) {
|
||||
+ DCHECK(!fragmented_boxes->IsEmpty());
|
||||
+ // Append in the descending order of |fragmented_box_data_index| because the
|
||||
+ // indices will change as boxes are inserted into |box_data_list_|.
|
||||
+ std::sort(fragmented_boxes->begin(), fragmented_boxes->end(),
|
||||
+ [](const BoxData& a, const BoxData& b) {
|
||||
+ if (a.fragmented_box_data_index != b.fragmented_box_data_index) {
|
||||
+ return a.fragmented_box_data_index <
|
||||
+ b.fragmented_box_data_index;
|
||||
+ }
|
||||
+ DCHECK_NE(a.fragment_start, b.fragment_start);
|
||||
+ return a.fragment_start < b.fragment_start;
|
||||
+ });
|
||||
+ for (BoxData& fragmented_box : base::Reversed(*fragmented_boxes)) {
|
||||
+ // Insert the fragmented box to right after the box it was fragmented from.
|
||||
+ // The order in the |box_data_list_| is critical when propagating child
|
||||
+ // fragment data such as OOF to ancestors.
|
||||
+ const unsigned insert_at = fragmented_box.fragmented_box_data_index;
|
||||
+ DCHECK_GT(insert_at, 0u);
|
||||
+ fragmented_box.fragmented_box_data_index = 0;
|
||||
+ box_data_list_.insert(insert_at, fragmented_box);
|
||||
+
|
||||
+ // Adjust box data indices by the insertion.
|
||||
+ for (BoxData& box_data : box_data_list_) {
|
||||
+ if (box_data.fragmented_box_data_index >= insert_at)
|
||||
+ ++box_data.fragmented_box_data_index;
|
||||
+ }
|
||||
+
|
||||
+ // Set the index of the last fragment to the original box. This is needed to
|
||||
+ // update fragment edges.
|
||||
+ const unsigned fragmented_from = insert_at - 1;
|
||||
+ if (!box_data_list_[fragmented_from].fragmented_box_data_index)
|
||||
+ box_data_list_[fragmented_from].fragmented_box_data_index = insert_at;
|
||||
+ }
|
||||
+
|
||||
+ // Move the line-right edge to the last fragment.
|
||||
for (BoxData& box_data : box_data_list_) {
|
||||
if (box_data.fragmented_box_data_index)
|
||||
box_data.UpdateFragmentEdges(box_data_list_);
|
||||
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
|
||||
index 82ecfef8fe4d404d5713f0f67d83b38ecfbfca4c..9d079266efd7f2ccc43cef40d8d89e4fc6edda9e 100644
|
||||
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
|
||||
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
|
||||
@@ -156,17 +156,6 @@ class CORE_EXPORT NGInlineLayoutStateStack {
|
||||
// reordering.
|
||||
void UpdateAfterReorder(NGLogicalLineItems*);
|
||||
|
||||
- // Update start/end of the first BoxData found at |index|.
|
||||
- //
|
||||
- // If inline fragmentation is found, a new BoxData is added.
|
||||
- //
|
||||
- // Returns the index to process next. It should be given to the next call to
|
||||
- // this function.
|
||||
- unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*, unsigned index);
|
||||
-
|
||||
- // Update edges of inline fragmented boxes.
|
||||
- void UpdateFragmentedBoxDataEdges();
|
||||
-
|
||||
// Compute inline positions of fragments and boxes.
|
||||
LayoutUnit ComputeInlinePositions(NGLogicalLineItems*, LayoutUnit position);
|
||||
|
||||
@@ -259,6 +248,19 @@ class CORE_EXPORT NGInlineLayoutStateStack {
|
||||
scoped_refptr<const NGLayoutResult> CreateBoxFragment(NGLogicalLineItems*);
|
||||
};
|
||||
|
||||
+ // Update start/end of the first BoxData found at |index|.
|
||||
+ //
|
||||
+ // If inline fragmentation is found, a new BoxData is added.
|
||||
+ //
|
||||
+ // Returns the index to process next. It should be given to the next call to
|
||||
+ // this function.
|
||||
+ unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*,
|
||||
+ unsigned index,
|
||||
+ Vector<BoxData>* fragmented_boxes);
|
||||
+
|
||||
+ // Update edges of inline fragmented boxes.
|
||||
+ void UpdateFragmentedBoxDataEdges(Vector<BoxData>* fragmented_boxes);
|
||||
+
|
||||
Vector<NGInlineBoxState, 4> stack_;
|
||||
Vector<BoxData, 4> box_data_list_;
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b701d2b5688ace54aa99530c12fa8143f1e6a508
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
|
||||
@@ -0,0 +1,13 @@
|
||||
+<!DOCTYPE html>
|
||||
+<link rel="author" href="mailto:mstensho@chromium.org">
|
||||
+<link rel="help" href="https://crbug.com/1229999">
|
||||
+<div style="direction:rtl; width:500px">
|
||||
+ <span style="border:solid">
|
||||
+ <span style="position:relative">
|
||||
+ <div style="display:inline-block; width:1000%; height:10px"></div>
|
||||
+ <span dir="ltr">
|
||||
+ <div style="position:absolute"></div>
|
||||
+ </span>
|
||||
+ </span>
|
||||
+ </span>
|
||||
+</div>
|
||||
101
patches/chromium/cherry-pick-34d5af37f9ac.patch
Normal file
101
patches/chromium/cherry-pick-34d5af37f9ac.patch
Normal file
@@ -0,0 +1,101 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Asami Doi <asamidoi@chromium.org>
|
||||
Date: Thu, 10 Jun 2021 07:03:17 +0000
|
||||
Subject: BFCache: remove a controllee stored in `bfcached_controllee_map_`
|
||||
|
||||
This CL fixes the UAF that happens with the following case:
|
||||
Let's assume we have 2 service workers (sw1.js and sw2.js) are
|
||||
registered in the same page. When the second service worker (sw2.js) is
|
||||
registered, ServiceWorkerContainerHost::UpdateController() is called
|
||||
and the previous SWVersion (sw1.js) removes a controllee from
|
||||
`controllee_map_`. If BackForwardCache is enabled, a controllee is
|
||||
stored in `bfcached_controllee_map_` instead and the controllee will
|
||||
not be removed in ServiceWorkerContainerHost::UpdateController().
|
||||
When ServiceWorkerContainerHost::UpdateController() is called and
|
||||
keep a controllee in `bfcached_controllee_map_`, and a page navigates to
|
||||
a different page (evicts BFCache), use-after-free (UAF) happens.
|
||||
|
||||
This CL updates ServiceWorkerContainerHost::UpdateController()
|
||||
to remove a controllee from `bfcached_controllee_map_` if it exists.
|
||||
|
||||
(cherry picked from commit a2414a05a486ca0ad18ba4caf78e883a668a0555)
|
||||
|
||||
(cherry picked from commit 7cd7f6741fc4491c2f7ef21052a370ee23887e37)
|
||||
|
||||
Bug: 1212618
|
||||
Change-Id: I13e023e6d273268a08ea9276a056f7f5acba39cd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2919020
|
||||
Commit-Queue: Asami Doi <asamidoi@chromium.org>
|
||||
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/master@{#887109}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2929401
|
||||
Reviewed-by: Krishna Govind <govind@chromium.org>
|
||||
Reviewed-by: Ben Mason <benmason@chromium.org>
|
||||
Reviewed-by: Prudhvi Kumar Bommana <pbommana@google.com>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Owners-Override: Krishna Govind <govind@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4472@{#1375}
|
||||
Cr-Original-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2944946
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4430@{#1512}
|
||||
Cr-Branched-From: e5ce7dc4f7518237b3d9bb93cccca35d25216cbe-refs/heads/master@{#857950}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc
|
||||
index 0b1981efd9eb008caea1c94da138a2ed7c386bc5..9a2193ac5a4e8a738bef8e391145deecef9b9ac2 100644
|
||||
--- a/content/browser/service_worker/service_worker_container_host.cc
|
||||
+++ b/content/browser/service_worker/service_worker_container_host.cc
|
||||
@@ -138,7 +138,7 @@ ServiceWorkerContainerHost::~ServiceWorkerContainerHost() {
|
||||
}
|
||||
|
||||
if (IsContainerForClient() && controller_)
|
||||
- controller_->OnControlleeDestroyed(client_uuid());
|
||||
+ controller_->Uncontrol(client_uuid());
|
||||
|
||||
// Remove |this| as an observer of ServiceWorkerRegistrations.
|
||||
// TODO(falken): Use ScopedObserver instead of this explicit call.
|
||||
@@ -1244,7 +1244,7 @@ void ServiceWorkerContainerHost::UpdateController(
|
||||
}
|
||||
}
|
||||
if (previous_version)
|
||||
- previous_version->RemoveControllee(client_uuid());
|
||||
+ previous_version->Uncontrol(client_uuid());
|
||||
|
||||
// SetController message should be sent only for clients.
|
||||
DCHECK(IsContainerForClient());
|
||||
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
|
||||
index 798d0bd350976cf2724e4d4b726c24d63e0a5ec3..5e268a5331e80ff7c6c93c425171bbd31ddb342a 100644
|
||||
--- a/content/browser/service_worker/service_worker_version.cc
|
||||
+++ b/content/browser/service_worker/service_worker_version.cc
|
||||
@@ -886,8 +886,7 @@ void ServiceWorkerVersion::RemoveControlleeFromBackForwardCacheMap(
|
||||
bfcached_controllee_map_.erase(client_uuid);
|
||||
}
|
||||
|
||||
-void ServiceWorkerVersion::OnControlleeDestroyed(
|
||||
- const std::string& client_uuid) {
|
||||
+void ServiceWorkerVersion::Uncontrol(const std::string& client_uuid) {
|
||||
if (!IsBackForwardCacheEnabled()) {
|
||||
RemoveControllee(client_uuid);
|
||||
} else {
|
||||
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
|
||||
index cb5afe636f45b70fce2ff313641834bf7bddff30..a96d2c4575fa3879cf6133fbe656cb20745bd66a 100644
|
||||
--- a/content/browser/service_worker/service_worker_version.h
|
||||
+++ b/content/browser/service_worker/service_worker_version.h
|
||||
@@ -394,9 +394,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
|
||||
void RestoreControlleeFromBackForwardCacheMap(const std::string& client_uuid);
|
||||
// Called when a back-forward cached controllee is evicted or destroyed.
|
||||
void RemoveControlleeFromBackForwardCacheMap(const std::string& client_uuid);
|
||||
- // Called when a controllee is destroyed. Remove controllee from whichever
|
||||
- // map it belongs to, or do nothing when it is already removed.
|
||||
- void OnControlleeDestroyed(const std::string& client_uuid);
|
||||
+ // Called when this version should no longer be the controller of this client.
|
||||
+ // Called when the controllee is destroyed or it changes controller. Removes
|
||||
+ // controllee from whichever map it belongs to, or do nothing when it is
|
||||
+ // already removed. This function is different from RemoveController(), which
|
||||
+ // can only be called if the controllee is not in the back-forward cache map.
|
||||
+ void Uncontrol(const std::string& client_uuid);
|
||||
|
||||
// Returns true if this version has a controllee.
|
||||
// Note regarding BackForwardCache:
|
||||
38
patches/chromium/cherry-pick-3feda0244490.patch
Normal file
38
patches/chromium/cherry-pick-3feda0244490.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Reilly Grant <reillyg@chromium.org>
|
||||
Date: Mon, 28 Jun 2021 21:55:24 +0000
|
||||
Subject: serial: Fix parent class tracing for SerialPort
|
||||
|
||||
When SerialPort was updated to be ActiveScriptWrappable and an
|
||||
EventTarget the Trace method was not updated to call the parent class
|
||||
trace methods.
|
||||
|
||||
(cherry picked from commit 4059ecc3a5352601a4d79196f90c8ca19262afe1)
|
||||
|
||||
Bug: 1220078
|
||||
Change-Id: If6967a913268bce86d4488359a9418a814530f84
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2965255
|
||||
Auto-Submit: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
Reviewed-by: Tom Sepez <tsepez@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#893039}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2992740
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4472@{#1531}
|
||||
Cr-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/serial/serial_port.cc b/third_party/blink/renderer/modules/serial/serial_port.cc
|
||||
index b485935f6cfd1b397d86acb90ebf344e22e18a2c..835ac5f3526d1a933f81e3546344aa409a5eec09 100644
|
||||
--- a/third_party/blink/renderer/modules/serial/serial_port.cc
|
||||
+++ b/third_party/blink/renderer/modules/serial/serial_port.cc
|
||||
@@ -508,7 +508,8 @@ void SerialPort::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(open_resolver_);
|
||||
visitor->Trace(signal_resolvers_);
|
||||
visitor->Trace(close_resolver_);
|
||||
- ScriptWrappable::Trace(visitor);
|
||||
+ EventTargetWithInlineData::Trace(visitor);
|
||||
+ ActiveScriptWrappable<SerialPort>::Trace(visitor);
|
||||
}
|
||||
|
||||
bool SerialPort::HasPendingActivity() const {
|
||||
135
patches/chromium/cherry-pick-4ce2abc17078.patch
Normal file
135
patches/chromium/cherry-pick-4ce2abc17078.patch
Normal file
@@ -0,0 +1,135 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Flack <flackr@chromium.org>
|
||||
Date: Fri, 30 Jul 2021 18:51:38 +0000
|
||||
Subject: Forbid script execution for entire lifecycle update
|
||||
|
||||
We should not execute script during the lifecycle update except in cases where we we know it is safe to do so, either because we will rerun the lifecycle steps if anything is invalidated (resize observers, intersection observers) or because the script does not have access to invalidate the DOM (e.g. paint worklets).
|
||||
|
||||
(cherry picked from commit a73237da91de8aa49aaa5d9479bae51cf387f090)
|
||||
|
||||
Bug: 1196853
|
||||
Change-Id: Id1fdbbb25107cfdc6c234123f845406c28d32914
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2815619
|
||||
Reviewed-by: Stefan Zager <szager@chromium.org>
|
||||
Commit-Queue: Robert Flack <flackr@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#901110}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3058973
|
||||
Auto-Submit: Robert Flack <flackr@chromium.org>
|
||||
Commit-Queue: Stefan Zager <szager@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4472@{#1588}
|
||||
Cr-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
|
||||
index d3512edd4cad7b7dafbb1c3a6da5cd45ea367e79..69f8e8a598a4aefef652e603f1590c702e288b59 100644
|
||||
--- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
|
||||
@@ -96,6 +96,7 @@
|
||||
#include "third_party/blink/renderer/core/script/classic_script.h"
|
||||
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
|
||||
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
|
||||
+#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
|
||||
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
|
||||
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
|
||||
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
|
||||
@@ -804,6 +805,8 @@ void WebPluginContainerImpl::Dispose() {
|
||||
}
|
||||
|
||||
if (web_plugin_) {
|
||||
+ // Plugins may execute script on being detached during the lifecycle update.
|
||||
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
|
||||
CHECK(web_plugin_->Container() == this);
|
||||
web_plugin_->Destroy();
|
||||
web_plugin_ = nullptr;
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
index dd320dd900b7f556c9216c7faedc2ad35588b0d7..a9e724432440c05d1b3bb9863acb4345e07f77b4 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
@@ -2484,6 +2484,7 @@ bool LocalFrameView::UpdateLifecyclePhases(
|
||||
|
||||
void LocalFrameView::UpdateLifecyclePhasesInternal(
|
||||
DocumentLifecycle::LifecycleState target_state) {
|
||||
+ ScriptForbiddenScope forbid_script;
|
||||
// RunScrollTimelineSteps must not run more than once.
|
||||
bool should_run_scroll_timeline_steps = true;
|
||||
|
||||
@@ -2564,6 +2565,10 @@ void LocalFrameView::UpdateLifecyclePhasesInternal(
|
||||
continue;
|
||||
}
|
||||
|
||||
+ // At this point in time, script is allowed to run as we will repeat the
|
||||
+ // lifecycle update if anything is invalidated.
|
||||
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
|
||||
+
|
||||
// ResizeObserver and post-layout IntersectionObserver observation
|
||||
// deliveries may dirty style and layout. RunResizeObserverSteps will return
|
||||
// true if any observer ran that may have dirtied style or layout;
|
||||
@@ -2816,6 +2821,7 @@ bool LocalFrameView::AnyFrameIsPrintingOrPaintingPreview() {
|
||||
}
|
||||
|
||||
void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
|
||||
+ DCHECK(ScriptForbiddenScope::IsScriptForbidden());
|
||||
TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase");
|
||||
// While printing or capturing a paint preview of a document, the paint walk
|
||||
// is done into a special canvas. There is no point doing a normal paint step
|
||||
@@ -2850,17 +2856,11 @@ void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
|
||||
for (PaintLayerScrollableArea* area : *animating_scrollable_areas)
|
||||
area->UpdateCompositorScrollAnimations();
|
||||
}
|
||||
- {
|
||||
- // Updating animations can notify ready promises which could mutate
|
||||
- // the DOM. We should delay these until we have finished the lifecycle
|
||||
- // update. https://crbug.com/1196781
|
||||
- ScriptForbiddenScope forbid_script;
|
||||
- frame_view.GetLayoutView()
|
||||
- ->GetDocument()
|
||||
- .GetDocumentAnimations()
|
||||
- .UpdateAnimations(DocumentLifecycle::kPaintClean,
|
||||
- paint_artifact_compositor_.get());
|
||||
- }
|
||||
+ frame_view.GetLayoutView()
|
||||
+ ->GetDocument()
|
||||
+ .GetDocumentAnimations()
|
||||
+ .UpdateAnimations(DocumentLifecycle::kPaintClean,
|
||||
+ paint_artifact_compositor_.get());
|
||||
Document& document = frame_view.GetLayoutView()->GetDocument();
|
||||
total_animations_count +=
|
||||
document.GetDocumentAnimations().GetAnimationsCount();
|
||||
@@ -4454,6 +4454,7 @@ void LocalFrameView::RenderThrottlingStatusChanged() {
|
||||
// so painting the tree should just clear the previous painted output.
|
||||
DCHECK(!IsUpdatingLifecycle());
|
||||
AllowThrottlingScope allow_throtting(*this);
|
||||
+ ScriptForbiddenScope forbid_script;
|
||||
RunPaintLifecyclePhase();
|
||||
}
|
||||
|
||||
@@ -4989,6 +4990,7 @@ void LocalFrameView::RunPaintBenchmark(int repeat_count,
|
||||
// quantization when the time is very small.
|
||||
base::LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval);
|
||||
do {
|
||||
+ ScriptForbiddenScope forbid_script;
|
||||
RunPaintLifecyclePhase(mode);
|
||||
timer.NextLap();
|
||||
} while (!timer.HasTimeLimitExpired());
|
||||
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
|
||||
index e6e0c5b909c4d073963bcbb074bfb091a6ccb83b..618e08fbb5157c06348feee5f0120bd28ed0bc44 100644
|
||||
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
|
||||
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
|
||||
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h"
|
||||
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h"
|
||||
+#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
|
||||
#include "third_party/blink/renderer/platform/graphics/paint_generated_image.h"
|
||||
|
||||
namespace blink {
|
||||
@@ -126,6 +127,10 @@ scoped_refptr<Image> PaintWorklet::Paint(const String& name,
|
||||
layout_object.GetDocument(), layout_object.StyleRef(),
|
||||
paint_definition->NativeInvalidationProperties(),
|
||||
paint_definition->CustomInvalidationProperties());
|
||||
+ // The PaintWorkletGlobalScope is sufficiently isolated that it is safe to
|
||||
+ // run during the lifecycle update without concern for it causing
|
||||
+ // invalidations to the lifecycle.
|
||||
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
|
||||
sk_sp<PaintRecord> paint_record = paint_definition->Paint(
|
||||
container_size, zoom, style_map, data, device_scale_factor);
|
||||
if (!paint_record)
|
||||
204
patches/chromium/cherry-pick-910e9e40d376.patch
Normal file
204
patches/chromium/cherry-pick-910e9e40d376.patch
Normal file
@@ -0,0 +1,204 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Menke <mmenke@chromium.org>
|
||||
Date: Thu, 10 Jun 2021 07:05:07 +0000
|
||||
Subject: Fix URLLoader cleanup on CorsURLLoaderFactory destruction.
|
||||
|
||||
Destroying one URLLoader can result in other URLLoaders getting errors,
|
||||
due to to cache interconnectedness. CorsURLLoaderFactory's destructor
|
||||
was not taking that into account.
|
||||
|
||||
Also fix a bonus bug: HttpCache::Transaction::response_ wasn't being
|
||||
cleared in HttpCache::Transaction::DoHeadersPhaseCannotProceed(), which
|
||||
could result in DCHECKs when calling GetResponseInfo() when a
|
||||
transaction that was waiting on a cached response from another
|
||||
transaction ended up failing.
|
||||
|
||||
[M90]: Fixed trivial conflict
|
||||
|
||||
(cherry picked from commit 2f49a3c69a2184c95f43a395e4f33a3959cb8dbc)
|
||||
|
||||
(cherry picked from commit baf23e3c5b1394982cff718a0e055d4f239245ad)
|
||||
|
||||
Bug: 1209769
|
||||
Change-Id: I2c18caa488767a29011aca1e1b0bace24c1ba8fc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2922826
|
||||
Reviewed-by: Maksim Orlovich <morlovich@chromium.org>
|
||||
Commit-Queue: Matt Menke <mmenke@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/master@{#887522}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2935241
|
||||
Auto-Submit: Matt Menke <mmenke@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4472@{#1433}
|
||||
Cr-Original-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2948654
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Reviewed-by: Artem Sumaneev <asumaneev@google.com>
|
||||
Reviewed-by: Matt Menke <mmenke@chromium.org>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4430@{#1513}
|
||||
Cr-Branched-From: e5ce7dc4f7518237b3d9bb93cccca35d25216cbe-refs/heads/master@{#857950}
|
||||
|
||||
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
|
||||
index bb0b938e71f92c2743df2c12824e8f634f6ed5e2..6a1ccb4657f8de1a14396366b560bc11f4cee829 100644
|
||||
--- a/net/http/http_cache_transaction.cc
|
||||
+++ b/net/http/http_cache_transaction.cc
|
||||
@@ -2115,6 +2115,8 @@ int HttpCache::Transaction::DoHeadersPhaseCannotProceed(int result) {
|
||||
entry_ = nullptr;
|
||||
new_entry_ = nullptr;
|
||||
|
||||
+ SetResponse(HttpResponseInfo());
|
||||
+
|
||||
// Bypass the cache for timeout scenario.
|
||||
if (result == ERR_CACHE_LOCK_TIMEOUT)
|
||||
effective_load_flags_ |= LOAD_DISABLE_CACHE;
|
||||
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
|
||||
index 7e4d57cf7f2f8e4e0aa208f53f83833fc0c68112..bf744d52473e31fb100ccf1644abd5e9122ba669 100644
|
||||
--- a/services/network/cors/cors_url_loader_factory.cc
|
||||
+++ b/services/network/cors/cors_url_loader_factory.cc
|
||||
@@ -228,7 +228,17 @@ CorsURLLoaderFactory::CorsURLLoaderFactory(
|
||||
&CorsURLLoaderFactory::DeleteIfNeeded, base::Unretained(this)));
|
||||
}
|
||||
|
||||
-CorsURLLoaderFactory::~CorsURLLoaderFactory() = default;
|
||||
+CorsURLLoaderFactory::~CorsURLLoaderFactory() {
|
||||
+ // Delete loaders one at a time, since deleting one loader can cause another
|
||||
+ // loader waiting on it to fail synchronously, which could result in the other
|
||||
+ // loader calling DestroyURLLoader().
|
||||
+ while (!loaders_.empty()) {
|
||||
+ // No need to call context_->LoaderDestroyed(), since this method is only
|
||||
+ // called from the NetworkContext's destructor, or when there are no
|
||||
+ // remaining URLLoaders.
|
||||
+ loaders_.erase(loaders_.begin());
|
||||
+ }
|
||||
+}
|
||||
|
||||
void CorsURLLoaderFactory::OnLoaderCreated(
|
||||
std::unique_ptr<mojom::URLLoader> loader) {
|
||||
diff --git a/services/network/cors/cors_url_loader_factory_unittest.cc b/services/network/cors/cors_url_loader_factory_unittest.cc
|
||||
index 13811282f5bc922cce50a2d0c0c041d1cdd586c1..dd3361f818590031b8a843595bea1223e012bf3e 100644
|
||||
--- a/services/network/cors/cors_url_loader_factory_unittest.cc
|
||||
+++ b/services/network/cors/cors_url_loader_factory_unittest.cc
|
||||
@@ -7,7 +7,9 @@
|
||||
#include "base/macros.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
+#include "net/base/load_flags.h"
|
||||
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
|
||||
+#include "net/test/embedded_test_server/embedded_test_server.h"
|
||||
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_builder.h"
|
||||
@@ -49,6 +51,9 @@ class CorsURLLoaderFactoryTest : public testing::Test {
|
||||
protected:
|
||||
// testing::Test implementation.
|
||||
void SetUp() override {
|
||||
+ test_server_.AddDefaultHandlers();
|
||||
+ ASSERT_TRUE(test_server_.Start());
|
||||
+
|
||||
network_service_ = NetworkService::CreateForTesting();
|
||||
|
||||
auto context_params = mojom::NetworkContextParams::New();
|
||||
@@ -68,7 +73,7 @@ class CorsURLLoaderFactoryTest : public testing::Test {
|
||||
auto factory_params = network::mojom::URLLoaderFactoryParams::New();
|
||||
factory_params->process_id = kProcessId;
|
||||
factory_params->request_initiator_origin_lock =
|
||||
- url::Origin::Create(GURL("http://localhost"));
|
||||
+ url::Origin::Create(test_server_.base_url());
|
||||
auto resource_scheduler_client =
|
||||
base::MakeRefCounted<ResourceSchedulerClient>(
|
||||
kProcessId, kRouteId, &resource_scheduler_,
|
||||
@@ -81,15 +86,25 @@ class CorsURLLoaderFactoryTest : public testing::Test {
|
||||
}
|
||||
|
||||
void CreateLoaderAndStart(const ResourceRequest& request) {
|
||||
+ url_loaders_.emplace_back(mojo::Remote<mojom::URLLoader>());
|
||||
+ test_cors_loader_clients_.emplace_back(
|
||||
+ std::make_unique<TestURLLoaderClient>());
|
||||
cors_url_loader_factory_->CreateLoaderAndStart(
|
||||
- url_loader_.BindNewPipeAndPassReceiver(), kRouteId, kRequestId,
|
||||
+ url_loaders_.back().BindNewPipeAndPassReceiver(), kRouteId, kRequestId,
|
||||
mojom::kURLLoadOptionNone, request,
|
||||
- test_cors_loader_client_.CreateRemote(),
|
||||
+ test_cors_loader_clients_.back()->CreateRemote(),
|
||||
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
|
||||
}
|
||||
|
||||
void ResetFactory() { cors_url_loader_factory_.reset(); }
|
||||
|
||||
+ net::test_server::EmbeddedTestServer* test_server() { return &test_server_; }
|
||||
+
|
||||
+ std::vector<std::unique_ptr<TestURLLoaderClient>>&
|
||||
+ test_cors_loader_clients() {
|
||||
+ return test_cors_loader_clients_;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
// Test environment.
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
@@ -99,15 +114,17 @@ class CorsURLLoaderFactoryTest : public testing::Test {
|
||||
std::unique_ptr<NetworkContext> network_context_;
|
||||
mojo::Remote<mojom::NetworkContext> network_context_remote_;
|
||||
|
||||
+ net::test_server::EmbeddedTestServer test_server_;
|
||||
+
|
||||
// CorsURLLoaderFactory instance under tests.
|
||||
std::unique_ptr<mojom::URLLoaderFactory> cors_url_loader_factory_;
|
||||
mojo::Remote<mojom::URLLoaderFactory> cors_url_loader_factory_remote_;
|
||||
|
||||
- // Holds URLLoader that CreateLoaderAndStart() creates.
|
||||
- mojo::Remote<mojom::URLLoader> url_loader_;
|
||||
+ // Holds the URLLoaders that CreateLoaderAndStart() creates.
|
||||
+ std::vector<mojo::Remote<mojom::URLLoader>> url_loaders_;
|
||||
|
||||
- // TestURLLoaderClient that records callback activities.
|
||||
- TestURLLoaderClient test_cors_loader_client_;
|
||||
+ // TestURLLoaderClients that record callback activities.
|
||||
+ std::vector<std::unique_ptr<TestURLLoaderClient>> test_cors_loader_clients_;
|
||||
|
||||
// Holds for allowed origin access lists.
|
||||
OriginAccessList origin_access_list_;
|
||||
@@ -118,7 +135,7 @@ class CorsURLLoaderFactoryTest : public testing::Test {
|
||||
// Regression test for https://crbug.com/906305.
|
||||
TEST_F(CorsURLLoaderFactoryTest, DestructionOrder) {
|
||||
ResourceRequest request;
|
||||
- GURL url("http://localhost");
|
||||
+ GURL url = test_server()->GetURL("/hung");
|
||||
request.mode = mojom::RequestMode::kNoCors;
|
||||
request.credentials_mode = mojom::CredentialsMode::kOmit;
|
||||
request.method = net::HttpRequestHeaders::kGetMethod;
|
||||
@@ -141,5 +158,36 @@ TEST_F(CorsURLLoaderFactoryTest, DestructionOrder) {
|
||||
ResetFactory();
|
||||
}
|
||||
|
||||
+TEST_F(CorsURLLoaderFactoryTest, CleanupWithSharedCacheObjectInUse) {
|
||||
+ // Create a loader for a response that hangs after receiving headers, and run
|
||||
+ // it until headers are received.
|
||||
+ ResourceRequest request;
|
||||
+ GURL url = test_server()->GetURL("/hung-after-headers");
|
||||
+ request.mode = mojom::RequestMode::kNoCors;
|
||||
+ request.credentials_mode = mojom::CredentialsMode::kOmit;
|
||||
+ request.method = net::HttpRequestHeaders::kGetMethod;
|
||||
+ request.url = url;
|
||||
+ request.request_initiator = url::Origin::Create(url);
|
||||
+ CreateLoaderAndStart(request);
|
||||
+ test_cors_loader_clients().back()->RunUntilResponseReceived();
|
||||
+
|
||||
+ // Read only requests will fail synchonously on destruction of the request
|
||||
+ // they're waiting on if they're in the |done_headers_queue| when the other
|
||||
+ // request fails. Make a large number of such requests, spin the message loop
|
||||
+ // so they end up blocked on the hung request, and then destroy all loads. A
|
||||
+ // large number of loaders is needed because they're stored in a set, indexed
|
||||
+ // by address, so teardown order is random.
|
||||
+ request.load_flags =
|
||||
+ net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
|
||||
+ for (int i = 0; i < 10; ++i)
|
||||
+ CreateLoaderAndStart(request);
|
||||
+ base::RunLoop().RunUntilIdle();
|
||||
+
|
||||
+ // This should result in a crash if tearing down one URLLoaderFactory
|
||||
+ // resulting in a another one failing causes a crash during teardown. See
|
||||
+ // https://crbug.com/1209769.
|
||||
+ ResetFactory();
|
||||
+}
|
||||
+
|
||||
} // namespace cors
|
||||
} // namespace network
|
||||
103
patches/chromium/cherry-pick-ac9dc1235e28.patch
Normal file
103
patches/chromium/cherry-pick-ac9dc1235e28.patch
Normal file
@@ -0,0 +1,103 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ilya Nikolaevskiy <ilnik@chromium.org>
|
||||
Date: Mon, 17 May 2021 08:34:41 +0000
|
||||
Subject: Add locks and empty string checks to FakeV4L2Impl
|
||||
|
||||
FakeV4L2Impl is crashed by fuzzer with some weird ASAN errors, which
|
||||
turned out to be a threading issue.
|
||||
|
||||
Bug: 1205059,1196302
|
||||
Change-Id: Ieb3a917c9a4549b655862e69214774e183a70bc3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2883613
|
||||
Reviewed-by: Ricky Liang <jcliang@chromium.org>
|
||||
Commit-Queue: Ilya Nikolaevskiy <ilnik@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#883390}
|
||||
|
||||
diff --git a/media/capture/video/linux/fake_v4l2_impl.cc b/media/capture/video/linux/fake_v4l2_impl.cc
|
||||
index 4a976815d009e68b3740aa71e8c8fd641bf91493..09647474bed3c7c7b34cd9fb161edd2a7d2e170f 100644
|
||||
--- a/media/capture/video/linux/fake_v4l2_impl.cc
|
||||
+++ b/media/capture/video/linux/fake_v4l2_impl.cc
|
||||
@@ -380,10 +380,16 @@ FakeV4L2Impl::~FakeV4L2Impl() = default;
|
||||
|
||||
void FakeV4L2Impl::AddDevice(const std::string& device_name,
|
||||
const FakeV4L2DeviceConfig& config) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
device_configs_.emplace(device_name, config);
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::open(const char* device_name, int flags) {
|
||||
+ if (!device_name)
|
||||
+ return kInvalidId;
|
||||
+
|
||||
+ base::AutoLock lock(lock_);
|
||||
+
|
||||
std::string device_name_as_string(device_name);
|
||||
auto device_configs_iter = device_configs_.find(device_name_as_string);
|
||||
if (device_configs_iter == device_configs_.end())
|
||||
@@ -403,6 +409,7 @@ int FakeV4L2Impl::open(const char* device_name, int flags) {
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::close(int fd) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto device_iter = opened_devices_.find(fd);
|
||||
if (device_iter == opened_devices_.end())
|
||||
return kErrorReturnValue;
|
||||
@@ -412,6 +419,7 @@ int FakeV4L2Impl::close(int fd) {
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::ioctl(int fd, int request, void* argp) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto device_iter = opened_devices_.find(fd);
|
||||
if (device_iter == opened_devices_.end())
|
||||
return EBADF;
|
||||
@@ -518,6 +526,7 @@ void* FakeV4L2Impl::mmap(void* /*start*/,
|
||||
int flags,
|
||||
int fd,
|
||||
off_t offset) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
if (flags & MAP_FIXED) {
|
||||
errno = EINVAL;
|
||||
return MAP_FAILED;
|
||||
@@ -543,10 +552,12 @@ void* FakeV4L2Impl::mmap(void* /*start*/,
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::munmap(void* start, size_t length) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
return kSuccessReturnValue;
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::poll(struct pollfd* ufds, unsigned int nfds, int timeout) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
if (nfds != 1) {
|
||||
// We only support polling of a single device.
|
||||
errno = EINVAL;
|
||||
diff --git a/media/capture/video/linux/fake_v4l2_impl.h b/media/capture/video/linux/fake_v4l2_impl.h
|
||||
index 0a035a97dd8761b08eb4cfdbe2865efc346f0e23..ae7167f95163581c756ab4951717fd4352c67757 100644
|
||||
--- a/media/capture/video/linux/fake_v4l2_impl.h
|
||||
+++ b/media/capture/video/linux/fake_v4l2_impl.h
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
+#include "base/synchronization/lock.h"
|
||||
#include "media/capture/capture_export.h"
|
||||
#include "media/capture/video/linux/v4l2_capture_device.h"
|
||||
#include "media/capture/video/video_capture_device_descriptor.h"
|
||||
@@ -52,11 +53,13 @@ class CAPTURE_EXPORT FakeV4L2Impl : public V4L2CaptureDevice {
|
||||
private:
|
||||
class OpenedDevice;
|
||||
|
||||
- int next_id_to_return_from_open_;
|
||||
- std::map<std::string, FakeV4L2DeviceConfig> device_configs_;
|
||||
- std::map<std::string, int> device_name_to_open_id_map_;
|
||||
+ base::Lock lock_;
|
||||
+
|
||||
+ int next_id_to_return_from_open_ GUARDED_BY(lock_);
|
||||
+ std::map<std::string, FakeV4L2DeviceConfig> device_configs_ GUARDED_BY(lock_);
|
||||
+ std::map<std::string, int> device_name_to_open_id_map_ GUARDED_BY(lock_);
|
||||
std::map<int /*value returned by open()*/, std::unique_ptr<OpenedDevice>>
|
||||
- opened_devices_;
|
||||
+ opened_devices_ GUARDED_BY(lock_);
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
38
patches/chromium/cherry-pick-b77b38a3380c.patch
Normal file
38
patches/chromium/cherry-pick-b77b38a3380c.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brandon Jones <bajones@chromium.org>
|
||||
Date: Wed, 16 Jun 2021 21:47:09 +0000
|
||||
Subject: Ensure that XRLayer includes base EventTarget in Trace
|
||||
|
||||
Trace was skipping a level in the class hierarchy and calling
|
||||
ScriptWrappable::Trace() instead. This was likely the result of the
|
||||
class inheritance changing in the spec a while back and getting updated
|
||||
elsewhere but not here, since it didn't raise any warnings.
|
||||
|
||||
(cherry picked from commit 01b6f7e0a70648d7c7302454993f0bf86d5a0241)
|
||||
|
||||
Bug: 1219857
|
||||
Change-Id: I4ac9f7b037ac5e5dd0e6d670f1d5a30e6344862f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2964533
|
||||
Commit-Queue: Brandon Jones <bajones@chromium.org>
|
||||
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#892650}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2967199
|
||||
Auto-Submit: Brandon Jones <bajones@chromium.org>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4472@{#1492}
|
||||
Cr-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/xr/xr_layer.cc b/third_party/blink/renderer/modules/xr/xr_layer.cc
|
||||
index eaa8603c7354a5c8e71e9a2e6161824063804fb6..aa30a4cec88fa11b342695dc675ab572320e9166 100644
|
||||
--- a/third_party/blink/renderer/modules/xr/xr_layer.cc
|
||||
+++ b/third_party/blink/renderer/modules/xr/xr_layer.cc
|
||||
@@ -21,7 +21,7 @@ const AtomicString& XRLayer::InterfaceName() const {
|
||||
|
||||
void XRLayer::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(session_);
|
||||
- ScriptWrappable::Trace(visitor);
|
||||
+ EventTargetWithInlineData::Trace(visitor);
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
50
patches/chromium/cherry-pick-cd98d7c0dae9.patch
Normal file
50
patches/chromium/cherry-pick-cd98d7c0dae9.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peng Huang <penghuang@chromium.org>
|
||||
Date: Wed, 7 Jul 2021 20:50:53 +0000
|
||||
Subject: Fix UAF problem in SharedImageInterfaceInProcess
|
||||
|
||||
(cherry picked from commit 38b4905f8d877b27bc2d4ccd4cfc0f82b636deea)
|
||||
|
||||
Bug: 1216822
|
||||
Change-Id: I8ae1f7c406e1899e500ee7ddeaaf18230b1cbcb2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2971144
|
||||
Commit-Queue: Peng Huang <penghuang@chromium.org>
|
||||
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Auto-Submit: Peng Huang <penghuang@chromium.org>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#893931}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3011895
|
||||
Auto-Submit: Mason Freed <masonf@chromium.org>
|
||||
Reviewed-by: Peng Huang <penghuang@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4515@{#1369}
|
||||
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
|
||||
|
||||
diff --git a/gpu/ipc/shared_image_interface_in_process.cc b/gpu/ipc/shared_image_interface_in_process.cc
|
||||
index 54f9777201827e4bca5221af373e39dc021ac6a4..53c2dc489c50367986c46a34e8aaf48b68888ec7 100644
|
||||
--- a/gpu/ipc/shared_image_interface_in_process.cc
|
||||
+++ b/gpu/ipc/shared_image_interface_in_process.cc
|
||||
@@ -86,6 +86,8 @@ void SharedImageInterfaceInProcess::DestroyOnGpu(
|
||||
sync_point_client_state_->Destroy();
|
||||
sync_point_client_state_ = nullptr;
|
||||
}
|
||||
+
|
||||
+ context_state_ = nullptr;
|
||||
completion->Signal();
|
||||
}
|
||||
|
||||
diff --git a/gpu/ipc/shared_image_interface_in_process.h b/gpu/ipc/shared_image_interface_in_process.h
|
||||
index 8d74513f041564a416c20cab5616c9453555c547..c169b5a86af3e02ec869aae9cf1bfb150fa2ad69 100644
|
||||
--- a/gpu/ipc/shared_image_interface_in_process.h
|
||||
+++ b/gpu/ipc/shared_image_interface_in_process.h
|
||||
@@ -229,10 +229,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT SharedImageInterfaceInProcess
|
||||
// Accessed on GPU thread.
|
||||
// TODO(weiliangc): Check whether can be removed when !UsesSync().
|
||||
MailboxManager* mailbox_manager_;
|
||||
- // Used to check if context is lost at destruction time.
|
||||
- // TODO(weiliangc): SharedImageInterface should become active observer of
|
||||
- // whether context is lost.
|
||||
- SharedContextState* context_state_;
|
||||
+ scoped_refptr<SharedContextState> context_state_;
|
||||
// Created and only used by this SharedImageInterface.
|
||||
SyncPointManager* sync_point_manager_;
|
||||
scoped_refptr<SyncPointClientState> sync_point_client_state_;
|
||||
197
patches/chromium/cherry-pick-d9556a80a790.patch
Normal file
197
patches/chromium/cherry-pick-d9556a80a790.patch
Normal file
@@ -0,0 +1,197 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Date: Mon, 7 Jun 2021 20:41:16 +0000
|
||||
Subject: A few fixes to the D3D11H264Accelerator
|
||||
|
||||
- Adds a AsD3D11H264Picture method to H264Pictures because sometimes
|
||||
there can be just normal H264Pictures in the DPB and this could cause
|
||||
some invalid variable access as we were statically casting the
|
||||
pointer before.
|
||||
|
||||
- Adds a bounds check just in case there are more than 16 items in the
|
||||
DPB.
|
||||
|
||||
(cherry picked from commit 5a3cf91d0f2352e697017e13f4754989f46f2f3e)
|
||||
|
||||
Bug: 1194689
|
||||
Change-Id: Ief2e1d00b451fbc0585dd0b22b5aff7a6918fa11
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2923118
|
||||
Commit-Queue: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Reviewed-by: Frank Liberato <liberato@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#888267}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2944579
|
||||
Auto-Submit: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4472@{#1455}
|
||||
Cr-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
|
||||
diff --git a/media/gpu/h264_dpb.cc b/media/gpu/h264_dpb.cc
|
||||
index 8ef3bafb255349c6ac602c02a30615f0dd0b7d06..859e184b129f21f6af41b276051ca3a3adc03a7f 100644
|
||||
--- a/media/gpu/h264_dpb.cc
|
||||
+++ b/media/gpu/h264_dpb.cc
|
||||
@@ -55,6 +55,10 @@ VaapiH264Picture* H264Picture::AsVaapiH264Picture() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+D3D11H264Picture* H264Picture::AsD3D11H264Picture() {
|
||||
+ return nullptr;
|
||||
+}
|
||||
+
|
||||
H264DPB::H264DPB() : max_num_pics_(0) {}
|
||||
H264DPB::~H264DPB() = default;
|
||||
|
||||
diff --git a/media/gpu/h264_dpb.h b/media/gpu/h264_dpb.h
|
||||
index 1395f9ecb35302632c49392d11fecb91436cbdf6..36abd4a8984dcb01ce85fc5fffa5ec916ecbf46a 100644
|
||||
--- a/media/gpu/h264_dpb.h
|
||||
+++ b/media/gpu/h264_dpb.h
|
||||
@@ -23,6 +23,7 @@ namespace media {
|
||||
|
||||
class V4L2H264Picture;
|
||||
class VaapiH264Picture;
|
||||
+class D3D11H264Picture;
|
||||
|
||||
// A picture (a frame or a field) in the H.264 spec sense.
|
||||
// See spec at http://www.itu.int/rec/T-REC-H.264
|
||||
@@ -40,6 +41,7 @@ class MEDIA_GPU_EXPORT H264Picture : public CodecPicture {
|
||||
|
||||
virtual V4L2H264Picture* AsV4L2H264Picture();
|
||||
virtual VaapiH264Picture* AsVaapiH264Picture();
|
||||
+ virtual D3D11H264Picture* AsD3D11H264Picture();
|
||||
|
||||
// Values calculated per H.264 specification or taken from slice header.
|
||||
// See spec for more details on each (some names have been converted from
|
||||
diff --git a/media/gpu/windows/d3d11_h264_accelerator.cc b/media/gpu/windows/d3d11_h264_accelerator.cc
|
||||
index e87c1ece44f4c2af44e1c626ae69bfede43a0289..82abc9af5ed4255d5e262d539b4462e6e089fc61 100644
|
||||
--- a/media/gpu/windows/d3d11_h264_accelerator.cc
|
||||
+++ b/media/gpu/windows/d3d11_h264_accelerator.cc
|
||||
@@ -52,6 +52,8 @@ class D3D11H264Picture : public H264Picture {
|
||||
D3D11PictureBuffer* picture;
|
||||
size_t picture_index_;
|
||||
|
||||
+ D3D11H264Picture* AsD3D11H264Picture() override { return this; }
|
||||
+
|
||||
protected:
|
||||
~D3D11H264Picture() override;
|
||||
};
|
||||
@@ -101,10 +103,12 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
|
||||
|
||||
HRESULT hr;
|
||||
for (;;) {
|
||||
+ D3D11H264Picture* d3d11_pic = pic->AsD3D11H264Picture();
|
||||
+ if (!d3d11_pic)
|
||||
+ return DecoderStatus::kFail;
|
||||
hr = video_context_->DecoderBeginFrame(
|
||||
- video_decoder_.Get(),
|
||||
- static_cast<D3D11H264Picture*>(pic.get())->picture->output_view().Get(),
|
||||
- 0, nullptr);
|
||||
+ video_decoder_.Get(), d3d11_pic->picture->output_view().Get(), 0,
|
||||
+ nullptr);
|
||||
|
||||
if (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING) {
|
||||
// Hardware is busy. We should make the call again.
|
||||
@@ -119,7 +123,7 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
|
||||
}
|
||||
|
||||
sps_ = *sps;
|
||||
- for (size_t i = 0; i < 16; i++) {
|
||||
+ for (size_t i = 0; i < media::kRefFrameMaxCount; i++) {
|
||||
ref_frame_list_[i].bPicEntry = 0xFF;
|
||||
field_order_cnt_list_[i][0] = 0;
|
||||
field_order_cnt_list_[i][1] = 0;
|
||||
@@ -132,8 +136,19 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
|
||||
|
||||
int i = 0;
|
||||
for (auto it = dpb.begin(); it != dpb.end(); i++, it++) {
|
||||
- D3D11H264Picture* our_ref_pic = static_cast<D3D11H264Picture*>(it->get());
|
||||
- if (!our_ref_pic->ref)
|
||||
+ // The DPB is supposed to have a maximum of 16 pictures in it, but there's
|
||||
+ // nothing actually stopping it from having more. If we run into this case,
|
||||
+ // something is clearly wrong, and we should just fail decoding rather than
|
||||
+ // try to sort out which pictures really shouldn't be included.
|
||||
+ if (i >= media::kRefFrameMaxCount)
|
||||
+ return DecoderStatus::kFail;
|
||||
+
|
||||
+ D3D11H264Picture* our_ref_pic = it->get()->AsD3D11H264Picture();
|
||||
+ // How does a non-d3d11 picture get here you might ask? The decoder
|
||||
+ // inserts blank H264Picture objects that we can't use as part of filling
|
||||
+ // gaps in frame numbers. If we see one, it's not a reference picture
|
||||
+ // anyway, so skip it.
|
||||
+ if (!our_ref_pic || !our_ref_pic->ref)
|
||||
continue;
|
||||
ref_frame_list_[i].Index7Bits = our_ref_pic->picture_index_;
|
||||
ref_frame_list_[i].AssociatedFlag = our_ref_pic->long_term;
|
||||
@@ -279,9 +294,8 @@ void D3D11H264Accelerator::PicParamsFromSliceHeader(
|
||||
}
|
||||
|
||||
void D3D11H264Accelerator::PicParamsFromPic(DXVA_PicParams_H264* pic_param,
|
||||
- scoped_refptr<H264Picture> pic) {
|
||||
- pic_param->CurrPic.Index7Bits =
|
||||
- static_cast<D3D11H264Picture*>(pic.get())->picture_index_;
|
||||
+ D3D11H264Picture* pic) {
|
||||
+ pic_param->CurrPic.Index7Bits = pic->picture_index_;
|
||||
pic_param->RefPicFlag = pic->ref;
|
||||
pic_param->frame_num = pic->frame_num;
|
||||
|
||||
@@ -314,7 +328,11 @@ DecoderStatus D3D11H264Accelerator::SubmitSlice(
|
||||
if (!PicParamsFromPPS(&pic_param, pps))
|
||||
return DecoderStatus::kFail;
|
||||
PicParamsFromSliceHeader(&pic_param, slice_hdr);
|
||||
- PicParamsFromPic(&pic_param, std::move(pic));
|
||||
+
|
||||
+ D3D11H264Picture* d3d11_pic = pic->AsD3D11H264Picture();
|
||||
+ if (!d3d11_pic)
|
||||
+ return DecoderStatus::kFail;
|
||||
+ PicParamsFromPic(&pic_param, d3d11_pic);
|
||||
|
||||
memcpy(pic_param.RefFrameList, ref_frame_list_,
|
||||
sizeof pic_param.RefFrameList);
|
||||
@@ -573,9 +591,8 @@ void D3D11H264Accelerator::Reset() {
|
||||
}
|
||||
|
||||
bool D3D11H264Accelerator::OutputPicture(scoped_refptr<H264Picture> pic) {
|
||||
- D3D11H264Picture* our_pic = static_cast<D3D11H264Picture*>(pic.get());
|
||||
-
|
||||
- return client_->OutputResult(our_pic, our_pic->picture);
|
||||
+ D3D11H264Picture* our_pic = pic->AsD3D11H264Picture();
|
||||
+ return our_pic && client_->OutputResult(our_pic, our_pic->picture);
|
||||
}
|
||||
|
||||
void D3D11H264Accelerator::RecordFailure(const std::string& reason,
|
||||
diff --git a/media/gpu/windows/d3d11_h264_accelerator.h b/media/gpu/windows/d3d11_h264_accelerator.h
|
||||
index 00e2bd5cecd34f947c15aed1a7f5873b2ba4736c..c927706fb58b0637b6cf27516495028ead95325c 100644
|
||||
--- a/media/gpu/windows/d3d11_h264_accelerator.h
|
||||
+++ b/media/gpu/windows/d3d11_h264_accelerator.h
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
namespace media {
|
||||
|
||||
+constexpr int kRefFrameMaxCount = 16;
|
||||
+
|
||||
class D3D11H264Accelerator;
|
||||
class MediaLog;
|
||||
|
||||
@@ -74,8 +76,7 @@ class D3D11H264Accelerator : public H264Decoder::H264Accelerator {
|
||||
void PicParamsFromSliceHeader(DXVA_PicParams_H264* pic_param,
|
||||
const H264SliceHeader* pps);
|
||||
|
||||
- void PicParamsFromPic(DXVA_PicParams_H264* pic_param,
|
||||
- scoped_refptr<H264Picture> pic);
|
||||
+ void PicParamsFromPic(DXVA_PicParams_H264* pic_param, D3D11H264Picture* pic);
|
||||
|
||||
void SetVideoDecoder(ComD3D11VideoDecoder video_decoder);
|
||||
|
||||
@@ -95,10 +96,10 @@ class D3D11H264Accelerator : public H264Decoder::H264Accelerator {
|
||||
|
||||
// This information set at the beginning of a frame and saved for processing
|
||||
// all the slices.
|
||||
- DXVA_PicEntry_H264 ref_frame_list_[16];
|
||||
+ DXVA_PicEntry_H264 ref_frame_list_[kRefFrameMaxCount];
|
||||
H264SPS sps_;
|
||||
- INT field_order_cnt_list_[16][2];
|
||||
- USHORT frame_num_list_[16];
|
||||
+ INT field_order_cnt_list_[kRefFrameMaxCount][2];
|
||||
+ USHORT frame_num_list_[kRefFrameMaxCount];
|
||||
UINT used_for_reference_flags_;
|
||||
USHORT non_existing_frame_flags_;
|
||||
|
||||
64
patches/chromium/cherry-pick-e2123a8e0943.patch
Normal file
64
patches/chromium/cherry-pick-e2123a8e0943.patch
Normal file
@@ -0,0 +1,64 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tal Pressman <talp@chromium.org>
|
||||
Date: Wed, 21 Jul 2021 09:11:13 +0000
|
||||
Subject: Manually post task to bind FileUtilitiesHost.
|
||||
|
||||
The FileUtilitiesHost binder is posted to a separate sequence, and the
|
||||
ServiceWorkerHost may be destroyed by the time the it runs, causing a
|
||||
UAF.
|
||||
This CL changes it so that, when we try to bind a new receiver, the
|
||||
host's worker_process_id() is obtained first (on the service worker's
|
||||
core thread) and then a task is posted to do the actual binding on a
|
||||
USER_VISIBLE task runner.
|
||||
|
||||
Credit: This issue was first reported (with analysis) by
|
||||
soulchen8650@gmail.com.
|
||||
|
||||
Bug: 1229298
|
||||
Change-Id: I6d5c05a830ba30f6cb98bf2df70a3df3333f3dd9
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3041006
|
||||
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
|
||||
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
|
||||
Commit-Queue: Tal Pressman <talp@google.com>
|
||||
Cr-Commit-Position: refs/heads/master@{#903832}
|
||||
|
||||
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
|
||||
index a45f9d3db09dbc4827c41c254b2b532968930e96..b6f69c1813fc9c66cc6a20205c02cb6e5d810fc5 100644
|
||||
--- a/content/browser/browser_interface_binders.cc
|
||||
+++ b/content/browser/browser_interface_binders.cc
|
||||
@@ -367,10 +367,22 @@ void BindTextSuggestionHostForFrame(
|
||||
}
|
||||
#endif
|
||||
|
||||
+// Get the service worker's worker process ID and post a task to bind the
|
||||
+// receiver on a USER_VISIBLE task runner.
|
||||
+// This is necessary because:
|
||||
+// - Binding the host itself and checking the ID on the task's thread may cause
|
||||
+// a UAF if the host has been deleted in the meantime.
|
||||
+// - The process ID is not yet populated at the time `PopulateInterfaceBinders`
|
||||
+// is called.
|
||||
void BindFileUtilitiesHost(
|
||||
- const ServiceWorkerHost* host,
|
||||
+ ServiceWorkerHost* host,
|
||||
mojo::PendingReceiver<blink::mojom::FileUtilitiesHost> receiver) {
|
||||
- FileUtilitiesHostImpl::Create(host->worker_process_id(), std::move(receiver));
|
||||
+ auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
|
||||
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
|
||||
+ task_runner->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce(&FileUtilitiesHostImpl::Create, host->worker_process_id(),
|
||||
+ std::move(receiver)));
|
||||
}
|
||||
|
||||
template <typename WorkerHost, typename Interface>
|
||||
@@ -1122,9 +1134,7 @@ void PopulateServiceWorkerBinders(ServiceWorkerHost* host,
|
||||
|
||||
// static binders
|
||||
map->Add<blink::mojom::FileUtilitiesHost>(
|
||||
- base::BindRepeating(&BindFileUtilitiesHost, host),
|
||||
- base::ThreadPool::CreateSequencedTaskRunner(
|
||||
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE}));
|
||||
+ base::BindRepeating(&BindFileUtilitiesHost, host));
|
||||
map->Add<shape_detection::mojom::BarcodeDetectionProvider>(
|
||||
base::BindRepeating(&BindBarcodeDetectionProvider));
|
||||
map->Add<shape_detection::mojom::FaceDetectionProvider>(
|
||||
35
patches/chromium/cherry-pick-e60cc80ff744.patch
Normal file
35
patches/chromium/cherry-pick-e60cc80ff744.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shrek Shao <shrekshao@google.com>
|
||||
Date: Tue, 29 Jun 2021 01:17:03 +0000
|
||||
Subject: Fix multidraw validation drawcount + offset out of bounds
|
||||
|
||||
(cherry picked from commit 7d0a12ce19fed024d56b95a692d888fe3ef14e2f)
|
||||
|
||||
Bug: 1219886
|
||||
Change-Id: I8a84664150758370d9a77ee22ac5549bead0e37e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2977850
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Commit-Queue: Kenneth Russell <kbr@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#895423}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2988885
|
||||
Reviewed-by: Shrek Shao <shrekshao@google.com>
|
||||
Reviewed-by: Austin Eng <enga@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4515@{#1101}
|
||||
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
|
||||
index 91de853db2b382a7797d22cf741a84f463a2d5f2..c3cae01c63046ce4b8be2c0b03243e9105ed4f23 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
|
||||
@@ -34,6 +34,11 @@ bool WebGLMultiDrawCommon::ValidateArray(WebGLExtensionScopedContext* scoped,
|
||||
outOfBoundsDescription);
|
||||
return false;
|
||||
}
|
||||
+ if (static_cast<uint64_t>(drawcount) + offset > size) {
|
||||
+ scoped->Context()->SynthesizeGLError(GL_INVALID_OPERATION, function_name,
|
||||
+ "drawcount plus offset out of bounds");
|
||||
+ return false;
|
||||
+ }
|
||||
return true;
|
||||
}
|
||||
|
||||
54
patches/chromium/cherry-pick-ee6aee64e24c.patch
Normal file
54
patches/chromium/cherry-pick-ee6aee64e24c.patch
Normal file
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Raymond Toy <rtoy@chromium.org>
|
||||
Date: Wed, 9 Jun 2021 16:46:08 +0000
|
||||
Subject: Add AudioHandler to orphan handlers when context is suspended.
|
||||
|
||||
If the context is suspended, pulling of the audio graph is stopped.
|
||||
But we still need to add the handler in this case so that when the
|
||||
context is resumed, the handler is still alive until it can be safely
|
||||
removed. Hence, we must still add the handler if the context is
|
||||
suspended.
|
||||
|
||||
Test cases from issue 1176218 manually tested with no failures. Also
|
||||
this doesn't cause any regressions in issue 1003807 and issue 1017961.
|
||||
(Manually tested the test cases from those issues.)
|
||||
|
||||
(cherry picked from commit 4a38ea3f1f78e0a0ffc1464e227cee6c1f2fd90b)
|
||||
|
||||
Bug: 1176218
|
||||
Change-Id: Icd927c488505dfee9ff716866f98286e286d546a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2874771
|
||||
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
|
||||
Commit-Queue: Raymond Toy <rtoy@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#881533}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2944893
|
||||
Commit-Queue: Artem Sumaneev <asumaneev@google.com>
|
||||
Owners-Override: Artem Sumaneev <asumaneev@google.com>
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4430@{#1508}
|
||||
Cr-Branched-From: e5ce7dc4f7518237b3d9bb93cccca35d25216cbe-refs/heads/master@{#857950}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node.cc b/third_party/blink/renderer/modules/webaudio/audio_node.cc
|
||||
index 80a044235e4ff552eb696e8627f74927f622aae0..c036d175f403f239fb67c185f3cef84aabac92f7 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_node.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_node.cc
|
||||
@@ -614,13 +614,13 @@ void AudioNode::Dispose() {
|
||||
BaseAudioContext::GraphAutoLocker locker(context());
|
||||
Handler().Dispose();
|
||||
|
||||
- // Add the handler to the orphan list if the context is pulling on the audio
|
||||
- // graph. This keeps the handler alive until it can be deleted at a safe
|
||||
- // point (in pre/post handler task). If graph isn't being pulled, we can
|
||||
- // delete the handler now since nothing on the audio thread will be touching
|
||||
- // it.
|
||||
+ // Add the handler to the orphan list. This keeps the handler alive until it
|
||||
+ // can be deleted at a safe point (in pre/post handler task). If the graph is
|
||||
+ // being processed, the handler must be added. If the context is suspended,
|
||||
+ // the handler still needs to be added in case the context is resumed.
|
||||
DCHECK(context());
|
||||
- if (context()->IsPullingAudioGraph()) {
|
||||
+ if (context()->IsPullingAudioGraph() ||
|
||||
+ context()->ContextState() == BaseAudioContext::kSuspended) {
|
||||
context()->GetDeferredTaskHandler().AddRenderingOrphanHandler(
|
||||
std::move(handler_));
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Fri, 11 Jun 2021 08:05:05 +0000
|
||||
Subject: Remove container mutation during iteration
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On LongTaskDetector, we call OnLongTaskDetected for all registered
|
||||
observers. Some observers call LongTaskDetector::UnregisterObserver
|
||||
in the callback, which is problematic because container mutation is
|
||||
not allowed during iteration.
|
||||
|
||||
Copy the observer set to avoid the violation.
|
||||
|
||||
(cherry picked from commit 702f4d4ddb963cafb0d133972282dfc803510b75)
|
||||
|
||||
(cherry picked from commit e88c656a9fb4a7bb1c66ddcedae8049a448ebef4)
|
||||
|
||||
Bug: 1210487
|
||||
Change-Id: Iccea748ac144def6884be8cf542cdc3572bed81a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2909934
|
||||
Reviewed-by: Deep Roy <dproy@chromium.org>
|
||||
Reviewed-by: Nicolás Peña Moreno <npm@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/master@{#885033}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2939704
|
||||
Auto-Submit: Yutaka Hirano <yhirano@chromium.org>
|
||||
Owners-Override: Prudhvi Kumar Bommana <pbommana@google.com>
|
||||
Reviewed-by: Prudhvi Kumar Bommana <pbommana@google.com>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4472@{#1443}
|
||||
Cr-Original-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2945126
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Reviewed-by: Artem Sumaneev <asumaneev@google.com>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4430@{#1518}
|
||||
Cr-Branched-From: e5ce7dc4f7518237b3d9bb93cccca35d25216cbe-refs/heads/master@{#857950}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/long_task_detector.cc b/third_party/blink/renderer/core/loader/long_task_detector.cc
|
||||
index 7e1499b1ddde30db2344db6fd9a9d3e7be574033..f040ae5053265fb136c629f106aeefa0b01130f1 100644
|
||||
--- a/third_party/blink/renderer/core/loader/long_task_detector.cc
|
||||
+++ b/third_party/blink/renderer/core/loader/long_task_detector.cc
|
||||
@@ -43,7 +43,10 @@ void LongTaskDetector::DidProcessTask(base::TimeTicks start_time,
|
||||
if ((end_time - start_time) < LongTaskDetector::kLongTaskThreshold)
|
||||
return;
|
||||
|
||||
- for (auto& observer : observers_) {
|
||||
+ // We copy `observers_` because it might be mutated in OnLongTaskDetected,
|
||||
+ // and container mutation is not allowed during iteration.
|
||||
+ const HeapHashSet<Member<LongTaskObserver>> observers = observers_;
|
||||
+ for (auto& observer : observers) {
|
||||
observer->OnLongTaskDetected(start_time, end_time);
|
||||
}
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/loader/long_task_detector_test.cc b/third_party/blink/renderer/core/loader/long_task_detector_test.cc
|
||||
index 3384fa8ebfb0bd3ad1c408390db3fcb26edc4118..04959d3b682ddbf40577adc5799fe57a9ae9d500 100644
|
||||
--- a/third_party/blink/renderer/core/loader/long_task_detector_test.cc
|
||||
+++ b/third_party/blink/renderer/core/loader/long_task_detector_test.cc
|
||||
@@ -27,9 +27,24 @@ class TestLongTaskObserver :
|
||||
last_long_task_start = start_time;
|
||||
last_long_task_end = end_time;
|
||||
}
|
||||
-}; // Anonymous namespace
|
||||
+};
|
||||
+
|
||||
+class SelfUnregisteringObserver
|
||||
+ : public GarbageCollected<SelfUnregisteringObserver>,
|
||||
+ public LongTaskObserver {
|
||||
+ public:
|
||||
+ void OnLongTaskDetected(base::TimeTicks, base::TimeTicks) override {
|
||||
+ called_ = true;
|
||||
+ LongTaskDetector::Instance().UnregisterObserver(this);
|
||||
+ }
|
||||
+ bool IsCalled() const { return called_; }
|
||||
+
|
||||
+ private:
|
||||
+ bool called_ = false;
|
||||
+};
|
||||
|
||||
} // namespace
|
||||
+
|
||||
class LongTaskDetectorTest : public testing::Test {
|
||||
public:
|
||||
// Public because it's executed on a task queue.
|
||||
@@ -126,4 +141,13 @@ TEST_F(LongTaskDetectorTest, RegisterSameObserverTwice) {
|
||||
long_task_end_when_registered);
|
||||
}
|
||||
|
||||
+TEST_F(LongTaskDetectorTest, SelfUnregisteringObserver) {
|
||||
+ auto* observer = MakeGarbageCollected<SelfUnregisteringObserver>();
|
||||
+
|
||||
+ LongTaskDetector::Instance().RegisterObserver(observer);
|
||||
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
|
||||
+ base::TimeDelta::FromMilliseconds(10));
|
||||
+ EXPECT_TRUE(observer->IsCalled());
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
118
patches/chromium/m90-lts_reduce_memory_consumption_on.patch
Normal file
118
patches/chromium/m90-lts_reduce_memory_consumption_on.patch
Normal file
@@ -0,0 +1,118 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Fri, 11 Jun 2021 08:42:15 +0000
|
||||
Subject: Reduce memory consumption on LongTaskObserver::DidProcessTask
|
||||
|
||||
https://crrev.com/c/2909934 fixed a security issue, but it introduced a
|
||||
copy operation for each DidProcessTask for a long task. We see a memory
|
||||
regression on the change, and this is an attempt to mitigate the
|
||||
regression.
|
||||
|
||||
(cherry picked from commit 8097e73295a88e64d8318d982847a5e4f2bcc4d2)
|
||||
|
||||
(cherry picked from commit 7be6a34fe2f01af881bb074bc616bf5b6b5f7c31)
|
||||
|
||||
Bug: 1210487, 1211539
|
||||
Change-Id: Ib9101e29d70fadb11b7967754e847bb5cc754feb
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2915153
|
||||
Reviewed-by: Benoit L <lizeb@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/master@{#886221}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2944320
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4472@{#1460}
|
||||
Cr-Original-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2948750
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Reviewed-by: Artem Sumaneev <asumaneev@google.com>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4430@{#1520}
|
||||
Cr-Branched-From: e5ce7dc4f7518237b3d9bb93cccca35d25216cbe-refs/heads/master@{#857950}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/long_task_detector.cc b/third_party/blink/renderer/core/loader/long_task_detector.cc
|
||||
index f040ae5053265fb136c629f106aeefa0b01130f1..3816779cfafaef06295734b4a8a2f033bf752691 100644
|
||||
--- a/third_party/blink/renderer/core/loader/long_task_detector.cc
|
||||
+++ b/third_party/blink/renderer/core/loader/long_task_detector.cc
|
||||
@@ -24,6 +24,7 @@ LongTaskDetector::LongTaskDetector() = default;
|
||||
void LongTaskDetector::RegisterObserver(LongTaskObserver* observer) {
|
||||
DCHECK(IsMainThread());
|
||||
DCHECK(observer);
|
||||
+ DCHECK(!iterating_);
|
||||
if (observers_.insert(observer).is_new_entry && observers_.size() == 1) {
|
||||
// Number of observers just became non-zero.
|
||||
Thread::Current()->AddTaskTimeObserver(this);
|
||||
@@ -32,6 +33,10 @@ void LongTaskDetector::RegisterObserver(LongTaskObserver* observer) {
|
||||
|
||||
void LongTaskDetector::UnregisterObserver(LongTaskObserver* observer) {
|
||||
DCHECK(IsMainThread());
|
||||
+ if (iterating_) {
|
||||
+ observers_to_be_removed_.push_back(observer);
|
||||
+ return;
|
||||
+ }
|
||||
observers_.erase(observer);
|
||||
if (observers_.size() == 0) {
|
||||
Thread::Current()->RemoveTaskTimeObserver(this);
|
||||
@@ -43,16 +48,21 @@ void LongTaskDetector::DidProcessTask(base::TimeTicks start_time,
|
||||
if ((end_time - start_time) < LongTaskDetector::kLongTaskThreshold)
|
||||
return;
|
||||
|
||||
- // We copy `observers_` because it might be mutated in OnLongTaskDetected,
|
||||
- // and container mutation is not allowed during iteration.
|
||||
- const HeapHashSet<Member<LongTaskObserver>> observers = observers_;
|
||||
- for (auto& observer : observers) {
|
||||
+ iterating_ = true;
|
||||
+ for (auto& observer : observers_) {
|
||||
observer->OnLongTaskDetected(start_time, end_time);
|
||||
}
|
||||
+ iterating_ = false;
|
||||
+
|
||||
+ for (const auto& observer : observers_to_be_removed_) {
|
||||
+ UnregisterObserver(observer);
|
||||
+ }
|
||||
+ observers_to_be_removed_.clear();
|
||||
}
|
||||
|
||||
void LongTaskDetector::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(observers_);
|
||||
+ visitor->Trace(observers_to_be_removed_);
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/loader/long_task_detector.h b/third_party/blink/renderer/core/loader/long_task_detector.h
|
||||
index dc6f0dbab5c059b83bfe4212f0126e9690ab1a7f..5fd4bb8d2abcc67dd4e47927daa260fa37bc4aca 100644
|
||||
--- a/third_party/blink/renderer/core/loader/long_task_detector.h
|
||||
+++ b/third_party/blink/renderer/core/loader/long_task_detector.h
|
||||
@@ -49,6 +49,8 @@ class CORE_EXPORT LongTaskDetector final
|
||||
base::TimeTicks end_time) override;
|
||||
|
||||
HeapHashSet<Member<LongTaskObserver>> observers_;
|
||||
+ HeapVector<Member<LongTaskObserver>> observers_to_be_removed_;
|
||||
+ bool iterating_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LongTaskDetector);
|
||||
};
|
||||
diff --git a/third_party/blink/renderer/core/loader/long_task_detector_test.cc b/third_party/blink/renderer/core/loader/long_task_detector_test.cc
|
||||
index 04959d3b682ddbf40577adc5799fe57a9ae9d500..403ba452362a3fa2a6b24f238bad35d9eb1bac0c 100644
|
||||
--- a/third_party/blink/renderer/core/loader/long_task_detector_test.cc
|
||||
+++ b/third_party/blink/renderer/core/loader/long_task_detector_test.cc
|
||||
@@ -39,6 +39,8 @@ class SelfUnregisteringObserver
|
||||
}
|
||||
bool IsCalled() const { return called_; }
|
||||
|
||||
+ void Reset() { called_ = false; }
|
||||
+
|
||||
private:
|
||||
bool called_ = false;
|
||||
};
|
||||
@@ -148,6 +150,11 @@ TEST_F(LongTaskDetectorTest, SelfUnregisteringObserver) {
|
||||
SimulateTask(LongTaskDetector::kLongTaskThreshold +
|
||||
base::TimeDelta::FromMilliseconds(10));
|
||||
EXPECT_TRUE(observer->IsCalled());
|
||||
+ observer->Reset();
|
||||
+
|
||||
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
|
||||
+ base::TimeDelta::FromMilliseconds(10));
|
||||
+ EXPECT_FALSE(observer->IsCalled());
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
@@ -0,0 +1,574 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dominic Battre <battre@chromium.org>
|
||||
Date: Wed, 7 Jul 2021 20:02:45 +0000
|
||||
Subject: Replace first of two WaitableEvents in CreditCardAccessManager
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
(cherry picked from commit 48cf01e4039fecbe119d8223d1f6072aaf44f258)
|
||||
|
||||
Bug: 1214234
|
||||
Change-Id: I38171be7b38982f25abfbb3dff7a41f19a167764
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3001123
|
||||
Reviewed-by: Jared Saul <jsaul@google.com>
|
||||
Commit-Queue: Dominic Battré <battre@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#898237}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3011066
|
||||
Reviewed-by: Dominic Battré <battre@chromium.org>
|
||||
Reviewed-by: Prudhvi Kumar Bommana <pbommana@google.com>
|
||||
Owners-Override: Prudhvi Kumar Bommana <pbommana@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4515@{#1366}
|
||||
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
|
||||
|
||||
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
|
||||
index 5031372d31e25f8f14905ab1be721c4aaefed7c5..d6254700a20445078cc4c4fa0e821cd2fc3b1a7b 100644
|
||||
--- a/components/autofill/core/browser/BUILD.gn
|
||||
+++ b/components/autofill/core/browser/BUILD.gn
|
||||
@@ -237,6 +237,8 @@ static_library("browser") {
|
||||
"payments/payments_util.cc",
|
||||
"payments/payments_util.h",
|
||||
"payments/risk_data_loader.h",
|
||||
+ "payments/wait_for_signal_or_timeout.cc",
|
||||
+ "payments/wait_for_signal_or_timeout.h",
|
||||
"payments/strike_database.cc",
|
||||
"payments/strike_database.h",
|
||||
"payments/strike_database_integrator_base.cc",
|
||||
@@ -680,6 +682,7 @@ source_set("unit_tests") {
|
||||
"payments/payments_client_unittest.cc",
|
||||
"payments/payments_service_url_unittest.cc",
|
||||
"payments/payments_util_unittest.cc",
|
||||
+ "payments/wait_for_signal_or_timeout_unittest.cc",
|
||||
"payments/strike_database_integrator_test_strike_database_unittest.cc",
|
||||
"payments/strike_database_unittest.cc",
|
||||
"personal_data_manager_unittest.cc",
|
||||
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc
|
||||
index 560f30b57c88049842390095ca53eb2e4302bf63..7cab68d4cc6696329dd4739f51e809aa7877cb53 100644
|
||||
--- a/components/autofill/core/browser/payments/credit_card_access_manager.cc
|
||||
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "base/task/post_task.h"
|
||||
#include "base/task/task_traits.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
-#include "base/threading/sequenced_task_runner_handle.h"
|
||||
#include "base/time/time.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/autofill/core/browser/autofill_client.h"
|
||||
@@ -46,12 +45,6 @@ constexpr int64_t kUnmaskDetailsResponseTimeoutMs = 3 * 1000; // 3 sec
|
||||
// Time to wait between multiple calls to GetUnmaskDetails().
|
||||
constexpr int64_t kDelayForGetUnmaskDetails = 3 * 60 * 1000; // 3 min
|
||||
|
||||
-// Used for asynchronously waiting for |event| to be signaled.
|
||||
-bool WaitForEvent(base::WaitableEvent* event) {
|
||||
- event->declare_only_used_while_idle();
|
||||
- return event->TimedWait(
|
||||
- base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeoutMs));
|
||||
-}
|
||||
} // namespace
|
||||
|
||||
CreditCardAccessManager::CreditCardAccessManager(
|
||||
@@ -64,9 +57,6 @@ CreditCardAccessManager::CreditCardAccessManager(
|
||||
payments_client_(client_->GetPaymentsClient()),
|
||||
personal_data_manager_(personal_data_manager),
|
||||
form_event_logger_(form_event_logger),
|
||||
- ready_to_start_authentication_(
|
||||
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
||||
- base::WaitableEvent::InitialState::NOT_SIGNALED),
|
||||
can_fetch_unmask_details_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
||||
base::WaitableEvent::InitialState::SIGNALED) {
|
||||
}
|
||||
@@ -329,12 +319,10 @@ void CreditCardAccessManager::FetchCreditCard(
|
||||
|
||||
// Wait for |ready_to_start_authentication_| to be signaled by
|
||||
// OnDidGetUnmaskDetails() or until timeout before calling Authenticate().
|
||||
- auto task_runner = base::ThreadPool::CreateTaskRunner({base::MayBlock()});
|
||||
- cancelable_authenticate_task_tracker_.PostTaskAndReplyWithResult(
|
||||
- task_runner.get(), FROM_HERE,
|
||||
- base::BindOnce(&WaitForEvent, &ready_to_start_authentication_),
|
||||
+ ready_to_start_authentication_.OnEventOrTimeOut(
|
||||
base::BindOnce(&CreditCardAccessManager::Authenticate,
|
||||
- weak_ptr_factory_.GetWeakPtr()));
|
||||
+ weak_ptr_factory_.GetWeakPtr()),
|
||||
+ base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeoutMs));
|
||||
} else {
|
||||
Authenticate(get_unmask_details_returned);
|
||||
}
|
||||
@@ -699,7 +687,6 @@ void CreditCardAccessManager::HandleDialogUserResponse(
|
||||
case WebauthnDialogCallbackType::kVerificationCancelled:
|
||||
// TODO(crbug.com/949269): Add tests and logging for canceling verify
|
||||
// pending dialog.
|
||||
- cancelable_authenticate_task_tracker_.TryCancelAll();
|
||||
payments_client_->CancelRequest();
|
||||
SignalCanFetchUnmaskDetails();
|
||||
ready_to_start_authentication_.Reset();
|
||||
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h
|
||||
index 6bdf8b8c647f885aad5784f737e117b3a55bd2be..99f6581b7320312776f52383b8e8e3b7845268a8 100644
|
||||
--- a/components/autofill/core/browser/payments/credit_card_access_manager.h
|
||||
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
|
||||
#include "components/autofill/core/browser/payments/credit_card_cvc_authenticator.h"
|
||||
#include "components/autofill/core/browser/payments/payments_client.h"
|
||||
+#include "components/autofill/core/browser/payments/wait_for_signal_or_timeout.h"
|
||||
#include "components/autofill/core/browser/personal_data_manager.h"
|
||||
|
||||
#if !defined(OS_IOS)
|
||||
@@ -295,11 +296,7 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
|
||||
// Resets when PrepareToFetchCreditCard() is called, if not already reset.
|
||||
// Signaled when OnDidGetUnmaskDetails() is called or after timeout.
|
||||
// Authenticate() is called when signaled.
|
||||
- base::WaitableEvent ready_to_start_authentication_;
|
||||
-
|
||||
- // Tracks the Authenticate() task that is signaled by
|
||||
- // |ready_to_start_authentication_|, allowing it to be canceled if necessary.
|
||||
- base::CancelableTaskTracker cancelable_authenticate_task_tracker_;
|
||||
+ WaitForSignalOrTimeout ready_to_start_authentication_;
|
||||
|
||||
// Required to avoid any unnecessary preflight calls to Payments servers.
|
||||
// Initial state is signaled. Resets when PrepareToFetchCreditCard() is
|
||||
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
|
||||
index faa396e337d60167d759f9a616f4a901ac5b9db6..39507d6f45e318d632d73583ebaf9048120ae15a 100644
|
||||
--- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
|
||||
+++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
|
||||
@@ -139,8 +139,23 @@ class CreditCardAccessManagerTest : public testing::Test {
|
||||
public:
|
||||
CreditCardAccessManagerTest()
|
||||
: task_environment_(
|
||||
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME,
|
||||
base::test::TaskEnvironment::MainThreadType::DEFAULT,
|
||||
- base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
|
||||
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {
|
||||
+ // Advance the mock clock to 2021-01-01, 00:00:00.000.
|
||||
+ base::Time year_2021;
|
||||
+ CHECK(base::Time::FromUTCExploded({.year = 2021,
|
||||
+ .month = 1,
|
||||
+ .day_of_week = 4,
|
||||
+ .day_of_month = 1,
|
||||
+ .hour = 0,
|
||||
+ .minute = 0,
|
||||
+ .second = 0,
|
||||
+ .millisecond = 0},
|
||||
+ &year_2021));
|
||||
+ task_environment_.AdvanceClock(year_2021 -
|
||||
+ task_environment_.GetMockClock()->Now());
|
||||
+ }
|
||||
|
||||
void SetUp() override {
|
||||
autofill_client_.SetPrefs(test::PrefServiceForTesting());
|
||||
@@ -930,6 +945,7 @@ TEST_F(CreditCardAccessManagerTest,
|
||||
|
||||
ResetFetchCreditCard();
|
||||
credit_card_access_manager_->PrepareToFetchCreditCard();
|
||||
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
|
||||
WaitForCallbacks();
|
||||
|
||||
credit_card_access_manager_->FetchCreditCard(local_card,
|
||||
@@ -950,6 +966,7 @@ TEST_F(CreditCardAccessManagerTest,
|
||||
credit_card_access_manager_->PrepareToFetchCreditCard();
|
||||
credit_card_access_manager_->FetchCreditCard(server_card,
|
||||
accessor_->GetWeakPtr());
|
||||
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
|
||||
WaitForCallbacks();
|
||||
|
||||
histogram_tester.ExpectUniqueSample(
|
||||
@@ -1023,6 +1040,8 @@ TEST_F(CreditCardAccessManagerTest, Metrics_LoggingTimedOutCvcFallback) {
|
||||
|
||||
// Mock a delayed response.
|
||||
InvokeDelayedGetUnmaskDetailsResponse();
|
||||
+
|
||||
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
|
||||
WaitForCallbacks();
|
||||
|
||||
histogram_tester.ExpectUniqueSample(
|
||||
@@ -1044,6 +1063,7 @@ TEST_F(CreditCardAccessManagerTest, Metrics_LoggingTimedOutCvcFallback) {
|
||||
credit_card_access_manager_->PrepareToFetchCreditCard();
|
||||
credit_card_access_manager_->FetchCreditCard(server_card,
|
||||
accessor_->GetWeakPtr());
|
||||
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
|
||||
WaitForCallbacks();
|
||||
|
||||
histogram_tester.ExpectUniqueSample(
|
||||
diff --git a/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..713a53e0f006e51f5d9bd64466712bf75b3ba095
|
||||
--- /dev/null
|
||||
+++ b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc
|
||||
@@ -0,0 +1,78 @@
|
||||
+// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "components/autofill/core/browser/payments/wait_for_signal_or_timeout.h"
|
||||
+
|
||||
+#include "base/threading/sequenced_task_runner_handle.h"
|
||||
+
|
||||
+WaitForSignalOrTimeout::WaitForSignalOrTimeout() = default;
|
||||
+WaitForSignalOrTimeout::~WaitForSignalOrTimeout() = default;
|
||||
+
|
||||
+void WaitForSignalOrTimeout::Signal() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
|
||||
+ SignalHandler(/*triggered_by_signal=*/true);
|
||||
+}
|
||||
+
|
||||
+bool WaitForSignalOrTimeout::IsSignaled() const {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
|
||||
+ return state_ == State::kSignalReceived || state_ == State::kDone;
|
||||
+}
|
||||
+
|
||||
+void WaitForSignalOrTimeout::OnEventOrTimeOut(Callback callback,
|
||||
+ base::TimeDelta timeout) {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
|
||||
+ switch (state_) {
|
||||
+ case State::kInitialState:
|
||||
+ callback_ = std::move(callback);
|
||||
+ ++generation_id_; // Invalidate previous OnTimeOut tasks.
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce(&WaitForSignalOrTimeout::OnTimeOut,
|
||||
+ weak_factory_.GetWeakPtr(), generation_id_),
|
||||
+ timeout);
|
||||
+ break;
|
||||
+
|
||||
+ case State::kSignalReceived:
|
||||
+ state_ = State::kDone;
|
||||
+ std::move(callback).Run(
|
||||
+ /*triggered_by_signal=*/in_state_signal_received_due_to_signal_call_);
|
||||
+ break;
|
||||
+
|
||||
+ case State::kDone:
|
||||
+ Reset();
|
||||
+ OnEventOrTimeOut(std::move(callback), timeout);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void WaitForSignalOrTimeout::Reset() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
|
||||
+ state_ = State::kInitialState;
|
||||
+ ++generation_id_;
|
||||
+ callback_ = Callback();
|
||||
+}
|
||||
+
|
||||
+void WaitForSignalOrTimeout::OnTimeOut(int generation_id) {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
|
||||
+ if (generation_id == generation_id_)
|
||||
+ SignalHandler(/*triggered_by_signal=*/false);
|
||||
+}
|
||||
+
|
||||
+void WaitForSignalOrTimeout::SignalHandler(bool triggered_by_signal) {
|
||||
+ switch (state_) {
|
||||
+ case State::kInitialState:
|
||||
+ if (callback_.is_null()) {
|
||||
+ state_ = State::kSignalReceived;
|
||||
+ in_state_signal_received_due_to_signal_call_ = triggered_by_signal;
|
||||
+ } else {
|
||||
+ state_ = State::kDone;
|
||||
+ std::move(callback_).Run(triggered_by_signal);
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case State::kSignalReceived:
|
||||
+ case State::kDone:
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6b2c451245441f784938e4132e2ab03e7d85f9b6
|
||||
--- /dev/null
|
||||
+++ b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h
|
||||
@@ -0,0 +1,100 @@
|
||||
+// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
|
||||
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
|
||||
+
|
||||
+#include "base/callback.h"
|
||||
+#include "base/memory/weak_ptr.h"
|
||||
+#include "base/sequence_checker.h"
|
||||
+#include "base/time/time.h"
|
||||
+
|
||||
+// A WaitForSignalOrTimeout waits for Signal() or a time out and calls a
|
||||
+// callback when either of these happens for the first time.
|
||||
+//
|
||||
+// The WaitForSignalOrTimeout is Reset()-able and ensures that the callback will
|
||||
+// be called at most once (unless Reset() resets the state). The
|
||||
+// WaitForSignalOrTimeout can be destroyed at any time without negative
|
||||
+// side-effects. The callback won't be called in this case. If the Signal()
|
||||
+// arrives before a call for OnEventOrTimeOut(), the callback will be called
|
||||
+// immediately. If a second Signal() arrives, nothing happens. The
|
||||
+// WaitForSignalOrTimeout must be used on single task sequence.
|
||||
+//
|
||||
+// This class provides the bare minimum needed for a Payment task. If there are
|
||||
+// more use cases, feel free to spice it up and move it to base/.
|
||||
+class WaitForSignalOrTimeout {
|
||||
+ public:
|
||||
+ // The passed boolean is true if the callback happened by a call of Signal()
|
||||
+ // (as opposed to a timeout).
|
||||
+ using Callback = base::OnceCallback<void(bool)>;
|
||||
+
|
||||
+ WaitForSignalOrTimeout();
|
||||
+ ~WaitForSignalOrTimeout();
|
||||
+ WaitForSignalOrTimeout(const WaitForSignalOrTimeout&) = delete;
|
||||
+ WaitForSignalOrTimeout& operator=(const WaitForSignalOrTimeout&) = delete;
|
||||
+
|
||||
+ // Triggers |callback_| if it has not been called before, or registers that
|
||||
+ // the signal occurred, so that |callback| of OnEventOrTimeOut() can be
|
||||
+ // called immediately.
|
||||
+ void Signal();
|
||||
+
|
||||
+ // Returns whether Signal() was called at least once or a timeout happened,
|
||||
+ // and Reset() has not been called afterwards. Note that this function does
|
||||
+ // not discriminate whether Signal() was called or a timeout happened.
|
||||
+ // The |callback_|'s parameter has this distinction, though.
|
||||
+ bool IsSignaled() const;
|
||||
+
|
||||
+ // Registers the |callback| and calls it immediately if Signal() was called
|
||||
+ // already. Starts a timeout task, so that |callback| is called if no call of
|
||||
+ // Signal() is observed within |timeout|. A previous timeout is replaced by a
|
||||
+ // new one.
|
||||
+ void OnEventOrTimeOut(Callback callback, base::TimeDelta timeout);
|
||||
+
|
||||
+ // Resets the state machine so that no Signal() was observed, no callback is
|
||||
+ // registered and no timeout task is running.
|
||||
+ void Reset();
|
||||
+
|
||||
+ private:
|
||||
+ enum class State {
|
||||
+ // Signal() has not been called, yet.
|
||||
+ kInitialState,
|
||||
+ // Signal() has been called, but callback is not specified.
|
||||
+ kSignalReceived,
|
||||
+ // callback has been called.
|
||||
+ kDone,
|
||||
+ };
|
||||
+
|
||||
+ // Internal callback for the timeout. |generation_id| is a generation counter
|
||||
+ // to ensure that old, delayed timeout tasks are ignored.
|
||||
+ void OnTimeOut(int generation_id);
|
||||
+
|
||||
+ // Handler for Signal() and OnTimeOut(). Calls |callback_| if appropriate.
|
||||
+ // The parameter is true if this function is called via Signal() and false if
|
||||
+ // the function is called via OnTimeOut(). This parameter is passed to
|
||||
+ // callback.
|
||||
+ void SignalHandler(bool triggered_by_signal);
|
||||
+
|
||||
+ State state_ = State::kInitialState;
|
||||
+
|
||||
+ // This variable is only valid if state_ == State::kSignalReceived. It is
|
||||
+ // true if we moved into this state due to a Signal() call, and false if
|
||||
+ // we moved into this state due to an OnTimeOut() call.
|
||||
+ bool in_state_signal_received_due_to_signal_call_;
|
||||
+
|
||||
+ // As the base::ThreadPool does not support cancelable tasks, we just rely on
|
||||
+ // a generation counter. Every time Reset() or OnEventOrTimeOut() are called,
|
||||
+ // the generation id is incremented. If outdated delayed OnTimeOut() tasks
|
||||
+ // trickle in, we recognize them as tasks for which the |generation_id|
|
||||
+ // parameter is less than the current generation_id_ and ignore them.
|
||||
+ int generation_id_ = 0;
|
||||
+
|
||||
+ // Callback to be called in case of a Signal() or a time out.
|
||||
+ Callback callback_;
|
||||
+
|
||||
+ SEQUENCE_CHECKER(my_sequence_checker_);
|
||||
+
|
||||
+ base::WeakPtrFactory<WaitForSignalOrTimeout> weak_factory_{this};
|
||||
+};
|
||||
+
|
||||
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
|
||||
diff --git a/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc b/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..eda3fd362221cb9c08c893af02ce33a2826c5d6f
|
||||
--- /dev/null
|
||||
+++ b/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc
|
||||
@@ -0,0 +1,188 @@
|
||||
+// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "components/autofill/core/browser/payments/wait_for_signal_or_timeout.h"
|
||||
+
|
||||
+#include "base/test/task_environment.h"
|
||||
+#include "testing/gtest/include/gtest/gtest.h"
|
||||
+
|
||||
+class WaitForSignalOrTimeoutTest : public testing::Test {
|
||||
+ public:
|
||||
+ WaitForSignalOrTimeoutTest() = default;
|
||||
+ ~WaitForSignalOrTimeoutTest() override = default;
|
||||
+
|
||||
+ WaitForSignalOrTimeout::Callback GetCallback() {
|
||||
+ return base::BindOnce(&WaitForSignalOrTimeoutTest::Callback,
|
||||
+ base::Unretained(this));
|
||||
+ }
|
||||
+
|
||||
+ protected:
|
||||
+ void Callback(bool triggered_by_signal) {
|
||||
+ callbacks_++;
|
||||
+ last_callback_triggered_by_signal_ = triggered_by_signal;
|
||||
+ }
|
||||
+
|
||||
+ // Number of observed callbacks.
|
||||
+ int callbacks_ = 0;
|
||||
+
|
||||
+ bool last_callback_triggered_by_signal_ = false;
|
||||
+
|
||||
+ base::test::TaskEnvironment task_env_{
|
||||
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
|
||||
+};
|
||||
+
|
||||
+// WaitForSignalOrTimeout is initialized with a callback and then the Signal()
|
||||
+// happens.
|
||||
+TEST_F(WaitForSignalOrTimeoutTest, InitThenSignal) {
|
||||
+ WaitForSignalOrTimeout wait;
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+ wait.Signal();
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
|
||||
+
|
||||
+ // Another signal call should be ignored.
|
||||
+ wait.Signal();
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+
|
||||
+ // Also the pending timeout should not trigger further callbacks.
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+}
|
||||
+
|
||||
+// A Signal() is registered before the callback.
|
||||
+TEST_F(WaitForSignalOrTimeoutTest, SignalThenInit) {
|
||||
+ WaitForSignalOrTimeout wait;
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+
|
||||
+ // Trigger the signal before a callback handler is registered.
|
||||
+ wait.Signal();
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+
|
||||
+ // Once the callback handler is registered, it should be called immediately.
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
|
||||
+
|
||||
+ // Another signal call should be ignored.
|
||||
+ wait.Signal();
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+
|
||||
+ // Also the pending timeout should not trigger further callbacks.
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+}
|
||||
+
|
||||
+// A timeout occurs before Signal() is called.
|
||||
+TEST_F(WaitForSignalOrTimeoutTest, InitThenTimeout) {
|
||||
+ WaitForSignalOrTimeout wait;
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
|
||||
+
|
||||
+ // A late signal will be ignored.
|
||||
+ wait.Signal();
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+}
|
||||
+
|
||||
+// The WaitForSignalOrTimeout gets destroyed before a Signal() or timeout
|
||||
+// happens.
|
||||
+TEST_F(WaitForSignalOrTimeoutTest, DestroyedBeforeSignal) {
|
||||
+ {
|
||||
+ WaitForSignalOrTimeout wait;
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ }
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+}
|
||||
+
|
||||
+// The WaitForSignalOrTimeout gets signaled, reset, and signaled again.
|
||||
+TEST_F(WaitForSignalOrTimeoutTest, Reset) {
|
||||
+ WaitForSignalOrTimeout wait;
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+ wait.Signal();
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
|
||||
+
|
||||
+ wait.Reset();
|
||||
+
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+
|
||||
+ // This signal does not trigger a callback because none is registered.
|
||||
+ wait.Signal();
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ // Now the callback happens immediately.
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ EXPECT_EQ(2, callbacks_);
|
||||
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
|
||||
+
|
||||
+ wait.Reset();
|
||||
+
|
||||
+ // Finally, we simulate a timeout after the reset.
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
|
||||
+ EXPECT_EQ(3, callbacks_);
|
||||
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
|
||||
+}
|
||||
+
|
||||
+TEST_F(WaitForSignalOrTimeoutTest, OnEventOrTimeOutCalledTwice) {
|
||||
+ WaitForSignalOrTimeout wait;
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+
|
||||
+ // Wait some time but not long enough for the timeout to trigger.
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+
|
||||
+ // This resets the state machine (currently waiting for a signal or timeout)
|
||||
+ // and starts a new wait.
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+
|
||||
+ // Wait some time but not long enough for the timeout to trigger.
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
|
||||
+ // The first timeout should not have triggered anything.
|
||||
+ EXPECT_EQ(0, callbacks_);
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+
|
||||
+ // Wait some more time for the second timeout to kick in.
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(10));
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
|
||||
+
|
||||
+ // This resets the state machine (currently in done state) once more and
|
||||
+ // starts a new wait.
|
||||
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
|
||||
+
|
||||
+ // Wait some time but not long enough for the timeout to trigger.
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
|
||||
+ // The first timeout should not have triggered anything.
|
||||
+ EXPECT_EQ(1, callbacks_);
|
||||
+ EXPECT_FALSE(wait.IsSignaled());
|
||||
+
|
||||
+ // Wait some more time for the second timeout to kick in.
|
||||
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(10));
|
||||
+ EXPECT_EQ(2, callbacks_);
|
||||
+ EXPECT_TRUE(wait.IsSignaled());
|
||||
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
|
||||
+}
|
||||
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Fredrik=20S=C3=B6derqvist?= <fs@opera.com>
|
||||
Date: Fri, 9 Jul 2021 08:44:55 +0000
|
||||
Subject: Set SVGImage::page_ after document install
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We can end up having the associated ImageResource call
|
||||
SVGImage::ResetAnimation() before the Document has been associated with
|
||||
the SVGImage's LocalFrame, but after the link to the initial Document
|
||||
was severed, if a GC is triggered within that window and ends up
|
||||
collecting the last observer of the ImageResource.
|
||||
|
||||
By assigning |SVGImage::page_| after the installing the document, we
|
||||
close this hole since SVGImage::RootElement() (called by
|
||||
SVGImage::ResetAnimation()) will now observe a null Page and return null
|
||||
without attempting to dereference the document.
|
||||
|
||||
Bug: 1216190
|
||||
Change-Id: I26e08848e5b9bd52e3377841eee35e4acc03d320
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3010140
|
||||
Reviewed-by: Stephen Chenney <schenney@chromium.org>
|
||||
Commit-Queue: Fredrik Söderquist <fs@opera.com>
|
||||
Cr-Commit-Position: refs/heads/master@{#899922}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
|
||||
index 2ce8a78b3537c72206e2d3e6d55f9cc1fc5d3208..0dec91614edb0caa6f8e473f027c3be7b8bf1e4e 100644
|
||||
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc
|
||||
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
|
||||
@@ -830,12 +830,15 @@ Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) {
|
||||
// SVG Images are transparent.
|
||||
frame->View()->SetBaseBackgroundColor(Color::kTransparent);
|
||||
|
||||
- page_ = page;
|
||||
-
|
||||
TRACE_EVENT0("blink", "SVGImage::dataChanged::load");
|
||||
|
||||
frame->ForceSynchronousDocumentInstall("image/svg+xml", Data());
|
||||
|
||||
+ // Set up our Page reference after installing our document. This avoids
|
||||
+ // tripping on a non-existing (null) Document if a GC is triggered during the
|
||||
+ // set up and ends up collecting the last owner/observer of this image.
|
||||
+ page_ = page;
|
||||
+
|
||||
// Intrinsic sizing relies on computed style (e.g. font-size and
|
||||
// writing-mode).
|
||||
frame->GetDocument()->UpdateStyleAndLayoutTree();
|
||||
35
patches/chromium/webview_fullscreen.patch
Normal file
35
patches/chromium/webview_fullscreen.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
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: also propagate fullscreen state for outer frame
|
||||
|
||||
When entering fullscreen with Element.requestFullscreen in child frames,
|
||||
the parent frame should also enter fullscreen mode too. Chromium handles
|
||||
this for iframes, but not for webviews as they are essentially main
|
||||
frames instead of child frames.
|
||||
|
||||
This patch makes webviews propagate the fullscreen state to embedder.
|
||||
|
||||
Note that we also need to manually update embedder's
|
||||
`api::WebContents::IsFullscreenForTabOrPending` value.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 2e222a1bf9cb50efa990f875b102001998691f06..385080e04ed3fb6b82a1ed993889913546f0ba20 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -4728,6 +4728,15 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||
notified_instances.insert(parent_site_instance);
|
||||
}
|
||||
|
||||
+ // Entering fullscreen from webview should also notify its outer frame.
|
||||
+ if (frame_tree_node()->render_manager()->IsMainFrameForInnerDelegate()) {
|
||||
+ RenderFrameProxyHost* outer_proxy =
|
||||
+ frame_tree_node()->render_manager()->GetProxyToOuterDelegate();
|
||||
+ DCHECK(outer_proxy);
|
||||
+ outer_proxy->GetAssociatedRemoteFrame()->WillEnterFullscreen(
|
||||
+ options.Clone());
|
||||
+ }
|
||||
+
|
||||
delegate_->EnterFullscreenMode(this, *options);
|
||||
delegate_->FullscreenStateChanged(this, true /* is_fullscreen */,
|
||||
std::move(options));
|
||||
@@ -17,5 +17,9 @@
|
||||
|
||||
"src/electron/patches/nan": "src/third_party/nan",
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle"
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/usrsctp": "src/third_party/usrsctp/usrsctplib",
|
||||
|
||||
"src/electron/patches/sqlite": "src/third_party/sqlite/src"
|
||||
}
|
||||
|
||||
@@ -33,3 +33,4 @@ fix_remove_outdated_--experimental-wasm-bigint_flag.patch
|
||||
fix_parallel_test-crypto-ecdh-convert-key_to_use_compatible_group.patch
|
||||
src_inline_asynccleanuphookhandle_in_headers.patch
|
||||
node-api_faster_threadsafe_function.patch
|
||||
src_add_missing_context_scopes.patch
|
||||
|
||||
49
patches/node/src_add_missing_context_scopes.patch
Normal file
49
patches/node/src_add_missing_context_scopes.patch
Normal file
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anna Henningsen <anna@addaleax.net>
|
||||
Date: Sun, 6 Dec 2020 16:35:06 +0100
|
||||
Subject: src: add missing context scopes
|
||||
|
||||
Add scopes that ensure that the context associated with the
|
||||
current Environment is always entered when working with it.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/36413
|
||||
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
|
||||
Reviewed-By: Gus Caplan <me@gus.host>
|
||||
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
|
||||
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
Reviewed-By: Rich Trott <rtrott@gmail.com>
|
||||
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index 3ad13dd94a0954a447f5ce342a47823217d8b135..64266ea264448dfbe63a4ecad3cc784608ef3ffa 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -501,6 +501,8 @@ void Environment::InitializeLibuv() {
|
||||
[](uv_async_t* async) {
|
||||
Environment* env = ContainerOf(
|
||||
&Environment::task_queues_async_, async);
|
||||
+ HandleScope handle_scope(env->isolate());
|
||||
+ Context::Scope context_scope(env->context());
|
||||
env->RunAndClearNativeImmediates();
|
||||
});
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index de5c455c7a2a85f0676dfa50238c9bf29446ad58..3baf658961a80f91f08e75d728746c4127dab8bc 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -288,6 +288,7 @@ inline void FileHandle::Close() {
|
||||
void FileHandle::CloseReq::Resolve() {
|
||||
Isolate* isolate = env()->isolate();
|
||||
HandleScope scope(isolate);
|
||||
+ Context::Scope context_scope(env()->context());
|
||||
InternalCallbackScope callback_scope(this);
|
||||
Local<Promise> promise = promise_.Get(isolate);
|
||||
Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>();
|
||||
@@ -297,6 +298,7 @@ void FileHandle::CloseReq::Resolve() {
|
||||
void FileHandle::CloseReq::Reject(Local<Value> reason) {
|
||||
Isolate* isolate = env()->isolate();
|
||||
HandleScope scope(isolate);
|
||||
+ Context::Scope context_scope(env()->context());
|
||||
InternalCallbackScope callback_scope(this);
|
||||
Local<Promise> promise = promise_.Get(isolate);
|
||||
Local<Promise::Resolver> resolver = promise.As<Promise::Resolver>();
|
||||
2
patches/sqlite/.patches
Normal file
2
patches/sqlite/.patches
Normal file
@@ -0,0 +1,2 @@
|
||||
utf-8_q_when_20constructing_20the_20synthensized_20select_20sta.patch
|
||||
sqlite_fix_an_undefined-integer-overflow_problem_in_fts3_c.patch
|
||||
@@ -0,0 +1,157 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Darwin Huang <huangdarwin@chromium.org>
|
||||
Date: Wed, 19 May 2021 14:13:15 -0700
|
||||
Subject: sqlite: Fix an undefined-integer-overflow problem in fts3.c.
|
||||
|
||||
Original change: https://sqlite.org/src/info/a0bf931bd712037e
|
||||
|
||||
Bug: 1204066
|
||||
Change-Id: I34704f1cfe36672d10065f4103c91fb4f35d3895
|
||||
|
||||
diff --git a/amalgamation/sqlite3.c b/amalgamation/sqlite3.c
|
||||
index d19e25f98d37686a7fd1bfefe4bd044575abf5d4..175c55f86fa02cbe443b53f656519879f9192765 100644
|
||||
--- a/amalgamation/sqlite3.c
|
||||
+++ b/amalgamation/sqlite3.c
|
||||
@@ -169123,7 +169123,7 @@ static int fts3ScanInteriorNode(
|
||||
char *zBuffer = 0; /* Buffer to load terms into */
|
||||
i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
- sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
+ u64 iChild; /* Block id of child node to descend to */
|
||||
int nBuffer = 0; /* Total term size */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
@@ -169139,8 +169139,8 @@ static int fts3ScanInteriorNode(
|
||||
** table, then there are always 20 bytes of zeroed padding following the
|
||||
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
|
||||
*/
|
||||
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
if( zCsr>zEnd ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -169193,20 +169193,20 @@ static int fts3ScanInteriorNode(
|
||||
*/
|
||||
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
|
||||
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
|
||||
- *piFirst = iChild;
|
||||
+ *piFirst = (i64)iChild;
|
||||
piFirst = 0;
|
||||
}
|
||||
|
||||
if( piLast && cmp<0 ){
|
||||
- *piLast = iChild;
|
||||
+ *piLast = (i64)iChild;
|
||||
piLast = 0;
|
||||
}
|
||||
|
||||
iChild++;
|
||||
};
|
||||
|
||||
- if( piFirst ) *piFirst = iChild;
|
||||
- if( piLast ) *piLast = iChild;
|
||||
+ if( piFirst ) *piFirst = (i64)iChild;
|
||||
+ if( piLast ) *piLast = (i64)iChild;
|
||||
|
||||
finish_scan:
|
||||
sqlite3_free(zBuffer);
|
||||
diff --git a/amalgamation_dev/sqlite3.c b/amalgamation_dev/sqlite3.c
|
||||
index f4c985513fb7cac3930fe9706ddfc5c440dd3e85..c3ec02ed9124d59ee008548491b2b30e996472ef 100644
|
||||
--- a/amalgamation_dev/sqlite3.c
|
||||
+++ b/amalgamation_dev/sqlite3.c
|
||||
@@ -169636,7 +169636,7 @@ static int fts3ScanInteriorNode(
|
||||
char *zBuffer = 0; /* Buffer to load terms into */
|
||||
i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
- sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
+ u64 iChild; /* Block id of child node to descend to */
|
||||
int nBuffer = 0; /* Total term size */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
@@ -169652,8 +169652,8 @@ static int fts3ScanInteriorNode(
|
||||
** table, then there are always 20 bytes of zeroed padding following the
|
||||
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
|
||||
*/
|
||||
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
if( zCsr>zEnd ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -169706,20 +169706,20 @@ static int fts3ScanInteriorNode(
|
||||
*/
|
||||
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
|
||||
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
|
||||
- *piFirst = iChild;
|
||||
+ *piFirst = (i64)iChild;
|
||||
piFirst = 0;
|
||||
}
|
||||
|
||||
if( piLast && cmp<0 ){
|
||||
- *piLast = iChild;
|
||||
+ *piLast = (i64)iChild;
|
||||
piLast = 0;
|
||||
}
|
||||
|
||||
iChild++;
|
||||
};
|
||||
|
||||
- if( piFirst ) *piFirst = iChild;
|
||||
- if( piLast ) *piLast = iChild;
|
||||
+ if( piFirst ) *piFirst = (i64)iChild;
|
||||
+ if( piLast ) *piLast = (i64)iChild;
|
||||
|
||||
finish_scan:
|
||||
sqlite3_free(zBuffer);
|
||||
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
|
||||
index 79dc5c88ceacb823d16889bd36250597361d6186..62b31373c3c3e9b61b3e1daae8d87d9393779b61 100644
|
||||
--- a/ext/fts3/fts3.c
|
||||
+++ b/ext/fts3/fts3.c
|
||||
@@ -1897,7 +1897,7 @@ static int fts3ScanInteriorNode(
|
||||
char *zBuffer = 0; /* Buffer to load terms into */
|
||||
i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
- sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
+ u64 iChild; /* Block id of child node to descend to */
|
||||
int nBuffer = 0; /* Total term size */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
@@ -1913,8 +1913,8 @@ static int fts3ScanInteriorNode(
|
||||
** table, then there are always 20 bytes of zeroed padding following the
|
||||
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
|
||||
*/
|
||||
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
|
||||
if( zCsr>zEnd ){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
@@ -1967,20 +1967,20 @@ static int fts3ScanInteriorNode(
|
||||
*/
|
||||
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
|
||||
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
|
||||
- *piFirst = iChild;
|
||||
+ *piFirst = (i64)iChild;
|
||||
piFirst = 0;
|
||||
}
|
||||
|
||||
if( piLast && cmp<0 ){
|
||||
- *piLast = iChild;
|
||||
+ *piLast = (i64)iChild;
|
||||
piLast = 0;
|
||||
}
|
||||
|
||||
iChild++;
|
||||
};
|
||||
|
||||
- if( piFirst ) *piFirst = iChild;
|
||||
- if( piLast ) *piLast = iChild;
|
||||
+ if( piFirst ) *piFirst = (i64)iChild;
|
||||
+ if( piLast ) *piLast = (i64)iChild;
|
||||
|
||||
finish_scan:
|
||||
sqlite3_free(zBuffer);
|
||||
@@ -0,0 +1,178 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: drh <>
|
||||
Date: Wed, 19 May 2021 21:55:56 +0000
|
||||
Subject: When constructing the synthensized SELECT statement that is used to
|
||||
choose the rows in an UPDATE FROM, make sure the first table is really the
|
||||
table being updated, and not some common-table expression that happens to
|
||||
have the same name. [forum:/forumpost/a274248080|forum post a274248080]. More
|
||||
changes associated with CTE name resolution are pending.
|
||||
|
||||
FossilOrigin-Name: 0f0959c6f95046e8e7887716e0a7de95da18d1e926ab1f919527083a56541db5
|
||||
(cherry picked from commit 1168f810929ede4d8d323a6acf721ff9cd89de90)
|
||||
|
||||
diff --git a/amalgamation/sqlite3.c b/amalgamation/sqlite3.c
|
||||
index 6b4a7899d336d07cf150530440755d25207b594f..d19e25f98d37686a7fd1bfefe4bd044575abf5d4 100644
|
||||
--- a/amalgamation/sqlite3.c
|
||||
+++ b/amalgamation/sqlite3.c
|
||||
@@ -1173,7 +1173,7 @@ extern "C" {
|
||||
*/
|
||||
#define SQLITE_VERSION "3.34.0"
|
||||
#define SQLITE_VERSION_NUMBER 3034000
|
||||
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
|
||||
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -111305,7 +111305,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
|
||||
struct SrcList_item *p
|
||||
){
|
||||
const char *zDb;
|
||||
- assert( p->pSchema==0 || p->zDatabase==0 );
|
||||
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
|
||||
if( p->pSchema ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
|
||||
zDb = pParse->db->aDb[iDb].zDbSName;
|
||||
@@ -138346,6 +138346,10 @@ static void updateFromSelect(
|
||||
|
||||
assert( pTabList->nSrc>1 );
|
||||
if( pSrc ){
|
||||
+ if( pSrc->a[0].zDatabase==0 ){
|
||||
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
|
||||
+ }
|
||||
pSrc->a[0].iCursor = -1;
|
||||
pSrc->a[0].pTab->nTabRef--;
|
||||
pSrc->a[0].pTab = 0;
|
||||
@@ -231234,9 +231238,9 @@ SQLITE_API int sqlite3_stmt_init(
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
|
||||
|
||||
/************** End of stmt.c ************************************************/
|
||||
-#if __LINE__!=231237
|
||||
+#if __LINE__!=231241
|
||||
#undef SQLITE_SOURCE_ID
|
||||
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
|
||||
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt2"
|
||||
#endif
|
||||
/* Return the source-id for this library */
|
||||
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
|
||||
diff --git a/amalgamation/sqlite3.h b/amalgamation/sqlite3.h
|
||||
index 44be7872663c9216b30ce6e13b1683ca2d807bd6..4935dd32d6aab4261b758c4c199ef0ad18c23ce9 100644
|
||||
--- a/amalgamation/sqlite3.h
|
||||
+++ b/amalgamation/sqlite3.h
|
||||
@@ -125,7 +125,7 @@ extern "C" {
|
||||
*/
|
||||
#define SQLITE_VERSION "3.34.0"
|
||||
#define SQLITE_VERSION_NUMBER 3034000
|
||||
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
|
||||
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
diff --git a/amalgamation_dev/sqlite3.c b/amalgamation_dev/sqlite3.c
|
||||
index d30c9b7dea35e5b4785f78b8bc5789fbc56bba84..f4c985513fb7cac3930fe9706ddfc5c440dd3e85 100644
|
||||
--- a/amalgamation_dev/sqlite3.c
|
||||
+++ b/amalgamation_dev/sqlite3.c
|
||||
@@ -1173,7 +1173,7 @@ extern "C" {
|
||||
*/
|
||||
#define SQLITE_VERSION "3.34.0"
|
||||
#define SQLITE_VERSION_NUMBER 3034000
|
||||
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
|
||||
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -111318,7 +111318,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
|
||||
struct SrcList_item *p
|
||||
){
|
||||
const char *zDb;
|
||||
- assert( p->pSchema==0 || p->zDatabase==0 );
|
||||
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
|
||||
if( p->pSchema ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
|
||||
zDb = pParse->db->aDb[iDb].zDbSName;
|
||||
@@ -138359,6 +138359,10 @@ static void updateFromSelect(
|
||||
|
||||
assert( pTabList->nSrc>1 );
|
||||
if( pSrc ){
|
||||
+ if( pSrc->a[0].zDatabase==0 ){
|
||||
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
|
||||
+ }
|
||||
pSrc->a[0].iCursor = -1;
|
||||
pSrc->a[0].pTab->nTabRef--;
|
||||
pSrc->a[0].pTab = 0;
|
||||
@@ -231747,9 +231751,9 @@ SQLITE_API int sqlite3_stmt_init(
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
|
||||
|
||||
/************** End of stmt.c ************************************************/
|
||||
-#if __LINE__!=231750
|
||||
+#if __LINE__!=231754
|
||||
#undef SQLITE_SOURCE_ID
|
||||
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
|
||||
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt2"
|
||||
#endif
|
||||
/* Return the source-id for this library */
|
||||
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
|
||||
diff --git a/amalgamation_dev/sqlite3.h b/amalgamation_dev/sqlite3.h
|
||||
index 44be7872663c9216b30ce6e13b1683ca2d807bd6..4935dd32d6aab4261b758c4c199ef0ad18c23ce9 100644
|
||||
--- a/amalgamation_dev/sqlite3.h
|
||||
+++ b/amalgamation_dev/sqlite3.h
|
||||
@@ -125,7 +125,7 @@ extern "C" {
|
||||
*/
|
||||
#define SQLITE_VERSION "3.34.0"
|
||||
#define SQLITE_VERSION_NUMBER 3034000
|
||||
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
|
||||
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
diff --git a/manifest b/manifest
|
||||
index 6c9cbb5ed81ca973f03931cea4d861209dee7037..76872d8b3a63cf623a1903ac0ccfc9b80f5c47d3 100644
|
||||
--- a/manifest
|
||||
+++ b/manifest
|
||||
@@ -483,7 +483,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c ee14224322b9e4172d01e691e2f289f6c630ae39b7906f84b72dc780b9e42a76
|
||||
F src/btree.h dcdff4037d75b3f032a5de0d922fcfaf35d48589417f634fa8627362709315f9
|
||||
F src/btreeInt.h ffd66480520d9d70222171b3a026d78b80833b5cea49c89867949f3e023d5f43
|
||||
-F src/build.c f6449d4e85e998e14d3f537e8ea898dca2fcb83c277db3e60945af9b9177db81
|
||||
+F src/build.c 0803beedb8312c4ee4d60e63390ad0480a4ef471a329a56f8887a4b6ffc66da5
|
||||
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
|
||||
@@ -606,7 +606,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 4dc01b267593537e2a0d0efe9f80dabe24c5b6f7627bc6971c487fa6a1dacbbf
|
||||
F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
|
||||
F src/trigger.c 515e79206d40d1d4149129318582e79a6e9db590a7b74e226fdb5b2a6c7e1b10
|
||||
-F src/update.c 9f126204a6acb96bbe47391ae48e0fc579105d8e76a6d9c4fab3271367476580
|
||||
+F src/update.c 3e767f6605ed3adf6085d7e3eb8bbcf7e845b60ebf5590720123b24f907d7414
|
||||
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002
|
||||
diff --git a/src/build.c b/src/build.c
|
||||
index 9779e93732b6d2f50cf5ac3822df1fbe6802eaa6..29d8ea66c105f9098c49ade70246828c92465f96 100644
|
||||
--- a/src/build.c
|
||||
+++ b/src/build.c
|
||||
@@ -451,7 +451,7 @@ Table *sqlite3LocateTableItem(
|
||||
struct SrcList_item *p
|
||||
){
|
||||
const char *zDb;
|
||||
- assert( p->pSchema==0 || p->zDatabase==0 );
|
||||
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
|
||||
if( p->pSchema ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
|
||||
zDb = pParse->db->aDb[iDb].zDbSName;
|
||||
diff --git a/src/update.c b/src/update.c
|
||||
index f8cb2afedb6f9f2931d29d266f65fabcd2cd443c..3e0ec2544a274356c68416d978c8585a143bf8a4 100644
|
||||
--- a/src/update.c
|
||||
+++ b/src/update.c
|
||||
@@ -220,6 +220,10 @@ static void updateFromSelect(
|
||||
|
||||
assert( pTabList->nSrc>1 );
|
||||
if( pSrc ){
|
||||
+ if( pSrc->a[0].zDatabase==0 ){
|
||||
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
|
||||
+ }
|
||||
pSrc->a[0].iCursor = -1;
|
||||
pSrc->a[0].pTab->nTabRef--;
|
||||
pSrc->a[0].pTab = 0;
|
||||
1
patches/usrsctp/.patches
Normal file
1
patches/usrsctp/.patches
Normal file
@@ -0,0 +1 @@
|
||||
improve_restart_handling.patch
|
||||
63
patches/usrsctp/improve_restart_handling.patch
Normal file
63
patches/usrsctp/improve_restart_handling.patch
Normal file
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Tuexen <tuexen@fh-muenster.de>
|
||||
Date: Mon, 3 May 2021 02:29:58 +0200
|
||||
Subject: Improve restart handling.
|
||||
|
||||
This fixes in particular a possible use after free bug reported
|
||||
Anatoly Korniltsev and Taylor Brandstetter for the userland stack.
|
||||
|
||||
diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c
|
||||
index 517189fb6a977da7fd57e8720897574b0fe493ab..289c65c61d7d26e88796f71e1df093a051b9086a 100755
|
||||
--- a/usrsctplib/netinet/sctp_input.c
|
||||
+++ b/usrsctplib/netinet/sctp_input.c
|
||||
@@ -2005,11 +2005,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
/* temp code */
|
||||
if (how_indx < sizeof(asoc->cookie_how))
|
||||
asoc->cookie_how[how_indx] = 12;
|
||||
- sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net,
|
||||
- SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
|
||||
- sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
|
||||
- SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
|
||||
-
|
||||
+ sctp_stop_association_timers(stcb, false);
|
||||
/* notify upper layer */
|
||||
*notification = SCTP_NOTIFY_ASSOC_RESTART;
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
@@ -2042,6 +2038,10 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
asoc->str_reset_seq_in = asoc->init_seq_number;
|
||||
asoc->advanced_peer_ack_point = asoc->last_acked_seq;
|
||||
asoc->send_sack = 1;
|
||||
+ asoc->data_pkts_seen = 0;
|
||||
+ asoc->last_data_chunk_from = NULL;
|
||||
+ asoc->last_control_chunk_from = NULL;
|
||||
+ asoc->last_net_cmt_send_started = NULL;
|
||||
if (asoc->mapping_array) {
|
||||
memset(asoc->mapping_array, 0,
|
||||
asoc->mapping_array_size);
|
||||
@@ -2106,6 +2106,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
|
||||
SCTP_DECR_CHK_COUNT();
|
||||
}
|
||||
+ asoc->ctrl_queue_cnt = 0;
|
||||
+ asoc->str_reset = NULL;
|
||||
+ asoc->stream_reset_outstanding = 0;
|
||||
TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) {
|
||||
TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next);
|
||||
if (chk->data) {
|
||||
@@ -2176,12 +2179,13 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
return (NULL);
|
||||
}
|
||||
/* respond with a COOKIE-ACK */
|
||||
- sctp_stop_all_cookie_timers(stcb);
|
||||
- sctp_toss_old_cookies(stcb, asoc);
|
||||
sctp_send_cookie_ack(stcb);
|
||||
if (how_indx < sizeof(asoc->cookie_how))
|
||||
asoc->cookie_how[how_indx] = 15;
|
||||
-
|
||||
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE) &&
|
||||
+ (asoc->sctp_autoclose_ticks > 0)) {
|
||||
+ sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL);
|
||||
+ }
|
||||
return (stcb);
|
||||
}
|
||||
if (how_indx < sizeof(asoc->cookie_how))
|
||||
@@ -20,3 +20,9 @@ merged_wasm-simd_ia32_fix_f64x2_min_max_to_use_registers.patch
|
||||
merged_const-tracking_generalize_constness_when_delete_properties.patch
|
||||
merged_liftoff_fix_2gb_memory_accesses_on_32-bit.patch
|
||||
reland_compiler_fix_more_truncation_bugs_in_simplifiedlowering.patch
|
||||
cherry-pick-d0aadee1a60a.patch
|
||||
m90-lts_squashed_multiple_commits.patch
|
||||
cherry-pick-b9ad6a864c79.patch
|
||||
cherry-pick-50de6a8ddad9.patch
|
||||
cherry-pick-e76178b896f2.patch
|
||||
merged_compiler_fix_a_bug_in.patch
|
||||
|
||||
107
patches/v8/cherry-pick-50de6a8ddad9.patch
Normal file
107
patches/v8/cherry-pick-50de6a8ddad9.patch
Normal file
@@ -0,0 +1,107 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kim-Anh Tran <kimanh@chromium.org>
|
||||
Date: Thu, 6 May 2021 10:02:01 +0200
|
||||
Subject: M90-LTS: [debugger] Return ServerError if debugger agent is disabled
|
||||
|
||||
This returns a server error on setting breakpoints if the
|
||||
agent is disabled.
|
||||
|
||||
(cherry picked from commit 5aa2de8128f885c44df79d38fb4aa5c6a5d94306)
|
||||
|
||||
Also-by: bmeurer@chromium.org
|
||||
Fixed: chromium:1202534
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: I87c80a4bd785fa5c59a8dd0d5ac5f4b31b015ed8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2874662
|
||||
Commit-Queue: Kim-Anh Tran <kimanh@chromium.org>
|
||||
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
|
||||
Auto-Submit: Kim-Anh Tran <kimanh@chromium.org>
|
||||
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#74399}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2940883
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Commit-Queue: Artem Sumaneev <asumaneev@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/9.0@{#59}
|
||||
Cr-Branched-From: bd0108b4c88e0d6f2350cb79b5f363fbd02f3eb7-refs/heads/9.0.257@{#1}
|
||||
Cr-Branched-From: 349bcc6a075411f1a7ce2d866c3dfeefc2efa39d-refs/heads/master@{#73001}
|
||||
|
||||
diff --git a/src/inspector/v8-debugger-agent-impl.cc b/src/inspector/v8-debugger-agent-impl.cc
|
||||
index 4e0b83952e25d01d8d69cc3c51606a7f48c5f6ee..1ea1c6fab3fd5cbe92d4724f938c569605c1cf44 100644
|
||||
--- a/src/inspector/v8-debugger-agent-impl.cc
|
||||
+++ b/src/inspector/v8-debugger-agent-impl.cc
|
||||
@@ -499,6 +499,8 @@ Response V8DebuggerAgentImpl::setBreakpointByUrl(
|
||||
Maybe<int> optionalColumnNumber, Maybe<String16> optionalCondition,
|
||||
String16* outBreakpointId,
|
||||
std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) {
|
||||
+ if (!enabled()) return Response::ServerError(kDebuggerNotEnabled);
|
||||
+
|
||||
*locations = std::make_unique<Array<protocol::Debugger::Location>>();
|
||||
|
||||
int specified = (optionalURL.isJust() ? 1 : 0) +
|
||||
@@ -587,6 +589,8 @@ Response V8DebuggerAgentImpl::setBreakpoint(
|
||||
String16 breakpointId = generateBreakpointId(
|
||||
BreakpointType::kByScriptId, location->getScriptId(),
|
||||
location->getLineNumber(), location->getColumnNumber(0));
|
||||
+ if (!enabled()) return Response::ServerError(kDebuggerNotEnabled);
|
||||
+
|
||||
if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) !=
|
||||
m_breakpointIdToDebuggerBreakpointIds.end()) {
|
||||
return Response::ServerError(
|
||||
@@ -605,6 +609,8 @@ Response V8DebuggerAgentImpl::setBreakpoint(
|
||||
Response V8DebuggerAgentImpl::setBreakpointOnFunctionCall(
|
||||
const String16& functionObjectId, Maybe<String16> optionalCondition,
|
||||
String16* outBreakpointId) {
|
||||
+ if (!enabled()) return Response::ServerError(kDebuggerNotEnabled);
|
||||
+
|
||||
InjectedScript::ObjectScope scope(m_session, functionObjectId);
|
||||
Response response = scope.initialize();
|
||||
if (!response.IsSuccess()) return response;
|
||||
diff --git a/test/inspector/debugger/set-breakpoint-before-enabling-expected.txt b/test/inspector/debugger/set-breakpoint-before-enabling-expected.txt
|
||||
index 02bfe0d80cdecd96d37988d9d6850b49c5d7e39d..a85aab6fe0c71f3346fe79694d1a334e2cb12fb2 100644
|
||||
--- a/test/inspector/debugger/set-breakpoint-before-enabling-expected.txt
|
||||
+++ b/test/inspector/debugger/set-breakpoint-before-enabling-expected.txt
|
||||
@@ -1,7 +1,13 @@
|
||||
Tests that setting breakpoint before enabling debugger produces an error
|
||||
-setBreakpointByUrl error: undefined
|
||||
+setBreakpointByUrl error: {
|
||||
+ "code": -32000,
|
||||
+ "message": "Debugger agent is not enabled"
|
||||
+}
|
||||
setBreakpoint error: {
|
||||
- "code": -32602,
|
||||
- "message": "Invalid parameters",
|
||||
- "data": "Failed to deserialize params.location - BINDINGS: mandatory field missing at <some position>"
|
||||
+ "code": -32000,
|
||||
+ "message": "Debugger agent is not enabled"
|
||||
+}
|
||||
+setBreakpointOnFunctionCall error: {
|
||||
+ "code": -32000,
|
||||
+ "message": "Debugger agent is not enabled"
|
||||
}
|
||||
diff --git a/test/inspector/debugger/set-breakpoint-before-enabling.js b/test/inspector/debugger/set-breakpoint-before-enabling.js
|
||||
index 5af1085c8747089dea15550949130b8ea243b524..4401466a921692bbe94b52e60083d92769407ee3 100644
|
||||
--- a/test/inspector/debugger/set-breakpoint-before-enabling.js
|
||||
+++ b/test/inspector/debugger/set-breakpoint-before-enabling.js
|
||||
@@ -10,12 +10,19 @@ function didSetBreakpointByUrlBeforeEnable(message)
|
||||
{
|
||||
InspectorTest.log("setBreakpointByUrl error: " + JSON.stringify(
|
||||
InspectorTest.trimErrorMessage(message).error, null, 2));
|
||||
- Protocol.Debugger.setBreakpoint().then(didSetBreakpointBeforeEnable);
|
||||
+ Protocol.Debugger.setBreakpoint({location: { scriptId: "4", lineNumber: 0, columnNumber: 0 }}).then(didSetBreakpointBeforeEnable);
|
||||
}
|
||||
|
||||
function didSetBreakpointBeforeEnable(message)
|
||||
{
|
||||
InspectorTest.log("setBreakpoint error: " + JSON.stringify(
|
||||
InspectorTest.trimErrorMessage(message).error, null, 2));
|
||||
+ Protocol.Debugger.setBreakpointOnFunctionCall({objectId: "4"}).then(didSetBreakpointOnFunctionCallBeforeEnable);
|
||||
+}
|
||||
+
|
||||
+function didSetBreakpointOnFunctionCallBeforeEnable(message)
|
||||
+{
|
||||
+ InspectorTest.log("setBreakpointOnFunctionCall error: " + JSON.stringify(
|
||||
+ InspectorTest.trimErrorMessage(message).error, null, 2));
|
||||
InspectorTest.completeTest();
|
||||
}
|
||||
62
patches/v8/cherry-pick-b9ad6a864c79.patch
Normal file
62
patches/v8/cherry-pick-b9ad6a864c79.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Georg Neis <neis@chromium.org>
|
||||
Date: Thu, 27 May 2021 13:04:30 +0200
|
||||
Subject: Reland "Merged: [compiler] Always record constness dependency for
|
||||
FastDataConstant"
|
||||
|
||||
This is a reland of 638d1b238d510a349bdd38648add8d5c85bc5f7d after a
|
||||
one-character change. A local variable still has a non-optional type
|
||||
in this version of V8.
|
||||
|
||||
Original change's description:
|
||||
> Merged: [compiler] Always record constness dependency for FastDataConstant
|
||||
>
|
||||
> Revision: 1bfa5139966fe0c9e8036fe6362b61c483675775
|
||||
>
|
||||
> BUG=chromium:1209558
|
||||
> NOTRY=true
|
||||
> NOPRESUBMIT=true
|
||||
> NOTREECHECKS=true
|
||||
>
|
||||
> Change-Id: If4f7243647bcc12ed482796c1353f0717630f6b9
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2919823
|
||||
> Commit-Queue: Georg Neis <neis@chromium.org>
|
||||
> Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
> Cr-Commit-Position: refs/branch-heads/9.1@{#59}
|
||||
> Cr-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
|
||||
> Cr-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
|
||||
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
|
||||
(cherry picked from commit 73666e3f6d6bdbc93ab81cf8b3803dd04930e293)
|
||||
|
||||
Bug: chromium:1209558
|
||||
Change-Id: I0c81353882b0f17942fd92ad4181732f941bcb1d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2939991
|
||||
Commit-Queue: Georg Neis <neis@chromium.org>
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/9.1@{#63}
|
||||
Cr-Original-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
|
||||
Cr-Original-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2948651
|
||||
Reviewed-by: Artem Sumaneev <asumaneev@google.com>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/9.0@{#62}
|
||||
Cr-Branched-From: bd0108b4c88e0d6f2350cb79b5f363fbd02f3eb7-refs/heads/9.0.257@{#1}
|
||||
Cr-Branched-From: 349bcc6a075411f1a7ce2d866c3dfeefc2efa39d-refs/heads/master@{#73001}
|
||||
|
||||
diff --git a/src/compiler/access-info.cc b/src/compiler/access-info.cc
|
||||
index ddf742e7089544807d0565d42d6a26bc0dace56f..74f332456f8bcba4b93ae0f211c299293b9fd5b4 100644
|
||||
--- a/src/compiler/access-info.cc
|
||||
+++ b/src/compiler/access-info.cc
|
||||
@@ -897,7 +897,7 @@ PropertyAccessInfo AccessInfoFactory::LookupTransition(
|
||||
// Transitioning stores *may* store to const fields. The resulting
|
||||
// DataConstant access infos can be distinguished from later, i.e. redundant,
|
||||
// stores to the same constant field by the presence of a transition map.
|
||||
- switch (details.constness()) {
|
||||
+ switch (dependencies()->DependOnFieldConstness(transition_map_ref, number)) {
|
||||
case PropertyConstness::kMutable:
|
||||
return PropertyAccessInfo::DataField(
|
||||
zone(), map, std::move(unrecorded_dependencies), field_index,
|
||||
137
patches/v8/cherry-pick-d0aadee1a60a.patch
Normal file
137
patches/v8/cherry-pick-d0aadee1a60a.patch
Normal file
@@ -0,0 +1,137 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Georg Neis <neis@chromium.org>
|
||||
Date: Mon, 7 Jun 2021 10:41:38 +0200
|
||||
Subject: Squashed multiple commits.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Merged: Disable left-trimming when optimizing compile jobs exist
|
||||
Revision: ac0605a1a486b8d074f116cc365de9d2b6d7c9e5
|
||||
|
||||
Merged: [heap] Don't assume that optimizing-compile-dispatcher exists
|
||||
Revision: 022b312d55e75935cfa99cca7729ae2d3f795bd0
|
||||
|
||||
BUG=chromium:1211215,chromium:1215514
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
|
||||
(cherry picked from commit 8704c7c0b2f79cbe745f293b30d68f4505da7416)
|
||||
|
||||
Change-Id: I3b3a37d64402ea464c8e653517928522a1c5e0da
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2940899
|
||||
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
|
||||
Commit-Queue: Georg Neis <neis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/9.1@{#67}
|
||||
Cr-Original-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
|
||||
Cr-Original-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2948656
|
||||
Reviewed-by: Artem Sumaneev <asumaneev@google.com>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/9.0@{#61}
|
||||
Cr-Branched-From: bd0108b4c88e0d6f2350cb79b5f363fbd02f3eb7-refs/heads/9.0.257@{#1}
|
||||
Cr-Branched-From: 349bcc6a075411f1a7ce2d866c3dfeefc2efa39d-refs/heads/master@{#73001}
|
||||
|
||||
diff --git a/src/compiler-dispatcher/optimizing-compile-dispatcher.cc b/src/compiler-dispatcher/optimizing-compile-dispatcher.cc
|
||||
index d00b9b524bf2514eef92653f725764d625a43f6f..67d73367ad9373416fc7efa194430465c12106ea 100644
|
||||
--- a/src/compiler-dispatcher/optimizing-compile-dispatcher.cc
|
||||
+++ b/src/compiler-dispatcher/optimizing-compile-dispatcher.cc
|
||||
@@ -50,7 +50,6 @@ class OptimizingCompileDispatcher::CompileTask : public CancelableTask {
|
||||
worker_thread_runtime_call_stats_(
|
||||
isolate->counters()->worker_thread_runtime_call_stats()),
|
||||
dispatcher_(dispatcher) {
|
||||
- base::MutexGuard lock_guard(&dispatcher_->ref_count_mutex_);
|
||||
++dispatcher_->ref_count_;
|
||||
}
|
||||
|
||||
@@ -98,12 +97,7 @@ class OptimizingCompileDispatcher::CompileTask : public CancelableTask {
|
||||
};
|
||||
|
||||
OptimizingCompileDispatcher::~OptimizingCompileDispatcher() {
|
||||
-#ifdef DEBUG
|
||||
- {
|
||||
- base::MutexGuard lock_guard(&ref_count_mutex_);
|
||||
- DCHECK_EQ(0, ref_count_);
|
||||
- }
|
||||
-#endif
|
||||
+ DCHECK_EQ(0, ref_count_);
|
||||
DCHECK_EQ(0, input_queue_length_);
|
||||
DeleteArray(input_queue_);
|
||||
}
|
||||
@@ -234,6 +228,14 @@ void OptimizingCompileDispatcher::InstallOptimizedFunctions() {
|
||||
}
|
||||
}
|
||||
|
||||
+bool OptimizingCompileDispatcher::HasJobs() {
|
||||
+ DCHECK_EQ(ThreadId::Current(), isolate_->thread_id());
|
||||
+ // Note: This relies on {output_queue_} being mutated by a background thread
|
||||
+ // only when {ref_count_} is not zero. Also, {ref_count_} is never incremented
|
||||
+ // by a background thread.
|
||||
+ return !(ref_count_ == 0 && output_queue_.empty());
|
||||
+}
|
||||
+
|
||||
void OptimizingCompileDispatcher::QueueForOptimization(
|
||||
OptimizedCompilationJob* job) {
|
||||
DCHECK(IsQueueAvailable());
|
||||
diff --git a/src/compiler-dispatcher/optimizing-compile-dispatcher.h b/src/compiler-dispatcher/optimizing-compile-dispatcher.h
|
||||
index 36f285d163101a82e2090d075f69f0f8da82f414..7d7a5bebb74ea4b9fb49cb3c82c9bae1821335a0 100644
|
||||
--- a/src/compiler-dispatcher/optimizing-compile-dispatcher.h
|
||||
+++ b/src/compiler-dispatcher/optimizing-compile-dispatcher.h
|
||||
@@ -53,6 +53,9 @@ class V8_EXPORT_PRIVATE OptimizingCompileDispatcher {
|
||||
|
||||
static bool Enabled() { return FLAG_concurrent_recompilation; }
|
||||
|
||||
+ // This method must be called on the main thread.
|
||||
+ bool HasJobs();
|
||||
+
|
||||
private:
|
||||
class CompileTask;
|
||||
|
||||
@@ -90,7 +93,7 @@ class V8_EXPORT_PRIVATE OptimizingCompileDispatcher {
|
||||
|
||||
int blocked_jobs_;
|
||||
|
||||
- int ref_count_;
|
||||
+ std::atomic<int> ref_count_;
|
||||
base::Mutex ref_count_mutex_;
|
||||
base::ConditionVariable ref_count_zero_;
|
||||
|
||||
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
|
||||
index eb0231b719e7a0325500d3f2074e1e9782e7c4a4..3f4348b063995eb5c23ddd8af2aa2ac900a88723 100644
|
||||
--- a/src/heap/heap.cc
|
||||
+++ b/src/heap/heap.cc
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "src/codegen/compilation-cache.h"
|
||||
#include "src/common/assert-scope.h"
|
||||
#include "src/common/globals.h"
|
||||
+#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/execution/isolate-utils-inl.h"
|
||||
@@ -3014,6 +3015,12 @@ bool Heap::CanMoveObjectStart(HeapObject object) {
|
||||
|
||||
if (IsLargeObject(object)) return false;
|
||||
|
||||
+ // Compilation jobs may have references to the object.
|
||||
+ if (isolate()->concurrent_recompilation_enabled() &&
|
||||
+ isolate()->optimizing_compile_dispatcher()->HasJobs()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
// We can move the object start if the page was already swept.
|
||||
return Page::FromHeapObject(object)->SweepingDone();
|
||||
}
|
||||
diff --git a/test/mjsunit/compiler/regress-1215514.js b/test/mjsunit/compiler/regress-1215514.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a597b310498458fd7219c33ff188ca2a6e543f45
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/compiler/regress-1215514.js
|
||||
@@ -0,0 +1,7 @@
|
||||
+// Copyright 2021 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: --no-concurrent-recompilation
|
||||
+
|
||||
+new Array(4242).shift();
|
||||
65
patches/v8/cherry-pick-e76178b896f2.patch
Normal file
65
patches/v8/cherry-pick-e76178b896f2.patch
Normal file
@@ -0,0 +1,65 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Gomes <victorgomes@chromium.org>
|
||||
Date: Mon, 31 May 2021 13:16:54 +0200
|
||||
Subject: Merged: [JSON] Fix GC issue in BuildJsonObject
|
||||
|
||||
We must ensure that the sweeper is not running or has already swept
|
||||
mutable_double_buffer. Otherwise the GC can add it to the free list.
|
||||
|
||||
Change-Id: If0fc7617acdb6690f0567215b78f8728e1643ec0
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Bug: v8:11837, chromium:1214842
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2993033
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
|
||||
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/9.1@{#75}
|
||||
Cr-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
|
||||
Cr-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
|
||||
|
||||
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
|
||||
index 3f4348b063995eb5c23ddd8af2aa2ac900a88723..5239523c23d63c2af57a3a9795939bd582d7d10c 100644
|
||||
--- a/src/heap/heap.cc
|
||||
+++ b/src/heap/heap.cc
|
||||
@@ -2125,6 +2125,10 @@ void Heap::CompleteSweepingYoung(GarbageCollector collector) {
|
||||
array_buffer_sweeper()->EnsureFinished();
|
||||
}
|
||||
|
||||
+void Heap::EnsureSweepingCompleted() {
|
||||
+ mark_compact_collector()->EnsureSweepingCompleted();
|
||||
+}
|
||||
+
|
||||
void Heap::UpdateCurrentEpoch(GarbageCollector collector) {
|
||||
if (IsYoungGenerationCollector(collector)) {
|
||||
epoch_young_ = next_epoch();
|
||||
diff --git a/src/heap/heap.h b/src/heap/heap.h
|
||||
index 7dc9ef7d447521012c9b110e4fc94589ada3e6f4..b56641f2e1c51197a68d7c96d5bfca428feb1484 100644
|
||||
--- a/src/heap/heap.h
|
||||
+++ b/src/heap/heap.h
|
||||
@@ -1068,6 +1068,8 @@ class Heap {
|
||||
void CompleteSweepingFull();
|
||||
void CompleteSweepingYoung(GarbageCollector collector);
|
||||
|
||||
+ void EnsureSweepingCompleted();
|
||||
+
|
||||
IncrementalMarking* incremental_marking() {
|
||||
return incremental_marking_.get();
|
||||
}
|
||||
diff --git a/src/json/json-parser.cc b/src/json/json-parser.cc
|
||||
index c0109bb77a01f7b6e8e23cd1b2f5d85c4473385b..c9844251cc8659587b3de85066cb0ea993d87014 100644
|
||||
--- a/src/json/json-parser.cc
|
||||
+++ b/src/json/json-parser.cc
|
||||
@@ -633,6 +633,11 @@ Handle<Object> JsonParser<Char>::BuildJsonObject(
|
||||
DCHECK_EQ(mutable_double_address, end);
|
||||
}
|
||||
#endif
|
||||
+ // Before setting the length of mutable_double_buffer back to zero, we
|
||||
+ // must ensure that the sweeper is not running or has already swept the
|
||||
+ // object's page. Otherwise the GC can add the contents of
|
||||
+ // mutable_double_buffer to the free list.
|
||||
+ isolate()->heap()->EnsureSweepingCompleted();
|
||||
mutable_double_buffer->set_length(0);
|
||||
}
|
||||
}
|
||||
299
patches/v8/m90-lts_squashed_multiple_commits.patch
Normal file
299
patches/v8/m90-lts_squashed_multiple_commits.patch
Normal file
@@ -0,0 +1,299 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: "ishell@chromium.org" <ishell@chromium.org>
|
||||
Date: Tue, 8 Jun 2021 17:33:32 +0200
|
||||
Subject: Squashed multiple commits.
|
||||
|
||||
Merged: [runtime] Fix handling of interceptors
|
||||
Revision: f9857fdf74
|
||||
|
||||
Merged: [runtime] Fix handling of interceptors, pt.2
|
||||
Revision: 1f5113816c
|
||||
|
||||
BUG=chromium:1216437
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
|
||||
(cherry picked from commit 1936d568193b37d50d99218724ebbb76785a30d2)
|
||||
|
||||
Change-Id: Ief3da51866c8d0b5e85c76fad00b25ac2379f615
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2947407
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/9.1@{#71}
|
||||
Cr-Original-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
|
||||
Cr-Original-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2948661
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Reviewed-by: Artem Sumaneev <asumaneev@google.com>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/9.0@{#64}
|
||||
Cr-Branched-From: bd0108b4c88e0d6f2350cb79b5f363fbd02f3eb7-refs/heads/9.0.257@{#1}
|
||||
Cr-Branched-From: 349bcc6a075411f1a7ce2d866c3dfeefc2efa39d-refs/heads/master@{#73001}
|
||||
|
||||
diff --git a/src/objects/objects.cc b/src/objects/objects.cc
|
||||
index 5e17fa85fca29e709204950382c610f40d616a64..c5450d50527bb8db1ae67b93aafc4b455b10053b 100644
|
||||
--- a/src/objects/objects.cc
|
||||
+++ b/src/objects/objects.cc
|
||||
@@ -2519,9 +2519,21 @@ Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
|
||||
if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
|
||||
return WriteToReadOnlyProperty(it, value, should_throw);
|
||||
}
|
||||
- if (maybe_attributes.FromJust() == ABSENT) break;
|
||||
- *found = false;
|
||||
- return Nothing<bool>();
|
||||
+ // At this point we might have called interceptor's query or getter
|
||||
+ // callback. Assuming that the callbacks have side effects, we use
|
||||
+ // Object::SetSuperProperty() which works properly regardless on
|
||||
+ // whether the property was present on the receiver or not when
|
||||
+ // storing to the receiver.
|
||||
+ if (maybe_attributes.FromJust() == ABSENT) {
|
||||
+ // Proceed lookup from the next state.
|
||||
+ it->Next();
|
||||
+ } else {
|
||||
+ // Finish lookup in order to make Object::SetSuperProperty() store
|
||||
+ // property to the receiver.
|
||||
+ it->NotFound();
|
||||
+ }
|
||||
+ return Object::SetSuperProperty(it, value, store_origin,
|
||||
+ should_throw);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2596,6 +2608,8 @@ Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
|
||||
if (found) return result;
|
||||
}
|
||||
|
||||
+ // TODO(ishell): refactor this: both SetProperty and and SetSuperProperty have
|
||||
+ // this piece of code.
|
||||
// If the receiver is the JSGlobalObject, the store was contextual. In case
|
||||
// the property did not exist yet on the global object itself, we have to
|
||||
// throw a reference error in strict mode. In sloppy mode, we continue.
|
||||
@@ -2632,6 +2646,8 @@ Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
|
||||
}
|
||||
Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
|
||||
|
||||
+ // Note, the callers rely on the fact that this code is redoing the full own
|
||||
+ // lookup from scratch.
|
||||
LookupIterator::Configuration c = LookupIterator::OWN;
|
||||
LookupIterator own_lookup =
|
||||
it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
|
||||
@@ -2694,6 +2710,25 @@ Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
|
||||
}
|
||||
}
|
||||
|
||||
+ // TODO(ishell): refactor this: both SetProperty and and SetSuperProperty have
|
||||
+ // this piece of code.
|
||||
+ // If the receiver is the JSGlobalObject, the store was contextual. In case
|
||||
+ // the property did not exist yet on the global object itself, we have to
|
||||
+ // throw a reference error in strict mode. In sloppy mode, we continue.
|
||||
+ if (receiver->IsJSGlobalObject() &&
|
||||
+ (GetShouldThrow(isolate, should_throw) == ShouldThrow::kThrowOnError)) {
|
||||
+ if (own_lookup.state() == LookupIterator::TRANSITION) {
|
||||
+ // The property cell that we have created is garbage because we are going
|
||||
+ // to throw now instead of putting it into the global dictionary. However,
|
||||
+ // the cell might already have been stored into the feedback vector, so
|
||||
+ // we must invalidate it nevertheless.
|
||||
+ own_lookup.transition_cell()->ClearAndInvalidate(ReadOnlyRoots(isolate));
|
||||
+ }
|
||||
+ isolate->Throw(*isolate->factory()->NewReferenceError(
|
||||
+ MessageTemplate::kNotDefined, own_lookup.GetName()));
|
||||
+ return Nothing<bool>();
|
||||
+ }
|
||||
+
|
||||
return AddDataProperty(&own_lookup, value, NONE, should_throw, store_origin);
|
||||
}
|
||||
|
||||
diff --git a/test/cctest/test-api-interceptors.cc b/test/cctest/test-api-interceptors.cc
|
||||
index 236053eb45c02201d3425ea2fd98cf3913084bfe..3d3e970fa52b633ffc9e734077e7971ae37306bc 100644
|
||||
--- a/test/cctest/test-api-interceptors.cc
|
||||
+++ b/test/cctest/test-api-interceptors.cc
|
||||
@@ -875,9 +875,11 @@ THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
|
||||
CHECK(!value->BooleanValue(isolate));
|
||||
}
|
||||
|
||||
-static void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
- v8::GenericNamedPropertyQueryCallback query,
|
||||
- const char* source, int expected) {
|
||||
+namespace {
|
||||
+
|
||||
+void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
+ v8::GenericNamedPropertyQueryCallback query,
|
||||
+ const char* source, int expected) {
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
||||
@@ -892,14 +894,13 @@ static void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
CHECK_EQ(expected, value->Int32Value(context.local()).FromJust());
|
||||
}
|
||||
|
||||
-static void CheckInterceptorLoadIC(
|
||||
- v8::GenericNamedPropertyGetterCallback getter, const char* source,
|
||||
- int expected) {
|
||||
+void CheckInterceptorLoadIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
+ const char* source, int expected) {
|
||||
CheckInterceptorIC(getter, nullptr, source, expected);
|
||||
}
|
||||
|
||||
-static void InterceptorLoadICGetter(
|
||||
- Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
+void InterceptorLoadICGetter(Local<Name> name,
|
||||
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
CHECK_EQ(isolate, info.GetIsolate());
|
||||
@@ -909,6 +910,7 @@ static void InterceptorLoadICGetter(
|
||||
info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
|
||||
}
|
||||
|
||||
+} // namespace
|
||||
|
||||
// This test should hit the load IC for the interceptor case.
|
||||
THREADED_TEST(InterceptorLoadIC) {
|
||||
@@ -925,9 +927,23 @@ THREADED_TEST(InterceptorLoadIC) {
|
||||
// configurations of interceptor and explicit fields works fine
|
||||
// (those cases are special cased to get better performance).
|
||||
|
||||
-static void InterceptorLoadXICGetter(
|
||||
+namespace {
|
||||
+
|
||||
+void InterceptorLoadXICGetter(Local<Name> name,
|
||||
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
+ ApiTestFuzzer::Fuzz();
|
||||
+ info.GetReturnValue().Set(
|
||||
+ v8_str("x")
|
||||
+ ->Equals(info.GetIsolate()->GetCurrentContext(), name)
|
||||
+ .FromJust()
|
||||
+ ? v8::Local<v8::Value>(v8::Integer::New(info.GetIsolate(), 42))
|
||||
+ : v8::Local<v8::Value>());
|
||||
+}
|
||||
+
|
||||
+void InterceptorLoadXICGetterWithSideEffects(
|
||||
Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
+ CompileRun("interceptor_getter_side_effect()");
|
||||
info.GetReturnValue().Set(
|
||||
v8_str("x")
|
||||
->Equals(info.GetIsolate()->GetCurrentContext(), name)
|
||||
@@ -936,6 +952,7 @@ static void InterceptorLoadXICGetter(
|
||||
: v8::Local<v8::Value>());
|
||||
}
|
||||
|
||||
+} // namespace
|
||||
|
||||
THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
|
||||
CheckInterceptorLoadIC(InterceptorLoadXICGetter,
|
||||
@@ -1460,6 +1477,18 @@ void HasICQueryToggle(TKey name,
|
||||
isolate, toggle ? v8::internal::ABSENT : v8::internal::NONE));
|
||||
}
|
||||
|
||||
+template <typename TKey, v8::internal::PropertyAttributes attribute>
|
||||
+void HasICQuerySideEffect(TKey name,
|
||||
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
|
||||
+ ApiTestFuzzer::Fuzz();
|
||||
+ v8::Isolate* isolate = CcTest::isolate();
|
||||
+ CHECK_EQ(isolate, info.GetIsolate());
|
||||
+ CompileRun("interceptor_query_side_effect()");
|
||||
+ if (attribute != v8::internal::ABSENT) {
|
||||
+ info.GetReturnValue().Set(v8::Integer::New(isolate, attribute));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int named_query_counter = 0;
|
||||
void NamedQueryCallback(Local<Name> name,
|
||||
const v8::PropertyCallbackInfo<v8::Integer>& info) {
|
||||
@@ -1525,6 +1554,42 @@ THREADED_TEST(InterceptorHasICQueryToggle) {
|
||||
500);
|
||||
}
|
||||
|
||||
+THREADED_TEST(InterceptorStoreICWithSideEffectfulCallbacks) {
|
||||
+ CheckInterceptorIC(EmptyInterceptorGetter,
|
||||
+ HasICQuerySideEffect<Local<Name>, v8::internal::ABSENT>,
|
||||
+ "let r;"
|
||||
+ "let inside_side_effect = false;"
|
||||
+ "let interceptor_query_side_effect = function() {"
|
||||
+ " if (!inside_side_effect) {"
|
||||
+ " inside_side_effect = true;"
|
||||
+ " r.x = 153;"
|
||||
+ " inside_side_effect = false;"
|
||||
+ " }"
|
||||
+ "};"
|
||||
+ "for (var i = 0; i < 20; i++) {"
|
||||
+ " r = { __proto__: o };"
|
||||
+ " r.x = i;"
|
||||
+ "}",
|
||||
+ 19);
|
||||
+
|
||||
+ CheckInterceptorIC(InterceptorLoadXICGetterWithSideEffects,
|
||||
+ nullptr, // query callback is not provided
|
||||
+ "let r;"
|
||||
+ "let inside_side_effect = false;"
|
||||
+ "let interceptor_getter_side_effect = function() {"
|
||||
+ " if (!inside_side_effect) {"
|
||||
+ " inside_side_effect = true;"
|
||||
+ " r.y = 153;"
|
||||
+ " inside_side_effect = false;"
|
||||
+ " }"
|
||||
+ "};"
|
||||
+ "for (var i = 0; i < 20; i++) {"
|
||||
+ " r = { __proto__: o };"
|
||||
+ " r.y = i;"
|
||||
+ "}",
|
||||
+ 19);
|
||||
+}
|
||||
+
|
||||
static void InterceptorStoreICSetter(
|
||||
Local<Name> key, Local<Value> value,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
@@ -1574,6 +1639,52 @@ THREADED_TEST(InterceptorStoreICWithNoSetter) {
|
||||
CHECK_EQ(239 + 42, value->Int32Value(context.local()).FromJust());
|
||||
}
|
||||
|
||||
+THREADED_TEST(EmptyInterceptorDoesNotShadowReadOnlyProperty) {
|
||||
+ // Interceptor should not shadow readonly property 'x' on the prototype, and
|
||||
+ // attempt to store to 'x' must throw.
|
||||
+ CheckInterceptorIC(EmptyInterceptorGetter,
|
||||
+ HasICQuery<Local<Name>, v8::internal::ABSENT>,
|
||||
+ "'use strict';"
|
||||
+ "let p = {};"
|
||||
+ "Object.defineProperty(p, 'x', "
|
||||
+ " {value: 153, writable: false});"
|
||||
+ "o.__proto__ = p;"
|
||||
+ "let result = 0;"
|
||||
+ "let r;"
|
||||
+ "for (var i = 0; i < 20; i++) {"
|
||||
+ " r = { __proto__: o };"
|
||||
+ " try {"
|
||||
+ " r.x = i;"
|
||||
+ " } catch (e) {"
|
||||
+ " result++;"
|
||||
+ " }"
|
||||
+ "}"
|
||||
+ "result",
|
||||
+ 20);
|
||||
+}
|
||||
+
|
||||
+THREADED_TEST(InterceptorShadowsReadOnlyProperty) {
|
||||
+ // Interceptor claims that it has a writable property 'x', so the existence
|
||||
+ // of the readonly property 'x' on the prototype should not cause exceptions.
|
||||
+ CheckInterceptorIC(InterceptorLoadXICGetter,
|
||||
+ nullptr, // query callback
|
||||
+ "'use strict';"
|
||||
+ "let p = {};"
|
||||
+ "Object.defineProperty(p, 'x', "
|
||||
+ " {value: 153, writable: false});"
|
||||
+ "o.__proto__ = p;"
|
||||
+ "let result = 0;"
|
||||
+ "let r;"
|
||||
+ "for (var i = 0; i < 20; i++) {"
|
||||
+ " r = { __proto__: o };"
|
||||
+ " try {"
|
||||
+ " r.x = i;"
|
||||
+ " result++;"
|
||||
+ " } catch (e) {}"
|
||||
+ "}"
|
||||
+ "result",
|
||||
+ 20);
|
||||
+}
|
||||
|
||||
THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
35
patches/v8/merged_compiler_fix_a_bug_in.patch
Normal file
35
patches/v8/merged_compiler_fix_a_bug_in.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Georg Neis <neis@chromium.org>
|
||||
Date: Tue, 13 Jul 2021 17:26:47 +0200
|
||||
Subject: Merged: [compiler] Fix a bug in
|
||||
CodeGenerator::AddTranslationForOperand
|
||||
|
||||
(cherry picked from commit 374354bfe4a30740b96936b33e522d6fcd1cda67)
|
||||
|
||||
Bug: chromium:1228407
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: I358d8736b7b5f87300496cbb39a7689d8207d85f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3027260
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Adam Klein <adamk@chromium.org>
|
||||
Commit-Queue: Adam Klein <adamk@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/9.1@{#77}
|
||||
Cr-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
|
||||
Cr-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
|
||||
|
||||
diff --git a/src/compiler/backend/code-generator.cc b/src/compiler/backend/code-generator.cc
|
||||
index 83f8fbc4e8fdbbfea81ae5b368f0dbcf5b32b5bb..647444fa58b559cda4aaf257b0a477282eafd569 100644
|
||||
--- a/src/compiler/backend/code-generator.cc
|
||||
+++ b/src/compiler/backend/code-generator.cc
|
||||
@@ -1389,7 +1389,8 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
- if (literal.object().equals(info()->closure())) {
|
||||
+ if (literal.object().equals(info()->closure()) &&
|
||||
+ info()->function_context_specializing()) {
|
||||
translation->StoreJSFrameFunction();
|
||||
} else {
|
||||
int literal_id = DefineDeoptimizationLiteral(literal);
|
||||
@@ -14,6 +14,8 @@
|
||||
"parallel/test-child-process-fork-exec-path",
|
||||
"parallel/test-cli-node-print-help",
|
||||
"parallel/test-code-cache",
|
||||
"parallel/test-cluster-bind-privileged-port",
|
||||
"parallel/test-cluster-shared-handle-bind-privileged-port",
|
||||
"parallel/test-crypto",
|
||||
"parallel/test-crypto-aes-wrap",
|
||||
"parallel/test-crypto-authenticated",
|
||||
|
||||
@@ -229,6 +229,7 @@ async function callAppVeyor (targetBranch, job, options) {
|
||||
accountName: 'electron-bot',
|
||||
projectSlug: appVeyorJobs[job],
|
||||
branch: targetBranch,
|
||||
commitId: options.commit || undefined,
|
||||
environmentVariables
|
||||
}),
|
||||
method: 'POST'
|
||||
@@ -364,7 +365,7 @@ if (require.main === module) {
|
||||
if (args._.length < 1) {
|
||||
console.log(`Trigger CI to build release builds of electron.
|
||||
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor|VSTS|DevOps]
|
||||
[--ghRelease] [--armTest] [--circleBuildNum=xxx] [--appveyorJobId=xxx] TARGET_BRANCH
|
||||
[--ghRelease] [--armTest] [--circleBuildNum=xxx] [--appveyorJobId=xxx] [--commit=sha] TARGET_BRANCH
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ const rootPackageJson = require('../../package.json');
|
||||
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
const octokit = new Octokit({
|
||||
userAgent: 'electron-npm-publisher'
|
||||
userAgent: 'electron-npm-publisher',
|
||||
auth: process.env.ELECTRON_GITHUB_TOKEN
|
||||
});
|
||||
|
||||
if (!process.env.ELECTRON_NPM_OTP) {
|
||||
|
||||
@@ -26,6 +26,7 @@ function getLastBumpCommit (tag) {
|
||||
async function revertBumpCommit (tag) {
|
||||
const branch = await getCurrentBranch();
|
||||
const commitToRevert = getLastBumpCommit(tag).hash;
|
||||
await GitProcess.exec(['pull', '--rebase']);
|
||||
await GitProcess.exec(['revert', commitToRevert], ELECTRON_DIR);
|
||||
const pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], ELECTRON_DIR);
|
||||
if (pushDetails.exitCode === 0) {
|
||||
|
||||
@@ -524,4 +524,8 @@ async function validateChecksums (validationArgs) {
|
||||
`shasums defined in ${validationArgs.shaSumFile}.`);
|
||||
}
|
||||
|
||||
makeRelease(args.validateRelease);
|
||||
makeRelease(args.validateRelease)
|
||||
.catch((err) => {
|
||||
console.error('Error occurred while making release:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -103,7 +103,75 @@ namespace crash_reporter {
|
||||
extern const char kCrashpadProcess[];
|
||||
}
|
||||
|
||||
// In 32-bit builds, the main thread starts with the default (small) stack size.
|
||||
// The ARCH_CPU_32_BITS blocks here and below are in support of moving the main
|
||||
// thread to a fiber with a larger stack size.
|
||||
#if defined(ARCH_CPU_32_BITS)
|
||||
// The information needed to transfer control to the large-stack fiber and later
|
||||
// pass the main routine's exit code back to the small-stack fiber prior to
|
||||
// termination.
|
||||
struct FiberState {
|
||||
HINSTANCE instance;
|
||||
LPVOID original_fiber;
|
||||
int fiber_result;
|
||||
};
|
||||
|
||||
// A PFIBER_START_ROUTINE function run on a large-stack fiber that calls the
|
||||
// main routine, stores its return value, and returns control to the small-stack
|
||||
// fiber. |params| must be a pointer to a FiberState struct.
|
||||
void WINAPI FiberBinder(void* params) {
|
||||
auto* fiber_state = static_cast<FiberState*>(params);
|
||||
// Call the wWinMain routine from the fiber. Reusing the entry point minimizes
|
||||
// confusion when examining call stacks in crash reports - seeing wWinMain on
|
||||
// the stack is a handy hint that this is the main thread of the process.
|
||||
fiber_state->fiber_result =
|
||||
wWinMain(fiber_state->instance, nullptr, nullptr, 0);
|
||||
// Switch back to the main thread to exit.
|
||||
::SwitchToFiber(fiber_state->original_fiber);
|
||||
}
|
||||
#endif // defined(ARCH_CPU_32_BITS)
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
#if defined(ARCH_CPU_32_BITS)
|
||||
enum class FiberStatus { kConvertFailed, kCreateFiberFailed, kSuccess };
|
||||
FiberStatus fiber_status = FiberStatus::kSuccess;
|
||||
// GetLastError result if fiber conversion failed.
|
||||
DWORD fiber_error = ERROR_SUCCESS;
|
||||
if (!::IsThreadAFiber()) {
|
||||
// Make the main thread's stack size 4 MiB so that it has roughly the same
|
||||
// effective size as the 64-bit build's 8 MiB stack.
|
||||
constexpr size_t kStackSize = 4 * 1024 * 1024; // 4 MiB
|
||||
// Leak the fiber on exit.
|
||||
LPVOID original_fiber =
|
||||
::ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH);
|
||||
if (original_fiber) {
|
||||
FiberState fiber_state = {instance, original_fiber};
|
||||
// Create a fiber with a bigger stack and switch to it. Leak the fiber on
|
||||
// exit.
|
||||
LPVOID big_stack_fiber = ::CreateFiberEx(
|
||||
0, kStackSize, FIBER_FLAG_FLOAT_SWITCH, FiberBinder, &fiber_state);
|
||||
if (big_stack_fiber) {
|
||||
::SwitchToFiber(big_stack_fiber);
|
||||
// The fibers must be cleaned up to avoid obscure TLS-related shutdown
|
||||
// crashes.
|
||||
::DeleteFiber(big_stack_fiber);
|
||||
::ConvertFiberToThread();
|
||||
// Control returns here after Chrome has finished running on FiberMain.
|
||||
return fiber_state.fiber_result;
|
||||
}
|
||||
fiber_status = FiberStatus::kCreateFiberFailed;
|
||||
} else {
|
||||
fiber_status = FiberStatus::kConvertFailed;
|
||||
}
|
||||
// If we reach here then creating and switching to a fiber has failed. This
|
||||
// probably means we are low on memory and will soon crash. Try to report
|
||||
// this error once crash reporting is initialized.
|
||||
fiber_error = ::GetLastError();
|
||||
base::debug::Alias(&fiber_error);
|
||||
}
|
||||
// If we are already a fiber then continue normal execution.
|
||||
#endif // defined(ARCH_CPU_32_BITS)
|
||||
|
||||
struct Arguments {
|
||||
int argc = 0;
|
||||
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
@@ -198,6 +266,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
return crashpad_status;
|
||||
}
|
||||
|
||||
#if defined(ARCH_CPU_32_BITS)
|
||||
// Intentionally crash if converting to a fiber failed.
|
||||
CHECK_EQ(fiber_status, FiberStatus::kSuccess);
|
||||
#endif // defined(ARCH_CPU_32_BITS)
|
||||
|
||||
if (!electron::CheckCommandLineArguments(arguments.argc, arguments.argv))
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -864,6 +864,10 @@ void BaseWindow::SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) {
|
||||
}
|
||||
|
||||
#if defined(OS_MAC)
|
||||
std::string BaseWindow::GetAlwaysOnTopLevel() {
|
||||
return window_->GetAlwaysOnTopLevel();
|
||||
}
|
||||
|
||||
void BaseWindow::SetTrafficLightPosition(const gfx::Point& position) {
|
||||
window_->SetTrafficLightPosition(position);
|
||||
}
|
||||
@@ -1244,6 +1248,7 @@ void BaseWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("isVisibleOnAllWorkspaces",
|
||||
&BaseWindow::IsVisibleOnAllWorkspaces)
|
||||
#if defined(OS_MAC)
|
||||
.SetMethod("_getAlwaysOnTopLevel", &BaseWindow::GetAlwaysOnTopLevel)
|
||||
.SetMethod("setAutoHideCursor", &BaseWindow::SetAutoHideCursor)
|
||||
#endif
|
||||
.SetMethod("setVibrancy", &BaseWindow::SetVibrancy)
|
||||
|
||||
@@ -191,6 +191,7 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
||||
virtual void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value);
|
||||
|
||||
#if defined(OS_MAC)
|
||||
std::string GetAlwaysOnTopLevel();
|
||||
void SetTrafficLightPosition(const gfx::Point& position);
|
||||
gfx::Point GetTrafficLightPosition() const;
|
||||
#endif
|
||||
|
||||
@@ -394,6 +394,10 @@ void BrowserWindow::ResetBrowserViews() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void BrowserWindow::OnDevToolsResized() {
|
||||
UpdateDraggableRegions(draggable_regions_);
|
||||
}
|
||||
|
||||
void BrowserWindow::SetVibrancy(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> value) {
|
||||
std::string type = gin::V8ToString(isolate, value);
|
||||
|
||||
@@ -63,9 +63,7 @@ class BrowserWindow : public BaseWindow,
|
||||
void OnActivateContents() override;
|
||||
void OnPageTitleUpdated(const base::string16& title,
|
||||
bool explicit_set) override;
|
||||
#if defined(OS_MAC)
|
||||
void OnDevToolsResized() override;
|
||||
#endif
|
||||
|
||||
// NativeWindowObserver:
|
||||
void RequestPreferredWidth(int* width) override;
|
||||
@@ -121,9 +119,7 @@ class BrowserWindow : public BaseWindow,
|
||||
// it should be cancelled when we can prove that the window is responsive.
|
||||
base::CancelableClosure window_unresponsive_closure_;
|
||||
|
||||
#if defined(OS_MAC)
|
||||
std::vector<mojom::DraggableRegionPtr> draggable_regions_;
|
||||
#endif
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
base::WeakPtr<api::WebContents> api_web_contents_;
|
||||
|
||||
@@ -37,10 +37,6 @@ void BrowserWindow::OverrideNSWindowContentView(
|
||||
[contentView viewDidMoveToWindow];
|
||||
}
|
||||
|
||||
void BrowserWindow::OnDevToolsResized() {
|
||||
UpdateDraggableRegions(draggable_regions_);
|
||||
}
|
||||
|
||||
void BrowserWindow::UpdateDraggableRegions(
|
||||
const std::vector<mojom::DraggableRegionPtr>& regions) {
|
||||
if (window_->has_frame())
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "shell/browser/api/electron_api_browser_window.h"
|
||||
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#include "ui/aura/window.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -14,8 +15,20 @@ void BrowserWindow::UpdateDraggableRegions(
|
||||
const std::vector<mojom::DraggableRegionPtr>& regions) {
|
||||
if (window_->has_frame())
|
||||
return;
|
||||
|
||||
if (&draggable_regions_ != ®ions) {
|
||||
auto const offset =
|
||||
web_contents()->GetNativeView()->GetBoundsInRootWindow();
|
||||
auto snapped_regions = mojo::Clone(regions);
|
||||
for (auto& snapped_region : snapped_regions) {
|
||||
snapped_region->bounds.Offset(offset.x(), offset.y());
|
||||
}
|
||||
|
||||
draggable_regions_ = mojo::Clone(snapped_regions);
|
||||
}
|
||||
|
||||
static_cast<NativeWindowViews*>(window_.get())
|
||||
->UpdateDraggableRegions(regions);
|
||||
->UpdateDraggableRegions(draggable_regions_);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -236,7 +236,7 @@ base::string16 Menu::GetToolTipAt(int index) const {
|
||||
return model_->GetToolTipAt(index);
|
||||
}
|
||||
|
||||
#ifdef DCHECK_IS_ON
|
||||
#if DCHECK_IS_ON()
|
||||
base::string16 Menu::GetAcceleratorTextAtForTesting(int index) const {
|
||||
ui::Accelerator accelerator;
|
||||
model_->GetAcceleratorAtWithParams(index, true, &accelerator);
|
||||
@@ -297,7 +297,7 @@ v8::Local<v8::ObjectTemplate> Menu::FillObjectTemplate(
|
||||
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
|
||||
.SetMethod("popupAt", &Menu::PopupAt)
|
||||
.SetMethod("closePopupAt", &Menu::ClosePopupAt)
|
||||
#ifdef DCHECK_IS_ON
|
||||
#if DCHECK_IS_ON()
|
||||
.SetMethod("getAcceleratorTextAt", &Menu::GetAcceleratorTextAtForTesting)
|
||||
#endif
|
||||
.Build();
|
||||
|
||||
@@ -78,7 +78,7 @@ class Menu : public gin::Wrappable<Menu>,
|
||||
int positioning_item,
|
||||
base::OnceClosure callback) = 0;
|
||||
virtual void ClosePopupAt(int32_t window_id) = 0;
|
||||
#ifdef DCHECK_IS_ON
|
||||
#if DCHECK_IS_ON()
|
||||
virtual base::string16 GetAcceleratorTextAtForTesting(int index) const;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class MenuMac : public Menu {
|
||||
int positioning_item,
|
||||
base::OnceClosure callback);
|
||||
void ClosePopupAt(int32_t window_id) override;
|
||||
#ifdef DCHECK_IS_ON
|
||||
#if DCHECK_IS_ON()
|
||||
base::string16 GetAcceleratorTextAtForTesting(int index) const override;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ void MenuMac::ClosePopupAt(int32_t window_id) {
|
||||
std::move(close_popup));
|
||||
}
|
||||
|
||||
#ifdef DCHECK_IS_ON
|
||||
#if DCHECK_IS_ON()
|
||||
base::string16 MenuMac::GetAcceleratorTextAtForTesting(int index) const {
|
||||
// A least effort to get the real shortcut text of NSMenuItem, the code does
|
||||
// not need to be perfect since it is test only.
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
#include "shell/browser/web_contents_zoom_controller.h"
|
||||
#include "shell/browser/web_dialog_helper.h"
|
||||
#include "shell/browser/web_view_guest_delegate.h"
|
||||
#include "shell/browser/web_view_manager.h"
|
||||
#include "shell/common/api/electron_api_native_image.h"
|
||||
#include "shell/common/color_util.h"
|
||||
#include "shell/common/electron_constants.h"
|
||||
@@ -1229,31 +1230,29 @@ void WebContents::OnEnterFullscreenModeForTab(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
const blink::mojom::FullscreenOptions& options,
|
||||
bool allowed) {
|
||||
if (!allowed)
|
||||
return;
|
||||
if (!owner_window_)
|
||||
if (!allowed || !owner_window_)
|
||||
return;
|
||||
|
||||
auto* source = content::WebContents::FromRenderFrameHost(requesting_frame);
|
||||
if (IsFullscreenForTabOrPending(source)) {
|
||||
DCHECK_EQ(fullscreen_frame_, source->GetFocusedFrame());
|
||||
return;
|
||||
}
|
||||
|
||||
SetHtmlApiFullscreen(true);
|
||||
owner_window_->NotifyWindowEnterHtmlFullScreen();
|
||||
|
||||
if (native_fullscreen_) {
|
||||
// Explicitly trigger a view resize, as the size is not actually changing if
|
||||
// the browser is fullscreened, too.
|
||||
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
|
||||
}
|
||||
Emit("enter-html-full-screen");
|
||||
}
|
||||
|
||||
void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
|
||||
if (!owner_window_)
|
||||
return;
|
||||
|
||||
SetHtmlApiFullscreen(false);
|
||||
owner_window_->NotifyWindowLeaveHtmlFullScreen();
|
||||
|
||||
if (native_fullscreen_) {
|
||||
// Explicitly trigger a view resize, as the size is not actually changing if
|
||||
@@ -1261,7 +1260,6 @@ void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
|
||||
// `chrome/browser/ui/exclusive_access/fullscreen_controller.cc`.
|
||||
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
|
||||
}
|
||||
Emit("leave-html-full-screen");
|
||||
}
|
||||
|
||||
void WebContents::RendererUnresponsive(
|
||||
@@ -1740,6 +1738,8 @@ void WebContents::TitleWasSet(content::NavigationEntry* entry) {
|
||||
} else {
|
||||
final_title = title;
|
||||
}
|
||||
} else {
|
||||
final_title = web_contents()->GetTitle();
|
||||
}
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnPageTitleUpdated(final_title, explicit_set);
|
||||
@@ -3464,6 +3464,30 @@ void WebContents::DevToolsSearchInPath(int request_id,
|
||||
file_system_path));
|
||||
}
|
||||
|
||||
void WebContents::DevToolsSetEyeDropperActive(bool active) {
|
||||
auto* web_contents = GetWebContents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
if (active) {
|
||||
eye_dropper_ = std::make_unique<DevToolsEyeDropper>(
|
||||
web_contents, base::BindRepeating(&WebContents::ColorPickedInEyeDropper,
|
||||
base::Unretained(this)));
|
||||
} else {
|
||||
eye_dropper_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::ColorPickedInEyeDropper(int r, int g, int b, int a) {
|
||||
base::DictionaryValue color;
|
||||
color.SetInteger("r", r);
|
||||
color.SetInteger("g", g);
|
||||
color.SetInteger("b", b);
|
||||
color.SetInteger("a", a);
|
||||
inspectable_web_contents_->CallClientFunction(
|
||||
"DevToolsAPI.eyeDropperPickedColor", &color, nullptr, nullptr);
|
||||
}
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MAC)
|
||||
gfx::ImageSkia WebContents::GetDevToolsWindowIcon() {
|
||||
if (!owner_window())
|
||||
@@ -3532,13 +3556,13 @@ void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
// Window is already in fullscreen mode, save the state.
|
||||
if (enter_fullscreen && owner_window_->IsFullscreen()) {
|
||||
native_fullscreen_ = true;
|
||||
html_fullscreen_ = true;
|
||||
UpdateHtmlApiFullscreen(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit html fullscreen state but not window's fullscreen mode.
|
||||
if (!enter_fullscreen && native_fullscreen_) {
|
||||
html_fullscreen_ = false;
|
||||
UpdateHtmlApiFullscreen(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3553,10 +3577,47 @@ void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
owner_window_->SetFullScreen(enter_fullscreen);
|
||||
}
|
||||
|
||||
html_fullscreen_ = enter_fullscreen;
|
||||
UpdateHtmlApiFullscreen(enter_fullscreen);
|
||||
native_fullscreen_ = false;
|
||||
}
|
||||
|
||||
void WebContents::UpdateHtmlApiFullscreen(bool fullscreen) {
|
||||
if (fullscreen == is_html_fullscreen())
|
||||
return;
|
||||
|
||||
html_fullscreen_ = fullscreen;
|
||||
|
||||
// Notify renderer of the html fullscreen change.
|
||||
web_contents()
|
||||
->GetRenderViewHost()
|
||||
->GetWidget()
|
||||
->SynchronizeVisualProperties();
|
||||
|
||||
// The embedder WebContents is separated from the frame tree of webview, so
|
||||
// we must manually sync their fullscreen states.
|
||||
if (embedder_)
|
||||
embedder_->SetHtmlApiFullscreen(fullscreen);
|
||||
|
||||
if (fullscreen) {
|
||||
Emit("enter-html-full-screen");
|
||||
owner_window_->NotifyWindowEnterHtmlFullScreen();
|
||||
} else {
|
||||
Emit("leave-html-full-screen");
|
||||
owner_window_->NotifyWindowLeaveHtmlFullScreen();
|
||||
}
|
||||
|
||||
// Make sure all child webviews quit html fullscreen.
|
||||
if (!fullscreen && !IsGuest()) {
|
||||
auto* manager = WebViewManager::GetWebViewManager(web_contents());
|
||||
manager->ForEachGuest(
|
||||
web_contents(), base::BindRepeating([](content::WebContents* guest) {
|
||||
WebContents* api_web_contents = WebContents::From(guest);
|
||||
api_web_contents->SetHtmlApiFullscreen(false);
|
||||
return false;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
|
||||
v8::Isolate* isolate,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/observer_list_types.h"
|
||||
#include "chrome/browser/devtools/devtools_eye_dropper.h"
|
||||
#include "chrome/browser/devtools/devtools_file_system_indexer.h"
|
||||
#include "content/common/cursors/webcursor.h"
|
||||
#include "content/common/frame.mojom.h"
|
||||
@@ -665,6 +666,7 @@ class WebContents : public gin::Wrappable<WebContents>,
|
||||
void DevToolsSearchInPath(int request_id,
|
||||
const std::string& file_system_path,
|
||||
const std::string& query) override;
|
||||
void DevToolsSetEyeDropperActive(bool active) override;
|
||||
|
||||
// InspectableWebContentsViewDelegate:
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MAC)
|
||||
@@ -678,6 +680,8 @@ class WebContents : public gin::Wrappable<WebContents>,
|
||||
// Destroy the managed InspectableWebContents object.
|
||||
void ResetManagedWebContents(bool async);
|
||||
|
||||
void ColorPickedInEyeDropper(int r, int g, int b, int a);
|
||||
|
||||
// DevTools index event callbacks.
|
||||
void OnDevToolsIndexingWorkCalculated(int request_id,
|
||||
const std::string& file_system_path,
|
||||
@@ -693,6 +697,8 @@ class WebContents : public gin::Wrappable<WebContents>,
|
||||
|
||||
// Set fullscreen mode triggered by html api.
|
||||
void SetHtmlApiFullscreen(bool enter_fullscreen);
|
||||
// Update the html fullscreen flag in both browser and renderer.
|
||||
void UpdateHtmlApiFullscreen(bool fullscreen);
|
||||
|
||||
v8::Global<v8::Value> session_;
|
||||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
@@ -747,6 +753,8 @@ class WebContents : public gin::Wrappable<WebContents>,
|
||||
|
||||
scoped_refptr<DevToolsFileSystemIndexer> devtools_file_system_indexer_;
|
||||
|
||||
std::unique_ptr<DevToolsEyeDropper> eye_dropper_;
|
||||
|
||||
ElectronBrowserContext* browser_context_;
|
||||
|
||||
// The stored InspectableWebContents object.
|
||||
|
||||
@@ -129,7 +129,7 @@ v8::Local<v8::Value> HttpResponseHeadersToV8(
|
||||
!value.empty()) {
|
||||
net::HttpContentDisposition header(value, std::string());
|
||||
std::string decodedFilename =
|
||||
header.is_attachment() ? " attachement" : " inline";
|
||||
header.is_attachment() ? " attachment" : " inline";
|
||||
decodedFilename += "; filename=" + header.filename();
|
||||
value = decodedFilename;
|
||||
}
|
||||
@@ -214,8 +214,11 @@ void ReadFromResponse(v8::Isolate* isolate,
|
||||
void ReadFromResponse(v8::Isolate* isolate,
|
||||
gin::Dictionary* response,
|
||||
net::HttpRequestHeaders* headers) {
|
||||
headers->Clear();
|
||||
response->Get("requestHeaders", headers);
|
||||
v8::Local<v8::Value> value;
|
||||
if (response->Get("requestHeaders", &value) && value->IsObject()) {
|
||||
headers->Clear();
|
||||
gin::Converter<net::HttpRequestHeaders>::FromV8(isolate, value, headers);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadFromResponse(v8::Isolate* isolate,
|
||||
|
||||
@@ -1232,12 +1232,10 @@ ElectronBrowserClient::GetPlatformNotificationService(
|
||||
}
|
||||
|
||||
base::FilePath ElectronBrowserClient::GetDefaultDownloadDirectory() {
|
||||
// ~/Downloads
|
||||
base::FilePath path;
|
||||
if (base::PathService::Get(base::DIR_HOME, &path))
|
||||
path = path.Append(FILE_PATH_LITERAL("Downloads"));
|
||||
|
||||
return path;
|
||||
base::FilePath download_path;
|
||||
if (base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &download_path))
|
||||
return download_path;
|
||||
return base::FilePath();
|
||||
}
|
||||
|
||||
scoped_refptr<network::SharedURLLoaderFactory>
|
||||
|
||||
@@ -55,6 +55,7 @@ void BluetoothChooser::SetAdapterPresence(AdapterPresence presence) {
|
||||
event_handler_.Run(content::BluetoothChooserEvent::CANCELLED, "");
|
||||
break;
|
||||
case AdapterPresence::POWERED_ON:
|
||||
rescan_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +88,7 @@ void BluetoothChooser::ShowDiscoveryState(DiscoveryState state) {
|
||||
case DiscoveryState::DISCOVERING:
|
||||
// The first time this state fires is due to a rescan triggering so set a
|
||||
// flag to ignore devices
|
||||
if (!refreshing_) {
|
||||
if (rescan_ && !refreshing_) {
|
||||
refreshing_ = true;
|
||||
} else {
|
||||
// The second time this state fires we are now safe to pick a device
|
||||
|
||||
@@ -42,6 +42,7 @@ class BluetoothChooser : public content::BluetoothChooser {
|
||||
EventHandler event_handler_;
|
||||
int num_retries_ = 0;
|
||||
bool refreshing_ = false;
|
||||
bool rescan_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BluetoothChooser);
|
||||
};
|
||||
|
||||
@@ -70,11 +70,15 @@ void LoginHandler::EmitEvent(
|
||||
details.Set("firstAuthAttempt", first_auth_attempt);
|
||||
details.Set("responseHeaders", response_headers.get());
|
||||
|
||||
auto weak_this = weak_factory_.GetWeakPtr();
|
||||
bool default_prevented =
|
||||
api_web_contents->Emit("login", std::move(details), auth_info,
|
||||
base::BindOnce(&LoginHandler::CallbackFromJS,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
if (!default_prevented && auth_required_callback_) {
|
||||
// ⚠️ NB, if CallbackFromJS is called during Emit(), |this| will have been
|
||||
// deleted. Check the weak ptr before accessing any member variables to
|
||||
// prevent UAF.
|
||||
if (weak_this && !default_prevented && auth_required_callback_) {
|
||||
std::move(auth_required_callback_).Run(base::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||
|
||||
// Traffic Light API
|
||||
#if defined(OS_MAC)
|
||||
virtual std::string GetAlwaysOnTopLevel() = 0;
|
||||
virtual void SetTrafficLightPosition(const gfx::Point& position) = 0;
|
||||
virtual gfx::Point GetTrafficLightPosition() const = 0;
|
||||
virtual void RedrawTrafficLights() = 0;
|
||||
|
||||
@@ -89,6 +89,7 @@ class NativeWindowMac : public NativeWindow,
|
||||
void SetAlwaysOnTop(ui::ZOrderLevel z_order,
|
||||
const std::string& level,
|
||||
int relativeLevel) override;
|
||||
std::string GetAlwaysOnTopLevel() override;
|
||||
ui::ZOrderLevel GetZOrderLevel() override;
|
||||
void Center() override;
|
||||
void Invalidate() override;
|
||||
|
||||
@@ -498,7 +498,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||
// Use an NSEvent monitor to listen for the wheel event.
|
||||
BOOL __block began = NO;
|
||||
wheel_event_monitor_ = [NSEvent
|
||||
addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
|
||||
addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel
|
||||
handler:^(NSEvent* event) {
|
||||
if ([[event window] windowNumber] !=
|
||||
[window_ windowNumber])
|
||||
@@ -539,7 +539,10 @@ void NativeWindowMac::Cleanup() {
|
||||
DCHECK(!IsClosed());
|
||||
ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this);
|
||||
display::Screen::GetScreen()->RemoveObserver(this);
|
||||
[NSEvent removeMonitor:wheel_event_monitor_];
|
||||
if (wheel_event_monitor_) {
|
||||
[NSEvent removeMonitor:wheel_event_monitor_];
|
||||
wheel_event_monitor_ = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::RedrawTrafficLights() {
|
||||
@@ -706,6 +709,15 @@ void NativeWindowMac::Hide() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide all children of the current window before hiding the window.
|
||||
// components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
|
||||
// expects this when window visibility changes.
|
||||
if ([window_ childWindows]) {
|
||||
for (NSWindow* child in [window_ childWindows]) {
|
||||
[child orderOut:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// Deattach the window from the parent before.
|
||||
if (parent())
|
||||
InternalSetParentWindow(parent(), false);
|
||||
@@ -950,7 +962,7 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio,
|
||||
|
||||
// Reset the behaviour to default if aspect_ratio is set to 0 or less.
|
||||
if (aspect_ratio > 0.0)
|
||||
[window_ setAspectRatio:NSMakeSize(aspect_ratio, 1.0)];
|
||||
[window_ setContentAspectRatio:NSMakeSize(aspect_ratio, 1.0)];
|
||||
else
|
||||
[window_ setResizeIncrements:NSMakeSize(1.0, 1.0)];
|
||||
}
|
||||
@@ -1046,6 +1058,31 @@ void NativeWindowMac::SetAlwaysOnTop(ui::ZOrderLevel z_order,
|
||||
SetWindowLevel(level + relative_level);
|
||||
}
|
||||
|
||||
std::string NativeWindowMac::GetAlwaysOnTopLevel() {
|
||||
std::string level_name = "normal";
|
||||
|
||||
int level = [window_ level];
|
||||
if (level == NSFloatingWindowLevel) {
|
||||
level_name = "floating";
|
||||
} else if (level == NSTornOffMenuWindowLevel) {
|
||||
level_name = "torn-off-menu";
|
||||
} else if (level == NSModalPanelWindowLevel) {
|
||||
level_name = "modal-panel";
|
||||
} else if (level == NSMainMenuWindowLevel) {
|
||||
level_name = "main-menu";
|
||||
} else if (level == NSStatusWindowLevel) {
|
||||
level_name = "status";
|
||||
} else if (level == NSPopUpMenuWindowLevel) {
|
||||
level_name = "pop-up-menu";
|
||||
} else if (level == NSScreenSaverWindowLevel) {
|
||||
level_name = "screen-saver";
|
||||
} else if (level == NSDockWindowLevel) {
|
||||
level_name = "dock";
|
||||
}
|
||||
|
||||
return level_name;
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetWindowLevel(int unbounded_level) {
|
||||
int level = std::min(
|
||||
std::max(unbounded_level, CGWindowLevelForKey(kCGMinimumWindowLevelKey)),
|
||||
@@ -1747,8 +1784,6 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetActive(bool is_key) {
|
||||
if (is_key)
|
||||
widget()->Activate();
|
||||
is_active_ = is_key;
|
||||
}
|
||||
|
||||
@@ -1845,10 +1880,15 @@ void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent,
|
||||
|
||||
// Set new parent window.
|
||||
// Note that this method will force the window to become visible.
|
||||
if (parent && attach)
|
||||
if (parent && attach) {
|
||||
// Attaching a window as a child window resets its window level, so
|
||||
// save and restore it afterwards.
|
||||
NSInteger level = window_.level;
|
||||
[parent->GetNativeWindow().GetNativeNSWindow()
|
||||
addChildWindow:window_
|
||||
ordered:NSWindowAbove];
|
||||
[window_ setLevel:level];
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetForwardMouseMessages(bool forward) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "mojo/public/cpp/bindings/binding.h"
|
||||
#include "net/base/completion_repeating_callback.h"
|
||||
#include "net/base/load_flags.h"
|
||||
#include "net/http/http_status_code.h"
|
||||
#include "net/http/http_util.h"
|
||||
#include "services/metrics/public/cpp/ukm_source_id.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
@@ -305,6 +306,14 @@ void ProxyingURLLoaderFactory::InProgressRequest::OnComplete(
|
||||
|
||||
void ProxyingURLLoaderFactory::InProgressRequest::OnLoaderCreated(
|
||||
mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) {
|
||||
// When CORS is involved there may be multiple network::URLLoader associated
|
||||
// with this InProgressRequest, because CorsURLLoader may create a new
|
||||
// network::URLLoader for the same request id in redirect handling - see
|
||||
// CorsURLLoader::FollowRedirect. In such a case the old network::URLLoader
|
||||
// is going to be detached fairly soon, so we don't need to take care of it.
|
||||
// We need this explicit reset to avoid a DCHECK failure in mojo::Receiver.
|
||||
header_client_receiver_.reset();
|
||||
|
||||
header_client_receiver_.Bind(std::move(receiver));
|
||||
if (for_cors_preflight_) {
|
||||
// In this case we don't have |target_loader_| and
|
||||
@@ -548,13 +557,17 @@ void ProxyingURLLoaderFactory::InProgressRequest::
|
||||
override_headers_ = nullptr;
|
||||
|
||||
if (for_cors_preflight_) {
|
||||
// If this is for CORS preflight, there is no associated client. We notify
|
||||
// the completion here, and deletes |this|.
|
||||
// If this is for CORS preflight, there is no associated client.
|
||||
info_->AddResponseInfoFromResourceResponse(*current_response_);
|
||||
// Do not finish proxied preflight requests that require proxy auth.
|
||||
// The request is not finished yet, give control back to network service
|
||||
// which will start authentication process.
|
||||
if (info_->response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED)
|
||||
return;
|
||||
// We notify the completion here, and delete |this|.
|
||||
factory_->web_request_api()->OnResponseStarted(&info_.value(), request_);
|
||||
factory_->web_request_api()->OnCompleted(&info_.value(), request_, net::OK);
|
||||
|
||||
// Deletes |this|.
|
||||
factory_->RemoveRequest(network_service_request_id_, request_id_);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ void URLPipeLoader::OnDataReceived(base::StringPiece string_piece,
|
||||
producer_->Write(
|
||||
std::make_unique<mojo::StringDataSource>(
|
||||
string_piece, mojo::StringDataSource::AsyncWritingMode::
|
||||
STRING_STAYS_VALID_UNTIL_COMPLETION),
|
||||
STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION),
|
||||
base::BindOnce(&URLPipeLoader::OnWrite, weak_factory_.GetWeakPtr(),
|
||||
std::move(resume)));
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ void CocoaNotification::Show(const NotificationOptions& options) {
|
||||
NSString* identifier =
|
||||
[NSString stringWithFormat:@"%@:notification:%@",
|
||||
[[NSBundle mainBundle] bundleIdentifier],
|
||||
[[[NSUUID alloc] init] UUIDString]];
|
||||
[[NSUUID UUID] UUIDString]];
|
||||
|
||||
[notification_ setTitle:base::SysUTF16ToNSString(options.title)];
|
||||
[notification_ setSubtitle:base::SysUTF16ToNSString(options.subtitle)];
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 12,0,11,0
|
||||
PRODUCTVERSION 12,0,11,0
|
||||
FILEVERSION 12,0,18,0
|
||||
PRODUCTVERSION 12,0,18,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "12.0.11"
|
||||
VALUE "FileVersion", "12.0.18"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "12.0.11"
|
||||
VALUE "ProductVersion", "12.0.18"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -160,13 +160,12 @@
|
||||
|
||||
// Switch to new state.
|
||||
devtools_docked_ = docked;
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView();
|
||||
if (!docked) {
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView();
|
||||
|
||||
auto styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
|
||||
NSMiniaturizableWindowMask | NSWindowStyleMaskResizable |
|
||||
NSTexturedBackgroundWindowMask |
|
||||
@@ -189,6 +188,9 @@
|
||||
devToolsView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
[contentView addSubview:devToolsView];
|
||||
[devToolsView setMouseDownCanMoveWindow:NO];
|
||||
} else {
|
||||
[devToolsView setMouseDownCanMoveWindow:YES];
|
||||
}
|
||||
[self setDevToolsVisible:YES activate:activate];
|
||||
}
|
||||
|
||||
@@ -787,7 +787,10 @@ void InspectableWebContents::SearchInPath(int request_id,
|
||||
void InspectableWebContents::SetWhitelistedShortcuts(
|
||||
const std::string& message) {}
|
||||
|
||||
void InspectableWebContents::SetEyeDropperActive(bool active) {}
|
||||
void InspectableWebContents::SetEyeDropperActive(bool active) {
|
||||
if (delegate_)
|
||||
delegate_->DevToolsSetEyeDropperActive(active);
|
||||
}
|
||||
void InspectableWebContents::ShowCertificateViewer(
|
||||
const std::string& cert_chain) {}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ class InspectableWebContentsDelegate {
|
||||
virtual void DevToolsSearchInPath(int request_id,
|
||||
const std::string& file_system_path,
|
||||
const std::string& query) {}
|
||||
virtual void DevToolsSetEyeDropperActive(bool active) {}
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -38,6 +38,13 @@ int FramelessView::ResizingBorderHitTest(const gfx::Point& point) {
|
||||
bool can_ever_resize = frame_->widget_delegate()
|
||||
? frame_->widget_delegate()->CanResize()
|
||||
: false;
|
||||
|
||||
// https://github.com/electron/electron/issues/611
|
||||
// If window isn't resizable, we should always return HTCLIENT, otherwise the
|
||||
// hover state of DOM will not be cleared probably.
|
||||
if (!can_ever_resize)
|
||||
return HTCLIENT;
|
||||
|
||||
// Don't allow overlapping resize handles when the window is maximized or
|
||||
// fullscreen, as it can't be resized in those states.
|
||||
int resize_border = frame_->IsMaximized() || frame_->IsFullscreen()
|
||||
|
||||
@@ -132,6 +132,10 @@ void InspectableWebContentsViewViews::ShowDevTools(bool activate) {
|
||||
} else {
|
||||
devtools_window_->ShowInactive();
|
||||
}
|
||||
|
||||
// Update draggable regions to account for the new dock position.
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
} else {
|
||||
devtools_web_view_->SetVisible(true);
|
||||
devtools_web_view_->SetWebContents(
|
||||
@@ -232,6 +236,9 @@ void InspectableWebContentsViewViews::Layout() {
|
||||
|
||||
devtools_web_view_->SetBoundsRect(new_devtools_bounds);
|
||||
contents_web_view_->SetBoundsRect(new_contents_bounds);
|
||||
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -105,13 +105,18 @@ content::WebContents* WebViewGuestDelegate::CreateNewGuestWindow(
|
||||
guest_params.context = embedder_web_contents_->GetNativeView();
|
||||
std::unique_ptr<content::WebContents> guest_contents =
|
||||
content::WebContents::Create(guest_params);
|
||||
content::RenderWidgetHost* render_widget_host =
|
||||
guest_contents->GetRenderViewHost()->GetWidget();
|
||||
auto* guest_contents_impl =
|
||||
static_cast<content::WebContentsImpl*>(guest_contents.release());
|
||||
guest_contents_impl->GetView()->CreateViewForWidget(render_widget_host);
|
||||
|
||||
return guest_contents_impl;
|
||||
if (!create_params.opener_suppressed) {
|
||||
auto* guest_contents_impl =
|
||||
static_cast<content::WebContentsImpl*>(guest_contents.release());
|
||||
auto* new_guest_view = guest_contents_impl->GetView();
|
||||
content::RenderWidgetHostView* widget_view =
|
||||
new_guest_view->CreateViewForWidget(
|
||||
guest_contents_impl->GetRenderViewHost()->GetWidget());
|
||||
if (!create_params.initially_hidden)
|
||||
widget_view->Show();
|
||||
return guest_contents_impl;
|
||||
}
|
||||
return guest_contents.release();
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -25,7 +25,6 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||
|
||||
static WebViewManager* GetWebViewManager(content::WebContents* web_contents);
|
||||
|
||||
protected:
|
||||
// content::BrowserPluginGuestManager:
|
||||
bool ForEachGuest(content::WebContents* embedder,
|
||||
const GuestCallback& callback) override;
|
||||
|
||||
@@ -107,7 +107,7 @@ bool IsSameOrigin(const GURL& l, const GURL& r) {
|
||||
return url::Origin::Create(l).IsSameOriginWith(url::Origin::Create(r));
|
||||
}
|
||||
|
||||
#ifdef DCHECK_IS_ON
|
||||
#if DCHECK_IS_ON()
|
||||
std::vector<v8::Global<v8::Value>> weakly_tracked_values;
|
||||
|
||||
void WeaklyTrackValue(v8::Isolate* isolate, v8::Local<v8::Value> value) {
|
||||
@@ -157,7 +157,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
dict.SetMethod("requestGarbageCollectionForTesting",
|
||||
&RequestGarbageCollectionForTesting);
|
||||
dict.SetMethod("isSameOrigin", &IsSameOrigin);
|
||||
#ifdef DCHECK_IS_ON
|
||||
#if DCHECK_IS_ON()
|
||||
dict.SetMethod("triggerFatalErrorForTesting", &TriggerFatalErrorForTesting);
|
||||
dict.SetMethod("getWeaklyTrackedValues", &GetWeaklyTrackedValues);
|
||||
dict.SetMethod("clearWeaklyTrackedValues", &ClearWeaklyTrackedValues);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user