mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6d9d954b4 | ||
|
|
2ee375c5bf | ||
|
|
c04ec2d332 | ||
|
|
4f9122647a | ||
|
|
846504af8e | ||
|
|
5d97320ba3 | ||
|
|
2aaa5438cd | ||
|
|
08da5ee22a | ||
|
|
f3a4b44662 | ||
|
|
424177164e | ||
|
|
079251f168 | ||
|
|
17054405d8 | ||
|
|
d1d8c9badd | ||
|
|
700c410ec3 | ||
|
|
d3f7ad2035 | ||
|
|
f5deaedfaa | ||
|
|
2717a48f30 | ||
|
|
fea41c6f6d | ||
|
|
d58bfdcdfd | ||
|
|
d0451832ed | ||
|
|
22481aa347 | ||
|
|
7b0bb0b637 | ||
|
|
36f8e9daa2 | ||
|
|
4594af595e | ||
|
|
0bbd268eb4 | ||
|
|
47b9207e6d | ||
|
|
846412cdf1 | ||
|
|
b77e48a2c7 | ||
|
|
87d98480fa | ||
|
|
6d468cd9b5 | ||
|
|
38e585434f | ||
|
|
5481d27bcd | ||
|
|
135133e391 | ||
|
|
ad8de076e3 | ||
|
|
5bad2d106c | ||
|
|
883b089e0f | ||
|
|
d0abffc1e7 | ||
|
|
e24e77f4a2 | ||
|
|
9562a92c5d | ||
|
|
4efe747847 | ||
|
|
47f015f1e8 | ||
|
|
5604037294 | ||
|
|
f6a3ba5d67 | ||
|
|
34fe161bdd | ||
|
|
e1bf7b9d8b | ||
|
|
5de766deb5 | ||
|
|
70e41bcf43 | ||
|
|
f7a61c4592 | ||
|
|
b19c549511 | ||
|
|
de14497f1c | ||
|
|
570f9827ce | ||
|
|
9900e697b5 | ||
|
|
c6979ca421 | ||
|
|
ace3f9d3e1 | ||
|
|
7bd2f0db23 | ||
|
|
83db340eb3 | ||
|
|
17d08c1557 | ||
|
|
66e548333f | ||
|
|
7558b5878b | ||
|
|
3ad830c804 | ||
|
|
2460b02e48 | ||
|
|
9012c3bb8b | ||
|
|
90d72684fc | ||
|
|
529fbf53e1 | ||
|
|
4ef5c2666e | ||
|
|
4aa4d1914b | ||
|
|
16681be8fd | ||
|
|
0aef4d6a8d | ||
|
|
ae3c79d6ce | ||
|
|
fee2655061 | ||
|
|
a3c1866581 | ||
|
|
38f0916eea | ||
|
|
6543acce1d | ||
|
|
15db70d661 | ||
|
|
1b32fd2a9b | ||
|
|
6147bd77ac | ||
|
|
ffd1e9bad2 | ||
|
|
682b382aa3 | ||
|
|
3ad59397ae | ||
|
|
6502e4e9cb | ||
|
|
d5119c499c | ||
|
|
0fa84aef3b | ||
|
|
fe28c5ba06 | ||
|
|
9242fff9c2 | ||
|
|
a538755595 | ||
|
|
139cb2dea5 | ||
|
|
831e84504d | ||
|
|
ccbf615da0 | ||
|
|
d8fd2dca6d | ||
|
|
86d6aa75ad | ||
|
|
99df3b8147 | ||
|
|
776f76c6f5 | ||
|
|
1df0ea58d5 | ||
|
|
e50545db30 | ||
|
|
4a312e9c6b | ||
|
|
0992fb35ea | ||
|
|
904404d3c4 | ||
|
|
fa491d7e4b | ||
|
|
8a052c5537 | ||
|
|
b3d89bd3bf | ||
|
|
28f4c546ca |
@@ -94,6 +94,7 @@ env-release-build: &env-release-build
|
||||
STRIP_BINARIES: true
|
||||
GENERATE_SYMBOLS: true
|
||||
CHECK_DIST_MANIFEST: '1'
|
||||
IS_RELEASE: true
|
||||
|
||||
env-headless-testing: &env-headless-testing
|
||||
DISPLAY: ':99.0'
|
||||
@@ -232,23 +233,34 @@ step-gclient-sync: &step-gclient-sync
|
||||
"$CIRCLE_REPOSITORY_URL"
|
||||
|
||||
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
cd src/electron
|
||||
git update-index --refresh || true
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
# There are changes to the patches. Make a git commit with the updated patches
|
||||
git add patches
|
||||
GIT_COMMITTER_NAME="Electron Bot" GIT_COMMITTER_EMAIL="anonymous@electronjs.org" git commit -m "update patches" --author="Electron Bot <anonymous@electronjs.org>"
|
||||
# Export it
|
||||
mkdir -p ../../patches
|
||||
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "There were changes to the patches when applying."
|
||||
echo "Check the CI artifacts for a patch you can apply to fix it."
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
if [ "$IS_RELEASE" != "true" ]; then
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
cd src/electron
|
||||
git update-index --refresh || true
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
# There are changes to the patches. Make a git commit with the updated patches
|
||||
git add patches
|
||||
GIT_COMMITTER_NAME="Electron Bot" GIT_COMMITTER_EMAIL="electron@github.com" git commit -m "update patches" --author="Electron Bot <electron@github.com>"
|
||||
# Export it
|
||||
mkdir -p ../../patches
|
||||
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
|
||||
if (node ./script/push-patch.js 2> /dev/null > /dev/null); then
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "Changes to the patches when applying, we have auto-pushed the diff to the current branch"
|
||||
echo "A new CI job will kick off shortly"
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
else
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "There were changes to the patches when applying."
|
||||
echo "Check the CI artifacts for a patch you can apply to fix it."
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -275,10 +287,10 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
name: Setup Goma
|
||||
command: |
|
||||
echo 'export USE_GOMA=true' >> $BASH_ENV
|
||||
if [ "`uname`" == "Linux" ]; then
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
else
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=25' >> $BASH_ENV
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
echo 'ulimit -n 10000' >> $BASH_ENV
|
||||
echo 'sudo launchctl limit maxfiles 65536 200000' >> $BASH_ENV
|
||||
fi
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ]; then
|
||||
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
|
||||
@@ -287,7 +299,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
cd build-tools
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
node -e "require('./src/utils/goma.js').ensure()"
|
||||
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
|
||||
@@ -296,15 +308,17 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
step-restore-brew-cache: &step-restore-brew-cache
|
||||
restore_cache:
|
||||
paths:
|
||||
- /usr/local/Homebrew
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
keys:
|
||||
- v1-brew-cache-{{ arch }}
|
||||
- v4-brew-cache-{{ arch }}
|
||||
|
||||
step-save-brew-cache: &step-save-brew-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /usr/local/Homebrew
|
||||
key: v1-brew-cache-{{ arch }}
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
key: v4-brew-cache-{{ arch }}
|
||||
name: Persisting brew cache
|
||||
|
||||
step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
@@ -380,8 +394,10 @@ step-install-gnutar-on-mac: &step-install-gnutar-on-mac
|
||||
name: Install gnu-tar on macos
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
brew update
|
||||
brew install gnu-tar
|
||||
if [ ! -d /usr/local/Cellar/gnu-tar/ ]; then
|
||||
brew update
|
||||
brew install gnu-tar
|
||||
fi
|
||||
ln -fs /usr/local/bin/gtar /usr/local/bin/tar
|
||||
fi
|
||||
|
||||
@@ -550,10 +566,10 @@ step-electron-publish: &step-electron-publish
|
||||
cd src/electron
|
||||
if [ "$UPLOAD_TO_S3" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to S3'
|
||||
script/release/uploaders/upload.py --upload_to_s3
|
||||
script/release/uploaders/upload.py --verbose --upload_to_s3
|
||||
else
|
||||
echo 'Uploading Electron release distribution to Github releases'
|
||||
script/release/uploaders/upload.py
|
||||
script/release/uploaders/upload.py --verbose
|
||||
fi
|
||||
|
||||
step-persist-data-for-tests: &step-persist-data-for-tests
|
||||
@@ -789,6 +805,8 @@ step-ninja-summary: &step-ninja-summary
|
||||
run:
|
||||
name: Print ninja summary
|
||||
command: |
|
||||
set +e
|
||||
set +o pipefail
|
||||
python depot_tools/post_build_ninja_summary.py -C src/out/Default
|
||||
|
||||
step-ninja-report: &step-ninja-report
|
||||
@@ -993,7 +1011,6 @@ steps-checkout-and-save-cache: &steps-checkout-and-save-cache
|
||||
- *step-maybe-early-exit-doc-only-change
|
||||
- *step-depot-tools-get
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-restore-brew-cache
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-install-gnutar-on-mac
|
||||
|
||||
|
||||
9
BUILD.gn
9
BUILD.gn
@@ -370,6 +370,7 @@ source_set("electron_lib") {
|
||||
"//third_party/libyuv",
|
||||
"//third_party/webrtc_overrides:webrtc_component",
|
||||
"//third_party/widevine/cdm:headers",
|
||||
"//third_party/zlib/google:zip",
|
||||
"//ui/base/idle",
|
||||
"//ui/events:dom_keycode_converter",
|
||||
"//ui/gl",
|
||||
@@ -675,6 +676,14 @@ source_set("electron_lib") {
|
||||
"shell/browser/electron_pdf_web_contents_helper_client.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win && enable_win_dark_mode_window_ui) {
|
||||
sources += [
|
||||
"shell/browser/win/dark_mode.cc",
|
||||
"shell/browser/win/dark_mode.h",
|
||||
]
|
||||
libs += [ "uxtheme.lib" ]
|
||||
}
|
||||
}
|
||||
|
||||
electron_paks("packed_resources") {
|
||||
|
||||
@@ -1 +1 @@
|
||||
10.1.4
|
||||
10.3.0
|
||||
@@ -135,7 +135,7 @@ build_script:
|
||||
cd build-tools
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
$env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
$env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
cd ..
|
||||
@@ -220,10 +220,10 @@ deploy_script:
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_S3) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\release\uploaders\upload.py --upload_to_s3
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_s3
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
|
||||
@@ -21,6 +21,7 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_ELECTRON_EXTENSIONS=$enable_electron_extensions",
|
||||
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
|
||||
"ENABLE_PICTURE_IN_PICTURE=$enable_picture_in_picture",
|
||||
"ENABLE_WIN_DARK_MODE_WINDOW_UI=$enable_win_dark_mode_window_ui",
|
||||
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -36,4 +36,7 @@ declare_args() {
|
||||
|
||||
# Enable Spellchecker support
|
||||
enable_builtin_spellchecker = true
|
||||
|
||||
# Undocumented Windows dark mode API
|
||||
enable_win_dark_mode_window_ui = false
|
||||
}
|
||||
|
||||
@@ -826,10 +826,9 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
||||
to_send.append(current_dir.value());
|
||||
|
||||
const std::vector<std::string>& argv = electron::ElectronCommandLine::argv();
|
||||
for (std::vector<std::string>::const_iterator it = argv.begin();
|
||||
it != argv.end(); ++it) {
|
||||
for (const auto& arg : argv) {
|
||||
to_send.push_back(kTokenDelimiter);
|
||||
to_send.append(*it);
|
||||
to_send.append(arg);
|
||||
}
|
||||
|
||||
// Send the message
|
||||
|
||||
@@ -122,8 +122,7 @@ void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject* /* ignored */,
|
||||
GParamSpec* /* ignored */) {
|
||||
// If the name owner changed, we need to reregister all the live x11::Window
|
||||
// with the system.
|
||||
for (std::set<x11::Window>::const_iterator it = live_windows_.begin();
|
||||
it != live_windows_.end(); ++it) {
|
||||
RegisterXWindow(*it);
|
||||
for (const auto& window : live_windows_) {
|
||||
RegisterXWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ In most cases, you should do everything in the `ready` event handler.
|
||||
|
||||
Returns:
|
||||
|
||||
* `launchInfo` unknown _macOS_
|
||||
* `event` Event
|
||||
* `launchInfo` Record<string, any> _macOS_
|
||||
|
||||
Emitted once, when Electron has finished initializing. On macOS, `launchInfo`
|
||||
holds the `userInfo` of the `NSUserNotification` that was used to open the
|
||||
@@ -1267,7 +1268,7 @@ systems Application folder. Use in combination with `app.moveToApplicationsFolde
|
||||
### `app.moveToApplicationsFolder([options])` _macOS_
|
||||
|
||||
* `options` Object (optional)
|
||||
* `conflictHandler` Function<Boolean> (optional) - A handler for potential conflict in move failure.
|
||||
* `conflictHandler` Function\<Boolean> (optional) - A handler for potential conflict in move failure.
|
||||
* `conflictType` String - The type of move conflict encountered by the handler; can be `exists` or `existsAndRunning`, where `exists` means that an app of the same name is present in the Applications directory and `existsAndRunning` means both that it exists and that it's presently running.
|
||||
|
||||
Returns `Boolean` - Whether the move was successful. Please note that if
|
||||
|
||||
@@ -114,3 +114,9 @@ The following methods of `chrome.management` are supported:
|
||||
- `chrome.management.getPermissionWarningsByManifest`
|
||||
- `chrome.management.onEnabled`
|
||||
- `chrome.management.onDisabled`
|
||||
|
||||
### `chrome.webRequest`
|
||||
|
||||
All features of this API are supported.
|
||||
|
||||
> **NOTE:** Electron's [`webRequest`](web-request.md) module takes precedence over `chrome.webRequest` if there are conflicting handlers.
|
||||
|
||||
@@ -9,7 +9,7 @@ with the operating system so that you can customize the operations for various
|
||||
shortcuts.
|
||||
|
||||
**Note:** The shortcut is global; it will work even if the app does
|
||||
not have the keyboard focus. You should not use this module until the `ready`
|
||||
not have the keyboard focus. This module cannot be used before the `ready`
|
||||
event of the app module is emitted.
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -91,7 +91,7 @@ Removes listeners of the specified `channel`.
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
* `channel` String
|
||||
* `listener` Function<Promise<void> | any>
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
@@ -123,7 +123,7 @@ WebContents is the source of the invoke request.
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
* `channel` String
|
||||
* `listener` Function<Promise<void> | any>
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
|
||||
|
||||
#### `ses.setPermissionCheckHandler(handler)`
|
||||
|
||||
* `handler` Function<Boolean> | null
|
||||
* `handler` Function\<Boolean> | null
|
||||
* `webContents` [WebContents](web-contents.md) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
|
||||
* `permission` String - Enum of 'media'.
|
||||
* `requestingOrigin` String - The origin URL of the permission check
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# IpcMainEvent Object extends `Event`
|
||||
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `returnValue` any - Set this to the value to be returned in a synchronous message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# IpcMainInvokeEvent Object extends `Event`
|
||||
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
|
||||
@@ -1586,7 +1586,9 @@ app.whenReady().then(() => {
|
||||
|
||||
#### `contents.sendToFrame(frameId, channel, ...args)`
|
||||
|
||||
* `frameId` Integer
|
||||
* `frameId` Integer | [number, number] - the ID of the frame to send to, or a
|
||||
pair of `[processId, frameId]` if the frame is in a different process to the
|
||||
main frame.
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
@@ -1760,7 +1762,7 @@ Returns `Boolean` - If *offscreen rendering* is enabled returns whether it is cu
|
||||
* `fps` Integer
|
||||
|
||||
If *offscreen rendering* is enabled sets the frame rate to the specified number.
|
||||
Only values between 1 and 60 are accepted.
|
||||
Only values between 1 and 240 are accepted.
|
||||
|
||||
#### `contents.getFrameRate()`
|
||||
|
||||
@@ -1858,7 +1860,7 @@ The zoom factor is the zoom percent divided by 100, so 300% = 3.0.
|
||||
#### `contents.frameRate`
|
||||
|
||||
An `Integer` property that sets the frame rate of the web contents to the specified number.
|
||||
Only values between 1 and 60 are accepted.
|
||||
Only values between 1 and 240 are accepted.
|
||||
|
||||
Only applicable if *offscreen rendering* is enabled.
|
||||
|
||||
|
||||
@@ -186,6 +186,45 @@ you should plan to update your native modules to be context aware.
|
||||
|
||||
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||
|
||||
### Deprecated: `BrowserWindow` extension APIs
|
||||
|
||||
The following extension APIs have been deprecated:
|
||||
* `BrowserWindow.addExtension(path)`
|
||||
* `BrowserWindow.addDevToolsExtension(path)`
|
||||
* `BrowserWindow.removeExtension(name)`
|
||||
* `BrowserWindow.removeDevToolsExtension(name)`
|
||||
* `BrowserWindow.getExtensions()`
|
||||
* `BrowserWindow.getDevToolsExtensions()`
|
||||
|
||||
Use the session APIs instead:
|
||||
* `ses.loadExtension(path)`
|
||||
* `ses.removeExtension(extension_id)`
|
||||
* `ses.getAllExtensions()`
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.addExtension(path)
|
||||
BrowserWindow.addDevToolsExtension(path)
|
||||
// Replace with
|
||||
session.defaultSession.loadExtension(path)
|
||||
```
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.removeExtension(name)
|
||||
BrowserWindow.removeDevToolsExtension(name)
|
||||
// Replace with
|
||||
session.defaultSession.removeExtension(extension_id)
|
||||
```
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.getExtensions()
|
||||
BrowserWindow.getDevToolsExtensions()
|
||||
// Replace with
|
||||
session.defaultSession.getAllExtensions()
|
||||
```
|
||||
|
||||
### Removed: `<webview>.getWebContents()`
|
||||
|
||||
This API, which was deprecated in Electron 8.0, is now removed.
|
||||
@@ -329,6 +368,52 @@ in Electron 8.x, and cease to exist in Electron 9.x. The layout zoom level
|
||||
limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined
|
||||
[here](https://chromium.googlesource.com/chromium/src/+/938b37a6d2886bf8335fc7db792f1eb46c65b2ae/third_party/blink/common/page/page_zoom.cc#11).
|
||||
|
||||
### Deprecated events in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` events have been deprecated:
|
||||
* `inverted-color-scheme-changed`
|
||||
* `high-contrast-color-scheme-changed`
|
||||
|
||||
Use the new `updated` event on the `nativeTheme` module instead.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.on('inverted-color-scheme-changed', () => { /* ... */ })
|
||||
systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })
|
||||
|
||||
// Replace with
|
||||
nativeTheme.on('updated', () => { /* ... */ })
|
||||
```
|
||||
|
||||
### Deprecated: methods in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` methods have been deprecated:
|
||||
* `systemPreferences.isDarkMode()`
|
||||
* `systemPreferences.isInvertedColorScheme()`
|
||||
* `systemPreferences.isHighContrastColorScheme()`
|
||||
|
||||
Use the following `nativeTheme` properties instead:
|
||||
* `nativeTheme.shouldUseDarkColors`
|
||||
* `nativeTheme.shouldUseInvertedColorScheme`
|
||||
* `nativeTheme.shouldUseHighContrastColors`
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.isDarkMode()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseDarkColors
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.isInvertedColorScheme()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseInvertedColorScheme
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.isHighContrastColorScheme()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseHighContrastColors
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (7.0)
|
||||
|
||||
### Deprecated: Atom.io Node Headers URL
|
||||
|
||||
@@ -173,12 +173,12 @@ $ gn gen out/Testing-x86 --args='... target_cpu = "x86"'
|
||||
|
||||
Not all combinations of source and target CPU/OS are supported by Chromium.
|
||||
|
||||
<table>
|
||||
<tr><th>Host</th><th>Target</th><th>Status</th></tr>
|
||||
<tr><td>Windows x64</td><td>Windows arm64</td><td>Experimental</td>
|
||||
<tr><td>Windows x64</td><td>Windows x86</td><td>Automatically tested</td></tr>
|
||||
<tr><td>Linux x64</td><td>Linux x86</td><td>Automatically tested</td></tr>
|
||||
</table>
|
||||
| Host | Target | Status |
|
||||
|-------------|---------------|----------------------|
|
||||
| Windows x64 | Windows arm64 | Experimental |
|
||||
| Windows x64 | Windows x86 | Automatically tested |
|
||||
| Linux x64 | Linux x86 | Automatically tested |
|
||||
|
||||
|
||||
If you test other combinations and find them to work, please update this document :)
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
|
||||
|
||||
## Using the symbol server in Visual Studio
|
||||
|
||||
<img src='https://mdn.mozillademos.org/files/733/symbol-server-vc8express-menu.jpg'>
|
||||
<img src='https://mdn.mozillademos.org/files/2497/2005_options.gif'>
|
||||

|
||||

|
||||
|
||||
## Troubleshooting: Symbols will not load
|
||||
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
# DevTools Extension
|
||||
|
||||
Electron supports the [Chrome DevTools Extension][devtools-extension], which can
|
||||
be used to extend the ability of devtools for debugging popular web frameworks.
|
||||
Electron supports [Chrome DevTools extensions][devtools-extension], which can
|
||||
be used to extend the ability of Chrome's developer tools for debugging
|
||||
popular web frameworks.
|
||||
|
||||
## How to load a DevTools Extension
|
||||
## Loading a DevTools extension with tooling
|
||||
|
||||
This document outlines the process for manually loading an extension.
|
||||
You may also try
|
||||
[electron-devtools-installer](https://github.com/GPMDP/electron-devtools-installer),
|
||||
a third-party tool that downloads extensions directly from the Chrome WebStore.
|
||||
The easiest way to load a DevTools extension is to use third-party tooling to automate the
|
||||
process for you. [electron-devtools-installer][electron-devtools-installer] is a popular
|
||||
NPM package that does just that.
|
||||
|
||||
To load an extension in Electron, you need to download it in Chrome browser,
|
||||
locate its filesystem path, and then load it by calling the
|
||||
`BrowserWindow.addDevToolsExtension(extension)` API.
|
||||
## Manually loading a DevTools extension
|
||||
|
||||
Using the [React Developer Tools][react-devtools] as example:
|
||||
If you don't want to use the tooling approach, you can also do all of the necessary
|
||||
operations by hand. To load an extension in Electron, you need to download it via Chrome,
|
||||
locate its filesystem path, and then load it into your [Session][session] by calling the
|
||||
[`ses.loadExtension`] API.
|
||||
|
||||
1. Install it in Chrome browser.
|
||||
Using the [React Developer Tools][react-devtools] as an example:
|
||||
|
||||
1. Install the extension in Google Chrome.
|
||||
1. Navigate to `chrome://extensions`, and find its extension ID, which is a hash
|
||||
string like `fmkadmapgofadopljbjfkapdkoienihi`.
|
||||
1. Find out filesystem location used by Chrome for storing extensions:
|
||||
1. Find out the filesystem location used by Chrome for storing extensions:
|
||||
* on Windows it is `%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions`;
|
||||
* on Linux it could be:
|
||||
* `~/.config/google-chrome/Default/Extensions/`
|
||||
@@ -27,36 +30,48 @@ Using the [React Developer Tools][react-devtools] as example:
|
||||
* `~/.config/google-chrome-canary/Default/Extensions/`
|
||||
* `~/.config/chromium/Default/Extensions/`
|
||||
* on macOS it is `~/Library/Application Support/Google/Chrome/Default/Extensions`.
|
||||
1. Pass the location of the extension to `BrowserWindow.addDevToolsExtension`
|
||||
API, for the React Developer Tools, it is something like:
|
||||
1. Pass the location of the extension to the [`ses.loadExtension`][load-extension]
|
||||
API. For React Developer Tools `v4.9.0`, it looks something like:
|
||||
```javascript
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const { app, session } = require('electron')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
BrowserWindow.addDevToolsExtension(
|
||||
path.join(os.homedir(), '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.3.0_0')
|
||||
)
|
||||
// on macOS
|
||||
const reactDevToolsPath = path.join(
|
||||
os.homedir(),
|
||||
'/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'
|
||||
)
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
await session.defaultSession.loadExtension(reactDevToolsPath)
|
||||
})
|
||||
```
|
||||
|
||||
**Note:** The `BrowserWindow.addDevToolsExtension` API cannot be called before the
|
||||
ready event of the app module is emitted.
|
||||
**Notes:**
|
||||
|
||||
The extension will be remembered so you only need to call this API once per
|
||||
extension. If you try to add an extension that has already been loaded, this method
|
||||
will not return and instead log a warning to the console.
|
||||
* `loadExtension` returns a Promise with an [Extension object][extension-structure],
|
||||
which contains metadata about the extension that was loaded. This promise needs to
|
||||
resolve (e.g. with an `await` expression) before loading a page. Otherwise, the
|
||||
extension won't be guaranteed to load.
|
||||
* `loadExtension` cannot be called before the `ready` event of the `app` module
|
||||
is emitted, nor can it be called on in-memory (non-persistent) sessions.
|
||||
* `loadExtension` must be called on every boot of your app if you want the
|
||||
extension to be loaded.
|
||||
|
||||
### How to remove a DevTools Extension
|
||||
### Removing a DevTools extension
|
||||
|
||||
You can pass the name of the extension to the `BrowserWindow.removeDevToolsExtension`
|
||||
API to remove it. The name of the extension is returned by
|
||||
`BrowserWindow.addDevToolsExtension` and you can get the names of all installed
|
||||
DevTools Extensions using the `BrowserWindow.getDevToolsExtensions` API.
|
||||
You can pass the extension's ID to the [`ses.removeExtension`][remove-extension] API to
|
||||
remove it from your Session. Loaded extensions are not persisted between
|
||||
app launches.
|
||||
|
||||
## Supported DevTools Extensions
|
||||
## DevTools extension support
|
||||
|
||||
Electron only supports a limited set of `chrome.*` APIs, so some extensions
|
||||
using unsupported `chrome.*` APIs for chrome extension features may not work.
|
||||
Following Devtools Extensions are tested and guaranteed to work in Electron:
|
||||
Electron only supports
|
||||
[a limited set of `chrome.*` APIs][supported-extension-apis],
|
||||
so extensions using unsupported `chrome.*` APIs under the hood may not work.
|
||||
|
||||
The following Devtools extensions have been tested to work in Electron:
|
||||
|
||||
* [Ember Inspector](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
|
||||
* [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)
|
||||
@@ -68,14 +83,22 @@ Following Devtools Extensions are tested and guaranteed to work in Electron:
|
||||
* [Redux DevTools Extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd)
|
||||
* [MobX Developer Tools](https://chrome.google.com/webstore/detail/mobx-developer-tools/pfgnfdagidkfgccljigdamigbcnndkod)
|
||||
|
||||
### What should I do if a DevTools Extension is not working?
|
||||
### What should I do if a DevTools extension is not working?
|
||||
|
||||
First please make sure the extension is still being maintained, some extensions
|
||||
can not even work for recent versions of Chrome browser, and we are not able to
|
||||
do anything for them.
|
||||
First, please make sure the extension is still being maintained and is compatible
|
||||
with the latest version of Google Chrome. We cannot provide additional support for
|
||||
unsupported extensions.
|
||||
|
||||
Then file a bug at Electron's issues list, and describe which part of the
|
||||
extension is not working as expected.
|
||||
If the extension works on Chrome but not on Electron, file a bug in Electron's
|
||||
[issue tracker][issue-tracker] and describe which part
|
||||
of the extension is not working as expected.
|
||||
|
||||
[devtools-extension]: https://developer.chrome.com/extensions/devtools
|
||||
[session]: ../api/session.md
|
||||
[react-devtools]: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
|
||||
[load-extension]: ../api/session.md#sesloadextensionpath
|
||||
[extension-structure]: ../api/structures/extension.md
|
||||
[remove-extension]: ../api/session.md#sesremoveextensionextensionid
|
||||
[electron-devtools-installer]: https://github.com/MarshallOfSound/electron-devtools-installer
|
||||
[supported-extension-apis]: ../api/extensions.md
|
||||
[issue-tracker]: https://github.com/electron/electron/issues
|
||||
|
||||
@@ -9,7 +9,7 @@ Two modes of rendering can be used and only the dirty area is passed in the
|
||||
`'paint'` event to be more efficient. The rendering can be stopped, continued
|
||||
and the frame rate can be set. The specified frame rate is a top limit value,
|
||||
when there is nothing happening on a webpage, no frames are generated. The
|
||||
maximum frame rate is 60, because above that there is no benefit, only
|
||||
maximum frame rate is 240, because above that there is no benefit, only
|
||||
performance loss.
|
||||
|
||||
**Note:** An offscreen window is always created as a [Frameless Window](../api/frameless-window.md).
|
||||
|
||||
@@ -9,8 +9,12 @@ If you're looking for programming help,
|
||||
for answers to questions,
|
||||
or to join in discussion with other developers who use Electron,
|
||||
you can interact with the community in these locations:
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom
|
||||
forums
|
||||
- [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
|
||||
- Getting help
|
||||
- Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
|
||||
- Sharing ideas with other Electron app developers
|
||||
- And more!
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
|
||||
@@ -184,8 +184,12 @@ filenames = {
|
||||
"shell/browser/electron_web_ui_controller_factory.h",
|
||||
"shell/browser/event_emitter_mixin.cc",
|
||||
"shell/browser/event_emitter_mixin.h",
|
||||
"shell/browser/extended_web_contents_observer.h",
|
||||
"shell/browser/feature_list.cc",
|
||||
"shell/browser/feature_list.h",
|
||||
"shell/browser/file_select_helper.cc",
|
||||
"shell/browser/file_select_helper.h",
|
||||
"shell/browser/file_select_helper_mac.mm",
|
||||
"shell/browser/font_defaults.cc",
|
||||
"shell/browser/font_defaults.h",
|
||||
"shell/browser/javascript_environment.cc",
|
||||
@@ -345,6 +349,7 @@ filenames = {
|
||||
"shell/browser/ui/devtools_manager_delegate.h",
|
||||
"shell/browser/ui/devtools_ui.cc",
|
||||
"shell/browser/ui/devtools_ui.h",
|
||||
"shell/browser/ui/drag_util.cc",
|
||||
"shell/browser/ui/drag_util.h",
|
||||
"shell/browser/ui/drag_util_mac.mm",
|
||||
"shell/browser/ui/drag_util_views.cc",
|
||||
|
||||
@@ -16,7 +16,7 @@ if ('getAppLevelAppearance' in systemPreferences) {
|
||||
}
|
||||
|
||||
if ('getEffectiveAppearance' in systemPreferences) {
|
||||
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
|
||||
const nativeEAGetter = systemPreferences.getEffectiveAppearance;
|
||||
Object.defineProperty(SystemPreferences.prototype, 'effectiveAppearance', {
|
||||
get: () => nativeEAGetter.call(systemPreferences)
|
||||
});
|
||||
|
||||
@@ -167,29 +167,29 @@ WebContents.prototype._sendInternalToAll = function (channel, ...args) {
|
||||
|
||||
return this._send(internal, sendToAll, channel, args);
|
||||
};
|
||||
WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
|
||||
WebContents.prototype.sendToFrame = function (frame, channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
} else if (typeof frameId !== 'number') {
|
||||
throw new Error('Missing required frameId argument');
|
||||
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
|
||||
throw new Error('Missing required frame argument (must be number or array)');
|
||||
}
|
||||
|
||||
const internal = false;
|
||||
const sendToAll = false;
|
||||
|
||||
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
|
||||
return this._sendToFrame(internal, sendToAll, frame, channel, args);
|
||||
};
|
||||
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
|
||||
WebContents.prototype._sendToFrameInternal = function (frame, channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
} else if (typeof frameId !== 'number') {
|
||||
throw new Error('Missing required frameId argument');
|
||||
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
|
||||
throw new Error('Missing required frame argument (must be number or array)');
|
||||
}
|
||||
|
||||
const internal = true;
|
||||
const sendToAll = false;
|
||||
|
||||
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
|
||||
return this._sendToFrame(internal, sendToAll, frame, channel, args);
|
||||
};
|
||||
|
||||
// Following methods are mapped to webFrame.
|
||||
@@ -445,8 +445,9 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
|
||||
};
|
||||
|
||||
const addReplyToEvent = (event) => {
|
||||
const { processId, frameId } = event;
|
||||
event.reply = (...args) => {
|
||||
event.sender.sendToFrame(event.frameId, ...args);
|
||||
event.sender.sendToFrame([processId, frameId], ...args);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
|
||||
}
|
||||
// Remove from currentlyRunning once we resolve or reject
|
||||
currentlyRunning = currentlyRunning.filter(running => running.options !== options);
|
||||
if (event) {
|
||||
event.sender.removeListener('destroyed', stopRunning);
|
||||
}
|
||||
};
|
||||
|
||||
capturer._onerror = (error: string) => {
|
||||
@@ -66,7 +69,7 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
|
||||
// reference to emit and the capturer itself so that it never dispatches
|
||||
// back to the renderer
|
||||
if (event) {
|
||||
event.sender.once('destroyed', () => stopRunning());
|
||||
event.sender.once('destroyed', stopRunning);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ const fakeConstructor = (constructor: Function, name: string) =>
|
||||
});
|
||||
|
||||
// Convert array of meta data from renderer into array of real values.
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: number, contextId: string, args: any[]) {
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: [number, number], contextId: string, args: any[]) {
|
||||
const metaToValue = function (meta: MetaTypeFromRenderer): any {
|
||||
switch (meta.type) {
|
||||
case 'nativeimage':
|
||||
@@ -331,7 +331,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
|
||||
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
|
||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
|
||||
|
||||
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId, contextId, meta.id, sender);
|
||||
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId[0], frameId[1], contextId, meta.id, sender);
|
||||
rendererFunctions.set(objectId, callIntoRenderer);
|
||||
return callIntoRenderer;
|
||||
}
|
||||
@@ -480,7 +480,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CURRENT_WEB_CONTENTS', function (event, co
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const constructor = objectsRegistry.get(id);
|
||||
|
||||
if (constructor == null) {
|
||||
@@ -491,7 +491,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId,
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const func = objectsRegistry.get(id);
|
||||
|
||||
if (func == null) {
|
||||
@@ -508,7 +508,7 @@ handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
@@ -519,7 +519,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, cont
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
@@ -536,7 +536,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId,
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_SET', function (event, contextId, id, name, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const obj = objectsRegistry.get(id);
|
||||
|
||||
if (obj == null) {
|
||||
|
||||
@@ -38,7 +38,7 @@ const keysOfTypeNumber = ['top', 'left', ...Object.keys(keysOfTypeNumberCompileT
|
||||
type CoercedValue = string | number | boolean;
|
||||
function coerce (key: string, value: string): CoercedValue {
|
||||
if (keysOfTypeNumber.includes(key)) {
|
||||
return Number(value);
|
||||
return parseInt(value, 10);
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
|
||||
@@ -276,7 +276,7 @@ function metaToError (meta) {
|
||||
}
|
||||
|
||||
function handleMessage (channel, handler) {
|
||||
ipcRendererInternal.on(channel, (event, passedContextId, id, ...args) => {
|
||||
ipcRendererInternal.onMessageFromMain(channel, (event, passedContextId, id, ...args) => {
|
||||
if (passedContextId === contextId) {
|
||||
handler(id, ...args);
|
||||
} else {
|
||||
|
||||
@@ -6,11 +6,11 @@ class WebNavigation {
|
||||
private onCompleted = new Event()
|
||||
|
||||
constructor () {
|
||||
ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => {
|
||||
ipcRendererInternal.onMessageFromMain('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => {
|
||||
this.onBeforeNavigate.emit(details);
|
||||
});
|
||||
|
||||
ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => {
|
||||
ipcRendererInternal.onMessageFromMain('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => {
|
||||
this.onCompleted.emit(details);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-in
|
||||
type IPCHandler = (event: Electron.IpcRendererEvent, ...args: any[]) => any
|
||||
|
||||
export const handle = function <T extends IPCHandler> (channel: string, handler: T) {
|
||||
ipcRendererInternal.on(channel, async (event, requestId, ...args) => {
|
||||
ipcRendererInternal.onMessageFromMain(channel, async (event, requestId, ...args) => {
|
||||
const replyChannel = `${channel}_RESPONSE_${requestId}`;
|
||||
try {
|
||||
event.sender.send(replyChannel, null, await handler(event, ...args));
|
||||
|
||||
@@ -30,4 +30,27 @@ if (!ipcRendererInternal.send) {
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
ipcRendererInternal.onMessageFromMain = function (channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void) {
|
||||
return ipcRendererInternal.on(channel, (event, ...args) => {
|
||||
if (event.senderId !== 0) {
|
||||
console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`);
|
||||
return;
|
||||
}
|
||||
|
||||
listener(event, ...args);
|
||||
});
|
||||
};
|
||||
|
||||
ipcRendererInternal.onceMessageFromMain = function (channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void) {
|
||||
return ipcRendererInternal.on(channel, function wrapper (event, ...args) {
|
||||
if (event.senderId !== 0) {
|
||||
console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`);
|
||||
return;
|
||||
}
|
||||
|
||||
ipcRendererInternal.removeListener(channel, wrapper);
|
||||
listener(event, ...args);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ const warnAboutInsecureCSP = function () {
|
||||
|
||||
console.warn('%cElectron Security Warning (Insecure Content-Security-Policy)',
|
||||
'font-weight: bold;', warning);
|
||||
});
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ const WEB_VIEW_EVENTS: Record<string, Array<string>> = {
|
||||
'focus-change': ['focus', 'guestInstanceId'],
|
||||
close: [],
|
||||
crashed: [],
|
||||
'render-process-gone': ['details'],
|
||||
'plugin-crashed': ['name', 'version'],
|
||||
destroyed: [],
|
||||
'page-title-updated': ['title', 'explicitSet'],
|
||||
@@ -66,18 +67,18 @@ const dispatchEvent = function (
|
||||
};
|
||||
|
||||
export function registerEvents (webView: WebViewImpl, viewInstanceId: number) {
|
||||
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`, function () {
|
||||
ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`, function () {
|
||||
webView.guestInstanceId = undefined;
|
||||
webView.reset();
|
||||
const domEvent = new Event('destroyed');
|
||||
webView.dispatchEvent(domEvent);
|
||||
});
|
||||
|
||||
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`, function (event, eventName, ...args) {
|
||||
ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`, function (event, eventName, ...args) {
|
||||
dispatchEvent(webView, eventName, eventName, ...args);
|
||||
});
|
||||
|
||||
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`, function (event, channel, ...args) {
|
||||
ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`, function (event, channel, ...args) {
|
||||
const domEvent = new Event('ipc-message') as IpcMessageEvent;
|
||||
domEvent.channel = channel;
|
||||
domEvent.args = args;
|
||||
|
||||
@@ -17,7 +17,7 @@ interface MutationHandler {
|
||||
|
||||
// Attribute objects.
|
||||
// Default implementation of a WebView attribute.
|
||||
class WebViewAttribute implements MutationHandler {
|
||||
export class WebViewAttribute implements MutationHandler {
|
||||
public value: any;
|
||||
public ignoreMutation = false;
|
||||
|
||||
@@ -78,7 +78,7 @@ class BooleanAttribute extends WebViewAttribute {
|
||||
}
|
||||
|
||||
// Attribute representing the state of the storage partition.
|
||||
class PartitionAttribute extends WebViewAttribute {
|
||||
export class PartitionAttribute extends WebViewAttribute {
|
||||
public validPartitionId = true
|
||||
|
||||
constructor (public webViewImpl: WebViewImpl) {
|
||||
@@ -102,7 +102,7 @@ class PartitionAttribute extends WebViewAttribute {
|
||||
}
|
||||
|
||||
// Attribute that handles the location and navigation of the webview.
|
||||
class SrcAttribute extends WebViewAttribute {
|
||||
export class SrcAttribute extends WebViewAttribute {
|
||||
public observer!: MutationObserver;
|
||||
|
||||
constructor (public webViewImpl: WebViewImpl) {
|
||||
@@ -168,7 +168,7 @@ class SrcAttribute extends WebViewAttribute {
|
||||
}
|
||||
|
||||
public parse () {
|
||||
if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].validPartitionId || !this.getValue()) {
|
||||
if (!this.webViewImpl.elementAttached || !(this.webViewImpl.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION) as PartitionAttribute).validPartitionId || !this.getValue()) {
|
||||
return;
|
||||
}
|
||||
if (this.webViewImpl.guestInstanceId == null) {
|
||||
@@ -182,12 +182,12 @@ class SrcAttribute extends WebViewAttribute {
|
||||
// Navigate to |this.src|.
|
||||
const opts: Record<string, string> = {};
|
||||
|
||||
const httpreferrer = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER].getValue();
|
||||
const httpreferrer = this.webViewImpl.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER)!.getValue();
|
||||
if (httpreferrer) {
|
||||
opts.httpReferrer = httpreferrer;
|
||||
}
|
||||
|
||||
const useragent = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT].getValue();
|
||||
const useragent = this.webViewImpl.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT)!.getValue();
|
||||
if (useragent) {
|
||||
opts.userAgent = useragent;
|
||||
}
|
||||
@@ -274,19 +274,18 @@ class EnableRemoteModuleAttribute extends WebViewAttribute {
|
||||
|
||||
// Sets up all of the webview attributes.
|
||||
WebViewImpl.prototype.setupWebViewAttributes = function () {
|
||||
this.attributes = {};
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION] = new PartitionAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC] = new SrcAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE] = new EnableRemoteModuleAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this);
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this);
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION, new PartitionAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC, new SrcAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER, new HttpReferrerAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT, new UserAgentAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, new EnableRemoteModuleAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD, new PreloadAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES, new BlinkFeaturesAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES, new DisableBlinkFeaturesAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES, new WebPreferencesAttribute(this));
|
||||
};
|
||||
|
||||
@@ -16,9 +16,6 @@ export const enum WEB_VIEW_CONSTANTS {
|
||||
ATTRIBUTE_DISABLEBLINKFEATURES = 'disableblinkfeatures',
|
||||
ATTRIBUTE_WEBPREFERENCES = 'webpreferences',
|
||||
|
||||
// Internal attribute.
|
||||
ATTRIBUTE_INTERNALINSTANCEID = 'internalinstanceid',
|
||||
|
||||
// Error messages.
|
||||
ERROR_MSG_ALREADY_NAVIGATED = 'The object has already navigated, so its partition cannot be changed.',
|
||||
ERROR_MSG_CANNOT_INJECT_SCRIPT = '<webview> = ' + 'Script cannot be injected into content until the page has loaded.',
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
|
||||
import { WebViewImpl as IWebViewImpl, webViewImplModule } from '@electron/internal/renderer/web-view/web-view-impl';
|
||||
import type { SrcAttribute } from '@electron/internal/renderer/web-view/web-view-attributes';
|
||||
|
||||
// Return a WebViewElement class that is defined in this context.
|
||||
const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof webViewImplModule) => {
|
||||
@@ -49,7 +50,7 @@ const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof
|
||||
if (!internal.elementAttached) {
|
||||
guestViewInternal.registerEvents(internal, internal.viewInstanceId);
|
||||
internal.elementAttached = true;
|
||||
internal.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].parse();
|
||||
(internal.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC) as SrcAttribute).parse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-inte
|
||||
import * as guestViewInternal from '@electron/internal/renderer/web-view/guest-view-internal';
|
||||
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
|
||||
import { syncMethods, asyncMethods, properties } from '@electron/internal/common/web-view-methods';
|
||||
import type { WebViewAttribute, PartitionAttribute } from '@electron/internal/renderer/web-view/web-view-attributes';
|
||||
import { deserialize } from '@electron/internal/common/type-utils';
|
||||
const { webFrame } = electron;
|
||||
|
||||
@@ -33,7 +34,7 @@ export class WebViewImpl {
|
||||
public internalElement: HTMLIFrameElement
|
||||
|
||||
// Replaced in web-view-attributes
|
||||
public attributes: Record<string, any> = {}
|
||||
public attributes = new Map<string, WebViewAttribute>();
|
||||
public setupWebViewAttributes (): void {}
|
||||
|
||||
constructor (public webviewNode: HTMLElement) {
|
||||
@@ -76,7 +77,7 @@ export class WebViewImpl {
|
||||
}
|
||||
|
||||
this.beforeFirstNavigation = true;
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].validPartitionId = true;
|
||||
(this.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION) as PartitionAttribute).validPartitionId = true;
|
||||
|
||||
// Since attachment swaps a local frame for a remote frame, we need our
|
||||
// internal iframe element to be local again before we can reattach.
|
||||
@@ -95,12 +96,12 @@ export class WebViewImpl {
|
||||
// attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more
|
||||
// details.
|
||||
handleWebviewAttributeMutation (attributeName: string, oldValue: any, newValue: any) {
|
||||
if (!this.attributes[attributeName] || this.attributes[attributeName].ignoreMutation) {
|
||||
if (!this.attributes.has(attributeName) || this.attributes.get(attributeName)!.ignoreMutation) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Let the changed attribute handle its own mutation
|
||||
this.attributes[attributeName].handleMutation(oldValue, newValue);
|
||||
this.attributes.get(attributeName)!.handleMutation(oldValue, newValue);
|
||||
}
|
||||
|
||||
onElementResize () {
|
||||
@@ -149,7 +150,7 @@ export class WebViewImpl {
|
||||
// Touching the src attribute triggers a navigation. To avoid
|
||||
// triggering a page reload on every guest-initiated navigation,
|
||||
// we do not handle this mutation.
|
||||
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].setValueIgnoreMutation(newValue);
|
||||
this.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC)!.setValueIgnoreMutation(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +164,7 @@ export class WebViewImpl {
|
||||
}
|
||||
|
||||
onAttach (storagePartitionId: number) {
|
||||
return this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].setValue(storagePartitionId);
|
||||
return this.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION)!.setValue(storagePartitionId);
|
||||
}
|
||||
|
||||
buildParams () {
|
||||
@@ -172,10 +173,8 @@ export class WebViewImpl {
|
||||
userAgentOverride: this.userAgentOverride
|
||||
};
|
||||
|
||||
for (const attributeName in this.attributes) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.attributes, attributeName)) {
|
||||
params[attributeName] = this.attributes[attributeName].getValue();
|
||||
}
|
||||
for (const [attributeName, attribute] of this.attributes) {
|
||||
params[attributeName] = attribute.getValue();
|
||||
}
|
||||
|
||||
return params;
|
||||
|
||||
@@ -181,7 +181,7 @@ class BrowserWindowProxy {
|
||||
this.guestId = guestId;
|
||||
this._location = new LocationProxy(guestId);
|
||||
|
||||
ipcRendererInternal.once(`ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_${guestId}`, () => {
|
||||
ipcRendererInternal.onceMessageFromMain(`ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_${guestId}`, () => {
|
||||
removeProxy(guestId);
|
||||
this.closed = true;
|
||||
});
|
||||
@@ -281,7 +281,7 @@ export const windowSetup = (
|
||||
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['prompt'], window.prompt);
|
||||
|
||||
if (!usesNativeWindowOpen || openerId != null) {
|
||||
ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
|
||||
ipcRendererInternal.onMessageFromMain('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
|
||||
_event, sourceId: number, message: any, sourceOrigin: string
|
||||
) {
|
||||
// Manually dispatch event instead of using postMessage because we also need to
|
||||
@@ -336,7 +336,7 @@ export const windowSetup = (
|
||||
let cachedVisibilityState = isHiddenPage ? 'hidden' : 'visible';
|
||||
|
||||
// Subscribe to visibilityState changes.
|
||||
ipcRendererInternal.on('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', function (_event, visibilityState: VisibilityState) {
|
||||
ipcRendererInternal.onMessageFromMain('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', function (_event, visibilityState: VisibilityState) {
|
||||
if (cachedVisibilityState !== visibilityState) {
|
||||
cachedVisibilityState = visibilityState;
|
||||
document.dispatchEvent(new Event('visibilitychange'));
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "10.1.4",
|
||||
"version": "10.3.0",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@electron/docs-parser": "^0.7.2",
|
||||
"@electron/docs-parser": "^0.10.0",
|
||||
"@electron/typescript-definitions": "^8.7.2",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
"@octokit/rest": "^16.3.2",
|
||||
"@primer/octicons": "^9.1.1",
|
||||
"@types/basic-auth": "^1.1.3",
|
||||
|
||||
1
patches/angle/.patches
Normal file
1
patches/angle/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-2882e1afd982.patch
|
||||
65
patches/angle/cherry-pick-2882e1afd982.patch
Normal file
65
patches/angle/cherry-pick-2882e1afd982.patch
Normal file
@@ -0,0 +1,65 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 20 Oct 2020 09:45:23 -0400
|
||||
Subject: Fix missing validation cache update on VAO binding.
|
||||
|
||||
Bug: chromium:1139398
|
||||
Change-Id: I85a0d7a72bc2c97b07ebc5f86effd8e36aefd544
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2485581
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
|
||||
index c2d3868ff04af0813d496432c0f34b4f4a134fda..a6fa42c33a36a3e83f1bf959cbb566c6160e551e 100644
|
||||
--- a/src/libANGLE/Context.cpp
|
||||
+++ b/src/libANGLE/Context.cpp
|
||||
@@ -8666,6 +8666,7 @@ void StateCache::onVertexArrayBindingChange(Context *context)
|
||||
updateActiveAttribsMask(context);
|
||||
updateVertexElementLimits(context);
|
||||
updateBasicDrawStatesError();
|
||||
+ updateBasicDrawElementsError();
|
||||
}
|
||||
|
||||
void StateCache::onProgramExecutableChange(Context *context)
|
||||
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
|
||||
index 10fa566d0040b2abe8d7193d668198bc2e461e38..8f33d1db627ccadb8f4bb8755bb43713365a6c6d 100644
|
||||
--- a/src/libANGLE/Context.h
|
||||
+++ b/src/libANGLE/Context.h
|
||||
@@ -203,6 +203,7 @@ class StateCache final : angle::NonCopyable
|
||||
// 2. onVertexArrayBufferStateChange.
|
||||
// 3. onBufferBindingChange.
|
||||
// 4. onVertexArrayStateChange.
|
||||
+ // 5. onVertexArrayBindingStateChange.
|
||||
intptr_t getBasicDrawElementsError(const Context *context) const
|
||||
{
|
||||
if (mCachedBasicDrawElementsError != kInvalidPointer)
|
||||
diff --git a/src/tests/gl_tests/StateChangeTest.cpp b/src/tests/gl_tests/StateChangeTest.cpp
|
||||
index 7356edc230e0f067e47023d952cb18f41b154ada..1c886e9c66caaf7508867bf06c94b8910d5fd736 100644
|
||||
--- a/src/tests/gl_tests/StateChangeTest.cpp
|
||||
+++ b/src/tests/gl_tests/StateChangeTest.cpp
|
||||
@@ -5206,6 +5206,25 @@ TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest, BindZeroSizeBufferThen
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+// Tests DrawElements with an empty buffer using a VAO.
|
||||
+TEST_P(WebGL2ValidationStateChangeTest, DrawElementsEmptyVertexArray)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
|
||||
+
|
||||
+ glUseProgram(program);
|
||||
+
|
||||
+ // Draw with empty buffer. Out of range but valid.
|
||||
+ GLBuffer buffer;
|
||||
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
||||
+ glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(0x1000));
|
||||
+
|
||||
+ // Switch VAO. No buffer bound, should be an error.
|
||||
+ GLVertexArray vao;
|
||||
+ glBindVertexArray(vao);
|
||||
+ glDrawElements(GL_LINE_STRIP, 0x1000, GL_UNSIGNED_SHORT,
|
||||
+ reinterpret_cast<const GLvoid *>(0x1000));
|
||||
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
|
||||
+}
|
||||
} // anonymous namespace
|
||||
|
||||
ANGLE_INSTANTIATE_TEST_ES2(StateChangeTest);
|
||||
@@ -74,7 +74,6 @@ add_trustedauthclient_to_urlloaderfactory.patch
|
||||
feat_allow_disabling_blink_scheduler_throttling_per_renderview.patch
|
||||
accessible_pane_view.patch
|
||||
fix_use_the_new_mediaplaypause_key_listener_for_internal_chrome.patch
|
||||
use_electron_resources_in_pdf_util.patch
|
||||
hack_plugin_response_interceptor_to_point_to_electron.patch
|
||||
fix_route_mouse_event_navigations_through_the_web_contents_delegate.patch
|
||||
feat_add_support_for_overriding_the_base_spellchecker_download_url.patch
|
||||
@@ -94,7 +93,6 @@ fix_swap_global_proxies_before_initializing_the_windows_proxies.patch
|
||||
allow_setting_secondary_label_via_simplemenumodel.patch
|
||||
refactor_expose_cursor_changes_to_the_webcontentsobserver.patch
|
||||
disable_unnecessary_ischromefirstrun_check.patch
|
||||
use_electron_resources_in_icon_reader_service.patch
|
||||
fix_include_missing_header_file.patch
|
||||
cherrypick_future_chrome_commit_to_remove_superfluous_dcheck.patch
|
||||
worker_feat_add_hook_to_notify_script_ready.patch
|
||||
@@ -105,3 +103,25 @@ fix_properly_honor_printing_page_ranges.patch
|
||||
cherry-pick-8629cd7f8af3.patch
|
||||
avoid_use-after-free.patch
|
||||
don_t_create_providers_if_context_is_lost.patch
|
||||
fix_use_electron_generated_resources.patch
|
||||
chore_expose_v8_initialization_isolate_callbacks.patch
|
||||
cherry-pick-f440137cd96a.patch
|
||||
cherry-pick-30261f9de11e.patch
|
||||
cherry-pick-88f263f401b4.patch
|
||||
cherry-pick-229fdaf8fc05.patch
|
||||
cherry-pick-1ed869ad4bb3.patch
|
||||
cherry-pick-8f24f935c903.patch
|
||||
crashpad-initialize-logging.patch
|
||||
cherry-pick-bbb64b5c6916.patch
|
||||
ignore_renderframehostimpl_detach_for_speculative_rfhs.patch
|
||||
cherry-pick-eec5025668f8.patch
|
||||
cherry-pick-bbc6ab5bb49c.patch
|
||||
cherry-pick-3abc372c9c00.patch
|
||||
cherry-pick-d8d64b7cd244.patch
|
||||
cherry-pick-5ffbb7ed173a.patch
|
||||
ui_check_that_unpremultiply_is_passed_a_32bpp_image.patch
|
||||
cherry-pick-ecdec1fb0f42.patch
|
||||
merge_m86_ensure_that_buffers_used_by_imagedecoder_haven_t_been.patch
|
||||
cherry-pick-2d18de63acf1.patch
|
||||
only_zero_out_cross-origin_audio_that_doesn_t_get_played_out.patch
|
||||
fix_setparentacessibile_crash_win.patch
|
||||
|
||||
160
patches/chromium/cherry-pick-1ed869ad4bb3.patch
Normal file
160
patches/chromium/cherry-pick-1ed869ad4bb3.patch
Normal file
@@ -0,0 +1,160 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Reilly Grant <reillyg@chromium.org>
|
||||
Date: Wed, 7 Oct 2020 23:26:36 +0000
|
||||
Subject: usb: Prevent parallel calls to UsbDevice::Open
|
||||
|
||||
This change adds a check to prevent a Mojo client from calling Open()
|
||||
multiple times while the open is in progress.
|
||||
|
||||
Bug: 1135857
|
||||
Change-Id: Ib467de9129673710b883d9e186c32c359f8592d8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454846
|
||||
Auto-Submit: Reilly Grant <reillyg@chromium.org>
|
||||
Reviewed-by: Matt Reynolds <mattreynolds@chromium.org>
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#814940}
|
||||
|
||||
diff --git a/services/device/usb/mojo/device_impl.cc b/services/device/usb/mojo/device_impl.cc
|
||||
index 1e7a6a798cf43d24a6dcb42e4ac676098908e0a1..bc7081486476045ed7d957ba8cdec8a52227c517 100644
|
||||
--- a/services/device/usb/mojo/device_impl.cc
|
||||
+++ b/services/device/usb/mojo/device_impl.cc
|
||||
@@ -160,6 +160,7 @@ void DeviceImpl::OnOpen(base::WeakPtr<DeviceImpl> self,
|
||||
return;
|
||||
}
|
||||
|
||||
+ self->opening_ = false;
|
||||
self->device_handle_ = std::move(handle);
|
||||
if (self->device_handle_ && self->client_)
|
||||
self->client_->OnDeviceOpened();
|
||||
@@ -175,16 +176,19 @@ void DeviceImpl::OnPermissionGrantedForOpen(OpenCallback callback,
|
||||
device_->Open(base::BindOnce(
|
||||
&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), std::move(callback)));
|
||||
} else {
|
||||
+ opening_ = false;
|
||||
std::move(callback).Run(mojom::UsbOpenDeviceError::ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceImpl::Open(OpenCallback callback) {
|
||||
- if (device_handle_) {
|
||||
+ if (opening_ || device_handle_) {
|
||||
std::move(callback).Run(mojom::UsbOpenDeviceError::ALREADY_OPEN);
|
||||
return;
|
||||
}
|
||||
|
||||
+ opening_ = true;
|
||||
+
|
||||
if (!device_->permission_granted()) {
|
||||
device_->RequestPermission(
|
||||
base::BindOnce(&DeviceImpl::OnPermissionGrantedForOpen,
|
||||
diff --git a/services/device/usb/mojo/device_impl.h b/services/device/usb/mojo/device_impl.h
|
||||
index ca3bffe4392f7607f7cf7445e2f21320fc02a82f..0965ca72663e14463aedfcff813c8307a1ebd447 100644
|
||||
--- a/services/device/usb/mojo/device_impl.h
|
||||
+++ b/services/device/usb/mojo/device_impl.h
|
||||
@@ -106,7 +106,9 @@ class DeviceImpl : public mojom::UsbDevice, public device::UsbDevice::Observer {
|
||||
ScopedObserver<device::UsbDevice, device::UsbDevice::Observer> observer_;
|
||||
|
||||
// The device handle. Will be null before the device is opened and after it
|
||||
- // has been closed.
|
||||
+ // has been closed. |opening_| is set to true while the asynchronous open is
|
||||
+ // in progress.
|
||||
+ bool opening_ = false;
|
||||
scoped_refptr<UsbDeviceHandle> device_handle_;
|
||||
|
||||
mojo::SelfOwnedReceiverRef<mojom::UsbDevice> receiver_;
|
||||
diff --git a/services/device/usb/mojo/device_impl_unittest.cc b/services/device/usb/mojo/device_impl_unittest.cc
|
||||
index f0cd0eab4cf04d6f922c1748274d8f5f07a9452e..81045373bb3fa306b78f580f87424eacba36cd3d 100644
|
||||
--- a/services/device/usb/mojo/device_impl_unittest.cc
|
||||
+++ b/services/device/usb/mojo/device_impl_unittest.cc
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/stl_util.h"
|
||||
+#include "base/test/bind_test_util.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "mojo/public/cpp/bindings/interface_request.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
@@ -265,7 +266,10 @@ class USBDeviceImplTest : public testing::Test {
|
||||
void OpenMockHandle(UsbDevice::OpenCallback& callback) {
|
||||
EXPECT_FALSE(is_device_open_);
|
||||
is_device_open_ = true;
|
||||
- std::move(callback).Run(mock_handle_);
|
||||
+ // Simulate the asynchronous device opening process.
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
|
||||
+ FROM_HERE, base::BindOnce(std::move(callback), mock_handle_),
|
||||
+ base::TimeDelta::FromMilliseconds(1));
|
||||
}
|
||||
|
||||
void CloseMockHandle() {
|
||||
@@ -515,17 +519,39 @@ TEST_F(USBDeviceImplTest, OpenFailure) {
|
||||
GetMockDeviceProxy(device_client.CreateInterfacePtrAndBind());
|
||||
|
||||
EXPECT_CALL(mock_device(), OpenInternal(_))
|
||||
- .WillOnce(Invoke([](UsbDevice::OpenCallback& callback) {
|
||||
+ .WillOnce([](UsbDevice::OpenCallback& callback) {
|
||||
std::move(callback).Run(nullptr);
|
||||
- }));
|
||||
+ });
|
||||
EXPECT_CALL(device_client, OnDeviceOpened()).Times(0);
|
||||
EXPECT_CALL(device_client, OnDeviceClosed()).Times(0);
|
||||
|
||||
- base::RunLoop loop;
|
||||
- device->Open(base::BindOnce(&ExpectOpenAndThen,
|
||||
- mojom::UsbOpenDeviceError::ACCESS_DENIED,
|
||||
- loop.QuitClosure()));
|
||||
- loop.Run();
|
||||
+ {
|
||||
+ base::RunLoop loop;
|
||||
+ device->Open(
|
||||
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
|
||||
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::ACCESS_DENIED);
|
||||
+ loop.Quit();
|
||||
+ }));
|
||||
+ loop.Run();
|
||||
+ }
|
||||
+
|
||||
+ // A second attempt can succeed.
|
||||
+ EXPECT_CALL(mock_device(), OpenInternal(_));
|
||||
+ EXPECT_CALL(device_client, OnDeviceOpened());
|
||||
+ EXPECT_CALL(device_client, OnDeviceClosed());
|
||||
+
|
||||
+ {
|
||||
+ base::RunLoop loop;
|
||||
+ device->Open(
|
||||
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
|
||||
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::OK);
|
||||
+ loop.Quit();
|
||||
+ }));
|
||||
+ loop.Run();
|
||||
+ }
|
||||
+
|
||||
+ device.reset();
|
||||
+ base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
TEST_F(USBDeviceImplTest, OpenDelayedFailure) {
|
||||
@@ -549,6 +575,24 @@ TEST_F(USBDeviceImplTest, OpenDelayedFailure) {
|
||||
std::move(saved_callback).Run(nullptr);
|
||||
}
|
||||
|
||||
+TEST_F(USBDeviceImplTest, MultipleOpenNotAllowed) {
|
||||
+ MockUsbDeviceClient device_client;
|
||||
+ mojo::Remote<mojom::UsbDevice> device =
|
||||
+ GetMockDeviceProxy(device_client.CreateInterfacePtrAndBind());
|
||||
+
|
||||
+ base::RunLoop loop;
|
||||
+ device->Open(
|
||||
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
|
||||
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::OK);
|
||||
+ }));
|
||||
+ device->Open(
|
||||
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
|
||||
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::ALREADY_OPEN);
|
||||
+ loop.Quit();
|
||||
+ }));
|
||||
+ loop.Run();
|
||||
+}
|
||||
+
|
||||
TEST_F(USBDeviceImplTest, Close) {
|
||||
MockUsbDeviceClient device_client;
|
||||
mojo::Remote<mojom::UsbDevice> device =
|
||||
64
patches/chromium/cherry-pick-229fdaf8fc05.patch
Normal file
64
patches/chromium/cherry-pick-229fdaf8fc05.patch
Normal file
@@ -0,0 +1,64 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Guido Urdaneta <guidou@chromium.org>
|
||||
Date: Wed, 14 Oct 2020 19:40:12 +0000
|
||||
Subject: Validate input of MediaStreamDispatcherHost::OpenDevice()
|
||||
|
||||
This method forwards to MediaStreamManager::OpenDevice(), which
|
||||
DCHECKs for the stream type to be device video or audio capture
|
||||
(i.e., webcam or mic). However, MSDH admits other stream types,
|
||||
which cause MSM::OpenDevice to hit this DCHECK.
|
||||
|
||||
This CL ensures that a message containing an incorrect stream type,
|
||||
which could be sent by a malicious renderer, results in killing the
|
||||
renderer process.
|
||||
|
||||
Bug: 1135018
|
||||
Change-Id: I3884dde95d92c41f44966a8ab1dd7bdfd4b23b9b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2472397
|
||||
Auto-Submit: Guido Urdaneta <guidou@chromium.org>
|
||||
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
|
||||
Reviewed-by: Avi Drissman <avi@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#817151}
|
||||
|
||||
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
|
||||
index 0d5ef5f9d79dbc82a325f91b36350d01d760a064..ab0a195c2da772ea5825bb97e54743318bd06841 100644
|
||||
--- a/content/browser/bad_message.h
|
||||
+++ b/content/browser/bad_message.h
|
||||
@@ -255,6 +255,7 @@ enum BadMessageReason {
|
||||
RFH_INVALID_CALL_FROM_NOT_MAIN_FRAME = 227,
|
||||
INPUT_ROUTER_INVALID_EVENT_SOURCE = 228,
|
||||
RWH_CLOSE_PORTAL = 233,
|
||||
+ MSDH_INVALID_STREAM_TYPE = 234,
|
||||
|
||||
// Please add new elements here. The naming convention is abbreviated class
|
||||
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
|
||||
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
|
||||
index 3e43ba7ad5c9e7223df587f3126807618da17245..835c9be6981b0b0fa3548a4fa7629d19280aec76 100644
|
||||
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
|
||||
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
|
||||
@@ -196,6 +196,13 @@ void MediaStreamDispatcherHost::OpenDevice(int32_t page_request_id,
|
||||
blink::mojom::MediaStreamType type,
|
||||
OpenDeviceCallback callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
+ // OpenDevice is only supported for microphone or webcam capture.
|
||||
+ if (type != blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE &&
|
||||
+ type != blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
|
||||
+ bad_message::ReceivedBadMessage(
|
||||
+ render_process_id_, bad_message::MDDH_INVALID_DEVICE_TYPE_REQUEST);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
base::PostTaskAndReplyWithResult(
|
||||
GetUIThreadTaskRunner({}).get(), FROM_HERE,
|
||||
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
|
||||
index c394f02fb8d8150689109bc2c853f63af965fc29..e6c4aadf3dd94baec25aa3e6ce24aae191a6d145 100644
|
||||
--- a/tools/metrics/histograms/enums.xml
|
||||
+++ b/tools/metrics/histograms/enums.xml
|
||||
@@ -6154,6 +6154,7 @@ Unknown properties are collapsed to zero. -->
|
||||
<int value="227" label="RFH_INVALID_CALL_FROM_NOT_MAIN_FRAME"/>
|
||||
<int value="228" label="INPUT_ROUTER_INVALID_EVENT_SOURCE"/>
|
||||
<int value="233" label="RWH_CLOSE_PORTAL"/>
|
||||
+ <int value="234" label="MSDH_INVALID_STREAM_TYPE"/>
|
||||
</enum>
|
||||
|
||||
<enum name="BadMessageReasonExtensions">
|
||||
52
patches/chromium/cherry-pick-2d18de63acf1.patch
Normal file
52
patches/chromium/cherry-pick-2d18de63acf1.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: danakj <danakj@chromium.org>
|
||||
Date: Tue, 17 Nov 2020 21:47:27 +0000
|
||||
Subject: Convert strides with padding in skia::SkBitmapToN32OpaqueOrPremul().
|
||||
|
||||
Code using bitmaps converted with SkBitmapToN32OpaqueOrPremul() can
|
||||
easily assume that the pixels are one contiguous (width*4*height)-sized
|
||||
buffer. If it's not then out-of-bounds read/write can occur.
|
||||
|
||||
Also adds tests for SkBitmapToN32OpaqueOrPremul().
|
||||
|
||||
R=fmalita@chromium.org
|
||||
|
||||
Bug: 1147431, 1144462
|
||||
Change-Id: I21f7a958a8c9231bf5f052f8ff246f2c249bd70b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2544032
|
||||
Commit-Queue: danakj <danakj@chromium.org>
|
||||
Reviewed-by: Florin Malita <fmalita@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#828406}
|
||||
|
||||
diff --git a/skia/ext/skia_utils_base.cc b/skia/ext/skia_utils_base.cc
|
||||
index 516ad7ea1e3a0acb1c8b207f98f6daf534262cbc..f9e622eff3ec6c3287138d7cdf68814b8535a338 100644
|
||||
--- a/skia/ext/skia_utils_base.cc
|
||||
+++ b/skia/ext/skia_utils_base.cc
|
||||
@@ -85,7 +85,8 @@ void WriteSkFontStyle(base::Pickle* pickle, SkFontStyle style) {
|
||||
bool SkBitmapToN32OpaqueOrPremul(const SkBitmap& in, SkBitmap* out) {
|
||||
DCHECK(out);
|
||||
const SkImageInfo& info = in.info();
|
||||
- if (info.colorType() == kN32_SkColorType &&
|
||||
+ const bool stride_matches_width = in.rowBytes() == info.minRowBytes();
|
||||
+ if (stride_matches_width && info.colorType() == kN32_SkColorType &&
|
||||
(info.alphaType() == kPremul_SkAlphaType ||
|
||||
info.alphaType() == kOpaque_SkAlphaType)) {
|
||||
// Shallow copy if the data is already in the right format.
|
||||
diff --git a/skia/ext/skia_utils_base.h b/skia/ext/skia_utils_base.h
|
||||
index 2a1eca124e91695ddec635e593ad1e9b650aa156..40401bb2fe0e484fae64490757d63f85e5c5ffea 100644
|
||||
--- a/skia/ext/skia_utils_base.h
|
||||
+++ b/skia/ext/skia_utils_base.h
|
||||
@@ -42,9 +42,10 @@ SK_API void WriteSkFontIdentity(
|
||||
// Writes style into the request pickle.
|
||||
SK_API void WriteSkFontStyle(base::Pickle* pickle, SkFontStyle style);
|
||||
|
||||
-// Converts an SkBitmap to an Opaque or Premul N32 SkBitmap. If the input is in
|
||||
-// the right format (N32 Opaque or Premul) already, points |out| directly at
|
||||
-// |in|. |out| may or may not be GPU-backed.
|
||||
+// Converts an SkBitmap to an Opaque or Premul N32 SkBitmap with stride matching
|
||||
+// the width of each row. If the input is has the right format (N32 Opaque or
|
||||
+// Premul) without stride padding already, this assigns `in` to `out`, sharing
|
||||
+// the backing pixels. `out` may or may not be GPU-backed.
|
||||
//
|
||||
// If unsuccessful, returns false, but |out| may be modified.
|
||||
SK_API bool SkBitmapToN32OpaqueOrPremul(const SkBitmap& in, SkBitmap* out);
|
||||
29
patches/chromium/cherry-pick-30261f9de11e.patch
Normal file
29
patches/chromium/cherry-pick-30261f9de11e.patch
Normal file
@@ -0,0 +1,29 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lei Zhang <thestig@chromium.org>
|
||||
Date: Thu, 1 Oct 2020 19:18:54 +0000
|
||||
Subject: Check RF is alive In PrintRenderFrameHelper::PreviewPageRendered().
|
||||
|
||||
Do not take an accessibility snapshot if the RenderFrame is gone.
|
||||
|
||||
Bug: 1133983
|
||||
Change-Id: I612cc72936a1dcedc5180c24eae067e47237b09b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2442375
|
||||
Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org>
|
||||
Commit-Queue: Lei Zhang <thestig@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#812851}
|
||||
|
||||
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
|
||||
index c0107f561f444d537735d4725c6dbecbcaf45226..1f7b7294aa5afb7f967ec260ab9f62d8b27d6827 100644
|
||||
--- a/components/printing/renderer/print_render_frame_helper.cc
|
||||
+++ b/components/printing/renderer/print_render_frame_helper.cc
|
||||
@@ -2463,6 +2463,10 @@ bool PrintRenderFrameHelper::PreviewPageRendered(
|
||||
"page_number", page_number);
|
||||
|
||||
#if BUILDFLAG(ENABLE_TAGGED_PDF)
|
||||
+ // Make sure the RenderFrame is alive before taking the snapshot.
|
||||
+ if (render_frame_gone_)
|
||||
+ snapshotter_.reset();
|
||||
+
|
||||
// For tagged PDF exporting, send a snapshot of the accessibility tree
|
||||
// along with page 0. The accessibility tree contains the content for
|
||||
// all of the pages of the main frame.
|
||||
61
patches/chromium/cherry-pick-3abc372c9c00.patch
Normal file
61
patches/chromium/cherry-pick-3abc372c9c00.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Date: Tue, 3 Nov 2020 23:00:29 +0000
|
||||
Subject: Apply markup sanitizer in CompositeEditCommand::MoveParagraphs()
|
||||
|
||||
CompositeEditCommand::MoveParagraphs() serailizes part of the DOM and
|
||||
then re-parse it and insert it at some other place of the document. This
|
||||
is essentially a copy-and-paste, and can be exploited in the same way
|
||||
how copy-and-paste is exploited. So we should also sanitize markup in
|
||||
the function.
|
||||
|
||||
(cherry picked from commit c529cbcc1bb0f72af944c30f03c2b3b435317bc7)
|
||||
|
||||
Bug: 1141350
|
||||
Change-Id: I25c1dfc61c20b9134b23e057c5a3a0f56c190b5c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2500633
|
||||
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
|
||||
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#821098}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2518088
|
||||
Reviewed-by: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4280@{#1099}
|
||||
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
|
||||
index 08a19440da1bff652481c3cedae2f1edb2b58246..0ba9af6cff6dd6eaa373a0f4dca37226aee85ca0 100644
|
||||
--- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
|
||||
+++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
|
||||
@@ -1507,19 +1507,18 @@ void CompositeEditCommand::MoveParagraphs(
|
||||
// FIXME: This is an inefficient way to preserve style on nodes in the
|
||||
// paragraph to move. It shouldn't matter though, since moved paragraphs will
|
||||
// usually be quite small.
|
||||
- DocumentFragment* fragment =
|
||||
- start_of_paragraph_to_move.DeepEquivalent() !=
|
||||
- end_of_paragraph_to_move.DeepEquivalent()
|
||||
- ? CreateFragmentFromMarkup(
|
||||
- GetDocument(),
|
||||
- CreateMarkup(start.ParentAnchoredEquivalent(),
|
||||
- end.ParentAnchoredEquivalent(),
|
||||
- CreateMarkupOptions::Builder()
|
||||
- .SetShouldConvertBlocksToInlines(true)
|
||||
- .SetConstrainingAncestor(constraining_ancestor)
|
||||
- .Build()),
|
||||
- "", kDisallowScriptingAndPluginContent)
|
||||
- : nullptr;
|
||||
+ DocumentFragment* fragment = nullptr;
|
||||
+ if (start_of_paragraph_to_move.DeepEquivalent() !=
|
||||
+ end_of_paragraph_to_move.DeepEquivalent()) {
|
||||
+ const String paragraphs_markup = CreateMarkup(
|
||||
+ start.ParentAnchoredEquivalent(), end.ParentAnchoredEquivalent(),
|
||||
+ CreateMarkupOptions::Builder()
|
||||
+ .SetShouldConvertBlocksToInlines(true)
|
||||
+ .SetConstrainingAncestor(constraining_ancestor)
|
||||
+ .Build());
|
||||
+ fragment = CreateSanitizedFragmentFromMarkupWithContext(
|
||||
+ GetDocument(), paragraphs_markup, 0, paragraphs_markup.length(), "");
|
||||
+ }
|
||||
|
||||
// A non-empty paragraph's style is moved when we copy and move it. We don't
|
||||
// move anything if we're given an empty paragraph, but an empty paragraph can
|
||||
37
patches/chromium/cherry-pick-5ffbb7ed173a.patch
Normal file
37
patches/chromium/cherry-pick-5ffbb7ed173a.patch
Normal file
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Darwin Huang <huangdarwin@chromium.org>
|
||||
Date: Fri, 13 Nov 2020 10:07:05 +0000
|
||||
Subject: Pepper: Ensure weak pointer is still valid before use (M86).
|
||||
|
||||
TBR=bbudge@chromium.org
|
||||
(cherry picked from commit f24c213293752250db05e11c5e4b77adce002d38)
|
||||
|
||||
Bug: 1146675
|
||||
Change-Id: I382dcb5c0b09a26e3c397ebef46947f626e2aef9
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2527065
|
||||
Reviewed-by: Bill Budge <bbudge@chromium.org>
|
||||
Commit-Queue: Darwin Huang <huangdarwin@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#825558}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2536757
|
||||
Reviewed-by: Darwin Huang <huangdarwin@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1448}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/content/browser/renderer_host/pepper/pepper_file_io_host.cc
|
||||
index 28fba2fc56ddb7f42f3390db99999998ba912867..74bb7c539f8f05971b020e1d370098f5825e0ac2 100644
|
||||
--- a/content/browser/renderer_host/pepper/pepper_file_io_host.cc
|
||||
+++ b/content/browser/renderer_host/pepper/pepper_file_io_host.cc
|
||||
@@ -248,7 +248,12 @@ void PepperFileIOHost::GotUIThreadStuffForInternalFileSystems(
|
||||
return;
|
||||
}
|
||||
|
||||
- DCHECK(file_system_host_.get());
|
||||
+ if (!file_system_host_.get()) {
|
||||
+ reply_context.params.set_result(PP_ERROR_FAILED);
|
||||
+ SendOpenErrorReply(reply_context);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
DCHECK(file_system_host_->GetFileSystemOperationRunner());
|
||||
|
||||
file_system_host_->GetFileSystemOperationRunner()->OpenFile(
|
||||
315
patches/chromium/cherry-pick-88f263f401b4.patch
Normal file
315
patches/chromium/cherry-pick-88f263f401b4.patch
Normal file
@@ -0,0 +1,315 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Will Cassella <cassew@google.com>
|
||||
Date: Thu, 24 Sep 2020 22:54:27 +0000
|
||||
Subject: Add callback to WebMediaPlayerImpl to notify when a redirect occurs
|
||||
|
||||
(cherry picked from commit 8b18bcfd9aa8096c4551ec34c0225b6017cd211e)
|
||||
|
||||
Bug: 1128657
|
||||
Change-Id: I9548e1f3bfe5693871a56e23c3373f45147e52e0
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2422091
|
||||
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
|
||||
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
|
||||
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#809217}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2425223
|
||||
Commit-Queue: Will Cassella <cassew@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#993}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/media/blink/multibuffer_data_source.cc b/media/blink/multibuffer_data_source.cc
|
||||
index 0f6ae1fb8b4ff9f24ce3f407b7359e016fc6de5f..4ec77cf8a6b56002e601fb89eb0dee059f3ab31b 100644
|
||||
--- a/media/blink/multibuffer_data_source.cc
|
||||
+++ b/media/blink/multibuffer_data_source.cc
|
||||
@@ -145,7 +145,7 @@ MultibufferDataSource::MultibufferDataSource(
|
||||
DCHECK(url_data_.get());
|
||||
url_data_->Use();
|
||||
url_data_->OnRedirect(
|
||||
- base::BindOnce(&MultibufferDataSource::OnRedirect, weak_ptr_));
|
||||
+ base::BindOnce(&MultibufferDataSource::OnRedirected, weak_ptr_));
|
||||
}
|
||||
|
||||
MultibufferDataSource::~MultibufferDataSource() {
|
||||
@@ -219,10 +219,10 @@ void MultibufferDataSource::Initialize(InitializeCB init_cb) {
|
||||
}
|
||||
}
|
||||
|
||||
-void MultibufferDataSource::OnRedirect(
|
||||
- const scoped_refptr<UrlData>& destination) {
|
||||
- if (!destination) {
|
||||
- // A failure occured.
|
||||
+void MultibufferDataSource::OnRedirected(
|
||||
+ const scoped_refptr<UrlData>& new_destination) {
|
||||
+ if (!new_destination) {
|
||||
+ // A failure occurred.
|
||||
failed_ = true;
|
||||
if (init_cb_) {
|
||||
render_task_runner_->PostTask(
|
||||
@@ -235,38 +235,39 @@ void MultibufferDataSource::OnRedirect(
|
||||
StopLoader();
|
||||
return;
|
||||
}
|
||||
- if (url_data_->url().GetOrigin() != destination->url().GetOrigin()) {
|
||||
+ if (url_data_->url().GetOrigin() != new_destination->url().GetOrigin()) {
|
||||
single_origin_ = false;
|
||||
}
|
||||
SetReader(nullptr);
|
||||
- url_data_ = std::move(destination);
|
||||
+ url_data_ = std::move(new_destination);
|
||||
|
||||
- if (url_data_) {
|
||||
- url_data_->OnRedirect(
|
||||
- base::BindOnce(&MultibufferDataSource::OnRedirect, weak_ptr_));
|
||||
+ url_data_->OnRedirect(
|
||||
+ base::BindOnce(&MultibufferDataSource::OnRedirected, weak_ptr_));
|
||||
|
||||
- if (init_cb_) {
|
||||
- CreateResourceLoader(0, kPositionNotSpecified);
|
||||
- if (reader_->Available()) {
|
||||
- render_task_runner_->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
|
||||
- } else {
|
||||
- reader_->Wait(1, base::BindOnce(&MultibufferDataSource::StartCallback,
|
||||
- weak_ptr_));
|
||||
- }
|
||||
- } else if (read_op_) {
|
||||
- CreateResourceLoader(read_op_->position(), kPositionNotSpecified);
|
||||
- if (reader_->Available()) {
|
||||
- render_task_runner_->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
|
||||
- } else {
|
||||
- reader_->Wait(
|
||||
- 1, base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
|
||||
- }
|
||||
+ if (init_cb_) {
|
||||
+ CreateResourceLoader(0, kPositionNotSpecified);
|
||||
+ if (reader_->Available()) {
|
||||
+ render_task_runner_->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
|
||||
+ } else {
|
||||
+ reader_->Wait(
|
||||
+ 1, base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
|
||||
+ }
|
||||
+ } else if (read_op_) {
|
||||
+ CreateResourceLoader(read_op_->position(), kPositionNotSpecified);
|
||||
+ if (reader_->Available()) {
|
||||
+ render_task_runner_->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
|
||||
+ } else {
|
||||
+ reader_->Wait(
|
||||
+ 1, base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (redirect_cb_)
|
||||
+ redirect_cb_.Run();
|
||||
}
|
||||
|
||||
void MultibufferDataSource::SetPreload(Preload preload) {
|
||||
@@ -287,6 +288,10 @@ bool MultibufferDataSource::IsCorsCrossOrigin() const {
|
||||
return url_data_->is_cors_cross_origin();
|
||||
}
|
||||
|
||||
+void MultibufferDataSource::OnRedirect(RedirectCB callback) {
|
||||
+ redirect_cb_ = std::move(callback);
|
||||
+}
|
||||
+
|
||||
bool MultibufferDataSource::HasAccessControl() const {
|
||||
return url_data_->has_access_control();
|
||||
}
|
||||
diff --git a/media/blink/multibuffer_data_source.h b/media/blink/multibuffer_data_source.h
|
||||
index 3da5a7bba5e7cc0f54998a81649f4dd9d78aa7be..da316964ff1543086865d7c85597f381ca8a3296 100644
|
||||
--- a/media/blink/multibuffer_data_source.h
|
||||
+++ b/media/blink/multibuffer_data_source.h
|
||||
@@ -38,6 +38,7 @@ class MultiBufferReader;
|
||||
class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
|
||||
public:
|
||||
using DownloadingCB = base::RepeatingCallback<void(bool)>;
|
||||
+ using RedirectCB = base::RepeatingCallback<void()>;
|
||||
|
||||
// Used to specify video preload states. They are "hints" to the browser about
|
||||
// how aggressively the browser should load and buffer data.
|
||||
@@ -82,6 +83,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
|
||||
// This must be called after the response arrives.
|
||||
bool IsCorsCrossOrigin() const;
|
||||
|
||||
+ // Provides a callback to be run when the underlying url is redirected.
|
||||
+ void OnRedirect(RedirectCB callback);
|
||||
+
|
||||
// Returns true if the response includes an Access-Control-Allow-Origin
|
||||
// header (that is not "null").
|
||||
bool HasAccessControl() const;
|
||||
@@ -128,7 +132,7 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
|
||||
bool cancel_on_defer_for_testing() const { return cancel_on_defer_; }
|
||||
|
||||
protected:
|
||||
- void OnRedirect(const scoped_refptr<UrlData>& destination);
|
||||
+ void OnRedirected(const scoped_refptr<UrlData>& new_destination);
|
||||
|
||||
// A factory method to create a BufferedResourceLoader based on the read
|
||||
// parameters.
|
||||
@@ -243,6 +247,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
|
||||
// go between different origins.
|
||||
bool single_origin_;
|
||||
|
||||
+ // Callback used when a redirect occurs.
|
||||
+ RedirectCB redirect_cb_;
|
||||
+
|
||||
// Close the connection when we have enough data.
|
||||
bool cancel_on_defer_;
|
||||
|
||||
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
|
||||
index 8c769e69efad504f15a0fc79a2efc0cecf91f0a8..b234635ad78f6a22c91ecf854e7ae2f468315cc4 100644
|
||||
--- a/media/blink/webmediaplayer_impl.cc
|
||||
+++ b/media/blink/webmediaplayer_impl.cc
|
||||
@@ -799,6 +799,8 @@ void WebMediaPlayerImpl::DoLoad(LoadType load_type,
|
||||
base::BindRepeating(&WebMediaPlayerImpl::NotifyDownloading,
|
||||
weak_this_));
|
||||
data_source_.reset(mb_data_source_);
|
||||
+ mb_data_source_->OnRedirect(base::BindRepeating(
|
||||
+ &WebMediaPlayerImpl::OnDataSourceRedirected, weak_this_));
|
||||
mb_data_source_->SetPreload(preload_);
|
||||
mb_data_source_->SetIsClientAudioElement(client_->IsAudioElement());
|
||||
mb_data_source_->Initialize(
|
||||
@@ -2642,6 +2644,16 @@ void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
|
||||
StartPipeline();
|
||||
}
|
||||
|
||||
+void WebMediaPlayerImpl::OnDataSourceRedirected() {
|
||||
+ DVLOG(1) << __func__;
|
||||
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
|
||||
+ DCHECK(mb_data_source_);
|
||||
+
|
||||
+ if (WouldTaintOrigin()) {
|
||||
+ audio_source_provider_->TaintOrigin();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
|
||||
DVLOG(1) << __func__ << "(" << is_downloading << ")";
|
||||
if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
|
||||
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
|
||||
index f4e48c46f6217b218f39b96d40220f040bdb556b..d2ee61bae7e1b30d0eac4a14437e00bbdc8a6e68 100644
|
||||
--- a/media/blink/webmediaplayer_impl.h
|
||||
+++ b/media/blink/webmediaplayer_impl.h
|
||||
@@ -382,6 +382,9 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
|
||||
// Called after asynchronous initialization of a data source completed.
|
||||
void DataSourceInitialized(bool success);
|
||||
|
||||
+ // Called if the |MultiBufferDataSource| is redirected.
|
||||
+ void OnDataSourceRedirected();
|
||||
+
|
||||
// Called when the data source is downloading or paused.
|
||||
void NotifyDownloading(bool is_downloading);
|
||||
|
||||
diff --git a/third_party/blink/public/platform/webaudiosourceprovider_impl.h b/third_party/blink/public/platform/webaudiosourceprovider_impl.h
|
||||
index 5383074dcbffbb77a102de6fb551628ff5b964b8..bbf2a0b3d28282587625d6a5cd0103f6a5378b54 100644
|
||||
--- a/third_party/blink/public/platform/webaudiosourceprovider_impl.h
|
||||
+++ b/third_party/blink/public/platform/webaudiosourceprovider_impl.h
|
||||
@@ -75,6 +75,7 @@ class BLINK_PLATFORM_EXPORT WebAudioSourceProviderImpl
|
||||
bool CurrentThreadIsRenderingThread() override;
|
||||
void SwitchOutputDevice(const std::string& device_id,
|
||||
media::OutputDeviceStatusCB callback) override;
|
||||
+ void TaintOrigin();
|
||||
|
||||
// These methods allow a client to get a copy of the rendered audio.
|
||||
void SetCopyAudioCallback(CopyAudioCB callback);
|
||||
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
|
||||
index 48092cc09148886bf74e544f640fb373bb374102..2ffaca2d399daba2d59f6dd218ce84e5b9c6d880 100644
|
||||
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
|
||||
@@ -102,7 +102,7 @@ class HTMLAudioElementCapturerSourceTest : public testing::Test {
|
||||
media_stream_component_ = MakeGarbageCollected<MediaStreamComponent>(
|
||||
media_stream_source_->Id(), media_stream_source_);
|
||||
|
||||
- // |media_stream_source_| takes wnership of
|
||||
+ // |media_stream_source_| takes ownership of
|
||||
// HtmlAudioElementCapturerSource.
|
||||
auto capture_source = std::make_unique<HtmlAudioElementCapturerSource>(
|
||||
audio_source_, blink::scheduler::GetSingleThreadTaskRunnerForTesting());
|
||||
@@ -183,4 +183,36 @@ TEST_F(HTMLAudioElementCapturerSourceTest,
|
||||
track()->RemoveSink(&sink);
|
||||
}
|
||||
|
||||
+TEST_F(HTMLAudioElementCapturerSourceTest, TaintedPlayerDeliversMutedAudio) {
|
||||
+ testing::InSequence s;
|
||||
+
|
||||
+ base::RunLoop run_loop;
|
||||
+ base::OnceClosure quit_closure = run_loop.QuitClosure();
|
||||
+
|
||||
+ MockMediaStreamAudioSink sink;
|
||||
+ track()->AddSink(&sink);
|
||||
+ EXPECT_CALL(sink, OnSetFormat(testing::_)).Times(1);
|
||||
+ EXPECT_CALL(
|
||||
+ sink,
|
||||
+ OnData(testing::AllOf(
|
||||
+ testing::Property(&media::AudioBus::channels,
|
||||
+ kNumChannelsForTest),
|
||||
+ testing::Property(&media::AudioBus::frames,
|
||||
+ kAudioTrackSamplesPerBuffer),
|
||||
+ testing::Property(&media::AudioBus::AreFramesZero, true)),
|
||||
+ testing::_))
|
||||
+ .Times(1)
|
||||
+ .WillOnce([&](const auto&, auto) { std::move(quit_closure).Run(); });
|
||||
+
|
||||
+ audio_source_->TaintOrigin();
|
||||
+
|
||||
+ std::unique_ptr<media::AudioBus> bus =
|
||||
+ media::AudioBus::Create(kNumChannelsForTest, kAudioTrackSamplesPerBuffer);
|
||||
+ InjectAudio(bus.get());
|
||||
+ run_loop.Run();
|
||||
+
|
||||
+ track()->Stop();
|
||||
+ track()->RemoveSink(&sink);
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
|
||||
index a1e014ceb2ebc1496dd5712f2ed863a56e455af6..c54e1768886a7d2d922f13596a9fb3b456ba6611 100644
|
||||
--- a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
|
||||
+++ b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
|
||||
@@ -81,6 +81,10 @@ class WebAudioSourceProviderImpl::TeeFilter
|
||||
const int num_rendered_frames = renderer_->Render(
|
||||
delay, delay_timestamp, prior_frames_skipped, audio_bus);
|
||||
|
||||
+ // Zero out frames after rendering
|
||||
+ if (origin_tainted_.IsSet())
|
||||
+ audio_bus->Zero();
|
||||
+
|
||||
// Avoid taking the copy lock for the vast majority of cases.
|
||||
if (copy_required_) {
|
||||
base::AutoLock auto_lock(copy_lock_);
|
||||
@@ -114,11 +118,18 @@ class WebAudioSourceProviderImpl::TeeFilter
|
||||
copy_audio_bus_callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
+ void TaintOrigin() { origin_tainted_.Set(); }
|
||||
+
|
||||
private:
|
||||
AudioRendererSink::RenderCallback* renderer_ = nullptr;
|
||||
int channels_ = 0;
|
||||
int sample_rate_ = 0;
|
||||
|
||||
+ // Indicates whether the audio source is tainted, and output should be muted.
|
||||
+ // This can happen if the media element source is a cross-origin source which
|
||||
+ // the page is not allowed to access due to CORS restrictions.
|
||||
+ base::AtomicFlag origin_tainted_;
|
||||
+
|
||||
// The vast majority of the time we're operating in passthrough mode. So only
|
||||
// acquire a lock to read |copy_audio_bus_callback_| when necessary.
|
||||
std::atomic<bool> copy_required_;
|
||||
@@ -318,6 +329,10 @@ void WebAudioSourceProviderImpl::SwitchOutputDevice(
|
||||
sink_->SwitchOutputDevice(device_id, std::move(callback));
|
||||
}
|
||||
|
||||
+void WebAudioSourceProviderImpl::TaintOrigin() {
|
||||
+ tee_filter_->TaintOrigin();
|
||||
+}
|
||||
+
|
||||
void WebAudioSourceProviderImpl::SetCopyAudioCallback(CopyAudioCB callback) {
|
||||
DCHECK(!callback.is_null());
|
||||
tee_filter_->SetCopyAudioCallback(std::move(callback));
|
||||
40
patches/chromium/cherry-pick-8f24f935c903.patch
Normal file
40
patches/chromium/cherry-pick-8f24f935c903.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adrian Taylor <adetaylor@chromium.org>
|
||||
Date: Thu, 5 Nov 2020 08:50:39 +0000
|
||||
Subject: Prevent overflow of drag image on Windows.
|
||||
|
||||
(cherry picked from commit 236b1a349111fc945c741f85e1b1e2e04d9c42ff)
|
||||
|
||||
(cherry picked from commit 5f61af8f3af5efd0d915a51da6df822678d959b9)
|
||||
|
||||
Bug: 1144489
|
||||
Change-Id: I130adffc1c69073295537aaff3ce7054260064fc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2513345
|
||||
Reviewed-by: Krishna Govind <govind@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/branch-heads/4310@{#4}
|
||||
Cr-Original-Original-Branched-From: 3e31ebb7467fdc4295f123385825b8c95ef13332-refs/heads/master@{#822916}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2513349
|
||||
Reviewed-by: Adrian Taylor <adetaylor@chromium.org>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4240@{#1373}
|
||||
Cr-Original-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2517728
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4240_112@{#18}
|
||||
Cr-Branched-From: 427c00d3874b6abcf4c4c2719768835fc3ef26d6-refs/branch-heads/4240@{#1291}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.cc b/ui/base/dragdrop/os_exchange_data_provider_win.cc
|
||||
index b51a0161fdf028ac2a4f079b813d6622602f980c..41f163a3424e89a9370faebb77ac0058da9b01f6 100644
|
||||
--- a/ui/base/dragdrop/os_exchange_data_provider_win.cc
|
||||
+++ b/ui/base/dragdrop/os_exchange_data_provider_win.cc
|
||||
@@ -714,7 +714,7 @@ void OSExchangeDataProviderWin::SetDragImage(
|
||||
int width = unpremul_bitmap.width();
|
||||
int height = unpremul_bitmap.height();
|
||||
size_t rowbytes = unpremul_bitmap.rowBytes();
|
||||
- DCHECK_EQ(rowbytes, static_cast<size_t>(width) * 4u);
|
||||
+ CHECK_EQ(rowbytes, static_cast<size_t>(width) * 4u);
|
||||
|
||||
void* bits;
|
||||
HBITMAP hbitmap;
|
||||
81
patches/chromium/cherry-pick-bbb64b5c6916.patch
Normal file
81
patches/chromium/cherry-pick-bbb64b5c6916.patch
Normal file
@@ -0,0 +1,81 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Cheng <dcheng@chromium.org>
|
||||
Date: Sat, 7 Nov 2020 19:07:34 +0000
|
||||
Subject: Prevent UB if a WeakPtr to an already-destroyed object is
|
||||
dereferenced.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
If a WeakPtr references an already-destroyed object, operator-> and
|
||||
operator* end up simply dereferencing nullptr. However, dereferencing
|
||||
nullptr is undefined behavior and can be optimized in surprising ways
|
||||
by compilers. To prevent this from happening, add a defence of last
|
||||
resort and CHECK that the WeakPtr is still valid.
|
||||
|
||||
(cherry picked from commit 0b308a0e37b9d14a335c3b487511b7117c98d74b)
|
||||
|
||||
Bug: 817982
|
||||
Change-Id: Ib3a025c18fbd9d5db88770fced2063135086847b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463857
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Wez <wez@chromium.org>
|
||||
Reviewed-by: Jan Wilken Dörrie <jdoerrie@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#816701}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2524521
|
||||
Reviewed-by: Adrian Taylor <adetaylor@chromium.org>
|
||||
Reviewed-by: Krishna Govind <govind@chromium.org>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Commit-Queue: Adrian Taylor <adetaylor@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1410}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h
|
||||
index 42aa3412c5ed13c8cdf94584e65e2549548ed125..63508a6043dd55572f0683681f01b238751c360f 100644
|
||||
--- a/base/memory/weak_ptr.h
|
||||
+++ b/base/memory/weak_ptr.h
|
||||
@@ -248,11 +248,11 @@ class WeakPtr : public internal::WeakPtrBase {
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
- DCHECK(get() != nullptr);
|
||||
+ CHECK(ref_.IsValid());
|
||||
return *get();
|
||||
}
|
||||
T* operator->() const {
|
||||
- DCHECK(get() != nullptr);
|
||||
+ CHECK(ref_.IsValid());
|
||||
return get();
|
||||
}
|
||||
|
||||
diff --git a/base/memory/weak_ptr_unittest.cc b/base/memory/weak_ptr_unittest.cc
|
||||
index 6b1e9bf3c50d3da276c0d9d9de5322355719a61e..6425a88a36f716c58951f0bd52ef1979f598e895 100644
|
||||
--- a/base/memory/weak_ptr_unittest.cc
|
||||
+++ b/base/memory/weak_ptr_unittest.cc
|
||||
@@ -798,4 +798,26 @@ TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
|
||||
ASSERT_DCHECK_DEATH(arrow.target.get());
|
||||
}
|
||||
|
||||
+TEST(WeakPtrDeathTest, ArrowOperatorChecksOnBadDereference) {
|
||||
+ // The default style "fast" does not support multi-threaded tests
|
||||
+ // (introduces deadlock on Linux).
|
||||
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
||||
+
|
||||
+ auto target = std::make_unique<Target>();
|
||||
+ WeakPtr<Target> weak = target->AsWeakPtr();
|
||||
+ target.reset();
|
||||
+ EXPECT_CHECK_DEATH(weak->AsWeakPtr());
|
||||
+}
|
||||
+
|
||||
+TEST(WeakPtrDeathTest, StarOperatorChecksOnBadDereference) {
|
||||
+ // The default style "fast" does not support multi-threaded tests
|
||||
+ // (introduces deadlock on Linux).
|
||||
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
||||
+
|
||||
+ auto target = std::make_unique<Target>();
|
||||
+ WeakPtr<Target> weak = target->AsWeakPtr();
|
||||
+ target.reset();
|
||||
+ EXPECT_CHECK_DEATH((*weak).AsWeakPtr());
|
||||
+}
|
||||
+
|
||||
} // namespace base
|
||||
187
patches/chromium/cherry-pick-bbc6ab5bb49c.patch
Normal file
187
patches/chromium/cherry-pick-bbc6ab5bb49c.patch
Normal file
@@ -0,0 +1,187 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Rice <ricea@chromium.org>
|
||||
Date: Wed, 2 Dec 2020 20:26:52 +0000
|
||||
Subject: Add ports 5060 and 5061 to the restricted list
|
||||
|
||||
Some NAT devices examine traffic on port 5060 to look for a valid SIP
|
||||
message. If they find one, they will forward a port back to the origin
|
||||
host. A carefully crafted HTTP request can trick these NAT devices into
|
||||
forwarding an arbitrary port. See https://samy.pl/slipstream for more
|
||||
details on the attack and sample code.
|
||||
|
||||
Block port 5060 for HTTP. Out of an abundance of caution, and to match
|
||||
the Fetch standard (https://github.com/whatwg/fetch/pull/1109), also
|
||||
block port 5061 (SIP over TLS).
|
||||
|
||||
Also reduce the whitespace before protocol description comments. This
|
||||
was insisted on by clang-format and is not worth fighting.
|
||||
|
||||
BUG=1145680
|
||||
|
||||
(cherry picked from commit 90d1302aec437166b383eabc08af741bf24f7ea8)
|
||||
|
||||
(cherry picked from commit dbb0452e69a49e803e0e4cbb6921d5ccad338716)
|
||||
|
||||
Change-Id: I3a556fbbb4dc6099caa4418addaf1e89bf254ae3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2519174
|
||||
Reviewed-by: Matt Menke <mmenke@chromium.org>
|
||||
Commit-Queue: Adam Rice <ricea@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/master@{#824254}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2525474
|
||||
Reviewed-by: Adam Rice <ricea@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4280@{#1247}
|
||||
Cr-Original-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2560585
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Artem Sumaneev <asumaneev@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1474}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/net/base/port_util.cc b/net/base/port_util.cc
|
||||
index a10a4b4038171b317a2a9ae6cd42aeb1166f5552..72af86dd6acf2db65a14b2f1bb2e3a241a1d043d 100644
|
||||
--- a/net/base/port_util.cc
|
||||
+++ b/net/base/port_util.cc
|
||||
@@ -20,73 +20,75 @@ namespace {
|
||||
// The general list of blocked ports. Will be blocked unless a specific
|
||||
// protocol overrides it. (Ex: ftp can use ports 20 and 21)
|
||||
const int kRestrictedPorts[] = {
|
||||
- 1, // tcpmux
|
||||
- 7, // echo
|
||||
- 9, // discard
|
||||
- 11, // systat
|
||||
- 13, // daytime
|
||||
- 15, // netstat
|
||||
- 17, // qotd
|
||||
- 19, // chargen
|
||||
- 20, // ftp data
|
||||
- 21, // ftp access
|
||||
- 22, // ssh
|
||||
- 23, // telnet
|
||||
- 25, // smtp
|
||||
- 37, // time
|
||||
- 42, // name
|
||||
- 43, // nicname
|
||||
- 53, // domain
|
||||
- 77, // priv-rjs
|
||||
- 79, // finger
|
||||
- 87, // ttylink
|
||||
- 95, // supdup
|
||||
- 101, // hostriame
|
||||
- 102, // iso-tsap
|
||||
- 103, // gppitnp
|
||||
- 104, // acr-nema
|
||||
- 109, // pop2
|
||||
- 110, // pop3
|
||||
- 111, // sunrpc
|
||||
- 113, // auth
|
||||
- 115, // sftp
|
||||
- 117, // uucp-path
|
||||
- 119, // nntp
|
||||
- 123, // NTP
|
||||
- 135, // loc-srv /epmap
|
||||
- 139, // netbios
|
||||
- 143, // imap2
|
||||
- 179, // BGP
|
||||
- 389, // ldap
|
||||
- 427, // SLP (Also used by Apple Filing Protocol)
|
||||
- 465, // smtp+ssl
|
||||
- 512, // print / exec
|
||||
- 513, // login
|
||||
- 514, // shell
|
||||
- 515, // printer
|
||||
- 526, // tempo
|
||||
- 530, // courier
|
||||
- 531, // chat
|
||||
- 532, // netnews
|
||||
- 540, // uucp
|
||||
- 548, // AFP (Apple Filing Protocol)
|
||||
- 556, // remotefs
|
||||
- 563, // nntp+ssl
|
||||
- 587, // smtp (rfc6409)
|
||||
- 601, // syslog-conn (rfc3195)
|
||||
- 636, // ldap+ssl
|
||||
- 993, // ldap+ssl
|
||||
- 995, // pop3+ssl
|
||||
- 2049, // nfs
|
||||
- 3659, // apple-sasl / PasswordServer
|
||||
- 4045, // lockd
|
||||
- 6000, // X11
|
||||
- 6665, // Alternate IRC [Apple addition]
|
||||
- 6666, // Alternate IRC [Apple addition]
|
||||
- 6667, // Standard IRC [Apple addition]
|
||||
- 6668, // Alternate IRC [Apple addition]
|
||||
- 6669, // Alternate IRC [Apple addition]
|
||||
- 6697, // IRC + TLS
|
||||
+ 1, // tcpmux
|
||||
+ 7, // echo
|
||||
+ 9, // discard
|
||||
+ 11, // systat
|
||||
+ 13, // daytime
|
||||
+ 15, // netstat
|
||||
+ 17, // qotd
|
||||
+ 19, // chargen
|
||||
+ 20, // ftp data
|
||||
+ 21, // ftp access
|
||||
+ 22, // ssh
|
||||
+ 23, // telnet
|
||||
+ 25, // smtp
|
||||
+ 37, // time
|
||||
+ 42, // name
|
||||
+ 43, // nicname
|
||||
+ 53, // domain
|
||||
+ 77, // priv-rjs
|
||||
+ 79, // finger
|
||||
+ 87, // ttylink
|
||||
+ 95, // supdup
|
||||
+ 101, // hostriame
|
||||
+ 102, // iso-tsap
|
||||
+ 103, // gppitnp
|
||||
+ 104, // acr-nema
|
||||
+ 109, // pop2
|
||||
+ 110, // pop3
|
||||
+ 111, // sunrpc
|
||||
+ 113, // auth
|
||||
+ 115, // sftp
|
||||
+ 117, // uucp-path
|
||||
+ 119, // nntp
|
||||
+ 123, // NTP
|
||||
+ 135, // loc-srv /epmap
|
||||
+ 139, // netbios
|
||||
+ 143, // imap2
|
||||
+ 179, // BGP
|
||||
+ 389, // ldap
|
||||
+ 427, // SLP (Also used by Apple Filing Protocol)
|
||||
+ 465, // smtp+ssl
|
||||
+ 512, // print / exec
|
||||
+ 513, // login
|
||||
+ 514, // shell
|
||||
+ 515, // printer
|
||||
+ 526, // tempo
|
||||
+ 530, // courier
|
||||
+ 531, // chat
|
||||
+ 532, // netnews
|
||||
+ 540, // uucp
|
||||
+ 548, // AFP (Apple Filing Protocol)
|
||||
+ 556, // remotefs
|
||||
+ 563, // nntp+ssl
|
||||
+ 587, // smtp (rfc6409)
|
||||
+ 601, // syslog-conn (rfc3195)
|
||||
+ 636, // ldap+ssl
|
||||
+ 993, // ldap+ssl
|
||||
+ 995, // pop3+ssl
|
||||
+ 2049, // nfs
|
||||
+ 3659, // apple-sasl / PasswordServer
|
||||
+ 4045, // lockd
|
||||
+ 5060, // sip
|
||||
+ 5061, // sips
|
||||
+ 6000, // X11
|
||||
+ 6665, // Alternate IRC [Apple addition]
|
||||
+ 6666, // Alternate IRC [Apple addition]
|
||||
+ 6667, // Standard IRC [Apple addition]
|
||||
+ 6668, // Alternate IRC [Apple addition]
|
||||
+ 6669, // Alternate IRC [Apple addition]
|
||||
+ 6697, // IRC + TLS
|
||||
};
|
||||
|
||||
// FTP overrides the following restricted port.
|
||||
132
patches/chromium/cherry-pick-d8d64b7cd244.patch
Normal file
132
patches/chromium/cherry-pick-d8d64b7cd244.patch
Normal file
@@ -0,0 +1,132 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xianzhu Wang <wangxianzhu@chromium.org>
|
||||
Date: Mon, 16 Nov 2020 17:26:33 +0000
|
||||
Subject: Ensure change type for OverflowControlsClip is returned
|
||||
|
||||
This at least ensures that we will update the paint properites for the
|
||||
composited overflow control layers in pre-CompositeAfterPaint to avoid
|
||||
stale properties on the layers.
|
||||
|
||||
The test doesn't actually reproduce the bug because any test simpler
|
||||
than the bug case couldn't reproduce the bug as the update would be
|
||||
triggered in other code paths (any style change, layout change, etc.).
|
||||
|
||||
Anyway this CL does fix the bug case.
|
||||
|
||||
TBR=wangxianzhu@chromium.org
|
||||
|
||||
(cherry picked from commit c20bb9897ef6d26a46391a4dc1658c5d33e0c100)
|
||||
|
||||
(cherry picked from commit cfb81e677a508871f56d8bec958d0b585298ae0c)
|
||||
|
||||
Bug: 1137603
|
||||
Change-Id: I5cca970bcf8cda6085527f79a97f269c4e3e9986
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2500264
|
||||
Reviewed-by: Stefan Zager <szager@chromium.org>
|
||||
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/master@{#820986}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2536910
|
||||
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4240@{#1446}
|
||||
Cr-Original-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2540592
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Jana Grill <janagrill@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240_112@{#26}
|
||||
Cr-Branched-From: 427c00d3874b6abcf4c4c2719768835fc3ef26d6-refs/branch-heads/4240@{#1291}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
|
||||
index e991dfac93cfa90f46b92e00c4f29318736bc7ba..b42f1d6bd9b04f293034ee97c8eaa7aa10390ac9 100644
|
||||
--- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
|
||||
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
|
||||
@@ -174,4 +174,56 @@ TEST_F(CompositingLayerPropertyUpdaterTest,
|
||||
}
|
||||
}
|
||||
|
||||
+TEST_F(CompositingLayerPropertyUpdaterTest, OverflowControlsClip) {
|
||||
+ SetBodyInnerHTML(R"HTML(
|
||||
+ <style>
|
||||
+ ::-webkit-scrollbar { width: 20px; }
|
||||
+ #container {
|
||||
+ width: 5px;
|
||||
+ height: 100px;
|
||||
+ }
|
||||
+ #target {
|
||||
+ overflow: scroll;
|
||||
+ will-change: transform;
|
||||
+ width: 100%;
|
||||
+ height: 100%;
|
||||
+ }
|
||||
+ </style>
|
||||
+ <div id="container">
|
||||
+ <div id="target"></div>
|
||||
+ </div>
|
||||
+ )HTML");
|
||||
+
|
||||
+ // Initially the vertical scrollbar overflows the narrow border box.
|
||||
+ auto* container = GetDocument().getElementById("container");
|
||||
+ auto* target = ToLayoutBox(GetLayoutObjectByElementId("target"));
|
||||
+ auto* scrollbar_layer =
|
||||
+ target->GetScrollableArea()->GraphicsLayerForVerticalScrollbar();
|
||||
+ auto target_state = target->FirstFragment().LocalBorderBoxProperties();
|
||||
+ auto scrollbar_state = target_state;
|
||||
+ auto* overflow_controls_clip =
|
||||
+ target->FirstFragment().PaintProperties()->OverflowControlsClip();
|
||||
+ ASSERT_TRUE(overflow_controls_clip);
|
||||
+ scrollbar_state.SetClip(*overflow_controls_clip);
|
||||
+ EXPECT_EQ(scrollbar_state, scrollbar_layer->GetPropertyTreeState());
|
||||
+
|
||||
+ // Widen target to make the vertical scrollbar contained by the border box.
|
||||
+ container->setAttribute(html_names::kStyleAttr, "width: 100px");
|
||||
+ UpdateAllLifecyclePhasesForTest();
|
||||
+ LOG(ERROR) << target->Size();
|
||||
+ EXPECT_FALSE(
|
||||
+ target->FirstFragment().PaintProperties()->OverflowControlsClip());
|
||||
+ EXPECT_EQ(target_state, scrollbar_layer->GetPropertyTreeState());
|
||||
+
|
||||
+ // Narrow down target back.
|
||||
+ container->removeAttribute(html_names::kStyleAttr);
|
||||
+ UpdateAllLifecyclePhasesForTest();
|
||||
+ scrollbar_state = target_state;
|
||||
+ overflow_controls_clip =
|
||||
+ target->FirstFragment().PaintProperties()->OverflowControlsClip();
|
||||
+ ASSERT_TRUE(overflow_controls_clip);
|
||||
+ scrollbar_state.SetClip(*overflow_controls_clip);
|
||||
+ EXPECT_EQ(scrollbar_state, scrollbar_layer->GetPropertyTreeState());
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
|
||||
index 0702a0fc65a69ab1da2cceeb4e6dcb9be30c8d3b..527024f5b1e9c71d7ad5311805c81c3587a7dc32 100644
|
||||
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
|
||||
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
|
||||
@@ -1554,21 +1554,21 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowControlsClip() {
|
||||
|
||||
if (NeedsOverflowControlsClip()) {
|
||||
// Clip overflow controls to the border box rect. Not wrapped with
|
||||
- // OnUpdateClip() because this clip doesn't affect descendants.
|
||||
+ // OnUpdateClip() because this clip doesn't affect descendants. Wrap with
|
||||
+ // OnUpdate() to let PrePaintTreeWalk see the change. This may cause
|
||||
+ // unnecessary subtree update, but is not a big deal because it is rare.
|
||||
const auto& clip_rect = PhysicalRect(context_.current.paint_offset,
|
||||
ToLayoutBox(object_).Size());
|
||||
- properties_->UpdateOverflowControlsClip(
|
||||
+ OnUpdate(properties_->UpdateOverflowControlsClip(
|
||||
*context_.current.clip,
|
||||
ClipPaintPropertyNode::State(context_.current.transform,
|
||||
FloatRoundedRect(FloatRect(clip_rect)),
|
||||
- ToSnappedClipRect(clip_rect)));
|
||||
+ ToSnappedClipRect(clip_rect))));
|
||||
} else {
|
||||
- properties_->ClearOverflowControlsClip();
|
||||
+ OnClear(properties_->ClearOverflowControlsClip());
|
||||
}
|
||||
|
||||
- // No need to set force_subtree_update_reasons and clip_changed because
|
||||
- // OverflowControlsClip applies to overflow controls only, not descendants.
|
||||
- // We also don't walk into custom scrollbars in PrePaintTreeWalk and
|
||||
+ // We don't walk into custom scrollbars in PrePaintTreeWalk because
|
||||
// LayoutObjects under custom scrollbars don't support paint properties.
|
||||
}
|
||||
|
||||
70
patches/chromium/cherry-pick-ecdec1fb0f42.patch
Normal file
70
patches/chromium/cherry-pick-ecdec1fb0f42.patch
Normal file
@@ -0,0 +1,70 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etienne Bergeron <etienneb@chromium.org>
|
||||
Date: Fri, 13 Nov 2020 17:40:59 +0000
|
||||
Subject: Fix text eliding for single-codepoint text with BiDi
|
||||
|
||||
This CL is fixing a corner case where RenderText::Elide(...) may
|
||||
produce a text with more codepoints than the original one. This is
|
||||
an issue since the breaklists are not resized and the overflow
|
||||
will lead the render_text code to perfoarm an out-of-bound memory
|
||||
access by deferencing breaks_.end() while rendering the text. This
|
||||
is causing chrome to crash.
|
||||
|
||||
See crbug/1142020 for details.
|
||||
|
||||
The bug was happening when:
|
||||
1) The text to elide was a single codepoint
|
||||
2) The width of the glyph of the codepoint is larger than the width
|
||||
of the ellipsis glyph
|
||||
3) Eliding is set to ELIDING_TAIL
|
||||
4) The display_rect width will trigger eliding
|
||||
(smaller than codepoint width, but larger than ellipsis width)
|
||||
5) The render text is set to RTL
|
||||
|
||||
A possible solution is to adjust the breaklist but this required
|
||||
larger refactoring and cannot be a minimal patch to be merge on
|
||||
other channels.
|
||||
|
||||
TBR=msw@chromium.org
|
||||
(cherry picked from commit e54920751871321474e0b953329c8aedcc8702c3)
|
||||
|
||||
Bug: 1142020
|
||||
Change-Id: I9854651175562ec5f0d0bf7083a8da99fede0e29
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2522892
|
||||
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
|
||||
Reviewed-by: Michael Wasserman <msw@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#824878}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537931
|
||||
Reviewed-by: Etienne Bergeron <etienneb@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1450}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
|
||||
index 383943809398a59380518f00d84275f493f008c3..2887ea638e3843e61ca2a2935f52d08fe2bbe45e 100644
|
||||
--- a/ui/gfx/render_text.cc
|
||||
+++ b/ui/gfx/render_text.cc
|
||||
@@ -2060,8 +2060,10 @@ base::string16 RenderText::Elide(const base::string16& text,
|
||||
}
|
||||
|
||||
// Append the ellipsis and the optional directional marker characters.
|
||||
+ // Do not append the BiDi marker if the only codepoint in the text is
|
||||
+ // an ellipsis.
|
||||
new_text.append(ellipsis);
|
||||
- if (trailing_text_direction != text_direction) {
|
||||
+ if (new_text.size() != 1 && trailing_text_direction != text_direction) {
|
||||
if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT)
|
||||
new_text += base::i18n::kLeftToRightMark;
|
||||
else
|
||||
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
|
||||
index 2fd63b1b75fc0fdec9772a9d6b74a13423bf7221..42827f318c8b1896c021f30895072e1add742d32 100644
|
||||
--- a/ui/gfx/render_text_unittest.cc
|
||||
+++ b/ui/gfx/render_text_unittest.cc
|
||||
@@ -1901,7 +1901,7 @@ const ElideTextCase kElideTailTextCases[] = {
|
||||
{"ltr_0", L"abc", L""},
|
||||
{"rtl_3", L"\u05d0\u05d1\u05d2", L"\u05d0\u05d1\u05d2"},
|
||||
{"rtl_2", L"\u05d0\u05d1\u05d2", L"\u05d0\u2026"},
|
||||
- {"rtl_1", L"\u05d0\u05d1\u05d2", L"\u2026\x200E"},
|
||||
+ {"rtl_1", L"\u05d0\u05d1\u05d2", L"\u2026"},
|
||||
{"rtl_0", L"\u05d0\u05d1\u05d2", L""},
|
||||
{"ltr_rtl_5", L"abc\u05d0\u05d1\u05d2", L"abc\u05d0\u2026\x200F"},
|
||||
{"ltr_rtl_4", L"abc\u05d0\u05d1\u05d2", L"abc\u2026"},
|
||||
77
patches/chromium/cherry-pick-eec5025668f8.patch
Normal file
77
patches/chromium/cherry-pick-eec5025668f8.patch
Normal file
@@ -0,0 +1,77 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bill Budge <bbudge@chromium.org>
|
||||
Date: Fri, 13 Nov 2020 09:02:09 +0000
|
||||
Subject: Merged: [wasm][code cache] Match response to cached raw resource
|
||||
|
||||
- Verifies that the retrieved resource has the same response time, and
|
||||
that the source matches (i.e. both are from service worker, or both
|
||||
are not).
|
||||
|
||||
Bug: chromium:1146673
|
||||
|
||||
(cherry picked from commit a8b46244ecaa1647ee2d70304878c0365ee04087)
|
||||
|
||||
Change-Id: I6243ec9017b2405687056aa6ea199c67b1c16063
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2526802
|
||||
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
|
||||
Reviewed-by: Andreas Haas <ahaas@chromium.org>
|
||||
Commit-Queue: Bill Budge <bbudge@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#826277}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537531
|
||||
Commit-Queue: Clemens Backes <clemensb@chromium.org>
|
||||
Commit-Queue: Andreas Haas <ahaas@chromium.org>
|
||||
Auto-Submit: Clemens Backes <clemensb@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1447}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
|
||||
index 1010b8be1364fc500b1bb20338e8959d683df5e8..0fffec5084a09cb1af18e619cbad7cc1dd73c447 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
|
||||
@@ -210,7 +210,8 @@ class ExceptionToAbortStreamingScope {
|
||||
};
|
||||
|
||||
RawResource* GetRawResource(ScriptState* script_state,
|
||||
- const String& url_string) {
|
||||
+ const String& url_string,
|
||||
+ Response* response) {
|
||||
ExecutionContext* execution_context = ExecutionContext::From(script_state);
|
||||
if (!execution_context)
|
||||
return nullptr;
|
||||
@@ -224,6 +225,18 @@ RawResource* GetRawResource(ScriptState* script_state,
|
||||
if (!resource)
|
||||
return nullptr;
|
||||
|
||||
+ // Make sure the resource matches the |response|. To check that, we make sure
|
||||
+ // the response times match, and the response sources match.
|
||||
+ const ResourceResponse& resource_response = resource->GetResponse();
|
||||
+ const FetchResponseData* fetch_response_data =
|
||||
+ response->GetResponse()->InternalResponse();
|
||||
+ if (resource_response.ResponseTime() != fetch_response_data->ResponseTime())
|
||||
+ return nullptr;
|
||||
+ bool from_service_worker = fetch_response_data->ResponseSource() ==
|
||||
+ network::mojom::FetchResponseSource::kUnspecified;
|
||||
+ if (resource_response.WasFetchedViaServiceWorker() != from_service_worker)
|
||||
+ return nullptr;
|
||||
+
|
||||
// Wasm modules should be fetched as raw resources.
|
||||
DCHECK_EQ(ResourceType::kRaw, resource->GetType());
|
||||
return ToRawResource(resource);
|
||||
@@ -347,13 +360,12 @@ void StreamFromResponseCallback(
|
||||
String url = response->url();
|
||||
const std::string& url_utf8 = url.Utf8();
|
||||
streaming->SetUrl(url_utf8.c_str(), url_utf8.size());
|
||||
- RawResource* raw_resource = GetRawResource(script_state, url);
|
||||
- if (raw_resource) {
|
||||
- SingleCachedMetadataHandler* cache_handler =
|
||||
- raw_resource->ScriptCacheHandler();
|
||||
+ RawResource* resource = GetRawResource(script_state, url, response);
|
||||
+ if (resource) {
|
||||
+ SingleCachedMetadataHandler* cache_handler = resource->ScriptCacheHandler();
|
||||
if (cache_handler) {
|
||||
auto client = std::make_shared<WasmStreamingClient>(
|
||||
- url, raw_resource->GetResponse().ResponseTime());
|
||||
+ url, resource->GetResponse().ResponseTime());
|
||||
streaming->SetClient(client);
|
||||
scoped_refptr<CachedMetadata> cached_module =
|
||||
cache_handler->GetCachedMetadata(kWasmModuleTag);
|
||||
155
patches/chromium/cherry-pick-f440137cd96a.patch
Normal file
155
patches/chromium/cherry-pick-f440137cd96a.patch
Normal file
@@ -0,0 +1,155 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Stephen Chenney <schenney@chromium.org>
|
||||
Date: Wed, 14 Oct 2020 02:52:47 +0000
|
||||
Subject: Implement WebGL image-orientation
|
||||
|
||||
M-86 merge.
|
||||
|
||||
When creating textures for WebGL, always orient images
|
||||
with EXIF orientation data.
|
||||
|
||||
This change also corrects the transposed size reported by
|
||||
ImageBitmap. And it removes superfluous arguments from
|
||||
CopyImageData.
|
||||
|
||||
(cherry picked from commit f373458c504c2d115c42f31b29ff5c19674acbbc)
|
||||
|
||||
Bug: 1100470, 1125337
|
||||
Change-Id: I79aa798327a3582939aa574723926b3325c80e7c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2459400
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Commit-Queue: Stephen Chenney <schenney@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#815359}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2469776
|
||||
Reviewed-by: Stephen Chenney <schenney@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1237}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
|
||||
index b1cdb23186256ca2b4082d2acf556d98c910f145..3e2b5373fdba7bcd0abe866644e17fcb3cee167e 100644
|
||||
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
|
||||
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
|
||||
@@ -189,14 +189,16 @@ SkImageInfo GetSkImageInfo(const scoped_refptr<Image>& input) {
|
||||
|
||||
// This function results in a readback due to using SkImage::readPixels().
|
||||
// Returns transparent black pixels if the input SkImageInfo.bounds() does
|
||||
-// not intersect with the input image boundaries.
|
||||
+// not intersect with the input image boundaries. When apply_orientation
|
||||
+// is true this method will orient the data according to the source's EXIF
|
||||
+// information.
|
||||
Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input,
|
||||
const SkImageInfo& info,
|
||||
- const unsigned x = 0,
|
||||
- const unsigned y = 0) {
|
||||
+ bool apply_orientation = true) {
|
||||
if (info.isEmpty())
|
||||
return {};
|
||||
- sk_sp<SkImage> sk_image = input->PaintImageForCurrentFrame().GetSkImage();
|
||||
+ PaintImage paint_image = input->PaintImageForCurrentFrame();
|
||||
+ sk_sp<SkImage> sk_image = paint_image.GetSkImage();
|
||||
if (sk_image->bounds().isEmpty())
|
||||
return {};
|
||||
|
||||
@@ -205,16 +207,30 @@ Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input,
|
||||
Vector<uint8_t> dst_buffer(byte_length);
|
||||
|
||||
bool read_pixels_successful =
|
||||
- sk_image->readPixels(info, dst_buffer.data(), info.minRowBytes(), x, y);
|
||||
+ sk_image->readPixels(info, dst_buffer.data(), info.minRowBytes(), 0, 0);
|
||||
DCHECK(read_pixels_successful);
|
||||
if (!read_pixels_successful)
|
||||
return {};
|
||||
+
|
||||
+ // Orient the data, and re-read the pixels.
|
||||
+ if (apply_orientation && !input->HasDefaultOrientation()) {
|
||||
+ paint_image = Image::ResizeAndOrientImage(
|
||||
+ paint_image, input->CurrentFrameOrientation(), FloatSize(1, 1), 1,
|
||||
+ kInterpolationNone);
|
||||
+ sk_image = paint_image.GetSkImage();
|
||||
+ read_pixels_successful = sk_image->readPixels(info, dst_buffer.data(),
|
||||
+ info.minRowBytes(), 0, 0);
|
||||
+ DCHECK(read_pixels_successful);
|
||||
+ if (!read_pixels_successful)
|
||||
+ return {};
|
||||
+ }
|
||||
+
|
||||
return dst_buffer;
|
||||
}
|
||||
|
||||
Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input) {
|
||||
SkImageInfo info = GetSkImageInfo(input);
|
||||
- return CopyImageData(std::move(input), info);
|
||||
+ return CopyImageData(std::move(input), info, false);
|
||||
}
|
||||
|
||||
static inline bool ShouldAvoidPremul(
|
||||
@@ -1053,12 +1069,13 @@ Vector<uint8_t> ImageBitmap::CopyBitmapData(AlphaDisposition alpha_op,
|
||||
auto color_type = info.colorType();
|
||||
if (color_type == kN32_SkColorType && u8_color_type == kRGBAColorType)
|
||||
color_type = kRGBA_8888_SkColorType;
|
||||
+ // Note that width() and height() here apply EXIF orientation
|
||||
info =
|
||||
SkImageInfo::Make(width(), height(), color_type,
|
||||
(alpha_op == kPremultiplyAlpha) ? kPremul_SkAlphaType
|
||||
: kUnpremul_SkAlphaType,
|
||||
info.refColorSpace());
|
||||
- return CopyImageData(image_, info);
|
||||
+ return CopyImageData(image_, info, true);
|
||||
}
|
||||
|
||||
Vector<uint8_t> ImageBitmap::CopyBitmapData() {
|
||||
@@ -1090,7 +1107,7 @@ IntSize ImageBitmap::Size() const {
|
||||
return IntSize();
|
||||
DCHECK_GT(image_->width(), 0);
|
||||
DCHECK_GT(image_->height(), 0);
|
||||
- return IntSize(image_->width(), image_->height());
|
||||
+ return image_->SizeRespectingOrientation();
|
||||
}
|
||||
|
||||
ScriptPromise ImageBitmap::CreateImageBitmap(ScriptState* script_state,
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
index 457b7c3d2bef75bb378f8dfc5b61b932b6941fb6..d7445bf31a391bea3742327c34dc3eb46c72513b 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
@@ -5307,10 +5307,12 @@ void WebGLRenderingContextBase::TexImageHelperHTMLImageElement(
|
||||
return;
|
||||
|
||||
scoped_refptr<Image> image_for_render = image->CachedImage()->GetImage();
|
||||
- if (IsA<SVGImage>(image_for_render.get())) {
|
||||
- if (canvas()) {
|
||||
+ bool have_svg_image = IsA<SVGImage>(image_for_render.get());
|
||||
+ if (have_svg_image || !image_for_render->HasDefaultOrientation()) {
|
||||
+ if (have_svg_image && canvas()) {
|
||||
UseCounter::Count(canvas()->GetDocument(), WebFeature::kSVGInWebGL);
|
||||
}
|
||||
+ // DrawImageIntoBuffer always respects orientation
|
||||
image_for_render =
|
||||
DrawImageIntoBuffer(std::move(image_for_render), image->width(),
|
||||
image->height(), func_name);
|
||||
@@ -5846,6 +5848,7 @@ void WebGLRenderingContextBase::TexImageHelperImageBitmap(
|
||||
level, internalformat, width, height, depth, 0, format,
|
||||
type, xoffset, yoffset, zoffset))
|
||||
return;
|
||||
+
|
||||
scoped_refptr<StaticBitmapImage> image = bitmap->BitmapImage();
|
||||
DCHECK(image);
|
||||
|
||||
@@ -5872,9 +5875,16 @@ void WebGLRenderingContextBase::TexImageHelperImageBitmap(
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Apply orientation if necessary
|
||||
+ PaintImage paint_image = bitmap->BitmapImage()->PaintImageForCurrentFrame();
|
||||
+ if (!image->HasDefaultOrientation()) {
|
||||
+ paint_image = Image::ResizeAndOrientImage(
|
||||
+ paint_image, image->CurrentFrameOrientation(), FloatSize(1, 1), 1,
|
||||
+ kInterpolationNone);
|
||||
+ }
|
||||
+
|
||||
// TODO(kbr): refactor this away to use TexImageImpl on image.
|
||||
- sk_sp<SkImage> sk_image =
|
||||
- bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
|
||||
+ sk_sp<SkImage> sk_image = paint_image.GetSkImage();
|
||||
if (!sk_image) {
|
||||
SynthesizeGLError(GL_OUT_OF_MEMORY, func_name,
|
||||
"ImageBitmap unexpectedly empty");
|
||||
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 5 Oct 2020 13:43:59 -0700
|
||||
Subject: chore: expose v8 initialization isolate callbacks
|
||||
|
||||
This commit is necessary in order to ensure consistent behavior from
|
||||
v8 Isolate callbacks in contexts which Node.js does not control. If
|
||||
we're running with contextIsolation enabled, we should be falling back
|
||||
to Blink's logic. This will be upstreamed in some form.
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
index 21504ce01403d20067c8439c0c61ee0d71de84a5..13855078e4e9531304d30ec46cd2bb79798623ad 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
@@ -452,7 +452,7 @@ CodeGenerationCheckCallbackInMainThread(v8::Local<v8::Context> context,
|
||||
return {true, std::move(stringified_source)};
|
||||
}
|
||||
|
||||
-static bool WasmCodeGenerationCheckCallbackInMainThread(
|
||||
+bool V8Initializer::WasmCodeGenerationCheckCallbackInMainThread(
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Local<v8::String> source) {
|
||||
if (ExecutionContext* execution_context = ToExecutionContext(context)) {
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.h b/third_party/blink/renderer/bindings/core/v8/v8_initializer.h
|
||||
index e7cbc5db7d15aa0fcfb37ba261673b973827296a..6b93aa449a005e06862a99ea0c9b751ffff2d6ec 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.h
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.h
|
||||
@@ -67,6 +67,9 @@ class CORE_EXPORT V8Initializer {
|
||||
v8::Local<v8::Value>);
|
||||
static void MessageHandlerInWorker(v8::Local<v8::Message>,
|
||||
v8::Local<v8::Value>);
|
||||
+ static bool WasmCodeGenerationCheckCallbackInMainThread(
|
||||
+ v8::Local<v8::Context> context,
|
||||
+ v8::Local<v8::String> source);
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
146
patches/chromium/crashpad-initialize-logging.patch
Normal file
146
patches/chromium/crashpad-initialize-logging.patch
Normal file
@@ -0,0 +1,146 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joshua Peraza <jperaza@chromium.org>
|
||||
Date: Wed, 21 Oct 2020 11:10:25 -0700
|
||||
Subject: Initialize logging for crashpad
|
||||
|
||||
Although logging to files is not yet supported by mini_chromium, it is
|
||||
the default behavior for OS_WIN in chromium. This change should
|
||||
cause crashpad to log via OutputDebugString() on Windows, instead of
|
||||
debug.log files. Future work (crbug.com/crashpad/26) should arrange for
|
||||
logs to be uploaded with reports, embedded in associated minidumps or as
|
||||
file attachments.
|
||||
|
||||
Bug: chromium:711159
|
||||
Change-Id: I0f9004f7de94dd29d555cc7d23c48a63da6b4bba
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2425108
|
||||
Reviewed-by: Mark Mentovai <mark@chromium.org>
|
||||
|
||||
diff --git a/base/logging.cc b/base/logging.cc
|
||||
index 2da71c73819b34a45911131e2cc8bff861178789..6b701b7a8dee0d015758e11771c5c1f3a6b8d13b 100644
|
||||
--- a/base/logging.cc
|
||||
+++ b/base/logging.cc
|
||||
@@ -421,21 +421,23 @@ bool BaseInitLoggingImpl(const LoggingSettings& settings) {
|
||||
0u);
|
||||
#endif
|
||||
|
||||
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
- // Don't bother initializing |g_vlog_info| unless we use one of the
|
||||
- // vlog switches.
|
||||
- if (command_line->HasSwitch(switches::kV) ||
|
||||
- command_line->HasSwitch(switches::kVModule)) {
|
||||
- // NOTE: If |g_vlog_info| has already been initialized, it might be in use
|
||||
- // by another thread. Don't delete the old VLogInfo, just create a second
|
||||
- // one. We keep track of both to avoid memory leak warnings.
|
||||
- CHECK(!g_vlog_info_prev);
|
||||
- g_vlog_info_prev = g_vlog_info;
|
||||
-
|
||||
- g_vlog_info =
|
||||
- new VlogInfo(command_line->GetSwitchValueASCII(switches::kV),
|
||||
- command_line->GetSwitchValueASCII(switches::kVModule),
|
||||
- &g_min_log_level);
|
||||
+ if (base::CommandLine::InitializedForCurrentProcess()) {
|
||||
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
+ // Don't bother initializing |g_vlog_info| unless we use one of the
|
||||
+ // vlog switches.
|
||||
+ if (command_line->HasSwitch(switches::kV) ||
|
||||
+ command_line->HasSwitch(switches::kVModule)) {
|
||||
+ // NOTE: If |g_vlog_info| has already been initialized, it might be in use
|
||||
+ // by another thread. Don't delete the old VLogInfo, just create a second
|
||||
+ // one. We keep track of both to avoid memory leak warnings.
|
||||
+ CHECK(!g_vlog_info_prev);
|
||||
+ g_vlog_info_prev = g_vlog_info;
|
||||
+
|
||||
+ g_vlog_info =
|
||||
+ new VlogInfo(command_line->GetSwitchValueASCII(switches::kV),
|
||||
+ command_line->GetSwitchValueASCII(switches::kVModule),
|
||||
+ &g_min_log_level);
|
||||
+ }
|
||||
}
|
||||
|
||||
g_logging_destination = settings.logging_dest;
|
||||
@@ -446,7 +448,10 @@ bool BaseInitLoggingImpl(const LoggingSettings& settings) {
|
||||
config.min_severity = FX_LOG_INFO;
|
||||
config.console_fd = -1;
|
||||
config.log_service_channel = ZX_HANDLE_INVALID;
|
||||
- std::string log_tag = command_line->GetProgram().BaseName().AsUTF8Unsafe();
|
||||
+ std::string log_tag = base::CommandLine::ForCurrentProcess()
|
||||
+ ->GetProgram()
|
||||
+ .BaseName()
|
||||
+ .AsUTF8Unsafe();
|
||||
const char* log_tag_data = log_tag.data();
|
||||
config.tags = &log_tag_data;
|
||||
config.num_tags = 1;
|
||||
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS
|
||||
index ccb447cde9a9ee3c1fe29419abfa8aa63d777455..6ee9db5400cf12ae4812a261e78234581b036c25 100644
|
||||
--- a/third_party/crashpad/crashpad/DEPS
|
||||
+++ b/third_party/crashpad/crashpad/DEPS
|
||||
@@ -42,7 +42,7 @@ deps = {
|
||||
'7bde79cc274d06451bf65ae82c012a5d3e476b5a',
|
||||
'crashpad/third_party/mini_chromium/mini_chromium':
|
||||
Var('chromium_git') + '/chromium/mini_chromium@' +
|
||||
- 'ae14a14ab4cea36db9c446741581d427a7fc7f89',
|
||||
+ '5fc64bfbf1c000161445c586de45e40464ff2314',
|
||||
'crashpad/third_party/libfuzzer/src':
|
||||
Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' +
|
||||
'fda403cf93ecb8792cb1d061564d89a6553ca020',
|
||||
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc
|
||||
index d56857ff9042a0e4ed55bb101e419948f4028305..579a7c364077d2b6a78803fa75f7180109b37c89 100644
|
||||
--- a/third_party/crashpad/crashpad/handler/handler_main.cc
|
||||
+++ b/third_party/crashpad/crashpad/handler/handler_main.cc
|
||||
@@ -494,16 +494,26 @@ class ScopedStoppable {
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedStoppable);
|
||||
};
|
||||
|
||||
+void InitCrashpadLogging() {
|
||||
+ logging::LoggingSettings settings;
|
||||
+#if defined(OS_CHROMEOS)
|
||||
+ settings.logging_dest = logging::LOG_TO_FILE;
|
||||
+ settings.log_file_path = "/var/log/chrome/chrome";
|
||||
+#elif defined(OS_WIN)
|
||||
+ settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
+#else
|
||||
+ settings.logging_dest =
|
||||
+ logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR;
|
||||
+#endif
|
||||
+ logging::InitLogging(settings);
|
||||
+}
|
||||
+
|
||||
} // namespace
|
||||
|
||||
int HandlerMain(int argc,
|
||||
char* argv[],
|
||||
const UserStreamDataSources* user_stream_sources) {
|
||||
-#if defined(OS_CHROMEOS)
|
||||
- if (freopen("/var/log/chrome/chrome", "a", stderr) == nullptr) {
|
||||
- PLOG(ERROR) << "Failed to redirect stderr to /var/log/chrome/chrome";
|
||||
- }
|
||||
-#endif
|
||||
+ InitCrashpadLogging();
|
||||
|
||||
InstallCrashHandler();
|
||||
CallMetricsRecordNormalExit metrics_record_normal_exit;
|
||||
diff --git a/third_party/crashpad/crashpad/test/gtest_main.cc b/third_party/crashpad/crashpad/test/gtest_main.cc
|
||||
index 67cfa0d72d7eb469775201f3a9df906f27c302a9..c67b8e24bb940935d5da88428ed3058a135f5a57 100644
|
||||
--- a/third_party/crashpad/crashpad/test/gtest_main.cc
|
||||
+++ b/third_party/crashpad/crashpad/test/gtest_main.cc
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
+#include "base/logging.h"
|
||||
#include "build/build_config.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/main_arguments.h"
|
||||
@@ -99,6 +100,12 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
#endif // CRASHPAD_IS_IN_CHROMIUM
|
||||
|
||||
+ // base::TestSuite initializes logging when using Chromium's test launcher.
|
||||
+ logging::LoggingSettings settings;
|
||||
+ settings.logging_dest =
|
||||
+ logging::LOG_TO_STDERR | logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
+ logging::InitLogging(settings);
|
||||
+
|
||||
#if defined(CRASHPAD_TEST_LAUNCHER_GOOGLEMOCK)
|
||||
testing::InitGoogleMock(&argc, argv);
|
||||
#elif defined(CRASHPAD_TEST_LAUNCHER_GOOGLETEST)
|
||||
28
patches/chromium/fix_setparentacessibile_crash_win.patch
Normal file
28
patches/chromium/fix_setparentacessibile_crash_win.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Biru Mohanathas <birunthan@mohanathas.com>
|
||||
Date: Thu, 10 Dec 2020 19:02:37 +0200
|
||||
Subject: fix crash in NativeViewHost::SetParentAccessible
|
||||
|
||||
This fixes random crashes on Windows 10. It presumably started happening
|
||||
after the changes in
|
||||
https://chromium.googlesource.com/chromium/src.git/+/5c6c8e994bce2bfb867279ae5068e9f9134e70c3%5E!/#F15
|
||||
|
||||
For context, see: https://github.com/electron/electron/issues/26905
|
||||
|
||||
This patch can likely be upstreamed. The crash cannot be fixed without
|
||||
patching something in Chromium - this is the least invasive change.
|
||||
|
||||
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc
|
||||
index 4779e4f07d923b5af9ba05c2765cf294e75dcc14..6112217d532251f7f6850c23be5c312a908df1e2 100644
|
||||
--- a/ui/views/controls/native/native_view_host.cc
|
||||
+++ b/ui/views/controls/native/native_view_host.cc
|
||||
@@ -54,6 +54,9 @@ void NativeViewHost::Detach() {
|
||||
}
|
||||
|
||||
void NativeViewHost::SetParentAccessible(gfx::NativeViewAccessible accessible) {
|
||||
+ if (!native_wrapper_.get())
|
||||
+ return;
|
||||
+
|
||||
native_wrapper_->SetParentAccessible(accessible);
|
||||
}
|
||||
|
||||
52
patches/chromium/fix_use_electron_generated_resources.patch
Normal file
52
patches/chromium/fix_use_electron_generated_resources.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Thu, 24 Sep 2020 11:10:41 -0700
|
||||
Subject: fix: use electron generated resources
|
||||
|
||||
This patch fixes a few instances where we need to use Electron generated
|
||||
resources for IDS strings, or the IDs will be wrong and cause DCHECKS
|
||||
as they will loaded as empty strings.
|
||||
|
||||
* IDS_UTILITY_PROCESS_UTILITY_WIN_NAME on Windows
|
||||
* IDR_PDF_MANIFEST on Linux
|
||||
* IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME on Windows
|
||||
|
||||
diff --git a/chrome/browser/pdf/pdf_extension_util.cc b/chrome/browser/pdf/pdf_extension_util.cc
|
||||
index 9fd9791fd923d6c5e741cb7dc064ababf9a7995a..0a5534f2f09224196971076794daa3c805c91606 100644
|
||||
--- a/chrome/browser/pdf/pdf_extension_util.cc
|
||||
+++ b/chrome/browser/pdf/pdf_extension_util.cc
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "base/values.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/common/chrome_content_client.h"
|
||||
-#include "chrome/grit/browser_resources.h"
|
||||
+#include "electron/grit/electron_resources.h"
|
||||
#include "components/strings/grit/components_strings.h"
|
||||
#include "components/zoom/page_zoom_constants.h"
|
||||
#include "pdf/pdf_features.h"
|
||||
diff --git a/chrome/browser/printing/printing_service.cc b/chrome/browser/printing/printing_service.cc
|
||||
index 2b73b110049b5e8d28b52656bbd2423e18ba07a0..8fd868b39d64c74aa189b8ca3e24c8537d91b1ba 100644
|
||||
--- a/chrome/browser/printing/printing_service.cc
|
||||
+++ b/chrome/browser/printing/printing_service.cc
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "base/no_destructor.h"
|
||||
#include "chrome/browser/service_sandbox_type.h"
|
||||
-#include "chrome/grit/generated_resources.h"
|
||||
+#include "electron/grit/electron_resources.h"
|
||||
#include "content/public/browser/service_process_host.h"
|
||||
|
||||
const mojo::Remote<printing::mojom::PrintingService>& GetPrintingService() {
|
||||
diff --git a/chrome/browser/win/icon_reader_service.cc b/chrome/browser/win/icon_reader_service.cc
|
||||
index 721e1a863cc6925908f8343002df056f2373bf0b..10b2a95162541a8ff4d010c7be864f3f41dae378 100644
|
||||
--- a/chrome/browser/win/icon_reader_service.cc
|
||||
+++ b/chrome/browser/win/icon_reader_service.cc
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "chrome/browser/win/icon_reader_service.h"
|
||||
|
||||
#include "chrome/browser/service_sandbox_type.h"
|
||||
-#include "chrome/grit/generated_resources.h"
|
||||
+#include "electron/grit/electron_resources.h"
|
||||
#include "content/public/browser/service_process_host.h"
|
||||
|
||||
mojo::Remote<chrome::mojom::UtilReadIcon> LaunchIconReaderInstance() {
|
||||
@@ -0,0 +1,163 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Cheng <dcheng@chromium.org>
|
||||
Date: Wed, 11 Nov 2020 00:54:41 +0000
|
||||
Subject: Ignore RenderFrameHostImpl::Detach() for speculative RFHs.
|
||||
|
||||
Currently, this all happens to work by chance, because the speculative
|
||||
RFH or the entire FTN happens to be torn down before the browser process
|
||||
ever processes a Detach() IPC for a speculative RFH.
|
||||
|
||||
However, there are a number of followup CLs that restructure how
|
||||
provisional RenderFrames are managed and owned in the renderer process.
|
||||
To simplify those CLs, explicitly branch in Detach() based on whether or
|
||||
not the RFH is speculative. In the future, additional logic may be added
|
||||
to the speculative branch (e.g. cancelling the navigation, if
|
||||
appropriate).
|
||||
|
||||
(cherry picked from commit cf054220a2e1570a9149220494de8826c2e9d4db)
|
||||
|
||||
Bug: 1146709
|
||||
Change-Id: I6490a90f7b447422d698676665b52f6f3a6f8ffd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2524280
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Nasko Oskov <nasko@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#825903}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2530189
|
||||
Reviewed-by: Adrian Taylor <adetaylor@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1430}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
|
||||
index c1d7a3052516c6c8ac5a8e65c9688d04b8edec70..ab54a32a17f29e9b5ea9365e92de563737a1e513 100644
|
||||
--- a/content/browser/frame_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/frame_host/render_frame_host_impl.cc
|
||||
@@ -2625,6 +2625,9 @@ void RenderFrameHostImpl::UpdateRenderProcessHostFramePriorities() {
|
||||
}
|
||||
|
||||
void RenderFrameHostImpl::OnDetach() {
|
||||
+ if (lifecycle_state() == LifecycleState::kSpeculative)
|
||||
+ return;
|
||||
+
|
||||
if (!parent_) {
|
||||
bad_message::ReceivedBadMessage(GetProcess(),
|
||||
bad_message::RFH_DETACH_MAIN_FRAME);
|
||||
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
|
||||
index 7c9902648ab0465f4e0a7b4778b328ad8c1f2fcd..d81076da5ef7701475ef1158b528d02d3992ff0d 100644
|
||||
--- a/content/browser/site_per_process_browsertest.cc
|
||||
+++ b/content/browser/site_per_process_browsertest.cc
|
||||
@@ -10333,6 +10333,37 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
|
||||
EXPECT_EQ("opener-ping-reply", response);
|
||||
}
|
||||
|
||||
+IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
|
||||
+ DetachSpeculativeRenderFrameHost) {
|
||||
+ // Commit a page with one iframe.
|
||||
+ GURL main_url(embedded_test_server()->GetURL(
|
||||
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
|
||||
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
|
||||
+
|
||||
+ // Start a cross-site navigation.
|
||||
+ GURL cross_site_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
|
||||
+ TestNavigationManager nav_manager(shell()->web_contents(), cross_site_url);
|
||||
+ BeginNavigateIframeToURL(web_contents(), "child-0", cross_site_url);
|
||||
+
|
||||
+ // Wait for the request, but don't commit it yet. This should create a
|
||||
+ // speculative RenderFrameHost.
|
||||
+ ASSERT_TRUE(nav_manager.WaitForRequestStart());
|
||||
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
|
||||
+ RenderFrameHostImpl* speculative_rfh = root->current_frame_host()
|
||||
+ ->child_at(0)
|
||||
+ ->render_manager()
|
||||
+ ->speculative_frame_host();
|
||||
+ EXPECT_TRUE(speculative_rfh);
|
||||
+
|
||||
+ // Currently, the browser process never handles an explicit Detach() for a
|
||||
+ // speculative RFH, since the speculative RFH or the entire FTN is always
|
||||
+ // destroyed before the renderer sends this IPC.
|
||||
+ speculative_rfh->Detach();
|
||||
+
|
||||
+ // Passes if there is no crash.
|
||||
+}
|
||||
+
|
||||
+
|
||||
#if defined(OS_ANDROID)
|
||||
|
||||
namespace {
|
||||
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
|
||||
index cbc62fef825815309f417baee931a6c450500f32..d3fa4eb639f58c6eafe01651e643545897dcabcc 100644
|
||||
--- a/content/public/test/browser_test_utils.cc
|
||||
+++ b/content/public/test/browser_test_utils.cc
|
||||
@@ -603,15 +603,21 @@ bool NavigateToURL(WebContents* web_contents,
|
||||
bool NavigateIframeToURL(WebContents* web_contents,
|
||||
const std::string& iframe_id,
|
||||
const GURL& url) {
|
||||
+ TestNavigationObserver load_observer(web_contents);
|
||||
+ bool result = BeginNavigateIframeToURL(web_contents, iframe_id, url);
|
||||
+ load_observer.Wait();
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+bool BeginNavigateIframeToURL(WebContents* web_contents,
|
||||
+ const std::string& iframe_id,
|
||||
+ const GURL& url) {
|
||||
std::string script = base::StringPrintf(
|
||||
"setTimeout(\""
|
||||
"var iframes = document.getElementById('%s');iframes.src='%s';"
|
||||
"\",0)",
|
||||
iframe_id.c_str(), url.spec().c_str());
|
||||
- TestNavigationObserver load_observer(web_contents);
|
||||
- bool result = ExecuteScript(web_contents, script);
|
||||
- load_observer.Wait();
|
||||
- return result;
|
||||
+ return ExecuteScript(web_contents, script);
|
||||
}
|
||||
|
||||
void NavigateToURLBlockUntilNavigationsComplete(WebContents* web_contents,
|
||||
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
|
||||
index 275684ba6cf6b6a9f8e5f5b24951d8fb07969767..bc23592ce9b7eab268465fb0e171e8351aa25549 100644
|
||||
--- a/content/public/test/browser_test_utils.h
|
||||
+++ b/content/public/test/browser_test_utils.h
|
||||
@@ -138,6 +138,12 @@ bool NavigateIframeToURL(WebContents* web_contents,
|
||||
const std::string& iframe_id,
|
||||
const GURL& url);
|
||||
|
||||
+// Similar to |NavigateIframeToURL()| but returns as soon as the navigation is
|
||||
+// initiated.
|
||||
+bool BeginNavigateIframeToURL(WebContents* web_contents,
|
||||
+ const std::string& iframe_id,
|
||||
+ const GURL& url);
|
||||
+
|
||||
// Generate a URL for a file path including a query string.
|
||||
GURL GetFileUrlWithQuery(const base::FilePath& path,
|
||||
const std::string& query_string);
|
||||
diff --git a/content/test/data/cross_site_iframe_factory.html b/content/test/data/cross_site_iframe_factory.html
|
||||
index 0893a2063585a04520d9bc8f87ee0c1cb726c0d7..78f8126c9cf7f8ae9f2b0d34e17d76ad51784811 100644
|
||||
--- a/content/test/data/cross_site_iframe_factory.html
|
||||
+++ b/content/test/data/cross_site_iframe_factory.html
|
||||
@@ -10,12 +10,12 @@ Example usage in a browsertest, explained:
|
||||
When you navigate to the above URL, the outer document (on a.com) will create a
|
||||
single iframe:
|
||||
|
||||
- <iframe src="http://b.com:1234/cross_site_iframe_factory.html?b(c(),d())">
|
||||
+ <iframe id="child-0" src="http://b.com:1234/cross_site_iframe_factory.html?b(c(),d())">
|
||||
|
||||
Inside of which, then, are created the two leaf iframes:
|
||||
|
||||
- <iframe src="http://c.com:1234/cross_site_iframe_factory.html?c()">
|
||||
- <iframe src="http://d.com:1234/cross_site_iframe_factory.html?d()">
|
||||
+ <iframe id="child-0" src="http://c.com:1234/cross_site_iframe_factory.html?c()">
|
||||
+ <iframe id="child-1" src="http://d.com:1234/cross_site_iframe_factory.html?d()">
|
||||
|
||||
Add iframe options by enclosing them in '{' and '}' characters after the
|
||||
hostname (multiple options can be separated with commas):
|
||||
@@ -24,8 +24,8 @@ hostname (multiple options can be separated with commas):
|
||||
|
||||
Will create two iframes:
|
||||
|
||||
- <iframe src="http://a.com:1234/cross_site_iframe_factory.html?b()" allowfullscreen>
|
||||
- <iframe src="http://c.com:1234/cross_site_iframe_factory.html?c{sandbox-allow-scripts}(d())" sandbox="allow-scripts">
|
||||
+ <iframe id="child-0" src="http://a.com:1234/cross_site_iframe_factory.html?b()" allowfullscreen>
|
||||
+ <iframe id="child-1" src="http://c.com:1234/cross_site_iframe_factory.html?c{sandbox-allow-scripts}(d())" sandbox="allow-scripts">
|
||||
|
||||
To specify the site for each iframe, you can use a simple identifier like "a"
|
||||
or "b", and ".com" will be automatically appended. You can also specify a port
|
||||
@@ -0,0 +1,179 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Fri, 13 Nov 2020 21:06:58 +0000
|
||||
Subject: Merge M86: "Ensure that buffers used by ImageDecoder haven't been
|
||||
neutered."
|
||||
|
||||
Since JavaScript may detach the underlying buffers, we need to check
|
||||
to ensure they're still valid before using them for decoding.
|
||||
|
||||
TBR=sandersd
|
||||
|
||||
(cherry picked from commit fa93fba6a28d384b0a0cddd63e85eb10cb97bb53)
|
||||
|
||||
Test: Updated unittests. Manual test case breaks.
|
||||
Change-Id: Iefe5f8adf619cd6afdfedcb08a13c2996bfe0d32
|
||||
Fixed: 1146761
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2527542
|
||||
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Reviewed-by: Dan Sanders <sandersd@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#825615}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537781
|
||||
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1453}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
|
||||
index e42ceaf37038b58e53d11bfb63b7a27aa414a87b..780fdbef3afb9cca322002f736fc3d9b87f834b3 100644
|
||||
--- a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
|
||||
@@ -99,9 +99,8 @@ ImageDecoderExternal::ImageDecoderExternal(ScriptState* script_state,
|
||||
return;
|
||||
}
|
||||
|
||||
- // TODO: Data is owned by the caller who may be free to manipulate it. We will
|
||||
- // probably need to make a copy to our own internal data or neuter the buffers
|
||||
- // as seen by JS.
|
||||
+ // Since data is owned by the caller who may be free to manipulate it, we must
|
||||
+ // check HasValidEncodedData() before attempting to access |decoder_|.
|
||||
segment_reader_ = SegmentReader::CreateFromSkData(
|
||||
SkData::MakeWithoutCopy(buffer.Data(), buffer.ByteLengthAsSizeT()));
|
||||
if (!segment_reader_) {
|
||||
@@ -206,6 +205,7 @@ void ImageDecoderExternal::Trace(Visitor* visitor) const {
|
||||
|
||||
void ImageDecoderExternal::CreateImageDecoder() {
|
||||
DCHECK(!decoder_);
|
||||
+ DCHECK(HasValidEncodedData());
|
||||
|
||||
// TODO: We should probably call ImageDecoder::SetMemoryAllocator() so that
|
||||
// we can recycle frame buffers for decoded images.
|
||||
@@ -260,6 +260,13 @@ void ImageDecoderExternal::MaybeSatisfyPendingDecodes() {
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (!HasValidEncodedData()) {
|
||||
+ request->resolver->Reject(MakeGarbageCollected<DOMException>(
|
||||
+ DOMExceptionCode::kInvalidStateError,
|
||||
+ "Source data has been neutered"));
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
auto* image = decoder_->DecodeFrameBufferAtIndex(request->frame_index);
|
||||
if (decoder_->Failed() || !image) {
|
||||
request->complete = true;
|
||||
@@ -326,6 +333,7 @@ void ImageDecoderExternal::MaybeSatisfyPendingDecodes() {
|
||||
}
|
||||
|
||||
void ImageDecoderExternal::MaybeSatisfyPendingMetadataDecodes() {
|
||||
+ DCHECK(HasValidEncodedData());
|
||||
DCHECK(decoder_);
|
||||
DCHECK(decoder_->Failed() || decoder_->IsDecodedSizeAvailable());
|
||||
for (auto& resolver : pending_metadata_decodes_)
|
||||
@@ -334,6 +342,9 @@ void ImageDecoderExternal::MaybeSatisfyPendingMetadataDecodes() {
|
||||
}
|
||||
|
||||
void ImageDecoderExternal::MaybeUpdateMetadata() {
|
||||
+ if (!HasValidEncodedData())
|
||||
+ return;
|
||||
+
|
||||
const size_t decoded_frame_count = decoder_->FrameCount();
|
||||
if (decoder_->Failed()) {
|
||||
MaybeSatisfyPendingMetadataDecodes();
|
||||
@@ -358,4 +369,22 @@ void ImageDecoderExternal::MaybeUpdateMetadata() {
|
||||
MaybeSatisfyPendingMetadataDecodes();
|
||||
}
|
||||
|
||||
+bool ImageDecoderExternal::HasValidEncodedData() const {
|
||||
+ // If we keep an internal copy of the data, it's always valid.
|
||||
+ if (stream_buffer_)
|
||||
+ return true;
|
||||
+
|
||||
+ if (init_data_->data().IsArrayBuffer() &&
|
||||
+ init_data_->data().GetAsArrayBuffer()->IsDetached()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (init_data_->data().IsArrayBufferView() &&
|
||||
+ !init_data_->data().GetAsArrayBufferView()->BaseAddress()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc.rej b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc.rej
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..68d0eae0c7cd414f8cbe90aee79417d2a4ffe98b
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc.rej
|
||||
@@ -0,0 +1,53 @@
|
||||
+diff a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc (rejected hunks)
|
||||
+@@ -120,9 +120,8 @@
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+- // TODO(crbug.com/1073995): Data is owned by the caller who may be free to
|
||||
+- // manipulate it. We will probably need to make a copy to our own internal
|
||||
+- // data or neuter the buffers as seen by JS.
|
||||
++ // Since data is owned by the caller who may be free to manipulate it, we must
|
||||
++ // check HasValidEncodedData() before attempting to access |decoder_|.
|
||||
+ segment_reader_ = SegmentReader::CreateFromSkData(
|
||||
+ SkData::MakeWithoutCopy(buffer.Data(), buffer.ByteLengthAsSizeT()));
|
||||
+ if (!segment_reader_) {
|
||||
+@@ -266,6 +265,7 @@
|
||||
+
|
||||
+ void ImageDecoderExternal::CreateImageDecoder() {
|
||||
+ DCHECK(!decoder_);
|
||||
++ DCHECK(HasValidEncodedData());
|
||||
+
|
||||
+ // TODO(crbug.com/1073995): We should probably call
|
||||
+ // ImageDecoder::SetMemoryAllocator() so that we can recycle frame buffers for
|
||||
+@@ -320,6 +320,13 @@
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
++ if (!HasValidEncodedData()) {
|
||||
++ request->exception = MakeGarbageCollected<DOMException>(
|
||||
++ DOMExceptionCode::kInvalidStateError,
|
||||
++ "Source data has been neutered");
|
||||
++ continue;
|
||||
++ }
|
||||
++
|
||||
+ auto* image = decoder_->DecodeFrameBufferAtIndex(request->frame_index);
|
||||
+ if (decoder_->Failed() || !image) {
|
||||
+ // TODO(crbug.com/1073995): Include frameIndex in rejection?
|
||||
+@@ -398,6 +405,7 @@
|
||||
+ }
|
||||
+
|
||||
+ void ImageDecoderExternal::MaybeSatisfyPendingMetadataDecodes() {
|
||||
++ DCHECK(HasValidEncodedData());
|
||||
+ DCHECK(decoder_);
|
||||
+ if (!decoder_->IsSizeAvailable() && !decoder_->Failed())
|
||||
+ return;
|
||||
+@@ -409,6 +417,9 @@
|
||||
+ }
|
||||
+
|
||||
+ void ImageDecoderExternal::MaybeUpdateMetadata() {
|
||||
++ if (!HasValidEncodedData())
|
||||
++ return;
|
||||
++
|
||||
+ // Since we always create the decoder at construction, we need to wait until
|
||||
+ // at least the size is available before signaling that metadata has been
|
||||
+ // retrieved.
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h
|
||||
index 1b4ac0ce7eade63c06c1030c29fc90a8551aa7c2..7d9d534ce14d07e49fca99f11297e74b1311363e 100644
|
||||
--- a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.h
|
||||
@@ -61,6 +61,10 @@ class MODULES_EXPORT ImageDecoderExternal final : public ScriptWrappable,
|
||||
void MaybeSatisfyPendingMetadataDecodes();
|
||||
void MaybeUpdateMetadata();
|
||||
|
||||
+ // Returns false if the decoder was constructed with an ArrayBuffer or
|
||||
+ // ArrayBufferView that has since been neutered.
|
||||
+ bool HasValidEncodedData() const;
|
||||
+
|
||||
Member<ScriptState> script_state_;
|
||||
|
||||
// Used when a ReadableStream is provided.
|
||||
@@ -0,0 +1,206 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Mon, 5 Oct 2020 22:14:12 +0000
|
||||
Subject: Only zero out cross-origin audio that doesn't get played out.
|
||||
|
||||
Cross-origin audio is still allowed to play out, it just can't be
|
||||
captured by the containing page.
|
||||
|
||||
Bug: 1128657, 1134679
|
||||
Test: Unit tests added.
|
||||
|
||||
Change-Id: Id4c73e315072b8683e45a2ddf929d534f1da9928
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2450390
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Reviewed-by: Will Cassella <cassew@google.com>
|
||||
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#813956}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
|
||||
index c54e1768886a7d2d922f13596a9fb3b456ba6611..5cc64a4ae790f8b0b72520f1b8d2b89617bd22e2 100644
|
||||
--- a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
|
||||
+++ b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
|
||||
@@ -81,10 +81,6 @@ class WebAudioSourceProviderImpl::TeeFilter
|
||||
const int num_rendered_frames = renderer_->Render(
|
||||
delay, delay_timestamp, prior_frames_skipped, audio_bus);
|
||||
|
||||
- // Zero out frames after rendering
|
||||
- if (origin_tainted_.IsSet())
|
||||
- audio_bus->Zero();
|
||||
-
|
||||
// Avoid taking the copy lock for the vast majority of cases.
|
||||
if (copy_required_) {
|
||||
base::AutoLock auto_lock(copy_lock_);
|
||||
@@ -93,7 +89,11 @@ class WebAudioSourceProviderImpl::TeeFilter
|
||||
media::AudioTimestampHelper::TimeToFrames(delay, sample_rate_);
|
||||
std::unique_ptr<media::AudioBus> bus_copy =
|
||||
media::AudioBus::Create(audio_bus->channels(), audio_bus->frames());
|
||||
- audio_bus->CopyTo(bus_copy.get());
|
||||
+ // Disable copying when origin is tainted.
|
||||
+ if (origin_tainted_.IsSet())
|
||||
+ bus_copy->Zero();
|
||||
+ else
|
||||
+ audio_bus->CopyTo(bus_copy.get());
|
||||
copy_audio_bus_callback_.Run(std::move(bus_copy),
|
||||
static_cast<uint32_t>(frames_delayed),
|
||||
sample_rate_);
|
||||
@@ -119,6 +119,7 @@ class WebAudioSourceProviderImpl::TeeFilter
|
||||
}
|
||||
|
||||
void TaintOrigin() { origin_tainted_.Set(); }
|
||||
+ bool is_tainted() const { return origin_tainted_.IsSet(); }
|
||||
|
||||
private:
|
||||
AudioRendererSink::RenderCallback* renderer_ = nullptr;
|
||||
@@ -220,6 +221,13 @@ void WebAudioSourceProviderImpl::ProvideInput(
|
||||
DCHECK_EQ(tee_filter_->channels(), bus_wrapper_->channels());
|
||||
const int frames = tee_filter_->Render(
|
||||
base::TimeDelta(), base::TimeTicks::Now(), 0, bus_wrapper_.get());
|
||||
+
|
||||
+ // Zero out frames after rendering for tainted origins.
|
||||
+ if (tee_filter_->is_tainted()) {
|
||||
+ bus_wrapper_->Zero();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (frames < incoming_number_of_frames)
|
||||
bus_wrapper_->ZeroFramesPartial(frames, incoming_number_of_frames - frames);
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
|
||||
index 1f0c69d7143c06af3127a3f4b8dea6bd416d949f..db319bcc4f2fce940b5269da994e61a9978772f0 100644
|
||||
--- a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
|
||||
+++ b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl_test.cc
|
||||
@@ -22,6 +22,11 @@ using ::testing::_;
|
||||
namespace blink {
|
||||
|
||||
namespace {
|
||||
+
|
||||
+MATCHER(IsMuted, std::string(negation ? "isn't" : "is") + " muted") {
|
||||
+ return arg->AreFramesZero();
|
||||
+}
|
||||
+
|
||||
const float kTestVolume = 0.25;
|
||||
const int kTestSampleRate = 48000;
|
||||
} // namespace
|
||||
@@ -89,17 +94,10 @@ class WebAudioSourceProviderImplTest : public testing::Test,
|
||||
|
||||
// WebAudioSourceProviderClient implementation.
|
||||
MOCK_METHOD2(SetFormat, void(uint32_t numberOfChannels, float sampleRate));
|
||||
-
|
||||
- // CopyAudioCB. Added forwarder method due to GMock troubles with scoped_ptr.
|
||||
MOCK_METHOD3(DoCopyAudioCB,
|
||||
- void(media::AudioBus*,
|
||||
+ void(std::unique_ptr<media::AudioBus> bus,
|
||||
uint32_t frames_delayed,
|
||||
int sample_rate));
|
||||
- void OnAudioBus(std::unique_ptr<media::AudioBus> bus,
|
||||
- uint32_t frames_delayed,
|
||||
- int sample_rate) {
|
||||
- DoCopyAudioCB(bus.get(), frames_delayed, sample_rate);
|
||||
- }
|
||||
|
||||
int Render(media::AudioBus* audio_bus) {
|
||||
return wasp_impl_->RenderForTesting(audio_bus);
|
||||
@@ -163,6 +161,35 @@ TEST_F(WebAudioSourceProviderImplTest, SinkMethods) {
|
||||
CallAllSinkMethodsAndVerify(false);
|
||||
}
|
||||
|
||||
+// Test tainting effects on Render().
|
||||
+TEST_F(WebAudioSourceProviderImplTest, RenderTainted) {
|
||||
+ auto bus = media::AudioBus::Create(params_);
|
||||
+ bus->Zero();
|
||||
+
|
||||
+ // Point the WebVector into memory owned by |bus|.
|
||||
+ WebVector<float*> audio_data(static_cast<size_t>(bus->channels()));
|
||||
+ for (size_t i = 0; i < audio_data.size(); ++i)
|
||||
+ audio_data[i] = bus->channel(static_cast<int>(i));
|
||||
+
|
||||
+ wasp_impl_->Initialize(params_, &fake_callback_);
|
||||
+
|
||||
+ EXPECT_CALL(*mock_sink_, Start());
|
||||
+ wasp_impl_->Start();
|
||||
+ EXPECT_CALL(*mock_sink_, Play());
|
||||
+ wasp_impl_->Play();
|
||||
+
|
||||
+ Render(bus.get());
|
||||
+ ASSERT_FALSE(bus->AreFramesZero());
|
||||
+
|
||||
+ // Normal audio output should be unaffected by tainting.
|
||||
+ wasp_impl_->TaintOrigin();
|
||||
+ Render(bus.get());
|
||||
+ ASSERT_FALSE(bus->AreFramesZero());
|
||||
+
|
||||
+ EXPECT_CALL(*mock_sink_, Stop());
|
||||
+ wasp_impl_->Stop();
|
||||
+}
|
||||
+
|
||||
// Test the AudioRendererSink state machine and its effects on provideInput().
|
||||
TEST_F(WebAudioSourceProviderImplTest, ProvideInput) {
|
||||
auto bus1 = media::AudioBus::Create(params_);
|
||||
@@ -249,12 +276,37 @@ TEST_F(WebAudioSourceProviderImplTest, ProvideInput) {
|
||||
ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
|
||||
}
|
||||
|
||||
+// Test tainting effects on ProvideInput().
|
||||
+TEST_F(WebAudioSourceProviderImplTest, ProvideInputTainted) {
|
||||
+ auto bus = media::AudioBus::Create(params_);
|
||||
+ bus->Zero();
|
||||
+
|
||||
+ // Point the WebVector into memory owned by |bus|.
|
||||
+ WebVector<float*> audio_data(static_cast<size_t>(bus->channels()));
|
||||
+ for (size_t i = 0; i < audio_data.size(); ++i)
|
||||
+ audio_data[i] = bus->channel(static_cast<int>(i));
|
||||
+
|
||||
+ wasp_impl_->Initialize(params_, &fake_callback_);
|
||||
+ SetClient(this);
|
||||
+
|
||||
+ wasp_impl_->Start();
|
||||
+ wasp_impl_->Play();
|
||||
+ wasp_impl_->ProvideInput(audio_data, params_.frames_per_buffer());
|
||||
+ ASSERT_FALSE(bus->AreFramesZero());
|
||||
+
|
||||
+ wasp_impl_->TaintOrigin();
|
||||
+ wasp_impl_->ProvideInput(audio_data, params_.frames_per_buffer());
|
||||
+ ASSERT_TRUE(bus->AreFramesZero());
|
||||
+
|
||||
+ wasp_impl_->Stop();
|
||||
+}
|
||||
+
|
||||
// Verify CopyAudioCB is called if registered.
|
||||
TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) {
|
||||
testing::InSequence s;
|
||||
wasp_impl_->Initialize(params_, &fake_callback_);
|
||||
wasp_impl_->SetCopyAudioCallback(WTF::BindRepeating(
|
||||
- &WebAudioSourceProviderImplTest::OnAudioBus, base::Unretained(this)));
|
||||
+ &WebAudioSourceProviderImplTest::DoCopyAudioCB, base::Unretained(this)));
|
||||
|
||||
const auto bus1 = media::AudioBus::Create(params_);
|
||||
EXPECT_CALL(*this, DoCopyAudioCB(_, 0, params_.sample_rate())).Times(1);
|
||||
@@ -267,6 +319,27 @@ TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) {
|
||||
testing::Mock::VerifyAndClear(mock_sink_.get());
|
||||
}
|
||||
|
||||
+// Verify CopyAudioCB is zero when tainted.
|
||||
+TEST_F(WebAudioSourceProviderImplTest, CopyAudioCBTainted) {
|
||||
+ testing::InSequence s;
|
||||
+ wasp_impl_->Initialize(params_, &fake_callback_);
|
||||
+ wasp_impl_->SetCopyAudioCallback(WTF::BindRepeating(
|
||||
+ &WebAudioSourceProviderImplTest::DoCopyAudioCB, base::Unretained(this)));
|
||||
+
|
||||
+ const auto bus1 = media::AudioBus::Create(params_);
|
||||
+ EXPECT_CALL(*this,
|
||||
+ DoCopyAudioCB(testing::Not(IsMuted()), 0, params_.sample_rate()))
|
||||
+ .Times(1);
|
||||
+ Render(bus1.get());
|
||||
+
|
||||
+ wasp_impl_->TaintOrigin();
|
||||
+ EXPECT_CALL(*this, DoCopyAudioCB(IsMuted(), 0, params_.sample_rate()))
|
||||
+ .Times(1);
|
||||
+ Render(bus1.get());
|
||||
+
|
||||
+ testing::Mock::VerifyAndClear(mock_sink_.get());
|
||||
+}
|
||||
+
|
||||
TEST_F(WebAudioSourceProviderImplTest, MultipleInitializeWithSetClient) {
|
||||
// setClient() with a nullptr client should do nothing if no client is set.
|
||||
wasp_impl_->SetClient(nullptr);
|
||||
@@ -10,10 +10,10 @@ kinds of utility windows. Similarly for `disableAutoHideCursor`.
|
||||
Additionally, disables usage of some private APIs in MAS builds.
|
||||
|
||||
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
|
||||
index f872e4ec47c157288980caafa11104af2d205abb..8cf97e1a4aa6ed95bbc6427877ec96c6200dc7f2 100644
|
||||
index f872e4ec47c157288980caafa11104af2d205abb..4f5c251da5904e1e478f3420a571b2edd8427486 100644
|
||||
--- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
|
||||
+++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
|
||||
@@ -154,6 +154,11 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
@@ -154,6 +154,15 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -21,11 +21,15 @@ index f872e4ec47c157288980caafa11104af2d205abb..8cf97e1a4aa6ed95bbc6427877ec96c6
|
||||
+- (BOOL)acceptsFirstMouse;
|
||||
+- (BOOL)disableAutoHideCursor;
|
||||
+@end
|
||||
+
|
||||
+@interface NSView (ElectronCustomMethods)
|
||||
+- (BOOL)shouldIgnoreMouseEvent;
|
||||
+@end
|
||||
+
|
||||
// These are not documented, so use only after checking -respondsToSelector:.
|
||||
@interface NSApplication (UndocumentedSpeechMethods)
|
||||
- (void)speakString:(NSString*)string;
|
||||
@@ -573,6 +578,9 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
@@ -573,6 +582,9 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent {
|
||||
@@ -35,7 +39,16 @@ index f872e4ec47c157288980caafa11104af2d205abb..8cf97e1a4aa6ed95bbc6427877ec96c6
|
||||
return [self acceptsMouseEventsWhenInactive];
|
||||
}
|
||||
|
||||
@@ -990,6 +998,10 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
@@ -648,6 +660,8 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
// its parent view.
|
||||
BOOL hitSelf = NO;
|
||||
while (view) {
|
||||
+ if ([view respondsToSelector:@selector(shouldIgnoreMouseEvent)] && ![view shouldIgnoreMouseEvent])
|
||||
+ return NO;
|
||||
if (view == self)
|
||||
hitSelf = YES;
|
||||
if ([view isKindOfClass:[self class]] && ![view isEqual:self] &&
|
||||
@@ -990,6 +1004,10 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
eventType == NSKeyDown &&
|
||||
!(modifierFlags & NSCommandKeyMask);
|
||||
|
||||
@@ -46,7 +59,7 @@ index f872e4ec47c157288980caafa11104af2d205abb..8cf97e1a4aa6ed95bbc6427877ec96c6
|
||||
// We only handle key down events and just simply forward other events.
|
||||
if (eventType != NSKeyDown) {
|
||||
_hostHelper->ForwardKeyboardEvent(event, latency_info);
|
||||
@@ -1766,9 +1778,11 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
@@ -1766,9 +1784,11 @@ void ExtractUnderlines(NSAttributedString* string,
|
||||
// Since this implementation doesn't have to wait any IPC calls, this doesn't
|
||||
// make any key-typing jank. --hbono 7/23/09
|
||||
//
|
||||
@@ -58,7 +71,7 @@ index f872e4ec47c157288980caafa11104af2d205abb..8cf97e1a4aa6ed95bbc6427877ec96c6
|
||||
|
||||
- (NSArray*)validAttributesForMarkedText {
|
||||
// This code is just copied from WebKit except renaming variables.
|
||||
@@ -1777,7 +1791,10 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
|
||||
@@ -1777,7 +1797,10 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
|
||||
initWithObjects:NSUnderlineStyleAttributeName,
|
||||
NSUnderlineColorAttributeName,
|
||||
NSMarkedClauseSegmentAttributeName,
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Scott Violet <sky@chromium.org>
|
||||
Date: Fri, 13 Nov 2020 20:47:38 +0000
|
||||
Subject: ui: CHECK that UnPremultiply is passed a 32bpp image
|
||||
|
||||
To do otherwise results in accessing random data.
|
||||
|
||||
BUG=1147430
|
||||
TEST=none
|
||||
|
||||
(cherry picked from commit 1f673896837ab8c687d93fec604c96c78c7f679b)
|
||||
|
||||
Change-Id: Icedacbaac64cad3fc903e6423c6f9aad8c1e8cb5
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2531118
|
||||
Commit-Queue: danakj <danakj@chromium.org>
|
||||
Reviewed-by: danakj <danakj@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#826300}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2538047
|
||||
Reviewed-by: Scott Violet <sky@chromium.org>
|
||||
Commit-Queue: Scott Violet <sky@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4240@{#1452}
|
||||
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
|
||||
|
||||
diff --git a/ui/gfx/skbitmap_operations.cc b/ui/gfx/skbitmap_operations.cc
|
||||
index c08079f585b033849c744838c1db7a05ef729450..30372e849213d0446ac7edd72452782606bf938f 100644
|
||||
--- a/ui/gfx/skbitmap_operations.cc
|
||||
+++ b/ui/gfx/skbitmap_operations.cc
|
||||
@@ -630,6 +630,8 @@ SkBitmap SkBitmapOperations::UnPreMultiply(const SkBitmap& bitmap) {
|
||||
return bitmap;
|
||||
if (bitmap.isOpaque())
|
||||
return bitmap;
|
||||
+ // It's expected this code is called with a 32bpp image.
|
||||
+ CHECK_EQ(kN32_SkColorType, bitmap.colorType());
|
||||
|
||||
const SkImageInfo& opaque_info =
|
||||
bitmap.info().makeAlphaType(kOpaque_SkAlphaType);
|
||||
@@ -1,21 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Deepak Mohan <hop2deep@gmail.com>
|
||||
Date: Wed, 24 Jun 2020 21:00:00 -0700
|
||||
Subject: use electron resources in icon_reader_service
|
||||
|
||||
Without this, the ID for IDS_UTILITY_PROCESS_UTILITY_WIN_NAME will be wrong on windows
|
||||
and cause a DCHECK() failure
|
||||
|
||||
diff --git a/chrome/browser/win/icon_reader_service.cc b/chrome/browser/win/icon_reader_service.cc
|
||||
index 721e1a863cc6925908f8343002df056f2373bf0b..10b2a95162541a8ff4d010c7be864f3f41dae378 100644
|
||||
--- a/chrome/browser/win/icon_reader_service.cc
|
||||
+++ b/chrome/browser/win/icon_reader_service.cc
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "chrome/browser/win/icon_reader_service.h"
|
||||
|
||||
#include "chrome/browser/service_sandbox_type.h"
|
||||
-#include "chrome/grit/generated_resources.h"
|
||||
+#include "electron/grit/electron_resources.h"
|
||||
#include "content/public/browser/service_process_host.h"
|
||||
|
||||
mojo::Remote<chrome::mojom::UtilReadIcon> LaunchIconReaderInstance() {
|
||||
@@ -1,22 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Apthorp <nornagon@nornagon.net>
|
||||
Date: Mon, 10 Feb 2020 10:37:48 -0800
|
||||
Subject: use electron resources in pdf_util
|
||||
|
||||
Without this, the ID for IDR_PDF_MANIFEST will be wrong on linux
|
||||
and cause a DCHECK(), since the resource will be loaded as an empty
|
||||
string.
|
||||
|
||||
diff --git a/chrome/browser/pdf/pdf_extension_util.cc b/chrome/browser/pdf/pdf_extension_util.cc
|
||||
index 9fd9791fd923d6c5e741cb7dc064ababf9a7995a..0a5534f2f09224196971076794daa3c805c91606 100644
|
||||
--- a/chrome/browser/pdf/pdf_extension_util.cc
|
||||
+++ b/chrome/browser/pdf/pdf_extension_util.cc
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "base/values.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/common/chrome_content_client.h"
|
||||
-#include "chrome/grit/browser_resources.h"
|
||||
+#include "electron/grit/electron_resources.h"
|
||||
#include "components/strings/grit/components_strings.h"
|
||||
#include "components/zoom/page_zoom_constants.h"
|
||||
#include "pdf/pdf_features.h"
|
||||
@@ -7,5 +7,13 @@
|
||||
|
||||
"src/electron/patches/node": "src/third_party/electron_node",
|
||||
|
||||
"src/electron/patches/usrsctp": "src/third_party/usrsctp/usrsctplib"
|
||||
"src/electron/patches/usrsctp": "src/third_party/usrsctp/usrsctplib",
|
||||
|
||||
"src/electron/patches/freetype": "src/third_party/freetype/src",
|
||||
|
||||
"src/electron/patches/pdfium": "src/third_party/pdfium",
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/skia": "src/third_party/skia"
|
||||
}
|
||||
|
||||
1
patches/freetype/.patches
Normal file
1
patches/freetype/.patches
Normal file
@@ -0,0 +1 @@
|
||||
test_early_to_prevent_overflow.patch
|
||||
39
patches/freetype/test_early_to_prevent_overflow.patch
Normal file
39
patches/freetype/test_early_to_prevent_overflow.patch
Normal file
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andrey Belenko <anbelen@microsoft.com>
|
||||
Date: Tue, 20 Oct 2020 21:39:54 +0200
|
||||
Subject: Test early to prevent overflow.
|
||||
|
||||
Bug: chromium:1139963
|
||||
|
||||
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
|
||||
index 2e64e58463ad04c65424b2386e4a5a0d4ed7ca18..0bf2b4321752fc1526ca10d8fe0c96d5576128bd 100644
|
||||
--- a/src/sfnt/pngshim.c
|
||||
+++ b/src/sfnt/pngshim.c
|
||||
@@ -332,6 +332,13 @@
|
||||
|
||||
if ( populate_map_and_metrics )
|
||||
{
|
||||
+ /* reject too large bitmaps similarly to the rasterizer */
|
||||
+ if ( imgWidth > 0x7FFF || imgHeight > 0x7FFF )
|
||||
+ {
|
||||
+ error = FT_THROW( Array_Too_Large );
|
||||
+ goto DestroyExit;
|
||||
+ }
|
||||
+
|
||||
metrics->width = (FT_UShort)imgWidth;
|
||||
metrics->height = (FT_UShort)imgHeight;
|
||||
|
||||
@@ -340,13 +347,6 @@
|
||||
map->pixel_mode = FT_PIXEL_MODE_BGRA;
|
||||
map->pitch = (int)( map->width * 4 );
|
||||
map->num_grays = 256;
|
||||
-
|
||||
- /* reject too large bitmaps similarly to the rasterizer */
|
||||
- if ( map->rows > 0x7FFF || map->width > 0x7FFF )
|
||||
- {
|
||||
- error = FT_THROW( Array_Too_Large );
|
||||
- goto DestroyExit;
|
||||
- }
|
||||
}
|
||||
|
||||
/* convert palette/gray image to rgb */
|
||||
@@ -49,3 +49,5 @@ lib_use_non-symbols_in_isurlinstance_check.patch
|
||||
fix_enable_tls_renegotiation.patch
|
||||
crypto_update_certdata_to_nss_3_56.patch
|
||||
n-api_src_provide_asynchronous_cleanup_hooks.patch
|
||||
chore_expose_v8_initialization_isolate_callbacks.patch
|
||||
fix_add_safeforterminationscopes_for_sigint_interruptions.patch
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 5 Oct 2020 16:05:45 -0700
|
||||
Subject: chore: expose v8 initialization isolate callbacks
|
||||
|
||||
Exposes v8 initializer callbacks to Electron so that we can call them
|
||||
directly. We expand upon and adapt their behavior, so allows us to
|
||||
ensure that we stay in sync with Node.js default behavior.
|
||||
|
||||
This will be upstreamed.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 7b370579d365204b2bd40a25e740bbc83726c376..be58db8d2bebd1e1e5a0e6eb35c09b459d5d56e6 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -25,14 +25,16 @@ using v8::Private;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
-static bool AllowWasmCodeGenerationCallback(Local<Context> context,
|
||||
+// static
|
||||
+bool Environment::AllowWasmCodeGenerationCallback(Local<Context> context,
|
||||
Local<String>) {
|
||||
Local<Value> wasm_code_gen =
|
||||
context->GetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration);
|
||||
return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue();
|
||||
}
|
||||
|
||||
-static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
|
||||
+// static
|
||||
+bool Environment::ShouldAbortOnUncaughtException(Isolate* isolate) {
|
||||
DebugSealHandleScope scope(isolate);
|
||||
Environment* env = Environment::GetCurrent(isolate);
|
||||
return env != nullptr &&
|
||||
@@ -41,7 +43,8 @@ static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
|
||||
!env->inside_should_not_abort_on_uncaught_scope();
|
||||
}
|
||||
|
||||
-static MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
+// static
|
||||
+MaybeLocal<Value> Environment::PrepareStackTraceCallback(Local<Context> context,
|
||||
Local<Value> exception,
|
||||
Local<Array> trace) {
|
||||
Environment* env = Environment::GetCurrent(context);
|
||||
@@ -195,7 +198,7 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
|
||||
auto* abort_callback = s.should_abort_on_uncaught_exception_callback ?
|
||||
s.should_abort_on_uncaught_exception_callback :
|
||||
- ShouldAbortOnUncaughtException;
|
||||
+ Environment::ShouldAbortOnUncaughtException;
|
||||
isolate->SetAbortOnUncaughtExceptionCallback(abort_callback);
|
||||
|
||||
auto* fatal_error_cb = s.fatal_error_callback ?
|
||||
@@ -203,7 +206,7 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
isolate->SetFatalErrorHandler(fatal_error_cb);
|
||||
|
||||
auto* prepare_stack_trace_cb = s.prepare_stack_trace_callback ?
|
||||
- s.prepare_stack_trace_callback : PrepareStackTraceCallback;
|
||||
+ s.prepare_stack_trace_callback : Environment::PrepareStackTraceCallback;
|
||||
isolate->SetPrepareStackTraceCallback(prepare_stack_trace_cb);
|
||||
}
|
||||
|
||||
@@ -211,7 +214,7 @@ void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
isolate->SetMicrotasksPolicy(s.policy);
|
||||
|
||||
auto* allow_wasm_codegen_cb = s.allow_wasm_code_generation_callback ?
|
||||
- s.allow_wasm_code_generation_callback : AllowWasmCodeGenerationCallback;
|
||||
+ s.allow_wasm_code_generation_callback : Environment::AllowWasmCodeGenerationCallback;
|
||||
isolate->SetAllowWasmCodeGenerationCallback(allow_wasm_codegen_cb);
|
||||
|
||||
auto* promise_reject_cb = s.promise_reject_callback ?
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index e269c47ae3814b42fdd2792360c1acb1995e98d2..e251eb1bb478b61b6b5a679f311c00d4310ff5ce 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -908,6 +908,13 @@ class Environment : public MemoryRetainer {
|
||||
void Exit(int code);
|
||||
void ExitEnv();
|
||||
|
||||
+ static bool AllowWasmCodeGenerationCallback(v8::Local<v8::Context> context,
|
||||
+ v8::Local<v8::String>);
|
||||
+ static bool ShouldAbortOnUncaughtException(v8::Isolate* isolate);
|
||||
+ static v8::MaybeLocal<v8::Value> PrepareStackTraceCallback(v8::Local<v8::Context> context,
|
||||
+ v8::Local<v8::Value> exception,
|
||||
+ v8::Local<v8::Array> trace);
|
||||
+
|
||||
// Register clean-up cb to be called on environment destruction.
|
||||
inline void RegisterHandleCleanup(uv_handle_t* handle,
|
||||
HandleCleanupCb cb,
|
||||
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Thu, 10 Dec 2020 14:39:33 -0800
|
||||
Subject: fix: add SafeForTerminationScopes for SIGINT interruptions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We start Node.js with only_terminate_in_safe_scope set to true becuase
|
||||
it's set by gin’s IsolateHolder. In those cases, parts of the API that
|
||||
expect execution termination to happen need to be marked as able to
|
||||
receive those events.
|
||||
|
||||
Upstreamed at https://github.com/nodejs/node/pull/36344.
|
||||
|
||||
diff --git a/src/module_wrap.cc b/src/module_wrap.cc
|
||||
index 29078bf6e58ce1782c08946dae760e7d62de486d..592cdedaa427393296ae5d9cd7c3a0d124b52673 100644
|
||||
--- a/src/module_wrap.cc
|
||||
+++ b/src/module_wrap.cc
|
||||
@@ -313,6 +313,7 @@ void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
ShouldNotAbortOnUncaughtScope no_abort_scope(env);
|
||||
TryCatchScope try_catch(env);
|
||||
+ Isolate::SafeForTerminationScope safe_for_termination(env->isolate());
|
||||
|
||||
bool timed_out = false;
|
||||
bool received_signal = false;
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 2d30e0b8038ce473d1c8740861e13c5eabc2a0be..0902ac29b6f48c86302954a22a6e3318dc29836e 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -902,6 +902,7 @@ bool ContextifyScript::EvalMachine(Environment* env,
|
||||
return false;
|
||||
}
|
||||
TryCatchScope try_catch(env);
|
||||
+ Isolate::SafeForTerminationScope safe_for_termination(env->isolate());
|
||||
ContextifyScript* wrapped_script;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder(), false);
|
||||
Local<UnboundScript> unbound_script =
|
||||
1
patches/pdfium/.patches
Normal file
1
patches/pdfium/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-9591642a0896.patch
|
||||
33
patches/pdfium/cherry-pick-9591642a0896.patch
Normal file
33
patches/pdfium/cherry-pick-9591642a0896.patch
Normal file
@@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Sepez <tsepez@chromium.org>
|
||||
Date: Mon, 19 Oct 2020 17:07:57 +0000
|
||||
Subject: Reverse order of CPWL_ListCtrl and CPWL_List_Notify cleanup
|
||||
|
||||
(Speculative) fix for the crash in 1137630, since it only reproduces
|
||||
sporadically on my system, but hasn't re-occured since applying the
|
||||
patch.
|
||||
|
||||
TBR: thestig@chromium.org
|
||||
Bug: chromium:1137630
|
||||
Change-Id: I4f52c7109eca00dfa8faee9bc6341cd94c25b60c
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/75090
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
(cherry picked from commit 7dd9dbd6dd4959a568e7701da19871f859f8dce2)
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/75350
|
||||
Reviewed-by: Tom Sepez <tsepez@chromium.org>
|
||||
|
||||
diff --git a/fpdfsdk/pwl/cpwl_list_box.h b/fpdfsdk/pwl/cpwl_list_box.h
|
||||
index 48b53e514dcb5a307b099b4ae427f83e9311f20c..1e56697f86318a5d371a6690fce9ec50c60e5150 100644
|
||||
--- a/fpdfsdk/pwl/cpwl_list_box.h
|
||||
+++ b/fpdfsdk/pwl/cpwl_list_box.h
|
||||
@@ -97,8 +97,8 @@ class CPWL_ListBox : public CPWL_Wnd {
|
||||
protected:
|
||||
bool m_bMouseDown = false;
|
||||
bool m_bHoverSel = false;
|
||||
+ std::unique_ptr<CPWL_List_Notify> m_pListNotify; // Must outlive |m_pList|.
|
||||
std::unique_ptr<CPWL_ListCtrl> m_pList;
|
||||
- std::unique_ptr<CPWL_List_Notify> m_pListNotify;
|
||||
UnownedPtr<IPWL_Filler_Notify> m_pFillerNotify;
|
||||
|
||||
private:
|
||||
1
patches/skia/.patches
Normal file
1
patches/skia/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-6763a713f957.patch
|
||||
31
patches/skia/cherry-pick-6763a713f957.patch
Normal file
31
patches/skia/cherry-pick-6763a713f957.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Osman <brianosman@google.com>
|
||||
Date: Thu, 3 Sep 2020 15:19:14 -0400
|
||||
Subject: Limit morphology radius to 100 pixels
|
||||
|
||||
This limit is arbitrary, but hopefully prevents pathological (or
|
||||
malicious) SVG content from consuming huge amounts of CPU/GPU time,
|
||||
without impacting any legitimate uses of feMorphology. (Typical usage
|
||||
has a much smaller radius).
|
||||
|
||||
Bug: chromium:1123035
|
||||
Change-Id: I4405bc595128e9a6287eb5efa1be14621baa3a00
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/315219
|
||||
Reviewed-by: Mike Reed <reed@google.com>
|
||||
Commit-Queue: Brian Osman <brianosman@google.com>
|
||||
|
||||
diff --git a/src/effects/imagefilters/SkMorphologyImageFilter.cpp b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
|
||||
index 35f35d7f8d6bb3c9b4aca8057d5b876c237dbb22..a9a617f648e2fa229d6a555610fac4c737dd1459 100644
|
||||
--- a/src/effects/imagefilters/SkMorphologyImageFilter.cpp
|
||||
+++ b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
|
||||
@@ -663,7 +663,9 @@ sk_sp<SkSpecialImage> SkMorphologyImageFilterImpl::onFilterImage(const Context&
|
||||
int height = SkScalarRoundToInt(radius.height());
|
||||
|
||||
// Width (or height) must fit in a signed 32-bit int to avoid UBSAN issues (crbug.com/1018190)
|
||||
- constexpr int kMaxRadius = (std::numeric_limits<int>::max() - 1) / 2;
|
||||
+ // Further, we limit the radius to something much smaller, to avoid extremely slow draw calls:
|
||||
+ // (crbug.com/1123035):
|
||||
+ constexpr int kMaxRadius = 100; // (std::numeric_limits<int>::max() - 1) / 2;
|
||||
|
||||
if (width < 0 || height < 0 || width > kMaxRadius || height > kMaxRadius) {
|
||||
return nullptr;
|
||||
@@ -7,3 +7,11 @@ workaround_an_undefined_symbol_error.patch
|
||||
do_not_export_private_v8_symbols_on_windows.patch
|
||||
revert_cleanup_switch_offset_of_to_offsetof_where_possible.patch
|
||||
fix_build_deprecated_attirbute_for_older_msvc_versions.patch
|
||||
cherry-pick-6aa1e71fbd09.patch
|
||||
perf_make_getpositioninfoslow_faster.patch
|
||||
cherry-pick-6a4cd97d6691.patch
|
||||
cherry-pick-815b12dfb5ec.patch
|
||||
cherry-pick-8c725f7b5bbf.patch
|
||||
cherry-pick-146bd99e762b.patch
|
||||
cherry-pick-633f67caa6d0.patch
|
||||
cherry-pick-290fe9c6e245.patch
|
||||
|
||||
299
patches/v8/cherry-pick-146bd99e762b.patch
Normal file
299
patches/v8/cherry-pick-146bd99e762b.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, 3 Nov 2020 12:42:43 +0100
|
||||
Subject: Merged: Squashed multiple commits.
|
||||
|
||||
Merged: [map] Try to in-place transition during map update
|
||||
Revision: 8e3ae62d294818733a0322d8e8abd53d4e410f19
|
||||
|
||||
Merged: [map] Skip loading the field owner before GeneralizeField
|
||||
Revision: a928f5fcc2a67c2c8d621ece48f76deb0d36637b
|
||||
|
||||
BUG=chromium:1143772
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
R=verwaest@chromium.org
|
||||
|
||||
Change-Id: I78628cb697b21caa2098cc5948e226af5fcd020c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2516474
|
||||
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/8.7@{#31}
|
||||
Cr-Branched-From: 0d81cd72688512abcbe1601015baee390c484a6a-refs/heads/8.7.220@{#1}
|
||||
Cr-Branched-From: 942c2ef85caef00fcf02517d049f05e9a3d4b440-refs/heads/master@{#70196}
|
||||
|
||||
diff --git a/src/objects/map-updater.cc b/src/objects/map-updater.cc
|
||||
index e51bcfc76010a8c616dccc0af5daff5d498b7e81..b4b158749381efcf780d5c8ba07c286be6ba6b30 100644
|
||||
--- a/src/objects/map-updater.cc
|
||||
+++ b/src/objects/map-updater.cc
|
||||
@@ -232,10 +232,7 @@ MapUpdater::State MapUpdater::TryReconfigureToDataFieldInplace() {
|
||||
handle(old_descriptors_->GetFieldType(modified_descriptor_), isolate_),
|
||||
MaybeHandle<Object>(), new_field_type_, MaybeHandle<Object>());
|
||||
}
|
||||
- Handle<Map> field_owner(
|
||||
- old_map_->FindFieldOwner(isolate_, modified_descriptor_), isolate_);
|
||||
-
|
||||
- GeneralizeField(field_owner, modified_descriptor_, new_constness_,
|
||||
+ GeneralizeField(old_map_, modified_descriptor_, new_constness_,
|
||||
new_representation_, new_field_type_);
|
||||
// Check that the descriptor array was updated.
|
||||
DCHECK(old_descriptors_->GetDetails(modified_descriptor_)
|
||||
@@ -401,7 +398,13 @@ MapUpdater::State MapUpdater::FindTargetMap() {
|
||||
}
|
||||
Representation tmp_representation = tmp_details.representation();
|
||||
if (!old_details.representation().fits_into(tmp_representation)) {
|
||||
- break;
|
||||
+ // Try updating the field in-place to a generalized type.
|
||||
+ Representation generalized =
|
||||
+ tmp_representation.generalize(old_details.representation());
|
||||
+ if (!tmp_representation.CanBeInPlaceChangedTo(generalized)) {
|
||||
+ break;
|
||||
+ }
|
||||
+ tmp_representation = generalized;
|
||||
}
|
||||
|
||||
if (tmp_details.location() == kField) {
|
||||
diff --git a/src/objects/map.cc b/src/objects/map.cc
|
||||
index d85d5893c43798a6ee643da46267c77eacd49c0e..cc98acd0e2840da52cc84b076fdea987bf96a047 100644
|
||||
--- a/src/objects/map.cc
|
||||
+++ b/src/objects/map.cc
|
||||
@@ -611,6 +611,7 @@ void Map::DeprecateTransitionTree(Isolate* isolate) {
|
||||
transitions.GetTarget(i).DeprecateTransitionTree(isolate);
|
||||
}
|
||||
DCHECK(!constructor_or_backpointer().IsFunctionTemplateInfo());
|
||||
+ DCHECK(CanBeDeprecated());
|
||||
set_is_deprecated(true);
|
||||
if (FLAG_trace_maps) {
|
||||
LOG(isolate, MapEvent("Deprecate", handle(*this, isolate), Handle<Map>()));
|
||||
diff --git a/test/cctest/test-field-type-tracking.cc b/test/cctest/test-field-type-tracking.cc
|
||||
index a8ef298fb0d2a7da15a4b58e5088dcec7e88b426..740ae05c1eaf8104ad5c3c443b2e39429fc7fca5 100644
|
||||
--- a/test/cctest/test-field-type-tracking.cc
|
||||
+++ b/test/cctest/test-field-type-tracking.cc
|
||||
@@ -1038,7 +1038,8 @@ namespace {
|
||||
// where "p2A" and "p2B" differ only in the attributes.
|
||||
//
|
||||
void TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
- const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
|
||||
+ const CRFTData& from, const CRFTData& to, const CRFTData& expected,
|
||||
+ bool expected_deprecation) {
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
|
||||
Expectations expectations(isolate);
|
||||
@@ -1107,24 +1108,29 @@ void TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
CHECK_NE(*map2, *new_map);
|
||||
CHECK(expectations2.Check(*map2));
|
||||
|
||||
- // |map| should be deprecated and |new_map| should match new expectations.
|
||||
for (int i = kSplitProp; i < kPropCount; i++) {
|
||||
expectations.SetDataField(i, expected.constness, expected.representation,
|
||||
expected.type);
|
||||
}
|
||||
- CHECK(map->is_deprecated());
|
||||
- CHECK(!code_field_type->marked_for_deoptimization());
|
||||
- CHECK(!code_field_repr->marked_for_deoptimization());
|
||||
- CHECK(!code_field_const->marked_for_deoptimization());
|
||||
- CHECK_NE(*map, *new_map);
|
||||
+ if (expected_deprecation) {
|
||||
+ // |map| should be deprecated and |new_map| should match new expectations.
|
||||
+ CHECK(map->is_deprecated());
|
||||
+ CHECK(!code_field_type->marked_for_deoptimization());
|
||||
+ CHECK(!code_field_repr->marked_for_deoptimization());
|
||||
+ CHECK(!code_field_const->marked_for_deoptimization());
|
||||
+ CHECK_NE(*map, *new_map);
|
||||
|
||||
- CHECK(!new_map->is_deprecated());
|
||||
- CHECK(expectations.Check(*new_map));
|
||||
+ CHECK(!new_map->is_deprecated());
|
||||
+ CHECK(expectations.Check(*new_map));
|
||||
|
||||
- // Update deprecated |map|, it should become |new_map|.
|
||||
- Handle<Map> updated_map = Map::Update(isolate, map);
|
||||
- CHECK_EQ(*new_map, *updated_map);
|
||||
- CheckMigrationTarget(isolate, *map, *updated_map);
|
||||
+ // Update deprecated |map|, it should become |new_map|.
|
||||
+ Handle<Map> updated_map = Map::Update(isolate, map);
|
||||
+ CHECK_EQ(*new_map, *updated_map);
|
||||
+ CheckMigrationTarget(isolate, *map, *updated_map);
|
||||
+ } else {
|
||||
+ CHECK(!map->is_deprecated());
|
||||
+ CHECK(expectations.Check(*map));
|
||||
+ }
|
||||
}
|
||||
|
||||
// This test ensures that trivial field generalization (from HeapObject to
|
||||
@@ -1240,22 +1246,22 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) {
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kConst, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kConst, Representation::Double(), any_type},
|
||||
- {PropertyConstness::kConst, Representation::Double(), any_type});
|
||||
+ {PropertyConstness::kConst, Representation::Double(), any_type}, true);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kConst, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kMutable, Representation::Double(), any_type},
|
||||
- {PropertyConstness::kMutable, Representation::Double(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Double(), any_type}, true);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kMutable, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kConst, Representation::Double(), any_type},
|
||||
- {PropertyConstness::kMutable, Representation::Double(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Double(), any_type}, true);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kMutable, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kMutable, Representation::Double(), any_type},
|
||||
- {PropertyConstness::kMutable, Representation::Double(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Double(), any_type}, true);
|
||||
}
|
||||
|
||||
TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
|
||||
@@ -1270,22 +1276,26 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kConst, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kConst, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kConst, Representation::Tagged(), any_type},
|
||||
+ !FLAG_modify_field_representation_inplace);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kConst, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kMutable, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Tagged(), any_type},
|
||||
+ !FLAG_modify_field_representation_inplace);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kMutable, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kMutable, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Tagged(), any_type},
|
||||
+ !FLAG_modify_field_representation_inplace);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kMutable, Representation::Smi(), any_type},
|
||||
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kMutable, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Tagged(), any_type},
|
||||
+ !FLAG_modify_field_representation_inplace);
|
||||
}
|
||||
|
||||
TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
|
||||
@@ -1300,22 +1310,26 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kConst, Representation::Double(), any_type},
|
||||
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kConst, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kConst, Representation::Tagged(), any_type},
|
||||
+ FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kConst, Representation::Double(), any_type},
|
||||
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kMutable, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Tagged(), any_type},
|
||||
+ FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kMutable, Representation::Double(), any_type},
|
||||
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kMutable, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Tagged(), any_type},
|
||||
+ FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
|
||||
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kMutable, Representation::Double(), any_type},
|
||||
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
|
||||
- {PropertyConstness::kMutable, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Tagged(), any_type},
|
||||
+ FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
|
||||
}
|
||||
|
||||
TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
|
||||
@@ -1401,7 +1415,8 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
|
||||
TestReconfigureDataFieldAttribute_GeneralizeField(
|
||||
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
|
||||
{PropertyConstness::kMutable, Representation::Smi(), any_type},
|
||||
- {PropertyConstness::kMutable, Representation::Tagged(), any_type});
|
||||
+ {PropertyConstness::kMutable, Representation::Tagged(), any_type},
|
||||
+ !FLAG_modify_field_representation_inplace);
|
||||
}
|
||||
|
||||
// Checks that given |map| is deprecated and that it updates to given |new_map|
|
||||
diff --git a/test/mjsunit/regress/regress-1143772.js b/test/mjsunit/regress/regress-1143772.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..40bc494d458afec816fd72e3fbb36b20a7942649
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/regress/regress-1143772.js
|
||||
@@ -0,0 +1,71 @@
|
||||
+// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+//
|
||||
+// Flags: --allow-natives-syntax
|
||||
+
|
||||
+(function() {
|
||||
+ // Only run this test if doubles are transitioned in-place to tagged.
|
||||
+ let x = {};
|
||||
+ x.a = 0.1;
|
||||
+ let y = {};
|
||||
+ y.a = {};
|
||||
+ if (!%HaveSameMap(x, y)) return;
|
||||
+
|
||||
+ // m1: {}
|
||||
+ let m1 = {};
|
||||
+
|
||||
+ // m2: {a:d}
|
||||
+ let m2 = {};
|
||||
+ assertTrue(%HaveSameMap(m2, m1));
|
||||
+ m2.a = 13.37;
|
||||
+
|
||||
+ // m3: {a:d, b:s}
|
||||
+ let m3 = {};
|
||||
+ m3.a = 13.37;
|
||||
+ assertTrue(%HaveSameMap(m3, m2));
|
||||
+ m3.b = 1;
|
||||
+
|
||||
+ // m4: {a:d, b:s, c:h}
|
||||
+ let m4 = {};
|
||||
+ m4.a = 13.37;
|
||||
+ m4.b = 1;
|
||||
+ assertTrue(%HaveSameMap(m4, m3));
|
||||
+ m4.c = {};
|
||||
+
|
||||
+ // m4_2 == m4
|
||||
+ let m4_2 = {};
|
||||
+ m4_2.a = 13.37;
|
||||
+ m4_2.b = 1;
|
||||
+ m4_2.c = {};
|
||||
+ assertTrue(%HaveSameMap(m4_2, m4));
|
||||
+
|
||||
+ // m5: {a:d, b:d}
|
||||
+ let m5 = {};
|
||||
+ m5.a = 13.37;
|
||||
+ assertTrue(%HaveSameMap(m5, m2));
|
||||
+ m5.b = 13.37;
|
||||
+ assertFalse(%HaveSameMap(m5, m3));
|
||||
+
|
||||
+ // At this point, Map3 and Map4 are both deprecated. Map2 transitions to
|
||||
+ // Map5. Map5 is the migration target for Map3.
|
||||
+ assertFalse(%HaveSameMap(m5, m3));
|
||||
+
|
||||
+ // m6: {a:d, b:d, c:d}
|
||||
+ let m6 = {};
|
||||
+ m6.a = 13.37;
|
||||
+ assertTrue(%HaveSameMap(m6, m2));
|
||||
+ m6.b = 13.37;
|
||||
+ assertTrue(%HaveSameMap(m6, m5));
|
||||
+ m6.c = 13.37
|
||||
+
|
||||
+ // Make m7: {a:d, b:d, c:t}
|
||||
+ let m7 = m4_2;
|
||||
+ assertTrue(%HaveSameMap(m7, m4));
|
||||
+ // Map4 is deprecated, so this property access triggers a Map migration.
|
||||
+ // With in-place map updates and no double unboxing, this should end up
|
||||
+ // migrating to Map6, and updating it in-place.
|
||||
+ m7.c;
|
||||
+ assertFalse(%HaveSameMap(m7, m4));
|
||||
+ assertTrue(%HaveSameMap(m6, m7));
|
||||
+})();
|
||||
97
patches/v8/cherry-pick-290fe9c6e245.patch
Normal file
97
patches/v8/cherry-pick-290fe9c6e245.patch
Normal file
@@ -0,0 +1,97 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Georg Neis <neis@chromium.org>
|
||||
Date: Tue, 24 Nov 2020 14:43:35 +0100
|
||||
Subject: Merged: [compiler] Fix a bug in SimplifiedLowering
|
||||
|
||||
Revision: ba1b2cc09ab98b51ca3828d29d19ae3b0a7c3a92
|
||||
|
||||
BUG=chromium:1150649
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
TBR=tebbi@chromium.org
|
||||
|
||||
Change-Id: I3600d25ebc255b0e58a7db1ca8d025424f6ad3f5
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2557983
|
||||
Reviewed-by: Georg Neis <neis@chromium.org>
|
||||
Commit-Queue: Georg Neis <neis@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/8.7@{#55}
|
||||
Cr-Branched-From: 0d81cd72688512abcbe1601015baee390c484a6a-refs/heads/8.7.220@{#1}
|
||||
Cr-Branched-From: 942c2ef85caef00fcf02517d049f05e9a3d4b440-refs/heads/master@{#70196}
|
||||
|
||||
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
||||
index dd297d0b121e9997b6d4f76266c1f6e16e4ae72b..307ad5333869d4d80e59c115a486ed2f07f1798b 100644
|
||||
--- a/src/compiler/simplified-lowering.cc
|
||||
+++ b/src/compiler/simplified-lowering.cc
|
||||
@@ -1411,7 +1411,6 @@ class RepresentationSelector {
|
||||
IsSomePositiveOrderedNumber(input1_type)
|
||||
? CheckForMinusZeroMode::kDontCheckForMinusZero
|
||||
: CheckForMinusZeroMode::kCheckForMinusZero;
|
||||
-
|
||||
NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
|
||||
}
|
||||
|
||||
@@ -1455,6 +1454,13 @@ class RepresentationSelector {
|
||||
|
||||
Type left_feedback_type = TypeOf(node->InputAt(0));
|
||||
Type right_feedback_type = TypeOf(node->InputAt(1));
|
||||
+
|
||||
+ // Using Signed32 as restriction type amounts to promising there won't be
|
||||
+ // signed overflow. This is incompatible with relying on a Word32
|
||||
+ // truncation in order to skip the overflow check.
|
||||
+ Type const restriction =
|
||||
+ truncation.IsUsedAsWord32() ? Type::Any() : Type::Signed32();
|
||||
+
|
||||
// Handle the case when no int32 checks on inputs are necessary (but
|
||||
// an overflow check is needed on the output). Note that we do not
|
||||
// have to do any check if at most one side can be minus zero. For
|
||||
@@ -1468,7 +1474,7 @@ class RepresentationSelector {
|
||||
right_upper.Is(Type::Signed32OrMinusZero()) &&
|
||||
(left_upper.Is(Type::Signed32()) || right_upper.Is(Type::Signed32()))) {
|
||||
VisitBinop<T>(node, UseInfo::TruncatingWord32(),
|
||||
- MachineRepresentation::kWord32, Type::Signed32());
|
||||
+ MachineRepresentation::kWord32, restriction);
|
||||
} else {
|
||||
// If the output's truncation is identify-zeros, we can pass it
|
||||
// along. Moreover, if the operation is addition and we know the
|
||||
@@ -1488,8 +1494,9 @@ class RepresentationSelector {
|
||||
UseInfo right_use = CheckedUseInfoAsWord32FromHint(hint, FeedbackSource(),
|
||||
kIdentifyZeros);
|
||||
VisitBinop<T>(node, left_use, right_use, MachineRepresentation::kWord32,
|
||||
- Type::Signed32());
|
||||
+ restriction);
|
||||
}
|
||||
+
|
||||
if (lower<T>()) {
|
||||
if (truncation.IsUsedAsWord32() ||
|
||||
!CanOverflowSigned32(node->op(), left_feedback_type,
|
||||
diff --git a/test/mjsunit/compiler/regress-1150649.js b/test/mjsunit/compiler/regress-1150649.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a193481a3a20dc18dab7270a7686f6328bb79538
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/compiler/regress-1150649.js
|
||||
@@ -0,0 +1,24 @@
|
||||
+// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+// Flags: --allow-natives-syntax
|
||||
+
|
||||
+function foo(a) {
|
||||
+ var y = 0x7fffffff; // 2^31 - 1
|
||||
+
|
||||
+ // Widen the static type of y (this condition never holds).
|
||||
+ if (a == NaN) y = NaN;
|
||||
+
|
||||
+ // The next condition holds only in the warmup run. It leads to Smi
|
||||
+ // (SignedSmall) feedback being collected for the addition below.
|
||||
+ if (a) y = -1;
|
||||
+
|
||||
+ const z = (y + 1)|0;
|
||||
+ return z < 0;
|
||||
+}
|
||||
+
|
||||
+%PrepareFunctionForOptimization(foo);
|
||||
+assertFalse(foo(true));
|
||||
+%OptimizeFunctionOnNextCall(foo);
|
||||
+assertTrue(foo(false));
|
||||
50
patches/v8/cherry-pick-633f67caa6d0.patch
Normal file
50
patches/v8/cherry-pick-633f67caa6d0.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Haas <ahaas@chromium.org>
|
||||
Date: Wed, 28 Oct 2020 07:55:24 +0100
|
||||
Subject: Add missing HasValue check in BitfieldCheck::Detect
|
||||
|
||||
The value of a node was accessed without prior HasValue check. With
|
||||
WebAssembly this node is not guaranteed to be a value.
|
||||
|
||||
R=mslekova@chromium.org
|
||||
|
||||
Change-Id: I62170183f3940a04b0550dfbb78cb49d2f5d7f72
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2504250
|
||||
Reviewed-by: Maya Lekova <mslekova@chromium.org>
|
||||
Commit-Queue: Andreas Haas <ahaas@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#70833}
|
||||
|
||||
diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc
|
||||
index 127c7681099537c453a9ec08bc0af1d896e9717c..dbe4eae299468a33768656ef17836c04bbcfae7e 100644
|
||||
--- a/src/compiler/machine-operator-reducer.cc
|
||||
+++ b/src/compiler/machine-operator-reducer.cc
|
||||
@@ -1616,7 +1616,7 @@ struct BitfieldCheck {
|
||||
Uint32BinopMatcher eq(node);
|
||||
if (eq.left().IsWord32And()) {
|
||||
Uint32BinopMatcher mand(eq.left().node());
|
||||
- if (mand.right().HasValue()) {
|
||||
+ if (mand.right().HasValue() && eq.right().HasValue()) {
|
||||
BitfieldCheck result{mand.left().node(), mand.right().Value(),
|
||||
eq.right().Value(), false};
|
||||
if (mand.left().IsTruncateInt64ToInt32()) {
|
||||
diff --git a/test/unittests/compiler/machine-operator-reducer-unittest.cc b/test/unittests/compiler/machine-operator-reducer-unittest.cc
|
||||
index 53342cbd212e561bc98cd559b139696fac291143..d789c5646bde8be423dabed3a64417019067ab60 100644
|
||||
--- a/test/unittests/compiler/machine-operator-reducer-unittest.cc
|
||||
+++ b/test/unittests/compiler/machine-operator-reducer-unittest.cc
|
||||
@@ -837,6 +837,16 @@ TEST_F(MachineOperatorReducerTest, Word32AndWithBitFields) {
|
||||
}
|
||||
}
|
||||
|
||||
+TEST_F(MachineOperatorReducerTest, Word32AndWithIncorrectBitField) {
|
||||
+ Reduction const r = Reduce(graph()->NewNode(
|
||||
+ machine()->Word32And(), Parameter(0),
|
||||
+ graph()->NewNode(machine()->Word32Equal(),
|
||||
+ graph()->NewNode(machine()->Word32And(), Parameter(0),
|
||||
+ Int32Constant(4)),
|
||||
+ Parameter(0))));
|
||||
+ ASSERT_FALSE(r.Changed());
|
||||
+}
|
||||
+
|
||||
// -----------------------------------------------------------------------------
|
||||
// Word32Or
|
||||
|
||||
90
patches/v8/cherry-pick-6a4cd97d6691.patch
Normal file
90
patches/v8/cherry-pick-6a4cd97d6691.patch
Normal file
@@ -0,0 +1,90 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leszek Swirski <leszeks@chromium.org>
|
||||
Date: Wed, 30 Sep 2020 15:19:13 +0200
|
||||
Subject: Merged: [parser] Fix AST func reindexing for function fields
|
||||
|
||||
AST reindexing has to skip visiting fields that are already in the
|
||||
member initializer, as they will have already been visited when
|
||||
visiting said initializer. This is the case for private fields and
|
||||
fields with computed names.
|
||||
|
||||
However, the reindexer was incorrectly assuming that all properties
|
||||
with a FunctionLiteral value are methods (and thus not fields, and
|
||||
can safely be visited). This is not the case for fields with
|
||||
function expression values.
|
||||
|
||||
Now, we correctly use the class property's "kind" when making this
|
||||
visitation decision.
|
||||
|
||||
(cherry picked from commit a769ea7a4462115579ba87bc16fbffbae01310c1)
|
||||
|
||||
Bug: chromium:1132111
|
||||
Tbr: leszeks@chromium.org
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: I33ac5664bb5334e964d351de1ba7e2c57f3398f8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2465056
|
||||
Commit-Queue: Adam Klein <adamk@chromium.org>
|
||||
Reviewed-by: Adam Klein <adamk@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/8.6@{#24}
|
||||
Cr-Branched-From: a64aed2333abf49e494d2a5ce24bbd14fff19f60-refs/heads/8.6.395@{#1}
|
||||
Cr-Branched-From: a626bc036236c9bf92ac7b87dc40c9e538b087e3-refs/heads/master@{#69472}
|
||||
|
||||
diff --git a/src/ast/ast-function-literal-id-reindexer.cc b/src/ast/ast-function-literal-id-reindexer.cc
|
||||
index b583b5e4214ad469848844923ef03dba06b6554c..8c9318bfe7475d3c9b8cc2bdb50786b9118fd4a0 100644
|
||||
--- a/src/ast/ast-function-literal-id-reindexer.cc
|
||||
+++ b/src/ast/ast-function-literal-id-reindexer.cc
|
||||
@@ -54,10 +54,10 @@ void AstFunctionLiteralIdReindexer::VisitClassLiteral(ClassLiteral* expr) {
|
||||
// Private fields have their key and value present in
|
||||
// instance_members_initializer_function, so they will
|
||||
// already have been visited.
|
||||
- if (prop->value()->IsFunctionLiteral()) {
|
||||
- Visit(prop->value());
|
||||
- } else {
|
||||
+ if (prop->kind() == ClassLiteralProperty::Kind::FIELD) {
|
||||
CheckVisited(prop->value());
|
||||
+ } else {
|
||||
+ Visit(prop->value());
|
||||
}
|
||||
}
|
||||
ZonePtrList<ClassLiteral::Property>* props = expr->public_members();
|
||||
@@ -67,7 +67,8 @@ void AstFunctionLiteralIdReindexer::VisitClassLiteral(ClassLiteral* expr) {
|
||||
// Public fields with computed names have their key
|
||||
// and value present in instance_members_initializer_function, so they will
|
||||
// already have been visited.
|
||||
- if (prop->is_computed_name() && !prop->value()->IsFunctionLiteral()) {
|
||||
+ if (prop->is_computed_name() &&
|
||||
+ prop->kind() == ClassLiteralProperty::Kind::FIELD) {
|
||||
if (!prop->key()->IsLiteral()) {
|
||||
CheckVisited(prop->key());
|
||||
}
|
||||
diff --git a/test/mjsunit/regress/regress-1132111.js b/test/mjsunit/regress/regress-1132111.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..1dd1b58806862aaf6c0847f107377095105dcab1
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/regress/regress-1132111.js
|
||||
@@ -0,0 +1,23 @@
|
||||
+// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+// Public function field with computed name
|
||||
+eval(`
|
||||
+ buggy = ((bug = new class { [0] = x => 1337.0; }) => bug);
|
||||
+`);
|
||||
+
|
||||
+// Public method with computed name
|
||||
+eval(`
|
||||
+ buggy = ((bug = new class { [0](x) { return 1337.0}; }) => bug);
|
||||
+`);
|
||||
+
|
||||
+// Private function field with computed name
|
||||
+eval(`
|
||||
+ buggy = ((bug = new class { #foo = x => 1337.0; }) => bug);
|
||||
+`);
|
||||
+
|
||||
+// Private method with computed name
|
||||
+eval(`
|
||||
+ buggy = ((bug = new class { #foo(x) { return 1337.0; } }) => bug);
|
||||
+`);
|
||||
70
patches/v8/cherry-pick-6aa1e71fbd09.patch
Normal file
70
patches/v8/cherry-pick-6aa1e71fbd09.patch
Normal file
@@ -0,0 +1,70 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Haas <ahaas@chromium.org>
|
||||
Date: Tue, 25 Aug 2020 11:46:46 +0200
|
||||
Subject: Merged: [wasm][streaming] Avoid aborting the stream after it finished
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
With WebAssembly streaming compilation it is possible that FinishStream
|
||||
indirectly calls AbortStream. This had the effect that while
|
||||
FinishStream fulfilled the promise, AbortStream disposed the promise
|
||||
by removing the compile job from the wasm engine and thereby deallocated
|
||||
AsyncCompileJob and all the state that belongs to it. Without that
|
||||
state, FinishStream could not finish fulfilling the promise correctly.
|
||||
|
||||
With this CL the streaming decoder remembers that the stream has
|
||||
already been finished. When the stream has been finished, all calls to
|
||||
Abort get ignored.
|
||||
|
||||
The regression test for this issue requires the Chrome embedding, see
|
||||
https://crrev.com/c/2368359
|
||||
|
||||
R=clemensb@chromium.org
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
|
||||
(cherry picked from commit 32dd54709cd2ecdfc553aff3f7ab5377ff7c91a2)
|
||||
|
||||
Bug: chromium:1117258
|
||||
Change-Id: Ifc28a1ee38c228b051c4d7d85b305fe2a721fa1f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2367858
|
||||
Commit-Queue: Andreas Haas <ahaas@chromium.org>
|
||||
Reviewed-by: Clemens Backes <clemensb@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#69549}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2465830
|
||||
Cr-Commit-Position: refs/branch-heads/8.6@{#22}
|
||||
Cr-Branched-From: a64aed2333abf49e494d2a5ce24bbd14fff19f60-refs/heads/8.6.395@{#1}
|
||||
Cr-Branched-From: a626bc036236c9bf92ac7b87dc40c9e538b087e3-refs/heads/master@{#69472}
|
||||
|
||||
diff --git a/src/wasm/streaming-decoder.cc b/src/wasm/streaming-decoder.cc
|
||||
index eb2978070074981f20b0e2f27401bce39e0029d9..88f40b9a00df75231b9938a4691c1330d047b070 100644
|
||||
--- a/src/wasm/streaming-decoder.cc
|
||||
+++ b/src/wasm/streaming-decoder.cc
|
||||
@@ -214,6 +214,7 @@ class V8_EXPORT_PRIVATE AsyncStreamingDecoder : public StreamingDecoder {
|
||||
bool code_section_processed_ = false;
|
||||
uint32_t module_offset_ = 0;
|
||||
size_t total_size_ = 0;
|
||||
+ bool stream_finished_ = false;
|
||||
|
||||
// We need wire bytes in an array for deserializing cached modules.
|
||||
std::vector<uint8_t> wire_bytes_for_deserializing_;
|
||||
@@ -258,6 +259,8 @@ size_t AsyncStreamingDecoder::DecodingState::ReadBytes(
|
||||
|
||||
void AsyncStreamingDecoder::Finish() {
|
||||
TRACE_STREAMING("Finish\n");
|
||||
+ DCHECK(!stream_finished_);
|
||||
+ stream_finished_ = true;
|
||||
if (!ok()) return;
|
||||
|
||||
if (deserializing()) {
|
||||
@@ -298,6 +301,8 @@ void AsyncStreamingDecoder::Finish() {
|
||||
|
||||
void AsyncStreamingDecoder::Abort() {
|
||||
TRACE_STREAMING("Abort\n");
|
||||
+ if (stream_finished_) return;
|
||||
+ stream_finished_ = true;
|
||||
if (!ok()) return; // Failed already.
|
||||
processor_->OnAbort();
|
||||
Fail();
|
||||
819
patches/v8/cherry-pick-815b12dfb5ec.patch
Normal file
819
patches/v8/cherry-pick-815b12dfb5ec.patch
Normal file
@@ -0,0 +1,819 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: "ishell@chromium.org" <ishell@chromium.org>
|
||||
Date: Tue, 27 Oct 2020 13:13:08 +0100
|
||||
Subject: Merged: [runtime] Fix sorted order of DescriptorArray entries
|
||||
|
||||
Revision: 518d67ad652fc24b7eb03e48bb342f952d4ccf74
|
||||
|
||||
BUG=chromium:1133527
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
R=verwaest@chromium.org
|
||||
|
||||
Change-Id: I10831b27c5c10b9a967e47a5fd08f806ef5d306d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2502328
|
||||
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/8.6@{#34}
|
||||
Cr-Branched-From: a64aed2333abf49e494d2a5ce24bbd14fff19f60-refs/heads/8.6.395@{#1}
|
||||
Cr-Branched-From: a626bc036236c9bf92ac7b87dc40c9e538b087e3-refs/heads/master@{#69472}
|
||||
|
||||
diff --git a/src/codegen/code-stub-assembler.cc b/src/codegen/code-stub-assembler.cc
|
||||
index 6e9b817759dbccd314fec13a911fee40d0b92b80..da0cb08023d1cade3fcb6ef0fb0f5ecaacd125ba 100644
|
||||
--- a/src/codegen/code-stub-assembler.cc
|
||||
+++ b/src/codegen/code-stub-assembler.cc
|
||||
@@ -1772,12 +1772,13 @@ TNode<IntPtrT> CodeStubAssembler::LoadJSReceiverIdentityHash(
|
||||
return var_hash.value();
|
||||
}
|
||||
|
||||
-TNode<Uint32T> CodeStubAssembler::LoadNameHashField(SloppyTNode<Name> name) {
|
||||
- CSA_ASSERT(this, IsName(name));
|
||||
- return LoadObjectField<Uint32T>(name, Name::kHashFieldOffset);
|
||||
+TNode<Uint32T> CodeStubAssembler::LoadNameHashAssumeComputed(TNode<Name> name) {
|
||||
+ TNode<Uint32T> hash_field = LoadNameHashField(name);
|
||||
+ CSA_ASSERT(this, IsClearWord32(hash_field, Name::kHashNotComputedMask));
|
||||
+ return Unsigned(Word32Shr(hash_field, Int32Constant(Name::kHashShift)));
|
||||
}
|
||||
|
||||
-TNode<Uint32T> CodeStubAssembler::LoadNameHash(SloppyTNode<Name> name,
|
||||
+TNode<Uint32T> CodeStubAssembler::LoadNameHash(TNode<Name> name,
|
||||
Label* if_hash_not_computed) {
|
||||
TNode<Uint32T> hash_field = LoadNameHashField(name);
|
||||
if (if_hash_not_computed != nullptr) {
|
||||
@@ -8026,7 +8027,7 @@ void CodeStubAssembler::LookupBinary(TNode<Name> unique_name,
|
||||
TNode<Uint32T> limit =
|
||||
Unsigned(Int32Sub(NumberOfEntries<Array>(array), Int32Constant(1)));
|
||||
TVARIABLE(Uint32T, var_high, limit);
|
||||
- TNode<Uint32T> hash = LoadNameHashField(unique_name);
|
||||
+ TNode<Uint32T> hash = LoadNameHashAssumeComputed(unique_name);
|
||||
CSA_ASSERT(this, Word32NotEqual(hash, Int32Constant(0)));
|
||||
|
||||
// Assume non-empty array.
|
||||
@@ -8044,7 +8045,7 @@ void CodeStubAssembler::LookupBinary(TNode<Name> unique_name,
|
||||
TNode<Uint32T> sorted_key_index = GetSortedKeyIndex<Array>(array, mid);
|
||||
TNode<Name> mid_name = GetKey<Array>(array, sorted_key_index);
|
||||
|
||||
- TNode<Uint32T> mid_hash = LoadNameHashField(mid_name);
|
||||
+ TNode<Uint32T> mid_hash = LoadNameHashAssumeComputed(mid_name);
|
||||
|
||||
Label mid_greater(this), mid_less(this), merge(this);
|
||||
Branch(Uint32GreaterThanOrEqual(mid_hash, hash), &mid_greater, &mid_less);
|
||||
@@ -8071,7 +8072,7 @@ void CodeStubAssembler::LookupBinary(TNode<Name> unique_name,
|
||||
TNode<Uint32T> sort_index =
|
||||
GetSortedKeyIndex<Array>(array, var_low.value());
|
||||
TNode<Name> current_name = GetKey<Array>(array, sort_index);
|
||||
- TNode<Uint32T> current_hash = LoadNameHashField(current_name);
|
||||
+ TNode<Uint32T> current_hash = LoadNameHashAssumeComputed(current_name);
|
||||
GotoIf(Word32NotEqual(current_hash, hash), if_not_found);
|
||||
Label next(this);
|
||||
GotoIf(TaggedNotEqual(current_name, unique_name), &next);
|
||||
diff --git a/src/codegen/code-stub-assembler.h b/src/codegen/code-stub-assembler.h
|
||||
index a13699939942dd3260e98dff678566be2c8b4346..99a30c9ad95d4e36e25004f93472cf73130e9cdc 100644
|
||||
--- a/src/codegen/code-stub-assembler.h
|
||||
+++ b/src/codegen/code-stub-assembler.h
|
||||
@@ -1322,13 +1322,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
// Check if the map is set for slow properties.
|
||||
TNode<BoolT> IsDictionaryMap(SloppyTNode<Map> map);
|
||||
|
||||
- // Load the hash field of a name as an uint32 value.
|
||||
- TNode<Uint32T> LoadNameHashField(SloppyTNode<Name> name);
|
||||
- // Load the hash value of a name as an uint32 value.
|
||||
+ // Load the Name::hash() value of a name as an uint32 value.
|
||||
// If {if_hash_not_computed} label is specified then it also checks if
|
||||
// hash is actually computed.
|
||||
- TNode<Uint32T> LoadNameHash(SloppyTNode<Name> name,
|
||||
+ TNode<Uint32T> LoadNameHash(TNode<Name> name,
|
||||
Label* if_hash_not_computed = nullptr);
|
||||
+ TNode<Uint32T> LoadNameHashAssumeComputed(TNode<Name> name);
|
||||
|
||||
// Load length field of a String object as Smi value.
|
||||
TNode<Smi> LoadStringLengthAsSmi(TNode<String> string);
|
||||
diff --git a/src/diagnostics/objects-debug.cc b/src/diagnostics/objects-debug.cc
|
||||
index f94dd8a3c6a148ee53d49eae668ca7e3b85e41ff..185cf31d8cfda1207d0963904fb719f19c1e95c8 100644
|
||||
--- a/src/diagnostics/objects-debug.cc
|
||||
+++ b/src/diagnostics/objects-debug.cc
|
||||
@@ -1662,12 +1662,13 @@ bool DescriptorArray::IsSortedNoDuplicates() {
|
||||
uint32_t current = 0;
|
||||
for (int i = 0; i < number_of_descriptors(); i++) {
|
||||
Name key = GetSortedKey(i);
|
||||
+ CHECK(key.HasHashCode());
|
||||
if (key == current_key) {
|
||||
Print();
|
||||
return false;
|
||||
}
|
||||
current_key = key;
|
||||
- uint32_t hash = GetSortedKey(i).Hash();
|
||||
+ uint32_t hash = key.hash();
|
||||
if (hash < current) {
|
||||
Print();
|
||||
return false;
|
||||
@@ -1685,7 +1686,8 @@ bool TransitionArray::IsSortedNoDuplicates() {
|
||||
|
||||
for (int i = 0; i < number_of_transitions(); i++) {
|
||||
Name key = GetSortedKey(i);
|
||||
- uint32_t hash = key.Hash();
|
||||
+ CHECK(key.HasHashCode());
|
||||
+ uint32_t hash = key.hash();
|
||||
PropertyKind kind = kData;
|
||||
PropertyAttributes attributes = NONE;
|
||||
if (!TransitionsAccessor::IsSpecialTransition(key.GetReadOnlyRoots(),
|
||||
diff --git a/src/objects/descriptor-array-inl.h b/src/objects/descriptor-array-inl.h
|
||||
index d9e3408dd96aed4f798176a38ae4f0eade1c6c89..a7c6443a05fa7debc1841fb259ff1bc98ba7e184 100644
|
||||
--- a/src/objects/descriptor-array-inl.h
|
||||
+++ b/src/objects/descriptor-array-inl.h
|
||||
@@ -228,7 +228,7 @@ void DescriptorArray::Append(Descriptor* desc) {
|
||||
|
||||
for (insertion = descriptor_number; insertion > 0; --insertion) {
|
||||
Name key = GetSortedKey(insertion - 1);
|
||||
- if (key.Hash() <= hash) break;
|
||||
+ if (key.hash() <= hash) break;
|
||||
SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
|
||||
}
|
||||
|
||||
diff --git a/src/objects/descriptor-array.h b/src/objects/descriptor-array.h
|
||||
index f68948192900d901743548943e1df82567ade2ba..890863d5a01268756d5aa94037925120652cb1bd 100644
|
||||
--- a/src/objects/descriptor-array.h
|
||||
+++ b/src/objects/descriptor-array.h
|
||||
@@ -113,7 +113,7 @@ class DescriptorArray
|
||||
int slack = 0);
|
||||
|
||||
// Sort the instance descriptors by the hash codes of their keys.
|
||||
- void Sort();
|
||||
+ V8_EXPORT_PRIVATE void Sort();
|
||||
|
||||
// Search the instance descriptors for given name. {concurrent_search} signals
|
||||
// if we are doing the search on a background thread. If so, we will sacrifice
|
||||
diff --git a/src/objects/fixed-array-inl.h b/src/objects/fixed-array-inl.h
|
||||
index a49483ebc6490dafdf13301dd991ffc301037476..adde6c7c1f7958643c46aedf8be33300d36f6306 100644
|
||||
--- a/src/objects/fixed-array-inl.h
|
||||
+++ b/src/objects/fixed-array-inl.h
|
||||
@@ -217,7 +217,7 @@ int BinarySearch(T* array, Name name, int valid_entries,
|
||||
// index). After doing the binary search and getting the correct internal
|
||||
// index we check to have the index lower than valid_entries, if needed.
|
||||
int high = array->number_of_entries() - 1;
|
||||
- uint32_t hash = name.hash_field();
|
||||
+ uint32_t hash = name.hash();
|
||||
int limit = high;
|
||||
|
||||
DCHECK(low <= high);
|
||||
@@ -225,7 +225,7 @@ int BinarySearch(T* array, Name name, int valid_entries,
|
||||
while (low != high) {
|
||||
int mid = low + (high - low) / 2;
|
||||
Name mid_name = array->GetSortedKey(mid);
|
||||
- uint32_t mid_hash = mid_name.hash_field();
|
||||
+ uint32_t mid_hash = mid_name.hash();
|
||||
|
||||
if (mid_hash >= hash) {
|
||||
high = mid;
|
||||
@@ -237,7 +237,7 @@ int BinarySearch(T* array, Name name, int valid_entries,
|
||||
for (; low <= limit; ++low) {
|
||||
int sort_index = array->GetSortedKeyIndex(low);
|
||||
Name entry = array->GetKey(InternalIndex(sort_index));
|
||||
- uint32_t current_hash = entry.hash_field();
|
||||
+ uint32_t current_hash = entry.hash();
|
||||
if (current_hash != hash) {
|
||||
// 'search_mode == ALL_ENTRIES' here and below is not needed since
|
||||
// 'out_insertion_index != nullptr' implies 'search_mode == ALL_ENTRIES'.
|
||||
@@ -269,12 +269,12 @@ template <SearchMode search_mode, typename T>
|
||||
int LinearSearch(T* array, Name name, int valid_entries,
|
||||
int* out_insertion_index) {
|
||||
if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
|
||||
- uint32_t hash = name.hash_field();
|
||||
+ uint32_t hash = name.hash();
|
||||
int len = array->number_of_entries();
|
||||
for (int number = 0; number < len; number++) {
|
||||
int sorted_index = array->GetSortedKeyIndex(number);
|
||||
Name entry = array->GetKey(InternalIndex(sorted_index));
|
||||
- uint32_t current_hash = entry.hash_field();
|
||||
+ uint32_t current_hash = entry.hash();
|
||||
if (current_hash > hash) {
|
||||
*out_insertion_index = sorted_index;
|
||||
return T::kNotFound;
|
||||
diff --git a/src/objects/name-inl.h b/src/objects/name-inl.h
|
||||
index 0735b4e506fbcb453d4e1a5a832225ca83ca1b96..ffcd287fd37454e3449b5064b4aa37196dadfdbd 100644
|
||||
--- a/src/objects/name-inl.h
|
||||
+++ b/src/objects/name-inl.h
|
||||
@@ -94,6 +94,12 @@ uint32_t Name::Hash() {
|
||||
return String::cast(*this).ComputeAndSetHash();
|
||||
}
|
||||
|
||||
+uint32_t Name::hash() const {
|
||||
+ uint32_t field = hash_field();
|
||||
+ DCHECK(IsHashFieldComputed(field));
|
||||
+ return field >> kHashShift;
|
||||
+}
|
||||
+
|
||||
DEF_GETTER(Name, IsInterestingSymbol, bool) {
|
||||
return IsSymbol(isolate) && Symbol::cast(*this).is_interesting_symbol();
|
||||
}
|
||||
diff --git a/src/objects/name.h b/src/objects/name.h
|
||||
index 533d8b000ebfa0ef714b61a021de7fc3d0d456f8..6309de9d4ca4502d30c482455103dd16645e6401 100644
|
||||
--- a/src/objects/name.h
|
||||
+++ b/src/objects/name.h
|
||||
@@ -23,9 +23,15 @@ class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
|
||||
// Tells whether the hash code has been computed.
|
||||
inline bool HasHashCode();
|
||||
|
||||
- // Returns a hash value used for the property table
|
||||
+ // Returns a hash value used for the property table. Ensures that the hash
|
||||
+ // value is computed.
|
||||
+ // TODO(ishell): rename to EnsureHash().
|
||||
inline uint32_t Hash();
|
||||
|
||||
+ // Returns a hash value used for the property table (same as Hash()), assumes
|
||||
+ // the hash is already computed.
|
||||
+ inline uint32_t hash() const;
|
||||
+
|
||||
// Equality operations.
|
||||
inline bool Equals(Name other);
|
||||
inline static bool Equals(Isolate* isolate, Handle<Name> one,
|
||||
diff --git a/src/objects/objects.cc b/src/objects/objects.cc
|
||||
index 5e0c831f73b6ccbe40c556497f5ba6fbc9f42b48..54b19d6cdc5ff1f7bd73605a09681c199892b9eb 100644
|
||||
--- a/src/objects/objects.cc
|
||||
+++ b/src/objects/objects.cc
|
||||
@@ -4357,16 +4357,16 @@ void DescriptorArray::Sort() {
|
||||
// Reset sorting since the descriptor array might contain invalid pointers.
|
||||
for (int i = 0; i < len; ++i) SetSortedKey(i, i);
|
||||
// Bottom-up max-heap construction.
|
||||
- // Index of the last node with children
|
||||
+ // Index of the last node with children.
|
||||
const int max_parent_index = (len / 2) - 1;
|
||||
for (int i = max_parent_index; i >= 0; --i) {
|
||||
int parent_index = i;
|
||||
- const uint32_t parent_hash = GetSortedKey(i).Hash();
|
||||
+ const uint32_t parent_hash = GetSortedKey(i).hash();
|
||||
while (parent_index <= max_parent_index) {
|
||||
int child_index = 2 * parent_index + 1;
|
||||
- uint32_t child_hash = GetSortedKey(child_index).Hash();
|
||||
+ uint32_t child_hash = GetSortedKey(child_index).hash();
|
||||
if (child_index + 1 < len) {
|
||||
- uint32_t right_child_hash = GetSortedKey(child_index + 1).Hash();
|
||||
+ uint32_t right_child_hash = GetSortedKey(child_index + 1).hash();
|
||||
if (right_child_hash > child_hash) {
|
||||
child_index++;
|
||||
child_hash = right_child_hash;
|
||||
@@ -4385,13 +4385,13 @@ void DescriptorArray::Sort() {
|
||||
SwapSortedKeys(0, i);
|
||||
// Shift down the new top element.
|
||||
int parent_index = 0;
|
||||
- const uint32_t parent_hash = GetSortedKey(parent_index).Hash();
|
||||
+ const uint32_t parent_hash = GetSortedKey(parent_index).hash();
|
||||
const int max_parent_index = (i / 2) - 1;
|
||||
while (parent_index <= max_parent_index) {
|
||||
int child_index = parent_index * 2 + 1;
|
||||
- uint32_t child_hash = GetSortedKey(child_index).Hash();
|
||||
+ uint32_t child_hash = GetSortedKey(child_index).hash();
|
||||
if (child_index + 1 < i) {
|
||||
- uint32_t right_child_hash = GetSortedKey(child_index + 1).Hash();
|
||||
+ uint32_t right_child_hash = GetSortedKey(child_index + 1).hash();
|
||||
if (right_child_hash > child_hash) {
|
||||
child_index++;
|
||||
child_hash = right_child_hash;
|
||||
diff --git a/src/objects/transitions-inl.h b/src/objects/transitions-inl.h
|
||||
index 5694d66d948325bb139b67a3a34c22759224d139..09157b7f5d0051b80e60de51f358d4fd5bde0b99 100644
|
||||
--- a/src/objects/transitions-inl.h
|
||||
+++ b/src/objects/transitions-inl.h
|
||||
@@ -169,12 +169,20 @@ int TransitionArray::SearchNameForTesting(Name name, int* out_insertion_index) {
|
||||
return SearchName(name, out_insertion_index);
|
||||
}
|
||||
|
||||
+Map TransitionArray::SearchAndGetTargetForTesting(
|
||||
+ PropertyKind kind, Name name, PropertyAttributes attributes) {
|
||||
+ return SearchAndGetTarget(kind, name, attributes);
|
||||
+}
|
||||
+
|
||||
int TransitionArray::SearchSpecial(Symbol symbol, int* out_insertion_index) {
|
||||
return SearchName(symbol, out_insertion_index);
|
||||
}
|
||||
|
||||
int TransitionArray::SearchName(Name name, int* out_insertion_index) {
|
||||
DCHECK(name.IsUniqueName());
|
||||
+ // The name is taken from DescriptorArray, so it must already has a computed
|
||||
+ // hash.
|
||||
+ DCHECK(name.HasHashCode());
|
||||
return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(),
|
||||
out_insertion_index);
|
||||
}
|
||||
diff --git a/src/objects/transitions.cc b/src/objects/transitions.cc
|
||||
index 1309ca82be544dced9d636f52519d49e70fbc1a3..93d43f42d97ebc53adb6f5927ff92bbb82ba57aa 100644
|
||||
--- a/src/objects/transitions.cc
|
||||
+++ b/src/objects/transitions.cc
|
||||
@@ -604,8 +604,8 @@ void TransitionArray::Sort() {
|
||||
temp_kind = details.kind();
|
||||
temp_attributes = details.attributes();
|
||||
}
|
||||
- int cmp = CompareKeys(temp_key, temp_key.Hash(), temp_kind,
|
||||
- temp_attributes, key, key.Hash(), kind, attributes);
|
||||
+ int cmp = CompareKeys(temp_key, temp_key.hash(), temp_kind,
|
||||
+ temp_attributes, key, key.hash(), kind, attributes);
|
||||
if (cmp > 0) {
|
||||
SetKey(j + 1, temp_key);
|
||||
SetRawTarget(j + 1, temp_target);
|
||||
diff --git a/src/objects/transitions.h b/src/objects/transitions.h
|
||||
index 7bc4d70a35da1e20120cc2f55710ecb9155fd72c..26d29f4cf5ac5c333d95503ab484a9c3b4b1a2fa 100644
|
||||
--- a/src/objects/transitions.h
|
||||
+++ b/src/objects/transitions.h
|
||||
@@ -143,6 +143,9 @@ class V8_EXPORT_PRIVATE TransitionsAccessor {
|
||||
return encoding_;
|
||||
}
|
||||
|
||||
+
|
||||
+ inline TransitionArray transitions();
|
||||
+
|
||||
private:
|
||||
friend class MarkCompactCollector; // For HasSimpleTransitionTo.
|
||||
friend class TransitionArray;
|
||||
@@ -175,8 +178,6 @@ class V8_EXPORT_PRIVATE TransitionsAccessor {
|
||||
void TraverseTransitionTreeInternal(TraverseCallback callback, void* data,
|
||||
DisallowHeapAllocation* no_gc);
|
||||
|
||||
- inline TransitionArray transitions();
|
||||
-
|
||||
Isolate* isolate_;
|
||||
Handle<Map> map_handle_;
|
||||
Map map_;
|
||||
@@ -231,7 +232,7 @@ class TransitionArray : public WeakFixedArray {
|
||||
V8_EXPORT_PRIVATE bool IsSortedNoDuplicates();
|
||||
#endif
|
||||
|
||||
- void Sort();
|
||||
+ V8_EXPORT_PRIVATE void Sort();
|
||||
|
||||
void PrintInternal(std::ostream& os);
|
||||
|
||||
@@ -260,6 +261,9 @@ class TransitionArray : public WeakFixedArray {
|
||||
inline int SearchNameForTesting(Name name,
|
||||
int* out_insertion_index = nullptr);
|
||||
|
||||
+ inline Map SearchAndGetTargetForTesting(PropertyKind kind, Name name,
|
||||
+ PropertyAttributes attributes);
|
||||
+
|
||||
private:
|
||||
friend class Factory;
|
||||
friend class MarkCompactCollector;
|
||||
@@ -296,8 +300,8 @@ class TransitionArray : public WeakFixedArray {
|
||||
int Search(PropertyKind kind, Name name, PropertyAttributes attributes,
|
||||
int* out_insertion_index = nullptr);
|
||||
|
||||
- Map SearchAndGetTarget(PropertyKind kind, Name name,
|
||||
- PropertyAttributes attributes);
|
||||
+ V8_EXPORT_PRIVATE Map SearchAndGetTarget(PropertyKind kind, Name name,
|
||||
+ PropertyAttributes attributes);
|
||||
|
||||
// Search a non-property transition (like elements kind, observe or frozen
|
||||
// transitions).
|
||||
diff --git a/test/cctest/BUILD.gn b/test/cctest/BUILD.gn
|
||||
index a55451c6c9c1d87b9dd670e14c16fcdac1d9753d..c4d0d98466d23be18bb2884a22c02531c9a93878 100644
|
||||
--- a/test/cctest/BUILD.gn
|
||||
+++ b/test/cctest/BUILD.gn
|
||||
@@ -205,6 +205,7 @@ v8_source_set("cctest_sources") {
|
||||
"test-debug.cc",
|
||||
"test-decls.cc",
|
||||
"test-deoptimization.cc",
|
||||
+ "test-descriptor-array.cc",
|
||||
"test-dictionary.cc",
|
||||
"test-diy-fp.cc",
|
||||
"test-double.cc",
|
||||
diff --git a/test/cctest/test-descriptor-array.cc b/test/cctest/test-descriptor-array.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7abd36ec6c84959c3da59b8e78d9e4a0ee291632
|
||||
--- /dev/null
|
||||
+++ b/test/cctest/test-descriptor-array.cc
|
||||
@@ -0,0 +1,424 @@
|
||||
+// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "src/base/logging.h"
|
||||
+#include "src/codegen/code-stub-assembler.h"
|
||||
+#include "src/common/globals.h"
|
||||
+#include "src/objects/descriptor-array.h"
|
||||
+#include "src/objects/property-details.h"
|
||||
+#include "src/objects/string-inl.h"
|
||||
+#include "src/objects/transitions-inl.h"
|
||||
+#include "test/cctest/cctest.h"
|
||||
+#include "test/cctest/compiler/code-assembler-tester.h"
|
||||
+#include "test/cctest/compiler/function-tester.h"
|
||||
+#include "test/cctest/test-transitions.h"
|
||||
+
|
||||
+namespace v8 {
|
||||
+namespace internal {
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+using Label = compiler::CodeAssemblerLabel;
|
||||
+template <class T>
|
||||
+using TVariable = compiler::TypedCodeAssemblerVariable<T>;
|
||||
+
|
||||
+Handle<Name> NewNameWithHash(Isolate* isolate, const char* str, uint32_t hash,
|
||||
+ bool is_integer) {
|
||||
+ uint32_t hash_field = hash << Name::kHashShift;
|
||||
+
|
||||
+ static_assert(Name::kNofHashBitFields == 2, "This test needs updating");
|
||||
+ static_assert(Name::kHashNotComputedMask == 1, "This test needs updating");
|
||||
+ static_assert(Name::kIsNotIntegerIndexMask == 2, "This test needs updating");
|
||||
+
|
||||
+ if (!is_integer) {
|
||||
+ hash_field |= Name::kIsNotIntegerIndexMask;
|
||||
+ }
|
||||
+ Handle<Name> name = isolate->factory()->NewOneByteInternalizedString(
|
||||
+ OneByteVector(str), hash_field);
|
||||
+ name->set_hash_field(hash_field);
|
||||
+ CHECK(name->IsUniqueName());
|
||||
+ return name;
|
||||
+}
|
||||
+
|
||||
+template <typename... Args>
|
||||
+MaybeHandle<Object> Call(Isolate* isolate, Handle<JSFunction> function,
|
||||
+ Args... args) {
|
||||
+ const int nof_args = sizeof...(Args);
|
||||
+ Handle<Object> call_args[] = {args...};
|
||||
+ Handle<Object> receiver = isolate->factory()->undefined_value();
|
||||
+ return Execution::Call(isolate, function, receiver, nof_args, call_args);
|
||||
+}
|
||||
+
|
||||
+void CheckDescriptorArrayLookups(Isolate* isolate, Handle<Map> map,
|
||||
+ std::vector<Handle<Name>>& names,
|
||||
+ Handle<JSFunction> csa_lookup) {
|
||||
+ // Test C++ implementation.
|
||||
+ {
|
||||
+ DisallowHeapAllocation no_gc;
|
||||
+ DescriptorArray descriptors = map->instance_descriptors();
|
||||
+ DCHECK(descriptors.IsSortedNoDuplicates());
|
||||
+ int nof_descriptors = descriptors.number_of_descriptors();
|
||||
+
|
||||
+ for (size_t i = 0; i < names.size(); ++i) {
|
||||
+ Name name = *names[i];
|
||||
+ InternalIndex index = descriptors.Search(name, nof_descriptors, false);
|
||||
+ CHECK(index.is_found());
|
||||
+ CHECK_EQ(i, index.as_uint32());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Test CSA implementation.
|
||||
+ if (!FLAG_jitless) {
|
||||
+ for (size_t i = 0; i < names.size(); ++i) {
|
||||
+ Handle<Object> name_index =
|
||||
+ Call(isolate, csa_lookup, map, names[i]).ToHandleChecked();
|
||||
+ CHECK(name_index->IsSmi());
|
||||
+ CHECK_EQ(DescriptorArray::ToKeyIndex(static_cast<int>(i)),
|
||||
+ Smi::ToInt(*name_index));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void CheckTransitionArrayLookups(Isolate* isolate,
|
||||
+ Handle<TransitionArray> transitions,
|
||||
+ std::vector<Handle<Map>>& maps,
|
||||
+ Handle<JSFunction> csa_lookup) {
|
||||
+ // Test C++ implementation.
|
||||
+ {
|
||||
+ DisallowHeapAllocation no_gc;
|
||||
+ DCHECK(transitions->IsSortedNoDuplicates());
|
||||
+
|
||||
+ for (size_t i = 0; i < maps.size(); ++i) {
|
||||
+ Map expected_map = *maps[i];
|
||||
+ Name name =
|
||||
+ expected_map.instance_descriptors().GetKey(expected_map.LastAdded());
|
||||
+
|
||||
+ Map map = transitions->SearchAndGetTargetForTesting(PropertyKind::kData,
|
||||
+ name, NONE);
|
||||
+ CHECK(!map.is_null());
|
||||
+ CHECK_EQ(expected_map, map);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Test CSA implementation.
|
||||
+ if (!FLAG_jitless) {
|
||||
+ for (size_t i = 0; i < maps.size(); ++i) {
|
||||
+ Handle<Map> expected_map = maps[i];
|
||||
+ Handle<Name> name(expected_map->instance_descriptors().GetKey(
|
||||
+ expected_map->LastAdded()),
|
||||
+ isolate);
|
||||
+
|
||||
+ Handle<Object> transition_map =
|
||||
+ Call(isolate, csa_lookup, transitions, name).ToHandleChecked();
|
||||
+ CHECK(transition_map->IsMap());
|
||||
+ CHECK_EQ(*expected_map, *transition_map);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// Creates function with (Map, Name) arguments. Returns Smi with the index of
|
||||
+// the name value of the found descriptor (DescriptorArray::ToKeyIndex())
|
||||
+// or null otherwise.
|
||||
+Handle<JSFunction> CreateCsaDescriptorArrayLookup(Isolate* isolate) {
|
||||
+ // We are not allowed to generate code in jitless mode.
|
||||
+ if (FLAG_jitless) return Handle<JSFunction>();
|
||||
+
|
||||
+ // Preallocate handle for the result in the current handle scope.
|
||||
+ Handle<JSFunction> result_function(JSFunction{}, isolate);
|
||||
+
|
||||
+ const int kNumParams = 2;
|
||||
+
|
||||
+ compiler::CodeAssemblerTester asm_tester(
|
||||
+ isolate, kNumParams + 1, // +1 to include receiver.
|
||||
+ CodeKind::STUB);
|
||||
+ {
|
||||
+ CodeStubAssembler m(asm_tester.state());
|
||||
+
|
||||
+ TNode<Map> map = m.CAST(m.Parameter(1));
|
||||
+ TNode<Name> unique_name = m.CAST(m.Parameter(2));
|
||||
+
|
||||
+ Label passed(&m), failed(&m);
|
||||
+ Label if_found(&m), if_not_found(&m);
|
||||
+ TVariable<IntPtrT> var_name_index(&m);
|
||||
+
|
||||
+ TNode<Uint32T> bit_field3 = m.LoadMapBitField3(map);
|
||||
+ TNode<DescriptorArray> descriptors = m.LoadMapDescriptors(map);
|
||||
+
|
||||
+ m.DescriptorLookup(unique_name, descriptors, bit_field3, &if_found,
|
||||
+ &var_name_index, &if_not_found);
|
||||
+
|
||||
+ m.BIND(&if_found);
|
||||
+ m.Return(m.SmiTag(var_name_index.value()));
|
||||
+
|
||||
+ m.BIND(&if_not_found);
|
||||
+ m.Return(m.NullConstant());
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ compiler::FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
|
||||
+ // Copy function value to a handle created in the outer handle scope.
|
||||
+ *(result_function.location()) = ft.function->ptr();
|
||||
+ }
|
||||
+
|
||||
+ return result_function;
|
||||
+}
|
||||
+
|
||||
+// Creates function with (TransitionArray, Name) arguments. Returns transition
|
||||
+// map if transition is found or null otherwise.
|
||||
+Handle<JSFunction> CreateCsaTransitionArrayLookup(Isolate* isolate) {
|
||||
+ // We are not allowed to generate code in jitless mode.
|
||||
+ if (FLAG_jitless) return Handle<JSFunction>();
|
||||
+
|
||||
+ // Preallocate handle for the result in the current handle scope.
|
||||
+ Handle<JSFunction> result_function(JSFunction{}, isolate);
|
||||
+
|
||||
+ const int kNumParams = 2;
|
||||
+ compiler::CodeAssemblerTester asm_tester(
|
||||
+ isolate, kNumParams + 1, // +1 to include receiver.
|
||||
+ CodeKind::STUB);
|
||||
+ {
|
||||
+ CodeStubAssembler m(asm_tester.state());
|
||||
+
|
||||
+ TNode<TransitionArray> transitions = m.CAST(m.Parameter(1));
|
||||
+ TNode<Name> unique_name = m.CAST(m.Parameter(2));
|
||||
+
|
||||
+ Label passed(&m), failed(&m);
|
||||
+ Label if_found(&m), if_not_found(&m);
|
||||
+ TVariable<IntPtrT> var_name_index(&m);
|
||||
+
|
||||
+ m.TransitionLookup(unique_name, transitions, &if_found, &var_name_index,
|
||||
+ &if_not_found);
|
||||
+
|
||||
+ m.BIND(&if_found);
|
||||
+ {
|
||||
+ STATIC_ASSERT(kData == 0);
|
||||
+ STATIC_ASSERT(NONE == 0);
|
||||
+ const int kKeyToTargetOffset = (TransitionArray::kEntryTargetIndex -
|
||||
+ TransitionArray::kEntryKeyIndex) *
|
||||
+ kTaggedSize;
|
||||
+ TNode<Map> transition_map = m.CAST(m.GetHeapObjectAssumeWeak(
|
||||
+ m.LoadArrayElement(transitions, WeakFixedArray::kHeaderSize,
|
||||
+ var_name_index.value(), kKeyToTargetOffset)));
|
||||
+ m.Return(transition_map);
|
||||
+ }
|
||||
+
|
||||
+ m.BIND(&if_not_found);
|
||||
+ m.Return(m.NullConstant());
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ compiler::FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
|
||||
+ // Copy function value to a handle created in the outer handle scope.
|
||||
+ *(result_function.location()) = ft.function->ptr();
|
||||
+ }
|
||||
+
|
||||
+ return result_function;
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+TEST(DescriptorArrayHashCollisionMassive) {
|
||||
+ CcTest::InitializeVM();
|
||||
+ Isolate* isolate = CcTest::i_isolate();
|
||||
+ HandleScope handle_scope(isolate);
|
||||
+
|
||||
+ static_assert(Name::kNofHashBitFields == 2, "This test needs updating");
|
||||
+
|
||||
+ std::vector<Handle<Name>> names;
|
||||
+
|
||||
+ // Use the same hash value for all names.
|
||||
+ uint32_t hash =
|
||||
+ static_cast<uint32_t>(isolate->GenerateIdentityHash(Name::kHashBitMask));
|
||||
+
|
||||
+ for (int i = 0; i < kMaxNumberOfDescriptors / 2; ++i) {
|
||||
+ // Add pairs of names having the same base hash value but having different
|
||||
+ // values of is_integer bit.
|
||||
+ bool first_is_integer = (i & 1) != 0;
|
||||
+ bool second_is_integer = (i & 2) != 0;
|
||||
+
|
||||
+ names.push_back(NewNameWithHash(isolate, "a", hash, first_is_integer));
|
||||
+ names.push_back(NewNameWithHash(isolate, "b", hash, second_is_integer));
|
||||
+ }
|
||||
+
|
||||
+ // Create descriptor array with the created names by appending fields to some
|
||||
+ // map. DescriptorArray marking relies on the fact that it's attached to an
|
||||
+ // owning map.
|
||||
+ Handle<Map> map = Map::Create(isolate, 0);
|
||||
+
|
||||
+ Handle<FieldType> any_type = FieldType::Any(isolate);
|
||||
+
|
||||
+ for (size_t i = 0; i < names.size(); ++i) {
|
||||
+ map = Map::CopyWithField(isolate, map, names[i], any_type, NONE,
|
||||
+ PropertyConstness::kMutable,
|
||||
+ Representation::Tagged(), OMIT_TRANSITION)
|
||||
+ .ToHandleChecked();
|
||||
+ }
|
||||
+
|
||||
+ Handle<JSFunction> csa_lookup = CreateCsaDescriptorArrayLookup(isolate);
|
||||
+
|
||||
+ CheckDescriptorArrayLookups(isolate, map, names, csa_lookup);
|
||||
+
|
||||
+ // Sort descriptor array and check it again.
|
||||
+ map->instance_descriptors().Sort();
|
||||
+ CheckDescriptorArrayLookups(isolate, map, names, csa_lookup);
|
||||
+}
|
||||
+
|
||||
+TEST(DescriptorArrayHashCollision) {
|
||||
+ CcTest::InitializeVM();
|
||||
+ Isolate* isolate = CcTest::i_isolate();
|
||||
+ HandleScope handle_scope(isolate);
|
||||
+
|
||||
+ static_assert(Name::kNofHashBitFields == 2, "This test needs updating");
|
||||
+
|
||||
+ std::vector<Handle<Name>> names;
|
||||
+ uint32_t hash = 0;
|
||||
+
|
||||
+ for (int i = 0; i < kMaxNumberOfDescriptors / 2; ++i) {
|
||||
+ if (i % 2 == 0) {
|
||||
+ // Change hash value for every pair of names.
|
||||
+ hash = static_cast<uint32_t>(
|
||||
+ isolate->GenerateIdentityHash(Name::kHashBitMask));
|
||||
+ }
|
||||
+
|
||||
+ // Add pairs of names having the same base hash value but having different
|
||||
+ // values of is_integer bit.
|
||||
+ bool first_is_integer = (i & 1) != 0;
|
||||
+ bool second_is_integer = (i & 2) != 0;
|
||||
+
|
||||
+ names.push_back(NewNameWithHash(isolate, "a", hash, first_is_integer));
|
||||
+ names.push_back(NewNameWithHash(isolate, "b", hash, second_is_integer));
|
||||
+ }
|
||||
+
|
||||
+ // Create descriptor array with the created names by appending fields to some
|
||||
+ // map. DescriptorArray marking relies on the fact that it's attached to an
|
||||
+ // owning map.
|
||||
+ Handle<Map> map = Map::Create(isolate, 0);
|
||||
+
|
||||
+ Handle<FieldType> any_type = FieldType::Any(isolate);
|
||||
+
|
||||
+ for (size_t i = 0; i < names.size(); ++i) {
|
||||
+ map = Map::CopyWithField(isolate, map, names[i], any_type, NONE,
|
||||
+ PropertyConstness::kMutable,
|
||||
+ Representation::Tagged(), OMIT_TRANSITION)
|
||||
+ .ToHandleChecked();
|
||||
+ }
|
||||
+
|
||||
+ Handle<JSFunction> csa_lookup = CreateCsaDescriptorArrayLookup(isolate);
|
||||
+
|
||||
+ CheckDescriptorArrayLookups(isolate, map, names, csa_lookup);
|
||||
+
|
||||
+ // Sort descriptor array and check it again.
|
||||
+ map->instance_descriptors().Sort();
|
||||
+ CheckDescriptorArrayLookups(isolate, map, names, csa_lookup);
|
||||
+}
|
||||
+
|
||||
+TEST(TransitionArrayHashCollisionMassive) {
|
||||
+ CcTest::InitializeVM();
|
||||
+ Isolate* isolate = CcTest::i_isolate();
|
||||
+ HandleScope handle_scope(isolate);
|
||||
+
|
||||
+ static_assert(Name::kNofHashBitFields == 2, "This test needs updating");
|
||||
+
|
||||
+ std::vector<Handle<Name>> names;
|
||||
+
|
||||
+ // Use the same hash value for all names.
|
||||
+ uint32_t hash =
|
||||
+ static_cast<uint32_t>(isolate->GenerateIdentityHash(Name::kHashBitMask));
|
||||
+
|
||||
+ for (int i = 0; i < TransitionsAccessor::kMaxNumberOfTransitions / 2; ++i) {
|
||||
+ // Add pairs of names having the same base hash value but having different
|
||||
+ // values of is_integer bit.
|
||||
+ bool first_is_integer = (i & 1) != 0;
|
||||
+ bool second_is_integer = (i & 2) != 0;
|
||||
+
|
||||
+ names.push_back(NewNameWithHash(isolate, "a", hash, first_is_integer));
|
||||
+ names.push_back(NewNameWithHash(isolate, "b", hash, second_is_integer));
|
||||
+ }
|
||||
+
|
||||
+ // Create transitions for each name.
|
||||
+ Handle<Map> root_map = Map::Create(isolate, 0);
|
||||
+
|
||||
+ std::vector<Handle<Map>> maps;
|
||||
+
|
||||
+ Handle<FieldType> any_type = FieldType::Any(isolate);
|
||||
+
|
||||
+ for (size_t i = 0; i < names.size(); ++i) {
|
||||
+ Handle<Map> map =
|
||||
+ Map::CopyWithField(isolate, root_map, names[i], any_type, NONE,
|
||||
+ PropertyConstness::kMutable,
|
||||
+ Representation::Tagged(), INSERT_TRANSITION)
|
||||
+ .ToHandleChecked();
|
||||
+ maps.push_back(map);
|
||||
+ }
|
||||
+
|
||||
+ Handle<JSFunction> csa_lookup = CreateCsaTransitionArrayLookup(isolate);
|
||||
+
|
||||
+ Handle<TransitionArray> transition_array(
|
||||
+ TestTransitionsAccessor(isolate, root_map).transitions(), isolate);
|
||||
+
|
||||
+ CheckTransitionArrayLookups(isolate, transition_array, maps, csa_lookup);
|
||||
+
|
||||
+ // Sort transition array and check it again.
|
||||
+ transition_array->Sort();
|
||||
+ CheckTransitionArrayLookups(isolate, transition_array, maps, csa_lookup);
|
||||
+}
|
||||
+
|
||||
+TEST(TransitionArrayHashCollision) {
|
||||
+ CcTest::InitializeVM();
|
||||
+ Isolate* isolate = CcTest::i_isolate();
|
||||
+ HandleScope handle_scope(isolate);
|
||||
+
|
||||
+ static_assert(Name::kNofHashBitFields == 2, "This test needs updating");
|
||||
+
|
||||
+ std::vector<Handle<Name>> names;
|
||||
+
|
||||
+ // Use the same hash value for all names.
|
||||
+ uint32_t hash =
|
||||
+ static_cast<uint32_t>(isolate->GenerateIdentityHash(Name::kHashBitMask));
|
||||
+
|
||||
+ for (int i = 0; i < TransitionsAccessor::kMaxNumberOfTransitions / 2; ++i) {
|
||||
+ if (i % 2 == 0) {
|
||||
+ // Change hash value for every pair of names.
|
||||
+ hash = static_cast<uint32_t>(
|
||||
+ isolate->GenerateIdentityHash(Name::kHashBitMask));
|
||||
+ }
|
||||
+ // Add pairs of names having the same base hash value but having different
|
||||
+ // values of is_integer bit.
|
||||
+ bool first_is_integer = (i & 1) != 0;
|
||||
+ bool second_is_integer = (i & 2) != 0;
|
||||
+
|
||||
+ names.push_back(NewNameWithHash(isolate, "a", hash, first_is_integer));
|
||||
+ names.push_back(NewNameWithHash(isolate, "b", hash, second_is_integer));
|
||||
+ }
|
||||
+
|
||||
+ // Create transitions for each name.
|
||||
+ Handle<Map> root_map = Map::Create(isolate, 0);
|
||||
+
|
||||
+ std::vector<Handle<Map>> maps;
|
||||
+
|
||||
+ Handle<FieldType> any_type = FieldType::Any(isolate);
|
||||
+
|
||||
+ for (size_t i = 0; i < names.size(); ++i) {
|
||||
+ Handle<Map> map =
|
||||
+ Map::CopyWithField(isolate, root_map, names[i], any_type, NONE,
|
||||
+ PropertyConstness::kMutable,
|
||||
+ Representation::Tagged(), INSERT_TRANSITION)
|
||||
+ .ToHandleChecked();
|
||||
+ maps.push_back(map);
|
||||
+ }
|
||||
+
|
||||
+ Handle<JSFunction> csa_lookup = CreateCsaTransitionArrayLookup(isolate);
|
||||
+
|
||||
+ Handle<TransitionArray> transition_array(
|
||||
+ TestTransitionsAccessor(isolate, root_map).transitions(), isolate);
|
||||
+
|
||||
+ CheckTransitionArrayLookups(isolate, transition_array, maps, csa_lookup);
|
||||
+
|
||||
+ // Sort transition array and check it again.
|
||||
+ transition_array->Sort();
|
||||
+ CheckTransitionArrayLookups(isolate, transition_array, maps, csa_lookup);
|
||||
+}
|
||||
+
|
||||
+} // namespace internal
|
||||
+} // namespace v8
|
||||
diff --git a/test/cctest/test-transitions.h b/test/cctest/test-transitions.h
|
||||
index 724eb3d3c544b5e9535e7a1b14d95eccec34f4cc..66bbbfa76dd7c2aa4c84363a69705d2564fee8a6 100644
|
||||
--- a/test/cctest/test-transitions.h
|
||||
+++ b/test/cctest/test-transitions.h
|
||||
@@ -24,6 +24,8 @@ class TestTransitionsAccessor : public TransitionsAccessor {
|
||||
bool IsFullTransitionArrayEncoding() {
|
||||
return encoding() == kFullTransitionArray;
|
||||
}
|
||||
+
|
||||
+ TransitionArray transitions() { return TransitionsAccessor::transitions(); }
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
127
patches/v8/cherry-pick-8c725f7b5bbf.patch
Normal file
127
patches/v8/cherry-pick-8c725f7b5bbf.patch
Normal file
@@ -0,0 +1,127 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Thibaud Michaud <thibaudm@chromium.org>
|
||||
Date: Thu, 15 Oct 2020 12:45:34 +0200
|
||||
Subject: Merged: [codegen] Skip invalid optimization in tail calls
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Preparing for tail call is usually done by emitting the gap moves and
|
||||
then moving the stack pointer to its new position. An optimization
|
||||
consists in moving the stack pointer first and transforming some of the
|
||||
moves into pushes. In the attached case it looks like this (arm):
|
||||
|
||||
138 add sp, sp, #40
|
||||
13c str r6, [sp, #-4]!
|
||||
140 str r6, [sp, #-4]!
|
||||
144 str r6, [sp, #-4]!
|
||||
148 str r6, [sp, #-4]!
|
||||
14c str r6, [sp, #-4]!
|
||||
...
|
||||
160 vldr d1, [sp - 4*3]
|
||||
|
||||
The last line is a gap reload, but because the stack pointer was already
|
||||
moved, the slot is now below the stack pointer. This is invalid and
|
||||
triggers this DCHECK:
|
||||
|
||||
Fatal error in ../../v8/src/codegen/arm/assembler-arm.cc, line 402
|
||||
Debug check failed: 0 <= offset (0 vs. -12).
|
||||
|
||||
A comment already explains that we skip the optimization if the gap
|
||||
contains stack moves to prevent this, but the code only checks for
|
||||
non-FP slots. This is fixed by replacing "source.IsStackSlot()" with
|
||||
"source.IsAnyStackSlot()":
|
||||
|
||||
108 vldr d1, [sp + 4*2]
|
||||
...
|
||||
118 str r0, [sp, #+36]
|
||||
11c str r0, [sp, #+32]
|
||||
120 str r0, [sp, #+28]
|
||||
124 str r0, [sp, #+24]
|
||||
128 str r0, [sp, #+20]
|
||||
...
|
||||
134 add sp, sp, #20
|
||||
|
||||
TBR=jgruber@chromium.org
|
||||
|
||||
(cherry picked from commit 7506e063d0d7fb00e4b9c06735c91e1953296867)
|
||||
|
||||
Change-Id: I66ed6187755af956e245207e940c83ea0697a5e6
|
||||
Bug: chromium:1137608
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2505976
|
||||
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
|
||||
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/8.6@{#42}
|
||||
Cr-Branched-From: a64aed2333abf49e494d2a5ce24bbd14fff19f60-refs/heads/8.6.395@{#1}
|
||||
Cr-Branched-From: a626bc036236c9bf92ac7b87dc40c9e538b087e3-refs/heads/master@{#69472}
|
||||
|
||||
diff --git a/src/compiler/backend/code-generator.cc b/src/compiler/backend/code-generator.cc
|
||||
index 83dccf69e82dd144a1ca4720947104b1960ae812..5596058c00543744c35da8f55c8ac9563fa15560 100644
|
||||
--- a/src/compiler/backend/code-generator.cc
|
||||
+++ b/src/compiler/backend/code-generator.cc
|
||||
@@ -609,8 +609,8 @@ void CodeGenerator::GetPushCompatibleMoves(Instruction* instr,
|
||||
// then the full gap resolver must be used since optimization with
|
||||
// pushes don't participate in the parallel move and might clobber
|
||||
// values needed for the gap resolve.
|
||||
- if (source.IsStackSlot() && LocationOperand::cast(source).index() >=
|
||||
- first_push_compatible_index) {
|
||||
+ if (source.IsAnyStackSlot() && LocationOperand::cast(source).index() >=
|
||||
+ first_push_compatible_index) {
|
||||
pushes->clear();
|
||||
return;
|
||||
}
|
||||
diff --git a/test/mjsunit/regress/wasm/regress-1137608.js b/test/mjsunit/regress/wasm/regress-1137608.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5011dced2f70ffbe2b6096a4e1863f434c8898a8
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/regress/wasm/regress-1137608.js
|
||||
@@ -0,0 +1,46 @@
|
||||
+// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+//
|
||||
+// Flags: --no-liftoff --experimental-wasm-return-call --experimental-wasm-threads
|
||||
+
|
||||
+load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
+
|
||||
+(function Regress1137608() {
|
||||
+ print(arguments.callee.name);
|
||||
+ let builder = new WasmModuleBuilder();
|
||||
+ let sig0 = builder.addType(kSig_i_iii);
|
||||
+ let sig1 = builder.addType(makeSig([kWasmF64, kWasmF64, kWasmI32,
|
||||
+ kWasmI32, kWasmI32, kWasmF32, kWasmI32, kWasmF64, kWasmI32, kWasmF32,
|
||||
+ kWasmI32, kWasmF32, kWasmI32, kWasmF64, kWasmI32], [kWasmI32]));
|
||||
+ let main = builder.addFunction("main", sig0)
|
||||
+ .addBody([
|
||||
+ kExprI64Const, 0,
|
||||
+ kExprF64UConvertI64,
|
||||
+ kExprF64Const, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
|
||||
+ kExprF64Const, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ kExprF64Mul,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprF64Const, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ kExprF64StoreMem, 0x00, 0xb0, 0xe0, 0xc0, 0x81, 0x03,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprF32Const, 0x00, 0x00, 0x00, 0x00,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprF32Const, 0x00, 0x00, 0x00, 0x00,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprF32Const, 0x00, 0x00, 0x00, 0x00,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ kExprI32Const, 0,
|
||||
+ kExprI32Const, 2,
|
||||
+ kExprReturnCallIndirect, sig1, kTableZero]).exportFunc();
|
||||
+ builder.addFunction("f", sig1).addBody([kExprI32Const, 0]);
|
||||
+ builder.addTable(kWasmAnyFunc, 4, 4);
|
||||
+ builder.addMemory(16, 32, false, true);
|
||||
+ let module = new WebAssembly.Module(builder.toBuffer());
|
||||
+ let instance = new WebAssembly.Instance(module);
|
||||
+})();
|
||||
134
patches/v8/perf_make_getpositioninfoslow_faster.patch
Normal file
134
patches/v8/perf_make_getpositioninfoslow_faster.patch
Normal file
@@ -0,0 +1,134 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Kerr <charles@charleskerr.com>
|
||||
Date: Mon, 26 Oct 2020 16:53:25 -0500
|
||||
Subject: perf: make GetPositionInfoSlow() faster
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Halve the number of lookups in ExtractLocationForJSFunction() by calling
|
||||
GetPositionInfo() directly instead of making separate calls for column
|
||||
and line number.
|
||||
|
||||
Improve the efficiency of position lookups in slow mode. The current
|
||||
code does a linear walk through the source by calling String::Get() for
|
||||
each character. This PR also does a linear walk, but avoids the overhead
|
||||
of multiple Get() calls by pulling the String's flat content into a
|
||||
local vector and walking through that.
|
||||
|
||||
Downstream Electron discussion of this can be found at
|
||||
https://github.com/electron/electron/issues/24509
|
||||
|
||||
Change-Id: I22b034dc1bfe967164d2f8515a9a0c1d7f043c83
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2496065
|
||||
Commit-Queue: Simon Zünd <szuend@chromium.org>
|
||||
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
|
||||
Reviewed-by: Simon Zünd <szuend@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#70783}
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index 7c43c60fc13af2a793547a9e5ef689e380ef565f..31a46b9bec0757c78650124793ba30def5f438f7 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -69,6 +69,7 @@ Bert Belder <bertbelder@gmail.com>
|
||||
Burcu Dogan <burcujdogan@gmail.com>
|
||||
Caitlin Potter <caitpotter88@gmail.com>
|
||||
Craig Schlenter <craig.schlenter@gmail.com>
|
||||
+Charles Kerr <charles@charleskerr.com>
|
||||
Chengzhong Wu <legendecas@gmail.com>
|
||||
Choongwoo Han <cwhan.tunz@gmail.com>
|
||||
Chris Nardi <hichris123@gmail.com>
|
||||
diff --git a/src/objects/objects.cc b/src/objects/objects.cc
|
||||
index 3ef1067d9f956cba708475aa2beb87dcc5df261b..5e0c831f73b6ccbe40c556497f5ba6fbc9f42b48 100644
|
||||
--- a/src/objects/objects.cc
|
||||
+++ b/src/objects/objects.cc
|
||||
@@ -4785,30 +4785,43 @@ bool Script::ContainsAsmModule() {
|
||||
}
|
||||
|
||||
namespace {
|
||||
-bool GetPositionInfoSlow(const Script script, int position,
|
||||
- Script::PositionInfo* info) {
|
||||
- if (!script.source().IsString()) return false;
|
||||
- if (position < 0) position = 0;
|
||||
|
||||
- String source_string = String::cast(script.source());
|
||||
+template <typename Char>
|
||||
+bool GetPositionInfoSlowImpl(const Vector<Char>& source, int position,
|
||||
+ Script::PositionInfo* info) {
|
||||
+ if (position < 0) {
|
||||
+ position = 0;
|
||||
+ }
|
||||
int line = 0;
|
||||
- int line_start = 0;
|
||||
- int len = source_string.length();
|
||||
- for (int pos = 0; pos <= len; ++pos) {
|
||||
- if (pos == len || source_string.Get(pos) == '\n') {
|
||||
- if (position <= pos) {
|
||||
- info->line = line;
|
||||
- info->column = position - line_start;
|
||||
- info->line_start = line_start;
|
||||
- info->line_end = pos;
|
||||
- return true;
|
||||
- }
|
||||
- line++;
|
||||
- line_start = pos + 1;
|
||||
+ const auto begin = std::cbegin(source);
|
||||
+ const auto end = std::cend(source);
|
||||
+ for (auto line_begin = begin; line_begin < end;) {
|
||||
+ const auto line_end = std::find(line_begin, end, '\n');
|
||||
+ if (position <= (line_end - begin)) {
|
||||
+ info->line = line;
|
||||
+ info->column = static_cast<int>((begin + position) - line_begin);
|
||||
+ info->line_start = static_cast<int>(line_begin - begin);
|
||||
+ info->line_end = static_cast<int>(line_end - begin);
|
||||
+ return true;
|
||||
}
|
||||
+ ++line;
|
||||
+ line_begin = line_end + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
+bool GetPositionInfoSlow(const Script script, int position,
|
||||
+ const DisallowHeapAllocation& no_gc,
|
||||
+ Script::PositionInfo* info) {
|
||||
+ if (!script.source().IsString()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ auto source = String::cast(script.source());
|
||||
+ const auto flat = source.GetFlatContent(no_gc);
|
||||
+ return flat.IsOneByte()
|
||||
+ ? GetPositionInfoSlowImpl(flat.ToOneByteVector(), position, info)
|
||||
+ : GetPositionInfoSlowImpl(flat.ToUC16Vector(), position, info);
|
||||
+}
|
||||
+
|
||||
} // namespace
|
||||
|
||||
bool Script::GetPositionInfo(int position, PositionInfo* info,
|
||||
@@ -4830,7 +4843,9 @@ bool Script::GetPositionInfo(int position, PositionInfo* info,
|
||||
|
||||
if (line_ends().IsUndefined()) {
|
||||
// Slow mode: we do not have line_ends. We have to iterate through source.
|
||||
- if (!GetPositionInfoSlow(*this, position, info)) return false;
|
||||
+ if (!GetPositionInfoSlow(*this, position, no_allocation, info)) {
|
||||
+ return false;
|
||||
+ }
|
||||
} else {
|
||||
DCHECK(line_ends().IsFixedArray());
|
||||
FixedArray ends = FixedArray::cast(line_ends());
|
||||
diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc
|
||||
index 2fa4f2e5e841bbbf98580dee241fac00899e780e..8f98451488052ba34a59635b707aa5bd3d086161 100644
|
||||
--- a/src/profiler/heap-snapshot-generator.cc
|
||||
+++ b/src/profiler/heap-snapshot-generator.cc
|
||||
@@ -573,9 +573,9 @@ void V8HeapExplorer::ExtractLocationForJSFunction(HeapEntry* entry,
|
||||
Script script = Script::cast(func.shared().script());
|
||||
int scriptId = script.id();
|
||||
int start = func.shared().StartPosition();
|
||||
- int line = script.GetLineNumber(start);
|
||||
- int col = script.GetColumnNumber(start);
|
||||
- snapshot_->AddLocation(entry, scriptId, line, col);
|
||||
+ Script::PositionInfo info;
|
||||
+ script.GetPositionInfo(start, &info, Script::WITH_OFFSET);
|
||||
+ snapshot_->AddLocation(entry, scriptId, info.line, info.column);
|
||||
}
|
||||
|
||||
HeapEntry* V8HeapExplorer::AddEntry(HeapObject object) {
|
||||
@@ -1,7 +1,7 @@
|
||||
[req]
|
||||
default_bits = 4096
|
||||
encrypt_key = no
|
||||
default_md = 512
|
||||
default_md = sha512
|
||||
distinguished_name = req_distinguished_name
|
||||
prompt = no
|
||||
|
||||
|
||||
@@ -145,7 +145,6 @@
|
||||
"parallel/test-v8-flags",
|
||||
"parallel/test-vm-module-basic",
|
||||
"parallel/test-vm-parse-abort-on-uncaught-exception",
|
||||
"parallel/test-vm-sigint",
|
||||
"parallel/test-vm-sigint-existing-handler",
|
||||
"parallel/test-vm-timeout",
|
||||
"parallel/test-whatwg-encoding-custom-textdecoder",
|
||||
|
||||
41
script/push-patch.js
Normal file
41
script/push-patch.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const { createAppAuth } = require('@octokit/auth-app');
|
||||
const cp = require('child_process');
|
||||
|
||||
if (!process.env.CIRCLE_BRANCH) {
|
||||
console.error('Not building for a specific branch, can\'t autopush a patch');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (process.env.CIRCLE_PR_NUMBER) {
|
||||
console.error('Building for a forked PR, can\'t autopush a patch');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const auth = createAppAuth({
|
||||
appId: process.env.PATCH_UP_APP_ID,
|
||||
privateKey: Buffer.from(process.env.PATCH_UP_PRIVATE_KEY, 'base64').toString('utf8'),
|
||||
installationId: process.env.PATCH_UP_INSTALLATION_ID,
|
||||
clientId: process.env.PATCH_UP_CLIENT_ID,
|
||||
clientSecret: process.env.PATCH_UP_CLIENT_SECRET
|
||||
});
|
||||
|
||||
async function main () {
|
||||
const installationAuth = await auth({ type: 'installation' });
|
||||
const remoteURL = `https://x-access-token:${installationAuth.token}@github.com/electron/electron.git`;
|
||||
// NEVER LOG THE OUTPUT OF THIS COMMAND
|
||||
// GIT LEAKS THE ACCESS CREDENTIALS IN CONSOLE LOGS
|
||||
const { status } = cp.spawnSync('git', ['push', '--set-upstream', remoteURL], {
|
||||
stdio: 'ignore'
|
||||
});
|
||||
if (status !== 0) {
|
||||
console.error('Failed to push to target branch');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.mainModule === module) {
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
@@ -379,6 +379,7 @@ async function getBranchNameOfRef (ref, dir) {
|
||||
return (await runGit(dir, ['branch', '--all', '--contains', ref, '--sort', 'version:refname']))
|
||||
.split(/\r?\n/) // split into lines
|
||||
.shift() // we sorted by refname and want the first result
|
||||
.match(/(?:\s?\*\s){0,1}(.*)/)[1] // if present, remove leading '* ' in case we're currently in that branch
|
||||
.match(/(?:.*\/)?(.*)/)[1] // 'remote/origins/10-x-y' -> '10-x-y'
|
||||
.trim();
|
||||
}
|
||||
@@ -396,7 +397,7 @@ const getNotes = async (fromRef, toRef, newVersion) => {
|
||||
const pool = new Pool();
|
||||
const toBranch = await getBranchNameOfRef(toRef, ELECTRON_DIR);
|
||||
|
||||
console.log(`Generating release notes between ${fromRef} and ${toRef} for version ${newVersion} in branch ${toBranch}`);
|
||||
console.log(`Generating release notes between '${fromRef}' and '${toRef}' for version '${newVersion}' in branch '${toBranch}'`);
|
||||
|
||||
// get the electron/electron commits
|
||||
const electron = { owner: 'electron', repo: 'electron', dir: ELECTRON_DIR };
|
||||
|
||||
@@ -29,6 +29,8 @@ PDB_LIST = [
|
||||
os.path.join(RELEASE_DIR, '{0}.exe.pdb'.format(PROJECT_NAME))
|
||||
]
|
||||
|
||||
PDB_LIST += glob.glob(os.path.join(RELEASE_DIR, '*.dll.pdb'))
|
||||
|
||||
NPX_CMD = "npx"
|
||||
if sys.platform == "win32":
|
||||
NPX_CMD += ".cmd"
|
||||
|
||||
@@ -50,7 +50,7 @@ function uploadToGitHub () {
|
||||
console.log(`Error uploading ${fileName} to GitHub, will retry. Error was:`, err);
|
||||
retry++;
|
||||
|
||||
octokit.repos.listAssetsForRelease({
|
||||
octokit.repos.listReleaseAssets({
|
||||
owner: 'electron',
|
||||
repo: targetRepo,
|
||||
release_id: releaseId,
|
||||
|
||||
@@ -20,7 +20,7 @@ sys.path.append(
|
||||
from io import StringIO
|
||||
from zipfile import ZipFile
|
||||
from lib.config import PLATFORM, get_target_arch, get_env_var, s3_config, \
|
||||
get_zip_name
|
||||
get_zip_name, enable_verbose_mode, get_platform_key
|
||||
from lib.util import get_electron_branding, execute, get_electron_version, \
|
||||
scoped_cwd, s3put, get_electron_exec, \
|
||||
get_out_dir, SRC_DIR, ELECTRON_DIR
|
||||
@@ -44,7 +44,9 @@ TOOLCHAIN_PROFILE_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'toolchain
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
if args.upload_to_s3:
|
||||
if args.verbose:
|
||||
enable_verbose_mode()
|
||||
if args.upload_to_s3:
|
||||
utcnow = datetime.datetime.utcnow()
|
||||
args.upload_timestamp = utcnow.strftime('%Y%m%d')
|
||||
|
||||
@@ -76,11 +78,13 @@ def main():
|
||||
shutil.copy2(os.path.join(OUT_DIR, 'symbols.zip'), symbols_zip)
|
||||
upload_electron(release, symbols_zip, args)
|
||||
if PLATFORM == 'darwin':
|
||||
api_path = os.path.join(ELECTRON_DIR, 'electron-api.json')
|
||||
upload_electron(release, api_path, args)
|
||||
if get_platform_key() == 'darwin' and get_target_arch() == 'x64':
|
||||
api_path = os.path.join(ELECTRON_DIR, 'electron-api.json')
|
||||
upload_electron(release, api_path, args)
|
||||
|
||||
ts_defs_path = os.path.join(ELECTRON_DIR, 'electron.d.ts')
|
||||
upload_electron(release, ts_defs_path, args)
|
||||
|
||||
ts_defs_path = os.path.join(ELECTRON_DIR, 'electron.d.ts')
|
||||
upload_electron(release, ts_defs_path, args)
|
||||
dsym_zip = os.path.join(OUT_DIR, DSYM_NAME)
|
||||
shutil.copy2(os.path.join(OUT_DIR, 'dsym.zip'), dsym_zip)
|
||||
upload_electron(release, dsym_zip, args)
|
||||
@@ -149,6 +153,9 @@ def parse_args():
|
||||
action='store_true',
|
||||
default=False,
|
||||
required=False)
|
||||
parser.add_argument('--verbose',
|
||||
action='store_true',
|
||||
help='Mooooorreee logs')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include <glib.h> // for g_setenv()
|
||||
#endif
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/debug/stack_trace.h"
|
||||
#include "base/environment.h"
|
||||
@@ -39,7 +35,6 @@
|
||||
#include "shell/renderer/electron_renderer_client.h"
|
||||
#include "shell/renderer/electron_sandboxed_renderer_client.h"
|
||||
#include "shell/utility/electron_content_utility_client.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
|
||||
@@ -112,12 +107,8 @@ void InvalidParameterHandler(const wchar_t*,
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
// TODO(nornagon): move path provider overriding to its own file in
|
||||
// shell/common
|
||||
namespace electron {
|
||||
|
||||
bool GetDefaultCrashDumpsPath(base::FilePath* path) {
|
||||
base::FilePath cur;
|
||||
if (!base::PathService::Get(DIR_USER_DATA, &cur))
|
||||
@@ -147,12 +138,11 @@ void RegisterPathProvider() {
|
||||
PATH_END);
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
} // namespace
|
||||
|
||||
void LoadResourceBundle(const std::string& locale) {
|
||||
std::string LoadResourceBundle(const std::string& locale) {
|
||||
const bool initialized = ui::ResourceBundle::HasSharedInstance();
|
||||
if (initialized)
|
||||
ui::ResourceBundle::CleanupSharedInstance();
|
||||
DCHECK(!initialized);
|
||||
|
||||
// Load other resource files.
|
||||
base::FilePath pak_dir;
|
||||
@@ -163,12 +153,12 @@ void LoadResourceBundle(const std::string& locale) {
|
||||
base::PathService::Get(base::DIR_MODULE, &pak_dir);
|
||||
#endif
|
||||
|
||||
ui::ResourceBundle::InitSharedInstanceWithLocale(
|
||||
std::string loaded_locale = ui::ResourceBundle::InitSharedInstanceWithLocale(
|
||||
locale, nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
|
||||
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
|
||||
bundle.ReloadLocaleResources(locale);
|
||||
bundle.AddDataPackFromPath(pak_dir.Append(FILE_PATH_LITERAL("resources.pak")),
|
||||
ui::SCALE_FACTOR_NONE);
|
||||
return loaded_locale;
|
||||
}
|
||||
|
||||
ElectronMainDelegate::ElectronMainDelegate() = default;
|
||||
@@ -287,36 +277,6 @@ bool ElectronMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ElectronMainDelegate::PostEarlyInitialization(bool is_running_tests) {
|
||||
std::string custom_locale;
|
||||
ui::ResourceBundle::InitSharedInstanceWithLocale(
|
||||
custom_locale, nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
|
||||
auto* cmd_line = base::CommandLine::ForCurrentProcess();
|
||||
if (cmd_line->HasSwitch(::switches::kLang)) {
|
||||
const std::string locale = cmd_line->GetSwitchValueASCII(::switches::kLang);
|
||||
const base::FilePath locale_file_path =
|
||||
ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale);
|
||||
if (!locale_file_path.empty()) {
|
||||
custom_locale = locale;
|
||||
#if defined(OS_LINUX)
|
||||
/* When built with USE_GLIB, libcc's GetApplicationLocaleInternal() uses
|
||||
* glib's g_get_language_names(), which keys off of getenv("LC_ALL") */
|
||||
g_setenv("LC_ALL", custom_locale.c_str(), TRUE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (custom_locale.empty())
|
||||
l10n_util::OverrideLocaleWithCocoaLocale();
|
||||
#endif
|
||||
|
||||
LoadResourceBundle(custom_locale);
|
||||
|
||||
ElectronBrowserClient::SetApplicationLocale(
|
||||
l10n_util::GetApplicationLocale(custom_locale));
|
||||
}
|
||||
|
||||
void ElectronMainDelegate::PreSandboxStartup() {
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class TracingSamplerProfiler;
|
||||
|
||||
namespace electron {
|
||||
|
||||
void LoadResourceBundle(const std::string& locale);
|
||||
std::string LoadResourceBundle(const std::string& locale);
|
||||
|
||||
class ElectronMainDelegate : public content::ContentMainDelegate {
|
||||
public:
|
||||
@@ -31,7 +31,6 @@ class ElectronMainDelegate : public content::ContentMainDelegate {
|
||||
bool BasicStartupComplete(int* exit_code) override;
|
||||
void PreSandboxStartup() override;
|
||||
void PreCreateMainMessageLoop() override;
|
||||
void PostEarlyInitialization(bool is_running_tests) override;
|
||||
content::ContentBrowserClient* CreateContentBrowserClient() override;
|
||||
content::ContentGpuClient* CreateContentGpuClient() override;
|
||||
content::ContentRendererClient* CreateContentRendererClient() override;
|
||||
|
||||
@@ -12,7 +12,5 @@
|
||||
<string>APPL</string>
|
||||
<key>LSBackgroundOnly</key>
|
||||
<true/>
|
||||
<key>LSRequiresNativeExecution</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -492,10 +492,10 @@ void OnClientCertificateSelected(
|
||||
data.c_str(), data.length(), net::X509Certificate::FORMAT_AUTO);
|
||||
if (!certs.empty()) {
|
||||
scoped_refptr<net::X509Certificate> cert(certs[0].get());
|
||||
for (size_t i = 0; i < identities->size(); ++i) {
|
||||
if (cert->EqualsExcludingChain((*identities)[i]->certificate())) {
|
||||
for (auto& identity : *identities) {
|
||||
if (cert->EqualsExcludingChain(identity->certificate())) {
|
||||
net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
|
||||
std::move((*identities)[i]),
|
||||
std::move(identity),
|
||||
base::BindRepeating(&GotPrivateKey, delegate, std::move(cert)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#include "shell/browser/api/electron_api_browser_view.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
#include "shell/browser/ui/drag_util.h"
|
||||
#include "shell/common/color_util.h"
|
||||
#include "shell/common/gin_converters/gfx_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
@@ -63,11 +66,21 @@ BrowserView::BrowserView(gin::Arguments* args,
|
||||
gin::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
web_preferences.Set("type", "browserView");
|
||||
gin::Handle<class WebContents> web_contents =
|
||||
WebContents::Create(isolate, web_preferences);
|
||||
|
||||
v8::Local<v8::Value> value;
|
||||
|
||||
// Copy the webContents option to webPreferences. This is only used internally
|
||||
// to implement nativeWindowOpen option.
|
||||
if (options.Get("webContents", &value)) {
|
||||
web_preferences.SetHidden("webContents", value);
|
||||
}
|
||||
|
||||
auto web_contents =
|
||||
WebContents::CreateFromWebPreferences(args->isolate(), web_preferences);
|
||||
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
api_web_contents_->AddObserver(this);
|
||||
Observe(web_contents->web_contents());
|
||||
|
||||
view_.reset(
|
||||
@@ -80,6 +93,7 @@ BrowserView::~BrowserView() {
|
||||
if (api_web_contents_) { // destroy() is called
|
||||
// Destroy WebContents asynchronously unless app is shutting down,
|
||||
// because destroy() might be called inside WebContents's event handler.
|
||||
api_web_contents_->RemoveObserver(this);
|
||||
api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down());
|
||||
}
|
||||
}
|
||||
@@ -89,6 +103,11 @@ void BrowserView::WebContentsDestroyed() {
|
||||
web_contents_.Reset();
|
||||
}
|
||||
|
||||
void BrowserView::OnDraggableRegionsUpdated(
|
||||
const std::vector<mojom::DraggableRegionPtr>& regions) {
|
||||
view_->UpdateDraggableRegions(regions);
|
||||
}
|
||||
|
||||
// static
|
||||
gin_helper::WrappableBase* BrowserView::New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args) {
|
||||
|
||||
@@ -7,10 +7,13 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "gin/handle.h"
|
||||
#include "shell/browser/extended_web_contents_observer.h"
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
#include "shell/common/api/api.mojom.h"
|
||||
#include "shell/common/gin_helper/error_thrower.h"
|
||||
#include "shell/common/gin_helper/trackable_object.h"
|
||||
|
||||
@@ -31,7 +34,8 @@ namespace api {
|
||||
class WebContents;
|
||||
|
||||
class BrowserView : public gin_helper::TrackableObject<BrowserView>,
|
||||
public content::WebContentsObserver {
|
||||
public content::WebContentsObserver,
|
||||
public ExtendedWebContentsObserver {
|
||||
public:
|
||||
static gin_helper::WrappableBase* New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args);
|
||||
@@ -51,6 +55,10 @@ class BrowserView : public gin_helper::TrackableObject<BrowserView>,
|
||||
// content::WebContentsObserver:
|
||||
void WebContentsDestroyed() override;
|
||||
|
||||
// ExtendedWebContentsObserver:
|
||||
void OnDraggableRegionsUpdated(
|
||||
const std::vector<mojom::DraggableRegionPtr>& regions) override;
|
||||
|
||||
private:
|
||||
void SetAutoResize(AutoResizeFlags flags);
|
||||
void SetBounds(const gfx::Rect& bounds);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user