mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
164 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37a7155bd8 | ||
|
|
e34bf19dc7 | ||
|
|
63d1afd59c | ||
|
|
6bc1d0c4ec | ||
|
|
dd87075459 | ||
|
|
d2abd19cff | ||
|
|
3ea5a0ba6b | ||
|
|
071c8db510 | ||
|
|
015cc015c8 | ||
|
|
7d4325e0ec | ||
|
|
c465f0296b | ||
|
|
6a75402ee8 | ||
|
|
b6764c0276 | ||
|
|
1856b71bc1 | ||
|
|
302d4829b4 | ||
|
|
c3c2d844d5 | ||
|
|
28eaf77a25 | ||
|
|
68c436a3e5 | ||
|
|
f659fa4f0b | ||
|
|
1fc49a55d6 | ||
|
|
f46b3f48af | ||
|
|
83a933f303 | ||
|
|
133a69f43e | ||
|
|
6ce4445e63 | ||
|
|
8319490c59 | ||
|
|
5dd4d85b60 | ||
|
|
f09df625f2 | ||
|
|
8d59648128 | ||
|
|
f57244d00d | ||
|
|
f47bc6be2b | ||
|
|
8540d7ddf6 | ||
|
|
dc3a2ffd31 | ||
|
|
351b10d179 | ||
|
|
465e599359 | ||
|
|
b6ad975666 | ||
|
|
38a6fb9a53 | ||
|
|
13fd1105c7 | ||
|
|
5f3eae7119 | ||
|
|
b4613cfe9f | ||
|
|
e95a593199 | ||
|
|
9c2eed2333 | ||
|
|
f6798c5e99 | ||
|
|
e3b8dd1d9d | ||
|
|
2b611690f9 | ||
|
|
f2774427f9 | ||
|
|
16bf1edc77 | ||
|
|
f617308c6f | ||
|
|
acc14843cf | ||
|
|
027d803d73 | ||
|
|
34d77ca691 | ||
|
|
2d0d51ec43 | ||
|
|
ef1243803f | ||
|
|
9629d8fc58 | ||
|
|
744e0ead87 | ||
|
|
be8f54ba8a | ||
|
|
ec0b62ea65 | ||
|
|
e4c86842c3 | ||
|
|
771261f6b7 | ||
|
|
8174553f84 | ||
|
|
35561d7fb0 | ||
|
|
3c9318cc17 | ||
|
|
67a565310a | ||
|
|
e29c6aef2c | ||
|
|
d4edab2c9f | ||
|
|
0e0bf5495b | ||
|
|
bb7de2d7a0 | ||
|
|
2dc9091b3e | ||
|
|
9af52185e1 | ||
|
|
52c878b6bc | ||
|
|
7cdf38c3fc | ||
|
|
7a1c596d63 | ||
|
|
c7a7e0f56b | ||
|
|
b0d4474536 | ||
|
|
8ae3f8bf55 | ||
|
|
24e385f54b | ||
|
|
91b8fa26b8 | ||
|
|
105ab32645 | ||
|
|
8e5e91cfc1 | ||
|
|
582eb5c9bd | ||
|
|
8fe397cecc | ||
|
|
972213b032 | ||
|
|
5e36eed062 | ||
|
|
dbe8546e1b | ||
|
|
5462e954b7 | ||
|
|
376812fccd | ||
|
|
a1a1ffca2c | ||
|
|
6aefbacce3 | ||
|
|
9e21ebf6ea | ||
|
|
51bb4c1e7b | ||
|
|
e4fbf3852a | ||
|
|
20fc69ec99 | ||
|
|
d2b758240d | ||
|
|
7351f65482 | ||
|
|
173cc8e904 | ||
|
|
0fca1b536d | ||
|
|
c5bdabbb77 | ||
|
|
df8eb2aeb0 | ||
|
|
7478c82233 | ||
|
|
e60d3a7d27 | ||
|
|
484c90d4eb | ||
|
|
a978735582 | ||
|
|
8335d24684 | ||
|
|
71cd259b7b | ||
|
|
27fb917577 | ||
|
|
b763478ae5 | ||
|
|
8417c5ae41 | ||
|
|
4f3003dd40 | ||
|
|
38ca1aeab7 | ||
|
|
a6636c3ca6 | ||
|
|
20c63a644b | ||
|
|
e446b29afb | ||
|
|
a5c6a79a08 | ||
|
|
bb418b6e06 | ||
|
|
8638e8cea9 | ||
|
|
cb206b8a9f | ||
|
|
47364ace72 | ||
|
|
7746f1d13e | ||
|
|
58dd15f165 | ||
|
|
d9a25cff7c | ||
|
|
018bee38bc | ||
|
|
9f76b99382 | ||
|
|
35be7656ba | ||
|
|
eecda4656e | ||
|
|
22bd03d54b | ||
|
|
a641468b12 | ||
|
|
2764c06d0e | ||
|
|
0d6a3d27c2 | ||
|
|
76e9225c2b | ||
|
|
1e23632184 | ||
|
|
c2b3c974e0 | ||
|
|
9062352dd8 | ||
|
|
ca1d4784b7 | ||
|
|
857f5a8794 | ||
|
|
90c5f930fa | ||
|
|
c5a7ccc48b | ||
|
|
d8802f8b4c | ||
|
|
6fd689eb11 | ||
|
|
2eb43ede35 | ||
|
|
15454fd693 | ||
|
|
de1eef75dc | ||
|
|
7a3541d5af | ||
|
|
6be63fe11e | ||
|
|
bd6b139b16 | ||
|
|
911f966be3 | ||
|
|
5302dcf5ed | ||
|
|
25159f3ee1 | ||
|
|
042f00d25a | ||
|
|
dfc9cb6e7f | ||
|
|
3b1127ccbd | ||
|
|
efdce183d2 | ||
|
|
f1455d26a8 | ||
|
|
ed04f73fc2 | ||
|
|
34ee012262 | ||
|
|
154aee0f3d | ||
|
|
fb6e837110 | ||
|
|
01dd6b61ba | ||
|
|
a13ea19b3c | ||
|
|
d5537f620e | ||
|
|
951c8322a5 | ||
|
|
0c78c21c13 | ||
|
|
bf1fada136 | ||
|
|
40b994cfab | ||
|
|
6ec7b15b06 | ||
|
|
78c2f495ad |
2416
.circleci/build_config.yml
Normal file
2416
.circleci/build_config.yml
Normal file
File diff suppressed because it is too large
Load Diff
2622
.circleci/config.yml
2622
.circleci/config.yml
File diff suppressed because it is too large
Load Diff
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -4,7 +4,7 @@
|
||||
# https://git-scm.com/docs/gitignore
|
||||
|
||||
# Upgrades WG
|
||||
/patches/ @electron/wg-upgrades
|
||||
/patches/ @electron/wg-upgrades @electron/wg-security
|
||||
DEPS @electron/wg-upgrades
|
||||
|
||||
# Releases WG
|
||||
|
||||
6
BUILD.gn
6
BUILD.gn
@@ -187,6 +187,12 @@ action("electron_js2c") {
|
||||
rebase_path(sources, root_build_dir)
|
||||
}
|
||||
|
||||
action("generate_config_gypi") {
|
||||
outputs = [ "$root_gen_dir/config.gypi" ]
|
||||
script = "script/generate-config-gypi.py"
|
||||
args = rebase_path(outputs) + [ target_cpu ]
|
||||
}
|
||||
|
||||
target_gen_default_app_js = "$target_gen_dir/js/default_app"
|
||||
|
||||
typescript_build("default_app_js") {
|
||||
|
||||
@@ -1 +1 @@
|
||||
14.1.0
|
||||
14.2.9
|
||||
@@ -1685,7 +1685,7 @@ current window into a top-level window.
|
||||
|
||||
#### `win.getParentWindow()`
|
||||
|
||||
Returns `BrowserWindow` - The parent window.
|
||||
Returns `BrowserWindow | null` - The parent window or `null` if there is no parent.
|
||||
|
||||
#### `win.getChildWindows()`
|
||||
|
||||
|
||||
@@ -296,6 +296,35 @@ app.whenReady().then(() => {
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
|
||||
if (permission === 'serial') {
|
||||
// Add logic here to determine if permission should be given to allow serial selection
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// Optionally, retrieve previously persisted devices from a persistent store
|
||||
const grantedDevices = fetchGrantedDevices()
|
||||
|
||||
win.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'serial') {
|
||||
if (details.device.vendorId === 123 && details.device.productId === 345) {
|
||||
// Always allow this type of device (this allows skipping the call to `navigator.serial.requestPort` first)
|
||||
return true
|
||||
}
|
||||
|
||||
// Search through the list of devices that have previously been granted permission
|
||||
return grantedDevices.some((grantedDevice) => {
|
||||
return grantedDevice.vendorId === details.device.vendorId &&
|
||||
grantedDevice.productId === details.device.productId &&
|
||||
grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
|
||||
})
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
win.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
|
||||
event.preventDefault()
|
||||
const selectedPort = portList.find((device) => {
|
||||
@@ -587,6 +616,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `permissionGranted` Boolean - Allow or deny the permission.
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
* `externalURL` String (optional) - The url of the `openExternal` request.
|
||||
* `securityOrigin` String (optional) - The security origin of the `media` request.
|
||||
* `mediaTypes` String[] (optional) - The types of media access being requested, elements can be `video`
|
||||
or `audio`
|
||||
* `requestingUrl` String - The last URL the requesting frame loaded
|
||||
@@ -645,9 +675,9 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
|
||||
|
||||
* `handler` Function\<Boolean> | null
|
||||
* `details` Object
|
||||
* `deviceType` String - The type of device that permission is being requested on, can be `hid`.
|
||||
* `deviceType` String - The type of device that permission is being requested on, can be `hid` or `serial`.
|
||||
* `origin` String - The origin URL of the device permission check.
|
||||
* `device` [HIDDevice](structures/hid-device.md) - the device that permission is being requested for.
|
||||
* `device` [HIDDevice](structures/hid-device.md) | [SerialPort](structures/serial-port.md)- the device that permission is being requested for.
|
||||
* `frame` [WebFrameMain](web-frame-main.md) - WebFrameMain checking the device permission.
|
||||
|
||||
Sets the handler which can be used to respond to device permission checks for the `session`.
|
||||
@@ -672,6 +702,8 @@ app.whenReady().then(() => {
|
||||
if (permission === 'hid') {
|
||||
// Add logic here to determine if permission should be given to allow HID selection
|
||||
return true
|
||||
} else if (permission === 'serial') {
|
||||
// Add logic here to determine if permission should be given to allow serial port selection
|
||||
}
|
||||
return false
|
||||
})
|
||||
@@ -692,6 +724,11 @@ app.whenReady().then(() => {
|
||||
grantedDevice.productId === details.device.productId &&
|
||||
grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
|
||||
})
|
||||
} else if (details.deviceType === 'serial') {
|
||||
if (details.device.vendorId === 123 && details.device.productId === 345) {
|
||||
// Always allow this type of device (this allows skipping the call to `navigator.hid.requestDevice` first)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
@@ -731,6 +731,8 @@ first available device will be selected. `callback` should be called with
|
||||
`deviceId` to be selected, passing empty string to `callback` will
|
||||
cancel the request.
|
||||
|
||||
If no event listener is added for this event, all bluetooth requests will be cancelled.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
@@ -1479,8 +1481,8 @@ win.loadURL('http://github.com')
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
// Use default printing options
|
||||
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
|
||||
win.webContents.printToPDF({}).then(data => {
|
||||
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
|
||||
fs.writeFile(pdfPath, data, (error) => {
|
||||
if (error) throw error
|
||||
console.log(`Wrote PDF successfully to ${pdfPath}`)
|
||||
@@ -1595,7 +1597,7 @@ app.whenReady().then(() => {
|
||||
|
||||
* `options` Object (optional)
|
||||
* `mode` String - Opens the devtools with specified dock state, can be
|
||||
`right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
`left`, `right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
In `undocked` mode it's possible to dock back. In `detach` mode it's not.
|
||||
* `activate` Boolean (optional) - Whether to bring the opened devtools window
|
||||
to the foreground. The default is `true`.
|
||||
|
||||
@@ -995,3 +995,78 @@ Emitted when DevTools is focused / opened.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[chrome-webview]: https://developer.chrome.com/docs/extensions/reference/webviewTag/
|
||||
|
||||
### Event: 'context-menu'
|
||||
|
||||
Returns:
|
||||
|
||||
* `params` Object
|
||||
* `x` Integer - x coordinate.
|
||||
* `y` Integer - y coordinate.
|
||||
* `linkURL` String - URL of the link that encloses the node the context menu
|
||||
was invoked on.
|
||||
* `linkText` String - Text associated with the link. May be an empty
|
||||
string if the contents of the link are an image.
|
||||
* `pageURL` String - URL of the top level page that the context menu was
|
||||
invoked on.
|
||||
* `frameURL` String - URL of the subframe that the context menu was invoked
|
||||
on.
|
||||
* `srcURL` String - Source URL for the element that the context menu
|
||||
was invoked on. Elements with source URLs are images, audio and video.
|
||||
* `mediaType` String - Type of the node the context menu was invoked on. Can
|
||||
be `none`, `image`, `audio`, `video`, `canvas`, `file` or `plugin`.
|
||||
* `hasImageContents` Boolean - Whether the context menu was invoked on an image
|
||||
which has non-empty contents.
|
||||
* `isEditable` Boolean - Whether the context is editable.
|
||||
* `selectionText` String - Text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `titleText` String - Title text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `altText` String - Alt text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `suggestedFilename` String - Suggested filename to be used when saving file through 'Save
|
||||
Link As' option of context menu.
|
||||
* `selectionRect` [Rectangle](structures/rectangle.md) - Rect representing the coordinates in the document space of the selection.
|
||||
* `selectionStartOffset` Number - Start position of the selection text.
|
||||
* `referrerPolicy` [Referrer](structures/referrer.md) - The referrer policy of the frame on which the menu is invoked.
|
||||
* `misspelledWord` String - The misspelled word under the cursor, if any.
|
||||
* `dictionarySuggestions` String[] - An array of suggested words to show the
|
||||
user to replace the `misspelledWord`. Only available if there is a misspelled
|
||||
word and spellchecker is enabled.
|
||||
* `frameCharset` String - The character encoding of the frame on which the
|
||||
menu was invoked.
|
||||
* `inputFieldType` String - If the context menu was invoked on an input
|
||||
field, the type of that field. Possible values are `none`, `plainText`,
|
||||
`password`, `other`.
|
||||
* `spellcheckEnabled` Boolean - If the context is editable, whether or not spellchecking is enabled.
|
||||
* `menuSourceType` String - Input source that invoked the context menu.
|
||||
Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`, `longPress`, `longTap`, `touchHandle`, `stylus`, `adjustSelection`, or `adjustSelectionReset`.
|
||||
* `mediaFlags` Object - The flags for the media element the context menu was
|
||||
invoked on.
|
||||
* `inError` Boolean - Whether the media element has crashed.
|
||||
* `isPaused` Boolean - Whether the media element is paused.
|
||||
* `isMuted` Boolean - Whether the media element is muted.
|
||||
* `hasAudio` Boolean - Whether the media element has audio.
|
||||
* `isLooping` Boolean - Whether the media element is looping.
|
||||
* `isControlsVisible` Boolean - Whether the media element's controls are
|
||||
visible.
|
||||
* `canToggleControls` Boolean - Whether the media element's controls are
|
||||
toggleable.
|
||||
* `canPrint` Boolean - Whether the media element can be printed.
|
||||
* `canSave` Boolean - Whether or not the media element can be downloaded.
|
||||
* `canShowPictureInPicture` Boolean - Whether the media element can show picture-in-picture.
|
||||
* `isShowingPictureInPicture` Boolean - Whether the media element is currently showing picture-in-picture.
|
||||
* `canRotate` Boolean - Whether the media element can be rotated.
|
||||
* `canLoop` Boolean - Whether the media element can be looped.
|
||||
* `editFlags` Object - These flags indicate whether the renderer believes it
|
||||
is able to perform the corresponding action.
|
||||
* `canUndo` Boolean - Whether the renderer believes it can undo.
|
||||
* `canRedo` Boolean - Whether the renderer believes it can redo.
|
||||
* `canCut` Boolean - Whether the renderer believes it can cut.
|
||||
* `canCopy` Boolean - Whether the renderer believes it can copy.
|
||||
* `canPaste` Boolean - Whether the renderer believes it can paste.
|
||||
* `canDelete` Boolean - Whether the renderer believes it can delete.
|
||||
* `canSelectAll` Boolean - Whether the renderer believes it can select all.
|
||||
* `canEditRichly` Boolean - Whether the renderer believes it can edit text richly.
|
||||
|
||||
Emitted when there is a new context menu that needs to be handled.
|
||||
|
||||
@@ -65,6 +65,9 @@ window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIn
|
||||
`features` will be passed to any registered `webContents`'s
|
||||
`did-create-window` event handler in the `options` argument.
|
||||
* `frameName` follows the specification of `windowName` located in the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters).
|
||||
* When opening `about:blank`, the child window's `WebPreferences` will be copied
|
||||
from the parent window, and there is no way to override it because Chromium
|
||||
skips browser side navigation in this case.
|
||||
|
||||
To customize or cancel the creation of the window, you can optionally set an
|
||||
override handler with `webContents.setWindowOpenHandler()` from the main
|
||||
|
||||
@@ -43,8 +43,9 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
|
||||
|
||||
## Using the symbol server in Visual Studio
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
## Troubleshooting: Symbols will not load
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, shell } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, shell, dialog } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
let mainWindow;
|
||||
|
||||
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/images/vs-tools-options.png
Normal file
BIN
docs/images/vs-tools-options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/images/windows-progress-bar.png
Normal file
BIN
docs/images/windows-progress-bar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -56,7 +56,7 @@ will then be your distribution to deliver to users.
|
||||
|
||||
### With an app source code archive
|
||||
|
||||
Instead of from shipping your app by copying all of its source files, you can
|
||||
Instead of shipping your app by copying all of its source files, you can
|
||||
package your app into an [asar] archive to improve the performance of reading
|
||||
files on platforms like Windows, if you are not already using a bundler such
|
||||
as Parcel or Webpack.
|
||||
|
||||
@@ -84,13 +84,22 @@ There are several additional APIs for working with the Web Serial API:
|
||||
and [`serial-port-removed`](../api/session.md#event-serial-port-removed) events
|
||||
on the Session can be used to handle devices being plugged in or unplugged during the
|
||||
`navigator.serial.requestPort` process.
|
||||
* [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
|
||||
can be used to provide default permissioning to devices without first calling
|
||||
for permission to devices via `navigator.serial.requestPort`. Additionally,
|
||||
the default behavior of Electron is to store granted device permision through
|
||||
the lifetime of the corresponding WebContents. If longer term storage is
|
||||
needed, a developer can store granted device permissions (eg when handling
|
||||
the `select-serial-port` event) and then read from that storage with
|
||||
`setDevicePermissionHandler`.
|
||||
* [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler)
|
||||
can be used to disable serial access for specific origins.
|
||||
|
||||
### Example
|
||||
|
||||
This example demonstrates an Electron application that automatically selects
|
||||
the first available Arduino Uno serial device (if connected) through
|
||||
serial devices through [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
|
||||
as well as demonstrating selecting the first available Arduino Uno serial device (if connected) through
|
||||
[`select-serial-port` event on the Session](../api/session.md#event-select-serial-port)
|
||||
when the `Test Web Serial` button is clicked.
|
||||
|
||||
|
||||
@@ -2,43 +2,31 @@
|
||||
|
||||
> A detailed look at our versioning policy and implementation.
|
||||
|
||||
As of version 2.0.0, Electron follows [SemVer](#semver). The following command will install the most recent stable build of Electron:
|
||||
As of version 2.0.0, Electron follows the [SemVer](#semver) spec. The following command will install the most recent stable build of Electron:
|
||||
|
||||
```sh
|
||||
```sh npm2yarn
|
||||
npm install --save-dev electron
|
||||
```
|
||||
|
||||
To update an existing project to use the latest stable version:
|
||||
|
||||
```sh
|
||||
```sh npm2yarn
|
||||
npm install --save-dev electron@latest
|
||||
```
|
||||
|
||||
## Version 1.x
|
||||
|
||||
Electron versions *< 2.0* did not conform to the [SemVer](https://semver.org) spec: major versions corresponded to end-user API changes, minor versions corresponded to Chromium major releases, and patch versions corresponded to new features and bug fixes. While convenient for developers merging features, it creates problems for developers of client-facing applications. The QA testing cycles of major apps like Slack, Stride, Teams, Skype, VS Code, Atom, and Desktop can be lengthy and stability is a highly desired outcome. There is a high risk in adopting new features while trying to absorb bug fixes.
|
||||
|
||||
Here is an example of the 1.x strategy:
|
||||
|
||||

|
||||
|
||||
An app developed with `1.8.1` cannot take the `1.8.3` bug fix without either absorbing the `1.8.2` feature, or by backporting the fix and maintaining a new release line.
|
||||
|
||||
## Version 2.0 and Beyond
|
||||
## Versioning scheme
|
||||
|
||||
There are several major changes from our 1.x strategy outlined below. Each change is intended to satisfy the needs and priorities of developers/maintainers and app developers.
|
||||
|
||||
1. Strict use of SemVer
|
||||
1. Strict use of the [SemVer](#semver) spec
|
||||
2. Introduction of semver-compliant `-beta` tags
|
||||
3. Introduction of [conventional commit messages](https://conventionalcommits.org/)
|
||||
4. Well-defined stabilization branches
|
||||
5. The `master` branch is versionless; only stabilization branches contain version information
|
||||
5. The `main` branch is versionless; only stabilization branches contain version information
|
||||
|
||||
We will cover in detail how git branching works, how npm tagging works, what developers should expect to see, and how one can backport changes.
|
||||
|
||||
# SemVer
|
||||
|
||||
From 2.0 onward, Electron will follow SemVer.
|
||||
## SemVer
|
||||
|
||||
Below is a table explicitly mapping types of changes to their corresponding category of SemVer (e.g. Major, Minor, Patch).
|
||||
|
||||
@@ -48,22 +36,25 @@ Below is a table explicitly mapping types of changes to their corresponding cate
|
||||
| Node.js major version updates | Node.js minor version updates | Node.js patch version updates |
|
||||
| Chromium version updates | | fix-related chromium patches |
|
||||
|
||||
For more information, see the [Semantic Versioning 2.0.0](https://semver.org/) spec.
|
||||
|
||||
Note that most Chromium updates will be considered breaking. Fixes that can be backported will likely be cherry-picked as patches.
|
||||
|
||||
# Stabilization Branches
|
||||
## Stabilization branches
|
||||
|
||||
Stabilization branches are branches that run parallel to master, taking in only cherry-picked commits that are related to security or stability. These branches are never merged back to master.
|
||||
Stabilization branches are branches that run parallel to `main`, taking in only cherry-picked commits that are related to security or stability. These branches are never merged back to `main`.
|
||||
|
||||

|
||||
|
||||
Since Electron 8, stabilization branches are always **major** version lines, and named against the following template `$MAJOR-x-y` e.g. `8-x-y`. Prior to that we used **minor** version lines and named them as `$MAJOR-$MINOR-x` e.g. `2-0-x`
|
||||
Since Electron 8, stabilization branches are always **major** version lines, and named against the following template `$MAJOR-x-y` e.g. `8-x-y`. Prior to that we used **minor** version lines and named them as `$MAJOR-$MINOR-x` e.g. `2-0-x`.
|
||||
|
||||
We allow for multiple stabilization branches to exist simultaneously, one for each supported version. For more details on which versions are supported, see our [Electron Release Timelines](./electron-timelines.md) doc.
|
||||
|
||||
We allow for multiple stabilization branches to exist simultaneously, and intend to support at least two in parallel at all times, backporting security fixes as necessary.
|
||||

|
||||
|
||||
Older lines will not be supported by GitHub, but other groups can take ownership and backport stability and security fixes on their own. We discourage this, but recognize that it makes life easier for many app developers.
|
||||
Older lines will not be supported by the Electron project, but other groups can take ownership and backport stability and security fixes on their own. We discourage this, but recognize that it makes life easier for many app developers.
|
||||
|
||||
# Beta Releases and Bug Fixes
|
||||
## Beta releases and bug fixes
|
||||
|
||||
Developers want to know which releases are _safe_ to use. Even seemingly innocent features can introduce regressions in complex applications. At the same time, locking to a fixed version is dangerous because you’re ignoring security patches and bug fixes that may have come out since your version. Our goal is to allow the following standard semver ranges in `package.json` :
|
||||
|
||||
@@ -116,15 +107,7 @@ A few examples of how various SemVer ranges will pick up new releases:
|
||||
|
||||

|
||||
|
||||
# Missing Features: Alphas
|
||||
|
||||
Our strategy has a few tradeoffs, which for now we feel are appropriate. Most importantly that new features in master may take a while before reaching a stable release line. If you want to try a new feature immediately, you will have to build Electron yourself.
|
||||
|
||||
As a future consideration, we may introduce one or both of the following:
|
||||
|
||||
* alpha releases that have looser stability constraints to betas; for example it would be allowable to admit new features while a stability channel is in _alpha_
|
||||
|
||||
# Feature Flags
|
||||
## Feature flags
|
||||
|
||||
Feature flags are a common practice in Chromium, and are well-established in the web-development ecosystem. In the context of Electron, a feature flag or **soft branch** must have the following properties:
|
||||
|
||||
@@ -132,20 +115,29 @@ Feature flags are a common practice in Chromium, and are well-established in the
|
||||
* it completely segments new and old code paths; refactoring old code to support a new feature _violates_ the feature-flag contract
|
||||
* feature flags are eventually removed after the feature is released
|
||||
|
||||
# Semantic Commits
|
||||
## Semantic commits
|
||||
|
||||
We seek to increase clarity at all levels of the update and releases process. Starting with `2.0.0` we will require pull requests adhere to the [Conventional Commits](https://conventionalcommits.org/) spec, which can be summarized as follows:
|
||||
All pull requests must adhere to the [Conventional Commits](https://conventionalcommits.org/) spec, which can be summarized as follows:
|
||||
|
||||
* Commits that would result in a SemVer **major** bump must start their body with `BREAKING CHANGE:`.
|
||||
* Commits that would result in a SemVer **minor** bump must start with `feat:`.
|
||||
* Commits that would result in a SemVer **patch** bump must start with `fix:`.
|
||||
|
||||
* We allow squashing of commits, provided that the squashed message adheres to the above message format.
|
||||
* It is acceptable for some commits in a pull request to not include a semantic prefix, as long as the pull request title contains a meaningful encompassing semantic message.
|
||||
The `electron/electron` repository also enforces squash merging, so you only need to make sure that your pull request has the correct title prefix.
|
||||
|
||||
# Versioned `master`
|
||||
## Versioned `main` branch
|
||||
|
||||
* The `master` branch will always contain the next major version `X.0.0-nightly.DATE` in its `package.json`
|
||||
* Release branches are never merged back to master
|
||||
* Release branches _do_ contain the correct version in their `package.json`
|
||||
* As soon as a release branch is cut for a major, master must be bumped to the next major. I.e. `master` is always versioned as the next theoretical release branch
|
||||
* The `main` branch will always contain the next major version `X.0.0-nightly.DATE` in its `package.json`.
|
||||
* Release branches are never merged back to `main`.
|
||||
* Release branches _do_ contain the correct version in their `package.json`.
|
||||
* As soon as a release branch is cut for a major, `main` must be bumped to the next major (i.e. `main` is always versioned as the next theoretical release branch).
|
||||
|
||||
## Historical versioning (Electron 1.X)
|
||||
|
||||
Electron versions *< 2.0* did not conform to the [SemVer](https://semver.org) spec: major versions corresponded to end-user API changes, minor versions corresponded to Chromium major releases, and patch versions corresponded to new features and bug fixes. While convenient for developers merging features, it creates problems for developers of client-facing applications. The QA testing cycles of major apps like Slack, Teams, Skype, VS Code, and GitHub Desktop can be lengthy and stability is a highly desired outcome. There is a high risk in adopting new features while trying to absorb bug fixes.
|
||||
|
||||
Here is an example of the 1.x strategy:
|
||||
|
||||

|
||||
|
||||
An app developed with `1.8.1` cannot take the `1.8.3` bug fix without either absorbing the `1.8.2` feature, or by backporting the fix and maintaining a new release line.
|
||||
|
||||
@@ -7,7 +7,7 @@ without the need of switching to the window itself.
|
||||
|
||||
On Windows, you can use a taskbar button to display a progress bar.
|
||||
|
||||
![Windows Progress Bar][https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png]
|
||||

|
||||
|
||||
On macOS, the progress bar will be displayed as a part of the dock icon.
|
||||
|
||||
|
||||
@@ -593,6 +593,9 @@ WebContents.prototype._init = function () {
|
||||
ipcMainInternal.emit(channel, event, ...args);
|
||||
} else {
|
||||
addReplyToEvent(event);
|
||||
if (this.listenerCount('ipc-message-sync') === 0 && ipcMain.listenerCount(channel) === 0) {
|
||||
console.warn(`WebContents #${this.id} called ipcRenderer.sendSync() with '${channel}' channel without listeners.`);
|
||||
}
|
||||
this.emit('ipc-message-sync', event, channel, ...args);
|
||||
ipcMain.emit(channel, event, ...args);
|
||||
}
|
||||
@@ -666,16 +669,6 @@ WebContents.prototype._init = function () {
|
||||
postBody
|
||||
};
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
|
||||
// if attempting to use this API with the deprecated new-window event,
|
||||
// windowOpenOverriddenOptions will always return null. This ensures
|
||||
// short-term backwards compatibility until new-window is removed.
|
||||
const parsedFeatures = parseFeatures(rawFeatures);
|
||||
const overriddenFeatures: BrowserWindowConstructorOptions = {
|
||||
...parsedFeatures.options,
|
||||
webPreferences: parsedFeatures.webPreferences
|
||||
};
|
||||
windowOpenOverriddenOptions = windowOpenOverriddenOptions || overriddenFeatures;
|
||||
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
@@ -685,9 +678,19 @@ WebContents.prototype._init = function () {
|
||||
transparent: windowOpenOverriddenOptions.transparent,
|
||||
...windowOpenOverriddenOptions.webPreferences
|
||||
} : undefined;
|
||||
this._setNextChildWebPreferences(
|
||||
makeWebPreferences({ embedder: event.sender, secureOverrideWebPreferences })
|
||||
);
|
||||
// TODO(zcbenz): The features string is parsed twice: here where it is
|
||||
// passed to C++, and in |makeBrowserWindowOptions| later where it is
|
||||
// not actually used since the WebContents is created here.
|
||||
// We should be able to remove the latter once the |nativeWindowOpen|
|
||||
// option is removed.
|
||||
const { webPreferences: parsedWebPreferences } = parseFeatures(rawFeatures);
|
||||
// Parameters should keep same with |makeBrowserWindowOptions|.
|
||||
const webPreferences = makeWebPreferences({
|
||||
embedder: event.sender,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
secureOverrideWebPreferences
|
||||
});
|
||||
this._setNextChildWebPreferences(webPreferences);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -735,6 +738,14 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
this.on('select-bluetooth-device', (event, devices, callback) => {
|
||||
if (this.listenerCount('select-bluetooth-device') === 1) {
|
||||
// Cancel it if there are no handlers
|
||||
event.preventDefault();
|
||||
callback('');
|
||||
}
|
||||
});
|
||||
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
|
||||
|
||||
@@ -7,7 +7,11 @@ WebFrameMain.prototype.send = function (channel, ...args) {
|
||||
throw new Error('Missing required channel argument');
|
||||
}
|
||||
|
||||
return this._send(false /* internal */, channel, args);
|
||||
try {
|
||||
return this._send(false /* internal */, channel, args);
|
||||
} catch (e) {
|
||||
console.error('Error sending from webFrameMain: ', e);
|
||||
}
|
||||
};
|
||||
|
||||
WebFrameMain.prototype._sendInternal = function (channel, ...args) {
|
||||
@@ -15,7 +19,11 @@ WebFrameMain.prototype._sendInternal = function (channel, ...args) {
|
||||
throw new Error('Missing required channel argument');
|
||||
}
|
||||
|
||||
return this._send(true /* internal */, channel, args);
|
||||
try {
|
||||
return this._send(true /* internal */, channel, args);
|
||||
} catch (e) {
|
||||
console.error('Error sending from webFrameMain: ', e);
|
||||
}
|
||||
};
|
||||
|
||||
WebFrameMain.prototype.postMessage = function (...args) {
|
||||
|
||||
@@ -65,8 +65,13 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#apis-for-creating-and-navigating-browsing-contexts-by-name
|
||||
const existingWindow = getGuestWindowByFrameName(frameName);
|
||||
if (existingWindow) {
|
||||
existingWindow.loadURL(url);
|
||||
return existingWindow;
|
||||
if (existingWindow.isDestroyed() || existingWindow.webContents.isDestroyed()) {
|
||||
// FIXME(t57ser): The webContents is destroyed for some reason, unregister the frame name
|
||||
unregisterFrameName(frameName);
|
||||
} else {
|
||||
existingWindow.loadURL(url);
|
||||
return existingWindow;
|
||||
}
|
||||
}
|
||||
|
||||
const window = new BrowserWindow({
|
||||
@@ -212,6 +217,10 @@ function makeBrowserWindowOptions ({ embedder, features, overrideOptions }: {
|
||||
height: 600,
|
||||
...parsedOptions,
|
||||
...overrideOptions,
|
||||
// Note that for |nativeWindowOpen: true| the WebContents is created in
|
||||
// |api::WebContents::WebContentsCreatedWithFullParams|, with prefs
|
||||
// parsed in the |-will-add-new-contents| event.
|
||||
// The |webPreferences| here is only used by |nativeWindowOpen: false|.
|
||||
webPreferences: makeWebPreferences({
|
||||
embedder,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
|
||||
@@ -39,6 +39,10 @@ ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_LAST_WEB_PREFERENCES, function (
|
||||
return event.sender.getLastWebPreferences();
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO, function (event) {
|
||||
return event.sender._getProcessMemoryInfo();
|
||||
});
|
||||
|
||||
// Methods not listed in this set are called directly in the renderer process.
|
||||
const allowedClipboardMethods = (() => {
|
||||
switch (process.platform) {
|
||||
|
||||
@@ -4,6 +4,7 @@ export const enum IPC_MESSAGES {
|
||||
BROWSER_PRELOAD_ERROR = 'BROWSER_PRELOAD_ERROR',
|
||||
BROWSER_SANDBOX_LOAD = 'BROWSER_SANDBOX_LOAD',
|
||||
BROWSER_WINDOW_CLOSE = 'BROWSER_WINDOW_CLOSE',
|
||||
BROWSER_GET_PROCESS_MEMORY_INFO = 'BROWSER_GET_PROCESS_MEMORY_INFO',
|
||||
|
||||
GUEST_INSTANCE_VISIBILITY_CHANGE = 'GUEST_INSTANCE_VISIBILITY_CHANGE',
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
export const enum IPC_MESSAGES {
|
||||
BROWSER_REQUIRE = 'REMOTE_BROWSER_REQUIRE',
|
||||
BROWSER_GET_BUILTIN = 'REMOTE_BROWSER_GET_BUILTIN',
|
||||
BROWSER_GET_GLOBAL = 'REMOTE_BROWSER_GET_GLOBAL',
|
||||
BROWSER_GET_CURRENT_WINDOW = 'REMOTE_BROWSER_GET_CURRENT_WINDOW',
|
||||
BROWSER_GET_CURRENT_WEB_CONTENTS = 'REMOTE_BROWSER_GET_CURRENT_WEB_CONTENTS',
|
||||
BROWSER_CONSTRUCTOR = 'REMOTE_BROWSER_CONSTRUCTOR',
|
||||
BROWSER_FUNCTION_CALL = 'REMOTE_BROWSER_FUNCTION_CALL',
|
||||
BROWSER_MEMBER_CONSTRUCTOR = 'REMOTE_BROWSER_MEMBER_CONSTRUCTOR',
|
||||
BROWSER_MEMBER_CALL = 'REMOTE_BROWSER_MEMBER_CALL',
|
||||
BROWSER_MEMBER_GET = 'REMOTE_BROWSER_MEMBER_GET',
|
||||
BROWSER_MEMBER_SET = 'REMOTE_BROWSER_MEMBER_SET',
|
||||
BROWSER_DEREFERENCE = 'REMOTE_BROWSER_DEREFERENCE',
|
||||
BROWSER_CONTEXT_RELEASE = 'REMOTE_BROWSER_CONTEXT_RELEASE',
|
||||
BROWSER_WRONG_CONTEXT_ERROR = 'REMOTE_BROWSER_WRONG_CONTEXT_ERROR',
|
||||
|
||||
RENDERER_CALLBACK = 'REMOTE_RENDERER_CALLBACK',
|
||||
RENDERER_RELEASE_CALLBACK = 'REMOTE_RENDERER_RELEASE_CALLBACK',
|
||||
}
|
||||
@@ -59,6 +59,10 @@ v8Util.setHiddenValue(global, 'ipcNative', {
|
||||
}
|
||||
});
|
||||
|
||||
process.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
// Use electron module after everything is ready.
|
||||
const { webFrameInit } = require('@electron/internal/renderer/web-frame-init') as typeof webFrameInitModule;
|
||||
webFrameInit();
|
||||
|
||||
@@ -87,6 +87,10 @@ Object.assign(preloadProcess, processProps);
|
||||
Object.assign(process, binding.process);
|
||||
Object.assign(process, processProps);
|
||||
|
||||
process.getProcessMemoryInfo = preloadProcess.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||
get () {
|
||||
return process.noDeprecation;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "14.1.0",
|
||||
"version": "14.2.9",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -33,7 +33,7 @@
|
||||
"asar": "^3.0.3",
|
||||
"aws-sdk": "^2.727.1",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.4.0",
|
||||
"colors": "1.4.0",
|
||||
"dotenv-safe": "^4.0.4",
|
||||
"dugite": "^1.45.0",
|
||||
"eslint": "^7.4.0",
|
||||
|
||||
13
patches/angle/.patches
Normal file
13
patches/angle/.patches
Normal file
@@ -0,0 +1,13 @@
|
||||
fix_integer_overflow_in_blocklayoutencoder.patch
|
||||
cherry-pick-bdffa0ea5148.patch
|
||||
cherry-pick-05e69c75905f.patch
|
||||
cherry-pick-891020ed64d4.patch
|
||||
cherry-pick-2b98abd8cb6c.patch
|
||||
cherry-pick-cc44ae61f37b.patch
|
||||
m98_vulkan_fix_vkcmdresolveimage_extents.patch
|
||||
m98_vulkan_fix_vkcmdresolveimage_offsets.patch
|
||||
cherry-pick-49e8ff16f1fe.patch
|
||||
m99_vulkan_prevent_out_of_bounds_read_in_divisor_emulation_path.patch
|
||||
m99_vulkan_streamvertexdatawithdivisor_write_beyond_buffer_boundary.patch
|
||||
m98_protect_against_deleting_a_current_xfb_buffer.patch
|
||||
m96-lts_vulkan_fix_issue_with_redefining_a_layered_attachment.patch
|
||||
118
patches/angle/cherry-pick-05e69c75905f.patch
Normal file
118
patches/angle/cherry-pick-05e69c75905f.patch
Normal file
@@ -0,0 +1,118 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lingfeng Yang <lfy@google.com>
|
||||
Date: Wed, 1 Dec 2021 18:16:14 -0800
|
||||
Subject: M96: Vulkan: remove staged updates on storage set
|
||||
|
||||
Previously we would allow staged updates to bigger versions of a texture
|
||||
to go through even if the texture was redefined via glTexStorage*.
|
||||
|
||||
Bug: chromium:1262080
|
||||
Change-Id: I9d861fed68d4a1fdcd0777b97caf729cc74c595e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3312718
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Lingfeng Yang <lfy@google.com>
|
||||
(cherry picked from commit 929c8ed4e8c3912cf027d843e7a2af47b21e5612)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3328001
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index 68e7ffa73781b8431188d53c97d388bd1c7ffb52..ee159cbd3621a655f00ccf2eb24c8711e050da8b 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -1236,6 +1236,10 @@ angle::Result TextureVk::setStorageMultisample(const gl::Context *context,
|
||||
{
|
||||
releaseAndDeleteImageAndViews(contextVk);
|
||||
}
|
||||
+ else if (mImage)
|
||||
+ {
|
||||
+ mImage->releaseStagingBuffer(contextVk->getRenderer());
|
||||
+ }
|
||||
|
||||
const vk::Format &format = renderer->getFormat(internalformat);
|
||||
ANGLE_TRY(ensureImageAllocated(contextVk, format));
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index f0b48cb803981d1fdc7c30093c7bf7c0d170dece..9a20527ae5b8aa33ad2fcb9572eb2180710cd31c 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -9547,6 +9547,73 @@ void main()
|
||||
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
|
||||
}
|
||||
|
||||
+class TextureChangeStorageUploadTest : public ANGLETest
|
||||
+{
|
||||
+ protected:
|
||||
+ TextureChangeStorageUploadTest()
|
||||
+ {
|
||||
+ setWindowWidth(256);
|
||||
+ setWindowHeight(256);
|
||||
+ setConfigRedBits(8);
|
||||
+ setConfigGreenBits(8);
|
||||
+ setConfigBlueBits(8);
|
||||
+ setConfigAlphaBits(8);
|
||||
+ }
|
||||
+
|
||||
+ void testSetUp() override
|
||||
+ {
|
||||
+ mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ if (mProgram == 0)
|
||||
+ {
|
||||
+ FAIL() << "shader compilation failed.";
|
||||
+ }
|
||||
+
|
||||
+ mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+
|
||||
+ glClearColor(0, 0, 0, 0);
|
||||
+ glClearDepthf(0.0);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
+
|
||||
+ glEnable(GL_BLEND);
|
||||
+ glDisable(GL_DEPTH_TEST);
|
||||
+
|
||||
+ glGenTextures(1, &mTexture);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ }
|
||||
+
|
||||
+ void testTearDown() override
|
||||
+ {
|
||||
+ glDeleteTextures(1, &mTexture);
|
||||
+ glDeleteProgram(mProgram);
|
||||
+ }
|
||||
+
|
||||
+ GLuint mProgram;
|
||||
+ GLint mColorLocation;
|
||||
+ GLuint mTexture;
|
||||
+};
|
||||
+
|
||||
+// Verify that respecifying storage and re-uploading doesn't crash.
|
||||
+TEST_P(TextureChangeStorageUploadTest, Basic)
|
||||
+{
|
||||
+ constexpr int kImageSize = 8; // 4 doesn't trip ASAN
|
||||
+ constexpr int kSmallerImageSize = kImageSize / 2;
|
||||
+ EXPECT_GT(kImageSize, kSmallerImageSize);
|
||||
+ EXPECT_GT(kSmallerImageSize / 2, 0);
|
||||
+
|
||||
+ std::array<GLColor, kImageSize * kImageSize> kColor;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ kColor.data());
|
||||
+ glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
|
||||
+ // need partial update to sidestep optimizations that remove the full upload
|
||||
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
|
||||
+ GL_UNSIGNED_BYTE, kColor.data());
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
#define ES2_EMULATE_COPY_TEX_IMAGE() \
|
||||
@@ -9660,4 +9727,6 @@ ANGLE_INSTANTIATE_TEST_ES31_AND(TextureBufferTestES31, WithDirectSPIRVGeneration
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
|
||||
ANGLE_INSTANTIATE_TEST_ES31_AND(CopyImageTestES31, WithDirectSPIRVGeneration(ES31_VULKAN()));
|
||||
|
||||
+ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
|
||||
+
|
||||
} // anonymous namespace
|
||||
96
patches/angle/cherry-pick-2b98abd8cb6c.patch
Normal file
96
patches/angle/cherry-pick-2b98abd8cb6c.patch
Normal file
@@ -0,0 +1,96 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Tue, 30 Nov 2021 23:48:30 -0500
|
||||
Subject: M96: Vulkan: Fix image respecify's usage tracking
|
||||
|
||||
When respecifying an image due to mip level count changes, the previous
|
||||
image is staged as an update to the new image. The resource usage info
|
||||
was not being transferred to the image being staged as an update,
|
||||
causing it to be prematurely deleted.
|
||||
|
||||
Test based on one authored by sugoi@google.com.
|
||||
|
||||
Bug: chromium:1270658
|
||||
Bug: angleproject:4835
|
||||
Change-Id: I9810f8940e0107bc8a04fa3fb9c26a045c0d689c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3318257
|
||||
Reviewed-by: Lingfeng Yang <lfy@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.cpp b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
index efb04acf0fe5dc7c2d860ac8cc33dbe30691c4a3..e2cd1e3a96b1fa4e034efe6ed78ea1a787af6af6 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
@@ -26,6 +26,12 @@ Resource::Resource(Resource &&other) : Resource()
|
||||
mUse = std::move(other.mUse);
|
||||
}
|
||||
|
||||
+Resource &Resource::operator=(Resource &&rhs)
|
||||
+{
|
||||
+ std::swap(mUse, rhs.mUse);
|
||||
+ return *this;
|
||||
+}
|
||||
+
|
||||
Resource::~Resource()
|
||||
{
|
||||
mUse.release();
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.h b/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
index 67440122bf7fa0f72b5412816853b2eddd770fd4..abab9900b7361c8564cb1ad30e0841eaf873ee2e 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
@@ -192,6 +192,7 @@ class Resource : angle::NonCopyable
|
||||
protected:
|
||||
Resource();
|
||||
Resource(Resource &&other);
|
||||
+ Resource &operator=(Resource &&rhs);
|
||||
|
||||
// Current resource lifetime.
|
||||
SharedResourceUse mUse;
|
||||
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
index e8378d01aa29b98ea4b6a9db270c41b19ba1809a..0c21d3ea8b075cbd0fbbe95d8f4754647276c21f 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
@@ -6020,6 +6020,9 @@ void ImageHelper::stageSelfAsSubresourceUpdates(ContextVk *contextVk,
|
||||
// Move the necessary information for staged update to work, and keep the rest as part of this
|
||||
// object.
|
||||
|
||||
+ // Usage info
|
||||
+ prevImage->get().Resource::operator=(std::move(*this));
|
||||
+
|
||||
// Vulkan objects
|
||||
prevImage->get().mImage = std::move(mImage);
|
||||
prevImage->get().mDeviceMemory = std::move(mDeviceMemory);
|
||||
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
|
||||
index 4db00e78a7d2f7375fdcb9228fbdc83395973125..8a6d01ca36a84a9e294de3f6f0114ee7a54e1d9a 100644
|
||||
--- a/src/tests/gl_tests/MipmapTest.cpp
|
||||
+++ b/src/tests/gl_tests/MipmapTest.cpp
|
||||
@@ -2106,6 +2106,30 @@ TEST_P(MipmapTestES3, GenerateMipmapZeroSize)
|
||||
glGenerateMipmap(GL_TEXTURE_3D);
|
||||
}
|
||||
|
||||
+// Test that reducing the size of the mipchain by resizing the base image then deleting it doesn't
|
||||
+// cause a crash. Issue found by fuzzer.
|
||||
+TEST_P(MipmapTestES3, ResizeBaseMipTo1x1ThenDelete)
|
||||
+{
|
||||
+ GLTexture tex;
|
||||
+ glBindTexture(GL_TEXTURE_2D, tex);
|
||||
+
|
||||
+ std::vector<GLColor> data(2, GLColor::blue);
|
||||
+
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+
|
||||
+ clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
|
||||
+
|
||||
+ data[0] = GLColor::green;
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+
|
||||
+ clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
|
||||
+
|
||||
+ tex.reset();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MipmapTest);
|
||||
381
patches/angle/cherry-pick-49e8ff16f1fe.patch
Normal file
381
patches/angle/cherry-pick-49e8ff16f1fe.patch
Normal file
@@ -0,0 +1,381 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Tue, 25 Jan 2022 12:15:16 -0500
|
||||
Subject: M99: Vulkan: Fix texture array level redefinition
|
||||
|
||||
When a level of a texture is redefined, all staged updates to that level
|
||||
should be removed, not the ones specific to the new layers. The bug
|
||||
fixed was that if the texture was redefined to have its number of layers
|
||||
changed, the staged higher-layer-count update to the image was not
|
||||
removed.
|
||||
|
||||
Bug: chromium:1289383
|
||||
Change-Id: Iab79c38d846d1abbdd92e11b1b60a3adf0fbde4c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3441309
|
||||
Reviewed-by: Lingfeng Yang <lfy@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index ee159cbd3621a655f00ccf2eb24c8711e050da8b..859e017d491f49d76db8c5fdd4c76ff51759075c 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -1553,12 +1553,25 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context,
|
||||
|
||||
if (mImage != nullptr)
|
||||
{
|
||||
- // If there is any staged changes for this index, we can remove them since we're going to
|
||||
+ // If there are any staged changes for this index, we can remove them since we're going to
|
||||
// override them with this call.
|
||||
gl::LevelIndex levelIndexGL(index.getLevelIndex());
|
||||
uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
|
||||
- mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
|
||||
- index.getLayerCount());
|
||||
+ if (gl::IsArrayTextureType(index.getType()))
|
||||
+ {
|
||||
+ // A multi-layer texture is being redefined, remove all updates to this level; the
|
||||
+ // number of layers may have changed.
|
||||
+ mImage->removeStagedUpdates(contextVk, levelIndexGL, levelIndexGL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ // Otherwise remove only updates to this layer. For example, cube map updates can be
|
||||
+ // done through glTexImage2D, one per cube face (i.e. layer) and so should not remove
|
||||
+ // updates to the other layers.
|
||||
+ ASSERT(index.getLayerCount() == 1);
|
||||
+ mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
|
||||
+ index.getLayerCount());
|
||||
+ }
|
||||
|
||||
if (mImage->valid())
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
|
||||
index 8a6d01ca36a84a9e294de3f6f0114ee7a54e1d9a..957a52304edc9aa245f9f21e5557cc105cbad789 100644
|
||||
--- a/src/tests/gl_tests/MipmapTest.cpp
|
||||
+++ b/src/tests/gl_tests/MipmapTest.cpp
|
||||
@@ -1686,6 +1686,106 @@ TEST_P(MipmapTestES3, MipmapsForTexture3D)
|
||||
EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
}
|
||||
|
||||
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
|
||||
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(MipmapTestES3, TextureArrayRedefineThenGenerateMipmap)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red, then redefine it and fill with green
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Generate mipmaps
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mArrayProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
|
||||
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(MipmapTestES3, TextureArrayUseThenRedefineThenGenerateMipmap)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red.
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Generate mipmap
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mArrayProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Draw the fourth slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Redefine the image and fill with green
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ // Generate mipmap
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Create a 2D texture with levels 0-2, call GenerateMipmap with base level 1 so that level 0 stays
|
||||
// the same, and then sample levels 0 and 2.
|
||||
// GLES 3.0.4 section 3.8.10:
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index f1df6b5b947ca2684a9db7bd800f5de59ce0c64c..54ab7910ddeacf740a27816c6b9c5a9ce12cba68 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -1025,31 +1025,37 @@ class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
|
||||
class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
{
|
||||
protected:
|
||||
- Texture2DArrayTestES3() : TexCoordDrawTest(), m2DArrayTexture(0), mTextureArrayLocation(-1) {}
|
||||
+ Texture2DArrayTestES3()
|
||||
+ : TexCoordDrawTest(),
|
||||
+ m2DArrayTexture(0),
|
||||
+ mTextureArrayLocation(-1),
|
||||
+ mTextureArraySliceUniformLocation(-1)
|
||||
+ {}
|
||||
|
||||
const char *getVertexShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "out vec2 texcoord;\n"
|
||||
- "in vec4 position;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
|
||||
- " texcoord = (position.xy * 0.5) + 0.5;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+out vec2 texcoord;
|
||||
+in vec4 position;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(position.xy, 0.0, 1.0);
|
||||
+ texcoord = (position.xy * 0.5) + 0.5;
|
||||
+})";
|
||||
}
|
||||
|
||||
const char *getFragmentShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "precision highp float;\n"
|
||||
- "uniform highp sampler2DArray tex2DArray;\n"
|
||||
- "in vec2 texcoord;\n"
|
||||
- "out vec4 fragColor;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+precision highp float;
|
||||
+uniform highp sampler2DArray tex2DArray;
|
||||
+uniform int slice;
|
||||
+in vec2 texcoord;
|
||||
+out vec4 fragColor;
|
||||
+void main()
|
||||
+{
|
||||
+ fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
|
||||
+})";
|
||||
}
|
||||
|
||||
void testSetUp() override
|
||||
@@ -1061,6 +1067,9 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
|
||||
ASSERT_NE(-1, mTextureArrayLocation);
|
||||
|
||||
+ mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
|
||||
+ ASSERT_NE(-1, mTextureArraySliceUniformLocation);
|
||||
+
|
||||
glGenTextures(1, &m2DArrayTexture);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
@@ -1073,6 +1082,7 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
|
||||
GLuint m2DArrayTexture;
|
||||
GLint mTextureArrayLocation;
|
||||
+ GLint mTextureArraySliceUniformLocation;
|
||||
};
|
||||
|
||||
class TextureSizeTextureArrayTest : public TexCoordDrawTest
|
||||
@@ -1715,28 +1725,28 @@ class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
|
||||
|
||||
const char *getVertexShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "out vec2 texcoord;\n"
|
||||
- "in vec4 position;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
|
||||
- " texcoord = (position.xy * 0.5) + 0.5;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+out vec2 texcoord;
|
||||
+in vec4 position;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(position.xy, 0.0, 1.0);
|
||||
+ texcoord = (position.xy * 0.5) + 0.5;
|
||||
+})";
|
||||
}
|
||||
|
||||
const char *getFragmentShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "precision highp float;\n"
|
||||
- "uniform highp usampler2DArray tex2DArray;\n"
|
||||
- "in vec2 texcoord;\n"
|
||||
- "out vec4 fragColor;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " fragColor = vec4(texture(tex2DArray, vec3(texcoord.x, texcoord.y, "
|
||||
- "0.0)))/255.0;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+precision highp float;
|
||||
+uniform highp usampler2DArray tex2DArray;
|
||||
+uniform int slice;
|
||||
+in vec2 texcoord;
|
||||
+out vec4 fragColor;
|
||||
+void main()
|
||||
+{
|
||||
+ fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
|
||||
+})";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4972,6 +4982,94 @@ TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensio
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
|
||||
}
|
||||
|
||||
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
|
||||
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red, then redefine it and fill with green
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
|
||||
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red.
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Draw the fourth slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Redefine the image and fill with green
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Test that texture completeness is updated if texture max level changes.
|
||||
// GLES 3.0.4 section 3.8.13 Texture completeness
|
||||
TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
|
||||
163
patches/angle/cherry-pick-891020ed64d4.patch
Normal file
163
patches/angle/cherry-pick-891020ed64d4.patch
Normal file
@@ -0,0 +1,163 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Date: Mon, 22 Nov 2021 14:30:52 -0500
|
||||
Subject: Ignore the pixel unpack state for compressed textures.
|
||||
|
||||
From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding
|
||||
a compressed texture image
|
||||
This was causing a bad access when calling compressedTexImage3D
|
||||
with GL_UNPACK_IMAGE_HEIGHT greater than the image height.
|
||||
|
||||
Bug: chromium:1267496
|
||||
Change-Id: I9b1f4c645548af64f2695fd23262225a1ad07cd7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3296622
|
||||
Commit-Queue: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 870f458f507ff7ba0f67b28a30a27955ce79dd3e)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3309097
|
||||
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
|
||||
index 1e989ebaffb25da1a1a281afa0610a9088232119..67356b5bd47e96e98e2a5e4880a71f5042ca918d 100644
|
||||
--- a/src/libANGLE/Context.cpp
|
||||
+++ b/src/libANGLE/Context.cpp
|
||||
@@ -4923,7 +4923,9 @@ void Context::compressedTexImage2D(TextureTarget target,
|
||||
|
||||
Extents size(width, height, 1);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, mState.getUnpackState(), target, level,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
|
||||
internalformat, size, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
@@ -4955,7 +4957,9 @@ void Context::compressedTexImage3D(TextureTarget target,
|
||||
|
||||
Extents size(width, height, depth);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, mState.getUnpackState(), target, level,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
|
||||
internalformat, size, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
@@ -4989,8 +4993,10 @@ void Context::compressedTexSubImage2D(TextureTarget target,
|
||||
|
||||
Box area(xoffset, yoffset, 0, width, height, 1);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, mState.getUnpackState(), target, level,
|
||||
- area, format, imageSize,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
|
||||
+ format, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
|
||||
@@ -5031,8 +5037,10 @@ void Context::compressedTexSubImage3D(TextureTarget target,
|
||||
|
||||
Box area(xoffset, yoffset, zoffset, width, height, depth);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, mState.getUnpackState(), target, level,
|
||||
- area, format, imageSize,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
|
||||
+ format, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index 9a20527ae5b8aa33ad2fcb9572eb2180710cd31c..f1df6b5b947ca2684a9db7bd800f5de59ce0c64c 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -5011,6 +5011,43 @@ TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
|
||||
}
|
||||
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture3DTestES3, PixelUnpackStateTexImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
|
||||
+
|
||||
+ uint8_t data[64] = {0};
|
||||
+ glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
|
||||
+
|
||||
+ uint8_t data[64] = {0};
|
||||
+ glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
|
||||
+
|
||||
+ glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4,
|
||||
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Test that 3D texture completeness is updated if texture max level changes.
|
||||
// GLES 3.0.4 section 3.8.13 Texture completeness
|
||||
TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
|
||||
@@ -5690,6 +5727,41 @@ TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
|
||||
EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
|
||||
}
|
||||
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture2DTestES3, PixelUnpackStateTexImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 5);
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture2D);
|
||||
+
|
||||
+ uint8_t data[16] = {0};
|
||||
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 0, 16, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture2D);
|
||||
+
|
||||
+ uint8_t data[16] = {0};
|
||||
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 0, 16, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 5);
|
||||
+
|
||||
+ glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Copied from Texture2DTest::TexStorage
|
||||
// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
|
||||
// default color.
|
||||
169
patches/angle/cherry-pick-bdffa0ea5148.patch
Normal file
169
patches/angle/cherry-pick-bdffa0ea5148.patch
Normal file
@@ -0,0 +1,169 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Thu, 2 Dec 2021 14:30:42 -0500
|
||||
Subject: M96: Fix changing attached renderbuffer from MSRTT to non-MSRTT
|
||||
|
||||
FramebufferAttachment::mRenderToTextureSamples was never updated if the
|
||||
renderbuffer storage was changed after attaching to framebuffer.
|
||||
|
||||
Bug: chromium:1272068
|
||||
Change-Id: Icddbb5650354ea16d06c49532d6a8d0ae962ab5f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3320923
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp
|
||||
index 00714d0a0303050893abcd9564e760b22d9b2de5..720d3000d42e6c8c23214e66eee4aa6982216a60 100644
|
||||
--- a/src/libANGLE/FramebufferAttachment.cpp
|
||||
+++ b/src/libANGLE/FramebufferAttachment.cpp
|
||||
@@ -129,7 +129,7 @@ void FramebufferAttachment::attach(const Context *context,
|
||||
mNumViews = numViews;
|
||||
mBaseViewIndex = baseViewIndex;
|
||||
mIsMultiview = isMultiview;
|
||||
- mRenderToTextureSamples = samples;
|
||||
+ mRenderToTextureSamples = type == GL_RENDERBUFFER ? kDefaultRenderToTextureSamples : samples;
|
||||
resource->onAttach(context, framebufferSerial);
|
||||
|
||||
if (mResource != nullptr)
|
||||
@@ -222,6 +222,29 @@ GLint FramebufferAttachment::getBaseViewIndex() const
|
||||
return mBaseViewIndex;
|
||||
}
|
||||
|
||||
+bool FramebufferAttachment::isRenderToTexture() const
|
||||
+{
|
||||
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
|
||||
+
|
||||
+ if (mType == GL_RENDERBUFFER)
|
||||
+ {
|
||||
+ return getRenderbuffer()->getMultisamplingMode() ==
|
||||
+ MultisamplingMode::MultisampledRenderToTexture;
|
||||
+ }
|
||||
+ return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
|
||||
+}
|
||||
+
|
||||
+GLsizei FramebufferAttachment::getRenderToTextureSamples() const
|
||||
+{
|
||||
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
|
||||
+
|
||||
+ if (mType == GL_RENDERBUFFER)
|
||||
+ {
|
||||
+ return getRenderbuffer()->getState().getSamples();
|
||||
+ }
|
||||
+ return mRenderToTextureSamples;
|
||||
+}
|
||||
+
|
||||
Texture *FramebufferAttachment::getTexture() const
|
||||
{
|
||||
return rx::GetAs<Texture>(mResource);
|
||||
diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h
|
||||
index 013a1e02874e4df3680e9b4a56f74aaf94d188a9..6235b42cf2fdfcb0e9fa33242b458934f1afa5b0 100644
|
||||
--- a/src/libANGLE/FramebufferAttachment.h
|
||||
+++ b/src/libANGLE/FramebufferAttachment.h
|
||||
@@ -117,11 +117,8 @@ class FramebufferAttachment final
|
||||
bool isMultiview() const;
|
||||
GLint getBaseViewIndex() const;
|
||||
|
||||
- bool isRenderToTexture() const
|
||||
- {
|
||||
- return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
|
||||
- }
|
||||
- GLsizei getRenderToTextureSamples() const { return mRenderToTextureSamples; }
|
||||
+ bool isRenderToTexture() const;
|
||||
+ GLsizei getRenderToTextureSamples() const;
|
||||
|
||||
// The size of the underlying resource the attachment points to. The 'depth' value will
|
||||
// correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
|
||||
@@ -195,6 +192,14 @@ class FramebufferAttachment final
|
||||
GLsizei mNumViews;
|
||||
bool mIsMultiview;
|
||||
GLint mBaseViewIndex;
|
||||
+ // A single-sampled texture can be attached to a framebuffer either as single-sampled or as
|
||||
+ // multisampled-render-to-texture. In the latter case, |mRenderToTextureSamples| will contain
|
||||
+ // the number of samples. For renderbuffers, the number of samples is inherited from the
|
||||
+ // renderbuffer itself.
|
||||
+ //
|
||||
+ // Note that textures cannot change storage between single and multisample once attached to a
|
||||
+ // framebuffer. Renderbuffers instead can, and caching the number of renderbuffer samples here
|
||||
+ // can lead to stale data.
|
||||
GLsizei mRenderToTextureSamples;
|
||||
};
|
||||
|
||||
@@ -253,8 +258,7 @@ inline Format FramebufferAttachment::getFormat() const
|
||||
|
||||
inline GLsizei FramebufferAttachment::getSamples() const
|
||||
{
|
||||
- return (mRenderToTextureSamples != kDefaultRenderToTextureSamples) ? getRenderToTextureSamples()
|
||||
- : getResourceSamples();
|
||||
+ return isRenderToTexture() ? getRenderToTextureSamples() : getResourceSamples();
|
||||
}
|
||||
|
||||
inline GLsizei FramebufferAttachment::getResourceSamples() const
|
||||
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
index ff01848daff091d92e4fdce08bc6842a3bdd3ee9..cd733be3ae5c179860d882e305ec84d093a283ed 100644
|
||||
--- a/src/tests/gl_tests/FramebufferTest.cpp
|
||||
+++ b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
@@ -3366,6 +3366,65 @@ void main() {
|
||||
|
||||
// This shouldn't crash.
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Modify renderbuffer attachment samples after bind
|
||||
+TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySamples)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ glUseProgram(program);
|
||||
+ GLint colorUniformLocation =
|
||||
+ glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
|
||||
+ ASSERT_NE(colorUniformLocation, -1);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+
|
||||
+ GLsizei size = 16;
|
||||
+ glViewport(0, 0, size, size);
|
||||
+
|
||||
+ GLRenderbuffer color;
|
||||
+ glBindRenderbuffer(GL_RENDERBUFFER, color);
|
||||
+
|
||||
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, size, size);
|
||||
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
|
||||
+
|
||||
+ glUniform4f(colorUniformLocation, 1, 0, 0, 1);
|
||||
+ drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Modify renderbuffer attachment size after bind
|
||||
+TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ glUseProgram(program);
|
||||
+ GLint colorUniformLocation =
|
||||
+ glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
|
||||
+ ASSERT_NE(colorUniformLocation, -1);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+
|
||||
+ GLsizei size = 16;
|
||||
+ glViewport(0, 0, size, size);
|
||||
+
|
||||
+ GLRenderbuffer color;
|
||||
+ glBindRenderbuffer(GL_RENDERBUFFER, color);
|
||||
+
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
|
||||
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size / 2, size * 2);
|
||||
+
|
||||
+ glUniform4f(colorUniformLocation, 1, 0, 0, 1);
|
||||
+ drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
ANGLE_INSTANTIATE_TEST_ES2(AddMockTextureNoRenderTargetTest);
|
||||
43
patches/angle/cherry-pick-cc44ae61f37b.patch
Normal file
43
patches/angle/cherry-pick-cc44ae61f37b.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 4 Jan 2022 12:28:55 -0500
|
||||
Subject: M96: D3D11: Fix OOB access in vertex conversion code.
|
||||
|
||||
This could happen when using certain combinations of stride and
|
||||
offset. Fix the issue by using checked math.
|
||||
|
||||
Bug: chromium:1274499
|
||||
Change-Id: I3e286a30fe128ab4684ee5e172dc9e3345e3b2f4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3365657
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
index 43fcdc8de5a0d15aacf4b06e0e32df008d78f886..031a12e2b8b0e0dee91087c02cbd2f8b17435a2b 100644
|
||||
--- a/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
@@ -58,17 +58,15 @@ int ElementsInBuffer(const gl::VertexAttribute &attrib,
|
||||
const gl::VertexBinding &binding,
|
||||
unsigned int size)
|
||||
{
|
||||
- // Size cannot be larger than a GLsizei
|
||||
- if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
|
||||
- {
|
||||
- size = static_cast<unsigned int>(std::numeric_limits<int>::max());
|
||||
- }
|
||||
+ angle::CheckedNumeric<size_t> bufferSize(size);
|
||||
+ angle::CheckedNumeric<size_t> stride = ComputeVertexAttributeStride(attrib, binding);
|
||||
+ angle::CheckedNumeric<size_t> offset = ComputeVertexAttributeOffset(attrib, binding);
|
||||
+ angle::CheckedNumeric<size_t> elementSize = ComputeVertexAttributeTypeSize(attrib);
|
||||
+
|
||||
+ auto elementsInBuffer = (bufferSize - (offset % stride) + (stride - elementSize)) / stride;
|
||||
+ auto elementsInBufferInt = angle::CheckedNumeric<int>::cast(elementsInBuffer);
|
||||
|
||||
- GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib, binding));
|
||||
- GLsizei offset = static_cast<GLsizei>(ComputeVertexAttributeOffset(attrib, binding));
|
||||
- return (size - offset % stride +
|
||||
- (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
|
||||
- stride;
|
||||
+ return elementsInBufferInt.ValueOrDefault(0);
|
||||
}
|
||||
|
||||
// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
|
||||
125
patches/angle/fix_integer_overflow_in_blocklayoutencoder.patch
Normal file
125
patches/angle/fix_integer_overflow_in_blocklayoutencoder.patch
Normal file
@@ -0,0 +1,125 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alexis Hetu <sugoi@google.com>
|
||||
Date: Wed, 15 Sep 2021 13:40:28 -0400
|
||||
Subject: Fix integer overflow in BlockLayoutEncoder
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
BlockLayoutEncoder::mCurrentOffset's computation had the
|
||||
possibility of causing integer overflows in multiple places,
|
||||
so this CL adds CheckedNumeric variables in a number of
|
||||
these occurrences in order to prevent integer overflows and
|
||||
causing issues.
|
||||
|
||||
The issue in this case was an integer overflow causing the
|
||||
code in ValidateTypeSizeLimitations.cpp to use an invalid
|
||||
result from "layoutEncoder.getCurrentOffset()", which ended
|
||||
up compiling a shader which would later cause an OOM error.
|
||||
|
||||
Bug: chromium:1248665
|
||||
Change-Id: I688d669f21c6dc2957e43bdf91f8f8f08180a6f7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3163356
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Alexis Hétu <sugoi@chromium.org>
|
||||
(cherry picked from commit 158ef351fc8b827c201e056a8ddba50fd4235671)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3194392
|
||||
|
||||
diff --git a/src/compiler/translator/blocklayout.cpp b/src/compiler/translator/blocklayout.cpp
|
||||
index 0539923bc75f5b88228dcb387c8aba4c701edc1b..1e6b143a1e1ee9a127b71685febd36416a8840f6 100644
|
||||
--- a/src/compiler/translator/blocklayout.cpp
|
||||
+++ b/src/compiler/translator/blocklayout.cpp
|
||||
@@ -199,6 +199,13 @@ BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
|
||||
return memberInfo;
|
||||
}
|
||||
|
||||
+size_t BlockLayoutEncoder::getCurrentOffset() const
|
||||
+{
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
||||
+ checkedOffset *= kBytesPerComponent;
|
||||
+ return checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
+}
|
||||
+
|
||||
size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor)
|
||||
{
|
||||
size_t currentOffset = mCurrentOffset;
|
||||
@@ -226,7 +233,13 @@ size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info)
|
||||
|
||||
void BlockLayoutEncoder::align(size_t baseAlignment)
|
||||
{
|
||||
- mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, baseAlignment);
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
||||
+ checkedOffset += baseAlignment;
|
||||
+ checkedOffset -= 1;
|
||||
+ angle::base::CheckedNumeric<size_t> checkedAlignmentOffset = checkedOffset;
|
||||
+ checkedAlignmentOffset %= baseAlignment;
|
||||
+ checkedOffset -= checkedAlignmentOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
|
||||
// StubBlockEncoder implementation.
|
||||
@@ -289,7 +302,7 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
|
||||
baseAlignment = ComponentAlignment(numComponents);
|
||||
}
|
||||
|
||||
- mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
|
||||
+ align(baseAlignment);
|
||||
|
||||
*matrixStrideOut = matrixStride;
|
||||
*arrayStrideOut = arrayStride;
|
||||
@@ -303,16 +316,23 @@ void Std140BlockEncoder::advanceOffset(GLenum type,
|
||||
{
|
||||
if (!arraySizes.empty())
|
||||
{
|
||||
- mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
|
||||
+ checkedOffset *= gl::ArraySizeProduct(arraySizes);
|
||||
+ checkedOffset += mCurrentOffset;
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
else if (gl::IsMatrixType(type))
|
||||
{
|
||||
- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
|
||||
- mCurrentOffset += matrixStride * numRegisters;
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(matrixStride);
|
||||
+ checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix);
|
||||
+ checkedOffset += mCurrentOffset;
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
else
|
||||
{
|
||||
- mCurrentOffset += gl::VariableComponentCount(type);
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
||||
+ checkedOffset += gl::VariableComponentCount(type);
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/compiler/translator/blocklayout.h b/src/compiler/translator/blocklayout.h
|
||||
index 726d76fa178f77a978ff2c82ec20fb8f1ad03f0b..ff90a2487830b365697ce41d660a689857b75319 100644
|
||||
--- a/src/compiler/translator/blocklayout.h
|
||||
+++ b/src/compiler/translator/blocklayout.h
|
||||
@@ -80,7 +80,7 @@ class BlockLayoutEncoder
|
||||
const std::vector<unsigned int> &arraySizes,
|
||||
bool isRowMajorMatrix);
|
||||
|
||||
- size_t getCurrentOffset() const { return mCurrentOffset * kBytesPerComponent; }
|
||||
+ size_t getCurrentOffset() const;
|
||||
size_t getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor);
|
||||
|
||||
// Called when entering/exiting a structure variable.
|
||||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
index f57e3c6e012788666186b532fad6fc2d07d9d4b7..35cadfd7312ab1cd77c7d153c6a25b5cd47d9fe8 100644
|
||||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
@@ -5047,7 +5047,7 @@ void main()
|
||||
|
||||
constexpr char kVSArrayMuchTooLarge[] =
|
||||
R"(varying vec4 color;
|
||||
-const int array_size = 795418649;
|
||||
+const int array_size = 556007917;
|
||||
void main()
|
||||
{
|
||||
mat2 array[array_size];
|
||||
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 1 Mar 2022 15:40:38 -0500
|
||||
Subject: Vulkan: Fix issue with redefining a layered attachment.
|
||||
|
||||
The fix ensures we complete level redefinition before we get the
|
||||
layer render target in TextureVk::getAttachmentRenderTarget.
|
||||
|
||||
Bug: chromium:1296866
|
||||
Change-Id: Id7fa8e9fed5e766c30580b09336713c675c4e4f0
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3498283
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 348ece42552a99cff88f79c80652b9dd3155ab22)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3513754
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index 859e017d491f49d76db8c5fdd4c76ff51759075c..87fbf7ae472a87b5859467a3a2ab5606f6893fec 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -2174,6 +2174,15 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
|
||||
|
||||
ContextVk *contextVk = vk::GetImpl(context);
|
||||
|
||||
+ if (mRedefinedLevels.any())
|
||||
+ {
|
||||
+ // If we have redefined levels, we must flush those out to fix the render targets.
|
||||
+ ANGLE_TRY(respecifyImageStorage(contextVk));
|
||||
+ }
|
||||
+
|
||||
+ // Otherwise, don't flush staged updates here. We'll handle that in FramebufferVk so we can
|
||||
+ // defer clears.
|
||||
+
|
||||
if (!mImage->valid())
|
||||
{
|
||||
// Immutable texture must already have a valid image
|
||||
@@ -2217,8 +2226,6 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
|
||||
useRobustInit));
|
||||
}
|
||||
|
||||
- // Don't flush staged updates here. We'll handle that in FramebufferVk so it can defer clears.
|
||||
-
|
||||
GLuint layerIndex = 0, layerCount = 0, imageLayerCount = 0;
|
||||
GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerIndex, &layerCount,
|
||||
&imageLayerCount);
|
||||
@@ -2229,10 +2236,14 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
|
||||
gl::LevelIndex(imageIndex.getLevelIndex()),
|
||||
renderToTextureIndex);
|
||||
|
||||
- ASSERT(imageIndex.getLevelIndex() <
|
||||
- static_cast<int32_t>(mSingleLayerRenderTargets[renderToTextureIndex].size()));
|
||||
- *rtOut = &mSingleLayerRenderTargets[renderToTextureIndex][imageIndex.getLevelIndex()]
|
||||
- [layerIndex];
|
||||
+ std::vector<RenderTargetVector> &levelRenderTargets =
|
||||
+ mSingleLayerRenderTargets[renderToTextureIndex];
|
||||
+ ASSERT(imageIndex.getLevelIndex() < static_cast<int32_t>(levelRenderTargets.size()));
|
||||
+
|
||||
+ RenderTargetVector &layerRenderTargets = levelRenderTargets[imageIndex.getLevelIndex()];
|
||||
+ ASSERT(imageIndex.getLayerIndex() < static_cast<int32_t>(layerRenderTargets.size()));
|
||||
+
|
||||
+ *rtOut = &layerRenderTargets[layerIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
index cd733be3ae5c179860d882e305ec84d093a283ed..c0b745978ae5d28d97bb833f7fe6278872d8d620 100644
|
||||
--- a/src/tests/gl_tests/FramebufferTest.cpp
|
||||
+++ b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
@@ -3427,6 +3427,25 @@ TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+// Tests redefining a layered framebuffer attachment.
|
||||
+TEST_P(FramebufferTest_ES3, RedefineLayerAttachment)
|
||||
+{
|
||||
+ GLTexture texture;
|
||||
+ glBindTexture(GL_TEXTURE_3D, texture);
|
||||
+ std::vector<uint8_t> imgData(20480, 0);
|
||||
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, 8, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, imgData.data());
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 8);
|
||||
+ glGenerateMipmap(GL_TEXTURE_3D);
|
||||
+
|
||||
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, 16, 16, 16, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
|
||||
+ imgData.data());
|
||||
+ glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 2, 15, 16, 16);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
ANGLE_INSTANTIATE_TEST_ES2(AddMockTextureNoRenderTargetTest);
|
||||
ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
|
||||
@@ -0,0 +1,109 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 1 Mar 2022 16:14:47 -0500
|
||||
Subject: Protect against deleting a current XFB buffer.
|
||||
|
||||
Bug: chromium:1295411
|
||||
Change-Id: I097f272c38e444e0af71aa55c0dc508a07aa0bd3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3498262
|
||||
Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit d9002eef2a5f27fc5d6b65d01d02afcfb9a35db1)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3514175
|
||||
Reviewed-by: Ian Elliott <ianelliott@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
|
||||
index 751830e3a66a017dddb2f635df3b635a50521a96..f06666ebc78f6eb09ed015d8f17d6d1eebe88f1e 100644
|
||||
--- a/src/libANGLE/State.cpp
|
||||
+++ b/src/libANGLE/State.cpp
|
||||
@@ -2105,6 +2105,10 @@ angle::Result State::detachBuffer(Context *context, const Buffer *buffer)
|
||||
if (curTransformFeedback)
|
||||
{
|
||||
ANGLE_TRY(curTransformFeedback->detachBuffer(context, bufferID));
|
||||
+ if (isTransformFeedbackActiveUnpaused())
|
||||
+ {
|
||||
+ context->getStateCache().onActiveTransformFeedbackChange(context);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (getVertexArray()->detachBuffer(context, bufferID))
|
||||
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
|
||||
index 80332ec0bfe6bd369ec11959cb3cbd376e4ffb02..fd62cc02414841a59ba10262bf69198acdcf0c90 100644
|
||||
--- a/src/libANGLE/validationES.cpp
|
||||
+++ b/src/libANGLE/validationES.cpp
|
||||
@@ -3877,6 +3877,14 @@ const char *ValidateDrawStates(const Context *context)
|
||||
return kTessellationShaderRequiresBothControlAndEvaluation;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (state.isTransformFeedbackActiveUnpaused())
|
||||
+ {
|
||||
+ if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
|
||||
+ {
|
||||
+ return kTransformFeedbackBufferMissing;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
if (programIsYUVOutput != framebufferIsYUV)
|
||||
@@ -7949,4 +7957,21 @@ bool ValidateInvalidateTextureANGLE(const Context *context, TextureType target)
|
||||
return true;
|
||||
}
|
||||
|
||||
+bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
|
||||
+ const ProgramExecutable *programExecutable)
|
||||
+{
|
||||
+ size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
|
||||
+ const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
|
||||
+ for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
|
||||
+ {
|
||||
+ const OffsetBindingPointer<Buffer> &buffer =
|
||||
+ transformFeedback->getIndexedBuffer(programXfbIndex);
|
||||
+ if (!buffer.get())
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
} // namespace gl
|
||||
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
|
||||
index f7daadb3de4d0a28f1896bad54bdc59f31a45cd3..934a35f6557462fd8da52fd7de7aba0ee5186dff 100644
|
||||
--- a/src/libANGLE/validationES.h
|
||||
+++ b/src/libANGLE/validationES.h
|
||||
@@ -755,6 +755,9 @@ bool ValidateGetMultisamplefvBase(const Context *context,
|
||||
const GLfloat *val);
|
||||
bool ValidateSampleMaskiBase(const Context *context, GLuint maskNumber, GLbitfield mask);
|
||||
|
||||
+bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
|
||||
+ const ProgramExecutable *programExecutable);
|
||||
+
|
||||
// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
|
||||
// implementation format info for incomplete framebuffers. It seems like these queries are
|
||||
// incongruent with the other errors.
|
||||
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
|
||||
index a41744a48bac533203a37d6977976b32888d7925..26069686fc110ba603fc7195db1248b17d052c14 100644
|
||||
--- a/src/libANGLE/validationES3.cpp
|
||||
+++ b/src/libANGLE/validationES3.cpp
|
||||
@@ -2786,16 +2786,10 @@ bool ValidateBeginTransformFeedback(const Context *context, PrimitiveMode primit
|
||||
return false;
|
||||
}
|
||||
|
||||
- size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
|
||||
- for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
|
||||
+ if (!ValidateProgramExecutableXFBBuffersPresent(context, programExecutable))
|
||||
{
|
||||
- const OffsetBindingPointer<Buffer> &buffer =
|
||||
- transformFeedback->getIndexedBuffer(programXfbIndex);
|
||||
- if (!buffer.get())
|
||||
- {
|
||||
- context->validationError(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
|
||||
- return false;
|
||||
- }
|
||||
+ context->validationError(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
112
patches/angle/m98_vulkan_fix_vkcmdresolveimage_extents.patch
Normal file
112
patches/angle/m98_vulkan_fix_vkcmdresolveimage_extents.patch
Normal file
@@ -0,0 +1,112 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 31 Jan 2022 12:07:43 -0500
|
||||
Subject: M98: Vulkan: Fix vkCmdResolveImage extents
|
||||
|
||||
The source framebuffer's extents were accidentally used instead of the
|
||||
blit area extents.
|
||||
|
||||
Bug: chromium:1288020
|
||||
Change-Id: I5c6128a191deeea2f972dc7f010be9d40c674ce6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3457022
|
||||
Reviewed-by: Tim Van Patten <timvp@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
index 7d088be90bc7a384ec7d6934bccddea28f8cfa0a..892983bd1ad52c6e0080c977022689c1d6a20ac5 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
@@ -1459,8 +1459,8 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
|
||||
resolveRegion.dstOffset.x = params.destOffset[0];
|
||||
resolveRegion.dstOffset.y = params.destOffset[1];
|
||||
resolveRegion.dstOffset.z = 0;
|
||||
- resolveRegion.extent.width = params.srcExtents[0];
|
||||
- resolveRegion.extent.height = params.srcExtents[1];
|
||||
+ resolveRegion.extent.width = params.blitArea.width;
|
||||
+ resolveRegion.extent.height = params.blitArea.height;
|
||||
resolveRegion.extent.depth = 1;
|
||||
|
||||
vk::PerfCounters &perfCounters = contextVk->getPerfCounters();
|
||||
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
|
||||
index dddb58fd10e4671e179f1db21781c750d7234460..72e32c27efabe8393ae840a9fef4ce37b3c5088c 100644
|
||||
--- a/src/tests/angle_end2end_tests_expectations.txt
|
||||
+++ b/src/tests/angle_end2end_tests_expectations.txt
|
||||
@@ -68,6 +68,7 @@
|
||||
// the test says. The test also fails on Intel/Vulkan/Windows.
|
||||
6068 INTEL VULKAN : MultiviewRenderPrimitiveTest.LineLoop/* = SKIP
|
||||
6068 INTEL VULKAN : MultiviewRenderPrimitiveTest.LineStrip/* = SKIP
|
||||
+6962 WIN INTEL VULKAN : BlitFramebufferTestES31.PartialResolve/* = SKIP
|
||||
|
||||
// Mac
|
||||
6025 MAC AMD OPENGL : IndexBufferOffsetTestES3.UseAsUBOThenUpdateThenUInt8Index/* = SKIP
|
||||
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
index 61f462cf4ce20b6fe14e7cab7c77b1498c1c2aa3..02f7d025d52f50fd067aea1b8ef1057afdfd4657 100644
|
||||
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
@@ -2632,6 +2632,67 @@ TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixel)
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
}
|
||||
|
||||
+// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was using the src extents
|
||||
+// as the resolve area instead of the area passed to glBlitFramebuffer.
|
||||
+TEST_P(BlitFramebufferTestES31, PartialResolve)
|
||||
+{
|
||||
+ constexpr GLint kWidth = 16;
|
||||
+ constexpr GLint kHeight = 32;
|
||||
+
|
||||
+ // Read framebuffer is multisampled.
|
||||
+ GLTexture readTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, readTexture);
|
||||
+ glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, GL_TRUE);
|
||||
+
|
||||
+ GLFramebuffer readFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
+ readTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(1, 0, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ // Draw framebuffer is single sampled. It's bound to a texture with base level the same size as
|
||||
+ // the read framebuffer, but it's bound to mip 1.
|
||||
+ GLTexture drawTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D, drawTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ nullptr);
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D);
|
||||
+
|
||||
+ GLFramebuffer drawFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawTexture, 1);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(0, 1, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kHeight / 2, GLColor::green);
|
||||
+
|
||||
+ constexpr GLint kResolveX0 = 1;
|
||||
+ constexpr GLint kResolveY0 = 2;
|
||||
+ constexpr GLint kResolveX1 = 4;
|
||||
+ constexpr GLint kResolveY1 = 6;
|
||||
+
|
||||
+ // Resolve only a portion of the read framebuffer.
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
|
||||
+ glBlitFramebuffer(kResolveX0, kResolveY0, kResolveX1, kResolveY1, kResolveX0, kResolveY0,
|
||||
+ kResolveX1, kResolveY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kResolveY0, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kResolveX0, kHeight / 2, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(kResolveX1, 0, kWidth / 2 - kResolveX1, kHeight / 2, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, kResolveY1, kWidth / 2, kHeight / 2 - kResolveY1, GLColor::green);
|
||||
+
|
||||
+ EXPECT_PIXEL_RECT_EQ(kResolveX0, kResolveY0, kResolveX1 - kResolveX0, kResolveY1 - kResolveY0,
|
||||
+ GLColor::red);
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BlitFramebufferANGLETest);
|
||||
109
patches/angle/m98_vulkan_fix_vkcmdresolveimage_offsets.patch
Normal file
109
patches/angle/m98_vulkan_fix_vkcmdresolveimage_offsets.patch
Normal file
@@ -0,0 +1,109 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 7 Feb 2022 13:46:46 -0500
|
||||
Subject: M98: Vulkan: Fix vkCmdResolveImage offsets
|
||||
|
||||
glBlitFramebuffer takes identical regions for src and dst when
|
||||
resolving. vkCmdResolveImage should use the clipped area instead of
|
||||
using the actual offsets passed to this function.
|
||||
|
||||
Bug: chromium:1292537
|
||||
Change-Id: If283a8acbca3249b771facbc30bd9f8080a03656
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3457023
|
||||
Reviewed-by: Tim Van Patten <timvp@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
index 892983bd1ad52c6e0080c977022689c1d6a20ac5..7fc8e785af2c9c50f624790eccf5f57ce4af2c87 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
@@ -1451,13 +1451,13 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
|
||||
resolveRegion.srcSubresource.mipLevel = 0;
|
||||
resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
|
||||
resolveRegion.srcSubresource.layerCount = 1;
|
||||
- resolveRegion.srcOffset.x = params.srcOffset[0];
|
||||
- resolveRegion.srcOffset.y = params.srcOffset[1];
|
||||
+ resolveRegion.srcOffset.x = params.blitArea.x;
|
||||
+ resolveRegion.srcOffset.y = params.blitArea.y;
|
||||
resolveRegion.srcOffset.z = 0;
|
||||
resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
resolveRegion.dstSubresource.layerCount = 1;
|
||||
- resolveRegion.dstOffset.x = params.destOffset[0];
|
||||
- resolveRegion.dstOffset.y = params.destOffset[1];
|
||||
+ resolveRegion.dstOffset.x = params.blitArea.x;
|
||||
+ resolveRegion.dstOffset.y = params.blitArea.y;
|
||||
resolveRegion.dstOffset.z = 0;
|
||||
resolveRegion.extent.width = params.blitArea.width;
|
||||
resolveRegion.extent.height = params.blitArea.height;
|
||||
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
|
||||
index 72e32c27efabe8393ae840a9fef4ce37b3c5088c..87041f3b43a9ab50a0ec87ea4c338b498024b1b5 100644
|
||||
--- a/src/tests/angle_end2end_tests_expectations.txt
|
||||
+++ b/src/tests/angle_end2end_tests_expectations.txt
|
||||
@@ -15,6 +15,8 @@
|
||||
6142 VULKAN : BlitFramebufferTest.BlitDepthStencilPixelByPixel/* = SKIP
|
||||
6153 VULKAN WIN INTEL : GLSLTest_ES31.StructAndArrayEqualOperator/ES3_1_Vulkan_DirectSPIRVGen = SKIP
|
||||
6153 VULKAN PIXEL4ORXL : GLSLTest_ES31.StructAndArrayEqualOperator/ES3_1_Vulkan_DirectSPIRVGen = SKIP
|
||||
+6989 OPENGL : BlitFramebufferTestES31.OOBResolve/* = SKIP
|
||||
+6989 GLES : BlitFramebufferTestES31.OOBResolve/* = SKIP
|
||||
|
||||
// SPIR-V generation doesn't yet support bools in interface blocks
|
||||
4889 VULKAN : GLSLTest.NestedSequenceOperatorWithTernaryInside/ES2_Vulkan_DirectSPIRVGen = SKIP
|
||||
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
index 02f7d025d52f50fd067aea1b8ef1057afdfd4657..ae2844d072ee5ab4c584bfa663b955994c011b0c 100644
|
||||
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
@@ -2632,6 +2632,55 @@ TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixel)
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
}
|
||||
|
||||
+// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was used with
|
||||
+// out-of-bounds regions.
|
||||
+TEST_P(BlitFramebufferTestES31, OOBResolve)
|
||||
+{
|
||||
+ constexpr GLint kWidth = 16;
|
||||
+ constexpr GLint kHeight = 32;
|
||||
+
|
||||
+ // Read framebuffer is multisampled.
|
||||
+ GLTexture readTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, readTexture);
|
||||
+ glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, GL_TRUE);
|
||||
+
|
||||
+ GLFramebuffer readFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
+ readTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(1, 0, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ // Draw framebuffer is single sampled.
|
||||
+ GLTexture drawTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D, drawTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ nullptr);
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D);
|
||||
+
|
||||
+ GLFramebuffer drawFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(0, 1, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
|
||||
+
|
||||
+ // Resolve the read framebuffer, using bounds that are outside the size of the image.
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
|
||||
+ glBlitFramebuffer(-kWidth * 2, -kHeight * 3, kWidth * 11, kHeight * 8, -kWidth * 2,
|
||||
+ -kHeight * 3, kWidth * 11, kHeight * 8, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
|
||||
+}
|
||||
+
|
||||
// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was using the src extents
|
||||
// as the resolve area instead of the area passed to glBlitFramebuffer.
|
||||
TEST_P(BlitFramebufferTestES31, PartialResolve)
|
||||
@@ -0,0 +1,303 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Roman Lavrov <romanl@google.com>
|
||||
Date: Tue, 18 Jan 2022 20:05:55 +0000
|
||||
Subject: M99: Vulkan: Prevent out of bounds read in divisor emulation path.
|
||||
|
||||
Split the replicated part of StreamVertexData out to
|
||||
StreamVertexDataWithDivisor, there is only a partial argument
|
||||
overlap between the two.
|
||||
|
||||
Bug: chromium:1285885
|
||||
Change-Id: Ibf6ab3efc6b12b430b1d391c6ae61bd9668b4407
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3398816
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Roman Lavrov <romanl@google.com>
|
||||
(cherry picked from commit 5f0badf4541ba52659c937cfe9190d3735a76c10)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3461414
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
index ed416508cab06797a8c4d52e7ab982d538f57e3c..1ca486af3ff004e11aea82c391b4c504b569096c 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
@@ -81,34 +81,62 @@ angle::Result StreamVertexData(ContextVk *contextVk,
|
||||
size_t destOffset,
|
||||
size_t vertexCount,
|
||||
size_t sourceStride,
|
||||
- size_t destStride,
|
||||
VertexCopyFunction vertexLoadFunction,
|
||||
vk::BufferHelper **bufferOut,
|
||||
- VkDeviceSize *bufferOffsetOut,
|
||||
- uint32_t replicateCount)
|
||||
+ VkDeviceSize *bufferOffsetOut)
|
||||
{
|
||||
uint8_t *dst = nullptr;
|
||||
ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, nullptr, bufferOffsetOut,
|
||||
nullptr));
|
||||
*bufferOut = dynamicBuffer->getCurrentBuffer();
|
||||
dst += destOffset;
|
||||
- if (replicateCount == 1)
|
||||
+ vertexLoadFunction(sourceData, sourceStride, vertexCount, dst);
|
||||
+
|
||||
+ ANGLE_TRY(dynamicBuffer->flush(contextVk));
|
||||
+ return angle::Result::Continue;
|
||||
+}
|
||||
+
|
||||
+angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
+ vk::DynamicBuffer *dynamicBuffer,
|
||||
+ const uint8_t *sourceData,
|
||||
+ size_t bytesToAllocate,
|
||||
+ size_t sourceStride,
|
||||
+ size_t destStride,
|
||||
+ VertexCopyFunction vertexLoadFunction,
|
||||
+ vk::BufferHelper **bufferOut,
|
||||
+ VkDeviceSize *bufferOffsetOut,
|
||||
+ uint32_t divisor,
|
||||
+ size_t numSrcVertices)
|
||||
+{
|
||||
+ uint8_t *dst = nullptr;
|
||||
+ ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, nullptr, bufferOffsetOut,
|
||||
+ nullptr));
|
||||
+ *bufferOut = dynamicBuffer->getCurrentBuffer();
|
||||
+
|
||||
+ // Each source vertex is used `divisor` times before advancing. Clamp to avoid OOB reads.
|
||||
+ size_t clampedSize = std::min(numSrcVertices * destStride * divisor, bytesToAllocate);
|
||||
+
|
||||
+ ASSERT(clampedSize % destStride == 0);
|
||||
+ ASSERT(divisor > 0);
|
||||
+
|
||||
+ uint32_t sourceVertexUseCount = 0;
|
||||
+ for (size_t dataCopied = 0; dataCopied < clampedSize; dataCopied += destStride, dst += destStride)
|
||||
{
|
||||
- vertexLoadFunction(sourceData, sourceStride, vertexCount, dst);
|
||||
+ vertexLoadFunction(sourceData, sourceStride, 1, dst);
|
||||
+ sourceVertexUseCount++;
|
||||
+ if (sourceVertexUseCount == divisor)
|
||||
+ {
|
||||
+ sourceData += sourceStride;
|
||||
+ sourceVertexUseCount = 0;
|
||||
+ }
|
||||
}
|
||||
- else
|
||||
+
|
||||
+ // Satisfy robustness constraints (only if extension enabled)
|
||||
+ if (contextVk->getExtensions().robustness)
|
||||
{
|
||||
- ASSERT(replicateCount > 1);
|
||||
- uint32_t sourceRemainingCount = replicateCount - 1;
|
||||
- for (size_t dataCopied = 0; dataCopied < bytesToAllocate;
|
||||
- dataCopied += destStride, dst += destStride, sourceRemainingCount--)
|
||||
+ if (clampedSize < bytesToAllocate)
|
||||
{
|
||||
- vertexLoadFunction(sourceData, sourceStride, 1, dst);
|
||||
- if (sourceRemainingCount == 0)
|
||||
- {
|
||||
- sourceData += sourceStride;
|
||||
- sourceRemainingCount = replicateCount;
|
||||
- }
|
||||
+ memset(dst + clampedSize, 0, bytesToAllocate - clampedSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +152,7 @@ size_t GetVertexCount(BufferVk *srcBuffer, const gl::VertexBinding &binding, uin
|
||||
return 0;
|
||||
|
||||
// Count the last vertex. It may occupy less than a full stride.
|
||||
+ // This is also correct if stride happens to be less than srcFormatSize.
|
||||
size_t numVertices = 1;
|
||||
bytes -= srcFormatSize;
|
||||
|
||||
@@ -452,8 +481,8 @@ angle::Result VertexArrayVk::convertVertexBufferCPU(ContextVk *contextVk,
|
||||
ASSERT(GetVertexInputAlignment(vertexFormat, compressed) <= vk::kVertexBufferAlignment);
|
||||
ANGLE_TRY(StreamVertexData(
|
||||
contextVk, &conversion->data, srcBytes, numVertices * dstFormatSize, 0, numVertices,
|
||||
- binding.getStride(), srcFormatSize, vertexFormat.getVertexLoadFunction(compressed),
|
||||
- &mCurrentArrayBuffers[attribIndex], &conversion->lastAllocationOffset, 1));
|
||||
+ binding.getStride(), vertexFormat.getVertexLoadFunction(compressed),
|
||||
+ &mCurrentArrayBuffers[attribIndex], &conversion->lastAllocationOffset));
|
||||
ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
|
||||
|
||||
ASSERT(conversion->dirty);
|
||||
@@ -808,28 +837,41 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context,
|
||||
// Instanced attrib
|
||||
if (divisor > renderer->getMaxVertexAttribDivisor())
|
||||
{
|
||||
- // Emulated attrib
|
||||
- BufferVk *bufferVk = nullptr;
|
||||
+ // Divisor will be set to 1 & so update buffer to have 1 attrib per instance
|
||||
+ size_t bytesToAllocate = instanceCount * stride;
|
||||
+
|
||||
if (binding.getBuffer().get() != nullptr)
|
||||
{
|
||||
// Map buffer to expand attribs for divisor emulation
|
||||
- bufferVk = vk::GetImpl(binding.getBuffer().get());
|
||||
- void *buffSrc = nullptr;
|
||||
+ BufferVk *bufferVk = vk::GetImpl(binding.getBuffer().get());
|
||||
+ void *buffSrc = nullptr;
|
||||
ANGLE_TRY(bufferVk->mapImpl(contextVk, &buffSrc));
|
||||
src = reinterpret_cast<const uint8_t *>(buffSrc) + binding.getOffset();
|
||||
- }
|
||||
- // Divisor will be set to 1 & so update buffer to have 1 attrib per instance
|
||||
- size_t bytesToAllocate = instanceCount * stride;
|
||||
|
||||
- ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, 0,
|
||||
- instanceCount, binding.getStride(), stride,
|
||||
- vertexFormat.vertexLoadFunction,
|
||||
- &mCurrentArrayBuffers[attribIndex],
|
||||
- &mCurrentArrayBufferOffsets[attribIndex], divisor));
|
||||
- if (bufferVk)
|
||||
- {
|
||||
+ uint32_t srcAttributeSize =
|
||||
+ static_cast<uint32_t>(ComputeVertexAttributeTypeSize(attrib));
|
||||
+
|
||||
+ size_t numVertices = GetVertexCount(bufferVk, binding, srcAttributeSize);
|
||||
+
|
||||
+ ANGLE_TRY(StreamVertexDataWithDivisor(
|
||||
+ contextVk, &mDynamicVertexData, src, bytesToAllocate, binding.getStride(),
|
||||
+ stride, vertexFormat.vertexLoadFunction,
|
||||
+ &mCurrentArrayBuffers[attribIndex],
|
||||
+ &mCurrentArrayBufferOffsets[attribIndex], divisor,
|
||||
+ numVertices));
|
||||
+
|
||||
ANGLE_TRY(bufferVk->unmapImpl(contextVk));
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ size_t numVertices = instanceCount;
|
||||
+ ANGLE_TRY(StreamVertexDataWithDivisor(
|
||||
+ contextVk, &mDynamicVertexData, src, bytesToAllocate, binding.getStride(),
|
||||
+ stride, vertexFormat.vertexLoadFunction,
|
||||
+ &mCurrentArrayBuffers[attribIndex],
|
||||
+ &mCurrentArrayBufferOffsets[attribIndex], divisor,
|
||||
+ numVertices));
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -838,10 +880,10 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context,
|
||||
size_t bytesToAllocate = count * stride;
|
||||
|
||||
ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, 0,
|
||||
- count, binding.getStride(), stride,
|
||||
+ count, binding.getStride(),
|
||||
vertexFormat.vertexLoadFunction,
|
||||
&mCurrentArrayBuffers[attribIndex],
|
||||
- &mCurrentArrayBufferOffsets[attribIndex], 1));
|
||||
+ &mCurrentArrayBufferOffsets[attribIndex]));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -856,8 +898,8 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context,
|
||||
|
||||
ANGLE_TRY(StreamVertexData(
|
||||
contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
|
||||
- binding.getStride(), stride, vertexFormat.vertexLoadFunction,
|
||||
- &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex], 1));
|
||||
+ binding.getStride(), vertexFormat.vertexLoadFunction,
|
||||
+ &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
|
||||
}
|
||||
|
||||
mCurrentArrayBufferHandles[attribIndex] =
|
||||
diff --git a/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp b/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp
|
||||
index 08917a2de3385eb853bced1dd576aff46f34f709..db708b0a2a3ce90a370b43786af6884b2f992bef 100644
|
||||
--- a/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp
|
||||
+++ b/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp
|
||||
@@ -564,6 +564,98 @@ TEST_P(RobustBufferAccessBehaviorTest, DynamicBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
+// Tests out of bounds read by divisor emulation due to a user-provided offset.
|
||||
+// Adapted from https://crbug.com/1285885.
|
||||
+TEST_P(RobustBufferAccessBehaviorTest, IndexOutOfBounds)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!initExtension());
|
||||
+
|
||||
+ constexpr char kVS[] = R"(precision highp float;
|
||||
+attribute vec4 a_position;
|
||||
+void main(void) {
|
||||
+ gl_Position = a_position;
|
||||
+})";
|
||||
+
|
||||
+ constexpr char kFS[] = R"(precision highp float;
|
||||
+uniform sampler2D oTexture;
|
||||
+uniform float oColor[3];
|
||||
+void main(void) {
|
||||
+ gl_FragData[0] = texture2DProj(oTexture, vec3(0.1,0.1,0.1));
|
||||
+})";
|
||||
+
|
||||
+ GLfloat singleFloat = 1.0f;
|
||||
+
|
||||
+ GLBuffer buf;
|
||||
+ glBindBuffer(GL_ARRAY_BUFFER, buf);
|
||||
+ glBufferData(GL_ARRAY_BUFFER, 4, &singleFloat, GL_STATIC_DRAW);
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glBindAttribLocation(program, 0, "a_position");
|
||||
+ glLinkProgram(program);
|
||||
+ ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
|
||||
+
|
||||
+ glEnableVertexAttribArray(0);
|
||||
+
|
||||
+ // Trying to exceed renderer->getMaxVertexAttribDivisor()
|
||||
+ GLuint constexpr kDivisor = 4096;
|
||||
+ glVertexAttribDivisor(0, kDivisor);
|
||||
+
|
||||
+ size_t outOfBoundsOffset = 0x50000000;
|
||||
+ glVertexAttribPointer(0, 1, GL_FLOAT, false, 8, reinterpret_cast<void *>(outOfBoundsOffset));
|
||||
+
|
||||
+ glUseProgram(program);
|
||||
+
|
||||
+ glDrawArrays(GL_TRIANGLES, 0, 32);
|
||||
+
|
||||
+ // No assertions, just checking for crashes.
|
||||
+}
|
||||
+
|
||||
+// Similar to the test above but index is first within bounds then goes out of bounds.
|
||||
+TEST_P(RobustBufferAccessBehaviorTest, IndexGoingOutOfBounds)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!initExtension());
|
||||
+
|
||||
+ constexpr char kVS[] = R"(precision highp float;
|
||||
+attribute vec4 a_position;
|
||||
+void main(void) {
|
||||
+ gl_Position = a_position;
|
||||
+})";
|
||||
+
|
||||
+ constexpr char kFS[] = R"(precision highp float;
|
||||
+uniform sampler2D oTexture;
|
||||
+uniform float oColor[3];
|
||||
+void main(void) {
|
||||
+ gl_FragData[0] = texture2DProj(oTexture, vec3(0.1,0.1,0.1));
|
||||
+})";
|
||||
+
|
||||
+ GLBuffer buf;
|
||||
+ glBindBuffer(GL_ARRAY_BUFFER, buf);
|
||||
+ std::array<GLfloat, 2> buffer = {{0.2f, 0.2f}};
|
||||
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * buffer.size(), buffer.data(), GL_STATIC_DRAW);
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glBindAttribLocation(program, 0, "a_position");
|
||||
+ glLinkProgram(program);
|
||||
+ ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
|
||||
+
|
||||
+ glEnableVertexAttribArray(0);
|
||||
+
|
||||
+ // Trying to exceed renderer->getMaxVertexAttribDivisor()
|
||||
+ GLuint constexpr kDivisor = 4096;
|
||||
+ glVertexAttribDivisor(0, kDivisor);
|
||||
+
|
||||
+ // 6 bytes remaining in the buffer from offset so only a single vertex can be read
|
||||
+ glVertexAttribPointer(0, 1, GL_FLOAT, false, 8, reinterpret_cast<void *>(2));
|
||||
+
|
||||
+ glUseProgram(program);
|
||||
+
|
||||
+ // Each vertex is read `kDivisor` times so the last read goes out of bounds
|
||||
+ GLsizei instanceCount = kDivisor + 1;
|
||||
+ glDrawArraysInstanced(GL_TRIANGLES, 0, 32, instanceCount);
|
||||
+
|
||||
+ // No assertions, just checking for crashes.
|
||||
+}
|
||||
+
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(RobustBufferAccessBehaviorTest);
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Charlie Lao <cclao@google.com>
|
||||
Date: Mon, 7 Feb 2022 15:08:15 -0800
|
||||
Subject: M99: Vulkan: StreamVertexDataWithDivisor write beyond buffer boundary
|
||||
|
||||
StreamVertexDataWithDivisor() function is advancing dst with dstStride,
|
||||
but then later on it is treating dst as if it never advanced, thus
|
||||
result in write out of buffer boundary. This was hidden by VMA's memory
|
||||
suballocation, which means it may result in some rendering artifacts.
|
||||
|
||||
Bug: angleproject:6990
|
||||
Change-Id: Ic91e917cedd247dfe85b12a69ae26b21b7a4e67a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3445528
|
||||
Reviewed-by: Roman Lavrov <romanl@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Commit-Queue: Charlie Lao <cclao@google.com>
|
||||
(cherry picked from commit 5204587698099207ce8ae70779ef44ffae877996)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3461417
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
Commit-Queue: Roman Lavrov <romanl@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
index 1ca486af3ff004e11aea82c391b4c504b569096c..93378c4b24495872405fc06ea01e15254229ab63 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
@@ -120,7 +120,7 @@ angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
ASSERT(divisor > 0);
|
||||
|
||||
uint32_t sourceVertexUseCount = 0;
|
||||
- for (size_t dataCopied = 0; dataCopied < clampedSize; dataCopied += destStride, dst += destStride)
|
||||
+ for (size_t dataCopied = 0; dataCopied < clampedSize; dataCopied += destStride)
|
||||
{
|
||||
vertexLoadFunction(sourceData, sourceStride, 1, dst);
|
||||
sourceVertexUseCount++;
|
||||
@@ -129,6 +129,7 @@ angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
sourceData += sourceStride;
|
||||
sourceVertexUseCount = 0;
|
||||
}
|
||||
+ dst += destStride;
|
||||
}
|
||||
|
||||
// Satisfy robustness constraints (only if extension enabled)
|
||||
@@ -136,7 +137,7 @@ angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
{
|
||||
if (clampedSize < bytesToAllocate)
|
||||
{
|
||||
- memset(dst + clampedSize, 0, bytesToAllocate - clampedSize);
|
||||
+ memset(dst, 0, bytesToAllocate - clampedSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
expose_ripemd160.patch
|
||||
expose_aes-cfb.patch
|
||||
expose_des-ede3.patch
|
||||
enable_x509_v_flag_trusted_first_flag.patch
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Juan Cruz Viotti <jv@jviotti.com>
|
||||
Date: Thu, 30 Sep 2021 13:39:23 -0400
|
||||
Subject: Enable X509_V_FLAG_TRUSTED_FIRST flag
|
||||
|
||||
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
|
||||
|
||||
diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c
|
||||
index 5a881d64c30076404cc800fff9e943bb0b30d2ac..29d5341efc8eb7ae6f90bdde5a8032e99f75c98e 100644
|
||||
--- a/crypto/x509/x509_vpm.c
|
||||
+++ b/crypto/x509/x509_vpm.c
|
||||
@@ -528,7 +528,7 @@ static const X509_VERIFY_PARAM default_table[] = {
|
||||
(char *)"default", /* X509 default parameters */
|
||||
0, /* Check time */
|
||||
0, /* internal flags */
|
||||
- 0, /* flags */
|
||||
+ X509_V_FLAG_TRUSTED_FIRST, /* flags */
|
||||
0, /* purpose */
|
||||
0, /* trust */
|
||||
100, /* depth */
|
||||
@@ -105,3 +105,55 @@ revert_roll_clang_llvmorg-13-init-14732-g8a7b5ebf-2.patch
|
||||
logging_win32_only_create_a_console_if_logging_to_stderr.patch
|
||||
fix_media_key_usage_with_globalshortcuts.patch
|
||||
cherry-pick-f8a74d72f328.patch
|
||||
cherry-pick-f2fd53c6d706.patch
|
||||
cherry-pick-096afc1c5428.patch
|
||||
cherry-pick-4e528a5a8d83.patch
|
||||
cherry-pick-3a5bafa35def.patch
|
||||
cherry-pick-b2c4e4dc21e5.patch
|
||||
m90-lts_prevents_non-browser_processes_from_requesting_memory.patch
|
||||
check_direction_of_rtcencodedframes.patch
|
||||
cherry-pick-c69dddfe1cde.patch
|
||||
speculative_fix_for_eye_dropper_getcolor_crash.patch
|
||||
cherry-pick-0894af410c4e.patch
|
||||
move_networkstateobserver_from_document_to_window.patch
|
||||
cherry-pick-8af66de55aad.patch
|
||||
cherry-pick-91dd4f79ab5b.patch
|
||||
cherry-pick-45f9dcf5021d.patch
|
||||
cherry-pick-1a8af2da50e4.patch
|
||||
cachestorage_store_partial_opaque_responses.patch
|
||||
introduce_crossthreadcopier_skbitmap.patch
|
||||
allow_null_skbitmap_to_be_transferred_across_threads.patch
|
||||
use_weakptrs_for_the_threadediconloader_s_background_tasks.patch
|
||||
cherry-pick-a5f54612590d.patch
|
||||
mas_gate_private_enterprise_APIs.patch
|
||||
fix_aspect_ratio_with_max_size.patch
|
||||
cherry-pick-f0a63e1f361f.patch
|
||||
cherry-pick-27eb11a28555.patch
|
||||
cherry-pick-f781748dcb3c.patch
|
||||
sandbox_fix_sandbox_inheritance_m96_merge.patch
|
||||
cherry-pick-dbde8795233a.patch
|
||||
cherry-pick-da11d71a0227.patch
|
||||
m96_fileapi_move_origin_checks_in_bloburlstore_sooner.patch
|
||||
cherry-pick-6bb320d134b1.patch
|
||||
cherry-pick-c5571653d932.patch
|
||||
cherry-pick-1282354.patch
|
||||
cherry-pick-9db9911e1242.patch
|
||||
cherry-pick-22f27676515e.patch
|
||||
cherry-pick-1283371.patch
|
||||
cherry-pick-1283375.patch
|
||||
cherry-pick-1283198.patch
|
||||
cherry-pick-1284367.patch
|
||||
cherry-pick-be50c60b4225.patch
|
||||
cherry-pick-e3805f29fed7.patch
|
||||
m98_fs_fix_fileutil_lifetime_issue.patch
|
||||
cherry-pick-0081bb347e67.patch
|
||||
cleanup_pausablecriptexecutor_usage.patch
|
||||
cherry-pick-ebc188ad769e.patch
|
||||
cherry-pick-1277917.patch
|
||||
cherry-pick-62142d222a80.patch
|
||||
cherry-pick-1887414c016d.patch
|
||||
cherry-pick-6b2643846ae3.patch
|
||||
m96-lts_roll_libxml_from_dea91c97_to_eab86522.patch
|
||||
cherry-pick-246c10dede97.patch
|
||||
fix_imagebitmaprenderingcontext_interaction_with_software_compositor.patch
|
||||
remove_incorrect_width_height_adjustments.patch
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Tue, 9 Nov 2021 09:03:17 +0000
|
||||
Subject: Allow null SkBitmap to be transferred across threads
|
||||
|
||||
(cherry picked from commit dad0c0e5162bcc49b8f60354d3bca92224d8381b)
|
||||
|
||||
Bug: 1241091
|
||||
Change-Id: Ie96932c14c8884d6d3eafa76dab5043e7aa31888
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3251815
|
||||
Reviewed-by: Florin Malita <fmalita@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936861}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3268018
|
||||
Auto-Submit: Yutaka Hirano <yhirano@chromium.org>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Commit-Queue: Kentaro Hara <haraken@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#893}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
index 3bd49cac3f5dfcad0fcc1140fcf876fe37558930..c037b85210bf2dedeb8478cf918633ad94885048 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
@@ -209,11 +209,13 @@ struct CrossThreadCopier<SkBitmap> {
|
||||
|
||||
using Type = SkBitmap;
|
||||
static SkBitmap Copy(const SkBitmap& bitmap) {
|
||||
- CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ CHECK(bitmap.isImmutable() || bitmap.isNull())
|
||||
+ << "Only immutable bitmaps can be transferred.";
|
||||
return bitmap;
|
||||
}
|
||||
static SkBitmap Copy(SkBitmap&& bitmap) {
|
||||
- CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ CHECK(bitmap.isImmutable() || bitmap.isNull())
|
||||
+ << "Only immutable bitmaps can be transferred.";
|
||||
return std::move(bitmap);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Kelly <wanderview@chromium.org>
|
||||
Date: Fri, 5 Nov 2021 19:47:08 +0000
|
||||
Subject: CacheStorage: Store partial opaque responses.
|
||||
|
||||
(cherry picked from commit 802faa035409ac7cbb58ad1a385bb8507fe99077)
|
||||
|
||||
Fixed: 1260649
|
||||
Change-Id: If83156096e6aecec55490330d03c56c0c26120bc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3251749
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Ben Kelly <wanderview@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#937400}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3264366
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#774}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
index c1463699290a24267e7760b89fa60cea14d0e2b5..2fd0027fda9cdb75656966c16141408e9a15e4f3 100644
|
||||
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
@@ -446,10 +446,10 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
|
||||
? metadata.response().request_include_credentials()
|
||||
: true;
|
||||
|
||||
- // Note that |has_range_requested| can be safely set to false since it only
|
||||
- // affects HTTP 206 (Partial) responses, which are blocked from cache storage.
|
||||
- // See https://fetch.spec.whatwg.org/#main-fetch for usage of
|
||||
- // |has_range_requested|.
|
||||
+ // While we block most partial responses from being stored, we can have
|
||||
+ // partial responses for bgfetch or opaque responses.
|
||||
+ bool has_range_requested = headers.contains(net::HttpRequestHeaders::kRange);
|
||||
+
|
||||
return blink::mojom::FetchAPIResponse::New(
|
||||
url_list, metadata.response().status_code(),
|
||||
metadata.response().status_text(),
|
||||
@@ -467,7 +467,7 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
|
||||
static_cast<net::HttpResponseInfo::ConnectionInfo>(
|
||||
metadata.response().connection_info()),
|
||||
alpn_negotiated_protocol, metadata.response().was_fetched_via_spdy(),
|
||||
- /*has_range_requested=*/false, /*auth_challenge_info=*/absl::nullopt,
|
||||
+ has_range_requested, /*auth_challenge_info=*/absl::nullopt,
|
||||
request_include_credentials);
|
||||
}
|
||||
|
||||
@@ -1892,7 +1892,13 @@ void LegacyCacheStorageCache::PutDidCreateEntry(
|
||||
}
|
||||
|
||||
proto::CacheResponse* response_metadata = metadata.mutable_response();
|
||||
- DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
|
||||
+ if (owner_ != storage::mojom::CacheStorageOwner::kBackgroundFetch &&
|
||||
+ put_context->response->response_type !=
|
||||
+ network::mojom::FetchResponseType::kOpaque &&
|
||||
+ put_context->response->response_type !=
|
||||
+ network::mojom::FetchResponseType::kOpaqueRedirect) {
|
||||
+ DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
|
||||
+ }
|
||||
response_metadata->set_status_code(put_context->response->status_code);
|
||||
response_metadata->set_status_text(put_context->response->status_text);
|
||||
response_metadata->set_response_type(FetchResponseTypeToProtoResponseType(
|
||||
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
index e16030caf58ca90273a11863eebd58e131f71a09..8a940b10692131fd4f0f61c444eac80e18373f0a 100644
|
||||
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
@@ -102,7 +102,7 @@ void ValidateResponseForPut(const Response* response,
|
||||
exception_state.ThrowTypeError("Vary header contains *");
|
||||
return;
|
||||
}
|
||||
- if (response->GetResponse()->InternalStatus() == 206) {
|
||||
+ if (response->GetResponse()->Status() == 206) {
|
||||
exception_state.ThrowTypeError(
|
||||
"Partial response (status code 206) is unsupported");
|
||||
return;
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
index b45910a3b8ba089e1724efa8b9e8a8d679c59320..f60c4b905ebcb61854b83177d59861ef92095624 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
@@ -144,7 +144,14 @@ cache_test(function(cache, test) {
|
||||
'Test framework error: The status code should be 0 for an ' +
|
||||
' opaque-filtered response. This is actually HTTP 206.');
|
||||
response = fetch_result.clone();
|
||||
- return promise_rejects_js(test, TypeError, cache.put(request, fetch_result));
|
||||
+ return cache.put(request, fetch_result);
|
||||
+ })
|
||||
+ .then(function() {
|
||||
+ return cache.match(test_url);
|
||||
+ })
|
||||
+ .then(function(result) {
|
||||
+ assert_not_equals(result, undefined,
|
||||
+ 'Cache.put should store an entry for the opaque response');
|
||||
});
|
||||
}, 'Cache.put with opaque-filtered HTTP 206 response');
|
||||
|
||||
188
patches/chromium/check_direction_of_rtcencodedframes.patch
Normal file
188
patches/chromium/check_direction_of_rtcencodedframes.patch
Normal file
@@ -0,0 +1,188 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Herre <toprice@chromium.org>
|
||||
Date: Fri, 1 Oct 2021 19:18:45 +0000
|
||||
Subject: Check direction of RTCEncodedFrames
|
||||
|
||||
Add a check to RTCEncodedVideoUnderlyingSink of the direction of the
|
||||
underlying webrtc frame, to make sure a web app doesn't take a received
|
||||
encoded frame and pass it into a sender insertable stream, which is as
|
||||
yet unsupported in WebRTC.
|
||||
|
||||
Bug: 1247260
|
||||
Change-Id: I9ed5bd8b2bd5e5ee461f3b553f8a91f6cc2e9ed7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3190473
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Reviewed-by: Harald Alvestrand <hta@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#927323}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
|
||||
index c390ab72418194cb10c3b0bc5a83b95de8dd19f6..775b837fee46836fd292b17ac8d80e4c83bd08a8 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
|
||||
@@ -14,8 +14,10 @@ namespace blink {
|
||||
|
||||
RTCEncodedVideoUnderlyingSink::RTCEncodedVideoUnderlyingSink(
|
||||
ScriptState* script_state,
|
||||
- TransformerCallback transformer_callback)
|
||||
- : transformer_callback_(std::move(transformer_callback)) {
|
||||
+ TransformerCallback transformer_callback,
|
||||
+ webrtc::TransformableFrameInterface::Direction expected_direction)
|
||||
+ : transformer_callback_(std::move(transformer_callback)),
|
||||
+ expected_direction_(expected_direction) {
|
||||
DCHECK(transformer_callback_);
|
||||
}
|
||||
|
||||
@@ -53,6 +55,12 @@ ScriptPromise RTCEncodedVideoUnderlyingSink::write(
|
||||
return ScriptPromise();
|
||||
}
|
||||
|
||||
+ if (webrtc_frame->GetDirection() != expected_direction_) {
|
||||
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
|
||||
+ "Invalid frame");
|
||||
+ return ScriptPromise();
|
||||
+ }
|
||||
+
|
||||
RTCEncodedVideoStreamTransformer* transformer = transformer_callback_.Run();
|
||||
if (!transformer) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h
|
||||
index dd1cad227eb7947dd0bf2ec7ba217956cb7a8787..8591fcc6eb1c78d0e107e4f097d3133d111ab959 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
|
||||
#include "third_party/blink/renderer/modules/modules_export.h"
|
||||
+#include "third_party/webrtc/api/frame_transformer_interface.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -18,7 +19,9 @@ class MODULES_EXPORT RTCEncodedVideoUnderlyingSink final
|
||||
public:
|
||||
using TransformerCallback =
|
||||
base::RepeatingCallback<RTCEncodedVideoStreamTransformer*()>;
|
||||
- RTCEncodedVideoUnderlyingSink(ScriptState*, TransformerCallback);
|
||||
+ RTCEncodedVideoUnderlyingSink(ScriptState*,
|
||||
+ TransformerCallback,
|
||||
+ webrtc::TransformableFrameInterface::Direction);
|
||||
|
||||
// UnderlyingSinkBase
|
||||
ScriptPromise start(ScriptState*,
|
||||
@@ -37,6 +40,7 @@ class MODULES_EXPORT RTCEncodedVideoUnderlyingSink final
|
||||
|
||||
private:
|
||||
TransformerCallback transformer_callback_;
|
||||
+ webrtc::TransformableFrameInterface::Direction expected_direction_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
|
||||
index d06c1a735767c936d25e68e23c15a4aca7ef901a..8238bd13f9a7c3276468c76bd3aee4c56345e83a 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
|
||||
@@ -75,11 +75,15 @@ class RTCEncodedVideoUnderlyingSinkTest : public testing::Test {
|
||||
EXPECT_FALSE(transformer_.HasTransformedFrameSinkCallback(kSSRC));
|
||||
}
|
||||
|
||||
- RTCEncodedVideoUnderlyingSink* CreateSink(ScriptState* script_state) {
|
||||
+ RTCEncodedVideoUnderlyingSink* CreateSink(
|
||||
+ ScriptState* script_state,
|
||||
+ webrtc::TransformableFrameInterface::Direction expected_direction =
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender) {
|
||||
return MakeGarbageCollected<RTCEncodedVideoUnderlyingSink>(
|
||||
script_state,
|
||||
WTF::BindRepeating(&RTCEncodedVideoUnderlyingSinkTest::GetTransformer,
|
||||
- WTF::Unretained(this)));
|
||||
+ WTF::Unretained(this)),
|
||||
+ expected_direction);
|
||||
}
|
||||
|
||||
RTCEncodedVideoUnderlyingSink* CreateNullCallbackSink(
|
||||
@@ -87,14 +91,20 @@ class RTCEncodedVideoUnderlyingSinkTest : public testing::Test {
|
||||
return MakeGarbageCollected<RTCEncodedVideoUnderlyingSink>(
|
||||
script_state,
|
||||
WTF::BindRepeating(
|
||||
- []() -> RTCEncodedVideoStreamTransformer* { return nullptr; }));
|
||||
+ []() -> RTCEncodedVideoStreamTransformer* { return nullptr; }),
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender);
|
||||
}
|
||||
|
||||
RTCEncodedVideoStreamTransformer* GetTransformer() { return &transformer_; }
|
||||
|
||||
- ScriptValue CreateEncodedVideoFrameChunk(ScriptState* script_state) {
|
||||
+ ScriptValue CreateEncodedVideoFrameChunk(
|
||||
+ ScriptState* script_state,
|
||||
+ webrtc::TransformableFrameInterface::Direction direction =
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender) {
|
||||
auto mock_frame = std::make_unique<NiceMock<MockTransformableVideoFrame>>();
|
||||
+
|
||||
ON_CALL(*mock_frame.get(), GetSsrc).WillByDefault(Return(kSSRC));
|
||||
+ ON_CALL(*mock_frame.get(), GetDirection).WillByDefault(Return(direction));
|
||||
RTCEncodedVideoFrame* frame =
|
||||
MakeGarbageCollected<RTCEncodedVideoFrame>(std::move(mock_frame));
|
||||
return ScriptValue(script_state->GetIsolate(),
|
||||
@@ -175,4 +185,21 @@ TEST_F(RTCEncodedVideoUnderlyingSinkTest, WriteToNullCallbackSinkFails) {
|
||||
DOMExceptionCode::kInvalidStateError));
|
||||
}
|
||||
|
||||
+TEST_F(RTCEncodedVideoUnderlyingSinkTest, WriteInvalidDirectionFails) {
|
||||
+ V8TestingScope v8_scope;
|
||||
+ ScriptState* script_state = v8_scope.GetScriptState();
|
||||
+ auto* sink = CreateSink(
|
||||
+ script_state, webrtc::TransformableFrameInterface::Direction::kSender);
|
||||
+
|
||||
+ // Write an encoded chunk with direction set to Receiver should fail as it
|
||||
+ // doesn't match the expected direction of our sink.
|
||||
+ DummyExceptionStateForTesting dummy_exception_state;
|
||||
+ sink->write(script_state,
|
||||
+ CreateEncodedVideoFrameChunk(
|
||||
+ script_state,
|
||||
+ webrtc::TransformableFrameInterface::Direction::kReceiver),
|
||||
+ nullptr, dummy_exception_state);
|
||||
+ EXPECT_TRUE(dummy_exception_state.HadException());
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
|
||||
index 9291c4f8a10f6d822bbda0ed47c2e206eb7955eb..1838055f829337c5f9c302ad0b0703899693be25 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
|
||||
@@ -595,7 +595,8 @@ void RTCRtpReceiver::InitializeEncodedVideoStreams(ScriptState* script_state) {
|
||||
->GetEncodedVideoStreamTransformer()
|
||||
: nullptr;
|
||||
},
|
||||
- WrapWeakPersistent(this)));
|
||||
+ WrapWeakPersistent(this)),
|
||||
+ webrtc::TransformableFrameInterface::Direction::kReceiver);
|
||||
// The high water mark for the stream is set to 1 so that the stream seems
|
||||
// ready to write, but without queuing frames.
|
||||
WritableStream* writable_stream =
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
|
||||
index 9adbd0b2ba67af5cb416e95685e0993200a4bbbc..293714421b4f00b8561bf637313b5041f15d0875 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
|
||||
@@ -950,7 +950,8 @@ void RTCRtpSender::InitializeEncodedVideoStreams(ScriptState* script_state) {
|
||||
->GetEncodedVideoStreamTransformer()
|
||||
: nullptr;
|
||||
},
|
||||
- WrapWeakPersistent(this)));
|
||||
+ WrapWeakPersistent(this)),
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender);
|
||||
// The high water mark for the stream is set to 1 so that the stream is
|
||||
// ready to write, but without queuing frames.
|
||||
WritableStream* writable_stream =
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/testing/mock_transformable_video_frame.h b/third_party/blink/renderer/modules/peerconnection/testing/mock_transformable_video_frame.h
|
||||
index 4780d43ca327c3b65125ccb855cdad618c3fc6ec..1e0b12eac7bfd70247b1a74c237a63c805303c16 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/testing/mock_transformable_video_frame.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/testing/mock_transformable_video_frame.h
|
||||
@@ -27,6 +27,10 @@ class MockTransformableVideoFrame
|
||||
GetMetadata,
|
||||
(),
|
||||
(const, override));
|
||||
+ MOCK_METHOD(webrtc::TransformableFrameInterface::Direction,
|
||||
+ GetDirection,
|
||||
+ (),
|
||||
+ (const, override));
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
26
patches/chromium/cherry-pick-0081bb347e67.patch
Normal file
26
patches/chromium/cherry-pick-0081bb347e67.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Reynolds <mattreynolds@google.com>
|
||||
Date: Wed, 19 Jan 2022 21:03:08 +0000
|
||||
Subject: gamepad: Return an invalid handle after ReportBadMessage
|
||||
|
||||
Bug: 1285449
|
||||
Change-Id: I746c539577f7bdf69cbe4212ac380e0c92a5c771
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3373944
|
||||
Auto-Submit: Matt Reynolds <mattreynolds@chromium.org>
|
||||
Reviewed-by: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#961125}
|
||||
|
||||
diff --git a/device/gamepad/gamepad_monitor.cc b/device/gamepad/gamepad_monitor.cc
|
||||
index ce8ba1ef7551e52f8ae4d9a112a08308ab2ce51c..28082924e632a895fc5bc4725bc6de3d6ca120ac 100644
|
||||
--- a/device/gamepad/gamepad_monitor.cc
|
||||
+++ b/device/gamepad/gamepad_monitor.cc
|
||||
@@ -53,6 +53,8 @@ void GamepadMonitor::GamepadStartPolling(GamepadStartPollingCallback callback) {
|
||||
GamepadService* service = GamepadService::GetInstance();
|
||||
if (!service->ConsumerBecameActive(this)) {
|
||||
mojo::ReportBadMessage("GamepadMonitor::GamepadStartPolling failed");
|
||||
+ std::move(callback).Run(base::ReadOnlySharedMemoryRegion());
|
||||
+ return;
|
||||
}
|
||||
std::move(callback).Run(service->DuplicateSharedMemoryRegion());
|
||||
}
|
||||
385
patches/chromium/cherry-pick-0894af410c4e.patch
Normal file
385
patches/chromium/cherry-pick-0894af410c4e.patch
Normal file
@@ -0,0 +1,385 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Min Qin <qinmin@chromium.org>
|
||||
Date: Tue, 31 Aug 2021 23:03:03 +0000
|
||||
Subject: Quarantine save package items that's downloaded from network
|
||||
|
||||
Currently quarantine is not performed for save page downloads. This CL
|
||||
fixes the issue.
|
||||
|
||||
BUG=1243020, 811161
|
||||
|
||||
Change-Id: I85d03cc324b0b90a45bd8b3429e4e9eec1aaf857
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3126709
|
||||
Reviewed-by: Xing Liu <xingliu@chromium.org>
|
||||
Commit-Queue: Min Qin <qinmin@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#917013}
|
||||
|
||||
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc
|
||||
index df2e3571636144acfefd1b79f157fd176db46ea0..f0a2d2bd58314420cc356400acc46ab412d49aca 100644
|
||||
--- a/chrome/browser/download/save_page_browsertest.cc
|
||||
+++ b/chrome/browser/download/save_page_browsertest.cc
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "components/prefs/pref_member.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/security_state/core/security_state.h"
|
||||
+#include "components/services/quarantine/test_support.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_types.h"
|
||||
@@ -431,6 +432,10 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveFileURL) {
|
||||
EXPECT_TRUE(base::PathExists(full_file_name));
|
||||
EXPECT_FALSE(base::PathExists(dir));
|
||||
EXPECT_TRUE(base::ContentsEqual(GetTestDirFile("text.txt"), full_file_name));
|
||||
+#if defined(OS_WIN)
|
||||
+ // Local file URL will not be quarantined.
|
||||
+ EXPECT_FALSE(quarantine::IsFileQuarantined(full_file_name, GURL(), GURL()));
|
||||
+#endif
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,
|
||||
@@ -964,6 +969,25 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveUnauthorizedResource) {
|
||||
EXPECT_FALSE(base::PathExists(dir.AppendASCII("should-not-save.jpg")));
|
||||
}
|
||||
|
||||
+#if defined(OS_WIN)
|
||||
+// Save a file and confirm that the file is correctly quarantined.
|
||||
+IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveURLQuarantine) {
|
||||
+ GURL url = embedded_test_server()->GetURL("/save_page/text.txt");
|
||||
+ ui_test_utils::NavigateToURL(browser(), url);
|
||||
+
|
||||
+ base::FilePath full_file_name, dir;
|
||||
+ SaveCurrentTab(url, content::SAVE_PAGE_TYPE_AS_ONLY_HTML, "test", 1, &dir,
|
||||
+ &full_file_name);
|
||||
+ ASSERT_FALSE(HasFailure());
|
||||
+
|
||||
+ base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
+ EXPECT_TRUE(base::PathExists(full_file_name));
|
||||
+ EXPECT_FALSE(base::PathExists(dir));
|
||||
+ EXPECT_TRUE(base::ContentsEqual(GetTestDirFile("text.txt"), full_file_name));
|
||||
+ EXPECT_TRUE(quarantine::IsFileQuarantined(full_file_name, url, GURL()));
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
// Test suite that allows testing --site-per-process against cross-site frames.
|
||||
// See http://dev.chromium.org/developers/design-documents/site-isolation.
|
||||
class SavePageSitePerProcessBrowserTest : public SavePageBrowserTest {
|
||||
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
|
||||
index b7e0163ab27e1b0e42d81776ae9242f72bd43e87..b29407e76d4e6f1f7fbbe62cea445d33c789fcc3 100644
|
||||
--- a/content/browser/download/download_manager_impl.h
|
||||
+++ b/content/browser/download/download_manager_impl.h
|
||||
@@ -170,6 +170,11 @@ class CONTENT_EXPORT DownloadManagerImpl
|
||||
int frame_tree_node_id,
|
||||
bool from_download_cross_origin_redirect);
|
||||
|
||||
+ // DownloadItemImplDelegate overrides.
|
||||
+ download::QuarantineConnectionCallback GetQuarantineConnectionCallback()
|
||||
+ override;
|
||||
+ std::string GetApplicationClientIdForFileScanning() const override;
|
||||
+
|
||||
private:
|
||||
using DownloadSet = std::set<download::DownloadItem*>;
|
||||
using DownloadGuidMap =
|
||||
@@ -237,7 +242,6 @@ class CONTENT_EXPORT DownloadManagerImpl
|
||||
bool ShouldOpenDownload(download::DownloadItemImpl* item,
|
||||
ShouldOpenDownloadCallback callback) override;
|
||||
void CheckForFileRemoval(download::DownloadItemImpl* download_item) override;
|
||||
- std::string GetApplicationClientIdForFileScanning() const override;
|
||||
void ResumeInterruptedDownload(
|
||||
std::unique_ptr<download::DownloadUrlParameters> params,
|
||||
const GURL& site_url) override;
|
||||
@@ -249,8 +253,6 @@ class CONTENT_EXPORT DownloadManagerImpl
|
||||
void ReportBytesWasted(download::DownloadItemImpl* download) override;
|
||||
void BindWakeLockProvider(
|
||||
mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) override;
|
||||
- download::QuarantineConnectionCallback GetQuarantineConnectionCallback()
|
||||
- override;
|
||||
std::unique_ptr<download::DownloadItemRenameHandler>
|
||||
GetRenameHandlerForDownload(
|
||||
download::DownloadItemImpl* download_item) override;
|
||||
diff --git a/content/browser/download/save_file.cc b/content/browser/download/save_file.cc
|
||||
index 6e0cf6ed1df5db407e31be0e3a6db2e919d8e1bf..296c0cf79c9f5ee5e4ab9835394fb34ae7d92acc 100644
|
||||
--- a/content/browser/download/save_file.cc
|
||||
+++ b/content/browser/download/save_file.cc
|
||||
@@ -63,10 +63,15 @@ void SaveFile::Finish() {
|
||||
file_.Finish();
|
||||
}
|
||||
|
||||
-void SaveFile::AnnotateWithSourceInformation() {
|
||||
- // TODO(gbillock): If this method is called, it should set the
|
||||
- // file_.SetClientGuid() method first.
|
||||
- NOTREACHED();
|
||||
+void SaveFile::AnnotateWithSourceInformation(
|
||||
+ const std::string& client_guid,
|
||||
+ const GURL& source_url,
|
||||
+ const GURL& referrer_url,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ download::BaseFile::OnAnnotationDoneCallback on_annotation_done_callback) {
|
||||
+ file_.AnnotateWithSourceInformation(client_guid, source_url, referrer_url,
|
||||
+ std::move(remote_quarantine),
|
||||
+ std::move(on_annotation_done_callback));
|
||||
}
|
||||
|
||||
base::FilePath SaveFile::FullPath() const {
|
||||
diff --git a/content/browser/download/save_file.h b/content/browser/download/save_file.h
|
||||
index 688574b07f9374e75a25caaaa13bdb405aea7b0d..1893a0031f4c6642c6c806577da2246e55e49091 100644
|
||||
--- a/content/browser/download/save_file.h
|
||||
+++ b/content/browser/download/save_file.h
|
||||
@@ -34,7 +34,12 @@ class SaveFile {
|
||||
void Detach();
|
||||
void Cancel();
|
||||
void Finish();
|
||||
- void AnnotateWithSourceInformation();
|
||||
+ void AnnotateWithSourceInformation(
|
||||
+ const std::string& client_guid,
|
||||
+ const GURL& source_url,
|
||||
+ const GURL& referrer_url,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ download::BaseFile::OnAnnotationDoneCallback on_annotation_done_callback);
|
||||
base::FilePath FullPath() const;
|
||||
bool InProgress() const;
|
||||
int64_t BytesSoFar() const;
|
||||
diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc
|
||||
index bb322825a449920001b3c09fce33d3ed7e4d82da..98ce67d548d0880ed187779a0e41e7995c83543b 100644
|
||||
--- a/content/browser/download/save_file_manager.cc
|
||||
+++ b/content/browser/download/save_file_manager.cc
|
||||
@@ -51,6 +51,7 @@ static SaveFileManager* g_save_file_manager = nullptr;
|
||||
class SaveFileManager::SimpleURLLoaderHelper
|
||||
: public network::SimpleURLLoaderStreamConsumer {
|
||||
public:
|
||||
+ using URLLoaderCompleteCallback = base::OnceCallback<void(bool success)>;
|
||||
static std::unique_ptr<SimpleURLLoaderHelper> CreateAndStartDownload(
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
SaveItemId save_item_id,
|
||||
@@ -59,11 +60,12 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
int render_frame_routing_id,
|
||||
const net::NetworkTrafficAnnotationTag& annotation_tag,
|
||||
network::mojom::URLLoaderFactory* url_loader_factory,
|
||||
- SaveFileManager* save_file_manager) {
|
||||
+ SaveFileManager* save_file_manager,
|
||||
+ URLLoaderCompleteCallback on_complete_cb) {
|
||||
return std::unique_ptr<SimpleURLLoaderHelper>(new SimpleURLLoaderHelper(
|
||||
std::move(resource_request), save_item_id, save_package_id,
|
||||
render_process_id, render_frame_routing_id, annotation_tag,
|
||||
- url_loader_factory, save_file_manager));
|
||||
+ url_loader_factory, save_file_manager, std::move(on_complete_cb)));
|
||||
}
|
||||
|
||||
~SimpleURLLoaderHelper() override = default;
|
||||
@@ -77,10 +79,12 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
int render_frame_routing_id,
|
||||
const net::NetworkTrafficAnnotationTag& annotation_tag,
|
||||
network::mojom::URLLoaderFactory* url_loader_factory,
|
||||
- SaveFileManager* save_file_manager)
|
||||
+ SaveFileManager* save_file_manager,
|
||||
+ URLLoaderCompleteCallback on_complete_cb)
|
||||
: save_file_manager_(save_file_manager),
|
||||
save_item_id_(save_item_id),
|
||||
- save_package_id_(save_package_id) {
|
||||
+ save_package_id_(save_package_id),
|
||||
+ on_complete_cb_(std::move(on_complete_cb)) {
|
||||
GURL url = resource_request->url;
|
||||
url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
|
||||
annotation_tag);
|
||||
@@ -125,9 +129,7 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
|
||||
void OnComplete(bool success) override {
|
||||
download::GetDownloadTaskRunner()->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&SaveFileManager::SaveFinished, save_file_manager_,
|
||||
- save_item_id_, save_package_id_, success));
|
||||
+ FROM_HERE, base::BindOnce(std::move(on_complete_cb_), success));
|
||||
}
|
||||
|
||||
void OnRetry(base::OnceClosure start_retry) override {
|
||||
@@ -139,6 +141,7 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
SaveItemId save_item_id_;
|
||||
SavePackageId save_package_id_;
|
||||
std::unique_ptr<network::SimpleURLLoader> url_loader_;
|
||||
+ URLLoaderCompleteCallback on_complete_cb_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SimpleURLLoaderHelper);
|
||||
};
|
||||
@@ -189,17 +192,20 @@ SavePackage* SaveFileManager::LookupPackage(SaveItemId save_item_id) {
|
||||
}
|
||||
|
||||
// Call from SavePackage for starting a saving job
|
||||
-void SaveFileManager::SaveURL(SaveItemId save_item_id,
|
||||
- const GURL& url,
|
||||
- const Referrer& referrer,
|
||||
- int render_process_host_id,
|
||||
- int render_view_routing_id,
|
||||
- int render_frame_routing_id,
|
||||
- SaveFileCreateInfo::SaveFileSource save_source,
|
||||
- const base::FilePath& file_full_path,
|
||||
- BrowserContext* context,
|
||||
- StoragePartition* storage_partition,
|
||||
- SavePackage* save_package) {
|
||||
+void SaveFileManager::SaveURL(
|
||||
+ SaveItemId save_item_id,
|
||||
+ const GURL& url,
|
||||
+ const Referrer& referrer,
|
||||
+ int render_process_host_id,
|
||||
+ int render_view_routing_id,
|
||||
+ int render_frame_routing_id,
|
||||
+ SaveFileCreateInfo::SaveFileSource save_source,
|
||||
+ const base::FilePath& file_full_path,
|
||||
+ BrowserContext* context,
|
||||
+ StoragePartition* storage_partition,
|
||||
+ SavePackage* save_package,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
// Insert started saving job to tracking list.
|
||||
@@ -285,11 +291,18 @@ void SaveFileManager::SaveURL(SaveItemId save_item_id,
|
||||
factory = storage_partition->GetURLLoaderFactoryForBrowserProcess().get();
|
||||
}
|
||||
|
||||
+ base::OnceCallback<void(bool /*success*/)> save_finished_cb =
|
||||
+ base::BindOnce(&SaveFileManager::OnURLLoaderComplete, this,
|
||||
+ save_item_id, save_package->id(),
|
||||
+ context->IsOffTheRecord() ? GURL() : url,
|
||||
+ context->IsOffTheRecord() ? GURL() : referrer.url,
|
||||
+ client_guid, std::move(remote_quarantine));
|
||||
+
|
||||
url_loader_helpers_[save_item_id] =
|
||||
SimpleURLLoaderHelper::CreateAndStartDownload(
|
||||
std::move(request), save_item_id, save_package->id(),
|
||||
render_process_host_id, render_frame_routing_id, traffic_annotation,
|
||||
- factory, this);
|
||||
+ factory, this, std::move(save_finished_cb));
|
||||
} else {
|
||||
// We manually start the save job.
|
||||
auto info = std::make_unique<SaveFileCreateInfo>(
|
||||
@@ -344,6 +357,36 @@ void SaveFileManager::SendCancelRequest(SaveItemId save_item_id) {
|
||||
base::BindOnce(&SaveFileManager::CancelSave, this, save_item_id));
|
||||
}
|
||||
|
||||
+void SaveFileManager::OnURLLoaderComplete(
|
||||
+ SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ const GURL& url,
|
||||
+ const GURL& referrer_url,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ bool is_success) {
|
||||
+ DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
|
||||
+ SaveFile* save_file = LookupSaveFile(save_item_id);
|
||||
+ if (!is_success || !save_file) {
|
||||
+ SaveFinished(save_item_id, save_package_id, is_success);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ save_file->AnnotateWithSourceInformation(
|
||||
+ client_guid, url, referrer_url, std::move(remote_quarantine),
|
||||
+ base::BindOnce(&SaveFileManager::OnQuarantineComplete, this, save_item_id,
|
||||
+ save_package_id));
|
||||
+}
|
||||
+
|
||||
+void SaveFileManager::OnQuarantineComplete(
|
||||
+ SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ download::DownloadInterruptReason result) {
|
||||
+ DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
|
||||
+ SaveFinished(save_item_id, save_package_id,
|
||||
+ result == download::DOWNLOAD_INTERRUPT_REASON_NONE);
|
||||
+}
|
||||
+
|
||||
// Notifications sent from the IO thread and run on the file thread:
|
||||
|
||||
// The IO thread created |info|, but the file thread (this method) uses it
|
||||
diff --git a/content/browser/download/save_file_manager.h b/content/browser/download/save_file_manager.h
|
||||
index 51eb63a9b189be388e4dff48e04644956e968345..0d4290b273ba4f150bc9a49418e54b709a601581 100644
|
||||
--- a/content/browser/download/save_file_manager.h
|
||||
+++ b/content/browser/download/save_file_manager.h
|
||||
@@ -61,6 +61,8 @@
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
+#include "components/download/public/common/download_interrupt_reasons.h"
|
||||
+#include "components/services/quarantine/quarantine.h"
|
||||
#include "content/browser/download/save_types.h"
|
||||
#include "content/common/content_export.h"
|
||||
|
||||
@@ -90,17 +92,20 @@ class CONTENT_EXPORT SaveFileManager
|
||||
|
||||
// Saves the specified URL |url|. |save_package| must not be deleted before
|
||||
// the call to RemoveSaveFile. Should be called on the UI thread,
|
||||
- void SaveURL(SaveItemId save_item_id,
|
||||
- const GURL& url,
|
||||
- const Referrer& referrer,
|
||||
- int render_process_host_id,
|
||||
- int render_view_routing_id,
|
||||
- int render_frame_routing_id,
|
||||
- SaveFileCreateInfo::SaveFileSource save_source,
|
||||
- const base::FilePath& file_full_path,
|
||||
- BrowserContext* context,
|
||||
- StoragePartition* storage_partition,
|
||||
- SavePackage* save_package);
|
||||
+ void SaveURL(
|
||||
+ SaveItemId save_item_id,
|
||||
+ const GURL& url,
|
||||
+ const Referrer& referrer,
|
||||
+ int render_process_host_id,
|
||||
+ int render_view_routing_id,
|
||||
+ int render_frame_routing_id,
|
||||
+ SaveFileCreateInfo::SaveFileSource save_source,
|
||||
+ const base::FilePath& file_full_path,
|
||||
+ BrowserContext* context,
|
||||
+ StoragePartition* storage_partition,
|
||||
+ SavePackage* save_package,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine);
|
||||
|
||||
// Notifications sent from the IO thread and run on the file thread:
|
||||
void StartSave(std::unique_ptr<SaveFileCreateInfo> info);
|
||||
@@ -159,6 +164,21 @@ class CONTENT_EXPORT SaveFileManager
|
||||
// Help function for sending notification of canceling specific request.
|
||||
void SendCancelRequest(SaveItemId save_item_id);
|
||||
|
||||
+ // Called on the file thread when the URLLoader completes saving a SaveItem.
|
||||
+ void OnURLLoaderComplete(
|
||||
+ SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ const GURL& url,
|
||||
+ const GURL& referrer_url,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ bool is_success);
|
||||
+
|
||||
+ // Called on the file thread when file quarantine finishes on a SaveItem.
|
||||
+ void OnQuarantineComplete(SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ download::DownloadInterruptReason result);
|
||||
+
|
||||
// Notifications sent from the file thread and run on the UI thread.
|
||||
|
||||
// Lookup the SaveManager for this WebContents' saving browser context and
|
||||
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
|
||||
index 7a5b64845a0e733467e3607cfa7feb75d1f3cb4c..0193ec702ffe5ba0fd3e87cbb65aa3b0e0bf3add 100644
|
||||
--- a/content/browser/download/save_package.cc
|
||||
+++ b/content/browser/download/save_package.cc
|
||||
@@ -859,6 +859,12 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
|
||||
RenderFrameHostImpl* requester_frame =
|
||||
requester_frame_tree_node->current_frame_host();
|
||||
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> quarantine;
|
||||
+ auto quarantine_callback =
|
||||
+ download_manager_->GetQuarantineConnectionCallback();
|
||||
+ if (quarantine_callback)
|
||||
+ quarantine_callback.Run(quarantine.InitWithNewPipeAndPassReceiver());
|
||||
+
|
||||
file_manager_->SaveURL(
|
||||
save_item_ptr->id(), save_item_ptr->url(), save_item_ptr->referrer(),
|
||||
requester_frame->GetProcess()->GetID(),
|
||||
@@ -870,8 +876,8 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
|
||||
.GetRenderViewHost()
|
||||
->GetProcess()
|
||||
->GetStoragePartition(),
|
||||
- this);
|
||||
-
|
||||
+ this, download_manager_->GetApplicationClientIdForFileScanning(),
|
||||
+ std::move(quarantine));
|
||||
} while (process_all_remaining_items && !waiting_item_queue_.empty());
|
||||
}
|
||||
|
||||
106
patches/chromium/cherry-pick-096afc1c5428.patch
Normal file
106
patches/chromium/cherry-pick-096afc1c5428.patch
Normal file
@@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rayan Kanso <rayankans@google.com>
|
||||
Date: Tue, 7 Sep 2021 20:14:30 +0000
|
||||
Subject: Use less-specific error codes for CORS-failing fetches
|
||||
|
||||
(cherry picked from commit 26be5702dab1d98e4d4b076a73d4688d20c043be)
|
||||
|
||||
Bug: 1245053
|
||||
Change-Id: If0343157a3ba41a6c946b5f7401a9d114f834779
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3135676
|
||||
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
|
||||
Reviewed-by: Richard Knoll <knollr@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#918109}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3143786
|
||||
Commit-Queue: Richard Knoll <knollr@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#833}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc
|
||||
index 221e3731ef4de60279cb74fb112d3724e97d4670..4cd4ca92b401d19a8113d72bc51c2b9f170226f3 100644
|
||||
--- a/content/browser/background_fetch/background_fetch_job_controller.cc
|
||||
+++ b/content/browser/background_fetch/background_fetch_job_controller.cc
|
||||
@@ -178,6 +178,8 @@ void BackgroundFetchJobController::DidStartRequest(
|
||||
BackgroundFetchCrossOriginFilter filter(
|
||||
registration_id_.storage_key().origin(), *request);
|
||||
request->set_can_populate_body(filter.CanPopulateBody());
|
||||
+ if (!request->can_populate_body())
|
||||
+ has_failed_cors_request_ = true;
|
||||
}
|
||||
|
||||
void BackgroundFetchJobController::DidUpdateRequest(const std::string& guid,
|
||||
@@ -258,7 +260,14 @@ uint64_t BackgroundFetchJobController::GetInProgressUploadedBytes() {
|
||||
|
||||
void BackgroundFetchJobController::AbortFromDelegate(
|
||||
BackgroundFetchFailureReason failure_reason) {
|
||||
- failure_reason_ = failure_reason;
|
||||
+ if (failure_reason == BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED &&
|
||||
+ has_failed_cors_request_) {
|
||||
+ // Don't expose that the download total has been exceeded. Use a less
|
||||
+ // specific error.
|
||||
+ failure_reason_ = BackgroundFetchFailureReason::FETCH_ERROR;
|
||||
+ } else {
|
||||
+ failure_reason_ = failure_reason;
|
||||
+ }
|
||||
|
||||
Finish(failure_reason_, base::DoNothing());
|
||||
}
|
||||
diff --git a/content/browser/background_fetch/background_fetch_job_controller.h b/content/browser/background_fetch/background_fetch_job_controller.h
|
||||
index 0d041d21e9caf5b7f94e2366c85dc27f52bc5787..28863399f9fbad451e60d5f55bc6dc9888092e4a 100644
|
||||
--- a/content/browser/background_fetch/background_fetch_job_controller.h
|
||||
+++ b/content/browser/background_fetch/background_fetch_job_controller.h
|
||||
@@ -210,6 +210,10 @@ class CONTENT_EXPORT BackgroundFetchJobController
|
||||
blink::mojom::BackgroundFetchFailureReason failure_reason_ =
|
||||
blink::mojom::BackgroundFetchFailureReason::NONE;
|
||||
|
||||
+ // Whether one of the requests handled by the controller failed
|
||||
+ // the CORS checks and should not have its response exposed.
|
||||
+ bool has_failed_cors_request_ = false;
|
||||
+
|
||||
// Custom callback that runs after the controller is finished.
|
||||
FinishedCallback finished_callback_;
|
||||
|
||||
diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
|
||||
index f42b363139d33e50e57433982df6b2cf4b08e811..1dc386051f030ee033fd06616fef9f54ce46172a 100644
|
||||
--- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
|
||||
+++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
|
||||
@@ -430,6 +430,39 @@ TEST_F(BackgroundFetchJobControllerTest, Abort) {
|
||||
GetCompletionStatus(registration_id));
|
||||
}
|
||||
|
||||
+TEST_F(BackgroundFetchJobControllerTest, AbortDownloadExceededCrossOrigin) {
|
||||
+ BackgroundFetchRegistrationId registration_id;
|
||||
+
|
||||
+ auto requests = CreateRegistrationForRequests(
|
||||
+ ®istration_id, {{GURL("https://example2.com/funny_cat.png"), "GET"}},
|
||||
+ /* auto_complete_requests= */ true);
|
||||
+
|
||||
+ EXPECT_EQ(JobCompletionStatus::kRunning,
|
||||
+ GetCompletionStatus(registration_id));
|
||||
+
|
||||
+ std::unique_ptr<BackgroundFetchJobController> controller =
|
||||
+ CreateJobController(registration_id, requests.size());
|
||||
+
|
||||
+ controller->StartRequest(requests[0], base::DoNothing());
|
||||
+
|
||||
+ controller->DidStartRequest(
|
||||
+ requests[0]->download_guid(),
|
||||
+ std::make_unique<BackgroundFetchResponse>(
|
||||
+ std::vector<GURL>{GURL("https://example2.com/funny_cat.png")},
|
||||
+ nullptr));
|
||||
+ EXPECT_FALSE(requests[0]->can_populate_body());
|
||||
+
|
||||
+ controller->AbortFromDelegate(
|
||||
+ blink::mojom::BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED);
|
||||
+
|
||||
+ base::RunLoop().RunUntilIdle();
|
||||
+
|
||||
+ EXPECT_EQ(JobCompletionStatus::kAborted,
|
||||
+ GetCompletionStatus(registration_id));
|
||||
+ EXPECT_EQ(finished_requests_[registration_id],
|
||||
+ blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR);
|
||||
+}
|
||||
+
|
||||
TEST_F(BackgroundFetchJobControllerTest, Progress) {
|
||||
BackgroundFetchRegistrationId registration_id;
|
||||
|
||||
176
patches/chromium/cherry-pick-1277917.patch
Normal file
176
patches/chromium/cherry-pick-1277917.patch
Normal file
@@ -0,0 +1,176 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Pelchat <spelchat@chromium.org>
|
||||
Date: Fri, 7 Jan 2022 20:00:37 +0000
|
||||
Subject: Avoid UAF on StreamingSearchPrefetchURLLoader.
|
||||
|
||||
StreamingSearchPrefetchURLLoader::OnDataAvailable used to "delete this",
|
||||
which results in deleting the DataPipeDrainer, which will then be used
|
||||
once OnDataAvailable returns. Instead, we post a task to delete the
|
||||
URL loader later on.
|
||||
|
||||
Bug: 1277917
|
||||
Change-Id: I8d78c73a01fff0315b96ccb0e7fe605884b99823
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3365387
|
||||
Reviewed-by: Max Curran <curranmax@chromium.org>
|
||||
Reviewed-by: Robert Ogden <robertogden@chromium.org>
|
||||
Commit-Queue: Simon Pelchat <spelchat@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956628}
|
||||
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
index 1d3d1ea93c026d371a6ad5678e8ff37dc58f8423..e3eaad96fbada18211f295988c07d218ab67921f 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h"
|
||||
|
||||
#include "chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h"
|
||||
+#include "streaming_search_prefetch_request.h"
|
||||
|
||||
StreamingSearchPrefetchRequest::StreamingSearchPrefetchRequest(
|
||||
const GURL& prefetch_url,
|
||||
@@ -19,7 +20,9 @@ void StreamingSearchPrefetchRequest::StartPrefetchRequestInternal(
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
const net::NetworkTrafficAnnotationTag& network_traffic_annotation) {
|
||||
streaming_url_loader_ = std::make_unique<StreamingSearchPrefetchURLLoader>(
|
||||
- this, profile, std::move(resource_request), network_traffic_annotation);
|
||||
+ this, profile, std::move(resource_request), network_traffic_annotation,
|
||||
+ base::BindOnce(&StreamingSearchPrefetchRequest::StopPrefetch,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
std::unique_ptr<SearchPrefetchURLLoader>
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
index ff051c61e9cbed67d5cffbcac007d6c12a26cc76..ad75d404abe9e743d079725ffd8b01d3a49ae017 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
@@ -47,6 +47,8 @@ class StreamingSearchPrefetchRequest : public BaseSearchPrefetchRequest {
|
||||
private:
|
||||
// The ongoing prefetch request. Null before and after the fetch.
|
||||
std::unique_ptr<StreamingSearchPrefetchURLLoader> streaming_url_loader_;
|
||||
+
|
||||
+ base::WeakPtrFactory<StreamingSearchPrefetchRequest> weak_factory_{this};
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_STREAMING_SEARCH_PREFETCH_REQUEST_H_
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
index 09a8f5c444c5346dd6d2544c403a4b844e0ba781..2134bdbd2514d86b912b83480ca90242d7f7455e 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
@@ -26,15 +26,18 @@
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
#include "services/network/public/mojom/early_hints.mojom.h"
|
||||
#include "services/network/public/mojom/url_response_head.mojom.h"
|
||||
+#include "streaming_search_prefetch_url_loader.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
StreamingSearchPrefetchURLLoader::StreamingSearchPrefetchURLLoader(
|
||||
StreamingSearchPrefetchRequest* streaming_prefetch_request,
|
||||
Profile* profile,
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
- const net::NetworkTrafficAnnotationTag& network_traffic_annotation)
|
||||
+ const net::NetworkTrafficAnnotationTag& network_traffic_annotation,
|
||||
+ base::OnceClosure stop_prefetch_closure)
|
||||
: resource_request_(std::move(resource_request)),
|
||||
- streaming_prefetch_request_(streaming_prefetch_request) {
|
||||
+ streaming_prefetch_request_(streaming_prefetch_request),
|
||||
+ stop_prefetch_closure_(std::move(stop_prefetch_closure)) {
|
||||
DCHECK(streaming_prefetch_request_);
|
||||
auto url_loader_factory = profile->GetDefaultStoragePartition()
|
||||
->GetURLLoaderFactoryForBrowserProcess();
|
||||
@@ -130,7 +133,7 @@ void StreamingSearchPrefetchURLLoader::OnReceiveRedirect(
|
||||
if (streaming_prefetch_request_) {
|
||||
streaming_prefetch_request_->ErrorEncountered();
|
||||
} else {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +216,7 @@ void StreamingSearchPrefetchURLLoader::OnStartLoadingResponseBodyFromData() {
|
||||
mojo::CreateDataPipe(&options, producer_handle_, consumer_handle);
|
||||
|
||||
if (rv != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -235,7 +238,7 @@ void StreamingSearchPrefetchURLLoader::OnHandleReady(
|
||||
MojoResult result,
|
||||
const mojo::HandleSignalsState& state) {
|
||||
if (result != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
PushData();
|
||||
@@ -261,7 +264,7 @@ void StreamingSearchPrefetchURLLoader::PushData() {
|
||||
}
|
||||
|
||||
if (result != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,16 +351,24 @@ void StreamingSearchPrefetchURLLoader::OnURLLoaderMojoDisconnect() {
|
||||
DCHECK(streaming_prefetch_request_);
|
||||
streaming_prefetch_request_->ErrorEncountered();
|
||||
} else {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
void StreamingSearchPrefetchURLLoader::OnURLLoaderClientMojoDisconnect() {
|
||||
DCHECK(forwarding_client_);
|
||||
DCHECK(!streaming_prefetch_request_);
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
|
||||
void StreamingSearchPrefetchURLLoader::ClearOwnerPointer() {
|
||||
streaming_prefetch_request_ = nullptr;
|
||||
}
|
||||
+
|
||||
+void StreamingSearchPrefetchURLLoader::PostTaskToStopPrefetchAndDeleteSelf() {
|
||||
+ // To avoid UAF bugs, post a separate task to delete this object.
|
||||
+ if (stop_prefetch_closure_) {
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE, std::move(stop_prefetch_closure_));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
index 2213fb079e3f29566d67030dd2fa399ce11024e2..ed225db0b4d2b0d24aae967f320a7010c1a45044 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
@@ -39,7 +39,8 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
StreamingSearchPrefetchRequest* streaming_prefetch_request,
|
||||
Profile* profile,
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
- const net::NetworkTrafficAnnotationTag& network_traffic_annotation);
|
||||
+ const net::NetworkTrafficAnnotationTag& network_traffic_annotation,
|
||||
+ base::OnceClosure stop_prefetch_closure);
|
||||
|
||||
~StreamingSearchPrefetchURLLoader() override;
|
||||
|
||||
@@ -105,6 +106,9 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
// Clears |producer_handle_| and |handle_watcher_|.
|
||||
void Finish();
|
||||
|
||||
+ // Post a task to delete this object by running stop_prefetch_closure_.
|
||||
+ void PostTaskToStopPrefetchAndDeleteSelf();
|
||||
+
|
||||
// Sets up mojo forwarding to the navigation path. Resumes
|
||||
// |network_url_loader_| calls. Serves the start of the response to the
|
||||
// navigation path. After this method is called, |this| manages its own
|
||||
@@ -164,6 +168,9 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
mojo::ScopedDataPipeProducerHandle producer_handle_;
|
||||
std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
|
||||
|
||||
+ // Closure to cancel this prefetch. Running this callback will destroy |this|.
|
||||
+ base::OnceClosure stop_prefetch_closure_;
|
||||
+
|
||||
base::WeakPtrFactory<StreamingSearchPrefetchURLLoader> weak_factory_{this};
|
||||
};
|
||||
|
||||
31
patches/chromium/cherry-pick-1282354.patch
Normal file
31
patches/chromium/cherry-pick-1282354.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Bookholt <bookholt@chromium.org>
|
||||
Date: Tue, 11 Jan 2022 00:33:53 +0000
|
||||
Subject: ServiceWorkerContainerHost::EnsureFileAccess: abort request
|
||||
processing if the requesting process lacks file access
|
||||
|
||||
Bug: 1282354
|
||||
Change-Id: Ia37ef5b97eedb0d2ad25ffe2869844a40e5be862
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3379268
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Chris Bookholt <bookholt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#957344}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc
|
||||
index 5aca9f432a9efdb9739363e80b52233339529a1c..8b15f204e457904423da33b01bead1b03b59597a 100644
|
||||
--- a/content/browser/service_worker/service_worker_container_host.cc
|
||||
+++ b/content/browser/service_worker/service_worker_container_host.cc
|
||||
@@ -375,10 +375,12 @@ void ServiceWorkerContainerHost::EnsureFileAccess(
|
||||
ChildProcessSecurityPolicyImpl* policy =
|
||||
ChildProcessSecurityPolicyImpl::GetInstance();
|
||||
for (const auto& file : file_paths) {
|
||||
- if (!policy->CanReadFile(process_id_, file))
|
||||
+ if (!policy->CanReadFile(process_id_, file)) {
|
||||
mojo::ReportBadMessage(
|
||||
"The renderer doesn't have access to the file "
|
||||
"but it tried to grant access to the controller.");
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (!policy->CanReadFile(controller_process_id, file))
|
||||
policy->GrantReadFile(controller_process_id, file);
|
||||
28
patches/chromium/cherry-pick-1283198.patch
Normal file
28
patches/chromium/cherry-pick-1283198.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Hosseinian <dhoss@chromium.org>
|
||||
Date: Thu, 30 Dec 2021 05:08:29 +0000
|
||||
Subject: CHECK page on thumbnail requests
|
||||
|
||||
Elevate DCHECK to CHECK.
|
||||
|
||||
Fixed: 1283198
|
||||
Change-Id: Iacb3da961cfb44f94f7a377e225270a57809ef9c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3361538
|
||||
Auto-Submit: Daniel Hosseinian <dhoss@chromium.org>
|
||||
Reviewed-by: K. Moon <kmoon@chromium.org>
|
||||
Commit-Queue: K. Moon <kmoon@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#954552}
|
||||
|
||||
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
|
||||
index 7f70791ceddf298d2c95ca3569799a0f4d3746a3..c7ae1b65d416024a7d90e377a57b5ae1ea3e0c07 100644
|
||||
--- a/pdf/pdfium/pdfium_engine.cc
|
||||
+++ b/pdf/pdfium/pdfium_engine.cc
|
||||
@@ -4224,7 +4224,7 @@ void PDFiumEngine::SetLinkUnderCursorForAnnotation(FPDF_ANNOTATION annot,
|
||||
void PDFiumEngine::RequestThumbnail(int page_index,
|
||||
float device_pixel_ratio,
|
||||
SendThumbnailCallback send_callback) {
|
||||
- DCHECK(PageIndexInBounds(page_index));
|
||||
+ CHECK(PageIndexInBounds(page_index));
|
||||
pages_[page_index]->RequestThumbnail(device_pixel_ratio,
|
||||
std::move(send_callback));
|
||||
}
|
||||
138
patches/chromium/cherry-pick-1283371.patch
Normal file
138
patches/chromium/cherry-pick-1283371.patch
Normal file
@@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Clark DuVall <cduvall@chromium.org>
|
||||
Date: Thu, 6 Jan 2022 01:21:21 +0000
|
||||
Subject: Fix lifetime bug in PrefetchURLLoader
|
||||
|
||||
PrefetchURLLoader is now owned by PrefetchURLLoaderService, which is no
|
||||
longer refcounted. This makes the lifetime much easier to reason about.
|
||||
|
||||
Bug: 1283371
|
||||
Change-Id: Iaa58c1f44cc9f066459ce344012f57faca533197
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3361198
|
||||
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
|
||||
Reviewed-by: Kunihiko Sakamoto <ksakamoto@chromium.org>
|
||||
Commit-Queue: Clark DuVall <cduvall@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#955986}
|
||||
|
||||
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc
|
||||
index 5211d5552d6b2e1c1967d7dd6c6079001fef6895..345bf021541a121ea183ba16fa7ed76373f0dfd1 100644
|
||||
--- a/content/browser/loader/prefetch_url_loader_service.cc
|
||||
+++ b/content/browser/loader/prefetch_url_loader_service.cc
|
||||
@@ -202,29 +202,25 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
|
||||
->prefetched_signed_exchange_cache;
|
||||
}
|
||||
|
||||
- // For now we make self owned receiver for the loader to the request, while we
|
||||
- // can also possibly make the new loader owned by the factory so that they can
|
||||
- // live longer than the client (i.e. run in detached mode).
|
||||
- // TODO(kinuko): Revisit this.
|
||||
- mojo::MakeSelfOwnedReceiver(
|
||||
- std::make_unique<PrefetchURLLoader>(
|
||||
- request_id, options, current_context.frame_tree_node_id,
|
||||
- resource_request,
|
||||
- resource_request.trusted_params
|
||||
- ? resource_request.trusted_params->isolation_info
|
||||
- .network_isolation_key()
|
||||
- : current_context.render_frame_host->GetNetworkIsolationKey(),
|
||||
- std::move(client), traffic_annotation,
|
||||
- std::move(network_loader_factory_to_use),
|
||||
- base::BindRepeating(
|
||||
- &PrefetchURLLoaderService::CreateURLLoaderThrottles, this,
|
||||
- resource_request, current_context.frame_tree_node_id),
|
||||
- browser_context_, signed_exchange_prefetch_metric_recorder_,
|
||||
- std::move(prefetched_signed_exchange_cache), accept_langs_,
|
||||
- base::BindOnce(
|
||||
- &PrefetchURLLoaderService::GenerateRecursivePrefetchToken, this,
|
||||
- current_context.weak_ptr_factory.GetWeakPtr())),
|
||||
- std::move(receiver));
|
||||
+ // base::Unretained is safe here since |this| owns the loader.
|
||||
+ auto loader = std::make_unique<PrefetchURLLoader>(
|
||||
+ request_id, options, current_context.frame_tree_node_id, resource_request,
|
||||
+ resource_request.trusted_params
|
||||
+ ? resource_request.trusted_params->isolation_info
|
||||
+ .network_isolation_key()
|
||||
+ : current_context.render_frame_host->GetNetworkIsolationKey(),
|
||||
+ std::move(client), traffic_annotation,
|
||||
+ std::move(network_loader_factory_to_use),
|
||||
+ base::BindRepeating(&PrefetchURLLoaderService::CreateURLLoaderThrottles,
|
||||
+ base::Unretained(this), resource_request,
|
||||
+ current_context.frame_tree_node_id),
|
||||
+ browser_context_, signed_exchange_prefetch_metric_recorder_,
|
||||
+ std::move(prefetched_signed_exchange_cache), accept_langs_,
|
||||
+ base::BindOnce(&PrefetchURLLoaderService::GenerateRecursivePrefetchToken,
|
||||
+ base::Unretained(this),
|
||||
+ current_context.weak_ptr_factory.GetWeakPtr()));
|
||||
+ auto* raw_loader = loader.get();
|
||||
+ prefetch_receivers_.Add(raw_loader, std::move(receiver), std::move(loader));
|
||||
}
|
||||
|
||||
PrefetchURLLoaderService::~PrefetchURLLoaderService() = default;
|
||||
diff --git a/content/browser/loader/prefetch_url_loader_service.h b/content/browser/loader/prefetch_url_loader_service.h
|
||||
index 210794966c8d25947f3e6b490538c1f851d80d52..c5fff844f73deaf2912716de9cf97547c498e4e5 100644
|
||||
--- a/content/browser/loader/prefetch_url_loader_service.h
|
||||
+++ b/content/browser/loader/prefetch_url_loader_service.h
|
||||
@@ -35,13 +35,11 @@ class URLLoaderFactoryGetter;
|
||||
// prefetches. The renderer uses it for prefetch requests including <link
|
||||
// rel="prefetch">.
|
||||
class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
- : public base::RefCountedThreadSafe<
|
||||
- PrefetchURLLoaderService,
|
||||
- content::BrowserThread::DeleteOnUIThread>,
|
||||
- public blink::mojom::RendererPreferenceWatcher,
|
||||
+ : public blink::mojom::RendererPreferenceWatcher,
|
||||
public network::mojom::URLLoaderFactory {
|
||||
public:
|
||||
explicit PrefetchURLLoaderService(BrowserContext* browser_context);
|
||||
+ ~PrefetchURLLoaderService() override;
|
||||
|
||||
void GetFactory(
|
||||
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
|
||||
@@ -67,12 +65,8 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
}
|
||||
|
||||
private:
|
||||
- friend class base::DeleteHelper<content::PrefetchURLLoaderService>;
|
||||
- friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
|
||||
struct BindContext;
|
||||
|
||||
- ~PrefetchURLLoaderService() override;
|
||||
-
|
||||
// network::mojom::URLLoaderFactory:
|
||||
void CreateLoaderAndStart(
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
|
||||
@@ -114,6 +108,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
mojo::ReceiverSet<network::mojom::URLLoaderFactory,
|
||||
std::unique_ptr<BindContext>>
|
||||
loader_factory_receivers_;
|
||||
+ mojo::ReceiverSet<network::mojom::URLLoader,
|
||||
+ std::unique_ptr<network::mojom::URLLoader>>
|
||||
+ prefetch_receivers_;
|
||||
// Used in the IO thread.
|
||||
mojo::Receiver<blink::mojom::RendererPreferenceWatcher>
|
||||
preference_watcher_receiver_{this};
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index 263fe6195ac6d48cd7a985ca844d1a6e421a9b1d..ac0bba6a7b41e497eb28c820476f36de5c63bc34 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1285,7 +1285,7 @@ void StoragePartitionImpl::Initialize(
|
||||
blob_context, filesystem_context_, fallback_blob_registry);
|
||||
|
||||
prefetch_url_loader_service_ =
|
||||
- base::MakeRefCounted<PrefetchURLLoaderService>(browser_context_);
|
||||
+ std::make_unique<PrefetchURLLoaderService>(browser_context_);
|
||||
|
||||
cookie_store_context_ = base::MakeRefCounted<CookieStoreContext>();
|
||||
// Unit tests use the Initialize() callback to crash early if restoring the
|
||||
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
|
||||
index 6d1c4031c340e0a16943b1f0c0efdf9f5dc5f99b..ba0ae57aae69a5edf4ce23c202a93c8cdb003051 100644
|
||||
--- a/content/browser/storage_partition_impl.h
|
||||
+++ b/content/browser/storage_partition_impl.h
|
||||
@@ -561,7 +561,7 @@ class CONTENT_EXPORT StoragePartitionImpl
|
||||
std::unique_ptr<BroadcastChannelProvider> broadcast_channel_provider_;
|
||||
std::unique_ptr<BluetoothAllowedDevicesMap> bluetooth_allowed_devices_map_;
|
||||
scoped_refptr<BlobRegistryWrapper> blob_registry_;
|
||||
- scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
|
||||
+ std::unique_ptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
|
||||
scoped_refptr<CookieStoreContext> cookie_store_context_;
|
||||
scoped_refptr<BucketContext> bucket_context_;
|
||||
scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
|
||||
74
patches/chromium/cherry-pick-1283375.patch
Normal file
74
patches/chromium/cherry-pick-1283375.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alan Screen <awscreen@chromium.org>
|
||||
Date: Fri, 7 Jan 2022 09:38:01 +0000
|
||||
Subject: Ensure valid print render host before proceeding to print.
|
||||
|
||||
Bug: 1283375
|
||||
Change-Id: I5691fc2a9d09040e777aafd0061b957025643b8a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3369086
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Alan Screen <awscreen@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956443}
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
|
||||
index bfed66e625f1d6e53b31750cd7d5fa7748cae75c..6c5ec9086264972ff67beab712ae2695ffa93395 100644
|
||||
--- a/chrome/browser/printing/print_view_manager.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager.cc
|
||||
@@ -91,6 +91,11 @@ bool PrintViewManager::PrintForSystemDialogNow(
|
||||
on_print_dialog_shown_callback_ = std::move(dialog_shown_callback);
|
||||
is_switching_to_system_dialog_ = true;
|
||||
|
||||
+ // Remember the ID for `print_preview_rfh_`, to enable checking that the
|
||||
+ // `RenderFrameHost` is still valid after a possible inner message loop runs
|
||||
+ // in `DisconnectFromCurrentPrintJob()`.
|
||||
+ content::GlobalRenderFrameHostId rfh_id = print_preview_rfh_->GetGlobalId();
|
||||
+
|
||||
auto weak_this = weak_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
if (!weak_this)
|
||||
@@ -100,6 +105,10 @@ bool PrintViewManager::PrintForSystemDialogNow(
|
||||
if (IsCrashed())
|
||||
return false;
|
||||
|
||||
+ // Don't print if `print_preview_rfh_` is no longer live.
|
||||
+ if (!content::RenderFrameHost::FromID(rfh_id))
|
||||
+ return false;
|
||||
+
|
||||
// TODO(crbug.com/809738) Register with `PrintBackendServiceManager` when
|
||||
// system print is enabled out-of-process.
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
||||
index 562800bf194e1f07f58b912b54a740b7c7dcabb6..c34f3ba9bb4adbfa8f190d5ef75cfa72937f0b1d 100644
|
||||
--- a/chrome/browser/printing/print_view_manager_base.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "components/services/print_compositor/public/cpp/print_service_mojo_types.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
+#include "content/public/browser/global_routing_id.h"
|
||||
#include "content/public/browser/notification_details.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_source.h"
|
||||
@@ -364,6 +365,11 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
|
||||
bool silent,
|
||||
base::Value settings,
|
||||
CompletionCallback callback) {
|
||||
+ // Remember the ID for `rfh`, to enable checking that the `RenderFrameHost`
|
||||
+ // is still valid after a possible inner message loop runs in
|
||||
+ // `DisconnectFromCurrentPrintJob()`.
|
||||
+ content::GlobalRenderFrameHostId rfh_id = rfh->GetGlobalId();
|
||||
+
|
||||
auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
if (!weak_this)
|
||||
@@ -373,6 +379,10 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
|
||||
if (IsCrashed())
|
||||
return false;
|
||||
|
||||
+ // Don't print if `rfh` is no longer live.
|
||||
+ if (!content::RenderFrameHost::FromID(rfh_id))
|
||||
+ return false;
|
||||
+
|
||||
// TODO(crbug.com/809738) Register with `PrintBackendServiceManager` when
|
||||
// system print is enabled out-of-process. A corresponding unregister should
|
||||
// go in `ReleasePrintJob()`.
|
||||
188
patches/chromium/cherry-pick-1284367.patch
Normal file
188
patches/chromium/cherry-pick-1284367.patch
Normal file
@@ -0,0 +1,188 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xinghui Lu <xinghuilu@chromium.org>
|
||||
Date: Thu, 6 Jan 2022 08:36:45 +0000
|
||||
Subject: Use RFH global id to ensure the RFH is valid.
|
||||
|
||||
Observing via RenderFrameDeleted and RenderFrameHostChanged is not
|
||||
sufficient for validating the RFH is still valid, because the frames
|
||||
can belong to inner WebContents. As suggested in
|
||||
https://crrev.com/c/2449389, storing a GlobalFrameRoutingId is the
|
||||
preferred method of keeping a reference to a RFH.
|
||||
|
||||
Bug: 1284367
|
||||
Change-Id: I3afb40e394d6e2e7fd19b2704e0dd68fa23c7bb2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3367466
|
||||
Reviewed-by: Daniel Rubery <drubery@chromium.org>
|
||||
Commit-Queue: Xinghui Lu <xinghuilu@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956061}
|
||||
|
||||
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
index 4ba3daa516121e73ead560fd3ba9d6e011ceadc7..c7ca2f45eb8afdb2713630e507733741bf4a8307 100644
|
||||
--- a/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
+++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
@@ -596,7 +596,8 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails) {
|
||||
parent_node->children.push_back(GURL(kDOMChildURL));
|
||||
params.push_back(std::move(parent_node));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -815,10 +816,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(),
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params_copy));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params_copy));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params_copy));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -864,9 +866,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(outer_params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -990,9 +994,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_AmbiguousDOM) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(outer_params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(outer_params));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params));
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
ClientSafeBrowsingReportRequest actual;
|
||||
@@ -1257,10 +1263,10 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_TrimToAdTags) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), child_rfh,
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), child_rfh->GetGlobalId(),
|
||||
std::move(inner_params));
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), main_rfh(),
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
@@ -1333,10 +1339,10 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_EmptyReportNotSent) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), child_rfh,
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), child_rfh->GetGlobalId(),
|
||||
std::move(inner_params));
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), main_rfh(),
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
@@ -1593,7 +1599,8 @@ TEST_F(ThreatDetailsTest, HTTPCache) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1673,7 +1680,8 @@ TEST_F(ThreatDetailsTest, HttpsResourceSanitization) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1756,7 +1764,8 @@ TEST_F(ThreatDetailsTest, HTTPCacheNoEntries) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1815,7 +1824,8 @@ TEST_F(ThreatDetailsTest, HistoryServiceUrls) {
|
||||
// The redirects collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the redirects callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
diff --git a/components/safe_browsing/content/browser/threat_details.cc b/components/safe_browsing/content/browser/threat_details.cc
|
||||
index f3fe647b5d443c2a2f284289ae66d81782c5f6e8..361830189b0ab6324fe87719f36f2fa0bc948224 100644
|
||||
--- a/components/safe_browsing/content/browser/threat_details.cc
|
||||
+++ b/components/safe_browsing/content/browser/threat_details.cc
|
||||
@@ -664,16 +664,20 @@ void ThreatDetails::RequestThreatDOMDetails(content::RenderFrameHost* frame) {
|
||||
pending_render_frame_hosts_.push_back(frame);
|
||||
raw_threat_report->GetThreatDOMDetails(
|
||||
base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, GetWeakPtr(),
|
||||
- std::move(threat_reporter), frame));
|
||||
+ std::move(threat_reporter), frame->GetGlobalId()));
|
||||
}
|
||||
|
||||
// When the renderer is done, this is called.
|
||||
void ThreatDetails::OnReceivedThreatDOMDetails(
|
||||
mojo::Remote<mojom::ThreatReporter> threat_reporter,
|
||||
- content::RenderFrameHost* sender,
|
||||
+ content::GlobalRenderFrameHostId sender_id,
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params) {
|
||||
// If the RenderFrameHost was closed between sending the IPC and this callback
|
||||
// running, |sender| will be invalid.
|
||||
+ auto* sender = content::RenderFrameHost::FromID(sender_id);
|
||||
+ if (!sender) {
|
||||
+ return;
|
||||
+ }
|
||||
const auto sender_it = std::find(pending_render_frame_hosts_.begin(),
|
||||
pending_render_frame_hosts_.end(), sender);
|
||||
if (sender_it == pending_render_frame_hosts_.end()) {
|
||||
diff --git a/components/safe_browsing/content/browser/threat_details.h b/components/safe_browsing/content/browser/threat_details.h
|
||||
index 8cb89700141561aab49edc474799c9e7148b8ae8..61dcb8d9c772d223661236d99aebd1d3ebe01d3a 100644
|
||||
--- a/components/safe_browsing/content/browser/threat_details.h
|
||||
+++ b/components/safe_browsing/content/browser/threat_details.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "components/safe_browsing/core/common/proto/csd.pb.h"
|
||||
#include "components/security_interstitials/core/unsafe_resource.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
+#include "content/public/browser/global_routing_id.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
|
||||
@@ -169,7 +170,7 @@ class ThreatDetails : public content::WebContentsObserver {
|
||||
|
||||
void OnReceivedThreatDOMDetails(
|
||||
mojo::Remote<mojom::ThreatReporter> threat_reporter,
|
||||
- content::RenderFrameHost* sender,
|
||||
+ content::GlobalRenderFrameHostId sender_id,
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params);
|
||||
|
||||
void AddRedirectUrlList(const std::vector<GURL>& urls);
|
||||
53
patches/chromium/cherry-pick-1887414c016d.patch
Normal file
53
patches/chromium/cherry-pick-1887414c016d.patch
Normal file
@@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Muyao Xu <muyaoxu@google.com>
|
||||
Date: Thu, 17 Feb 2022 16:23:29 +0000
|
||||
Subject: Replace WidgetObserver::OnWidgetClosing() with OnWidgetDestroying()
|
||||
|
||||
In some cases, OnWidgetClosing() is not called when the widget is
|
||||
closed, resulting an invalid pointer |widget_| stored in
|
||||
WebContentsDisplayObserverView.
|
||||
|
||||
This CL replaces OnWidgetClosing() with OnWidgetDestroying(), which
|
||||
is recommended in crbug.com/1240365
|
||||
|
||||
(cherry picked from commit 4535fe2334d0713535adb52b641a8cb34e11333c)
|
||||
|
||||
Bug: 1291728
|
||||
Change-Id: I64fef8b30930f60220008809ee00f4385d6c3520
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3425473
|
||||
Auto-Submit: Muyao Xu <muyaoxu@google.com>
|
||||
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#965431}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3435985
|
||||
Reviewed-by: Michael Ershov <miersh@google.com>
|
||||
Owners-Override: Michael Ershov <miersh@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1480}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
index b2cd4550d26fcbe5463043181800e5d705559cb3..e2a1c772c31a3c073c8629cb745c7a5dd16174a8 100644
|
||||
--- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
+++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
@@ -64,7 +64,7 @@ void WebContentsDisplayObserverView::OnBrowserSetLastActive(Browser* browser) {
|
||||
}
|
||||
}
|
||||
|
||||
-void WebContentsDisplayObserverView::OnWidgetClosing(views::Widget* widget) {
|
||||
+void WebContentsDisplayObserverView::OnWidgetDestroying(views::Widget* widget) {
|
||||
if (widget_)
|
||||
widget_->RemoveObserver(this);
|
||||
widget_ = nullptr;
|
||||
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
index 17a8ca48b1c836a82e2be5e5c605bc1837150cba..b63cf4505318a44c65585b06ec13960bad5d9e32 100644
|
||||
--- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
+++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
@@ -28,7 +28,7 @@ class WebContentsDisplayObserverView : public WebContentsDisplayObserver,
|
||||
void OnBrowserSetLastActive(Browser* browser) override;
|
||||
|
||||
// views::WidgetObserver overrides:
|
||||
- void OnWidgetClosing(views::Widget* widget) override;
|
||||
+ void OnWidgetDestroying(views::Widget* widget) override;
|
||||
void OnWidgetBoundsChanged(views::Widget* widget,
|
||||
const gfx::Rect& new_bounds) override;
|
||||
|
||||
354
patches/chromium/cherry-pick-1a8af2da50e4.patch
Normal file
354
patches/chromium/cherry-pick-1a8af2da50e4.patch
Normal file
@@ -0,0 +1,354 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lukasz Anforowicz <lukasza@chromium.org>
|
||||
Date: Mon, 8 Nov 2021 15:05:30 +0000
|
||||
Subject: Deleting unused field: `FetchEventPreloadHandle::url_loader`.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The `FetchEventPreloadHandle::url_loader` field is not really used - it
|
||||
is only needed to keep the URLLoader alive (and this can be accomplished
|
||||
in a simpler way, by keeping the mojo::PendingRemote in the Browser
|
||||
process).
|
||||
|
||||
This CL removes the `FetchEventPreloadHandle::url_loader` field and the
|
||||
FetchEventPreloadHandle and WebFetchEventPreloadHandle types (collapsing
|
||||
these handle types into their only other remaining field:
|
||||
mojo::PendingReceiver<network::mojom::URLLoaderClient>).
|
||||
|
||||
(cherry picked from commit dbe67ccde52e30acf6a66b1b9cc83768a067fa6a)
|
||||
|
||||
Fixed: 1264477
|
||||
Change-Id: I9c9c54900d79e92ac08eeb43536c938fa84a58f8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3252914
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Ben Kelly <wanderview@chromium.org>
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#937895}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3262600
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Ben Kelly <wanderview@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#853}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
|
||||
index d6faccd4c57e4ceb3ea3a9371de5afff035eba79..a6bbbf73953b9de6620ab3f0b193d9cc35a4d523 100644
|
||||
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
|
||||
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
|
||||
@@ -449,8 +449,10 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
|
||||
// NetworkService.
|
||||
URLLoaderAssets(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
|
||||
+ mojo::PendingRemote<network::mojom::URLLoader> url_loader,
|
||||
std::unique_ptr<DelegatingURLLoaderClient> url_loader_client)
|
||||
: shared_url_loader_factory_(std::move(shared_url_loader_factory)),
|
||||
+ url_loader_(std::move(url_loader)),
|
||||
url_loader_client_(std::move(url_loader_client)) {}
|
||||
|
||||
void MaybeReportToDevTools(std::pair<int, int> worker_id,
|
||||
@@ -467,6 +469,7 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
|
||||
|
||||
// NetworkService:
|
||||
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
|
||||
+ mojo::PendingRemote<network::mojom::URLLoader> url_loader_;
|
||||
|
||||
// Both:
|
||||
std::unique_ptr<DelegatingURLLoaderClient> url_loader_client_;
|
||||
@@ -633,7 +636,8 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
|
||||
auto params = blink::mojom::DispatchFetchEventParams::New();
|
||||
params->request = std::move(request_);
|
||||
params->client_id = client_id_;
|
||||
- params->preload_handle = std::move(preload_handle_);
|
||||
+ params->preload_url_loader_client_receiver =
|
||||
+ std::move(preload_url_loader_client_receiver_);
|
||||
params->is_offline_capability_check = is_offline_capability_check_;
|
||||
|
||||
// TODO(https://crbug.com/900700): Make the remote connected to a receiver
|
||||
@@ -721,13 +725,9 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
|
||||
// When the fetch event is for an offline capability check, respond to the
|
||||
// navigation preload with a network disconnected error, to simulate offline.
|
||||
if (is_offline_capability_check_) {
|
||||
- mojo::PendingRemote<network::mojom::URLLoader> url_loader_to_pass;
|
||||
mojo::Remote<network::mojom::URLLoaderClient> url_loader_client;
|
||||
- auto dummy_receiver = url_loader_to_pass.InitWithNewPipeAndPassReceiver();
|
||||
|
||||
- preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
|
||||
- preload_handle_->url_loader = std::move(url_loader_to_pass);
|
||||
- preload_handle_->url_loader_client_receiver =
|
||||
+ preload_url_loader_client_receiver_ =
|
||||
url_loader_client.BindNewPipeAndPassReceiver();
|
||||
|
||||
url_loader_client->OnComplete(
|
||||
@@ -770,12 +770,10 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
|
||||
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
|
||||
std::move(network_factory));
|
||||
|
||||
- preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
|
||||
-
|
||||
// Create the DelegatingURLLoaderClient, which becomes the
|
||||
// URLLoaderClient for the navigation preload network request.
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> inner_url_loader_client;
|
||||
- preload_handle_->url_loader_client_receiver =
|
||||
+ preload_url_loader_client_receiver_ =
|
||||
inner_url_loader_client.InitWithNewPipeAndPassReceiver();
|
||||
auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>(
|
||||
std::move(inner_url_loader_client), resource_request);
|
||||
@@ -810,11 +808,9 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
|
||||
net::MutableNetworkTrafficAnnotationTag(
|
||||
kNavigationPreloadTrafficAnnotation));
|
||||
|
||||
- preload_handle_->url_loader = std::move(url_loader);
|
||||
-
|
||||
DCHECK(!url_loader_assets_);
|
||||
url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>(
|
||||
- std::move(factory), std::move(url_loader_client));
|
||||
+ std::move(factory), std::move(url_loader), std::move(url_loader_client));
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h
|
||||
index 4aae09d3659c60f318801f305e1bc4feee93c544..ebec34d82d0467f79f21b9bf00d201cf6021bd2e 100644
|
||||
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.h
|
||||
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
|
||||
@@ -122,10 +122,11 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
|
||||
|
||||
scoped_refptr<URLLoaderAssets> url_loader_assets_;
|
||||
|
||||
- // |preload_handle_| holds the URLLoader and URLLoaderClient for the service
|
||||
- // worker to receive the navigation preload response. It's passed to the
|
||||
- // service worker along with the fetch event.
|
||||
- blink::mojom::FetchEventPreloadHandlePtr preload_handle_;
|
||||
+ // Holds the URLLoaderClient for the service worker to receive the navigation
|
||||
+ // preload response. It's passed to the service worker along with the fetch
|
||||
+ // event.
|
||||
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver_;
|
||||
|
||||
// Whether to dispatch an offline-capability-check fetch event.
|
||||
const bool is_offline_capability_check_ = false;
|
||||
diff --git a/content/renderer/service_worker/navigation_preload_request.cc b/content/renderer/service_worker/navigation_preload_request.cc
|
||||
index c9e9ffd4c68a583569fd5633ca2369e190e2aed7..92f9d4a7de115cac0502aeb9c777605a756b6175 100644
|
||||
--- a/content/renderer/service_worker/navigation_preload_request.cc
|
||||
+++ b/content/renderer/service_worker/navigation_preload_request.cc
|
||||
@@ -19,12 +19,12 @@ NavigationPreloadRequest::NavigationPreloadRequest(
|
||||
ServiceWorkerContextClient* owner,
|
||||
int fetch_event_id,
|
||||
const GURL& url,
|
||||
- blink::mojom::FetchEventPreloadHandlePtr preload_handle)
|
||||
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver)
|
||||
: owner_(owner),
|
||||
fetch_event_id_(fetch_event_id),
|
||||
url_(url),
|
||||
- url_loader_(std::move(preload_handle->url_loader)),
|
||||
- receiver_(this, std::move(preload_handle->url_loader_client_receiver)) {}
|
||||
+ receiver_(this, std::move(preload_url_loader_client_receiver)) {}
|
||||
|
||||
NavigationPreloadRequest::~NavigationPreloadRequest() = default;
|
||||
|
||||
diff --git a/content/renderer/service_worker/navigation_preload_request.h b/content/renderer/service_worker/navigation_preload_request.h
|
||||
index 08cfc4a0dad5777b88f2388da5d07c864d9953fd..f6d19a3d1383767e1c450be7ec29a47ff245ff5a 100644
|
||||
--- a/content/renderer/service_worker/navigation_preload_request.h
|
||||
+++ b/content/renderer/service_worker/navigation_preload_request.h
|
||||
@@ -35,7 +35,8 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
|
||||
ServiceWorkerContextClient* owner,
|
||||
int fetch_event_id,
|
||||
const GURL& url,
|
||||
- blink::mojom::FetchEventPreloadHandlePtr preload_handle);
|
||||
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver);
|
||||
~NavigationPreloadRequest() override;
|
||||
|
||||
// network::mojom::URLLoaderClient:
|
||||
@@ -59,11 +60,10 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
|
||||
void ReportErrorToOwner(const std::string& message,
|
||||
blink::WebServiceWorkerError::Mode error_mode);
|
||||
|
||||
- ServiceWorkerContextClient* owner_;
|
||||
+ ServiceWorkerContextClient* owner_ = nullptr;
|
||||
|
||||
- const int fetch_event_id_;
|
||||
+ const int fetch_event_id_ = -1;
|
||||
const GURL url_;
|
||||
- mojo::Remote<network::mojom::URLLoader> url_loader_;
|
||||
mojo::Receiver<network::mojom::URLLoaderClient> receiver_;
|
||||
|
||||
std::unique_ptr<blink::WebURLResponse> response_;
|
||||
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
|
||||
index d569c5362c0c3866b333db714d7dd8e7f3344afc..f65f535b5c228ce881a0b0066b67d9847b6168a4 100644
|
||||
--- a/content/renderer/service_worker/service_worker_context_client.cc
|
||||
+++ b/content/renderer/service_worker/service_worker_context_client.cc
|
||||
@@ -476,14 +476,14 @@ void ServiceWorkerContextClient::SendWorkerStarted(
|
||||
void ServiceWorkerContextClient::SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const blink::WebURL& url,
|
||||
- std::unique_ptr<blink::WebFetchEventPreloadHandle> preload_handle) {
|
||||
+ blink::CrossVariantMojoReceiver<
|
||||
+ network::mojom::URLLoaderClientInterfaceBase>
|
||||
+ preload_url_loader_client_receiver) {
|
||||
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
|
||||
DCHECK(context_);
|
||||
auto preload_request = std::make_unique<NavigationPreloadRequest>(
|
||||
this, fetch_event_id, GURL(url),
|
||||
- blink::mojom::FetchEventPreloadHandle::New(
|
||||
- std::move(preload_handle->url_loader),
|
||||
- std::move(preload_handle->url_loader_client_receiver)));
|
||||
+ std::move(preload_url_loader_client_receiver));
|
||||
context_->preload_requests.AddWithID(std::move(preload_request),
|
||||
fetch_event_id);
|
||||
}
|
||||
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
|
||||
index 8191aaec6ed37c6a64bcbd9beac720777de3075e..5abd533c6c3b1926efa6b8fc158562468cc96e19 100644
|
||||
--- a/content/renderer/service_worker/service_worker_context_client.h
|
||||
+++ b/content/renderer/service_worker/service_worker_context_client.h
|
||||
@@ -159,8 +159,9 @@ class CONTENT_EXPORT ServiceWorkerContextClient
|
||||
const blink::WebString& source_url) override;
|
||||
void SetupNavigationPreload(int fetch_event_id,
|
||||
const blink::WebURL& url,
|
||||
- std::unique_ptr<blink::WebFetchEventPreloadHandle>
|
||||
- preload_handle) override;
|
||||
+ blink::CrossVariantMojoReceiver<
|
||||
+ network::mojom::URLLoaderClientInterfaceBase>
|
||||
+ preload_url_loader_client_receiver) override;
|
||||
void RequestTermination(RequestTerminationCallback callback) override;
|
||||
scoped_refptr<blink::WebServiceWorkerFetchContext>
|
||||
CreateWorkerFetchContextOnInitiatorThread() override;
|
||||
diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md
|
||||
index b950df5a7733b26ae3a9dbc1bacc208e584fa9e6..334ba1c8fd92aed36dec6993afe38ca91ffcc49a 100644
|
||||
--- a/mojo/public/cpp/bindings/README.md
|
||||
+++ b/mojo/public/cpp/bindings/README.md
|
||||
@@ -1709,6 +1709,9 @@ C++ sources can depend on shared sources only, by referencing the
|
||||
`"${target_name}_shared"` target, e.g. `"//foo/mojom:mojom_shared"` in the
|
||||
example above.
|
||||
|
||||
+For converting between Blink and non-Blink variants, please see
|
||||
+`//third_party/blink/public/platform/cross_variant_mojo_util.h`.
|
||||
+
|
||||
## Versioning Considerations
|
||||
|
||||
For general documentation of versioning in the Mojom IDL see
|
||||
diff --git a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
|
||||
index 382be0b3dd042ceadb73e4d514f93ac7c8624b43..c95a2e255166871ff45b6a4c3a8b206e1dace776 100644
|
||||
--- a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
|
||||
+++ b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
|
||||
@@ -9,13 +9,6 @@ import "third_party/blink/public/mojom/blob/blob.mojom";
|
||||
import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
|
||||
import "third_party/blink/public/mojom/timing/worker_timing_container.mojom";
|
||||
|
||||
-// Used for service worker navigation preload, to create
|
||||
-// FetchEvent#preloadResponse.
|
||||
-struct FetchEventPreloadHandle {
|
||||
- pending_remote<network.mojom.URLLoader> url_loader;
|
||||
- pending_receiver<network.mojom.URLLoaderClient> url_loader_client_receiver;
|
||||
-};
|
||||
-
|
||||
// Parameters used for dispatching a FetchEvent.
|
||||
struct DispatchFetchEventParams {
|
||||
// FetchEvent#request.
|
||||
@@ -23,8 +16,9 @@ struct DispatchFetchEventParams {
|
||||
|
||||
// FetchEvent#clientId.
|
||||
string client_id;
|
||||
+
|
||||
// FetchEvent#preloadResponse.
|
||||
- FetchEventPreloadHandle? preload_handle;
|
||||
+ pending_receiver<network.mojom.URLLoaderClient>? preload_url_loader_client_receiver;
|
||||
|
||||
// This is currently null for navigation because it's still being implemented.
|
||||
// TODO(https://crbug.com/900700): Make this non-nullable when implementation
|
||||
diff --git a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
|
||||
index 67c0c9d3cb10478755422b489c97afe8adce1a24..0a8cde9a7f6bab9de2c43f13c1bc0d35375bc2b5 100644
|
||||
--- a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
|
||||
+++ b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
|
||||
@@ -31,8 +31,6 @@
|
||||
#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_CONTEXT_CLIENT_H_
|
||||
#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_CONTEXT_CLIENT_H_
|
||||
|
||||
-#include <memory>
|
||||
-
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "services/network/public/mojom/url_loader.mojom-shared.h"
|
||||
#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h"
|
||||
@@ -53,14 +51,6 @@ namespace blink {
|
||||
class WebServiceWorkerContextProxy;
|
||||
class WebString;
|
||||
|
||||
-// Used to pass the mojom struct blink.mojom.FetchEventPreloadHandle across the
|
||||
-// boundary between //content and Blink.
|
||||
-struct WebFetchEventPreloadHandle {
|
||||
- CrossVariantMojoRemote<network::mojom::URLLoaderInterfaceBase> url_loader;
|
||||
- CrossVariantMojoReceiver<network::mojom::URLLoaderClientInterfaceBase>
|
||||
- url_loader_client_receiver;
|
||||
-};
|
||||
-
|
||||
// WebServiceWorkerContextClient is a "client" of a service worker execution
|
||||
// context. This interface is implemented by the embedder and allows the
|
||||
// embedder to communicate with the service worker execution context. It is
|
||||
@@ -166,7 +156,8 @@ class WebServiceWorkerContextClient {
|
||||
virtual void SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const WebURL& url,
|
||||
- std::unique_ptr<WebFetchEventPreloadHandle> preload_handle) {}
|
||||
+ CrossVariantMojoReceiver<network::mojom::URLLoaderClientInterfaceBase>
|
||||
+ preload_url_loader_client_receiver) {}
|
||||
|
||||
// Called when we need to request to terminate this worker due to idle
|
||||
// timeout.
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
index 39559c139024f36a3a8c91470105454e3d721534..daf2279408cf51877bf463984296734807f0ea6f 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
@@ -1511,11 +1511,12 @@ void ServiceWorkerGlobalScope::StartFetchEvent(
|
||||
params->request->url.ElidedString().Utf8());
|
||||
|
||||
// Set up for navigation preload (FetchEvent#preloadResponse) if needed.
|
||||
- const bool navigation_preload_sent = !!params->preload_handle;
|
||||
+ bool navigation_preload_sent = !!params->preload_url_loader_client_receiver;
|
||||
if (navigation_preload_sent) {
|
||||
To<ServiceWorkerGlobalScopeProxy>(ReportingProxy())
|
||||
- .SetupNavigationPreload(event_id, params->request->url,
|
||||
- std::move(params->preload_handle));
|
||||
+ .SetupNavigationPreload(
|
||||
+ event_id, params->request->url,
|
||||
+ std::move(params->preload_url_loader_client_receiver));
|
||||
}
|
||||
|
||||
ScriptState::Scope scope(ScriptController()->GetScriptState());
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
|
||||
index b2efbea7c370b7f641cad9c5db75f9826ec705ed..33d11a19b350e1dd12c105403ed513e9a62a76ec 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
|
||||
@@ -257,14 +257,11 @@ bool ServiceWorkerGlobalScopeProxy::IsServiceWorkerGlobalScopeProxy() const {
|
||||
void ServiceWorkerGlobalScopeProxy::SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const KURL& url,
|
||||
- mojom::blink::FetchEventPreloadHandlePtr preload_handle) {
|
||||
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
|
||||
- auto web_preload_handle = std::make_unique<WebFetchEventPreloadHandle>();
|
||||
- web_preload_handle->url_loader = std::move(preload_handle->url_loader);
|
||||
- web_preload_handle->url_loader_client_receiver =
|
||||
- std::move(preload_handle->url_loader_client_receiver);
|
||||
- Client().SetupNavigationPreload(fetch_event_id, url,
|
||||
- std::move(web_preload_handle));
|
||||
+ Client().SetupNavigationPreload(
|
||||
+ fetch_event_id, url, std::move(preload_url_loader_client_receiver));
|
||||
}
|
||||
|
||||
void ServiceWorkerGlobalScopeProxy::RequestTermination(
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
|
||||
index 783dbe1919d1282f40117aea22b75a8e54e82d89..d54a2449da63f67930cb3d85cfbb27c35c45a8d3 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
|
||||
@@ -129,7 +129,8 @@ class ServiceWorkerGlobalScopeProxy final : public WebServiceWorkerContextProxy,
|
||||
void SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const KURL& url,
|
||||
- mojom::blink::FetchEventPreloadHandlePtr preload_handle);
|
||||
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver);
|
||||
void RequestTermination(WTF::CrossThreadOnceFunction<void(bool)> callback);
|
||||
|
||||
// Detaches this proxy object entirely from the outside world, clearing out
|
||||
86
patches/chromium/cherry-pick-22f27676515e.patch
Normal file
86
patches/chromium/cherry-pick-22f27676515e.patch
Normal file
@@ -0,0 +1,86 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Christopher Cameron <ccameron@chromium.org>
|
||||
Date: Tue, 9 Nov 2021 00:23:45 +0000
|
||||
Subject: WebContentsVideoCaptureDevice: Fix use-after-free
|
||||
|
||||
The classes WebContentsVideoCaptureDevice,
|
||||
AuraWindowVideoCaptureDevice::WindowTracker, and
|
||||
ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate all keep a raw
|
||||
pointer that they use to access the MouseCursorOverlayController.
|
||||
|
||||
This raw pointer comes from the base class FrameSinkVideoCaptureDevice
|
||||
and should outlive the class that has a raw pointer. On macOS, this
|
||||
isn't necessarily the case.
|
||||
|
||||
Avoid this sharp edge by using a WeakPtr for the
|
||||
MouseCursorOverlayController, and checking that it is valid before
|
||||
using it.
|
||||
|
||||
Bug: 1252562, 1179098
|
||||
Change-Id: I1d74bea1255597662aab3f9f2430c49d2e39836a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3260842
|
||||
Commit-Queue: ccameron <ccameron@chromium.org>
|
||||
Reviewed-by: mark a. foltz <mfoltz@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#939604}
|
||||
|
||||
diff --git a/content/browser/media/capture/views_widget_video_capture_device_mac.cc b/content/browser/media/capture/views_widget_video_capture_device_mac.cc
|
||||
index fee27cebfd64ee1cddbcb9873fa4b5e67cb526fc..50da870a417c17b1999b7d98bd8c2cb82e356c06 100644
|
||||
--- a/content/browser/media/capture/views_widget_video_capture_device_mac.cc
|
||||
+++ b/content/browser/media/capture/views_widget_video_capture_device_mac.cc
|
||||
@@ -19,9 +19,10 @@ namespace content {
|
||||
class ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate
|
||||
: public remote_cocoa::ScopedCGWindowID::Observer {
|
||||
public:
|
||||
- UIThreadDelegate(uint32_t cg_window_id,
|
||||
- const base::WeakPtr<FrameSinkVideoCaptureDevice> device,
|
||||
- MouseCursorOverlayController* cursor_controller)
|
||||
+ UIThreadDelegate(
|
||||
+ uint32_t cg_window_id,
|
||||
+ const base::WeakPtr<FrameSinkVideoCaptureDevice> device,
|
||||
+ const base::WeakPtr<MouseCursorOverlayController> cursor_controller)
|
||||
: cg_window_id_(cg_window_id),
|
||||
device_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
||||
device_(device),
|
||||
@@ -83,8 +84,11 @@ class ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate
|
||||
void OnScopedCGWindowIDMouseMoved(uint32_t cg_window_id,
|
||||
const gfx::PointF& location_in_window,
|
||||
const gfx::Size& window_size) override {
|
||||
- cursor_controller_->SetTargetSize(window_size);
|
||||
- cursor_controller_->OnMouseMoved(location_in_window);
|
||||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
+ if (cursor_controller_) {
|
||||
+ cursor_controller_->SetTargetSize(window_size);
|
||||
+ cursor_controller_->OnMouseMoved(location_in_window);
|
||||
+ }
|
||||
}
|
||||
|
||||
const uint32_t cg_window_id_;
|
||||
@@ -96,20 +100,21 @@ class ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate
|
||||
|
||||
// |device_| may only be dereferenced by tasks posted to
|
||||
// |device_task_runner_|.
|
||||
- base::WeakPtr<FrameSinkVideoCaptureDevice> device_;
|
||||
+ const base::WeakPtr<FrameSinkVideoCaptureDevice> device_;
|
||||
|
||||
- // Owned by FrameSinkVideoCaptureDevice. This will be valid for the life of
|
||||
- // UIThreadDelegate because the UIThreadDelegate deleter task will be posted
|
||||
- // to the UI thread before the MouseCursorOverlayController deleter task.
|
||||
- // See similar behavior in WebContentsVideoCaptureDevice::FrameTracker.
|
||||
- MouseCursorOverlayController* const cursor_controller_;
|
||||
+ // Owned by FrameSinkVideoCaptureDevice. This may only be accessed on the
|
||||
+ // UI thread. This is not guaranteed to be valid and must be checked before
|
||||
+ // use.
|
||||
+ // https://crbug.com/1252562
|
||||
+ const base::WeakPtr<MouseCursorOverlayController> cursor_controller_;
|
||||
};
|
||||
|
||||
ViewsWidgetVideoCaptureDeviceMac::ViewsWidgetVideoCaptureDeviceMac(
|
||||
const DesktopMediaID& source_id)
|
||||
: weak_factory_(this) {
|
||||
ui_thread_delegate_ = std::make_unique<UIThreadDelegate>(
|
||||
- source_id.id, weak_factory_.GetWeakPtr(), cursor_controller());
|
||||
+ source_id.id, weak_factory_.GetWeakPtr(),
|
||||
+ cursor_controller()->GetWeakPtr());
|
||||
}
|
||||
|
||||
ViewsWidgetVideoCaptureDeviceMac::~ViewsWidgetVideoCaptureDeviceMac() {
|
||||
36
patches/chromium/cherry-pick-246c10dede97.patch
Normal file
36
patches/chromium/cherry-pick-246c10dede97.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Herre <toprice@chromium.org>
|
||||
Date: Fri, 18 Feb 2022 13:52:01 +0000
|
||||
Subject: Switch to new RequestPermissionsFromCurrentDocument API method for
|
||||
Media Stream Devices
|
||||
|
||||
Switch away from the deprecated RequestPermissions() API, as a part of removing a bug where the previously provided request.security_origin param might get destroyed during the method execution.
|
||||
|
||||
(cherry picked from commit cb6778fb965e2b010922f157c68480de863c252e)
|
||||
|
||||
Bug: 1283402
|
||||
Change-Id: I512ce910146ec60d4d35fa1a86a71a3b0983a5d1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3417436
|
||||
Reviewed-by: Florent Castelli <orphis@chromium.org>
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#964535}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3473365
|
||||
Cr-Commit-Position: refs/branch-heads/4844@{#655}
|
||||
Cr-Branched-From: 007241ce2e6c8e5a7b306cc36c730cd07cd38825-refs/heads/main@{#961656}
|
||||
|
||||
diff --git a/components/webrtc/media_stream_devices_controller.cc b/components/webrtc/media_stream_devices_controller.cc
|
||||
index 8eb0e01815f6a5f2f0241554b3e5b93017564242..33468f9f2b1bcc2cda8d98748902984ae82e147d 100644
|
||||
--- a/components/webrtc/media_stream_devices_controller.cc
|
||||
+++ b/components/webrtc/media_stream_devices_controller.cc
|
||||
@@ -139,9 +139,8 @@ void MediaStreamDevicesController::RequestPermissions(
|
||||
}
|
||||
}
|
||||
|
||||
- permission_manager->RequestPermissions(
|
||||
- content_settings_types, rfh, request.security_origin,
|
||||
- request.user_gesture,
|
||||
+ permission_manager->RequestPermissionsFromCurrentDocument(
|
||||
+ content_settings_types, rfh, request.user_gesture,
|
||||
base::BindOnce(
|
||||
&MediaStreamDevicesController::RequestAndroidPermissionsIfNeeded,
|
||||
web_contents, std::move(controller), will_prompt_for_audio,
|
||||
71
patches/chromium/cherry-pick-27eb11a28555.patch
Normal file
71
patches/chromium/cherry-pick-27eb11a28555.patch
Normal file
@@ -0,0 +1,71 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Wed, 29 Sep 2021 07:58:26 +0000
|
||||
Subject: Run CORS check for manual redirects
|
||||
|
||||
...to prevent status code leak.
|
||||
|
||||
Bug: 1251179
|
||||
Change-Id: I7fcab0daf49e16305ed53702f42d1d1eacc933e5
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3193481
|
||||
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#926166}
|
||||
|
||||
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
|
||||
index 6e4e8acf811f29712e87994e3fa125a811da978a..72aac202ca076fe7ea81f833549773f540e9b7d7 100644
|
||||
--- a/services/network/cors/cors_url_loader.cc
|
||||
+++ b/services/network/cors/cors_url_loader.cc
|
||||
@@ -303,13 +303,6 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
|
||||
DCHECK(forwarding_client_);
|
||||
DCHECK(!deferred_redirect_url_);
|
||||
|
||||
- if (request_.redirect_mode == mojom::RedirectMode::kManual) {
|
||||
- deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
|
||||
- forwarding_client_->OnReceiveRedirect(redirect_info,
|
||||
- std::move(response_head));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
// If |CORS flag| is set and a CORS check for |request| and |response| returns
|
||||
// failure, then return a network error.
|
||||
if (fetch_cors_flag_ && IsCorsEnabledRequestMode(request_.mode)) {
|
||||
@@ -327,6 +320,13 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (request_.redirect_mode == mojom::RedirectMode::kManual) {
|
||||
+ deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
|
||||
+ forwarding_client_->OnReceiveRedirect(redirect_info,
|
||||
+ std::move(response_head));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
timing_allow_failed_flag_ = !PassesTimingAllowOriginCheck(*response_head);
|
||||
|
||||
// Because we initiate a new request on redirect in some cases, we cannot
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
index eed44e0414cb8947c9b7c21df6ef288f733f8994..9f1ff98c65af97bcf185867ac6c6e128dbd77715 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
@@ -1,6 +1,7 @@
|
||||
// META: script=/common/get-host-info.sub.js
|
||||
|
||||
var redirectLocation = "cors-top.txt";
|
||||
+const { ORIGIN, REMOTE_ORIGIN } = get_host_info();
|
||||
|
||||
function testRedirect(origin, redirectStatus, redirectMode, corsMode) {
|
||||
var url = new URL("../resources/redirect.py", self.location);
|
||||
@@ -47,4 +48,12 @@ for (var origin of ["same-origin", "cross-origin"]) {
|
||||
}
|
||||
}
|
||||
|
||||
+promise_test(async (t) => {
|
||||
+ const destination = `${ORIGIN}/common/blank.html`;
|
||||
+ // We use /common/redirect.py intentionally, as we want a CORS error.
|
||||
+ const url =
|
||||
+ `${REMOTE_ORIGIN}/common/redirect.py?location=${destination}`;
|
||||
+ await promise_rejects_js(t, TypeError, fetch(url, { redirect: "manual" }));
|
||||
+}, "manual redirect with a CORS error should be rejected");
|
||||
+
|
||||
done();
|
||||
36
patches/chromium/cherry-pick-3a5bafa35def.patch
Normal file
36
patches/chromium/cherry-pick-3a5bafa35def.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gough <ajgo@chromium.org>
|
||||
Date: Fri, 1 Oct 2021 23:30:09 +0000
|
||||
Subject: Tell clang not to devirtualize TargetServices
|
||||
|
||||
Before this change in official builds a child process's delayed
|
||||
integrity level was not being set correctly. With this change
|
||||
renderers run at Untrusted IL as intended.
|
||||
|
||||
(cherry picked from commit 19d2be5d47e0edc406ef7d93096f54009e47937f)
|
||||
|
||||
Tests: https://bugs.chromium.org/p/chromium/issues/detail?id=1254631#c13
|
||||
Bug: 1254631
|
||||
Change-Id: I52c149cca3de5218033ed0f37d9f76782b9a6302
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3198382
|
||||
Reviewed-by: Will Harris <wfh@chromium.org>
|
||||
Commit-Queue: Will Harris <wfh@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#926934}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3200146
|
||||
Commit-Queue: Alex Gough <ajgo@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1285}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/sandbox/win/src/sandbox.h b/sandbox/win/src/sandbox.h
|
||||
index 35996c1726e4767f04fff38e2efb655250e17e41..a53a347007212f79063044263c5703b014e2c4d2 100644
|
||||
--- a/sandbox/win/src/sandbox.h
|
||||
+++ b/sandbox/win/src/sandbox.h
|
||||
@@ -143,7 +143,7 @@ class [[clang::lto_visibility_public]] BrokerServices {
|
||||
// }
|
||||
//
|
||||
// For more information see the BrokerServices API documentation.
|
||||
-class TargetServices {
|
||||
+class [[clang::lto_visibility_public]] TargetServices {
|
||||
public:
|
||||
// Initializes the target. Must call this function before any other.
|
||||
// returns ALL_OK if successful. All other return values imply failure.
|
||||
51
patches/chromium/cherry-pick-45f9dcf5021d.patch
Normal file
51
patches/chromium/cherry-pick-45f9dcf5021d.patch
Normal file
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Vasiliev <vasilvv@chromium.org>
|
||||
Date: Tue, 26 Oct 2021 04:50:35 +0000
|
||||
Subject: Disable QuicTransport explicitly in the Network Service
|
||||
|
||||
(cherry picked from commit b1997bdadcda9738a19773f82605f65832acedac)
|
||||
|
||||
Bug: 1260940
|
||||
Change-Id: I6689fbce8115eda19e68414d7c03691704749b17
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3242207
|
||||
Auto-Submit: Victor Vasiliev <vasilvv@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1411}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/services/network/web_transport.cc b/services/network/web_transport.cc
|
||||
index 8eaba815d063c41588ac792dde914b41f04dde6a..1501da757db07294cf55d631b91fbc5b403d01ed 100644
|
||||
--- a/services/network/web_transport.cc
|
||||
+++ b/services/network/web_transport.cc
|
||||
@@ -27,7 +27,7 @@ net::WebTransportParameters CreateParameters(
|
||||
const std::vector<mojom::WebTransportCertificateFingerprintPtr>&
|
||||
fingerprints) {
|
||||
net::WebTransportParameters params;
|
||||
- params.enable_quic_transport = true;
|
||||
+ params.enable_quic_transport = false;
|
||||
params.enable_web_transport_http3 = true;
|
||||
|
||||
for (const auto& fingerprint : fingerprints) {
|
||||
diff --git a/services/network/web_transport_unittest.cc b/services/network/web_transport_unittest.cc
|
||||
index 1c02da12001499d0a6509ae71e59e3dd189b06e1..a85359bef06200cc60e8f6fbd7dc4637ef30fd9c 100644
|
||||
--- a/services/network/web_transport_unittest.cc
|
||||
+++ b/services/network/web_transport_unittest.cc
|
||||
@@ -364,7 +364,7 @@ struct PrintStringPiece {
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WebTransportTests,
|
||||
WebTransportTest,
|
||||
- testing::Values("quic-transport", "https"),
|
||||
+ testing::Values("https"),
|
||||
PrintStringPiece());
|
||||
|
||||
TEST_P(WebTransportTest, ConnectSuccessfully) {
|
||||
@@ -703,7 +703,7 @@ class WebTransportWithCustomCertificateTest : public WebTransportTest {
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WebTransportWithCustomCertificateTests,
|
||||
WebTransportWithCustomCertificateTest,
|
||||
- testing::Values("quic-transport", "https"),
|
||||
+ testing::Values("https"),
|
||||
PrintStringPiece());
|
||||
|
||||
TEST_P(WebTransportWithCustomCertificateTest, WithValidFingerprint) {
|
||||
62
patches/chromium/cherry-pick-4e528a5a8d83.patch
Normal file
62
patches/chromium/cherry-pick-4e528a5a8d83.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Wed, 15 Sep 2021 23:57:27 +0000
|
||||
Subject: FSA: Fix race condition in manager
|
||||
|
||||
(cherry picked from commit 951339b41022b08a67ad94ba5960b05c84bf4cf2)
|
||||
|
||||
Bug: 1248030
|
||||
Change-Id: I1ea819d1d6ac63ec8f400a45c893da49596235ef
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3154425
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Auto-Submit: Austin Sullivan <asully@chromium.org>
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#920376}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3160301
|
||||
Commit-Queue: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1077}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
index e317b6609026444e1b7cef4c27c33e44099aab75..0cd44a57e525cceb1b087ffd6a1351ed7dea6a7d 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
+++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
@@ -454,6 +454,11 @@ void FileSystemAccessManagerImpl::ResolveDefaultDirectory(
|
||||
std::move(callback))));
|
||||
}
|
||||
|
||||
+void FileSystemAccessManagerImpl::Shutdown() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+ permission_context_ = nullptr;
|
||||
+}
|
||||
+
|
||||
void FileSystemAccessManagerImpl::SetDefaultPathAndShowPicker(
|
||||
const BindingContext& context,
|
||||
blink::mojom::FilePickerOptionsPtr options,
|
||||
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.h b/content/browser/file_system_access/file_system_access_manager_impl.h
|
||||
index 82b2625ce7b22975e80114ce21ba53e298106977..29d53b2a25a13f0d36cf72cfd9f5f30abdd2976e 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_manager_impl.h
|
||||
+++ b/content/browser/file_system_access/file_system_access_manager_impl.h
|
||||
@@ -260,6 +260,8 @@ class CONTENT_EXPORT FileSystemAccessManagerImpl
|
||||
PathType path_type,
|
||||
const base::FilePath& path);
|
||||
|
||||
+ void Shutdown();
|
||||
+
|
||||
private:
|
||||
friend class FileSystemAccessFileHandleImpl;
|
||||
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index ba5ab2ff3ef437a6aa364753e5cc680f4545b282..86c6de60739a0c5aa49ed63f1546b478d7f58054 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1091,6 +1091,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
|
||||
std::move(database_tracker)));
|
||||
}
|
||||
|
||||
+ if (GetFileSystemAccessManager())
|
||||
+ GetFileSystemAccessManager()->Shutdown();
|
||||
+
|
||||
if (GetFileSystemContext())
|
||||
GetFileSystemContext()->Shutdown();
|
||||
|
||||
151
patches/chromium/cherry-pick-62142d222a80.patch
Normal file
151
patches/chromium/cherry-pick-62142d222a80.patch
Normal file
@@ -0,0 +1,151 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Thu, 24 Feb 2022 15:13:13 +0000
|
||||
Subject: Validate message headers sooner
|
||||
|
||||
M96 merge issues:
|
||||
- multiplex_router.h: conflict in removed lines because of
|
||||
differences in comments above header_validator_
|
||||
- connector.h: conflicting includes
|
||||
|
||||
Message header validation has been tied to interface message dispatch,
|
||||
but not all mojo::Message consumers are interface bindings.
|
||||
|
||||
mojo::Connector is a more general-purpose entry point through which
|
||||
incoming messages are received and transformed into mojo::Message
|
||||
objects. Blink's MessagePort implementation uses Connector directly to
|
||||
transmit and receive raw serialized object data.
|
||||
|
||||
This change moves MessageHeaderValidator ownership into Connector and
|
||||
always applies its validation immediately after reading a message from
|
||||
the pipe, thereby ensuring that all mojo::Message objects used in
|
||||
production have validated headers before use.
|
||||
|
||||
(cherry picked from commit 8d5bc69146505785ce299c490e35e3f3ef19f69c)
|
||||
|
||||
Fixed: 1281908
|
||||
Change-Id: Ie0e251ab04681a4fd4b849d82c247e0ed800dc04
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3462461
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#971263}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3483815
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1505}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h
|
||||
index 3975d01a434d6caf229c6d8eaedfe5e2acf684f8..ff17af9b378a1992dbd681e80e957826ebfd83dd 100644
|
||||
--- a/mojo/public/cpp/bindings/connector.h
|
||||
+++ b/mojo/public/cpp/bindings/connector.h
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "base/sequenced_task_runner.h"
|
||||
#include "mojo/public/cpp/bindings/connection_group.h"
|
||||
#include "mojo/public/cpp/bindings/message.h"
|
||||
+#include "mojo/public/cpp/bindings/message_header_validator.h"
|
||||
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
|
||||
#include "mojo/public/cpp/system/core.h"
|
||||
#include "mojo/public/cpp/system/handle_signal_tracker.h"
|
||||
@@ -345,6 +346,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) Connector : public MessageReceiver {
|
||||
// The number of pending tasks for |CallDispatchNextMessageFromPipe|.
|
||||
size_t num_pending_dispatch_tasks_ = 0;
|
||||
|
||||
+ MessageHeaderValidator header_validator_;
|
||||
+
|
||||
#if defined(ENABLE_IPC_FUZZER)
|
||||
std::unique_ptr<MessageReceiver> message_dumper_;
|
||||
#endif
|
||||
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
|
||||
index 92a9756cbaebe12377e9c9b81467260c73528311..cb08f13b1bfa13a1a79f7f39005f826e51c12a69 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/connector.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/connector.cc
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "base/rand_util.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/strcat.h"
|
||||
+#include "base/strings/string_util.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/threading/sequence_local_storage_slot.h"
|
||||
@@ -152,7 +153,11 @@ Connector::Connector(ScopedMessagePipeHandle message_pipe,
|
||||
force_immediate_dispatch_(!EnableTaskPerMessage()),
|
||||
outgoing_serialization_mode_(g_default_outgoing_serialization_mode),
|
||||
incoming_serialization_mode_(g_default_incoming_serialization_mode),
|
||||
- interface_name_(interface_name) {
|
||||
+ interface_name_(interface_name),
|
||||
+ header_validator_(
|
||||
+ base::JoinString({interface_name ? interface_name : "Generic",
|
||||
+ "MessageHeaderValidator"},
|
||||
+ "")) {
|
||||
if (config == MULTI_THREADED_SEND)
|
||||
lock_.emplace();
|
||||
|
||||
@@ -492,6 +497,7 @@ MojoResult Connector::ReadMessage(Message* message) {
|
||||
return result;
|
||||
|
||||
*message = Message::CreateFromMessageHandle(&handle);
|
||||
+
|
||||
if (message->IsNull()) {
|
||||
// Even if the read was successful, the Message may still be null if there
|
||||
// was a problem extracting handles from it. We treat this essentially as
|
||||
@@ -507,6 +513,10 @@ MojoResult Connector::ReadMessage(Message* message) {
|
||||
return MOJO_RESULT_ABORTED;
|
||||
}
|
||||
|
||||
+ if (!header_validator_.Accept(message)) {
|
||||
+ return MOJO_RESULT_ABORTED;
|
||||
+ }
|
||||
+
|
||||
return MOJO_RESULT_OK;
|
||||
}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
index 605e51344d64eb5ede3ab475bc8833b37a458535..23e3970089e33d07b18d734d4f599c9c9f9e4bc8 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
|
||||
#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
|
||||
#include "mojo/public/cpp/bindings/lib/message_quota_checker.h"
|
||||
-#include "mojo/public/cpp/bindings/message_header_validator.h"
|
||||
#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
|
||||
|
||||
namespace mojo {
|
||||
@@ -389,14 +388,7 @@ MultiplexRouter::MultiplexRouter(
|
||||
if (quota_checker)
|
||||
connector_.SetMessageQuotaChecker(std::move(quota_checker));
|
||||
|
||||
- std::unique_ptr<MessageHeaderValidator> header_validator =
|
||||
- std::make_unique<MessageHeaderValidator>();
|
||||
- header_validator_ = header_validator.get();
|
||||
- dispatcher_.SetValidator(std::move(header_validator));
|
||||
-
|
||||
if (primary_interface_name) {
|
||||
- header_validator_->SetDescription(base::JoinString(
|
||||
- {primary_interface_name, "[primary] MessageHeaderValidator"}, " "));
|
||||
control_message_handler_.SetDescription(base::JoinString(
|
||||
{primary_interface_name, "[primary] PipeControlMessageHandler"}, " "));
|
||||
}
|
||||
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
index 3d3bbb16e25b1adc678e536bd977fa22fc478920..3a9f76a57e301aa89d1bdc5aa1000f815793e238 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
@@ -38,7 +38,6 @@ class SequencedTaskRunner;
|
||||
namespace mojo {
|
||||
|
||||
class AsyncFlusher;
|
||||
-class MessageHeaderValidator;
|
||||
class PendingFlush;
|
||||
|
||||
namespace internal {
|
||||
@@ -301,9 +300,6 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) MultiplexRouter
|
||||
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
||||
|
||||
- // Owned by |dispatcher_| below.
|
||||
- MessageHeaderValidator* header_validator_ = nullptr;
|
||||
-
|
||||
MessageDispatcher dispatcher_;
|
||||
Connector connector_;
|
||||
|
||||
150
patches/chromium/cherry-pick-6b2643846ae3.patch
Normal file
150
patches/chromium/cherry-pick-6b2643846ae3.patch
Normal file
@@ -0,0 +1,150 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Date: Thu, 24 Feb 2022 17:39:53 +0000
|
||||
Subject: Guard BatchingMediaLog::event_handlers_ with lock
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It seems that despite MediaLog::OnWebMediaPlayerDestroyed and
|
||||
MediaLog::AddLogRecord both grabbing a lock,
|
||||
BatchingMediaLog::AddLogRecordLocked can escape the lock handle by
|
||||
posting BatchingMediaLog::SendQueuedMediaEvents, causing a race.
|
||||
|
||||
When the addition of an event is interrupted by the deletion of a player
|
||||
due to player culling in MediaInspectorContextImpl, a UAF can occur.
|
||||
|
||||
R=dalecurtis
|
||||
|
||||
(cherry picked from commit 34526c3d0a857a22618e4d77c7f63b5ca6f8d3d2)
|
||||
|
||||
Bug: 1295786
|
||||
Change-Id: I77df94988f806e4d98924669d27860e50455299d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3451494
|
||||
Commit-Queue: Ted (Chromium) Meyer <tmathmeyer@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#970815}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3483655
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1508}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/renderer/media/batching_media_log.cc b/content/renderer/media/batching_media_log.cc
|
||||
index 8d8c5cb28b9bb0fcebcceb9e56db98fdace13c88..2d12a5eb42b930acac74a5ea2b2961e6c7e32fcf 100644
|
||||
--- a/content/renderer/media/batching_media_log.cc
|
||||
+++ b/content/renderer/media/batching_media_log.cc
|
||||
@@ -52,9 +52,9 @@ BatchingMediaLog::BatchingMediaLog(
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
std::vector<std::unique_ptr<EventHandler>> event_handlers)
|
||||
: task_runner_(std::move(task_runner)),
|
||||
- event_handlers_(std::move(event_handlers)),
|
||||
tick_clock_(base::DefaultTickClock::GetInstance()),
|
||||
last_ipc_send_time_(tick_clock_->NowTicks()),
|
||||
+ event_handlers_(std::move(event_handlers)),
|
||||
ipc_send_pending_(false),
|
||||
logged_rate_limit_warning_(false) {
|
||||
// Pre-bind the WeakPtr on the right thread since we'll receive calls from
|
||||
@@ -76,6 +76,7 @@ BatchingMediaLog::~BatchingMediaLog() {
|
||||
}
|
||||
|
||||
void BatchingMediaLog::OnWebMediaPlayerDestroyedLocked() {
|
||||
+ base::AutoLock lock(lock_);
|
||||
for (const auto& handler : event_handlers_)
|
||||
handler->OnWebMediaPlayerDestroyed();
|
||||
}
|
||||
@@ -198,32 +199,30 @@ std::string BatchingMediaLog::MediaEventToMessageString(
|
||||
|
||||
void BatchingMediaLog::SendQueuedMediaEvents() {
|
||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||
+ base::AutoLock auto_lock(lock_);
|
||||
|
||||
- std::vector<media::MediaLogRecord> events_to_send;
|
||||
- {
|
||||
- base::AutoLock auto_lock(lock_);
|
||||
- DCHECK(ipc_send_pending_);
|
||||
- ipc_send_pending_ = false;
|
||||
-
|
||||
- if (last_duration_changed_event_) {
|
||||
- queued_media_events_.push_back(*last_duration_changed_event_);
|
||||
- last_duration_changed_event_.reset();
|
||||
- }
|
||||
+ DCHECK(ipc_send_pending_);
|
||||
+ ipc_send_pending_ = false;
|
||||
|
||||
- if (last_buffering_state_event_) {
|
||||
- queued_media_events_.push_back(*last_buffering_state_event_);
|
||||
- last_buffering_state_event_.reset();
|
||||
- }
|
||||
+ if (last_duration_changed_event_) {
|
||||
+ queued_media_events_.push_back(*last_duration_changed_event_);
|
||||
+ last_duration_changed_event_.reset();
|
||||
+ }
|
||||
|
||||
- queued_media_events_.swap(events_to_send);
|
||||
- last_ipc_send_time_ = tick_clock_->NowTicks();
|
||||
+ if (last_buffering_state_event_) {
|
||||
+ queued_media_events_.push_back(*last_buffering_state_event_);
|
||||
+ last_buffering_state_event_.reset();
|
||||
}
|
||||
|
||||
- if (events_to_send.empty())
|
||||
+ last_ipc_send_time_ = tick_clock_->NowTicks();
|
||||
+
|
||||
+ if (queued_media_events_.empty())
|
||||
return;
|
||||
|
||||
for (const auto& handler : event_handlers_)
|
||||
- handler->SendQueuedMediaEvents(events_to_send);
|
||||
+ handler->SendQueuedMediaEvents(queued_media_events_);
|
||||
+
|
||||
+ queued_media_events_.clear();
|
||||
}
|
||||
|
||||
void BatchingMediaLog::SetTickClockForTesting(
|
||||
diff --git a/content/renderer/media/batching_media_log.h b/content/renderer/media/batching_media_log.h
|
||||
index 5810efdf0a75b809b94fb5abcd5f3dfbde7b019d..c59dbf2a2b980a89b41c45818476c77e9096339b 100644
|
||||
--- a/content/renderer/media/batching_media_log.h
|
||||
+++ b/content/renderer/media/batching_media_log.h
|
||||
@@ -63,9 +63,6 @@ class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
|
||||
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
- // impl for sending queued events.
|
||||
- std::vector<std::unique_ptr<EventHandler>> event_handlers_;
|
||||
-
|
||||
// |lock_| protects access to all of the following member variables. It
|
||||
// allows any render process thread to AddEvent(), while preserving their
|
||||
// sequence for throttled send on |task_runner_| and coherent retrieval by
|
||||
@@ -73,19 +70,24 @@ class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
|
||||
// guarantees provided by MediaLog, since SendQueuedMediaEvents must also
|
||||
// be synchronized with respect to AddEvent.
|
||||
mutable base::Lock lock_;
|
||||
- const base::TickClock* tick_clock_;
|
||||
- base::TimeTicks last_ipc_send_time_;
|
||||
- std::vector<media::MediaLogRecord> queued_media_events_;
|
||||
+ const base::TickClock* tick_clock_ GUARDED_BY(lock_);
|
||||
+ base::TimeTicks last_ipc_send_time_ GUARDED_BY(lock_);
|
||||
+ std::vector<media::MediaLogRecord> queued_media_events_ GUARDED_BY(lock_);
|
||||
+
|
||||
+ // impl for sending queued events.
|
||||
+ std::vector<std::unique_ptr<EventHandler>> event_handlers_ GUARDED_BY(lock_);
|
||||
|
||||
// For enforcing max 1 pending send.
|
||||
- bool ipc_send_pending_;
|
||||
+ bool ipc_send_pending_ GUARDED_BY(lock_);
|
||||
|
||||
// True if we've logged a warning message about exceeding rate limits.
|
||||
- bool logged_rate_limit_warning_;
|
||||
+ bool logged_rate_limit_warning_ GUARDED_BY(lock_);
|
||||
|
||||
// Limits the number of events we send over IPC to one.
|
||||
- absl::optional<media::MediaLogRecord> last_duration_changed_event_;
|
||||
- absl::optional<media::MediaLogRecord> last_buffering_state_event_;
|
||||
+ absl::optional<media::MediaLogRecord> last_duration_changed_event_
|
||||
+ GUARDED_BY(lock_);
|
||||
+ absl::optional<media::MediaLogRecord> last_buffering_state_event_
|
||||
+ GUARDED_BY(lock_);
|
||||
|
||||
// Holds the earliest MEDIA_ERROR_LOG_ENTRY event added to this log. This is
|
||||
// most likely to contain the most specific information available describing
|
||||
765
patches/chromium/cherry-pick-6bb320d134b1.patch
Normal file
765
patches/chromium/cherry-pick-6bb320d134b1.patch
Normal file
@@ -0,0 +1,765 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Costan <pwnall@chromium.org>
|
||||
Date: Thu, 11 Nov 2021 00:22:30 +0000
|
||||
Subject: M96: Storage Foundation: Share FileState ownership with I/O threads.
|
||||
|
||||
blink::NativeIOFile methods implementing the Storage Foundation
|
||||
JavaScript API pass raw pointers to NativeIOFile::FileState instances to
|
||||
their corresponding blink::NativeIOFile::Do*() methods, which rely on
|
||||
that CrossThreadPersistent<NativeIOFile> arguments to keep the
|
||||
underlying NativeIOFile::FileState instances alive.
|
||||
|
||||
CrossThreadPersistent can be used across threads to keep a garbage
|
||||
collected object alive, together with any non-garbage-collected objects
|
||||
that it owns. However, relying on CrossThreadPersistent existence to
|
||||
access the owned objects on a different thread is not safe.
|
||||
cppgc::subtle::CrossThreadPersistent (blink::CrossThreadPersistent is an
|
||||
alias to that) has comments explaining that the garbage collected heap
|
||||
can go away while the CrossThreadPersistent instance exists.
|
||||
|
||||
This CL fixes the problem by having the ownership of
|
||||
NativeIOFile::FileState be shared between the corresponding NativeIOFile
|
||||
instance and any threads doing I/O on the FileState.
|
||||
|
||||
(cherry picked from commit 7dc02206707362f3f92cea93f8eb2fa4af0d375f)
|
||||
|
||||
Bug: 1240593
|
||||
Change-Id: I5c9c818bcb23316fe1fd5afa57ed9c3fdb034377
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3269947
|
||||
Commit-Queue: Victor Costan <pwnall@chromium.org>
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940130}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3272672
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#945}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.cc b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
index 4d5aa4efa13930aea4886bac0fd8ba892ce8b5a5..615c1d3a20cba732a3d981bf6b2df181e56d2727 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "base/check.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/location.h"
|
||||
+#include "base/memory/scoped_refptr.h"
|
||||
#include "base/numerics/checked_math.h"
|
||||
#include "base/sequenced_task_runner.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
@@ -47,31 +48,167 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
-struct NativeIOFile::FileState {
|
||||
- explicit FileState(base::File file) : file(std::move(file)) {}
|
||||
+// State and logic for performing file I/O off the JavaScript thread.
|
||||
+//
|
||||
+// Instances are allocated on the PartitionAlloc heap. Instances cannot be
|
||||
+// garbage-collected, because garbage collected heaps get deallocated when the
|
||||
+// underlying threads are terminated, and we need a guarantee that each
|
||||
+// instance remains alive while it is used by a thread performing file I/O.
|
||||
+//
|
||||
+// Instances are initially constructed on a Blink thread that executes
|
||||
+// JavaScript, which can be Blink's main thread, or a worker thread. Afterwards,
|
||||
+// instances are (mostly*) only accessed on dedicated threads that do blocking
|
||||
+// file I/O.
|
||||
+//
|
||||
+// Mostly*: On macOS < 10.15, SetLength() synchronously accesses FileState on
|
||||
+// the JavaScript thread. This could be fixed with extra thread hopping. We're
|
||||
+// not currently planning to invest in the fix.
|
||||
+class NativeIOFile::FileState
|
||||
+ : public base::RefCountedThreadSafe<NativeIOFile::FileState> {
|
||||
+ public:
|
||||
+ explicit FileState(base::File file) : file_(std::move(file)) {
|
||||
+ DCHECK(file_.IsValid());
|
||||
+ }
|
||||
|
||||
FileState(const FileState&) = delete;
|
||||
FileState& operator=(const FileState&) = delete;
|
||||
|
||||
~FileState() = default;
|
||||
|
||||
+ // Returns true until Close() is called. Returns false afterwards.
|
||||
+ //
|
||||
+ // On macOS < 10.15, returns false between a TakeFile() call and the
|
||||
+ // corresponding SetFile() call.
|
||||
+ bool IsValid() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ return file_.IsValid();
|
||||
+ }
|
||||
+
|
||||
+ void Close() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ file_.Close();
|
||||
+ }
|
||||
+
|
||||
+ // Returns {length, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {invalid number, error} in case of failure.
|
||||
+ std::pair<int64_t, base::File::Error> GetLength() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int64_t length = file_.GetLength();
|
||||
+ base::File::Error error =
|
||||
+ (length < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+
|
||||
+ return {length, error};
|
||||
+ }
|
||||
+
|
||||
+ // Returns {expected_length, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {actual file length, error} in case of failure.
|
||||
+ std::pair<int64_t, base::File::Error> SetLength(int64_t expected_length) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK_GE(expected_length, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ bool success = file_.SetLength(expected_length);
|
||||
+ base::File::Error error =
|
||||
+ success ? base::File::FILE_OK : file_.GetLastFileError();
|
||||
+ int64_t actual_length = success ? expected_length : file_.GetLength();
|
||||
+
|
||||
+ return {actual_length, error};
|
||||
+ }
|
||||
+
|
||||
+#if defined(OS_MAC)
|
||||
+ // Used to implement browser-side SetLength() on macOS < 10.15.
|
||||
+ base::File TakeFile() {
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ return std::move(file_);
|
||||
+ }
|
||||
+
|
||||
+ // Used to implement browser-side SetLength() on macOS < 10.15.
|
||||
+ void SetFile(base::File file) {
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ DCHECK(!file_.IsValid()) << __func__ << " called on valid file";
|
||||
+
|
||||
+ file_ = std::move(file);
|
||||
+ }
|
||||
+#endif // defined(OS_MAC)
|
||||
+
|
||||
+ // Returns {read byte count, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {invalid number, error} in case of failure.
|
||||
+ std::pair<int, base::File::Error> Read(NativeIODataBuffer* buffer,
|
||||
+ int64_t file_offset,
|
||||
+ int read_size) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK(buffer);
|
||||
+ DCHECK_GE(file_offset, 0);
|
||||
+ DCHECK_GE(read_size, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int read_bytes = file_.Read(file_offset, buffer->Data(), read_size);
|
||||
+ base::File::Error error =
|
||||
+ (read_bytes < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+
|
||||
+ return {read_bytes, error};
|
||||
+ }
|
||||
+
|
||||
+ // Returns {0, write_size, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {actual file length, written bytes, base::File::OK} in case of a
|
||||
+ // short write.
|
||||
+ // Returns {actual file length, invalid number, error} in case of failure.
|
||||
+ std::tuple<int64_t, int, base::File::Error> Write(NativeIODataBuffer* buffer,
|
||||
+ int64_t file_offset,
|
||||
+ int write_size) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK(buffer);
|
||||
+ DCHECK_GE(file_offset, 0);
|
||||
+ DCHECK_GE(write_size, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int written_bytes = file_.Write(file_offset, buffer->Data(), write_size);
|
||||
+ base::File::Error error =
|
||||
+ (written_bytes < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+ int64_t actual_file_length_on_failure = 0;
|
||||
+ if (written_bytes < write_size || error != base::File::FILE_OK) {
|
||||
+ actual_file_length_on_failure = file_.GetLength();
|
||||
+ if (actual_file_length_on_failure < 0 && error != base::File::FILE_OK)
|
||||
+ error = file_.GetLastFileError();
|
||||
+ }
|
||||
+
|
||||
+ return {actual_file_length_on_failure, written_bytes, error};
|
||||
+ }
|
||||
+
|
||||
+ base::File::Error Flush() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ bool success = file_.Flush();
|
||||
+ return success ? base::File::FILE_OK : file_.GetLastFileError();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
// Lock coordinating cross-thread access to the state.
|
||||
- WTF::Mutex mutex;
|
||||
+ WTF::Mutex mutex_;
|
||||
+
|
||||
// The file on disk backing this NativeIOFile.
|
||||
- //
|
||||
- // The mutex is there to protect us against using the file after it was
|
||||
- // closed, and against OS-specific behavior around concurrent file access. It
|
||||
- // should never cause the main (JS) thread to block. This is because the mutex
|
||||
- // is only taken on the main thread in CloseBackingFile(), which is called
|
||||
- // when the NativeIOFile is destroyed (which implies there's no pending I/O
|
||||
- // operation, because all I/O operations hold onto a Persistent<NativeIOFile>)
|
||||
- // and when the mojo pipe is closed, which currently only happens when the JS
|
||||
- // context is being torn down.
|
||||
- //
|
||||
- // TODO(rstz): Is it possible and worthwhile to remove the mutex and rely
|
||||
- // exclusively on |NativeIOFile::io_pending_|, or remove
|
||||
- // |NativeIOFile::io_pending_| in favor of the mutex (might be harder)?
|
||||
- base::File file GUARDED_BY(mutex);
|
||||
+ base::File file_ GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
NativeIOFile::NativeIOFile(
|
||||
@@ -81,7 +218,7 @@ NativeIOFile::NativeIOFile(
|
||||
NativeIOCapacityTracker* capacity_tracker,
|
||||
ExecutionContext* execution_context)
|
||||
: file_length_(backing_file_length),
|
||||
- file_state_(std::make_unique<FileState>(std::move(backing_file))),
|
||||
+ file_state_(base::MakeRefCounted<FileState>(std::move(backing_file))),
|
||||
// TODO(pwnall): Get a dedicated queue when the specification matures.
|
||||
resolver_task_runner_(
|
||||
execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)),
|
||||
@@ -94,7 +231,7 @@ NativeIOFile::NativeIOFile(
|
||||
}
|
||||
|
||||
NativeIOFile::~NativeIOFile() {
|
||||
- // Needed to avoid having the base::File destructor close the file descriptor
|
||||
+ // Needed to avoid having the FileState destructor close the file descriptor
|
||||
// synchronously on the main thread.
|
||||
CloseBackingFile();
|
||||
}
|
||||
@@ -114,6 +251,9 @@ ScriptPromise NativeIOFile::close(ScriptState* script_state) {
|
||||
queued_close_resolver_ = resolver;
|
||||
|
||||
if (!io_pending_) {
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
+
|
||||
// Pretend that a close() promise was queued behind an I/O operation, and
|
||||
// the operation just finished. This is less logic than handling the
|
||||
// non-queued case separately.
|
||||
@@ -138,18 +278,15 @@ ScriptPromise NativeIOFile::getLength(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
- io_pending_ = true;
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoGetLength, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -175,6 +312,9 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
+
|
||||
int64_t expected_length = base::as_signed(new_length);
|
||||
|
||||
DCHECK_GE(expected_length, 0);
|
||||
@@ -201,8 +341,8 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
}
|
||||
file_length_ = expected_length;
|
||||
}
|
||||
- io_pending_ = true;
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
|
||||
#if defined(OS_MAC)
|
||||
@@ -217,26 +357,19 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
// To preserve this invariant, we pass this file's handle to the browser
|
||||
// process during the SetLength() mojo call, and the browser passes it back
|
||||
// when the call completes.
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state_->mutex);
|
||||
- backend_file_->SetLength(
|
||||
- expected_length, std::move(file_state_->file),
|
||||
- WTF::Bind(&NativeIOFile::DidSetLengthIpc, WrapPersistent(this),
|
||||
- WrapPersistent(resolver)));
|
||||
- }
|
||||
+ base::File file = file_state_->TakeFile();
|
||||
+ backend_file_->SetLength(
|
||||
+ expected_length, std::move(file),
|
||||
+ WTF::Bind(&NativeIOFile::DidSetLengthIpc, WrapPersistent(this),
|
||||
+ WrapPersistent(resolver)));
|
||||
return resolver->Promise();
|
||||
}
|
||||
#endif // defined(OS_MAC)
|
||||
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoSetLength, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, expected_length));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -258,6 +391,8 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
// TODO(pwnall): This assignment should move right before the
|
||||
// worker_pool::PostTask() call.
|
||||
@@ -281,16 +416,10 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // The first CrossThreadUnretained() is safe here because the
|
||||
- // NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
- // also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
- // FileState instance is guaranteed to remain alive during the task's
|
||||
- // execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoRead, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, std::move(result_buffer_data),
|
||||
file_offset, read_size));
|
||||
return resolver->Promise();
|
||||
@@ -313,6 +442,8 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
int write_size = NativeIOOperationSize(*buffer);
|
||||
int64_t write_end_offset;
|
||||
@@ -346,6 +477,14 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
file_length_ = write_end_offset;
|
||||
}
|
||||
|
||||
+ // TODO(pwnall): This assignment should move right before the
|
||||
+ // worker_pool::PostTask() call.
|
||||
+ //
|
||||
+ // `io_pending_` should only be set to true when we know for sure we'll post a
|
||||
+ // task that eventually results in getting `io_pending_` set back to false.
|
||||
+ // Having `io_pending_` set to true in an early return case (rejecting with an
|
||||
+ // exception) leaves the NativeIOFile "stuck" in a state where all future I/O
|
||||
+ // method calls will reject.
|
||||
io_pending_ = true;
|
||||
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
@@ -358,16 +497,10 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // The first CrossThreadUnretained() is safe here because the
|
||||
- // NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
- // also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
- // FileState instance is guaranteed to remain alive during the task's
|
||||
- // execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoWrite, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, std::move(result_buffer_data),
|
||||
file_offset, write_size));
|
||||
return resolver->Promise();
|
||||
@@ -391,18 +524,15 @@ ScriptPromise NativeIOFile::flush(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
- io_pending_ = true;
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoFlush, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -430,28 +560,29 @@ void NativeIOFile::DispatchQueuedClose() {
|
||||
ScriptPromiseResolver* resolver = queued_close_resolver_;
|
||||
queued_close_resolver_ = nullptr;
|
||||
|
||||
+ scoped_refptr<FileState> file_state = std::move(file_state_);
|
||||
+ DCHECK(!file_state_);
|
||||
+
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoClose, WrapCrossThreadPersistent(this),
|
||||
WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
- resolver_task_runner_));
|
||||
+ std::move(file_state), resolver_task_runner_));
|
||||
}
|
||||
|
||||
// static
|
||||
void NativeIOFile::DoClose(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- file_state->file.Close();
|
||||
- }
|
||||
+ file_state->Close();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -482,19 +613,17 @@ void NativeIOFile::DidClose(
|
||||
void NativeIOFile::DoGetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+
|
||||
+ int64_t length;
|
||||
base::File::Error get_length_error;
|
||||
- int64_t length = -1;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- length = file_state->file.GetLength();
|
||||
- get_length_error = (length < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- }
|
||||
+ std::tie(length, get_length_error) = file_state->GetLength();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -541,22 +670,20 @@ void NativeIOFile::DidGetLength(
|
||||
void NativeIOFile::DoSetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
int64_t expected_length) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK_GE(expected_length, 0);
|
||||
|
||||
- base::File::Error set_length_error;
|
||||
int64_t actual_length;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- bool success = file_state->file.SetLength(expected_length);
|
||||
- set_length_error =
|
||||
- success ? base::File::FILE_OK : file_state->file.GetLastFileError();
|
||||
- actual_length = success ? expected_length : file_state->file.GetLength();
|
||||
- }
|
||||
+ base::File::Error set_length_error;
|
||||
+ std::tie(actual_length, set_length_error) =
|
||||
+ file_state->SetLength(expected_length);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -619,10 +746,7 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
int64_t actual_length,
|
||||
mojom::blink::NativeIOErrorPtr set_length_error) {
|
||||
DCHECK(backing_file.IsValid()) << "browser returned closed file";
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state_->mutex);
|
||||
- file_state_->file = std::move(backing_file);
|
||||
- }
|
||||
+ file_state_->SetFile(std::move(backing_file));
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
|
||||
DCHECK(io_pending_) << "I/O operation performed without io_pending_ set";
|
||||
@@ -673,13 +797,15 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
void NativeIOFile::DoRead(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
-
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
DCHECK(resolver_task_runner);
|
||||
DCHECK(result_buffer_data);
|
||||
DCHECK(result_buffer_data->IsValid());
|
||||
@@ -690,15 +816,8 @@ void NativeIOFile::DoRead(
|
||||
|
||||
int read_bytes;
|
||||
base::File::Error read_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- read_bytes = file_state->file.Read(file_offset, result_buffer_data->Data(),
|
||||
- read_size);
|
||||
- read_error = (read_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- }
|
||||
+ std::tie(read_bytes, read_error) =
|
||||
+ file_state->Read(result_buffer_data.get(), file_offset, read_size);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -743,12 +862,15 @@ void NativeIOFile::DidRead(
|
||||
void NativeIOFile::DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
DCHECK(resolver_task_runner);
|
||||
DCHECK(result_buffer_data);
|
||||
DCHECK(result_buffer_data->IsValid());
|
||||
@@ -760,22 +882,8 @@ void NativeIOFile::DoWrite(
|
||||
int written_bytes;
|
||||
int64_t actual_file_length_on_failure = 0;
|
||||
base::File::Error write_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- written_bytes = file_state->file.Write(
|
||||
- file_offset, result_buffer_data->Data(), write_size);
|
||||
- write_error = (written_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- if (written_bytes < write_size || write_error != base::File::FILE_OK) {
|
||||
- actual_file_length_on_failure = file_state->file.GetLength();
|
||||
- if (actual_file_length_on_failure < 0 &&
|
||||
- write_error != base::File::FILE_OK) {
|
||||
- write_error = file_state->file.GetLastFileError();
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ std::tie(actual_file_length_on_failure, written_bytes, write_error) =
|
||||
+ file_state->Write(result_buffer_data.get(), file_offset, write_size);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -846,18 +954,14 @@ void NativeIOFile::DidWrite(
|
||||
void NativeIOFile::DoFlush(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
- base::File::Error flush_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- bool success = file_state->file.Flush();
|
||||
- flush_error =
|
||||
- success ? base::File::FILE_OK : file_state->file.GetLastFileError();
|
||||
- }
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+
|
||||
+ base::File::Error flush_error = file_state->Flush();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -887,20 +991,23 @@ void NativeIOFile::DidFlush(
|
||||
|
||||
void NativeIOFile::CloseBackingFile() {
|
||||
closed_ = true;
|
||||
- file_state_->mutex.lock();
|
||||
- base::File backing_file = std::move(file_state_->file);
|
||||
- file_state_->mutex.unlock();
|
||||
|
||||
- if (!backing_file.IsValid()) {
|
||||
+ if (!file_state_) {
|
||||
// Avoid posting a cross-thread task if the file is already closed. This is
|
||||
// the expected path.
|
||||
return;
|
||||
}
|
||||
|
||||
- worker_pool::PostTask(
|
||||
- FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce([](base::File file) { file.Close(); },
|
||||
- std::move(backing_file)));
|
||||
+ scoped_refptr<FileState> file_state = std::move(file_state_);
|
||||
+ DCHECK(!file_state_);
|
||||
+
|
||||
+ worker_pool::PostTask(FROM_HERE, {base::MayBlock()},
|
||||
+ CrossThreadBindOnce(
|
||||
+ [](scoped_refptr<FileState> file_state) {
|
||||
+ DCHECK(file_state);
|
||||
+ file_state->Close();
|
||||
+ },
|
||||
+ std::move(file_state)));
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.h b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
index 8ae49ebc2d36d547d152d4e56192e30f8cacd641..95d2da4ac3e1859a0abc21ea15d269758eed1681 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
@@ -67,12 +67,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
void Trace(Visitor* visitor) const override;
|
||||
|
||||
private:
|
||||
- // Data accessed on the threads that do file I/O.
|
||||
- //
|
||||
- // Instances are allocated on the PartitionAlloc heap. Instances are initially
|
||||
- // constructed on Blink's main thread, or on a worker thread. Afterwards,
|
||||
- // instances are only accessed on dedicated threads that do blocking file I/O.
|
||||
- struct FileState;
|
||||
+ class FileState;
|
||||
|
||||
// Called when the mojo backend disconnects.
|
||||
void OnBackendDisconnect();
|
||||
@@ -84,7 +79,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoClose(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file I/O part of close(), on the main thread.
|
||||
void DidClose(CrossThreadPersistent<ScriptPromiseResolver> resolver);
|
||||
@@ -93,7 +88,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoGetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file I/O part of getLength(), on the main thread.
|
||||
void DidGetLength(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
@@ -104,7 +99,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoSetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
int64_t expected_length);
|
||||
// Performs the post file I/O part of setLength(), on the main thread.
|
||||
@@ -128,7 +123,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// Performs the file I/O part of read(), off the main thread.
|
||||
static void DoRead(CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
@@ -143,7 +138,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
@@ -163,7 +158,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoFlush(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file-I/O part of flush(), on the main thread.
|
||||
void DidFlush(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
@@ -210,8 +205,13 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// TODO(rstz): Consider moving this variable into `file_state_`
|
||||
int64_t file_length_ = 0;
|
||||
|
||||
- // See NativeIOFile::FileState, declared above.
|
||||
- const std::unique_ptr<FileState> file_state_;
|
||||
+ // Points to a NativeIOFile::FileState while the underlying file is open.
|
||||
+ //
|
||||
+ // When the underlying file is closed, this pointer is nulled out, and the
|
||||
+ // FileState instance is passed to a different thread, where the closing
|
||||
+ // happens. This avoids having any I/O performed by the base::File::Close()
|
||||
+ // jank the JavaScript thread that owns this NativeIOFile instance.
|
||||
+ scoped_refptr<FileState> file_state_;
|
||||
|
||||
// Schedules resolving Promises with file I/O results.
|
||||
const scoped_refptr<base::SequencedTaskRunner> resolver_task_runner_;
|
||||
126
patches/chromium/cherry-pick-8af66de55aad.patch
Normal file
126
patches/chromium/cherry-pick-8af66de55aad.patch
Normal file
@@ -0,0 +1,126 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Date: Tue, 24 Aug 2021 15:01:17 +0000
|
||||
Subject: Limit length of 'csp' attribute
|
||||
|
||||
Most servers limit the length of request headers anywhere. 4Kb seems
|
||||
like a reasonable limit, which some popular http servers have by
|
||||
default, and which we already enforce for Referer
|
||||
(https://crrev.com/c/1595872).
|
||||
|
||||
I would have liked the constant 4096 to be shared between //content
|
||||
and blink. This would have required putting it somewhere like in
|
||||
//services/network or in //third_party/blink/common, creating a new
|
||||
file for it. I thought it would be easier to avoid that for this
|
||||
change.
|
||||
|
||||
It would be safer to not load the iframe document, or to impose some
|
||||
very strict CSP like "default-src 'none'", instead than just ignoring
|
||||
the 'csp' attribute if that's too long. However, ignoring is what we
|
||||
already do if the attribute contains illegal characters or does not
|
||||
match the CSP grammary or is not subsumed by the parent iframe's csp
|
||||
attribute. For this change, I believe it's better to stay consistent
|
||||
with that, and later change the CSPEE code to block loading in all
|
||||
those cases.
|
||||
|
||||
Bug: 1233067
|
||||
Change-Id: Ie9cd3db82287a76892cca76a0bf0d4a1613a3055
|
||||
Fixed: 1233067
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3057048
|
||||
Commit-Queue: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Reviewed-by: Mike West <mkwst@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#914730}
|
||||
|
||||
diff --git a/content/browser/content_security_policy_browsertest.cc b/content/browser/content_security_policy_browsertest.cc
|
||||
index 1d0631955600449d142697ce68c474f1957eae75..f95fe16e3c3f8c8b6c603f7cd19dcdb915deacfa 100644
|
||||
--- a/content/browser/content_security_policy_browsertest.cc
|
||||
+++ b/content/browser/content_security_policy_browsertest.cc
|
||||
@@ -225,4 +225,21 @@ IN_PROC_BROWSER_TEST_F(ContentSecurityPolicyBrowserTest, FileURLs) {
|
||||
}
|
||||
}
|
||||
|
||||
+// Test that a 'csp' attribute longer than 4096 bytes is ignored.
|
||||
+IN_PROC_BROWSER_TEST_F(ContentSecurityPolicyBrowserTest, CSPAttributeTooLong) {
|
||||
+ std::string long_csp_attribute = "script-src 'none' ";
|
||||
+ long_csp_attribute.resize(4097, 'a');
|
||||
+ std::string page = "data:text/html,<body><iframe csp=\"" +
|
||||
+ long_csp_attribute + "\"></iframe></body>";
|
||||
+
|
||||
+ GURL url(page);
|
||||
+ WebContentsConsoleObserver console_observer(web_contents());
|
||||
+ console_observer.SetPattern("'csp' attribute too long*");
|
||||
+ EXPECT_TRUE(NavigateToURL(shell(), url));
|
||||
+ console_observer.Wait();
|
||||
+
|
||||
+ EXPECT_EQ(current_frame_host()->child_count(), 1u);
|
||||
+ EXPECT_FALSE(current_frame_host()->child_at(0)->csp_attribute());
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 605fa35ca1edeab84287c5d37327010a40d64f67..10f34740cad12975914107a9c07bdbe9279120aa 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -876,9 +876,11 @@ enum class VerifyDidCommitParamsDifference {
|
||||
};
|
||||
|
||||
bool ValidateCSPAttribute(const std::string& value) {
|
||||
+ static const size_t kMaxLengthCSPAttribute = 4096;
|
||||
if (!base::IsStringASCII(value))
|
||||
return false;
|
||||
- if (value.find('\n') != std::string::npos ||
|
||||
+ if (value.length() > kMaxLengthCSPAttribute ||
|
||||
+ value.find('\n') != std::string::npos ||
|
||||
value.find('\r') != std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
|
||||
index c60e3281ea96ef39e16034c88abf4c6c2a9bd2eb..f9434ae7a2c1066dd2c97f552ee572ca4d808f24 100644
|
||||
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
|
||||
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
|
||||
@@ -208,16 +208,27 @@ void HTMLIFrameElement::ParseAttribute(
|
||||
UpdateContainerPolicy();
|
||||
}
|
||||
} else if (name == html_names::kCspAttr) {
|
||||
+ static const size_t kMaxLengthCSPAttribute = 4096;
|
||||
if (value && (value.Contains('\n') || value.Contains('\r') ||
|
||||
!MatchesTheSerializedCSPGrammar(value.GetString()))) {
|
||||
+ // TODO(antoniosartori): It would be safer to block loading iframes with
|
||||
+ // invalid 'csp' attribute.
|
||||
required_csp_ = g_null_atom;
|
||||
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
|
||||
mojom::blink::ConsoleMessageSource::kOther,
|
||||
mojom::blink::ConsoleMessageLevel::kError,
|
||||
"'csp' attribute is invalid: " + value));
|
||||
- return;
|
||||
- }
|
||||
- if (required_csp_ != value) {
|
||||
+ } else if (value && value.length() > kMaxLengthCSPAttribute) {
|
||||
+ // TODO(antoniosartori): It would be safer to block loading iframes with
|
||||
+ // invalid 'csp' attribute.
|
||||
+ required_csp_ = g_null_atom;
|
||||
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
|
||||
+ mojom::blink::ConsoleMessageSource::kOther,
|
||||
+ mojom::blink::ConsoleMessageLevel::kError,
|
||||
+ String::Format("'csp' attribute too long. The max length for the "
|
||||
+ "'csp' attribute is %zu bytes.",
|
||||
+ kMaxLengthCSPAttribute)));
|
||||
+ } else if (required_csp_ != value) {
|
||||
required_csp_ = value;
|
||||
DidChangeAttributes();
|
||||
UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute);
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
|
||||
index a9ad787408786e594ccb554d2bd9186a9e8e7c1e..e0a31db8e28fb1a9d2884c7677597072d4badba2 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
|
||||
@@ -59,6 +59,9 @@
|
||||
{ "name": "Wrong and dangerous value of `csp` should not trigger sending Sec-Required-CSP Header - report-to present",
|
||||
"csp": "script-src 'unsafe-inline'; report-to resources/dummy-report.php",
|
||||
"expected": null },
|
||||
+ { "name": "Sec-Required-CSP is not sent if `csp` attribute is longer than 4096 bytes",
|
||||
+ "csp": "style-src " + Array.from(Array(2044).keys()).map(i => 'a').join(' '),
|
||||
+ "expected": null },
|
||||
];
|
||||
|
||||
tests.forEach(test => {
|
||||
48
patches/chromium/cherry-pick-91dd4f79ab5b.patch
Normal file
48
patches/chromium/cherry-pick-91dd4f79ab5b.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Mon, 25 Oct 2021 18:22:50 +0000
|
||||
Subject: Validate INTRODUCE source node
|
||||
|
||||
INTRODUCE NodeChannel messages should only be acknowledged when coming
|
||||
from the broker process.
|
||||
|
||||
(cherry picked from commit 6e74f7b5cb2f48b17403f0431f3e4f3a2e716265)
|
||||
|
||||
Fixed: 1252858
|
||||
Change-Id: I2dff6d5cab102ce744ad2ad66a9f24b4202cbea8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3193798
|
||||
Reviewed-by: Alex Gough <ajgo@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#926430}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3229034
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Oksana Zhuravlova <oksamyt@chromium.org>
|
||||
Commit-Queue: Oksana Zhuravlova <oksamyt@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4638@{#964}
|
||||
Cr-Branched-From: 159257cab5585bc8421abf347984bb32fdfe9eb9-refs/heads/main@{#920003}
|
||||
|
||||
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
|
||||
index 9f2e79b9e04e9df8aff6c924e6a480ac81857701..21edab39368e69ee6665e490b2c4de13f424edbd 100644
|
||||
--- a/mojo/core/node_controller.cc
|
||||
+++ b/mojo/core/node_controller.cc
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "mojo/core/broker.h"
|
||||
#include "mojo/core/broker_host.h"
|
||||
#include "mojo/core/configuration.h"
|
||||
+#include "mojo/core/ports/name.h"
|
||||
#include "mojo/core/request_context.h"
|
||||
#include "mojo/core/user_message_impl.h"
|
||||
#include "mojo/public/cpp/platform/named_platform_channel.h"
|
||||
@@ -1127,6 +1128,12 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node,
|
||||
const uint64_t remote_capabilities) {
|
||||
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
+ if (broker_name_ == ports::kInvalidNodeName || from_node != broker_name_) {
|
||||
+ DVLOG(1) << "Ignoring introduction from non-broker process.";
|
||||
+ DropPeer(from_node, nullptr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (!channel_handle.is_valid()) {
|
||||
node_->LostConnectionToNode(name);
|
||||
|
||||
151
patches/chromium/cherry-pick-9db9911e1242.patch
Normal file
151
patches/chromium/cherry-pick-9db9911e1242.patch
Normal file
@@ -0,0 +1,151 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Stephen Roettger <sroettger@google.com>
|
||||
Date: Fri, 7 Jan 2022 09:36:31 +0000
|
||||
Subject: Keep a set of previously dropped peers
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Test that a given node name hasn't been seen before.
|
||||
A side effect of this fix is that re-invitation will not work anymore.
|
||||
|
||||
BUG=chromium:1274113
|
||||
|
||||
Change-Id: Ibdc50291efa1f6298614b163b544ad980615a981
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3341553
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Stephen Röttger <sroettger@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#956441}
|
||||
|
||||
diff --git a/mojo/core/invitation_unittest.cc b/mojo/core/invitation_unittest.cc
|
||||
index 2c8eeef9feefc6be689f1ca2052af316b4b7db68..0687a58ee2b294580d1165e872ec5855e5de2b53 100644
|
||||
--- a/mojo/core/invitation_unittest.cc
|
||||
+++ b/mojo/core/invitation_unittest.cc
|
||||
@@ -693,7 +693,8 @@ DEFINE_TEST_CLIENT(ProcessErrorsClient) {
|
||||
EXPECT_EQ(kDisconnectMessage, ReadMessage(pipe));
|
||||
}
|
||||
|
||||
-TEST_F(InvitationTest, Reinvitation) {
|
||||
+// Temporary removed support for reinvitation for non-isolated connections.
|
||||
+TEST_F(InvitationTest, DISABLED_Reinvitation) {
|
||||
// The gist of this test is that a process should be able to accept an
|
||||
// invitation, lose its connection to the process network, and then accept a
|
||||
// new invitation to re-establish communication.
|
||||
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
|
||||
index 21edab39368e69ee6665e490b2c4de13f424edbd..79b933ebbe9eb1cb9eb11512f8480c682811745c 100644
|
||||
--- a/mojo/core/node_controller.cc
|
||||
+++ b/mojo/core/node_controller.cc
|
||||
@@ -543,7 +543,8 @@ scoped_refptr<NodeChannel> NodeController::GetBrokerChannel() {
|
||||
|
||||
void NodeController::AddPeer(const ports::NodeName& name,
|
||||
scoped_refptr<NodeChannel> channel,
|
||||
- bool start_channel) {
|
||||
+ bool start_channel,
|
||||
+ bool allow_name_reuse) {
|
||||
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
DCHECK(name != ports::kInvalidNodeName);
|
||||
@@ -562,6 +563,11 @@ void NodeController::AddPeer(const ports::NodeName& name,
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (dropped_peers_.Contains(name) && !allow_name_reuse) {
|
||||
+ LOG(ERROR) << "Trying to re-add dropped peer " << name;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
auto result = peers_.insert(std::make_pair(name, channel));
|
||||
DCHECK(result.second);
|
||||
|
||||
@@ -602,6 +608,7 @@ void NodeController::DropPeer(const ports::NodeName& node_name,
|
||||
if (it != peers_.end()) {
|
||||
ports::NodeName peer = it->first;
|
||||
peers_.erase(it);
|
||||
+ dropped_peers_.Insert(peer);
|
||||
DVLOG(1) << "Dropped peer " << peer;
|
||||
}
|
||||
|
||||
@@ -1265,7 +1272,8 @@ void NodeController::OnAcceptPeer(const ports::NodeName& from_node,
|
||||
// Note that we explicitly drop any prior connection to the same peer so
|
||||
// that new isolated connections can replace old ones.
|
||||
DropPeer(peer_name, nullptr);
|
||||
- AddPeer(peer_name, channel, false /* start_channel */);
|
||||
+ AddPeer(peer_name, channel, false /* start_channel */,
|
||||
+ true /* allow_name_reuse */);
|
||||
DVLOG(1) << "Node " << name_ << " accepted peer " << peer_name;
|
||||
}
|
||||
|
||||
@@ -1381,5 +1389,24 @@ NodeController::IsolatedConnection&
|
||||
NodeController::IsolatedConnection::operator=(IsolatedConnection&& other) =
|
||||
default;
|
||||
|
||||
+BoundedPeerSet::BoundedPeerSet() = default;
|
||||
+BoundedPeerSet::~BoundedPeerSet() = default;
|
||||
+
|
||||
+void BoundedPeerSet::Insert(const ports::NodeName& name) {
|
||||
+ if (new_set_.size() == kHalfSize) {
|
||||
+ old_set_.clear();
|
||||
+ std::swap(old_set_, new_set_);
|
||||
+ }
|
||||
+ new_set_.insert(name);
|
||||
+}
|
||||
+
|
||||
+bool BoundedPeerSet::Contains(const ports::NodeName& name) {
|
||||
+ if (old_set_.find(name) != old_set_.end())
|
||||
+ return true;
|
||||
+ if (new_set_.find(name) != new_set_.end())
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
} // namespace core
|
||||
} // namespace mojo
|
||||
diff --git a/mojo/core/node_controller.h b/mojo/core/node_controller.h
|
||||
index 040eeab79f72efcdb2823cf62e7dbaefa8b9233f..571e578da4950135456bb97c8ea7a30ceabca7cc 100644
|
||||
--- a/mojo/core/node_controller.h
|
||||
+++ b/mojo/core/node_controller.h
|
||||
@@ -38,6 +38,26 @@ namespace core {
|
||||
class Broker;
|
||||
class Core;
|
||||
|
||||
+// A set of NodeNames that is bounded by a maximum size.
|
||||
+// If the max size is reached, it will delete the older half of stored names.
|
||||
+class BoundedPeerSet {
|
||||
+ public:
|
||||
+ BoundedPeerSet();
|
||||
+ BoundedPeerSet(const BoundedPeerSet&) = delete;
|
||||
+ BoundedPeerSet& operator=(const BoundedPeerSet&) = delete;
|
||||
+
|
||||
+ ~BoundedPeerSet();
|
||||
+
|
||||
+ void Insert(const ports::NodeName& name);
|
||||
+ bool Contains(const ports::NodeName& name);
|
||||
+
|
||||
+ private:
|
||||
+ static constexpr int kHalfSize = 50000;
|
||||
+
|
||||
+ std::unordered_set<ports::NodeName> old_set_;
|
||||
+ std::unordered_set<ports::NodeName> new_set_;
|
||||
+};
|
||||
+
|
||||
// The owner of ports::Node which facilitates core EDK implementation. All
|
||||
// public interface methods are safe to call from any thread.
|
||||
class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
@@ -180,7 +200,8 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
|
||||
void AddPeer(const ports::NodeName& name,
|
||||
scoped_refptr<NodeChannel> channel,
|
||||
- bool start_channel);
|
||||
+ bool start_channel,
|
||||
+ bool allow_name_reuse = false);
|
||||
void DropPeer(const ports::NodeName& name, NodeChannel* channel);
|
||||
void SendPeerEvent(const ports::NodeName& name, ports::ScopedEvent event);
|
||||
void DropAllPeers();
|
||||
@@ -265,6 +286,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
|
||||
// Channels to known peers, including inviter and invitees, if any.
|
||||
NodeMap peers_;
|
||||
+ BoundedPeerSet dropped_peers_;
|
||||
|
||||
// Outgoing message queues for peers we've heard of but can't yet talk to.
|
||||
std::unordered_map<ports::NodeName, OutgoingMessageQueue>
|
||||
649
patches/chromium/cherry-pick-a5f54612590d.patch
Normal file
649
patches/chromium/cherry-pick-a5f54612590d.patch
Normal file
@@ -0,0 +1,649 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Costan <pwnall@chromium.org>
|
||||
Date: Wed, 10 Nov 2021 21:14:03 +0000
|
||||
Subject: M96: Storage Foundation: Avoid cross-thread access of
|
||||
DOMArrayBufferView.
|
||||
|
||||
blink::NativeIOFile::{read, write}() (in the Storage Foundation API
|
||||
implementation) pass DOMArrayBufferView instances to
|
||||
blink::NativeIOFile::Do{Read,Write}() via CrossThreadPersistent.
|
||||
blink::NativeIOFile::Do{Read,Write}() accesses these instances.
|
||||
|
||||
CrossThreadPersistent can be used across threads to keep a garbage
|
||||
collected object alive. However, accessing the object on a different
|
||||
thread is not safe. cppgc::subtle::CrossThreadPersistent
|
||||
(blink::CrossThreadPersistent is an alias to that) has comments
|
||||
explaining that the garbage collected heap can go away while the
|
||||
CrossThreadPersistent instance exists.
|
||||
|
||||
This CL bypasses the problem by having Do{Read,Write}() receive a
|
||||
ArrayBufferContents that has the DOMArrayBufferView's backing buffer.
|
||||
ArrayBufferContents is not garbage-collected, so it can be safely used
|
||||
across threads.
|
||||
|
||||
This CL introduces a NativeIODataBuffer class that contains the logic
|
||||
and state for tearing a DOMArrayBufferView apart into its components
|
||||
(backing buffer, view type, view offset, view length) and putting it
|
||||
back together into a new DOMArrayBufferView, after it doesn't need to be
|
||||
accessed cross-thread anymore.
|
||||
|
||||
(cherry picked from commit 5200793c2aea5979cc79f3350a4e3d6c0795d6f2)
|
||||
|
||||
Bug: 1268274
|
||||
Change-Id: I51588f5bfe963de96ce426e0f480e8c5b4902688
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3269366
|
||||
Commit-Queue: Victor Costan <pwnall@chromium.org>
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Reviewed-by: Joshua Bell <jsbell@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940070}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3272377
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#941}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.cc b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
index b25cf909f05be73f690fabee7942ee1fa83c1e04..4d5aa4efa13930aea4886bac0fd8ba892ce8b5a5 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_error.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
|
||||
@@ -256,39 +258,41 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+
|
||||
+ // TODO(pwnall): This assignment should move right before the
|
||||
+ // worker_pool::PostTask() call.
|
||||
+ //
|
||||
+ // `io_pending_` should only be set to true when we know for sure we'll post a
|
||||
+ // task that eventually results in getting `io_pending_` set back to false.
|
||||
+ // Having `io_pending_` set to true in an early return case (rejecting with an
|
||||
+ // exception) leaves the NativeIOFile "stuck" in a state where all future I/O
|
||||
+ // method calls will reject.
|
||||
io_pending_ = true;
|
||||
|
||||
int read_size = NativeIOOperationSize(*buffer);
|
||||
|
||||
- DOMArrayBufferView* result_buffer =
|
||||
- TransferToNewArrayBufferView(script_state->GetIsolate(), buffer);
|
||||
- if (!result_buffer) {
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
+ NativeIODataBuffer::Create(script_state, buffer);
|
||||
+ if (!result_buffer_data) {
|
||||
exception_state.ThrowTypeError("Could not transfer buffer");
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
- char* result_buffer_data = static_cast<char*>(result_buffer->BaseAddress());
|
||||
-
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
// The first CrossThreadUnretained() is safe here because the
|
||||
// NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
// also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
// FileState instance is guaranteed to remain alive during the task's
|
||||
// execution.
|
||||
- //
|
||||
- // The second CrossThreadUnretained() is safe here because result_buffer_data
|
||||
- // is backed by a DOMArrayBufferView that is also passed to the task via
|
||||
- // WrapCrossThreadPersistent. Therefore, the buffer is guaranteed to remain
|
||||
- // alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce(
|
||||
- &DoRead, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- WrapCrossThreadPersistent(result_buffer),
|
||||
- CrossThreadUnretained(file_state_.get()), resolver_task_runner_,
|
||||
- CrossThreadUnretained(result_buffer_data), file_offset, read_size));
|
||||
+ CrossThreadBindOnce(&DoRead, WrapCrossThreadPersistent(this),
|
||||
+ WrapCrossThreadPersistent(resolver),
|
||||
+ CrossThreadUnretained(file_state_.get()),
|
||||
+ resolver_task_runner_, std::move(result_buffer_data),
|
||||
+ file_offset, read_size));
|
||||
return resolver->Promise();
|
||||
}
|
||||
|
||||
@@ -344,35 +348,28 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
|
||||
io_pending_ = true;
|
||||
|
||||
- DOMArrayBufferView* result_buffer =
|
||||
- TransferToNewArrayBufferView(script_state->GetIsolate(), buffer);
|
||||
- if (!result_buffer) {
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
+ NativeIODataBuffer::Create(script_state, buffer);
|
||||
+ if (!result_buffer_data) {
|
||||
exception_state.ThrowTypeError("Could not transfer buffer");
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
- char* result_buffer_data = static_cast<char*>(result_buffer->BaseAddress());
|
||||
-
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
// The first CrossThreadUnretained() is safe here because the
|
||||
// NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
// also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
// FileState instance is guaranteed to remain alive during the task's
|
||||
// execution.
|
||||
- //
|
||||
- // The second CrossThreadUnretained() is safe here because result_buffer_data
|
||||
- // is backed by a DOMArrayBufferView that is also passed to the task via
|
||||
- // WrapCrossThreadPersistent. Therefore, the data is guaranteed to remain
|
||||
- // alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce(
|
||||
- &DoWrite, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- WrapCrossThreadPersistent(result_buffer),
|
||||
- CrossThreadUnretained(file_state_.get()), resolver_task_runner_,
|
||||
- CrossThreadUnretained(result_buffer_data), file_offset, write_size));
|
||||
+ CrossThreadBindOnce(&DoWrite, WrapCrossThreadPersistent(this),
|
||||
+ WrapCrossThreadPersistent(resolver),
|
||||
+ CrossThreadUnretained(file_state_.get()),
|
||||
+ resolver_task_runner_, std::move(result_buffer_data),
|
||||
+ file_offset, write_size));
|
||||
return resolver->Promise();
|
||||
}
|
||||
|
||||
@@ -676,22 +673,29 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
void NativeIOFile::DoRead(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+ DCHECK_GE(read_size, 0);
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(static_cast<size_t>(read_size), result_buffer_data->DataLength());
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+
|
||||
int read_bytes;
|
||||
base::File::Error read_error;
|
||||
{
|
||||
WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
DCHECK(file_state->file.IsValid())
|
||||
<< "file I/O operation queued after file closed";
|
||||
- read_bytes =
|
||||
- file_state->file.Read(file_offset, result_buffer_data, read_size);
|
||||
+ read_bytes = file_state->file.Read(file_offset, result_buffer_data->Data(),
|
||||
+ read_size);
|
||||
read_error = (read_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
: base::File::FILE_OK;
|
||||
}
|
||||
@@ -699,15 +703,18 @@ void NativeIOFile::DoRead(
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
CrossThreadBindOnce(&NativeIOFile::DidRead, std::move(native_io_file),
|
||||
- std::move(resolver), std::move(result_buffer),
|
||||
+ std::move(resolver), std::move(result_buffer_data),
|
||||
read_bytes, read_error));
|
||||
}
|
||||
|
||||
void NativeIOFile::DidRead(
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int read_bytes,
|
||||
base::File::Error read_error) {
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
if (!script_state->ContextIsValid())
|
||||
return;
|
||||
@@ -727,7 +734,7 @@ void NativeIOFile::DidRead(
|
||||
DCHECK_EQ(read_error, base::File::FILE_OK)
|
||||
<< "Error set but positive number of bytes read.";
|
||||
NativeIOReadResult* read_result = MakeGarbageCollected<NativeIOReadResult>();
|
||||
- read_result->setBuffer(NotShared<DOMArrayBufferView>(result_buffer));
|
||||
+ read_result->setBuffer(result_buffer_data->Take());
|
||||
read_result->setReadBytes(read_bytes);
|
||||
resolver->Resolve(read_result);
|
||||
}
|
||||
@@ -736,13 +743,19 @@ void NativeIOFile::DidRead(
|
||||
void NativeIOFile::DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- const char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+ DCHECK_GE(write_size, 0);
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(static_cast<size_t>(write_size), result_buffer_data->DataLength());
|
||||
+#endif // DCHECK_IS_ON()
|
||||
|
||||
int written_bytes;
|
||||
int64_t actual_file_length_on_failure = 0;
|
||||
@@ -751,8 +764,8 @@ void NativeIOFile::DoWrite(
|
||||
WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
DCHECK(file_state->file.IsValid())
|
||||
<< "file I/O operation queued after file closed";
|
||||
- written_bytes =
|
||||
- file_state->file.Write(file_offset, result_buffer_data, write_size);
|
||||
+ written_bytes = file_state->file.Write(
|
||||
+ file_offset, result_buffer_data->Data(), write_size);
|
||||
write_error = (written_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
: base::File::FILE_OK;
|
||||
if (written_bytes < write_size || write_error != base::File::FILE_OK) {
|
||||
@@ -767,18 +780,21 @@ void NativeIOFile::DoWrite(
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
CrossThreadBindOnce(&NativeIOFile::DidWrite, std::move(native_io_file),
|
||||
- std::move(resolver), std::move(result_buffer),
|
||||
+ std::move(resolver), std::move(result_buffer_data),
|
||||
written_bytes, write_error, write_size,
|
||||
actual_file_length_on_failure));
|
||||
}
|
||||
|
||||
void NativeIOFile::DidWrite(
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int written_bytes,
|
||||
base::File::Error write_error,
|
||||
int write_size,
|
||||
int64_t actual_file_length_on_failure) {
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
if (!script_state->ContextIsValid())
|
||||
return;
|
||||
@@ -821,7 +837,7 @@ void NativeIOFile::DidWrite(
|
||||
DCHECK_EQ(write_error, base::File::FILE_OK);
|
||||
NativeIOWriteResult* write_result =
|
||||
MakeGarbageCollected<NativeIOWriteResult>();
|
||||
- write_result->setBuffer(NotShared<DOMArrayBufferView>(result_buffer));
|
||||
+ write_result->setBuffer(result_buffer_data->Take());
|
||||
write_result->setWrittenBytes(written_bytes);
|
||||
resolver->Resolve(write_result);
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.h b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
index 2e41efeefbcf9805ec2b2ed70d018c717c5c75d1..8ae49ebc2d36d547d152d4e56192e30f8cacd641 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_capacity_tracker.h"
|
||||
+#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
|
||||
#include "third_party/blink/renderer/platform/heap/handle.h"
|
||||
#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
@@ -127,15 +128,14 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// Performs the file I/O part of read(), off the main thread.
|
||||
static void DoRead(CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
- char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size);
|
||||
// Performs the post file I/O part of read(), on the main thread.
|
||||
void DidRead(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int read_bytes,
|
||||
base::File::Error read_error);
|
||||
|
||||
@@ -143,10 +143,9 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- const char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size);
|
||||
// Performs the post file I/O part of write(), on the main thread.
|
||||
@@ -154,7 +153,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// `actual_file_length_on_failure` is negative if the I/O operation was
|
||||
// unsuccessful and the correct length of the file could not be determined.
|
||||
void DidWrite(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int written_bytes,
|
||||
base::File::Error write_error,
|
||||
int write_size,
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc b/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
index c50a0a94d111d9ea4eb1eac8a7da920936e0d1a3..3e98a12059374d41b22c8d5c706c31e81581aeae 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
@@ -3,9 +3,16 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
+
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
+#include "base/sequence_checker.h"
|
||||
+#include "base/types/pass_key.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
|
||||
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
|
||||
+#include "v8/include/v8.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -72,4 +79,140 @@ DOMArrayBufferView* TransferToNewArrayBufferView(
|
||||
return target;
|
||||
}
|
||||
|
||||
+// static
|
||||
+std::unique_ptr<NativeIODataBuffer> NativeIODataBuffer::Create(
|
||||
+ ScriptState* script_state,
|
||||
+ NotShared<DOMArrayBufferView> source) {
|
||||
+ DCHECK(script_state);
|
||||
+ DCHECK(source);
|
||||
+
|
||||
+ DOMArrayBufferView::ViewType type = source->GetType();
|
||||
+ size_t offset = source->byteOffset();
|
||||
+ size_t byte_length = source->byteLength();
|
||||
+ size_t length = byte_length / source->TypeSize();
|
||||
+
|
||||
+ // Explicitly fail if the source buffer is not detachable. On its own,
|
||||
+ // Transfer() copies non-detachable input buffers.
|
||||
+ DOMArrayBuffer* buffer = source->buffer();
|
||||
+ v8::Isolate* isolate = script_state->GetIsolate();
|
||||
+ if (!buffer->IsDetachable(isolate))
|
||||
+ return nullptr;
|
||||
+
|
||||
+ ArrayBufferContents contents;
|
||||
+ if (!buffer->Transfer(isolate, contents))
|
||||
+ return nullptr;
|
||||
+ DCHECK(source->IsDetached());
|
||||
+
|
||||
+ return std::make_unique<NativeIODataBuffer>(
|
||||
+ std::move(contents), type, offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ length, base::PassKey<NativeIODataBuffer>());
|
||||
+}
|
||||
+
|
||||
+NativeIODataBuffer::NativeIODataBuffer(ArrayBufferContents contents,
|
||||
+ DOMArrayBufferView::ViewType type,
|
||||
+ size_t offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ size_t byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ size_t length,
|
||||
+ base::PassKey<NativeIODataBuffer>)
|
||||
+ : contents_(std::move(contents)),
|
||||
+ type_(type),
|
||||
+ offset_(offset),
|
||||
+#if DCHECK_IS_ON()
|
||||
+ byte_length_(byte_length),
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ length_(length) {
|
||||
+ DCHECK(IsValid());
|
||||
+ DCHECK(!contents_.IsShared());
|
||||
+
|
||||
+ // DataLength() returns 0 when called on an invalid ArrayBufferContents
|
||||
+ // (backing an empty array). This works as expected.
|
||||
+ DCHECK_LE(offset, contents_.DataLength());
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(length, byte_length);
|
||||
+ DCHECK_LE(byte_length, contents_.DataLength() - offset);
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+}
|
||||
+
|
||||
+NativeIODataBuffer::~NativeIODataBuffer() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+}
|
||||
+
|
||||
+bool NativeIODataBuffer::IsValid() const {
|
||||
+ // The ArrayBufferContents is not shared when this instance is constructed. It
|
||||
+ // should not become shared while the instance is valid, because no other code
|
||||
+ // can gain access and make it shared.
|
||||
+ //
|
||||
+ // ArrayBufferContents::IsShared() returns false for invalid instances, which
|
||||
+ // works out well for this check.
|
||||
+ DCHECK(!contents_.IsShared());
|
||||
+
|
||||
+ // Transferring the data out of an empty ArrayBuffer yields an invalid
|
||||
+ // ArrayBufferContents.
|
||||
+ return length_ == 0 || contents_.IsValid();
|
||||
+}
|
||||
+
|
||||
+NotShared<DOMArrayBufferView> NativeIODataBuffer::Take() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+ DCHECK(IsValid());
|
||||
+
|
||||
+ DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(std::move(contents_));
|
||||
+
|
||||
+ DOMArrayBufferView* view = nullptr;
|
||||
+ switch (type_) {
|
||||
+ case DOMArrayBufferView::kTypeInt8:
|
||||
+ view = DOMInt8Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint8:
|
||||
+ view = DOMUint8Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint8Clamped:
|
||||
+ view = DOMUint8ClampedArray::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeInt16:
|
||||
+ view = DOMInt16Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint16:
|
||||
+ view = DOMUint16Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeInt32:
|
||||
+ view = DOMInt32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint32:
|
||||
+ view = DOMUint32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeFloat32:
|
||||
+ view = DOMFloat32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeFloat64:
|
||||
+ view = DOMFloat64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeBigInt64:
|
||||
+ view = DOMBigInt64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeBigUint64:
|
||||
+ view = DOMBigUint64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeDataView:
|
||||
+ view = DOMDataView::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+ }
|
||||
+ return NotShared<DOMArrayBufferView>(view);
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_utils.h b/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
index 355a67a8125ea11158dfe435a71c1c01b1ece361..a500d38bcdf8340e7c747cbde949db8f980ea272 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
@@ -5,11 +5,19 @@
|
||||
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
|
||||
+#include <cstddef>
|
||||
+#include <memory>
|
||||
+
|
||||
+#include "base/sequence_checker.h"
|
||||
+#include "base/types/pass_key.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
+class ScriptState;
|
||||
+
|
||||
// Extracts the read/write operation size from the buffer size.
|
||||
int NativeIOOperationSize(const DOMArrayBufferView& buffer);
|
||||
|
||||
@@ -20,6 +28,121 @@ DOMArrayBufferView* TransferToNewArrayBufferView(
|
||||
v8::Isolate* isolate,
|
||||
NotShared<DOMArrayBufferView> source);
|
||||
|
||||
+// Provides cross-thread access to the buffer backing a DOMArrayBufferView.
|
||||
+//
|
||||
+// This class is necessary because DOMArrayBufferView is garbage-collected,
|
||||
+// which entails that each DOMArrayBufferView instance can only be safely
|
||||
+// accessed on the thread where it was created. Note that CrossThreadPersistent
|
||||
+// can be used to keep a DOMArrayBufferView alive across threads, but the
|
||||
+// instance cannot be safely accessed on a different thread. See the comments on
|
||||
+// cppgc::subtle::CrossThreadPersistent for details.
|
||||
+//
|
||||
+// An instance takes over a DOMArrayBufferView's backing buffer at construction.
|
||||
+// The instance exposes the backing buffer via the Data() and DataLength()
|
||||
+// methods. At some point, the backing buffer is turned back into a
|
||||
+// DOMArrayBufferView via the Take() method. Once Take() is called, the instance
|
||||
+// is invalid, and Data() / DataLength() must not be called anymore.
|
||||
+//
|
||||
+// An instance should be owned by a single sequence at a time. Changing the
|
||||
+// owning sequence should be accomplished by PostTask-ing an owning pointer to
|
||||
+// the instance.
|
||||
+//
|
||||
+// Each instance must be destroyed on the same sequence where it was created.
|
||||
+// Take() must be called on the same sequence where the instance was created.
|
||||
+class NativeIODataBuffer {
|
||||
+ public:
|
||||
+ // Detaches the buffer backing `source`.
|
||||
+ //
|
||||
+ // Returns nullptr if detaching failed.
|
||||
+ static std::unique_ptr<NativeIODataBuffer> Create(
|
||||
+ ScriptState* script_state,
|
||||
+ NotShared<DOMArrayBufferView> source);
|
||||
+
|
||||
+ // Exposed for std::make_unique. Instances should be obtained from Create().
|
||||
+ NativeIODataBuffer(ArrayBufferContents contents,
|
||||
+ DOMArrayBufferView::ViewType type,
|
||||
+ size_t offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ size_t byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ size_t length,
|
||||
+ base::PassKey<NativeIODataBuffer>);
|
||||
+
|
||||
+ NativeIODataBuffer(const NativeIODataBuffer&) = delete;
|
||||
+ NativeIODataBuffer& operator=(const NativeIODataBuffer&) = delete;
|
||||
+
|
||||
+ ~NativeIODataBuffer();
|
||||
+
|
||||
+ // Re-creates the DOMArrayBufferView.
|
||||
+ //
|
||||
+ // Must only be called while this instance is onwed by the same sequence where
|
||||
+ // Create() was called. Must only be called if IsValid() is true.
|
||||
+ // After the call, IsValid() will return false.
|
||||
+ NotShared<DOMArrayBufferView> Take();
|
||||
+
|
||||
+ // Exposed for DCHECKs.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence.
|
||||
+ bool IsValid() const;
|
||||
+
|
||||
+ // Returns a raw pointer to the DOMArrayBufferView's view.
|
||||
+ //
|
||||
+ // The return type was chosen so that the raw pointer can be conveniently
|
||||
+ // passed to base::File methods.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence. Must only be
|
||||
+ // called if IsValid() is true.
|
||||
+ char* Data() {
|
||||
+ DCHECK(IsValid());
|
||||
+
|
||||
+ // An invalid ArrayBufferContents (backing an empty array) returns nullptr
|
||||
+ // when Data() is called. However, in that case, the offset must be zero.
|
||||
+ DCHECK(contents_.Data() || contents_.DataLength() == 0);
|
||||
+ DCHECK(contents_.Data() || offset_ == 0);
|
||||
+
|
||||
+ // According to the DCHECKs above, this branch isn't strictly needed. The
|
||||
+ // return statement below the branch will never do pointer arithmetic on
|
||||
+ // nullptr, because `offset_` is guaranteed to be zero when
|
||||
+ // the ArrayBufferContents is not valid but this instance is.
|
||||
+ char* data = static_cast<char*>(contents_.Data());
|
||||
+ if (!data) {
|
||||
+ DCHECK_EQ(offset_, 0u);
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ return data + offset_;
|
||||
+ }
|
||||
+
|
||||
+#if DCHECK_IS_ON()
|
||||
+ // Returns the size of the DOMArrayBufferView's view, in bytes.
|
||||
+ //
|
||||
+ // Exposed for DCHECKs around base::File calls.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence. Must only be
|
||||
+ // called if IsValid() is true.
|
||||
+ size_t DataLength() const {
|
||||
+ DCHECK(IsValid());
|
||||
+ return byte_length_;
|
||||
+ }
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+
|
||||
+ private:
|
||||
+ SEQUENCE_CHECKER(sequence_checker_);
|
||||
+
|
||||
+ // May not be valid, as reported by ArrayBufferContents::IsValid().
|
||||
+ //
|
||||
+ // If valid, guaranteed not to be shared, as reported by
|
||||
+ // ArrayBufferContents::IsShared().
|
||||
+ ArrayBufferContents contents_;
|
||||
+
|
||||
+ DOMArrayBufferView::ViewType type_;
|
||||
+ const size_t offset_;
|
||||
+#if DCHECK_IS_ON()
|
||||
+ const size_t byte_length_;
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ const size_t length_;
|
||||
+};
|
||||
+
|
||||
} // namespace blink
|
||||
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
36
patches/chromium/cherry-pick-b2c4e4dc21e5.patch
Normal file
36
patches/chromium/cherry-pick-b2c4e4dc21e5.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Reilly Grant <reillyg@chromium.org>
|
||||
Date: Mon, 4 Oct 2021 23:02:19 +0000
|
||||
Subject: mojo: CHECK when array has too many elements to serialize
|
||||
|
||||
This change turns an early return into a CHECK because the surrounding
|
||||
code expects memory allocation to succeed.
|
||||
|
||||
(cherry picked from commit 588cb74f661269a5b2b69f52619c0f7a09867d6f)
|
||||
|
||||
Bug: 1236318
|
||||
Change-Id: Ib11e0564fb0fa653cb50c82e1973c76ec0c9c725
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3139712
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Auto-Submit: Reilly Grant <reillyg@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#917908}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3203131
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1301}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/lib/message_fragment.h b/mojo/public/cpp/bindings/lib/message_fragment.h
|
||||
index e466d62250e0b1052ef0d5a8cb6e1abe165147ae..748d3bf409984637f3e824f12e85bf38ffbffe24 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/message_fragment.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/message_fragment.h
|
||||
@@ -149,8 +149,7 @@ class MessageFragment<Array_Data<T>> {
|
||||
static_assert(
|
||||
std::numeric_limits<uint32_t>::max() > Traits::kMaxNumElements,
|
||||
"Max num elements castable to 32bit");
|
||||
- if (num_elements > Traits::kMaxNumElements)
|
||||
- return;
|
||||
+ CHECK_LE(num_elements, Traits::kMaxNumElements);
|
||||
|
||||
const uint32_t num_bytes =
|
||||
Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
|
||||
41
patches/chromium/cherry-pick-be50c60b4225.patch
Normal file
41
patches/chromium/cherry-pick-be50c60b4225.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Wed, 2 Feb 2022 05:45:44 +0000
|
||||
Subject: Viz: Fix UAF on context loss
|
||||
|
||||
(cherry picked from commit 98d246cabe677e1d8287e4d42ce02825417be9e2)
|
||||
|
||||
Fixed: 1250655
|
||||
Change-Id: I2898316635d370fa36b94e0ae2564ed357745b2c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3413372
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Commit-Queue: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#963012}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3430523
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1050}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
index a31c10c610000415b5a88a0824eea63b45a435cc..1b323f142d934afea0215dea190efaa197cec554 100644
|
||||
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
@@ -478,9 +478,13 @@ const gpu::GpuFeatureInfo& ContextProviderCommandBuffer::GetGpuFeatureInfo()
|
||||
void ContextProviderCommandBuffer::OnLostContext() {
|
||||
CheckValidThreadOrLockAcquired();
|
||||
|
||||
- // Ensure |this| isn't destroyed in the middle of OnLostContext() if observers
|
||||
- // drop all references to it.
|
||||
- scoped_refptr<ContextProviderCommandBuffer> ref(this);
|
||||
+ // Observers may drop the last persistent references to `this`, but there may
|
||||
+ // be weak references in use further up the stack. This task is posted to
|
||||
+ // ensure that destruction is deferred until it's safe.
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce([](scoped_refptr<ContextProviderCommandBuffer>) {},
|
||||
+ base::WrapRefCounted(this)));
|
||||
|
||||
for (auto& observer : observers_)
|
||||
observer.OnContextLost();
|
||||
183
patches/chromium/cherry-pick-c5571653d932.patch
Normal file
183
patches/chromium/cherry-pick-c5571653d932.patch
Normal file
@@ -0,0 +1,183 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jarryd <jarrydg@chromium.org>
|
||||
Date: Wed, 29 Dec 2021 19:49:22 +0000
|
||||
Subject: Quota: Use Threadsafe Pressure Callback.
|
||||
|
||||
Fixes UAF by removing use of raw ptr to StorageNotificationService.
|
||||
Instead, the service's interface exposes a method to create a
|
||||
thread-safe callback to pass to the quota manager instead.
|
||||
|
||||
This change also changes the parameter type for the call chain from
|
||||
url::Origin to blink::StorageKey to match the type Quota is keyed on.
|
||||
|
||||
Bug:1275020
|
||||
|
||||
(cherry picked from commit e304c0373f9cc4a65d39d7094e4897627e83390e)
|
||||
|
||||
Change-Id: Icc696d22fa41324e7a6c056599db635bb5de6291
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3347939
|
||||
Reviewed-by: Joshua Bell <jsbell@chromium.org>
|
||||
Reviewed-by: Nasko Oskov <nasko@chromium.org>
|
||||
Commit-Queue: Jarryd Goodman <jarrydg@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#953375}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3360203
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Owners-Override: Krishna Govind <govind@chromium.org>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1352}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/storage/storage_notification_service_impl.cc b/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
index f8b38745827b25e46bfd1b4225bb3c55f2836d02..ceeafe0ad40e69574ccf885e4230ce042ecbaaaa 100644
|
||||
--- a/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
+++ b/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
+#include "content/public/browser/browser_task_traits.h"
|
||||
+#include "content/public/browser/browser_thread.h"
|
||||
|
||||
#if !defined(OS_ANDROID)
|
||||
#include "chrome/browser/ui/storage_pressure_bubble.h"
|
||||
@@ -36,8 +38,26 @@ const base::TimeDelta GetThrottlingInterval() {
|
||||
|
||||
} // namespace
|
||||
|
||||
+StoragePressureNotificationCallback
|
||||
+StorageNotificationServiceImpl::CreateThreadSafePressureNotificationCallback() {
|
||||
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
+ auto thread_unsafe_callback = base::BindRepeating(
|
||||
+ &StorageNotificationServiceImpl::MaybeShowStoragePressureNotification,
|
||||
+ weak_ptr_factory_.GetWeakPtr());
|
||||
+ return base::BindRepeating(
|
||||
+ [](StoragePressureNotificationCallback cb, blink::StorageKey key) {
|
||||
+ content::GetUIThreadTaskRunner({})->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce([](StoragePressureNotificationCallback callback,
|
||||
+ blink::StorageKey key) { callback.Run(key); },
|
||||
+ std::move(cb), key));
|
||||
+ },
|
||||
+ std::move(thread_unsafe_callback));
|
||||
+}
|
||||
+
|
||||
void StorageNotificationServiceImpl::MaybeShowStoragePressureNotification(
|
||||
- const url::Origin origin) {
|
||||
+ const blink::StorageKey storage_key) {
|
||||
+ auto origin = storage_key.origin();
|
||||
if (!disk_pressure_notification_last_sent_at_.is_null() &&
|
||||
base::TimeTicks::Now() - disk_pressure_notification_last_sent_at_ <
|
||||
GetThrottlingInterval()) {
|
||||
diff --git a/chrome/browser/storage/storage_notification_service_impl.h b/chrome/browser/storage/storage_notification_service_impl.h
|
||||
index 497a3063c835a37fe9141052263cf70c863235fa..44fe169b82ced5e328060f191d608aaa57d3af71 100644
|
||||
--- a/chrome/browser/storage/storage_notification_service_impl.h
|
||||
+++ b/chrome/browser/storage/storage_notification_service_impl.h
|
||||
@@ -5,10 +5,12 @@
|
||||
#ifndef CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
#define CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
|
||||
+#include "base/memory/weak_ptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "components/keyed_service/core/keyed_service.h"
|
||||
#include "content/public/browser/storage_notification_service.h"
|
||||
+#include "third_party/blink/public/common/storage_key/storage_key.h"
|
||||
|
||||
class StorageNotificationServiceImpl
|
||||
: public content::StorageNotificationService,
|
||||
@@ -16,13 +18,20 @@ class StorageNotificationServiceImpl
|
||||
public:
|
||||
StorageNotificationServiceImpl();
|
||||
~StorageNotificationServiceImpl() override;
|
||||
- void MaybeShowStoragePressureNotification(const url::Origin) override;
|
||||
+ // Called from the UI thread, this method returns a callback that can passed
|
||||
+ // to any thread, and proxies calls to
|
||||
+ // `MaybeShowStoragePressureNotification()` back to the UI thread. It wraps a
|
||||
+ // weak pointer to `this`.
|
||||
+ StoragePressureNotificationCallback
|
||||
+ CreateThreadSafePressureNotificationCallback() override;
|
||||
+ void MaybeShowStoragePressureNotification(const blink::StorageKey) override;
|
||||
base::TimeTicks GetLastSentAtForTesting() {
|
||||
return disk_pressure_notification_last_sent_at_;
|
||||
}
|
||||
|
||||
private:
|
||||
base::TimeTicks disk_pressure_notification_last_sent_at_;
|
||||
+ base::WeakPtrFactory<StorageNotificationServiceImpl> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index 86c6de60739a0c5aa49ed63f1546b478d7f58054..263fe6195ac6d48cd7a985ca844d1a6e421a9b1d 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1169,23 +1169,14 @@ void StoragePartitionImpl::Initialize(
|
||||
StorageNotificationService* storage_notification_service =
|
||||
browser_context_->GetStorageNotificationService();
|
||||
if (storage_notification_service) {
|
||||
- // base::Unretained is safe to use because the BrowserContext is guaranteed
|
||||
- // to outlive QuotaManager. This is because BrowserContext outlives this
|
||||
- // StoragePartitionImpl, which destroys the QuotaManager on teardown.
|
||||
- base::RepeatingCallback<void(const blink::StorageKey)>
|
||||
- send_notification_function = base::BindRepeating(
|
||||
- [](StorageNotificationService* service,
|
||||
- const blink::StorageKey storage_key) {
|
||||
- GetUIThreadTaskRunner({})->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&StorageNotificationService::
|
||||
- MaybeShowStoragePressureNotification,
|
||||
- base::Unretained(service),
|
||||
- std::move(storage_key.origin())));
|
||||
- },
|
||||
- base::Unretained(storage_notification_service));
|
||||
-
|
||||
- quota_manager_->SetStoragePressureCallback(send_notification_function);
|
||||
+ // The weak ptr associated with the pressure notification callback will be
|
||||
+ // created and evaluated by a task runner on the UI thread, as confirmed by
|
||||
+ // the DCHECK's above, ensuring that the task runner does not attempt to run
|
||||
+ // the callback in the case that the storage notification service is already
|
||||
+ // destructed.
|
||||
+ quota_manager_->SetStoragePressureCallback(
|
||||
+ storage_notification_service
|
||||
+ ->CreateThreadSafePressureNotificationCallback());
|
||||
}
|
||||
|
||||
// Each consumer is responsible for registering its QuotaClient during
|
||||
diff --git a/content/public/browser/storage_notification_service.h b/content/public/browser/storage_notification_service.h
|
||||
index 3eec5ef29051008041695bcf7ebbf63787f5bd89..e72adada318f1cb998e2a9e7468a6f2e54742760 100644
|
||||
--- a/content/public/browser/storage_notification_service.h
|
||||
+++ b/content/public/browser/storage_notification_service.h
|
||||
@@ -8,6 +8,15 @@
|
||||
#include "base/bind.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
+namespace blink {
|
||||
+class StorageKey;
|
||||
+}
|
||||
+
|
||||
+namespace {
|
||||
+using StoragePressureNotificationCallback =
|
||||
+ base::RepeatingCallback<void(const blink::StorageKey)>;
|
||||
+}
|
||||
+
|
||||
namespace content {
|
||||
|
||||
// This interface is used to create a connection between the storage layer and
|
||||
@@ -19,12 +28,15 @@ class StorageNotificationService {
|
||||
StorageNotificationService() = default;
|
||||
~StorageNotificationService() = default;
|
||||
|
||||
- // This pure virtual function should be implemented in the embedder layer
|
||||
+ // These pure virtual functions should be implemented in the embedder layer
|
||||
// where calls to UI and notification code can be implemented. This closure
|
||||
// is passed to QuotaManager in StoragePartitionImpl, where it is called
|
||||
// when QuotaManager determines appropriate to alert the user that the device
|
||||
// is in a state of storage pressure.
|
||||
- virtual void MaybeShowStoragePressureNotification(const url::Origin) = 0;
|
||||
+ virtual void MaybeShowStoragePressureNotification(
|
||||
+ const blink::StorageKey) = 0;
|
||||
+ virtual StoragePressureNotificationCallback
|
||||
+ CreateThreadSafePressureNotificationCallback() = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StorageNotificationService);
|
||||
122
patches/chromium/cherry-pick-c69dddfe1cde.patch
Normal file
122
patches/chromium/cherry-pick-c69dddfe1cde.patch
Normal file
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hongchan Choi <hongchan@chromium.org>
|
||||
Date: Mon, 11 Oct 2021 23:53:51 +0000
|
||||
Subject: Use zero when the starting value of exponential ramp is zero
|
||||
|
||||
The calculation of an exponential curve is done by the specification:
|
||||
https://webaudio.github.io/web-audio-api/#dom-audioparam-exponentialramptovalueattime
|
||||
|
||||
However, it missed a case where V0 (value1) is zero where it causes
|
||||
a NaN.
|
||||
|
||||
(cherry picked from commit 4e2dcd84dc33f29b032b52e053726ab49e4d0b4d)
|
||||
|
||||
Bug: 1253746,1240610
|
||||
Test: third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
|
||||
Change-Id: Ib4a95f9298b4300705eda6a2eea64169de7cb002
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3205982
|
||||
Reviewed-by: Ryan Sleevi <rsleevi@chromium.org>
|
||||
Reviewed-by: Chrome Cunningham <chcunningham@chromium.org>
|
||||
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#928673}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3218139
|
||||
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4638@{#766}
|
||||
Cr-Branched-From: 159257cab5585bc8421abf347984bb32fdfe9eb9-refs/heads/main@{#920003}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
|
||||
index 55e36732e0863153b09bb1db1eff601310606c1b..f3931e08031d001cdd4f5adb9094abc264f7a5da 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
|
||||
#include "third_party/fdlibm/ieee754.h"
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
@@ -133,7 +134,12 @@ float AudioParamTimeline::ExponentialRampAtTime(double t,
|
||||
double time1,
|
||||
float value2,
|
||||
double time2) {
|
||||
- return value1 * fdlibm::pow(value2 / value1, (t - time1) / (time2 - time1));
|
||||
+ DCHECK(!std::isnan(value1) && std::isfinite(value1));
|
||||
+ DCHECK(!std::isnan(value2) && std::isfinite(value2));
|
||||
+
|
||||
+ return (value1 == 0.0f || std::signbit(value1) != std::signbit(value2))
|
||||
+ ? value1
|
||||
+ : value1 * fdlibm::pow(value2 / value1, (t - time1) / (time2 - time1));
|
||||
}
|
||||
|
||||
// Compute the value of a set target event at time t with the given event
|
||||
@@ -1001,6 +1007,8 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(
|
||||
std::tie(value2, time2, next_event_type) =
|
||||
HandleCancelValues(event, next_event, value2, time2);
|
||||
|
||||
+ DCHECK(!std::isnan(value1));
|
||||
+ DCHECK(!std::isnan(value2));
|
||||
DCHECK_GE(time2, time1);
|
||||
|
||||
// |fillToEndFrame| is the exclusive upper bound of the last frame to be
|
||||
@@ -1060,7 +1068,6 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(
|
||||
value = event->Value();
|
||||
write_index =
|
||||
FillWithDefault(values, value, fill_to_frame, write_index);
|
||||
-
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1403,6 +1410,7 @@ AudioParamTimeline::HandleCancelValues(const ParamEvent* current_event,
|
||||
value2 = ExponentialRampAtTime(next_event->Time(), value1, time1,
|
||||
saved_event->Value(),
|
||||
saved_event->Time());
|
||||
+ DCHECK(!std::isnan(value1));
|
||||
break;
|
||||
case ParamEvent::kSetValueCurve:
|
||||
case ParamEvent::kSetValueCurveEnd:
|
||||
diff --git a/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html b/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..85397c5cc6757ae1464a0cd6733283b6b60abeee
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
|
||||
@@ -0,0 +1,39 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html>
|
||||
+<head>
|
||||
+ <title>
|
||||
+ Test if a corner case crashes the exponential ramp.
|
||||
+ </title>
|
||||
+ <script src="../../resources/testharness.js"></script>
|
||||
+ <script src="../../resources/testharnessreport.js"></script>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <script>
|
||||
+ const t = async_test('exponential-ramp-crash');
|
||||
+
|
||||
+ const onload = () => {
|
||||
+ const context = new OfflineAudioContext(2, 441000, 44100);
|
||||
+ const source = new ConstantSourceNode(context);
|
||||
+ const delay_node = context.createDelay(30);
|
||||
+ delay_node.connect(context.destination);
|
||||
+ // The time overlap between 4.1s and 4s caused a crash in M95:
|
||||
+ // https://crbug.com/1253746
|
||||
+ delay_node.delayTime.exponentialRampToValueAtTime(2, 4.1);
|
||||
+ delay_node.delayTime.cancelAndHoldAtTime(4);
|
||||
+ context.oncomplete = t.step_func_done(() => {
|
||||
+ // The |delay_node.delayTime| value should be zero because it does not
|
||||
+ // have the previous anchor value. Based on the specification, if the
|
||||
+ // beginning of an expoential ramp is zero, the resulting value falls
|
||||
+ // into zero. In this case, there was no value point before the
|
||||
+ // exponential ramp, and having no value point is treated as a
|
||||
+ // default value, which is zero for |delayTime|.
|
||||
+ assert_equals(delay_node.delayTime.value, 0);
|
||||
+ assert_equals(context.state, 'closed');
|
||||
+ });
|
||||
+ context.startRendering();
|
||||
+ };
|
||||
+
|
||||
+ window.addEventListener('load', t.step_func(onload));
|
||||
+ </script>
|
||||
+</body>
|
||||
+</html>
|
||||
62
patches/chromium/cherry-pick-da11d71a0227.patch
Normal file
62
patches/chromium/cherry-pick-da11d71a0227.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Fri, 10 Dec 2021 01:03:53 +0000
|
||||
Subject: mojo/ipc: Drop messages targeting invalid task runner
|
||||
|
||||
If the endpoint's task runner does not match the current task runner (or
|
||||
an equivalent main-thread task runner for the ChannelProxy) when a
|
||||
executing a message dispatch task for that endpoint, this ignores the
|
||||
message instead of dispatching it on the wrong sequence.
|
||||
|
||||
(cherry picked from commit 0747c9405e1098c0bbbc5593183696eafb45b72c)
|
||||
|
||||
Fixed: 1263457
|
||||
Change-Id: I4f6ba22de3ff8cf3994b748e1ffd0f0aabb17b70
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3318601
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#949140}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3328403
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1269}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
|
||||
index 18b4dc9be5bf54e6f5443d53739bc06ba3f98767..07e522337090494e278395ac4e7ead73c472ef72 100644
|
||||
--- a/ipc/ipc_mojo_bootstrap.cc
|
||||
+++ b/ipc/ipc_mojo_bootstrap.cc
|
||||
@@ -966,11 +966,14 @@ class ChannelAssociatedGroupController
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
+ if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
|
||||
+ !proxy_task_runner_->RunsTasksInCurrentSequence()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Using client->interface_name() is safe here because this is a static
|
||||
// string defined for each mojo interface.
|
||||
TRACE_EVENT0("mojom", client->interface_name());
|
||||
- DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence() ||
|
||||
- proxy_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
// Sync messages should never make their way to this method.
|
||||
DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
|
||||
@@ -1000,11 +1003,14 @@ class ChannelAssociatedGroupController
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
+ if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
|
||||
+ !proxy_task_runner_->RunsTasksInCurrentSequence()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Using client->interface_name() is safe here because this is a static
|
||||
// string defined for each mojo interface.
|
||||
TRACE_EVENT0("mojom", client->interface_name());
|
||||
- DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence() ||
|
||||
- proxy_task_runner_->RunsTasksInCurrentSequence());
|
||||
MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
|
||||
|
||||
// The message must have already been dequeued by the endpoint waking up
|
||||
308
patches/chromium/cherry-pick-dbde8795233a.patch
Normal file
308
patches/chromium/cherry-pick-dbde8795233a.patch
Normal file
@@ -0,0 +1,308 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Meenan <pmeenan@chromium.org>
|
||||
Date: Fri, 3 Dec 2021 18:15:17 +0000
|
||||
Subject: Prevent opaque range request responses from entering the preload
|
||||
cache
|
||||
|
||||
ResourceLoader cancels range request responses that were not initiated
|
||||
with range request headers causing them to error out and be cleared from
|
||||
the preload cache. Other responses (200, 416, error, etc) complete
|
||||
successfully and would otherwise enter the preload cache, making them
|
||||
observable.
|
||||
|
||||
This prevents opaque range responses of any kind from persisting in the
|
||||
preload cache (which would not naturally have any anyway).
|
||||
|
||||
(cherry picked from commit a5f630e5f94da28a926d60da7dde194acd8697f0)
|
||||
|
||||
Bug: 1270990
|
||||
Change-Id: Ife9922fe0b88e39722f3664ddd091a1516892157
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3294001
|
||||
Reviewed-by: Ben Kelly <wanderview@chromium.org>
|
||||
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
|
||||
Commit-Queue: Patrick Meenan <pmeenan@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#946055}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3313416
|
||||
Auto-Submit: Patrick Meenan <pmeenan@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1222}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
index 8fc72ba0b932bd20b96630373e3bc4ee7765c8a1..d27c52259038fe5daf23f9ad0acbf7cb1ade38fb 100644
|
||||
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
@@ -1873,6 +1873,19 @@ void ResourceFetcher::HandleLoaderFinish(Resource* resource,
|
||||
}
|
||||
|
||||
resource->VirtualTimePauser().UnpauseVirtualTime();
|
||||
+
|
||||
+ // A response should not serve partial content if it was not requested via a
|
||||
+ // Range header: https://fetch.spec.whatwg.org/#main-fetch so keep it out
|
||||
+ // of the preload cache in case of a non-206 response (which generates an
|
||||
+ // error).
|
||||
+ if (resource->GetResponse().GetType() ==
|
||||
+ network::mojom::FetchResponseType::kOpaque &&
|
||||
+ resource->GetResponse().HasRangeRequested() &&
|
||||
+ !resource->GetResourceRequest().HttpHeaderFields().Contains(
|
||||
+ net::HttpRequestHeaders::kRange)) {
|
||||
+ RemovePreload(resource);
|
||||
+ }
|
||||
+
|
||||
if (type == kDidFinishLoading) {
|
||||
resource->Finish(response_end, freezable_task_runner_.get());
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a0058551d52d45b3c16882014be740d75e51ddd1
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
|
||||
@@ -0,0 +1,47 @@
|
||||
+"""
|
||||
+This generates a partial response for a 100-byte text file.
|
||||
+"""
|
||||
+import re
|
||||
+
|
||||
+from wptserve.utils import isomorphic_decode
|
||||
+
|
||||
+def main(request, response):
|
||||
+ total_length = int(request.GET.first(b'length', b'100'))
|
||||
+ partial_code = int(request.GET.first(b'partial', b'206'))
|
||||
+ range_header = request.headers.get(b'Range', b'')
|
||||
+
|
||||
+ # Send a 200 if there is no range request
|
||||
+ if not range_header:
|
||||
+ to_send = ''.zfill(total_length)
|
||||
+ response.headers.set(b"Content-Type", b"text/plain")
|
||||
+ response.headers.set(b"Cache-Control", b"no-cache")
|
||||
+ response.headers.set(b"Content-Length", total_length)
|
||||
+ response.content = to_send
|
||||
+ return
|
||||
+
|
||||
+ # Simple range parsing, requires specifically "bytes=xxx-xxxx"
|
||||
+ range_header_match = re.search(r'^bytes=(\d*)-(\d*)$', isomorphic_decode(range_header))
|
||||
+ start, end = range_header_match.groups()
|
||||
+ start = int(start)
|
||||
+ end = int(end) if end else total_length
|
||||
+ length = end - start
|
||||
+
|
||||
+ # Error the request if the range goes beyond the length
|
||||
+ if length <= 0 or end > total_length:
|
||||
+ response.set_error(416, u"Range Not Satisfiable")
|
||||
+ response.write()
|
||||
+ return
|
||||
+
|
||||
+ # Generate a partial response of the requested length
|
||||
+ to_send = ''.zfill(length)
|
||||
+ response.headers.set(b"Content-Type", b"text/plain")
|
||||
+ response.headers.set(b"Accept-Ranges", b"bytes")
|
||||
+ response.headers.set(b"Cache-Control", b"no-cache")
|
||||
+ response.status = partial_code
|
||||
+
|
||||
+ content_range = b"bytes %d-%d/%d" % (start, end, total_length)
|
||||
+
|
||||
+ response.headers.set(b"Content-Range", content_range)
|
||||
+ response.headers.set(b"Content-Length", length)
|
||||
+
|
||||
+ response.content = to_send
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
index 3680c0c471d3d5f36c4aba4cc58dcd52c38a08df..b47823f03b4ef3749e622fbf7dd3b515a216b5be 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
@@ -12,7 +12,7 @@ async function broadcast(msg) {
|
||||
}
|
||||
}
|
||||
|
||||
-addEventListener('fetch', event => {
|
||||
+addEventListener('fetch', async event => {
|
||||
/** @type Request */
|
||||
const request = event.request;
|
||||
const url = new URL(request.url);
|
||||
@@ -34,6 +34,11 @@ addEventListener('fetch', event => {
|
||||
case 'broadcast-accept-encoding':
|
||||
broadcastAcceptEncoding(event);
|
||||
return;
|
||||
+ case 'record-media-range-request':
|
||||
+ return recordMediaRangeRequest(event);
|
||||
+ case 'use-media-range-request':
|
||||
+ useMediaRangeRequest(event);
|
||||
+ return;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -157,3 +162,57 @@ function broadcastAcceptEncoding(event) {
|
||||
// Just send back any response, it isn't important for the test.
|
||||
event.respondWith(new Response(''));
|
||||
}
|
||||
+
|
||||
+let rangeResponse = {};
|
||||
+
|
||||
+async function recordMediaRangeRequest(event) {
|
||||
+ /** @type Request */
|
||||
+ const request = event.request;
|
||||
+ const url = new URL(request.url);
|
||||
+ const urlParams = new URLSearchParams(url.search);
|
||||
+ const size = urlParams.get("size");
|
||||
+ const id = urlParams.get('id');
|
||||
+ const key = 'size' + size;
|
||||
+
|
||||
+ if (key in rangeResponse) {
|
||||
+ // Don't re-fetch ranges we already have.
|
||||
+ const clonedResponse = rangeResponse[key].clone();
|
||||
+ event.respondWith(clonedResponse);
|
||||
+ } else if (event.request.headers.get("range") === "bytes=0-") {
|
||||
+ // Generate a bogus 206 response to trigger subsequent range requests
|
||||
+ // of the desired size.
|
||||
+ const length = urlParams.get("length") + 100;
|
||||
+ const body = "A".repeat(Number(size));
|
||||
+ event.respondWith(new Response(body, {status: 206, headers: {
|
||||
+ "Content-Type": "audio/mp4",
|
||||
+ "Content-Range": `bytes 0-1/${length}`
|
||||
+ }}));
|
||||
+ } else if (event.request.headers.get("range") === `bytes=${Number(size)}-`) {
|
||||
+ // Pass through actual range requests which will attempt to fetch up to the
|
||||
+ // length in the original response which is bigger than the actual resource
|
||||
+ // to make sure 206 and 416 responses are treated the same.
|
||||
+ rangeResponse[key] = await fetch(event.request);
|
||||
+
|
||||
+ // Let the client know we have the range response for the given ID
|
||||
+ broadcast({id});
|
||||
+ } else {
|
||||
+ event.respondWith(Promise.reject(Error("Invalid Request")));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+function useMediaRangeRequest(event) {
|
||||
+ /** @type Request */
|
||||
+ const request = event.request;
|
||||
+ const url = new URL(request.url);
|
||||
+ const urlParams = new URLSearchParams(url.search);
|
||||
+ const size = urlParams.get("size");
|
||||
+ const key = 'size' + size;
|
||||
+
|
||||
+ // Send a clone of the range response to preload.
|
||||
+ if (key in rangeResponse) {
|
||||
+ const clonedResponse = rangeResponse[key].clone();
|
||||
+ event.respondWith(clonedResponse);
|
||||
+ } else {
|
||||
+ event.respondWith(Promise.reject(Error("Invalid Request")));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
index 16ed737f63e8eee26a306c70acb0589e424db35d..ad2853b33dc7474293df1423dd8af459571736b9 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
@@ -8,6 +8,18 @@ function loadScript(url, { doc = document }={}) {
|
||||
})
|
||||
}
|
||||
|
||||
+function preloadImage(url, { doc = document }={}) {
|
||||
+ return new Promise((resolve, reject) => {
|
||||
+ const preload = doc.createElement('link');
|
||||
+ preload.rel = 'preload';
|
||||
+ preload.as = 'image';
|
||||
+ preload.onload = () => resolve();
|
||||
+ preload.onerror = () => resolve();
|
||||
+ preload.href = url;
|
||||
+ doc.body.appendChild(preload);
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
/**
|
||||
*
|
||||
* @param {Document} document
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
index 134b0a7abd817599921d4fb430e8247a2cb40f82..a9577f01727678cd7a76bcc65e132fd6fcb230ac 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
@@ -4,6 +4,7 @@ PASS Defer range header passthrough tests to service worker
|
||||
PASS Ranged response not allowed following no-cors ranged request
|
||||
PASS Non-opaque ranged response executed
|
||||
FAIL Accept-Encoding should not appear in a service worker assert_equals: Accept-Encoding should not be set for media expected (object) null but got (string) "identity;q=1, *;q=0"
|
||||
+PASS Opaque range preload successes and failures should be indistinguishable
|
||||
PASS Range headers correctly preserved
|
||||
PASS Range headers correctly removed
|
||||
PASS Headers correctly filtered
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
index 76f80e9416c615417ad2a9fbaa565641ff5b8a12..42e4ac6d75afdcbb2ad1e9d3e4069d9cbfd10dbd 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
@@ -149,3 +149,78 @@ promise_test(async t => {
|
||||
|
||||
assert_equals((await audioBroadcast).acceptEncoding, null, "Accept-Encoding should not be set for media");
|
||||
}, `Accept-Encoding should not appear in a service worker`);
|
||||
+
|
||||
+promise_test(async t => {
|
||||
+ const scope = BASE_SCOPE + Math.random();
|
||||
+ await setupRegistration(t, scope);
|
||||
+ const iframe = await with_iframe(scope);
|
||||
+ const w = iframe.contentWindow;
|
||||
+ const length = 100;
|
||||
+ const count = 3;
|
||||
+ const counts = {};
|
||||
+
|
||||
+ // test a single range request size
|
||||
+ async function testSizedRange(size, partialResponseCode) {
|
||||
+ const rangeId = Math.random() + '';
|
||||
+ const rangeBroadcast = awaitMessage(w.navigator.serviceWorker, rangeId);
|
||||
+
|
||||
+ // Create a bogus audo element to trick the browser into sending
|
||||
+ // cross-origin range requests that can be manipulated by the service worker.
|
||||
+ const sound_url = new URL('partial-text.py', w.location);
|
||||
+ sound_url.hostname = REMOTE_HOST;
|
||||
+ sound_url.searchParams.set('action', 'record-media-range-request');
|
||||
+ sound_url.searchParams.set('length', length);
|
||||
+ sound_url.searchParams.set('size', size);
|
||||
+ sound_url.searchParams.set('partial', partialResponseCode);
|
||||
+ sound_url.searchParams.set('id', rangeId);
|
||||
+ appendAudio(w.document, sound_url);
|
||||
+
|
||||
+ // wait for the range requests to happen
|
||||
+ await rangeBroadcast;
|
||||
+
|
||||
+ // Create multiple preload requests and count the number of resource timing
|
||||
+ // entries that get created to make sure 206 and 416 range responses are treated
|
||||
+ // the same.
|
||||
+ const url = new URL('partial-text.py', w.location);
|
||||
+ url.searchParams.set('action', 'use-media-range-request');
|
||||
+ url.searchParams.set('size', size);
|
||||
+ counts['size' + size] = 0;
|
||||
+ for (let i = 0; i < count; i++) {
|
||||
+ await preloadImage(url, { doc: w.document });
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Test range requests from 1 smaller than the correct size to 1 larger than
|
||||
+ // the correct size to exercise the various permutations using the default 206
|
||||
+ // response code for successful range requests.
|
||||
+ for (let size = length - 1; size <= length + 1; size++) {
|
||||
+ await testSizedRange(size, '206');
|
||||
+ }
|
||||
+
|
||||
+ // Test a successful range request using a 200 response.
|
||||
+ await testSizedRange(length - 2, '200');
|
||||
+
|
||||
+ // Check the resource timing entries and count the reported number of fetches of each type
|
||||
+ const resources = w.performance.getEntriesByType("resource");
|
||||
+ for (const entry of resources) {
|
||||
+ const url = new URL(entry.name);
|
||||
+ if (url.searchParams.has('action') &&
|
||||
+ url.searchParams.get('action') == 'use-media-range-request' &&
|
||||
+ url.searchParams.has('size')) {
|
||||
+ counts['size' + url.searchParams.get('size')]++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Make sure there are a non-zero number of preload requests and they are all the same
|
||||
+ let counts_valid = true;
|
||||
+ const first = 'size' + (length - 2);
|
||||
+ for (let size = length - 2; size <= length + 1; size++) {
|
||||
+ let key = 'size' + size;
|
||||
+ if (!(key in counts) || counts[key] <= 0 || counts[key] != counts[first]) {
|
||||
+ counts_valid = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ assert_true(counts_valid, `Opaque range request preloads were different for error and success`);
|
||||
+}, `Opaque range preload successes and failures should be indistinguishable`);
|
||||
72
patches/chromium/cherry-pick-e3805f29fed7.patch
Normal file
72
patches/chromium/cherry-pick-e3805f29fed7.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Ellis <kevers@google.com>
|
||||
Date: Fri, 11 Feb 2022 01:36:04 +0000
|
||||
Subject: Code health cleanup: replacing animations.
|
||||
|
||||
Animation::Update performed a synchronous processing of the finish
|
||||
microtask to ensure that finished events where dispatched ahead of
|
||||
replace events. This step does not align with the spec. Instead we
|
||||
should be queuing the replace event. Microtasks will be processed in
|
||||
the correct order.
|
||||
|
||||
Spec link: https://www.w3.org/TR/web-animations-1/#timelines
|
||||
|
||||
Change-Id: Ibe7753e792fb6cf905bbe6815a080a8cc51c2803
|
||||
|
||||
(cherry picked from commit d4fb69ff0fe343fe8a171014785a88eabfe2b1c2)
|
||||
|
||||
Bug: 1290858
|
||||
Change-Id: Ibe7753e792fb6cf905bbe6815a080a8cc51c2803
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3414765
|
||||
Reviewed-by: Mustaq Ahmed <mustaq@chromium.org>
|
||||
Commit-Queue: Kevin Ellis <kevers@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#964223}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3453925
|
||||
Reviewed-by: Adrian Taylor <adetaylor@google.com>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1134}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
|
||||
index 545dcd7f0faae91cee574fce60fdedb4f6903bb6..96ecc0bf8c7dbb01714f680b6f0930d1e801f4a8 100644
|
||||
--- a/third_party/blink/renderer/core/animation/animation.cc
|
||||
+++ b/third_party/blink/renderer/core/animation/animation.cc
|
||||
@@ -2232,10 +2232,6 @@ bool Animation::Update(TimingUpdateReason reason) {
|
||||
|
||||
if (reason == kTimingUpdateForAnimationFrame) {
|
||||
if (idle || CalculateAnimationPlayState() == kFinished) {
|
||||
- // TODO(crbug.com/1029348): Per spec, we should have a microtask
|
||||
- // checkpoint right after the update cycle. Once this is fixed we should
|
||||
- // no longer need to force a synchronous resolution here.
|
||||
- AsyncFinishMicrotask();
|
||||
finished_ = true;
|
||||
}
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/animation/document_animations.cc b/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
index 6e5b4f970387929b6b940b18e14e997d2baa339c..f8090e41f8b0aa2e138738f5a3ba7c434d85535b 100644
|
||||
--- a/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
+++ b/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "third_party/blink/renderer/core/page/page.h"
|
||||
#include "third_party/blink/renderer/core/page/page_animator.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/microtask.h"
|
||||
+#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -286,10 +287,13 @@ void DocumentAnimations::RemoveReplacedAnimations(
|
||||
|
||||
// The list of animations for removal is constructed in reverse composite
|
||||
// ordering for efficiency. Flip the ordering to ensure that events are
|
||||
- // dispatched in composite order.
|
||||
+ // dispatched in composite order. Queue as a microtask so that the finished
|
||||
+ // event is dispatched ahead of the remove event.
|
||||
for (auto it = animations_to_remove.rbegin();
|
||||
it != animations_to_remove.rend(); it++) {
|
||||
- (*it)->RemoveReplacedAnimation();
|
||||
+ Animation* animation = *it;
|
||||
+ Microtask::EnqueueMicrotask(WTF::Bind(&Animation::RemoveReplacedAnimation,
|
||||
+ WrapWeakPersistent(animation)));
|
||||
}
|
||||
}
|
||||
|
||||
55
patches/chromium/cherry-pick-ebc188ad769e.patch
Normal file
55
patches/chromium/cherry-pick-ebc188ad769e.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Sat, 5 Feb 2022 13:41:47 +0000
|
||||
Subject: Fix potential handle reuse in Mojo
|
||||
|
||||
(cherry picked from commit 76eca90d0e9c09bfbb8c3e8999f36e6da6842a39)
|
||||
|
||||
(cherry picked from commit e1432faf5e101b3a516037a26818c03c759d2fdd)
|
||||
|
||||
Fixed: 1270333
|
||||
Change-Id: Ife188d519092e4e634355fd53d97c85009771b76
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3414063
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/main@{#962946}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3421488
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4844@{#87}
|
||||
Cr-Original-Branched-From: 007241ce2e6c8e5a7b306cc36c730cd07cd38825-refs/heads/main@{#961656}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3427544
|
||||
Reviewed-by: Jana Grill <janagrill@google.com>
|
||||
Owners-Override: Jana Grill <janagrill@google.com>
|
||||
Commit-Queue: Zakhar Voit <voit@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1455}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/mojo/core/handle_table.cc b/mojo/core/handle_table.cc
|
||||
index 9426281d73f050598bd5f88b38aac39c4b994ff3..a044f1c8e38f0affe269a87a10c70b49fe6d353c 100644
|
||||
--- a/mojo/core/handle_table.cc
|
||||
+++ b/mojo/core/handle_table.cc
|
||||
@@ -65,13 +65,19 @@ bool HandleTable::AddDispatchersFromTransit(
|
||||
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
|
||||
MojoHandle* handles) {
|
||||
// Oops, we're out of handles.
|
||||
- if (next_available_handle_ == MOJO_HANDLE_INVALID)
|
||||
+ if (next_available_handle_ == MOJO_HANDLE_INVALID) {
|
||||
return false;
|
||||
+ }
|
||||
+
|
||||
+ // MOJO_HANDLE_INVALID is zero.
|
||||
+ DCHECK_GE(next_available_handle_, 1u);
|
||||
|
||||
- DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
|
||||
// If this insertion would cause handle overflow, we're out of handles.
|
||||
- if (next_available_handle_ + dispatchers.size() < next_available_handle_)
|
||||
+ const uint32_t num_handles_available =
|
||||
+ std::numeric_limits<uint32_t>::max() - next_available_handle_ + 1;
|
||||
+ if (num_handles_available < dispatchers.size()) {
|
||||
return false;
|
||||
+ }
|
||||
|
||||
for (size_t i = 0; i < dispatchers.size(); ++i) {
|
||||
MojoHandle handle = MOJO_HANDLE_INVALID;
|
||||
245
patches/chromium/cherry-pick-f0a63e1f361f.patch
Normal file
245
patches/chromium/cherry-pick-f0a63e1f361f.patch
Normal file
@@ -0,0 +1,245 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Rice <ricea@chromium.org>
|
||||
Date: Sat, 6 Nov 2021 18:52:26 +0000
|
||||
Subject: Return undefined from UnderlyingSinkBase "type" getter
|
||||
|
||||
The "type" attribute of an object passed to the WritableStream
|
||||
constructor is supposed to return undefined. Add a getter to
|
||||
UnderlyingSinkBase to ensure it always does.
|
||||
|
||||
Add tests to verify that "type" is not inherited from
|
||||
Object.prototype.type.
|
||||
|
||||
Move some methods out-of-line into a new underlying_sink_base.cc file.
|
||||
|
||||
Make WritableStreamDefaultController::From() more robust.
|
||||
|
||||
BUG=1262791
|
||||
|
||||
(cherry picked from commit 26564c88bc9e034cc512afd857cf303193647b9a)
|
||||
|
||||
Change-Id: I97f43233eef0e473fb1a22a3ea8afafe92e16266
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3252171
|
||||
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
|
||||
Commit-Queue: Adam Rice <ricea@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936834}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3266824
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#806}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/streams/build.gni b/third_party/blink/renderer/core/streams/build.gni
|
||||
index 57a106353bd6720bc7da88f96dce66e4332aea2a..744d47f1a1e9352cc4df56ce89635b3d6f8b5425 100644
|
||||
--- a/third_party/blink/renderer/core/streams/build.gni
|
||||
+++ b/third_party/blink/renderer/core/streams/build.gni
|
||||
@@ -43,6 +43,7 @@ blink_core_sources_streams = [
|
||||
"transform_stream_default_controller.cc",
|
||||
"transform_stream_default_controller.h",
|
||||
"transform_stream_transformer.h",
|
||||
+ "underlying_sink_base.cc",
|
||||
"underlying_sink_base.h",
|
||||
"underlying_source_base.cc",
|
||||
"underlying_source_base.h",
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.cc b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a10d4f1865fc4e11c90f463b64ff666cce0fba69
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
|
||||
@@ -0,0 +1,29 @@
|
||||
+// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
|
||||
+
|
||||
+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
+#include "v8/include/v8.h"
|
||||
+
|
||||
+namespace blink {
|
||||
+
|
||||
+ScriptPromise UnderlyingSinkBase::start(ScriptState* script_state,
|
||||
+ ScriptValue controller,
|
||||
+ ExceptionState& exception_state) {
|
||||
+ controller_ = WritableStreamDefaultController::From(script_state, controller);
|
||||
+ return start(script_state, controller_, exception_state);
|
||||
+}
|
||||
+
|
||||
+ScriptValue UnderlyingSinkBase::type(ScriptState* script_state) const {
|
||||
+ auto* isolate = script_state->GetIsolate();
|
||||
+ return ScriptValue(isolate, v8::Undefined(isolate));
|
||||
+}
|
||||
+
|
||||
+void UnderlyingSinkBase::Trace(Visitor* visitor) const {
|
||||
+ visitor->Trace(controller_);
|
||||
+ ScriptWrappable::Trace(visitor);
|
||||
+}
|
||||
+
|
||||
+} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.h b/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
index 3b07d87f064a26e01c4ee827d78fca005049c90a..07ba729fc3a78cf2102e2d64e527048af8be9c71 100644
|
||||
--- a/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
@@ -6,16 +6,20 @@
|
||||
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_UNDERLYING_SINK_BASE_H_
|
||||
|
||||
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
|
||||
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
|
||||
#include "third_party/blink/renderer/core/core_export.h"
|
||||
-#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
|
||||
#include "third_party/blink/renderer/platform/heap/visitor.h"
|
||||
|
||||
+// Various files depend on us exporting this header.
|
||||
+// TODO(ricea): Clean up the dependencies and remove this include.
|
||||
+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
+
|
||||
namespace blink {
|
||||
|
||||
class ExceptionState;
|
||||
-class ScriptValue;
|
||||
class ScriptState;
|
||||
+class WritableStreamDefaultController;
|
||||
|
||||
class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
@@ -38,12 +42,8 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
ScriptValue reason,
|
||||
ExceptionState&) = 0;
|
||||
|
||||
- ScriptPromise start(ScriptState* script_state,
|
||||
- ScriptValue controller,
|
||||
- ExceptionState& exception_state) {
|
||||
- controller_ = WritableStreamDefaultController::From(controller);
|
||||
- return start(script_state, controller_, exception_state);
|
||||
- }
|
||||
+ ScriptPromise start(ScriptState*, ScriptValue controller, ExceptionState&);
|
||||
+
|
||||
ScriptPromise write(ScriptState* script_state,
|
||||
ScriptValue chunk,
|
||||
ScriptValue controller,
|
||||
@@ -52,10 +52,11 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
return write(script_state, chunk, controller_, exception_state);
|
||||
}
|
||||
|
||||
- void Trace(Visitor* visitor) const override {
|
||||
- visitor->Trace(controller_);
|
||||
- ScriptWrappable::Trace(visitor);
|
||||
- }
|
||||
+ // Returns a JavaScript "undefined" value. This is required by the
|
||||
+ // WritableStream Create() method.
|
||||
+ ScriptValue type(ScriptState*) const;
|
||||
+
|
||||
+ void Trace(Visitor*) const override;
|
||||
|
||||
protected:
|
||||
WritableStreamDefaultController* Controller() const { return controller_; }
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.idl b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
index 8351141cbc07ed32566a0006f998aab61e8fd6b5..470eb527b11e3dce355d724eaa63ec981b7788e4 100644
|
||||
--- a/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
@@ -14,4 +14,7 @@ interface UnderlyingSinkBase {
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> write(any chunk, any controller);
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> close();
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> abort(any reason);
|
||||
+
|
||||
+ // This only exists to prevent Object.prototype.type being accessed.
|
||||
+ [CallWith=ScriptState] readonly attribute any type;
|
||||
};
|
||||
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
index 0b22eedcddc87b0ac695389a76ed5e353dd5f92c..bc959b6c33dbba6a367b4d247d56b67698299635 100644
|
||||
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
@@ -20,10 +20,14 @@
|
||||
namespace blink {
|
||||
|
||||
WritableStreamDefaultController* WritableStreamDefaultController::From(
|
||||
+ ScriptState* script_state,
|
||||
ScriptValue controller) {
|
||||
- DCHECK(controller.IsObject());
|
||||
- return V8WritableStreamDefaultController::ToImpl(
|
||||
- controller.V8Value().As<v8::Object>());
|
||||
+ CHECK(controller.IsObject());
|
||||
+ auto* controller_impl =
|
||||
+ V8WritableStreamDefaultController::ToImplWithTypeCheck(
|
||||
+ script_state->GetIsolate(), controller.V8Value().As<v8::Object>());
|
||||
+ CHECK(controller_impl);
|
||||
+ return controller_impl;
|
||||
}
|
||||
|
||||
// Only used internally. Not reachable from JavaScript.
|
||||
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
index 3351dcd6941360fc9fecaa8c03080da813a5b6a2..8be676421763caa911b8d003c869856675e28713 100644
|
||||
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
@@ -27,7 +27,7 @@ class CORE_EXPORT WritableStreamDefaultController final
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
|
||||
public:
|
||||
- static WritableStreamDefaultController* From(ScriptValue);
|
||||
+ static WritableStreamDefaultController* From(ScriptState*, ScriptValue);
|
||||
|
||||
// The JavaScript-exposed constructor throws automatically as no constructor
|
||||
// is specified in the IDL. This constructor is used internally during
|
||||
diff --git a/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fbbc26b08ea4e310ed99b7a02e1a7952e8f60921
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
|
||||
@@ -0,0 +1,57 @@
|
||||
+<!DOCTYPE html>
|
||||
+<meta charset="utf-8">
|
||||
+<script src="/resources/testharness.js"></script>
|
||||
+<script src="/resources/testharnessreport.js"></script>
|
||||
+<script>
|
||||
+'use strict';
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ throw Error();
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ // The WritableStream is created lazily, so access it to trigger creation.
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a throwing getter on Object.prototype.type should not interfere with ' +
|
||||
+ 'native writable stream creation');
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ this.start(0x414141);
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a getter that calls start() with a number on Object.prototype.type ' +
|
||||
+ 'should not interfere with native writable stream creation');
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ this.start({});
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a getter that calls start() with an object on Object.prototype.type ' +
|
||||
+ 'should not interfere with native writable stream creation');
|
||||
+
|
||||
+</script>
|
||||
115
patches/chromium/cherry-pick-f2fd53c6d706.patch
Normal file
115
patches/chromium/cherry-pick-f2fd53c6d706.patch
Normal file
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rayan Kanso <rayankans@google.com>
|
||||
Date: Tue, 7 Sep 2021 19:35:02 +0000
|
||||
Subject: Check whether the SW ID is valid for GetIds().
|
||||
|
||||
(cherry picked from commit d97b8b86be732448cbc57b47f6b46547c9866df3)
|
||||
|
||||
Bug: 1243622
|
||||
Change-Id: I93a40db0e71c7a087d279653e741800015232d7f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3135479
|
||||
Reviewed-by: Richard Knoll <knollr@chromium.org>
|
||||
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#917314}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3143705
|
||||
Reviewed-by: Rayan Kanso <rayankans@chromium.org>
|
||||
Commit-Queue: Richard Knoll <knollr@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#828}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc
|
||||
index 5a93282ec4bcae6c68cf19ff7bf60e5a5db47a86..8a9953859b56af33df739dfd37ad71f561e6dea8 100644
|
||||
--- a/content/browser/background_fetch/background_fetch_service_unittest.cc
|
||||
+++ b/content/browser/background_fetch/background_fetch_service_unittest.cc
|
||||
@@ -1115,12 +1115,8 @@ TEST_F(BackgroundFetchServiceTest, GetDeveloperIds) {
|
||||
std::vector<std::string> developer_ids;
|
||||
|
||||
GetDeveloperIds(service_worker_registration_id, &error, &developer_ids);
|
||||
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
|
||||
-
|
||||
- // TODO(crbug.com/850076): The Storage Worker Database access is not
|
||||
- // checking the origin. In a non-test environment this won't happen since a
|
||||
- // ServiceWorker registration ID is tied to the origin.
|
||||
- ASSERT_EQ(developer_ids.size(), 2u);
|
||||
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::STORAGE_ERROR);
|
||||
+ EXPECT_TRUE(developer_ids.empty());
|
||||
}
|
||||
|
||||
// Verify that using the wrong service worker id does not return developer ids
|
||||
@@ -1134,9 +1130,8 @@ TEST_F(BackgroundFetchServiceTest, GetDeveloperIds) {
|
||||
|
||||
GetDeveloperIds(bogus_service_worker_registration_id, &error,
|
||||
&developer_ids);
|
||||
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
|
||||
-
|
||||
- ASSERT_EQ(developer_ids.size(), 0u);
|
||||
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::STORAGE_ERROR);
|
||||
+ EXPECT_TRUE(developer_ids.empty());
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/content/browser/background_fetch/storage/get_developer_ids_task.cc b/content/browser/background_fetch/storage/get_developer_ids_task.cc
|
||||
index c7413fdab5413bae2eca8d4451d53856f7ba464e..7851f5ee07aea9036055578e7d72876bf42fefdc 100644
|
||||
--- a/content/browser/background_fetch/storage/get_developer_ids_task.cc
|
||||
+++ b/content/browser/background_fetch/storage/get_developer_ids_task.cc
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "base/bind.h"
|
||||
#include "content/browser/background_fetch/storage/database_helpers.h"
|
||||
#include "content/browser/service_worker/service_worker_context_wrapper.h"
|
||||
+#include "content/browser/service_worker/service_worker_registration.h"
|
||||
|
||||
namespace content {
|
||||
namespace background_fetch {
|
||||
@@ -26,6 +27,28 @@ GetDeveloperIdsTask::GetDeveloperIdsTask(
|
||||
GetDeveloperIdsTask::~GetDeveloperIdsTask() = default;
|
||||
|
||||
void GetDeveloperIdsTask::Start() {
|
||||
+ service_worker_context()->FindReadyRegistrationForIdOnly(
|
||||
+ service_worker_registration_id_,
|
||||
+ base::BindOnce(&GetDeveloperIdsTask::DidGetServiceWorkerRegistration,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
+}
|
||||
+
|
||||
+void GetDeveloperIdsTask::DidGetServiceWorkerRegistration(
|
||||
+ blink::ServiceWorkerStatusCode status,
|
||||
+ scoped_refptr<ServiceWorkerRegistration> registration) {
|
||||
+ if (ToDatabaseStatus(status) != DatabaseStatus::kOk || !registration) {
|
||||
+ SetStorageErrorAndFinish(
|
||||
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // TODO(crbug.com/1199077): Move this check into the SW context.
|
||||
+ if (registration->key() != storage_key_) {
|
||||
+ SetStorageErrorAndFinish(
|
||||
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
service_worker_context()->GetRegistrationUserKeysAndDataByKeyPrefix(
|
||||
service_worker_registration_id_, {kActiveRegistrationUniqueIdKeyPrefix},
|
||||
base::BindOnce(&GetDeveloperIdsTask::DidGetUniqueIds,
|
||||
diff --git a/content/browser/background_fetch/storage/get_developer_ids_task.h b/content/browser/background_fetch/storage/get_developer_ids_task.h
|
||||
index b5b3e8c4ab82ca46382e05464a7afe3dc3e5f3cc..e273ecfc622260cdf14aa7a0cf86410de3406fc9 100644
|
||||
--- a/content/browser/background_fetch/storage/get_developer_ids_task.h
|
||||
+++ b/content/browser/background_fetch/storage/get_developer_ids_task.h
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
|
||||
|
||||
namespace content {
|
||||
+
|
||||
+class ServiceWorkerRegistration;
|
||||
+
|
||||
namespace background_fetch {
|
||||
|
||||
// Gets the developer ids for all active registrations - registrations that have
|
||||
@@ -34,6 +37,9 @@ class GetDeveloperIdsTask : public DatabaseTask {
|
||||
void Start() override;
|
||||
|
||||
private:
|
||||
+ void DidGetServiceWorkerRegistration(
|
||||
+ blink::ServiceWorkerStatusCode status,
|
||||
+ scoped_refptr<ServiceWorkerRegistration> registration);
|
||||
void DidGetUniqueIds(
|
||||
blink::ServiceWorkerStatusCode status,
|
||||
const base::flat_map<std::string, std::string>& data_map);
|
||||
195
patches/chromium/cherry-pick-f781748dcb3c.patch
Normal file
195
patches/chromium/cherry-pick-f781748dcb3c.patch
Normal file
@@ -0,0 +1,195 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ravjit <ravjit@chromium.org>
|
||||
Date: Thu, 16 Sep 2021 12:29:55 +0000
|
||||
Subject: Show the origin of the last redirecting server in external protocol
|
||||
handler dialogs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
External protocol handlers always show the initiating url's origin. This can be misleading if there are server side redirects.
|
||||
Now we will show the origin of the last redirecting server (falling back to the request_initiator if there were no redirects / if the request goes straight to an external protocol).
|
||||
|
||||
Bug: 1197889
|
||||
Change-Id: I3cf7ccf3a8bd79d161364680a1871d1c88bec813
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3113931
|
||||
Commit-Queue: Ravjit Singh Uppal <ravjit@chromium.org>
|
||||
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Reviewed-by: Collin Baker <collinbaker@chromium.org>
|
||||
Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
|
||||
Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#922096}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
index 7e953fe89ff8dadf4da9578c0fdc6c3aada11aca..5c7e331ea4fbbcf36ac6463b37884cc9c6ca7e41 100644
|
||||
--- a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
+++ b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
@@ -14,11 +14,15 @@
|
||||
#include "chrome/browser/ui/test/test_browser_dialog.h"
|
||||
#include "chrome/browser/ui/views/external_protocol_dialog.h"
|
||||
#include "chrome/test/base/in_process_browser_test.h"
|
||||
+#include "chrome/test/base/ui_test_utils.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/test/browser_test.h"
|
||||
+#include "net/dns/mock_host_resolver.h"
|
||||
+#include "net/test/embedded_test_server/http_request.h"
|
||||
+#include "net/test/embedded_test_server/http_response.h"
|
||||
#include "ui/views/controls/button/checkbox.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@@ -41,6 +45,33 @@ class ExternalProtocolDialogTestApi {
|
||||
|
||||
} // namespace test
|
||||
|
||||
+namespace {
|
||||
+constexpr char kInitiatingOrigin[] = "a.test";
|
||||
+constexpr char kRedirectingOrigin[] = "b.test";
|
||||
+
|
||||
+class FakeDefaultProtocolClientWorker
|
||||
+ : public shell_integration::DefaultProtocolClientWorker {
|
||||
+ public:
|
||||
+ explicit FakeDefaultProtocolClientWorker(const std::string& protocol)
|
||||
+ : DefaultProtocolClientWorker(protocol) {}
|
||||
+ FakeDefaultProtocolClientWorker(const FakeDefaultProtocolClientWorker&) =
|
||||
+ delete;
|
||||
+ FakeDefaultProtocolClientWorker& operator=(
|
||||
+ const FakeDefaultProtocolClientWorker&) = delete;
|
||||
+
|
||||
+ private:
|
||||
+ ~FakeDefaultProtocolClientWorker() override = default;
|
||||
+ shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
|
||||
+ return shell_integration::DefaultWebClientState::NOT_DEFAULT;
|
||||
+ }
|
||||
+
|
||||
+ void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override {
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE, std::move(on_finished_callback));
|
||||
+ }
|
||||
+};
|
||||
+} // namespace
|
||||
+
|
||||
class ExternalProtocolDialogBrowserTest
|
||||
: public DialogBrowserTest,
|
||||
public ExternalProtocolHandler::Delegate {
|
||||
@@ -71,11 +102,11 @@ class ExternalProtocolDialogBrowserTest
|
||||
// ExternalProtocolHander::Delegate:
|
||||
scoped_refptr<shell_integration::DefaultProtocolClientWorker>
|
||||
CreateShellWorker(const std::string& protocol) override {
|
||||
- return nullptr;
|
||||
+ return base::MakeRefCounted<FakeDefaultProtocolClientWorker>(protocol);
|
||||
}
|
||||
ExternalProtocolHandler::BlockState GetBlockState(const std::string& scheme,
|
||||
Profile* profile) override {
|
||||
- return ExternalProtocolHandler::DONT_BLOCK;
|
||||
+ return ExternalProtocolHandler::UNKNOWN;
|
||||
}
|
||||
void BlockRequest() override {}
|
||||
void RunExternalProtocolDialog(
|
||||
@@ -83,7 +114,10 @@ class ExternalProtocolDialogBrowserTest
|
||||
content::WebContents* web_contents,
|
||||
ui::PageTransition page_transition,
|
||||
bool has_user_gesture,
|
||||
- const absl::optional<url::Origin>& initiating_origin) override {}
|
||||
+ const absl::optional<url::Origin>& initiating_origin) override {
|
||||
+ url_did_launch_ = true;
|
||||
+ launch_url_ = initiating_origin->host();
|
||||
+ }
|
||||
void LaunchUrlWithoutSecurityCheck(
|
||||
const GURL& url,
|
||||
content::WebContents* web_contents) override {
|
||||
@@ -98,6 +132,12 @@ class ExternalProtocolDialogBrowserTest
|
||||
blocked_state_ = state;
|
||||
}
|
||||
|
||||
+ void SetUpOnMainThread() override {
|
||||
+ DialogBrowserTest::SetUpOnMainThread();
|
||||
+ host_resolver()->AddRule(kInitiatingOrigin, "127.0.0.1");
|
||||
+ host_resolver()->AddRule(kRedirectingOrigin, "127.0.0.1");
|
||||
+ }
|
||||
+
|
||||
base::HistogramTester histogram_tester_;
|
||||
|
||||
protected:
|
||||
@@ -106,6 +146,7 @@ class ExternalProtocolDialogBrowserTest
|
||||
url::Origin blocked_origin_;
|
||||
BlockState blocked_state_ = BlockState::UNKNOWN;
|
||||
bool url_did_launch_ = false;
|
||||
+ std::string launch_url_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ExternalProtocolDialogBrowserTest);
|
||||
@@ -231,3 +272,21 @@ IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestFocus) {
|
||||
const views::View* focused_view = focus_manager->GetFocusedView();
|
||||
EXPECT_TRUE(focused_view);
|
||||
}
|
||||
+
|
||||
+IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, OriginNameTest) {
|
||||
+ ASSERT_TRUE(embedded_test_server()->Start());
|
||||
+ content::WebContents* web_contents =
|
||||
+ browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(
|
||||
+ browser(), embedded_test_server()->GetURL("a.test", "/empty.html")));
|
||||
+ EXPECT_TRUE(content::ExecJs(
|
||||
+ web_contents,
|
||||
+ content::JsReplace("location.href = $1",
|
||||
+ embedded_test_server()->GetURL(
|
||||
+ "b.test", "/server-redirect?ms-calc:"))));
|
||||
+ content::WaitForLoadStop(web_contents);
|
||||
+ EXPECT_TRUE(url_did_launch_);
|
||||
+ // The url should be the url of the last redirecting server and not of the
|
||||
+ // request initiator
|
||||
+ EXPECT_EQ(launch_url_, "b.test");
|
||||
+}
|
||||
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
|
||||
index 4d0c1a27449d5f88a4a88c915a3d741df42d4613..8174e746f76337716cdcbf6eba4fd54cacb12a0a 100644
|
||||
--- a/content/browser/loader/navigation_url_loader_impl.cc
|
||||
+++ b/content/browser/loader/navigation_url_loader_impl.cc
|
||||
@@ -621,6 +621,13 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
|
||||
if (known_schemes_.find(resource_request_->url.scheme()) ==
|
||||
known_schemes_.end()) {
|
||||
mojo::PendingRemote<network::mojom::URLLoaderFactory> loader_factory;
|
||||
+ absl::optional<url::Origin> initiating_origin;
|
||||
+ if (url_chain_.size() > 1) {
|
||||
+ initiating_origin =
|
||||
+ url::Origin::Create(url_chain_[url_chain_.size() - 2]);
|
||||
+ } else {
|
||||
+ initiating_origin = resource_request_->request_initiator;
|
||||
+ }
|
||||
bool handled = GetContentClient()->browser()->HandleExternalProtocol(
|
||||
resource_request_->url, web_contents_getter_,
|
||||
ChildProcessHost::kInvalidUniqueID, frame_tree_node_id_,
|
||||
@@ -628,8 +635,8 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
|
||||
resource_request_->resource_type ==
|
||||
static_cast<int>(blink::mojom::ResourceType::kMainFrame),
|
||||
static_cast<ui::PageTransition>(resource_request_->transition_type),
|
||||
- resource_request_->has_user_gesture,
|
||||
- resource_request_->request_initiator, &loader_factory);
|
||||
+ resource_request_->has_user_gesture, initiating_origin,
|
||||
+ &loader_factory);
|
||||
|
||||
if (loader_factory) {
|
||||
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index e07f51020fc2139a9757b8d52bd5f5a002e1c561..db802c5a3354e10567f3ab559168965add3cd59a 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -1754,10 +1754,12 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
// Otherwise child_id will be the process id and |navigation_ui_data| will be
|
||||
// nullptr.
|
||||
//
|
||||
- // |initiating_origin| is the origin that initiated the navigation to the
|
||||
- // external protocol, and may be null, e.g. in the case of browser-initiated
|
||||
- // navigations. The initiating origin is intended to help users make security
|
||||
- // decisions about whether to allow an external application to launch.
|
||||
+ // |initiating_origin| is the origin of the last redirecting server (falling
|
||||
+ // back to the request initiator if there were no redirects / if the request
|
||||
+ // goes straight to an external protocol, or null, e.g. in the case of
|
||||
+ // browser-initiated navigations. The initiating origin is intended to help
|
||||
+ // users make security decisions about whether to allow an external
|
||||
+ // application to launch.
|
||||
virtual bool HandleExternalProtocol(
|
||||
const GURL& url,
|
||||
base::RepeatingCallback<WebContents*()> web_contents_getter,
|
||||
138
patches/chromium/cleanup_pausablecriptexecutor_usage.patch
Normal file
138
patches/chromium/cleanup_pausablecriptexecutor_usage.patch
Normal file
@@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Tapuska <dtapuska@chromium.org>
|
||||
Date: Tue, 8 Feb 2022 15:58:40 +0000
|
||||
Subject: Cleanup PausablecriptExecutor usage.
|
||||
|
||||
Improve performance of API so we don't have to go from
|
||||
WTF::String->WebString->WTF::String for execution.
|
||||
|
||||
Ensure the Executor is traced via the PausableScriptExecutor.
|
||||
|
||||
BUG=1289384
|
||||
|
||||
(cherry picked from commit c8231f9a89460fd8336e6c0d8e10347f52f540ec)
|
||||
|
||||
Change-Id: If9badab91222c49c08a983c60132ce71b183e951
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3407654
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#963010}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3443262
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1109}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
index 08af6a3d5d457afa9f5ac4815f64cce1e520c9a4..8daa90b37b50f916a6ad82cefb81891acb9c4bdc 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
@@ -210,15 +210,16 @@ v8::MaybeLocal<v8::Value> CallMethodOnFrame(LocalFrame* local_frame,
|
||||
|
||||
// A wrapper class used as the callback for JavaScript executed
|
||||
// in an isolated world.
|
||||
-class JavaScriptIsolatedWorldRequest
|
||||
- : public GarbageCollected<JavaScriptIsolatedWorldRequest>,
|
||||
- public WebScriptExecutionCallback {
|
||||
+class JavaScriptIsolatedWorldRequest : public PausableScriptExecutor::Executor,
|
||||
+ public WebScriptExecutionCallback {
|
||||
using JavaScriptExecuteRequestInIsolatedWorldCallback =
|
||||
mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback;
|
||||
|
||||
public:
|
||||
JavaScriptIsolatedWorldRequest(
|
||||
LocalFrame* local_frame,
|
||||
+ int32_t world_id,
|
||||
+ const String& script,
|
||||
bool wants_result,
|
||||
mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback
|
||||
callback);
|
||||
@@ -228,27 +229,53 @@ class JavaScriptIsolatedWorldRequest
|
||||
const JavaScriptIsolatedWorldRequest&) = delete;
|
||||
~JavaScriptIsolatedWorldRequest() override;
|
||||
|
||||
- // WebScriptExecutionCallback:
|
||||
- void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
|
||||
+ // PausableScriptExecutor::Executor overrides.
|
||||
+ Vector<v8::Local<v8::Value>> Execute(LocalDOMWindow*) override;
|
||||
+
|
||||
+ void Trace(Visitor* visitor) const override;
|
||||
|
||||
- void Trace(Visitor* visitor) const { visitor->Trace(local_frame_); }
|
||||
+ // WebScriptExecutionCallback overrides.
|
||||
+ void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
|
||||
|
||||
private:
|
||||
Member<LocalFrame> local_frame_;
|
||||
+ int32_t world_id_;
|
||||
+ String script_;
|
||||
bool wants_result_;
|
||||
JavaScriptExecuteRequestInIsolatedWorldCallback callback_;
|
||||
};
|
||||
|
||||
JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest(
|
||||
LocalFrame* local_frame,
|
||||
+ int32_t world_id,
|
||||
+ const String& script,
|
||||
bool wants_result,
|
||||
JavaScriptExecuteRequestInIsolatedWorldCallback callback)
|
||||
: local_frame_(local_frame),
|
||||
+ world_id_(world_id),
|
||||
+ script_(script),
|
||||
wants_result_(wants_result),
|
||||
- callback_(std::move(callback)) {}
|
||||
+ callback_(std::move(callback)) {
|
||||
+ DCHECK_GT(world_id, DOMWrapperWorld::kMainWorldId);
|
||||
+}
|
||||
|
||||
JavaScriptIsolatedWorldRequest::~JavaScriptIsolatedWorldRequest() = default;
|
||||
|
||||
+void JavaScriptIsolatedWorldRequest::Trace(Visitor* visitor) const {
|
||||
+ PausableScriptExecutor::Executor::Trace(visitor);
|
||||
+ visitor->Trace(local_frame_);
|
||||
+}
|
||||
+
|
||||
+Vector<v8::Local<v8::Value>> JavaScriptIsolatedWorldRequest::Execute(
|
||||
+ LocalDOMWindow* window) {
|
||||
+ // Note: An error event in an isolated world will never be dispatched to
|
||||
+ // a foreign world.
|
||||
+ ClassicScript* classic_script = ClassicScript::CreateUnspecifiedScript(
|
||||
+ script_, SanitizeScriptErrors::kDoNotSanitize);
|
||||
+ return {classic_script->RunScriptInIsolatedWorldAndReturnValue(window,
|
||||
+ world_id_)};
|
||||
+}
|
||||
+
|
||||
void JavaScriptIsolatedWorldRequest::Completed(
|
||||
const WebVector<v8::Local<v8::Value>>& result) {
|
||||
base::Value value;
|
||||
@@ -268,7 +295,6 @@ void JavaScriptIsolatedWorldRequest::Completed(
|
||||
if (new_value)
|
||||
value = base::Value::FromUniquePtrValue(std::move(new_value));
|
||||
}
|
||||
-
|
||||
std::move(callback_).Run(std::move(value));
|
||||
}
|
||||
|
||||
@@ -849,13 +875,16 @@ void LocalFrameMojoHandler::JavaScriptExecuteRequestInIsolatedWorld(
|
||||
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
|
||||
scoped_refptr<DOMWrapperWorld> isolated_world =
|
||||
DOMWrapperWorld::EnsureIsolatedWorld(ToIsolate(frame_), world_id);
|
||||
- ScriptSourceCode source_code = ScriptSourceCode(javascript);
|
||||
- HeapVector<ScriptSourceCode> sources;
|
||||
- sources.Append(&source_code, 1);
|
||||
- auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
|
||||
- DomWindow(), std::move(isolated_world), sources, false /* user_gesture */,
|
||||
+
|
||||
+ // This member will be traced as the |executor| on the PausableScriptExector.
|
||||
+ auto* execution_request =
|
||||
MakeGarbageCollected<JavaScriptIsolatedWorldRequest>(
|
||||
- frame_, wants_result, std::move(callback)));
|
||||
+ frame_, world_id, javascript, wants_result, std::move(callback));
|
||||
+
|
||||
+ auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
|
||||
+ DomWindow(), ToScriptState(frame_, *isolated_world),
|
||||
+ /*callback=*/execution_request,
|
||||
+ /*executor=*/execution_request);
|
||||
executor->Run();
|
||||
}
|
||||
|
||||
38
patches/chromium/fix_aspect_ratio_with_max_size.patch
Normal file
38
patches/chromium/fix_aspect_ratio_with_max_size.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cezary Kulakowski <cezary@openfin.co>
|
||||
Date: Tue, 11 May 2021 11:14:06 +0200
|
||||
Subject: fix: fix aspect ratio when max width/height is set
|
||||
|
||||
Add the native frame border size to the minimum and maximum size if
|
||||
the view reports its size as the client size. It allows to enlarge
|
||||
window to proper values when aspect ratio and max width/height are
|
||||
set. It also fixes DCHECK which was triggered when user tried to
|
||||
enlarge window above dimensions set during creation of the
|
||||
BrowserWindow.
|
||||
|
||||
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
|
||||
index 41fa3c23b9a5d8596f2fb44d0957ab6e1f60a95a..e4c25788cf40e2b748cb25f004e448c0ea5f622c 100644
|
||||
--- a/ui/views/win/hwnd_message_handler.cc
|
||||
+++ b/ui/views/win/hwnd_message_handler.cc
|
||||
@@ -3569,6 +3569,21 @@ void HWNDMessageHandler::SizeWindowToAspectRatio(UINT param,
|
||||
delegate_->GetMinMaxSize(&min_window_size, &max_window_size);
|
||||
min_window_size = delegate_->DIPToScreenSize(min_window_size);
|
||||
max_window_size = delegate_->DIPToScreenSize(max_window_size);
|
||||
+ // Add the native frame border size to the minimum and maximum size if the
|
||||
+ // view reports its size as the client size.
|
||||
+ if (delegate_->WidgetSizeIsClientSize()) {
|
||||
+ RECT client_rect, rect;
|
||||
+ GetClientRect(hwnd(), &client_rect);
|
||||
+ GetWindowRect(hwnd(), &rect);
|
||||
+ CR_DEFLATE_RECT(&rect, &client_rect);
|
||||
+ min_window_size.Enlarge(rect.right - rect.left,
|
||||
+ rect.bottom - rect.top);
|
||||
+ // Either axis may be zero, so enlarge them independently.
|
||||
+ if (max_window_size.width())
|
||||
+ max_window_size.Enlarge(rect.right - rect.left, 0);
|
||||
+ if (max_window_size.height())
|
||||
+ max_window_size.Enlarge(0, rect.bottom - rect.top);
|
||||
+ }
|
||||
gfx::SizeRectToAspectRatio(GetWindowResizeEdge(param), aspect_ratio_.value(),
|
||||
min_window_size, max_window_size, window_rect);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Justin Novosad <junov@chromium.org>
|
||||
Date: Fri, 14 Jan 2022 15:26:55 +0000
|
||||
Subject: Fix ImageBitmapRenderingContext interaction with software compositor.
|
||||
|
||||
Before this CL, there was an early exit condition that prevented
|
||||
texture-backed resources from being presented to the software compositor
|
||||
even when the texture backing is swiftshader. This meant that in some
|
||||
cases, ImageBitmaps that were created by webGL contexts would fail to
|
||||
render. Once the early exit removed, there were other bugs due to the
|
||||
fact that bitmaps were not being converted to N32 format before being
|
||||
dispatched to the software compositor. This could cause several types
|
||||
of rendering artifacts, including leaking bitmap data between contexts.
|
||||
|
||||
BUG=1283434
|
||||
|
||||
Change-Id: I6f353bc6301b79d7a4124445c85956125135f539
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3387268
|
||||
Reviewed-by: Juanmi Huertas <juanmihd@chromium.org>
|
||||
Commit-Queue: Justin Novosad <junov@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#959192}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
|
||||
index 7b8f2b08249f298d4b3dc8deeb61638d199d3275..cd3c301bcf5d2eccb64fa46ceae63fbf92b0e952 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
|
||||
+++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
|
||||
@@ -136,13 +136,9 @@ bool ImageLayerBridge::PrepareTransferableResource(
|
||||
|
||||
has_presented_since_last_set_image_ = true;
|
||||
|
||||
- bool gpu_compositing = SharedGpuContext::IsGpuCompositingEnabled();
|
||||
+ const bool gpu_compositing = SharedGpuContext::IsGpuCompositingEnabled();
|
||||
bool gpu_image = image_->IsTextureBacked();
|
||||
|
||||
- // Expect software images for software compositing.
|
||||
- if (!gpu_compositing && gpu_image)
|
||||
- return false;
|
||||
-
|
||||
// If the texture comes from a software image then it does not need to be
|
||||
// flipped.
|
||||
layer_->SetFlipped(gpu_image);
|
||||
@@ -199,14 +195,17 @@ bool ImageLayerBridge::PrepareTransferableResource(
|
||||
return false;
|
||||
|
||||
const gfx::Size size(image_->width(), image_->height());
|
||||
- viz::ResourceFormat resource_format = viz::RGBA_8888;
|
||||
- if (sk_image->colorType() == SkColorType::kRGBA_F16_SkColorType)
|
||||
- resource_format = viz::RGBA_F16;
|
||||
+
|
||||
+ // Always convert to N32 format. This is a constraint of the software
|
||||
+ // compositor.
|
||||
+ constexpr SkColorType dst_color_type = kN32_SkColorType;
|
||||
+ viz::ResourceFormat resource_format =
|
||||
+ viz::SkColorTypeToResourceFormat(dst_color_type);
|
||||
RegisteredBitmap registered =
|
||||
CreateOrRecycleBitmap(size, resource_format, bitmap_registrar);
|
||||
|
||||
SkImageInfo dst_info =
|
||||
- SkImageInfo::Make(size.width(), size.height(), sk_image->colorType(),
|
||||
+ SkImageInfo::Make(size.width(), size.height(), dst_color_type,
|
||||
kPremul_SkAlphaType, sk_image->refColorSpace());
|
||||
void* pixels = registered.bitmap->memory();
|
||||
|
||||
@@ -235,8 +234,8 @@ ImageLayerBridge::RegisteredBitmap ImageLayerBridge::CreateOrRecycleBitmap(
|
||||
recycled_bitmaps_.begin(), recycled_bitmaps_.end(),
|
||||
[&size, &format](const RegisteredBitmap& registered) {
|
||||
unsigned src_bytes_per_pixel =
|
||||
- (registered.bitmap->format() == viz::RGBA_8888) ? 4 : 8;
|
||||
- unsigned target_bytes_per_pixel = (format == viz::RGBA_8888) ? 4 : 8;
|
||||
+ viz::BitsPerPixel(registered.bitmap->format()) / 8;
|
||||
+ unsigned target_bytes_per_pixel = viz::BitsPerPixel(format) / 8;
|
||||
return (registered.bitmap->size().GetArea() * src_bytes_per_pixel !=
|
||||
size.GetArea() * target_bytes_per_pixel);
|
||||
});
|
||||
diff --git a/third_party/blink/web_tests/fast/canvas/bug1283434-expected.html b/third_party/blink/web_tests/fast/canvas/bug1283434-expected.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d0046a6c5ede6804497107318650f5f452b0d5e2
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/fast/canvas/bug1283434-expected.html
|
||||
@@ -0,0 +1,11 @@
|
||||
+
|
||||
+<!doctype html>
|
||||
+<html>
|
||||
+<head>
|
||||
+</head>
|
||||
+<body>
|
||||
+<p>The two squares below should be filled in blue.</p>
|
||||
+<canvas id="c" width="100" height="100" style="background-color: #00f;"></canvas>
|
||||
+<canvas id="c2" width="100" height="100" style="background-color: #00f;"></canvas>
|
||||
+</body>
|
||||
+</html>
|
||||
\ No newline at end of file
|
||||
diff --git a/third_party/blink/web_tests/fast/canvas/bug1283434.html b/third_party/blink/web_tests/fast/canvas/bug1283434.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b07298cbcb356b7fb34e3923259c3365e3a976fb
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/fast/canvas/bug1283434.html
|
||||
@@ -0,0 +1,28 @@
|
||||
+
|
||||
+<!doctype html>
|
||||
+<html>
|
||||
+<head>
|
||||
+</head>
|
||||
+<body>
|
||||
+<p>The two squares below should be filled in blue.</p>
|
||||
+<canvas id="c" width="100" height="100" style="background-color: red;"></canvas>
|
||||
+<canvas id="c2" width="100" height="100" style="background-color: red;"></canvas>
|
||||
+<script>
|
||||
+ const canvas = document.getElementById('c');
|
||||
+ const canvas2 = document.getElementById('c2');
|
||||
+ const renderer = canvas.getContext('bitmaprenderer');
|
||||
+ const renderer2 = canvas2.getContext('2d');
|
||||
+
|
||||
+ const temp_canvas = new OffscreenCanvas(640, 480);
|
||||
+ const gl = temp_canvas.getContext('webgl');
|
||||
+
|
||||
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
|
||||
+ gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ const bitmap = temp_canvas.transferToImageBitmap();
|
||||
+
|
||||
+ renderer2.drawImage(bitmap, 0, 0);
|
||||
+ renderer.transferFromImageBitmap(bitmap);
|
||||
+</script>
|
||||
+</body>
|
||||
+</html>
|
||||
\ No newline at end of file
|
||||
@@ -10,33 +10,91 @@ receive remote control events until it begins playing audio. This runs
|
||||
counter to the design of globalShortcuts, and so we need to instead
|
||||
use `ui::MediaKeysListener`.
|
||||
|
||||
diff --git a/chrome/browser/extensions/global_shortcut_listener.cc b/chrome/browser/extensions/global_shortcut_listener.cc
|
||||
index bc009606d01469125052e68a9cdc82aaa697c764..ff18043cb07d748a49adea9874517fb29e3e7f9f 100644
|
||||
--- a/chrome/browser/extensions/global_shortcut_listener.cc
|
||||
+++ b/chrome/browser/extensions/global_shortcut_listener.cc
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "base/check.h"
|
||||
#include "base/notreached.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
+#include "content/public/browser/media_keys_listener_manager.h"
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
@@ -66,6 +67,22 @@ void GlobalShortcutListener::UnregisterAccelerator(
|
||||
StopListening();
|
||||
}
|
||||
|
||||
+// static
|
||||
+void GlobalShortcutListener::SetShouldUseInternalMediaKeyHandling(bool should_use) {
|
||||
+ if (content::MediaKeysListenerManager::
|
||||
+ IsMediaKeysListenerManagerEnabled()) {
|
||||
+ content::MediaKeysListenerManager* media_keys_listener_manager =
|
||||
+ content::MediaKeysListenerManager::GetInstance();
|
||||
+ DCHECK(media_keys_listener_manager);
|
||||
+
|
||||
+ if (should_use) {
|
||||
+ media_keys_listener_manager->EnableInternalMediaKeyHandling();
|
||||
+ } else {
|
||||
+ media_keys_listener_manager->DisableInternalMediaKeyHandling();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void GlobalShortcutListener::UnregisterAccelerators(Observer* observer) {
|
||||
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
if (IsShortcutHandlingSuspended())
|
||||
diff --git a/chrome/browser/extensions/global_shortcut_listener.h b/chrome/browser/extensions/global_shortcut_listener.h
|
||||
index 9aec54a3263d24491d24013a80b719dfc834ecd4..001a6cb2a5eb701351fa924109b43fab6f30748d 100644
|
||||
--- a/chrome/browser/extensions/global_shortcut_listener.h
|
||||
+++ b/chrome/browser/extensions/global_shortcut_listener.h
|
||||
@@ -31,6 +31,8 @@ class GlobalShortcutListener {
|
||||
|
||||
static GlobalShortcutListener* GetInstance();
|
||||
|
||||
+ static void SetShouldUseInternalMediaKeyHandling(bool should_use);
|
||||
+
|
||||
// Register an observer for when a certain |accelerator| is struck. Returns
|
||||
// true if register successfully, or false if 1) the specificied |accelerator|
|
||||
// has been registered by another caller or other native applications, or
|
||||
diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
index 5938f75742b793868638e693a9a8c8dc686dfc46..bf8782c23095a09dec62c68d7d902df24abcb13e 100644
|
||||
index 5938f75742b793868638e693a9a8c8dc686dfc46..afeca1ede732543c4769fe47e5b41a6444a3bf6f 100644
|
||||
--- a/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
+++ b/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
@@ -231,7 +231,7 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
|
||||
media::AudioManager::GetGlobalAppName());
|
||||
@@ -232,18 +232,26 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
|
||||
#endif
|
||||
|
||||
- if (system_media_controls_) {
|
||||
+ if (/* DISABLES CODE */ (0)) {
|
||||
if (system_media_controls_) {
|
||||
+ // This is required for proper functioning of MediaMetadata.
|
||||
system_media_controls_->AddObserver(this);
|
||||
system_media_controls_notifier_ =
|
||||
std::make_unique<SystemMediaControlsNotifier>(
|
||||
@@ -239,8 +239,13 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
|
||||
} else {
|
||||
// If we can't access system media controls, then directly listen for media
|
||||
// key keypresses instead.
|
||||
+#if defined(OS_MAC)
|
||||
+ media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
+ this, ui::MediaKeysListener::Scope::kGlobalRequiresAccessibility);
|
||||
+#else
|
||||
media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
+#endif
|
||||
DCHECK(media_keys_listener_);
|
||||
system_media_controls_.get());
|
||||
- } else {
|
||||
- // If we can't access system media controls, then directly listen for media
|
||||
- // key keypresses instead.
|
||||
- media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
- this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
- DCHECK(media_keys_listener_);
|
||||
}
|
||||
|
||||
+ // Directly listen for media key keypresses when using GlobalShortcuts.
|
||||
+#if defined(OS_MACOS)
|
||||
+ auto scope = media_key_handling_enabled_ ?
|
||||
+ ui::MediaKeysListener::Scope::kGlobal :
|
||||
+ ui::MediaKeysListener::Scope::kGlobalRequiresAccessibility;
|
||||
+ media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
+ this, scope);
|
||||
+#else
|
||||
+ media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
+ this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
+#endif
|
||||
+ DCHECK(media_keys_listener_);
|
||||
+
|
||||
EnsureAuxiliaryServices();
|
||||
}
|
||||
|
||||
diff --git a/ui/base/accelerators/media_keys_listener.h b/ui/base/accelerators/media_keys_listener.h
|
||||
index c2b03328c0e508995bdc135031500783f500ceba..1b6b14dc2999c99445cef6ffc04d49a7c1728a54 100644
|
||||
--- a/ui/base/accelerators/media_keys_listener.h
|
||||
|
||||
62
patches/chromium/introduce_crossthreadcopier_skbitmap.patch
Normal file
62
patches/chromium/introduce_crossthreadcopier_skbitmap.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Tue, 9 Nov 2021 05:02:50 +0000
|
||||
Subject: Introduce CrossThreadCopier<SkBitmap>
|
||||
|
||||
Allow immutable SkBitmap to be transferred across threads.
|
||||
|
||||
(cherry picked from commit fd794ad56432870e462aab9d62e4f059169c1a5f)
|
||||
|
||||
Bug: 1241091
|
||||
Change-Id: Ia771893245ef2fc1acb05cd4906d64bf2dd406fe
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3244824
|
||||
Reviewed-by: danakj <danakj@chromium.org>
|
||||
Reviewed-by: Florin Malita <fmalita@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936435}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3267808
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#887}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
index 997893fef2caee37b65e8ca6dfe9ca7b81302f98..3bd49cac3f5dfcad0fcc1140fcf876fe37558930 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
@@ -39,7 +39,9 @@
|
||||
#include "third_party/blink/renderer/platform/graphics/image.h"
|
||||
#include "third_party/blink/renderer/platform/platform_export.h"
|
||||
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
|
||||
+#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "third_party/skia/include/core/SkData.h"
|
||||
@@ -197,4 +199,25 @@ PLATFORM_EXPORT sk_sp<SkData> TryAllocateSkData(size_t size);
|
||||
|
||||
} // namespace blink
|
||||
|
||||
+namespace WTF {
|
||||
+
|
||||
+// We define CrossThreadCopier<SKBitMap> here because we cannot include skia
|
||||
+// headers in platform/wtf.
|
||||
+template <>
|
||||
+struct CrossThreadCopier<SkBitmap> {
|
||||
+ STATIC_ONLY(CrossThreadCopier);
|
||||
+
|
||||
+ using Type = SkBitmap;
|
||||
+ static SkBitmap Copy(const SkBitmap& bitmap) {
|
||||
+ CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ return bitmap;
|
||||
+ }
|
||||
+ static SkBitmap Copy(SkBitmap&& bitmap) {
|
||||
+ CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ return std::move(bitmap);
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+} // namespace WTF
|
||||
+
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_SKIA_UTILS_H_
|
||||
@@ -0,0 +1,227 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Erik Chen <erikchen@chromium.org>
|
||||
Date: Fri, 1 Oct 2021 12:44:24 +0000
|
||||
Subject: Prevents non-browser processes from requesting memory dumps.
|
||||
|
||||
This CL makes several changes:
|
||||
|
||||
(1) Causes the browser to reset non-browser
|
||||
mojo::PendingReceiver<Coordinator>. This means that non-browser
|
||||
processes will never be able to use the Coordinator interface.
|
||||
|
||||
(2) Add CHECKs to existing code to prevent non-browser processes from
|
||||
attempting to use the Coordinator interface.
|
||||
|
||||
A code audit shows that all Coordinator usages should already only be
|
||||
from the browser process.
|
||||
|
||||
Note that (2) is important since attempting to use an unbound interface
|
||||
will trigger a nullptr dereference, which is undefined behavior.
|
||||
|
||||
(cherry picked from commit d9cc471e122e9a2391a68fa7cd72ea50587d8d97)
|
||||
|
||||
Bug: 1251787
|
||||
Change-Id: Ifbe9610cc0e373edaaa60fad46b447e8bdb3ec04
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3174305
|
||||
Auto-Submit: Erik Chen <erikchen@chromium.org>
|
||||
Commit-Queue: Erik Chen <erikchen@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#923693}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3197813
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Owners-Override: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4430@{#1631}
|
||||
Cr-Branched-From: e5ce7dc4f7518237b3d9bb93cccca35d25216cbe-refs/heads/master@{#857950}
|
||||
|
||||
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
|
||||
index 9a836207989b19ae041a3ec700b55185d63f9a4c..ed1d10aae4470c9aac28cfce67d97f351b8266d5 100644
|
||||
--- a/content/browser/browser_child_process_host_impl.cc
|
||||
+++ b/content/browser/browser_child_process_host_impl.cc
|
||||
@@ -708,6 +708,9 @@ void BrowserChildProcessHostImpl::RegisterCoordinatorClient(
|
||||
mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
|
||||
client_process) {
|
||||
+ // Intentionally disallow non-browser processes from getting a Coordinator.
|
||||
+ receiver.reset();
|
||||
+
|
||||
// The child process may have already terminated by the time this message is
|
||||
// dispatched. We do nothing in that case.
|
||||
if (!IsProcessLaunched())
|
||||
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
index bd24cb0f6edc37bf23c40f0a7839a2f5d85c9a01..09d883fba5167ea254e8e463bb6e79026bf61f50 100644
|
||||
--- a/content/browser/renderer_host/render_process_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
@@ -2860,6 +2860,9 @@ void RenderProcessHostImpl::RegisterCoordinatorClient(
|
||||
mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
|
||||
client_process) {
|
||||
+ // Intentionally disallow non-browser processes from getting a Coordinator.
|
||||
+ receiver.reset();
|
||||
+
|
||||
if (!GetProcess().IsValid()) {
|
||||
// If the process dies before we get this message. we have no valid PID
|
||||
// and there's nothing to register.
|
||||
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
|
||||
index 741e35dc3df4f2e6b73a8873b034bd9fc7fdc6cc..0f4551f6c4f6cc6d3285149411d851936dda3c8c 100644
|
||||
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
|
||||
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
|
||||
@@ -105,7 +105,8 @@ void CoordinatorImpl::RegisterClientProcess(
|
||||
const absl::optional<std::string>& service_name) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
mojo::Remote<mojom::ClientProcess> process(std::move(client_process));
|
||||
- coordinator_receivers_.Add(this, std::move(receiver), process_id);
|
||||
+ if (receiver.is_valid())
|
||||
+ coordinator_receivers_.Add(this, std::move(receiver), process_id);
|
||||
process.set_disconnect_handler(
|
||||
base::BindOnce(&CoordinatorImpl::UnregisterClientProcess,
|
||||
base::Unretained(this), process_id));
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
|
||||
index fea3e999ee0c624948445421829a731879c4fe74..1afe539a08287a81cd2590a2c4901fa528a37df3 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
|
||||
@@ -24,6 +24,11 @@ void ClientProcessImpl::CreateInstance(
|
||||
mojo::PendingReceiver<mojom::ClientProcess> receiver,
|
||||
mojo::PendingRemote<mojom::Coordinator> coordinator,
|
||||
bool is_browser_process) {
|
||||
+ // Intentionally disallow non-browser processes from ever holding a
|
||||
+ // Coordinator.
|
||||
+ if (!is_browser_process)
|
||||
+ coordinator.reset();
|
||||
+
|
||||
static ClientProcessImpl* instance = nullptr;
|
||||
if (!instance) {
|
||||
instance = new ClientProcessImpl(
|
||||
@@ -39,10 +44,12 @@ ClientProcessImpl::ClientProcessImpl(
|
||||
mojo::PendingRemote<mojom::Coordinator> coordinator,
|
||||
bool is_browser_process,
|
||||
bool initialize_memory_instrumentation)
|
||||
- : receiver_(this, std::move(receiver)) {
|
||||
+ : receiver_(this, std::move(receiver)),
|
||||
+ is_browser_process_(is_browser_process) {
|
||||
if (initialize_memory_instrumentation) {
|
||||
// Initialize the public-facing MemoryInstrumentation helper.
|
||||
- MemoryInstrumentation::CreateInstance(std::move(coordinator));
|
||||
+ MemoryInstrumentation::CreateInstance(std::move(coordinator),
|
||||
+ is_browser_process);
|
||||
} else {
|
||||
coordinator_.Bind(std::move(coordinator));
|
||||
}
|
||||
@@ -110,6 +117,8 @@ void ClientProcessImpl::OnChromeMemoryDumpDone(
|
||||
void ClientProcessImpl::RequestGlobalMemoryDump_NoCallback(
|
||||
base::trace_event::MemoryDumpType dump_type,
|
||||
base::trace_event::MemoryDumpLevelOfDetail level_of_detail) {
|
||||
+ CHECK(is_browser_process_);
|
||||
+
|
||||
if (!task_runner_->RunsTasksInCurrentSequence()) {
|
||||
task_runner_->PostTask(
|
||||
FROM_HERE,
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
|
||||
index d41651d9bef7bbc8ec1685e68cfd77993f0d4551..aef7f5a03091a0c42168cb2154edabf41d28d829 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
|
||||
@@ -96,6 +96,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
|
||||
mojo::Remote<mojom::Coordinator> coordinator_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
+ // Only browser process is allowed to request memory dumps.
|
||||
+ const bool is_browser_process_;
|
||||
+
|
||||
// TODO(crbug.com/728199): The observer is only used to setup and tear down
|
||||
// MemoryDumpManager in each process. Setting up MemoryDumpManager should
|
||||
// be moved away from TracingObserver.
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
|
||||
index c81d5f83bf9e1ad5e7a77d7c187fa33bd02812d5..ec90ab9211ede586d441f40e3e2bc2c820658fb1 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
|
||||
@@ -21,10 +21,11 @@ void WrapGlobalMemoryDump(
|
||||
|
||||
// static
|
||||
void MemoryInstrumentation::CreateInstance(
|
||||
- mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
|
||||
- coordinator) {
|
||||
+ mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator,
|
||||
+ bool is_browser_process) {
|
||||
DCHECK(!g_instance);
|
||||
- g_instance = new MemoryInstrumentation(std::move(coordinator));
|
||||
+ g_instance =
|
||||
+ new MemoryInstrumentation(std::move(coordinator), is_browser_process);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -33,8 +34,10 @@ MemoryInstrumentation* MemoryInstrumentation::GetInstance() {
|
||||
}
|
||||
|
||||
MemoryInstrumentation::MemoryInstrumentation(
|
||||
- mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator)
|
||||
- : coordinator_(std::move(coordinator)) {}
|
||||
+ mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator,
|
||||
+ bool is_browser_process)
|
||||
+ : coordinator_(std::move(coordinator)),
|
||||
+ is_browser_process_(is_browser_process) {}
|
||||
|
||||
MemoryInstrumentation::~MemoryInstrumentation() {
|
||||
g_instance = nullptr;
|
||||
@@ -43,6 +46,7 @@ MemoryInstrumentation::~MemoryInstrumentation() {
|
||||
void MemoryInstrumentation::RequestGlobalDump(
|
||||
const std::vector<std::string>& allocator_dump_names,
|
||||
RequestGlobalDumpCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestGlobalMemoryDump(
|
||||
MemoryDumpType::SUMMARY_ONLY, MemoryDumpLevelOfDetail::BACKGROUND,
|
||||
MemoryDumpDeterminism::NONE, allocator_dump_names,
|
||||
@@ -52,6 +56,7 @@ void MemoryInstrumentation::RequestGlobalDump(
|
||||
void MemoryInstrumentation::RequestPrivateMemoryFootprint(
|
||||
base::ProcessId pid,
|
||||
RequestGlobalDumpCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestPrivateMemoryFootprint(
|
||||
pid, base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
|
||||
}
|
||||
@@ -60,6 +65,7 @@ void MemoryInstrumentation::RequestGlobalDumpForPid(
|
||||
base::ProcessId pid,
|
||||
const std::vector<std::string>& allocator_dump_names,
|
||||
RequestGlobalDumpCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestGlobalMemoryDumpForPid(
|
||||
pid, allocator_dump_names,
|
||||
base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
|
||||
@@ -70,6 +76,7 @@ void MemoryInstrumentation::RequestGlobalDumpAndAppendToTrace(
|
||||
MemoryDumpLevelOfDetail level_of_detail,
|
||||
MemoryDumpDeterminism determinism,
|
||||
RequestGlobalMemoryDumpAndAppendToTraceCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestGlobalMemoryDumpAndAppendToTrace(
|
||||
dump_type, level_of_detail, determinism, std::move(callback));
|
||||
}
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
|
||||
index 3264917890cc30179c4477657158fd359a9d1e01..72157b5345fb003452f67045e2b2c984e748958a 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
|
||||
@@ -34,7 +34,8 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
|
||||
|
||||
static void CreateInstance(
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
|
||||
- coordinator);
|
||||
+ coordinator,
|
||||
+ bool is_browser_process);
|
||||
static MemoryInstrumentation* GetInstance();
|
||||
|
||||
// Retrieves a Coordinator interface to communicate with the service. This is
|
||||
@@ -100,12 +101,16 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
|
||||
private:
|
||||
explicit MemoryInstrumentation(
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
|
||||
- coordinator);
|
||||
+ coordinator,
|
||||
+ bool is_browser_process);
|
||||
~MemoryInstrumentation();
|
||||
|
||||
const mojo::SharedRemote<memory_instrumentation::mojom::Coordinator>
|
||||
coordinator_;
|
||||
|
||||
+ // Only browser process is allowed to request memory dumps.
|
||||
+ const bool is_browser_process_;
|
||||
+
|
||||
DISALLOW_COPY_AND_ASSIGN(MemoryInstrumentation);
|
||||
};
|
||||
|
||||
1863
patches/chromium/m96-lts_roll_libxml_from_dea91c97_to_eab86522.patch
Normal file
1863
patches/chromium/m96-lts_roll_libxml_from_dea91c97_to_eab86522.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,420 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Date: Tue, 16 Nov 2021 22:16:15 +0000
|
||||
Subject: M96: [FileAPI] Move origin checks in BlobURLStore sooner.
|
||||
|
||||
Rather than waiting to verify if a valid origin was passed in until
|
||||
register/revoke time, check if the origin is valid at the time the
|
||||
mojo interface is requested. This avoids the need to pass the
|
||||
delegate on to BlobURLStoreImpl, further decoupling this from
|
||||
BlobRegistryImpl.
|
||||
|
||||
(cherry picked from commit 15cfa2bed3ce9dcdd0a06d3cd3b8330e3591acdc)
|
||||
|
||||
Bug: 1262183
|
||||
Change-Id: I4889685d03501158abfe4f87c647dc468d005f78
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3264353
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940015}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3285385
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1078}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
index ca2f5cbbaa845d281b44e60ff93e0ba536961d24..8be1504b801e6690d94d7e68fcd4f3b0e43e9862 100644
|
||||
--- a/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
+++ b/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
@@ -483,8 +483,8 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
|
||||
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
- "Received bad user message: Non committable URL passed to "
|
||||
- "BlobURLStore::Register",
|
||||
+ "Received bad user message: "
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
|
||||
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
- "Received bad user message: Non committable URL passed to "
|
||||
- "BlobURLStore::Register",
|
||||
+ "Received bad user message: "
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc
|
||||
index 317ce6c282abc81f472b7c911d9a2eabdb86a1d4..66360f2ab627f85935734320ab6ac402d5fe4bd5 100644
|
||||
--- a/content/browser/blob_storage/blob_url_unittest.cc
|
||||
+++ b/content/browser/blob_storage/blob_url_unittest.cc
|
||||
@@ -184,15 +184,14 @@ class BlobURLTest : public testing::Test {
|
||||
|
||||
void TestRequest(const std::string& method,
|
||||
const net::HttpRequestHeaders& extra_headers) {
|
||||
- GURL url("blob:blah");
|
||||
+ auto origin = url::Origin::Create(GURL("https://example.com"));
|
||||
+ auto url = GURL("blob:" + origin.Serialize() + "/id1");
|
||||
network::ResourceRequest request;
|
||||
request.url = url;
|
||||
request.method = method;
|
||||
request.headers = extra_headers;
|
||||
|
||||
- storage::MockBlobRegistryDelegate delegate;
|
||||
- storage::BlobURLStoreImpl url_store(blob_url_registry_.AsWeakPtr(),
|
||||
- &delegate);
|
||||
+ storage::BlobURLStoreImpl url_store(origin, blob_url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob_remote;
|
||||
storage::BlobImpl::Create(
|
||||
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
|
||||
index 5073d38cef7124b7ca1d0b38da2fcdc8683e45fb..eb5cb552c4e5d71cae2958c93d99645ce3d040b2 100644
|
||||
--- a/content/browser/security_exploit_browsertest.cc
|
||||
+++ b/content/browser/security_exploit_browsertest.cc
|
||||
@@ -782,7 +782,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestMojoBlobURLs,
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
"Received bad user message: "
|
||||
- "Non committable URL passed to BlobURLStore::Register",
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
|
||||
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
|
||||
index c01eb0635324a171a64c6c13b4ef7288b3f5de45..7c7686309f799f25ce30ec1dc18c75e608829ee2 100644
|
||||
--- a/storage/browser/blob/blob_registry_impl.cc
|
||||
+++ b/storage/browser/blob/blob_registry_impl.cc
|
||||
@@ -634,13 +634,14 @@ void BlobRegistryImpl::GetBlobFromUUID(
|
||||
void BlobRegistryImpl::URLStoreForOrigin(
|
||||
const url::Origin& origin,
|
||||
mojo::PendingAssociatedReceiver<blink::mojom::BlobURLStore> receiver) {
|
||||
- // TODO(mek): Pass origin on to BlobURLStoreImpl so it can use it to generate
|
||||
- // Blob URLs, and verify at this point that the renderer can create URLs for
|
||||
- // that origin.
|
||||
Delegate* delegate = receivers_.current_context().get();
|
||||
DCHECK(delegate);
|
||||
+ if (!origin.opaque() && !delegate->CanCommitURL(origin.GetURL())) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ "Non committable origin passed to BlobRegistryImpl::URLStoreForOrigin");
|
||||
+ }
|
||||
auto self_owned_associated_receiver = mojo::MakeSelfOwnedAssociatedReceiver(
|
||||
- std::make_unique<BlobURLStoreImpl>(url_registry_, delegate),
|
||||
+ std::make_unique<BlobURLStoreImpl>(origin, url_registry_),
|
||||
std::move(receiver));
|
||||
if (g_url_store_creation_hook)
|
||||
g_url_store_creation_hook->Run(self_owned_associated_receiver);
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc
|
||||
index b46ee60849c9b758e022d7e576de61b080fd59f5..d4edd988f5982788f5157d27fbfa31abcb1eede7 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl.cc
|
||||
+++ b/storage/browser/blob/blob_url_store_impl.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "storage/browser/blob/blob_url_store_impl.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
+#include "base/strings/strcat.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "storage/browser/blob/blob_impl.h"
|
||||
#include "storage/browser/blob/blob_url_loader_factory.h"
|
||||
@@ -58,9 +59,9 @@ class BlobURLTokenImpl : public blink::mojom::BlobURLToken {
|
||||
const base::UnguessableToken token_;
|
||||
};
|
||||
|
||||
-BlobURLStoreImpl::BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
|
||||
- BlobRegistryImpl::Delegate* delegate)
|
||||
- : registry_(std::move(registry)), delegate_(delegate) {}
|
||||
+BlobURLStoreImpl::BlobURLStoreImpl(const url::Origin& origin,
|
||||
+ base::WeakPtr<BlobUrlRegistry> registry)
|
||||
+ : origin_(origin), registry_(std::move(registry)) {}
|
||||
|
||||
BlobURLStoreImpl::~BlobURLStoreImpl() {
|
||||
if (registry_) {
|
||||
@@ -72,20 +73,9 @@ BlobURLStoreImpl::~BlobURLStoreImpl() {
|
||||
void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob,
|
||||
const GURL& url,
|
||||
RegisterCallback callback) {
|
||||
- if (!url.SchemeIsBlob()) {
|
||||
- mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Register");
|
||||
- std::move(callback).Run();
|
||||
- return;
|
||||
- }
|
||||
- if (!delegate_->CanCommitURL(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "Non committable URL passed to BlobURLStore::Register");
|
||||
- std::move(callback).Run();
|
||||
- return;
|
||||
- }
|
||||
- if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "URL with fragment passed to BlobURLStore::Register");
|
||||
+ // TODO(mek): Generate blob URLs here, rather than validating the URLs the
|
||||
+ // renderer process generated.
|
||||
+ if (!BlobUrlIsValid(url, "Register")) {
|
||||
std::move(callback).Run();
|
||||
return;
|
||||
}
|
||||
@@ -97,19 +87,8 @@ void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob,
|
||||
}
|
||||
|
||||
void BlobURLStoreImpl::Revoke(const GURL& url) {
|
||||
- if (!url.SchemeIsBlob()) {
|
||||
- mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Revoke");
|
||||
- return;
|
||||
- }
|
||||
- if (!delegate_->CanCommitURL(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "Non committable URL passed to BlobURLStore::Revoke");
|
||||
+ if (!BlobUrlIsValid(url, "Revoke"))
|
||||
return;
|
||||
- }
|
||||
- if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
- mojo::ReportBadMessage("URL with fragment passed to BlobURLStore::Revoke");
|
||||
- return;
|
||||
- }
|
||||
|
||||
if (registry_)
|
||||
registry_->RemoveUrlMapping(url);
|
||||
@@ -144,4 +123,38 @@ void BlobURLStoreImpl::ResolveForNavigation(
|
||||
new BlobURLTokenImpl(registry_, url, std::move(blob), std::move(token));
|
||||
}
|
||||
|
||||
+bool BlobURLStoreImpl::BlobUrlIsValid(const GURL& url,
|
||||
+ const char* method) const {
|
||||
+ if (!url.SchemeIsBlob()) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ base::StrCat({"Invalid scheme passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ url::Origin url_origin = url::Origin::Create(url);
|
||||
+ // For file:// origins blink sometimes creates blob URLs with "null" as origin
|
||||
+ // and other times "file://" (based on a runtime setting). On the other hand,
|
||||
+ // `origin_` will always be a non-opaque file: origin for pages loaded from
|
||||
+ // file:// URLs. To deal with this, we treat file:// origins and
|
||||
+ // opaque origins separately from non-opaque origins.
|
||||
+ bool valid_origin = true;
|
||||
+ if (url_origin.scheme() == url::kFileScheme) {
|
||||
+ valid_origin = origin_.scheme() == url::kFileScheme;
|
||||
+ } else if (url_origin.opaque()) {
|
||||
+ valid_origin = origin_.opaque() || origin_.scheme() == url::kFileScheme;
|
||||
+ } else {
|
||||
+ valid_origin = origin_ == url_origin;
|
||||
+ }
|
||||
+ if (!valid_origin) {
|
||||
+ mojo::ReportBadMessage(base::StrCat(
|
||||
+ {"URL with invalid origin passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ base::StrCat({"URL with fragment passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
} // namespace storage
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl.h b/storage/browser/blob/blob_url_store_impl.h
|
||||
index 6b4a738a4646f8d8e35e8bb1be5aba391e612917..5db371d7c6d50520d8b40a3b4cb6d6bbf920b570 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl.h
|
||||
+++ b/storage/browser/blob/blob_url_store_impl.h
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
-#include "storage/browser/blob/blob_registry_impl.h"
|
||||
+#include "storage/browser/blob/blob_url_registry.h"
|
||||
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
|
||||
+#include "url/origin.h"
|
||||
|
||||
namespace storage {
|
||||
|
||||
@@ -21,8 +22,9 @@ class BlobUrlRegistry;
|
||||
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
|
||||
: public blink::mojom::BlobURLStore {
|
||||
public:
|
||||
- BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
|
||||
- BlobRegistryImpl::Delegate* delegate);
|
||||
+ BlobURLStoreImpl(const url::Origin& origin,
|
||||
+ base::WeakPtr<BlobUrlRegistry> registry);
|
||||
+
|
||||
~BlobURLStoreImpl() override;
|
||||
|
||||
void Register(mojo::PendingRemote<blink::mojom::Blob> blob,
|
||||
@@ -39,8 +41,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
|
||||
mojo::PendingReceiver<blink::mojom::BlobURLToken> token) override;
|
||||
|
||||
private:
|
||||
+ // Checks if the passed in url is a valid blob url for this blob url store.
|
||||
+ // Returns false and reports a bad mojo message if not.
|
||||
+ bool BlobUrlIsValid(const GURL& url, const char* method) const;
|
||||
+
|
||||
+ const url::Origin origin_;
|
||||
base::WeakPtr<BlobUrlRegistry> registry_;
|
||||
- BlobRegistryImpl::Delegate* delegate_;
|
||||
|
||||
std::set<GURL> urls_;
|
||||
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
index b81232212472036878e0918523be17bb2c2a8b8a..4244890c48240769b1333492bb870420fa26b869 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
+++ b/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "storage/browser/blob/blob_impl.h"
|
||||
#include "storage/browser/blob/blob_storage_context.h"
|
||||
#include "storage/browser/blob/blob_url_registry.h"
|
||||
-#include "storage/browser/test/mock_blob_registry_delegate.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
using blink::mojom::BlobURLStore;
|
||||
@@ -70,9 +69,9 @@ class BlobURLStoreImplTest : public testing::Test {
|
||||
|
||||
mojo::PendingRemote<BlobURLStore> CreateURLStore() {
|
||||
mojo::PendingRemote<BlobURLStore> result;
|
||||
- mojo::MakeSelfOwnedReceiver(std::make_unique<BlobURLStoreImpl>(
|
||||
- url_registry_.AsWeakPtr(), &delegate_),
|
||||
- result.InitWithNewPipeAndPassReceiver());
|
||||
+ mojo::MakeSelfOwnedReceiver(
|
||||
+ std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr()),
|
||||
+ result.InitWithNewPipeAndPassReceiver());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -102,15 +101,19 @@ class BlobURLStoreImplTest : public testing::Test {
|
||||
}
|
||||
|
||||
const std::string kId = "id";
|
||||
- const GURL kValidUrl = GURL("blob:id");
|
||||
+ const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
|
||||
+ const GURL kValidUrl = GURL("blob:" + kOrigin.Serialize() + "/id1");
|
||||
+ const GURL kValidUrl2 = GURL("blob:" + kOrigin.Serialize() + "/id2");
|
||||
const GURL kInvalidUrl = GURL("bolb:id");
|
||||
- const GURL kFragmentUrl = GURL("blob:id#fragment");
|
||||
+ const GURL kFragmentUrl = GURL(kValidUrl.spec() + "#fragment");
|
||||
+ const url::Origin kWrongOrigin =
|
||||
+ url::Origin::Create(GURL("https://test.com"));
|
||||
+ const GURL kWrongOriginUrl = GURL("blob:" + kWrongOrigin.Serialize() + "/id");
|
||||
|
||||
protected:
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
std::unique_ptr<BlobStorageContext> context_;
|
||||
BlobUrlRegistry url_registry_;
|
||||
- MockBlobRegistryDelegate delegate_;
|
||||
std::vector<std::string> bad_messages_;
|
||||
};
|
||||
|
||||
@@ -119,7 +122,7 @@ TEST_F(BlobURLStoreImplTest, BasicRegisterRevoke) {
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
// Register a URL and make sure the URL keeps the blob alive.
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
blob = url_registry_.GetBlobFromUrl(kValidUrl);
|
||||
@@ -147,15 +150,13 @@ TEST_F(BlobURLStoreImplTest, RegisterInvalidScheme) {
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
-TEST_F(BlobURLStoreImplTest, RegisterCantCommit) {
|
||||
+TEST_F(BlobURLStoreImplTest, RegisterWrongOrigin) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- delegate_.can_commit_url_result = false;
|
||||
-
|
||||
mojo::Remote<BlobURLStore> url_store(CreateURLStore());
|
||||
- RegisterURL(url_store.get(), std::move(blob), kValidUrl);
|
||||
- EXPECT_FALSE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
+ RegisterURL(url_store.get(), std::move(blob), kWrongOriginUrl);
|
||||
+ EXPECT_FALSE(url_registry_.GetBlobFromUrl(kWrongOriginUrl));
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
@@ -170,14 +171,13 @@ TEST_F(BlobURLStoreImplTest, RegisterUrlFragment) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ImplicitRevoke) {
|
||||
- const GURL kValidUrl2("blob:id2");
|
||||
mojo::Remote<blink::mojom::Blob> blob(
|
||||
CreateBlobFromString(kId, "hello world"));
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob2;
|
||||
blob->Clone(blob2.InitWithNewPipeAndPassReceiver());
|
||||
|
||||
auto url_store =
|
||||
- std::make_unique<BlobURLStoreImpl>(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(url_store.get(), blob.Unbind(), kValidUrl);
|
||||
EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
RegisterURL(url_store.get(), std::move(blob2), kValidUrl2);
|
||||
@@ -193,8 +193,8 @@ TEST_F(BlobURLStoreImplTest, RevokeThroughDifferentURLStore) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store1(url_registry_.AsWeakPtr(), &delegate_);
|
||||
- BlobURLStoreImpl url_store2(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store1(kOrigin, url_registry_.AsWeakPtr());
|
||||
+ BlobURLStoreImpl url_store2(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
RegisterURL(&url_store1, std::move(blob), kValidUrl);
|
||||
EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
@@ -210,11 +210,9 @@ TEST_F(BlobURLStoreImplTest, RevokeInvalidScheme) {
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
-TEST_F(BlobURLStoreImplTest, RevokeCantCommit) {
|
||||
- delegate_.can_commit_url_result = false;
|
||||
-
|
||||
+TEST_F(BlobURLStoreImplTest, RevokeWrongOrigin) {
|
||||
mojo::Remote<BlobURLStore> url_store(CreateURLStore());
|
||||
- url_store->Revoke(kValidUrl);
|
||||
+ url_store->Revoke(kWrongOriginUrl);
|
||||
url_store.FlushForTesting();
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
@@ -230,7 +228,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
blob = ResolveURL(&url_store, kValidUrl);
|
||||
@@ -245,7 +243,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
ResolveURL(&url_store, kValidUrl);
|
||||
@@ -255,7 +253,7 @@ TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ResolveInvalidURL) {
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
ResolveURL(&url_store, kInvalidUrl);
|
||||
@@ -266,7 +264,7 @@ TEST_F(BlobURLStoreImplTest, ResolveAsURLLoaderFactory) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
mojo::Remote<network::mojom::URLLoaderFactory> factory;
|
||||
@@ -292,7 +290,7 @@ TEST_F(BlobURLStoreImplTest, ResolveForNavigation) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
mojo::Remote<blink::mojom::BlobURLToken> token_remote;
|
||||
67
patches/chromium/m98_fs_fix_fileutil_lifetime_issue.patch
Normal file
67
patches/chromium/m98_fs_fix_fileutil_lifetime_issue.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Thu, 10 Feb 2022 22:18:54 +0000
|
||||
Subject: M98: FS: Fix FileUtil lifetime issue
|
||||
|
||||
Keeps FileSystemContext alive while while resolving a URL on an open
|
||||
file system, removing the possibility of the file system being
|
||||
destroyed while a URL is being resolved on it.
|
||||
|
||||
(cherry picked from commit 3fdf2adf11b3c716c9015597d30b59bffc7ac91b)
|
||||
|
||||
Bug: 1275622, 1289394
|
||||
Change-Id: Ic1b97552f9d41a61163d72ff8c605699f673f55f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3373583
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#968470}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3451059
|
||||
Auto-Submit: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1131}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/storage/browser/file_system/file_system_context.cc b/storage/browser/file_system/file_system_context.cc
|
||||
index 4ae64d27f5ef446dca59b89b7fa8f652fb949bdc..f88aa4e0b3c0bf6c9cf25dada88d9af960409e7e 100644
|
||||
--- a/storage/browser/file_system/file_system_context.cc
|
||||
+++ b/storage/browser/file_system/file_system_context.cc
|
||||
@@ -418,9 +418,22 @@ void FileSystemContext::OpenFileSystem(const url::Origin& origin,
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Bind `this` to the callback to ensure this instance stays alive while the
|
||||
+ // URL is resolving.
|
||||
backend->ResolveURL(
|
||||
CreateCrackedFileSystemURL(origin, type, base::FilePath()), mode,
|
||||
- std::move(callback));
|
||||
+ base::BindOnce(&FileSystemContext::DidResolveURLOnOpenFileSystem, this,
|
||||
+ std::move(callback)));
|
||||
+}
|
||||
+
|
||||
+void FileSystemContext::DidResolveURLOnOpenFileSystem(
|
||||
+ OpenFileSystemCallback callback,
|
||||
+ const GURL& filesystem_root,
|
||||
+ const std::string& filesystem_name,
|
||||
+ base::File::Error error) {
|
||||
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
+
|
||||
+ std::move(callback).Run(filesystem_root, filesystem_name, error);
|
||||
}
|
||||
|
||||
void FileSystemContext::ResolveURL(const FileSystemURL& url,
|
||||
diff --git a/storage/browser/file_system/file_system_context.h b/storage/browser/file_system/file_system_context.h
|
||||
index 2f9b043f15b78c8e09bb4e6675bb5ef21fdac90c..789cecb8fd69ef39b050c229fd0668b7269f352b 100644
|
||||
--- a/storage/browser/file_system/file_system_context.h
|
||||
+++ b/storage/browser/file_system/file_system_context.h
|
||||
@@ -382,6 +382,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext
|
||||
const std::string& filesystem_name,
|
||||
base::File::Error error);
|
||||
|
||||
+ void DidResolveURLOnOpenFileSystem(OpenFileSystemCallback callback,
|
||||
+ const GURL& filesystem_root,
|
||||
+ const std::string& filesystem_name,
|
||||
+ base::File::Error error);
|
||||
+
|
||||
// Returns a FileSystemBackend, used only by test code.
|
||||
SandboxFileSystemBackend* sandbox_backend() const {
|
||||
return sandbox_backend_.get();
|
||||
36
patches/chromium/mas_gate_private_enterprise_APIs.patch
Normal file
36
patches/chromium/mas_gate_private_enterprise_APIs.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: VerteDinde <khammond@slack-corp.com>
|
||||
Date: Tue, 19 Oct 2021 16:56:25 -0700
|
||||
Subject: fix: mas gate private enterprise APIs
|
||||
|
||||
Beginning in Electron 15.2.0, Chromium moved several formerly public
|
||||
APIs into the AreDeviceAndUserJoinedToDomain method. Using these APIs
|
||||
in a MAS build will result in rejection from the Apple Store. This
|
||||
patch gates those APIs to non-MAS builds to comply with Apple
|
||||
Store requirements, and returns the default state for MAS builds.
|
||||
|
||||
diff --git a/base/enterprise_util_mac.mm b/base/enterprise_util_mac.mm
|
||||
index bbb851e1cafb37ebaa67e4577598fab25c90fde6..6ab12e5505b5ba545e7e0cc8c93d3ba9a6d0bacc 100644
|
||||
--- a/base/enterprise_util_mac.mm
|
||||
+++ b/base/enterprise_util_mac.mm
|
||||
@@ -168,6 +168,13 @@ MacDeviceManagementStateNew IsDeviceRegisteredWithManagementNew() {
|
||||
DeviceUserDomainJoinState AreDeviceAndUserJoinedToDomain() {
|
||||
static DeviceUserDomainJoinState state = [] {
|
||||
DeviceUserDomainJoinState state{false, false};
|
||||
+#if defined(MAS_BUILD)
|
||||
+ return state;
|
||||
+ }();
|
||||
+
|
||||
+ return state;
|
||||
+}
|
||||
+#else
|
||||
|
||||
@autoreleasepool {
|
||||
ODSession* session = [ODSession defaultSession];
|
||||
@@ -274,5 +281,6 @@ DeviceUserDomainJoinState AreDeviceAndUserJoinedToDomain() {
|
||||
|
||||
return state;
|
||||
}
|
||||
+#endif
|
||||
|
||||
} // namespace base
|
||||
@@ -0,0 +1,222 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Rice <ricea@chromium.org>
|
||||
Date: Thu, 30 Sep 2021 13:35:07 +0000
|
||||
Subject: Move NetworkStateObserver from document to window
|
||||
|
||||
Previously NetworkStateObserver was a nested class of Document. Make it
|
||||
a nested class of LocalDOMWindow instead, since they have the same
|
||||
lifetime and it fires "online" and "offline" events at the window, not
|
||||
the document.
|
||||
|
||||
BUG=1206928
|
||||
|
||||
(cherry picked from commit af84d38b5cf5ee24f432ae8273bc2dad1e075f0e)
|
||||
|
||||
Change-Id: I2a1080915cf56cfa47eae65594fe6edcc8c2130a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3167550
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Commit-Queue: Adam Rice <ricea@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#922429}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3196231
|
||||
Cr-Commit-Position: refs/branch-heads/4638@{#476}
|
||||
Cr-Branched-From: 159257cab5585bc8421abf347984bb32fdfe9eb9-refs/heads/main@{#920003}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
|
||||
index e600be44138a17d2fc6e7c6e615d47387e87dfd8..ab7b51f997548f594462e45ff37fd5681fad35c2 100644
|
||||
--- a/third_party/blink/renderer/core/dom/document.cc
|
||||
+++ b/third_party/blink/renderer/core/dom/document.cc
|
||||
@@ -324,7 +324,6 @@
|
||||
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
|
||||
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
|
||||
#include "third_party/blink/renderer/platform/network/http_parsers.h"
|
||||
-#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
|
||||
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
|
||||
@@ -578,43 +577,6 @@ uint64_t Document::global_tree_version_ = 0;
|
||||
|
||||
static bool g_threaded_parsing_enabled_for_testing = true;
|
||||
|
||||
-class Document::NetworkStateObserver final
|
||||
- : public GarbageCollected<Document::NetworkStateObserver>,
|
||||
- public NetworkStateNotifier::NetworkStateObserver,
|
||||
- public ExecutionContextLifecycleObserver {
|
||||
- public:
|
||||
- explicit NetworkStateObserver(ExecutionContext* context)
|
||||
- : ExecutionContextLifecycleObserver(context) {
|
||||
- online_observer_handle_ = GetNetworkStateNotifier().AddOnLineObserver(
|
||||
- this, GetExecutionContext()->GetTaskRunner(TaskType::kNetworking));
|
||||
- }
|
||||
-
|
||||
- void OnLineStateChange(bool on_line) override {
|
||||
- AtomicString event_name =
|
||||
- on_line ? event_type_names::kOnline : event_type_names::kOffline;
|
||||
- auto* window = To<LocalDOMWindow>(GetExecutionContext());
|
||||
- window->DispatchEvent(*Event::Create(event_name));
|
||||
- probe::NetworkStateChanged(window->GetFrame(), on_line);
|
||||
- }
|
||||
-
|
||||
- void ContextDestroyed() override {
|
||||
- UnregisterAsObserver(GetExecutionContext());
|
||||
- }
|
||||
-
|
||||
- void UnregisterAsObserver(ExecutionContext* context) {
|
||||
- DCHECK(context);
|
||||
- online_observer_handle_ = nullptr;
|
||||
- }
|
||||
-
|
||||
- void Trace(Visitor* visitor) const override {
|
||||
- ExecutionContextLifecycleObserver::Trace(visitor);
|
||||
- }
|
||||
-
|
||||
- private:
|
||||
- std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
|
||||
- online_observer_handle_;
|
||||
-};
|
||||
-
|
||||
ExplicitlySetAttrElementsMap* Document::GetExplicitlySetAttrElementsMap(
|
||||
Element* element) {
|
||||
DCHECK(element);
|
||||
@@ -2694,12 +2656,6 @@ void Document::Initialize() {
|
||||
|
||||
if (View())
|
||||
View()->DidAttachDocument();
|
||||
-
|
||||
- // Observer(s) should not be initialized until the document is initialized /
|
||||
- // attached to a frame. Otherwise
|
||||
- // ExecutionContextLifecycleObserver::contextDestroyed wouldn't be fired.
|
||||
- network_state_observer_ =
|
||||
- MakeGarbageCollected<NetworkStateObserver>(GetExecutionContext());
|
||||
}
|
||||
|
||||
void Document::Shutdown() {
|
||||
@@ -7913,7 +7869,6 @@ void Document::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(intersection_observer_controller_);
|
||||
visitor->Trace(snap_coordinator_);
|
||||
visitor->Trace(property_registry_);
|
||||
- visitor->Trace(network_state_observer_);
|
||||
visitor->Trace(policy_);
|
||||
visitor->Trace(slot_assignment_engine_);
|
||||
visitor->Trace(viewport_data_);
|
||||
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
|
||||
index bc4b61badba0bbf96619c09345788fca224f5dcf..2eda9ae6b731aa0fad623a82303cbea0e8335ea2 100644
|
||||
--- a/third_party/blink/renderer/core/dom/document.h
|
||||
+++ b/third_party/blink/renderer/core/dom/document.h
|
||||
@@ -1742,7 +1742,6 @@ class CORE_EXPORT Document : public ContainerNode,
|
||||
BeforeMatchExpandedHiddenMatchableUkm);
|
||||
FRIEND_TEST_ALL_PREFIXES(TextFinderSimTest,
|
||||
BeforeMatchExpandedHiddenMatchableUkmNoHandler);
|
||||
- class NetworkStateObserver;
|
||||
|
||||
friend class AXContext;
|
||||
void AddAXContext(AXContext*);
|
||||
@@ -2172,8 +2171,6 @@ class CORE_EXPORT Document : public ContainerNode,
|
||||
|
||||
Member<PropertyRegistry> property_registry_;
|
||||
|
||||
- Member<NetworkStateObserver> network_state_observer_;
|
||||
-
|
||||
// |ukm_recorder_| and |source_id_| will allow objects that are part of
|
||||
// the document to record UKM.
|
||||
std::unique_ptr<ukm::UkmRecorder> ukm_recorder_;
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
index 61bec75d4a144e094f79053f86173f0e9af96412..afb278b466dfc2bb2db8e5c568e38e796a50cfcf 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
@@ -129,6 +129,7 @@
|
||||
#include "third_party/blink/renderer/platform/bindings/script_state.h"
|
||||
#include "third_party/blink/renderer/platform/heap/heap.h"
|
||||
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
|
||||
+#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
|
||||
#include "third_party/blink/renderer/platform/storage/blink_storage_key.h"
|
||||
@@ -166,6 +167,38 @@ bool ShouldRecordPostMessageIncomingFrameUkmEvent(
|
||||
|
||||
} // namespace
|
||||
|
||||
+class LocalDOMWindow::NetworkStateObserver final
|
||||
+ : public GarbageCollected<LocalDOMWindow::NetworkStateObserver>,
|
||||
+ public NetworkStateNotifier::NetworkStateObserver,
|
||||
+ public ExecutionContextLifecycleObserver {
|
||||
+ public:
|
||||
+ explicit NetworkStateObserver(ExecutionContext* context)
|
||||
+ : ExecutionContextLifecycleObserver(context) {}
|
||||
+
|
||||
+ void Initialize() {
|
||||
+ online_observer_handle_ = GetNetworkStateNotifier().AddOnLineObserver(
|
||||
+ this, GetExecutionContext()->GetTaskRunner(TaskType::kNetworking));
|
||||
+ }
|
||||
+
|
||||
+ void OnLineStateChange(bool on_line) override {
|
||||
+ AtomicString event_name =
|
||||
+ on_line ? event_type_names::kOnline : event_type_names::kOffline;
|
||||
+ auto* window = To<LocalDOMWindow>(GetExecutionContext());
|
||||
+ window->DispatchEvent(*Event::Create(event_name));
|
||||
+ probe::NetworkStateChanged(window->GetFrame(), on_line);
|
||||
+ }
|
||||
+
|
||||
+ void ContextDestroyed() override { online_observer_handle_ = nullptr; }
|
||||
+
|
||||
+ void Trace(Visitor* visitor) const override {
|
||||
+ ExecutionContextLifecycleObserver::Trace(visitor);
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
|
||||
+ online_observer_handle_;
|
||||
+};
|
||||
+
|
||||
LocalDOMWindow::LocalDOMWindow(LocalFrame& frame, WindowAgent* agent)
|
||||
: DOMWindow(frame),
|
||||
ExecutionContext(V8PerIsolateData::MainThreadIsolate(), agent),
|
||||
@@ -183,7 +216,9 @@ LocalDOMWindow::LocalDOMWindow(LocalFrame& frame, WindowAgent* agent)
|
||||
isolated_world_csp_map_(
|
||||
MakeGarbageCollected<
|
||||
HeapHashMap<int, Member<ContentSecurityPolicy>>>()),
|
||||
- token_(frame.GetLocalFrameToken()) {}
|
||||
+ token_(frame.GetLocalFrameToken()),
|
||||
+ network_state_observer_(
|
||||
+ MakeGarbageCollected<NetworkStateObserver>(this)) {}
|
||||
|
||||
void LocalDOMWindow::BindContentSecurityPolicy() {
|
||||
DCHECK(!GetContentSecurityPolicy()->IsBound());
|
||||
@@ -193,6 +228,7 @@ void LocalDOMWindow::BindContentSecurityPolicy() {
|
||||
|
||||
void LocalDOMWindow::Initialize() {
|
||||
GetAgent()->AttachContext(this);
|
||||
+ network_state_observer_->Initialize();
|
||||
}
|
||||
|
||||
void LocalDOMWindow::ResetWindowAgent(WindowAgent* agent) {
|
||||
@@ -2089,6 +2125,7 @@ void LocalDOMWindow::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(spell_checker_);
|
||||
visitor->Trace(text_suggestion_controller_);
|
||||
visitor->Trace(isolated_world_csp_map_);
|
||||
+ visitor->Trace(network_state_observer_);
|
||||
DOMWindow::Trace(visitor);
|
||||
ExecutionContext::Trace(visitor);
|
||||
Supplementable<LocalDOMWindow>::Trace(visitor);
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
|
||||
index b37537bcf85ac5333dd317ecfe6c783486486a28..8e7e544f901a1d957a03a834efa30f7cd1286f7a 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
|
||||
@@ -448,6 +448,8 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
|
||||
LocalDOMWindow* source) override;
|
||||
|
||||
private:
|
||||
+ class NetworkStateObserver;
|
||||
+
|
||||
// Intentionally private to prevent redundant checks when the type is
|
||||
// already LocalDOMWindow.
|
||||
bool IsLocalDOMWindow() const override { return true; }
|
||||
@@ -555,6 +557,9 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
|
||||
|
||||
// The storage key for this LocalDomWindow.
|
||||
BlinkStorageKey storage_key_;
|
||||
+
|
||||
+ // Fire "online" and "offline" events.
|
||||
+ Member<NetworkStateObserver> network_state_observer_;
|
||||
};
|
||||
|
||||
template <>
|
||||
@@ -408,7 +408,7 @@ index 623659a3c78ce069cbcc83eeccfbc7265437ff01..f02cb6bced9f8382c84f560b5b40c924
|
||||
// Tells the RenderFrame to switch the CSS to print media type, render every
|
||||
// requested page using the print preview document's frame/node, and then
|
||||
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
|
||||
index 868f1706b1b8db28b995cc2dc9fcfefec62b6574..9224b935815f28086ce4df05e3f4c81b6dd92e7f 100644
|
||||
index 868f1706b1b8db28b995cc2dc9fcfefec62b6574..5f98a820f4452328ab38b2e918a2d9a6258cb658 100644
|
||||
--- a/components/printing/renderer/print_render_frame_helper.cc
|
||||
+++ b/components/printing/renderer/print_render_frame_helper.cc
|
||||
@@ -38,6 +38,7 @@
|
||||
@@ -539,18 +539,52 @@ index 868f1706b1b8db28b995cc2dc9fcfefec62b6574..9224b935815f28086ce4df05e3f4c81b
|
||||
// Check if |this| is still valid.
|
||||
if (!self)
|
||||
return;
|
||||
@@ -2169,7 +2210,9 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
@@ -2169,36 +2210,51 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
}
|
||||
}
|
||||
|
||||
-bool PrintRenderFrameHelper::InitPrintSettings(bool fit_to_paper_size) {
|
||||
- mojom::PrintPagesParams settings;
|
||||
- settings.params = mojom::PrintParams::New();
|
||||
- GetPrintManagerHost()->GetDefaultPrintSettings(&settings.params);
|
||||
+bool PrintRenderFrameHelper::InitPrintSettings(
|
||||
+ bool fit_to_paper_size,
|
||||
+ const base::DictionaryValue& new_settings) {
|
||||
mojom::PrintPagesParams settings;
|
||||
settings.params = mojom::PrintParams::New();
|
||||
GetPrintManagerHost()->GetDefaultPrintSettings(&settings.params);
|
||||
@@ -2193,12 +2236,14 @@ bool PrintRenderFrameHelper::InitPrintSettings(bool fit_to_paper_size) {
|
||||
+ mojom::PrintPagesParamsPtr settings;
|
||||
+
|
||||
+ if (new_settings.DictEmpty()) {
|
||||
+ settings = mojom::PrintPagesParams::New();
|
||||
+ settings->params = mojom::PrintParams::New();
|
||||
+ GetPrintManagerHost()->GetDefaultPrintSettings(&settings->params);
|
||||
+ } else {
|
||||
+ bool canceled = false;
|
||||
+ int cookie =
|
||||
+ print_pages_params_ ? print_pages_params_->params->document_cookie : 0;
|
||||
+ GetPrintManagerHost()->UpdatePrintSettings(cookie, new_settings.Clone(), &settings, &canceled);
|
||||
+ if (canceled)
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
// Check if the printer returned any settings, if the settings is empty, we
|
||||
// can safely assume there are no printer drivers configured. So we safely
|
||||
// terminate.
|
||||
bool result = true;
|
||||
- if (!PrintMsg_Print_Params_IsValid(*settings.params))
|
||||
+ if (!PrintMsg_Print_Params_IsValid(*settings->params))
|
||||
result = false;
|
||||
|
||||
// Reset to default values.
|
||||
ignore_css_margins_ = false;
|
||||
- settings.pages.clear();
|
||||
+ settings->pages.clear();
|
||||
|
||||
- settings.params->print_scaling_option =
|
||||
+ settings->params->print_scaling_option =
|
||||
fit_to_paper_size ? mojom::PrintScalingOption::kFitToPrintableArea
|
||||
: mojom::PrintScalingOption::kSourceSize;
|
||||
|
||||
- SetPrintPagesParams(settings);
|
||||
+ SetPrintPagesParams(*settings);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -569,7 +603,7 @@ index 868f1706b1b8db28b995cc2dc9fcfefec62b6574..9224b935815f28086ce4df05e3f4c81b
|
||||
notify_browser_of_print_failure_ = false;
|
||||
GetPrintManagerHost()->ShowInvalidPrinterSettingsError();
|
||||
return false;
|
||||
@@ -2569,18 +2614,7 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) {
|
||||
@@ -2569,18 +2625,7 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) {
|
||||
}
|
||||
|
||||
bool PrintRenderFrameHelper::CheckForCancel() {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bruce Dawson <brucedawson@chromium.org>
|
||||
Date: Mon, 28 Feb 2022 19:07:41 +0000
|
||||
Subject: Remove incorrect width/height adjustments
|
||||
|
||||
In late 2016 a change which fixed some problems around window sizing
|
||||
when attaching or detaching additional displays was landed, which fixed
|
||||
some genuine bugs. Unfortunately it included a subtraction of 1 from the
|
||||
width and height of the Chrome window. I couldn't find any discussion of
|
||||
this size adjustment and I think that it was just a misunderstanding of
|
||||
how window rectangles work (inclusive versus exclusive extents).
|
||||
|
||||
This size adjustment causes non-maximized Chrome windows to shrink every
|
||||
time a monitor is added or removed. The problematic commit was found
|
||||
by the bug-filer through a bisect of more than four years of Chrome
|
||||
history - I'm just landing the fix that they suggested.
|
||||
|
||||
Bug: 1300415
|
||||
Change-Id: Ief124f584a91aa9cc3f10704b0cc1e83356dea5b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3492658
|
||||
Reviewed-by: Allen Bauer <kylixrd@chromium.org>
|
||||
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#975872}
|
||||
|
||||
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
|
||||
index e4c25788cf40e2b748cb25f004e448c0ea5f622c..72a62447a4a713c78984065f36f1734ad0826b62 100644
|
||||
--- a/ui/views/win/hwnd_message_handler.cc
|
||||
+++ b/ui/views/win/hwnd_message_handler.cc
|
||||
@@ -2818,8 +2818,8 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
|
||||
// (Win+Shift+Arrows). See crbug.com/656001.
|
||||
window_rect.left = window_pos->x;
|
||||
window_rect.top = window_pos->y;
|
||||
- window_rect.right = window_pos->x + window_pos->cx - 1;
|
||||
- window_rect.bottom = window_pos->y + window_pos->cy - 1;
|
||||
+ window_rect.right = window_pos->x + window_pos->cx;
|
||||
+ window_rect.bottom = window_pos->y + window_pos->cy;
|
||||
}
|
||||
|
||||
HMONITOR monitor;
|
||||
157
patches/chromium/sandbox_fix_sandbox_inheritance_m96_merge.patch
Normal file
157
patches/chromium/sandbox_fix_sandbox_inheritance_m96_merge.patch
Normal file
@@ -0,0 +1,157 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Date: Wed, 3 Nov 2021 12:49:50 +0000
|
||||
Subject: sandbox: Fix sandbox inheritance [M96 merge]
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is a cherry-pick of the following patch:
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/3231298
|
||||
|
||||
Patch description:
|
||||
------------------
|
||||
When creating a new frame and the initial empty document, blink was only
|
||||
sending the frame's sandbox attribute, but without combining with its owner's
|
||||
(=document) sandbox flags.
|
||||
|
||||
This patch combines frame's attribute with its document sandbox flags.
|
||||
|
||||
🎁 Arthur Sonzogni wishes for a better future: 🎁
|
||||
-------------------------------------------------
|
||||
There are no good reasons sandbox flags inheritance to be complicated.
|
||||
See: content/browser/renderer_host/sandbox_flags.md
|
||||
|
||||
For legacy reasons, Chrome's developers were confused about what objects
|
||||
have frame or document semantic. On the browser process, the
|
||||
FrameTreeNode represents the frame and the RenderFrameHost is almost
|
||||
(%RenderDocument) the document/execution-context.
|
||||
|
||||
Currently, sandbox flags is plumbed inside FramePolicy, and it is not
|
||||
clear to me whether FramePolicy is a frame-scoped or document-scoped
|
||||
property (or both).
|
||||
The current logic speak about "pending" FramePolicy (=frame) and
|
||||
"active" FramePolicy (=document) and store both type into the
|
||||
FrameTreeNode and RenderFrameHost, which is not ideal.
|
||||
|
||||
I believe we should extract SandboxFlags outside of FramePolicy and
|
||||
make a very clean implementation, parallel to the PolicyContainer logic.
|
||||
In a second step it could also be integrated into PolicyContainer, if we
|
||||
resolve the additional property that sandbox flags can also be further
|
||||
restricted at the frame level, similar to CSP embedded enforcement.
|
||||
|
||||
Bug: 1256822, 1262061
|
||||
Change-Id: Id38de6d7eeeb1e4fa7722ab56288666763fae838
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3231298
|
||||
Commit-Queue: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Auto-Submit: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Reviewed-by: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Reviewed-by: Mike West <mkwst@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#933845}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3256558
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#695}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
|
||||
index 56f159a45c50e6db658ffd783bf01ea4d4e54988..de7d2cfd70fbc02499b1c3a2097f7340c2d01e0b 100644
|
||||
--- a/content/browser/bad_message.h
|
||||
+++ b/content/browser/bad_message.h
|
||||
@@ -275,6 +275,11 @@ enum BadMessageReason {
|
||||
MDDH_INVALID_PERMITTED_ORIGIN = 247,
|
||||
MDDH_NOT_TOP_LEVEL = 248,
|
||||
RFH_DID_CHANGE_IFRAME_ATTRIBUTE = 249,
|
||||
+ FARI_LOGOUT_BAD_ENDPOINT = 250,
|
||||
+ RFH_CHILD_FRAME_UNEXPECTED_OWNER_ELEMENT_TYPE = 251,
|
||||
+ RFH_POPUP_REQUEST_WHILE_PRERENDERING = 252,
|
||||
+ RFH_INTERECEPT_DOWNLOAD_WHILE_INACTIVE = 253, // Unused until 97.0.4674.0
|
||||
+ RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS = 254,
|
||||
|
||||
// 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/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
|
||||
index 7596d071d856b8b41ba8e7101f7fb032e3055334..6cf311deea370119bb1504e7f02c08c6757fa1da 100644
|
||||
--- a/content/browser/renderer_host/frame_tree_node.cc
|
||||
+++ b/content/browser/renderer_host/frame_tree_node.cc
|
||||
@@ -472,6 +472,12 @@ bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
|
||||
|
||||
bool FrameTreeNode::CommitFramePolicy(
|
||||
const blink::FramePolicy& new_frame_policy) {
|
||||
+ // Documents create iframes, iframes host new documents. Both are associated
|
||||
+ // with sandbox flags. They are required to be stricter or equal to their
|
||||
+ // owner when they change, as we go down.
|
||||
+ // TODO(https://crbug.com/1262061). Enforce the invariant mentioned above,
|
||||
+ // once the interactions with FencedIframe has been tested and clarified.
|
||||
+
|
||||
bool did_change_flags = new_frame_policy.sandbox_flags !=
|
||||
replication_state_->frame_policy.sandbox_flags;
|
||||
bool did_change_container_policy =
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 10f34740cad12975914107a9c07bdbe9279120aa..1077dc1ef688c7dcea8dc85f006eae4560c9115a 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -3506,6 +3506,16 @@ void RenderFrameHostImpl::CreateChildFrame(
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Documents create iframes, iframes host new documents. Both are associated
|
||||
+ // with sandbox flags. They are required to be stricter or equal to their
|
||||
+ // owner when they are created, as we go down.
|
||||
+ if (frame_policy.sandbox_flags !=
|
||||
+ (frame_policy.sandbox_flags | active_sandbox_flags())) {
|
||||
+ bad_message::ReceivedBadMessage(
|
||||
+ GetProcess(), bad_message::RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// TODO(crbug.com/1145708). The interface exposed to tests should
|
||||
// match the mojo interface.
|
||||
OnCreateChildFrame(new_routing_id, std::move(frame_remote),
|
||||
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
index 1ffff24a749e37552ad771061c9cef68568df784..2be62c3b5ef9f192dd5652e432b81adf71aa067c 100644
|
||||
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
@@ -2113,6 +2113,16 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
|
||||
policy_container_receiver =
|
||||
policy_container_remote.InitWithNewEndpointAndPassReceiver();
|
||||
|
||||
+ FramePolicy frame_policy = owner_element->GetFramePolicy();
|
||||
+ // Documents create iframes, iframes host new documents. Both are associated
|
||||
+ // with sandbox flags. They are required to be stricter or equal as we go
|
||||
+ // down. The iframe owner element only returns the additional restrictions
|
||||
+ // defined in the HTMLIFrameElement's sanbox attribute. It needs to be
|
||||
+ // combined with the document's sandbox flags to get the frame's sandbox
|
||||
+ // policy right.
|
||||
+ frame_policy.sandbox_flags |=
|
||||
+ GetFrame()->GetDocument()->GetExecutionContext()->GetSandboxFlags();
|
||||
+
|
||||
// FIXME: Using subResourceAttributeName as fallback is not a perfect
|
||||
// solution. subResourceAttributeName returns just one attribute name. The
|
||||
// element might not have the attribute, and there might be other attributes
|
||||
@@ -2122,8 +2132,7 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
|
||||
scope, name,
|
||||
owner_element->getAttribute(
|
||||
owner_element->SubResourceAttributeName()),
|
||||
- owner_element->GetFramePolicy(), owner_properties,
|
||||
- owner_element->OwnerType(),
|
||||
+ std::move(frame_policy), owner_properties, owner_element->OwnerType(),
|
||||
WebPolicyContainerBindParams{std::move(policy_container_receiver)}));
|
||||
if (!webframe_child)
|
||||
return nullptr;
|
||||
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
|
||||
index 521f49669eef1ed5fe445618984c3c93fb70d786..8e8bffa245e752f0941e2419da1db0cf365d0f50 100644
|
||||
--- a/tools/metrics/histograms/enums.xml
|
||||
+++ b/tools/metrics/histograms/enums.xml
|
||||
@@ -7589,6 +7589,11 @@ Called by update_bad_message_reasons.py.-->
|
||||
<int value="247" label="MDDH_INVALID_PERMITTED_ORIGIN"/>
|
||||
<int value="248" label="MDDH_NOT_TOP_LEVEL"/>
|
||||
<int value="249" label="RFH_DID_CHANGE_IFRAME_ATTRIBUTE"/>
|
||||
+ <int value="250" label="FARI_LOGOUT_BAD_ENDPOINT"/>
|
||||
+ <int value="251" label="RFH_CHILD_FRAME_UNEXPECTED_OWNER_ELEMENT_TYPE"/>
|
||||
+ <int value="252" label="RFH_POPUP_REQUEST_WHILE_PRERENDERING"/>
|
||||
+ <int value="253" label="RFH_INTERECEPT_DOWNLOAD_WHILE_INACTIVE"/>
|
||||
+ <int value="254" label="RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS"/>
|
||||
</enum>
|
||||
|
||||
<enum name="BadMessageReasonExtensions">
|
||||
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ionel Popescu <iopopesc@microsoft.com>
|
||||
Date: Wed, 15 Sep 2021 18:16:16 +0000
|
||||
Subject: Speculative fix for eye dropper getColor crash.
|
||||
|
||||
There seems to be a situation where the captured frame coordinates
|
||||
are different than the ones accessible by moving the mouse.
|
||||
|
||||
I am not able to locally reproduce this issue, so I am adding DCHECKs
|
||||
to validate that the coordinates are correct and I am also handling
|
||||
the invalid coordinates to prevent invalid memory access.
|
||||
|
||||
(cherry picked from commit a656373ae7212e0d88474bdec4691a4152452748)
|
||||
|
||||
Bug: 1246631
|
||||
Change-Id: I915d46a71aa73b5dcf08127d347fdd47c1ddf54c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3152423
|
||||
Reviewed-by: Mason Freed <masonf@chromium.org>
|
||||
Commit-Queue: Ionel Popescu <iopopesc@microsoft.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#920811}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3163070
|
||||
Auto-Submit: Ionel Popescu <iopopesc@microsoft.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4638@{#75}
|
||||
Cr-Branched-From: 159257cab5585bc8421abf347984bb32fdfe9eb9-refs/heads/main@{#920003}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc b/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc
|
||||
index 1701eedcd8289d805087635eb2ed71c600a60466..16bb9a5f758a2d6995ae3f52eca2b6c5edcb3213 100644
|
||||
--- a/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc
|
||||
+++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc
|
||||
@@ -65,6 +65,7 @@ class EyeDropperView::ScreenCapturer
|
||||
std::unique_ptr<webrtc::DesktopFrame> frame) override;
|
||||
|
||||
SkBitmap GetBitmap() const;
|
||||
+ SkColor GetColor(int x, int y) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<webrtc::DesktopCapturer> capturer_;
|
||||
@@ -95,6 +96,13 @@ SkBitmap EyeDropperView::ScreenCapturer::GetBitmap() const {
|
||||
return frame_;
|
||||
}
|
||||
|
||||
+SkColor EyeDropperView::ScreenCapturer::GetColor(int x, int y) const {
|
||||
+ DCHECK(x < frame_.width());
|
||||
+ DCHECK(y < frame_.height());
|
||||
+ return x < frame_.width() && y < frame_.height() ? frame_.getColor(x, y)
|
||||
+ : SK_ColorBLACK;
|
||||
+}
|
||||
+
|
||||
EyeDropperView::EyeDropperView(content::RenderFrameHost* frame,
|
||||
content::EyeDropperListener* listener)
|
||||
: render_frame_host_(frame),
|
||||
@@ -182,7 +190,8 @@ void EyeDropperView::OnPaint(gfx::Canvas* view_canvas) {
|
||||
|
||||
// Store the pixel color under the cursor as it is the last color seen
|
||||
// by the user before selection.
|
||||
- selected_color_ = frame.getColor(center_position.x(), center_position.y());
|
||||
+ selected_color_ =
|
||||
+ screen_capturer_->GetColor(center_position.x(), center_position.y());
|
||||
|
||||
// Paint grid.
|
||||
cc::PaintFlags flags;
|
||||
@@ -0,0 +1,291 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rayan Kanso <rayankans@google.com>
|
||||
Date: Tue, 9 Nov 2021 14:10:59 +0000
|
||||
Subject: Use WeakPtrs for the ThreadedIconLoader's background tasks.
|
||||
|
||||
(cherry picked from commit f0375e38d259b3651fd9f305ca2e723ca9c02c64)
|
||||
|
||||
Bug: 1241091
|
||||
Change-Id: I35b9cf705f1c5ffa2a719e47aec7b0f7d98ddc6b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3222803
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Commit-Queue: Kentaro Hara <haraken@chromium.org>
|
||||
Auto-Submit: Rayan Kanso <rayankans@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#937427}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3269570
|
||||
Auto-Submit: Yutaka Hirano <yhirano@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#897}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
|
||||
index aba93c594fc85d6f82ff5f2ebf339e46d03a7111..3c15a85a2788c7faca3f39273fe3e77e456a1bad 100644
|
||||
--- a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
|
||||
+++ b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "skia/ext/image_operations.h"
|
||||
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
|
||||
+#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
|
||||
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
|
||||
#include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
|
||||
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
|
||||
@@ -24,6 +25,80 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+void DecodeAndResizeImage(
|
||||
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
+ scoped_refptr<SegmentReader> data,
|
||||
+ gfx::Size resize_dimensions,
|
||||
+ CrossThreadOnceFunction<void(SkBitmap, double)> done_callback) {
|
||||
+ auto notify_complete = [&](SkBitmap icon, double resize_scale) {
|
||||
+ // This is needed so it can be moved cross-thread.
|
||||
+ icon.setImmutable();
|
||||
+ PostCrossThreadTask(*task_runner, FROM_HERE,
|
||||
+ CrossThreadBindOnce(std::move(done_callback),
|
||||
+ std::move(icon), resize_scale));
|
||||
+ };
|
||||
+
|
||||
+ std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
|
||||
+ std::move(data), /* data_complete= */ true,
|
||||
+ ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth,
|
||||
+ ColorBehavior::TransformToSRGB());
|
||||
+
|
||||
+ if (!decoder) {
|
||||
+ notify_complete(SkBitmap(), -1.0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ImageFrame* image_frame = decoder->DecodeFrameBufferAtIndex(0);
|
||||
+
|
||||
+ if (!image_frame) {
|
||||
+ notify_complete(SkBitmap(), -1.0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ SkBitmap decoded_icon = image_frame->Bitmap();
|
||||
+ if (resize_dimensions.IsEmpty()) {
|
||||
+ notify_complete(std::move(decoded_icon), 1.0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // If the icon is larger than |resize_dimensions| permits, we need to
|
||||
+ // resize it as well. This can be done synchronously given that we're on a
|
||||
+ // background thread already.
|
||||
+ double scale = std::min(
|
||||
+ static_cast<double>(resize_dimensions.width()) / decoded_icon.width(),
|
||||
+ static_cast<double>(resize_dimensions.height()) / decoded_icon.height());
|
||||
+
|
||||
+ if (scale >= 1.0) {
|
||||
+ notify_complete(std::move(decoded_icon), 1.0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ int resized_width =
|
||||
+ base::ClampToRange(static_cast<int>(scale * decoded_icon.width()), 1,
|
||||
+ resize_dimensions.width());
|
||||
+ int resized_height =
|
||||
+ base::ClampToRange(static_cast<int>(scale * decoded_icon.height()), 1,
|
||||
+ resize_dimensions.height());
|
||||
+
|
||||
+ // Use the RESIZE_GOOD quality allowing the implementation to pick an
|
||||
+ // appropriate method for the resize. Can be increased to RESIZE_BETTER
|
||||
+ // or RESIZE_BEST if the quality looks poor.
|
||||
+ SkBitmap resized_icon = skia::ImageOperations::Resize(
|
||||
+ decoded_icon, skia::ImageOperations::RESIZE_GOOD, resized_width,
|
||||
+ resized_height);
|
||||
+
|
||||
+ if (resized_icon.isNull()) {
|
||||
+ notify_complete(std::move(decoded_icon), 1.0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ notify_complete(std::move(resized_icon), scale);
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
void ThreadedIconLoader::Start(
|
||||
ExecutionContext* execution_context,
|
||||
const ResourceRequestHead& resource_request,
|
||||
@@ -83,87 +158,18 @@ void ThreadedIconLoader::DidFinishLoading(uint64_t resource_identifier) {
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE,
|
||||
CrossThreadBindOnce(
|
||||
- &ThreadedIconLoader::DecodeAndResizeImageOnBackgroundThread,
|
||||
- WrapCrossThreadPersistent(this), std::move(task_runner),
|
||||
- SegmentReader::CreateFromSharedBuffer(std::move(data_))));
|
||||
-}
|
||||
-
|
||||
-void ThreadedIconLoader::DecodeAndResizeImageOnBackgroundThread(
|
||||
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
- scoped_refptr<SegmentReader> data) {
|
||||
- DCHECK(task_runner);
|
||||
- DCHECK(data);
|
||||
-
|
||||
- auto notify_complete = [&](double refactor_scale) {
|
||||
- PostCrossThreadTask(
|
||||
- *task_runner, FROM_HERE,
|
||||
- CrossThreadBindOnce(&ThreadedIconLoader::OnBackgroundTaskComplete,
|
||||
- WrapCrossThreadPersistent(this), refactor_scale));
|
||||
- };
|
||||
-
|
||||
- std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
|
||||
- std::move(data), /* data_complete= */ true,
|
||||
- ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth,
|
||||
- ColorBehavior::TransformToSRGB());
|
||||
-
|
||||
- if (!decoder) {
|
||||
- notify_complete(-1.0);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- ImageFrame* image_frame = decoder->DecodeFrameBufferAtIndex(0);
|
||||
-
|
||||
- if (!image_frame) {
|
||||
- notify_complete(-1.0);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- decoded_icon_ = image_frame->Bitmap();
|
||||
- if (!resize_dimensions_) {
|
||||
- notify_complete(1.0);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // If the icon is larger than |resize_dimensions_| permits, we need to resize
|
||||
- // it as well. This can be done synchronously given that we're on a
|
||||
- // background thread already.
|
||||
- double scale = std::min(
|
||||
- static_cast<double>(resize_dimensions_->width()) / decoded_icon_.width(),
|
||||
- static_cast<double>(resize_dimensions_->height()) /
|
||||
- decoded_icon_.height());
|
||||
-
|
||||
- if (scale >= 1.0) {
|
||||
- notify_complete(1.0);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- int resized_width =
|
||||
- base::ClampToRange(static_cast<int>(scale * decoded_icon_.width()), 1,
|
||||
- resize_dimensions_->width());
|
||||
- int resized_height =
|
||||
- base::ClampToRange(static_cast<int>(scale * decoded_icon_.height()), 1,
|
||||
- resize_dimensions_->height());
|
||||
-
|
||||
- // Use the RESIZE_GOOD quality allowing the implementation to pick an
|
||||
- // appropriate method for the resize. Can be increased to RESIZE_BETTER
|
||||
- // or RESIZE_BEST if the quality looks poor.
|
||||
- SkBitmap resized_icon = skia::ImageOperations::Resize(
|
||||
- decoded_icon_, skia::ImageOperations::RESIZE_GOOD, resized_width,
|
||||
- resized_height);
|
||||
-
|
||||
- if (resized_icon.isNull()) {
|
||||
- notify_complete(1.0);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- decoded_icon_ = std::move(resized_icon);
|
||||
- notify_complete(scale);
|
||||
+ &DecodeAndResizeImage, std::move(task_runner),
|
||||
+ SegmentReader::CreateFromSharedBuffer(std::move(data_)),
|
||||
+ resize_dimensions_ ? *resize_dimensions_ : gfx::Size(),
|
||||
+ CrossThreadBindOnce(&ThreadedIconLoader::OnBackgroundTaskComplete,
|
||||
+ WrapCrossThreadWeakPersistent(this))));
|
||||
}
|
||||
|
||||
-void ThreadedIconLoader::OnBackgroundTaskComplete(double resize_scale) {
|
||||
+void ThreadedIconLoader::OnBackgroundTaskComplete(SkBitmap icon,
|
||||
+ double resize_scale) {
|
||||
if (stopped_)
|
||||
return;
|
||||
- std::move(icon_callback_).Run(std::move(decoded_icon_), resize_scale);
|
||||
+ std::move(icon_callback_).Run(std::move(icon), resize_scale);
|
||||
}
|
||||
|
||||
void ThreadedIconLoader::DidFail(uint64_t, const ResourceError& error) {
|
||||
diff --git a/third_party/blink/renderer/core/loader/threaded_icon_loader.h b/third_party/blink/renderer/core/loader/threaded_icon_loader.h
|
||||
index c1a9bb22b21ef1623c0aefc83ceeafe8e1e0a791..63a293b280678b4f0cc480616474b8cb99469eb7 100644
|
||||
--- a/third_party/blink/renderer/core/loader/threaded_icon_loader.h
|
||||
+++ b/third_party/blink/renderer/core/loader/threaded_icon_loader.h
|
||||
@@ -18,7 +18,6 @@
|
||||
namespace blink {
|
||||
|
||||
class ResourceRequestHead;
|
||||
-class SegmentReader;
|
||||
|
||||
// Utility class for loading, decoding, and potentially rescaling an icon on a
|
||||
// background thread. Note that icons are only downscaled and never upscaled.
|
||||
@@ -52,11 +51,7 @@ class CORE_EXPORT ThreadedIconLoader final
|
||||
void Trace(Visitor* visitor) const override;
|
||||
|
||||
private:
|
||||
- void DecodeAndResizeImageOnBackgroundThread(
|
||||
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
- scoped_refptr<SegmentReader> data);
|
||||
-
|
||||
- void OnBackgroundTaskComplete(double resize_scale);
|
||||
+ void OnBackgroundTaskComplete(SkBitmap icon, double resize_scale);
|
||||
|
||||
Member<ThreadableLoader> threadable_loader_;
|
||||
|
||||
@@ -64,9 +59,7 @@ class CORE_EXPORT ThreadedIconLoader final
|
||||
// of the image data starts.
|
||||
scoped_refptr<SharedBuffer> data_;
|
||||
|
||||
- // Accessed from main thread and background thread.
|
||||
absl::optional<gfx::Size> resize_dimensions_;
|
||||
- SkBitmap decoded_icon_;
|
||||
|
||||
IconCallback icon_callback_;
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc b/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
|
||||
index 79f4224fd96c46d7a6e1caabb44a509443b4bbff..3b5f52a9beb9c86d712332a4605f1b46c40f7682 100644
|
||||
--- a/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
|
||||
+++ b/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
|
||||
@@ -26,6 +26,7 @@ constexpr base::TimeDelta kIconFetchTimeout = base::TimeDelta::FromSeconds(30);
|
||||
void FetchIcon(ExecutionContext* execution_context,
|
||||
const KURL& icon_url,
|
||||
const gfx::Size& icon_size,
|
||||
+ ThreadedIconLoader* threaded_icon_loader,
|
||||
ThreadedIconLoader::IconCallback callback) {
|
||||
ResourceRequest resource_request(icon_url);
|
||||
resource_request.SetRequestContext(mojom::blink::RequestContextType::IMAGE);
|
||||
@@ -34,7 +35,6 @@ void FetchIcon(ExecutionContext* execution_context,
|
||||
resource_request.SetPriority(ResourceLoadPriority::kMedium);
|
||||
resource_request.SetTimeoutInterval(kIconFetchTimeout);
|
||||
|
||||
- auto* threaded_icon_loader = MakeGarbageCollected<ThreadedIconLoader>();
|
||||
threaded_icon_loader->Start(execution_context, resource_request, icon_size,
|
||||
std::move(callback));
|
||||
}
|
||||
@@ -100,16 +100,21 @@ void ContentIndexIconLoader::Start(
|
||||
if (icon_url.IsEmpty())
|
||||
icon_url = KURL(image_resources[0].src);
|
||||
|
||||
+ auto* threaded_icon_loader = MakeGarbageCollected<ThreadedIconLoader>();
|
||||
// |icons_ptr| is safe to use since it is owned by |barrier_closure|.
|
||||
FetchIcon(
|
||||
- execution_context, icon_url, icon_size,
|
||||
+ execution_context, icon_url, icon_size, threaded_icon_loader,
|
||||
WTF::Bind(
|
||||
[](base::OnceClosure done_closure, Vector<SkBitmap>* icons_ptr,
|
||||
- SkBitmap icon, double resize_scale) {
|
||||
+ ThreadedIconLoader* icon_loader, SkBitmap icon,
|
||||
+ double resize_scale) {
|
||||
icons_ptr->push_back(std::move(icon));
|
||||
std::move(done_closure).Run();
|
||||
},
|
||||
- barrier_closure, WTF::Unretained(icons_ptr)));
|
||||
+ barrier_closure, WTF::Unretained(icons_ptr),
|
||||
+ // Pass |threaded_icon_loader| to the callback to make sure it
|
||||
+ // doesn't get destroyed.
|
||||
+ WrapPersistent(threaded_icon_loader)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,9 @@
|
||||
|
||||
"src/electron/patches/Mantle": "src/third_party/squirrel.mac/vendor/Mantle",
|
||||
|
||||
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC"
|
||||
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC",
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/pdfium": "src/third_party/pdfium"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user