Compare commits

..

66 Commits

Author SHA1 Message Date
Sudowoodo Release Bot
dbe8546e1b Bump v14.2.2 2021-11-30 13:29:29 -08:00
trop[bot]
5462e954b7 fix: aspect ratio when max width/height is set (#31955)
* 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.

* chore: update patches

Co-authored-by: Cezary Kulakowski <cezary@openfin.co>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-11-24 17:07:37 -05:00
Pedro Pontes
376812fccd chore: cherry-pick 1a8af2da50e4 from chromium (#31903)
* chore: cherry-pick 1a8af2da50e4 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-11-24 16:24:48 -05:00
Pedro Pontes
a1a1ffca2c chore: cherry-pick 1fcfb942bd from chromium (#31928)
Co-authored-by: Electron Bot <electron@github.com>
2021-11-22 16:54:25 -05:00
Pedro Pontes
6aefbacce3 chore: cherry-pick 56de3b2004, bbca3704f9 and f2b0985ac3 from chromium (#31920)
Co-authored-by: Electron Bot <electron@github.com>
2021-11-22 08:34:19 -08:00
Pedro Pontes
9e21ebf6ea chore: cherry-pick 5d2b5e7c006c from v8 (#31911)
* chore: cherry-pick 5d2b5e7c006c from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-11-22 01:45:18 -08:00
Pedro Pontes
51bb4c1e7b chore: cherry-pick a5f54612590d from chromium (#31900) 2021-11-22 01:38:09 -08:00
trop[bot]
e4fbf3852a fix: BrowserView setBackgroundColor needs two calls (#31945)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-11-22 16:41:46 +09:00
trop[bot]
20fc69ec99 fix: ninja build failed on some system (#31941)
Co-authored-by: Black-Hole1 <158blackhole@gmail.com>
2021-11-22 16:36:48 +09:00
trop[bot]
d2b758240d fix: lint Objective-C header files (#31937)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-11-22 16:35:32 +09:00
trop[bot]
7351f65482 docs: fix typo in distribution docs (#31879)
Co-authored-by: Sergey Zolotarev <sryze@protonmail.com>
2021-11-18 20:32:49 +09:00
Shelley Vohr
173cc8e904 fix: BrowserView setBackgroundColor() (#31845) 2021-11-16 20:39:45 +01:00
trop[bot]
0fca1b536d chore: use std::forward() in ConvertToV8() (#31857)
The variable `input` is accepted by a universal reference, so it doesn't
make sense to cast a potential lvalue reference into an rvalue
reference. In case `input` is an lvalue reference, we should rather
forward the value as is to `ToV8()`.

Signed-off-by: Darshan Sen <darshan.sen@postman.com>

Co-authored-by: Darshan Sen <darshan.sen@postman.com>
2021-11-16 10:04:25 -05:00
trop[bot]
c5bdabbb77 fix: make BrowserView aware of owning window (#31840)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-11-16 12:00:14 +01:00
trop[bot]
df8eb2aeb0 fix: setContentProtection affects BrowserWindow frame (#31831)
Co-authored-by: Micha Hanselmann <micha.hanselmann@gmail.com>
2021-11-15 16:37:02 +01:00
trop[bot]
7478c82233 fix: in GTK open dialog, do not preview huge files (#31819)
* fix: in GTK open dialog, do not preview huge files

Previewing images whose files are larger than a GB can crash Electron.

* refactor: tweak CanPreview()

Co-authored-by: Charles Kerr <charles@charleskerr.com>
2021-11-15 16:35:53 +01:00
trop[bot]
e60d3a7d27 fix: correct default text for button labels in gtk dialogs (#31822) 2021-11-15 16:24:14 +01:00
trop[bot]
484c90d4eb fix: crash on browserView.webContents.destroy() (#31825)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-11-15 16:19:06 +01:00
trop[bot]
a978735582 chore: cleanup obsolete lib/common/remote/ipc-messages.ts (#31765)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-11-09 13:00:29 -05:00
trop[bot]
8335d24684 test: fix crash in electron::NativeWindowMac::Close() (#31759)
* test: fix crash in electron::NativeWindowMac::Close()

* remove extra close

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2021-11-09 12:09:57 -05:00
Sudowoodo Release Bot
71cd259b7b Bump v14.2.1 2021-11-08 10:41:28 -08:00
trop[bot]
27fb917577 fix: <webview> background transparency (#31727)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2021-11-05 20:09:30 -07:00
trop[bot]
b763478ae5 test: deflake <webview> tag loads devtools extensions on WOA (#31714)
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2021-11-04 19:46:49 -04:00
Pedro Pontes
8417c5ae41 chore: cherry-pick 656c2769c5 from v8 (#31677)
Co-authored-by: Electron Bot <electron@github.com>
2021-11-04 16:07:57 +09:00
trop[bot]
4f3003dd40 fix: incorrect Content-Disposition serialization (#31692)
* fix: incorrect Content-Disposition serialization

* test: fixup test

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-11-04 10:00:28 +09:00
Pedro Pontes
38ca1aeab7 chore: cherry-pick 91dd4f79ab5b from chromium (#31681)
* chore: cherry-pick 91dd4f79ab5b from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-11-03 13:44:14 -04:00
Pedro Pontes
a6636c3ca6 chore: cherry-pick 014e1f857c33 from v8 (#31672)
* chore: cherry-pick 014e1f857c33 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-11-03 20:39:22 +09:00
Pedro Pontes
20c63a644b chore: cherry-pick 45f9dcf5021d from chromium (#31670)
* chore: cherry-pick 45f9dcf5021d from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-11-03 20:39:07 +09:00
Pedro Pontes
e446b29afb chore: cherry-pick feef10137b16 from v8 (#31664)
* chore: cherry-pick feef10137b16 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-11-02 13:29:56 -04:00
trop[bot]
a5c6a79a08 fix: crash on close window when webContents destroyed (#31645)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-11-01 16:50:03 -04:00
Milan Burda
bb418b6e06 chore: update chore_add_context_to_context_aware_module_prevention.patch (#31579) (#31627)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2021-11-01 16:43:41 -04:00
Shelley Vohr
8638e8cea9 fix: silent print settings (#31617) 2021-11-01 10:03:49 -04:00
Pedro Pontes
cb206b8a9f chore: cherry-pick 0894af410c4e from chromium (#31544)
* chore: cherry-pick 0894af410c4e from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-10-26 17:45:28 +09:00
trop[bot]
47364ace72 build: retry hasher function if it fails first time (#31580)
* build: retry hasher function if it fails first time

* Update script/release/get-url-hash.js

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>

Co-authored-by: Samuel Attard <sattard@slack-corp.com>
Co-authored-by: Samuel Attard <sam@electronjs.org>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2021-10-26 17:41:33 +09:00
trop[bot]
7746f1d13e docs: win.getParentWindow() returns BrowserWindow | null (#31575)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-10-26 17:38:33 +09:00
Pedro Pontes
58dd15f165 chore: cherry-pick 36028012d897 from chromium (#31540)
Co-authored-by: Electron Bot <electron@github.com>
2021-10-25 13:28:58 -04:00
trop[bot]
d9a25cff7c fix: MediaMetadata not working properly (#31533)
* fix: MediaMetadata not working properly

* chore: update patches

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-10-25 14:01:14 +02:00
Pedro Pontes
018bee38bc chore: cherry-pick 8af66de55aad from chromium (#31524)
* chore: cherry-pick 8af66de55aad from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-10-25 09:47:33 +09:00
Pedro Pontes
9f76b99382 chore: cherry-pick c69dddfe1cde from chromium (#31520)
* chore: cherry-pick c69dddfe1cde from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-10-22 21:19:22 +09:00
trop[bot]
35be7656ba fix: black window on screen capture when content protection is enabled (#31551)
Co-authored-by: Micha Hanselmann <mhanselmann@microsoft.com>
2021-10-22 21:16:23 +09:00
Pedro Pontes
eecda4656e chore: cherry-pick 6de4e210688e from v8 (#31502)
* chore: cherry-pick 6de4e210688e from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-10-22 21:14:52 +09:00
Pedro Pontes
22bd03d54b chore: cherry-pick 29be6884cb8a from v8 (#31517) 2021-10-21 15:45:35 -04:00
Pedro Pontes
a641468b12 chore: cherry-pick 2e7c9b33453b from chromium (#31498) 2021-10-21 15:18:18 -04:00
Pedro Pontes
2764c06d0e chore: cherry-pick 8a822e28adea from pdfium (#31494) 2021-10-21 15:04:49 -04:00
trop[bot]
0d6a3d27c2 fix: event with invalid timestamp in trace log (#31421)
* fix: event with invalid timestamp in trace log

When node is started within Electron's environment it doesn't
initialize v8 and time of v8's start is never set. As a result
we log v8's start time as 0 and it breaks timestamps in the
trace log. With this change we log v8's start time only when
it was initialized by node.

* fixup patch for 14-x-y

Co-authored-by: Cezary Kulakowski <cezary@openfin.co>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2021-10-21 14:44:02 -04:00
trop[bot]
76e9225c2b feat: warn when ipcRenderer.sendSync() called with no listeners for channel (#31433)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-10-21 09:09:17 +09:00
trop[bot]
1e23632184 fix: ensure TracingAgent in place for SWs (#31475)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-10-21 09:08:04 +09:00
Sudowoodo Release Bot
c2b3c974e0 Bump v14.2.0 2021-10-20 09:56:28 -07:00
trop[bot]
9062352dd8 fix: don't use private enterprise APIs in MAS build (#31487)
* fix: don't use private enterprise APIs in MAS build

* Update .patches

Co-authored-by: VerteDinde <khammond@slack-corp.com>
Co-authored-by: Samuel Attard <sam@electronjs.org>
2021-10-20 09:19:02 -07:00
trop[bot]
ca1d4784b7 fix: link to image windows progress bar image was linked with square brackets [] insted of parenthesis () and to github asset storage instead of local image directory. (#31471)
Co-authored-by: Daniel Ramp <12480131+DanielRamp@users.noreply.github.com>
2021-10-19 20:40:31 +09:00
trop[bot]
857f5a8794 Avoid Undefined Variable In printToPdf Example (#31464)
Co-authored-by: universalstrapping <90921972+universalstrapping@users.noreply.github.com>
2021-10-19 17:41:50 +09:00
trop[bot]
90c5f930fa fix: add isDestroyed check (#31467)
* Added isDestroyed check

fix: https://github.com/electron/electron/issues/31196

* fix: unregister frame name

Unregister the frame name so that we do not accidentally unregister the wrong window later on in case there is a timing issue with the events

* fix; check if webContents is destroyed

* fix: check if window/webContents is destroyed

Co-authored-by: Cheng Zhao <github@zcbenz.com>

Co-authored-by: t57ser <seve@live.at>
Co-authored-by: Cheng Zhao <github@zcbenz.com>
2021-10-19 17:40:30 +09:00
Cheng Zhao
c5a7ccc48b fix: generate valid config.gypi (#31443)
* fix: generate valid config.gypi

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-10-18 12:20:24 -05:00
trop[bot]
d8802f8b4c chore: refactor persisting permission granted to serial ports (#31440)
(cherry picked from commit 515785aabe)

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2021-10-18 10:42:36 -04:00
trop[bot]
6fd689eb11 fix: also pass securityOrigin to media permissions request handler (#31436)
Co-authored-by: Maxime Serrano <mserrano@alumni.cmu.edu>
2021-10-15 13:32:27 +09:00
trop[bot]
2eb43ede35 fix: reset render_frame_disposed_ after render frame host change (#31425)
* fix: reset render_frame_disposed_ after hang

* fix: handle exception in webContents.send

Co-authored-by: VerteDinde <keeleymhammond@gmail.com>
Co-authored-by: VerteDinde <khammond@slack-corp.com>
2021-10-15 09:06:57 +09:00
trop[bot]
15454fd693 fix: mac window crash native theme update (#31428)
Co-authored-by: Samuel Maddock <samuel.maddock@gmail.com>
2021-10-15 09:06:21 +09:00
trop[bot]
de1eef75dc docs: update Versioning doc (#31387)
* fix information

* move historical section to bottom

* Update docs/tutorial/electron-versioning.md

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* chore: fix small typo

Co-authored-by: Erick Zhao <erick@hotmail.ca>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
2021-10-13 11:25:13 +09:00
trop[bot]
7a3541d5af fix: correctly notify WebViewGuestDelegate when webview is detached (#31374)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2021-10-11 14:36:11 +09:00
trop[bot]
6be63fe11e chore: add logging for print_backend failures (#31287)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-10-11 14:33:02 +09:00
trop[bot]
bd6b139b16 docs: add missing 'context-menu' event to webview-tag.md (#31310)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-10-11 14:28:36 +09:00
Pedro Pontes
911f966be3 chore: cherry-pick 3a5bafa35def from chromium (#31364)
* chore: cherry-pick 3a5bafa35def from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-10-11 14:27:22 +09:00
Pedro Pontes
5302dcf5ed chore: cherry-pick b2c4e4dc21e5 from chromium (#31362)
* chore: cherry-pick b2c4e4dc21e5 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-10-11 09:47:06 +09:00
trop[bot]
25159f3ee1 fix: crash on missing render frame (#31333)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-10-11 09:34:32 +09:00
Pedro Pontes
042f00d25a chore: cherry-pick 6a8a2098f9fa from chromium (#31230)
* chore: cherry-pick 6a8a2098f9fa from chromium

* chore: update patches

* fix: cherry-pick from M90 instead.

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-10-10 05:41:58 -07:00
Pedro Pontes
dfc9cb6e7f chore: cherry-pick 6584528aeb0f0 from webrtc and 36e370cf4db9a from chromium (#31358)
* chore: cherry-pick 6584528aeb0f0 from webrtc and 36e370cf4db9a from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-10-09 23:25:09 -07:00
94 changed files with 5028 additions and 345 deletions

View File

@@ -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") {

View File

@@ -1 +1 @@
14.1.1
14.2.2

View File

@@ -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()`

View File

@@ -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
})

View File

@@ -1479,8 +1479,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}`)

View File

@@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -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.

View File

@@ -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.

View File

@@ -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:
![1.x Versioning](../images/versioning-sketch-0.png)
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`.
![Stabilization Branches](../images/versioning-sketch-1.png)
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.
![Multiple Stability Branches](../images/versioning-sketch-2.png)
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 youre 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:
![Semvers and Releases](../images/versioning-sketch-7.png)
# 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:
![1.x Versioning](../images/versioning-sketch-0.png)
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.

View File

@@ -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]
![Windows Progress Bar](../images/windows-progress-bar.png)
On macOS, the progress bar will be displayed as a part of the dock icon.

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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({

View File

@@ -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',
}

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "14.1.1",
"version": "14.2.2",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {

View File

@@ -108,3 +108,22 @@ 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
mas_gate_private_enterprise_APIs
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
fix_aspect_ratio_with_max_size.patch

View File

@@ -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);
}
};

View File

@@ -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');

View 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

View 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());
}

View 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

View 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.

View 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) {

View 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 => {

View 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);

View 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_

View 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));

View 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>

View 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);
}

View File

@@ -10,33 +10,94 @@ 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..1263d679a5174beb960265989c370dd4a58ae7b4 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() {
@@ -231,18 +231,24 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
media::AudioManager::GetGlobalAppName());
#endif
- if (system_media_controls_) {
+ if (/* DISABLES CODE */ (0)) {
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
- system_media_controls_->AddObserver(this);
- system_media_controls_notifier_ =
- std::make_unique<SystemMediaControlsNotifier>(
- system_media_controls_.get());
- } else {
- // If we can't access system media controls, then directly listen for media
- // key keypresses instead.
+ // This is required for proper functioning of MediaMetadata.
+ system_media_controls_->AddObserver(this);
+ system_media_controls_notifier_ =
+ std::make_unique<SystemMediaControlsNotifier>(
+ system_media_controls_.get());
+
+ // 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, ui::MediaKeysListener::Scope::kGlobal);
- this, ui::MediaKeysListener::Scope::kGlobal);
- DCHECK(media_keys_listener_);
- }
+ this, scope);
+#else
+ media_keys_listener_ = ui::MediaKeysListener::Create(
+ this, ui::MediaKeysListener::Scope::kGlobal);
+#endif
DCHECK(media_keys_listener_);
}
+ 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

View 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_

View File

@@ -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);
};

View 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

View File

@@ -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 <>

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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)));
}
}

View File

@@ -15,5 +15,7 @@
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC",
"src/electron/patches/angle": "src/third_party/angle"
"src/electron/patches/angle": "src/third_party/angle",
"src/electron/patches/pdfium": "src/third_party/pdfium"
}

View File

@@ -6,7 +6,6 @@ feat_initialize_asar_support.patch
expose_get_builtin_module_function.patch
build_add_gn_build_files.patch
fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
feat_add_new_built_with_electron_variable_to_config_gypi.patch
feat_add_flags_for_low-level_hooks_and_exceptions.patch
fix_expose_tracing_agent_and_use_tracing_tracingcontroller_instead.patch
pass_all_globals_through_require.patch
@@ -37,3 +36,4 @@ src_remove_extra_semi_after_member_fn.patch
errors_refactor_to_use_more_primordials.patch
repl_fix_crash_when_sharedarraybuffer_disabled.patch
fix_remove_expired_dst_root_ca_x3.patch
fix_event_with_invalid_timestamp_in_trace_log.patch

View File

@@ -7,10 +7,10 @@ This adds GN build files for Node, so we don't have to build with GYP.
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..446119163d1f7bad577cb0b7b217ecf24b994526
index 0000000000000000000000000000000000000000..f267a14ffd12828417e441c09ca3a673236dfd34
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,360 @@
@@ -0,0 +1,352 @@
+import("//electron/build/asar.gni")
+import("//v8/gni/v8.gni")
+
@@ -75,20 +75,12 @@ index 0000000000000000000000000000000000000000..446119163d1f7bad577cb0b7b217ecf2
+ ]
+}
+
+action("generate_config_gypi") {
+ outputs = [
+ "$target_gen_dir/config.gypi",
+ ]
+ script = "tools/generate_config_gypi.py"
+ args = rebase_path(outputs, root_build_dir)
+}
+
+chdir_action("node_js2c") {
+ deps = [
+ ":generate_config_gypi",
+ "//electron:generate_config_gypi",
+ ":node_js2c_inputs",
+ ]
+ config_gypi = [ "$target_gen_dir/config.gypi" ]
+ config_gypi = [ "$root_gen_dir/config.gypi" ]
+ inputs = library_files + config_gypi
+ outputs = [
+ "$target_gen_dir/node_javascript.cc",
@@ -319,10 +311,10 @@ index 0000000000000000000000000000000000000000..446119163d1f7bad577cb0b7b217ecf2
+
+copy("node_gypi_headers") {
+ deps = [
+ ":generate_config_gypi",
+ "//electron:generate_config_gypi",
+ ]
+ sources = [
+ "$target_gen_dir/config.gypi",
+ "$root_gen_dir/config.gypi",
+ "common.gypi",
+ ]
+ outputs = [
@@ -1655,23 +1647,6 @@ index 5419747db7b6504ad9d61b1cd3d53d93913e360f..e51bf333b77e67af188a3d352ca22b12
// The NAPI_VERSION provided by this version of the runtime. This is the version
// which the Node binary being built supports.
diff --git a/tools/generate_config_gypi.py b/tools/generate_config_gypi.py
new file mode 100644
index 0000000000000000000000000000000000000000..01f62d4ae6e3b9d539444e3dff069f0011353caa
--- /dev/null
+++ b/tools/generate_config_gypi.py
@@ -0,0 +1,11 @@
+# TODO: assess which if any of the config variables are important to include in
+# the js2c'd config.gypi.
+import sys
+
+def main(args):
+ out = args[0]
+ with open(out, 'w') as f:
+ f.write("{'variables':{}}\n")
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/tools/generate_gn_filenames_json.py b/tools/generate_gn_filenames_json.py
new file mode 100755
index 0000000000000000000000000000000000000000..e5fd79da5323e7039730fd8cca66caae8c84e903

View File

@@ -8,7 +8,7 @@ modules from being used in the renderer process. This should be upstreamed as
a customizable error message.
diff --git a/src/node_binding.cc b/src/node_binding.cc
index ca5a01f925a2ae69ba4295d82316e546f45c60cd..a0f6730de75b9b1dc58e2cec5ed64f9619162a2b 100644
index ca5a01f925a2ae69ba4295d82316e546f45c60cd..7aa9190b383050dd7cdf7ae3f9620105b6a6f473 100644
--- a/src/node_binding.cc
+++ b/src/node_binding.cc
@@ -3,6 +3,7 @@
@@ -27,7 +27,7 @@ index ca5a01f925a2ae69ba4295d82316e546f45c60cd..a0f6730de75b9b1dc58e2cec5ed64f96
+ char errmsg[1024];
+ snprintf(errmsg,
+ sizeof(errmsg),
+ "Loading non-context-aware native module in renderer: '%s', but app.allowRendererProcessReuse is true. See https://github.com/electron/electron/issues/18397.",
+ "Loading non-context-aware native module in renderer: '%s'. See https://github.com/electron/electron/issues/18397.",
+ *filename);
+ env->ThrowError(errmsg);
return false;

View File

@@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Tue, 2 Oct 2018 11:39:58 -0700
Subject: feat: add new built_with_electron variable to config.gypi
This allows 3rd-party native modules to know whether they're being built
against Electron.
diff --git a/tools/generate_config_gypi.py b/tools/generate_config_gypi.py
index 01f62d4ae6e3b9d539444e3dff069f0011353caa..d8b279f590c115108d5dca879747de7b0c9f1934 100644
--- a/tools/generate_config_gypi.py
+++ b/tools/generate_config_gypi.py
@@ -5,7 +5,7 @@ import sys
def main(args):
out = args[0]
with open(out, 'w') as f:
- f.write("{'variables':{}}\n")
+ f.write("{'variables':{'built_with_electron': 1}}\n")
if __name__ == '__main__':
main(sys.argv[1:])

View File

@@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cezary Kulakowski <cezary@openfin.co>
Date: Fri, 8 Oct 2021 11:18:58 +0200
Subject: fix: event with invalid timestamp in trace log
When node is started within Electron's environment it doesn't
initialize v8 and time of v8's start is never set. As a result
we log v8's start time as 0 and it breaks timestamps in the
trace log. With this change we log v8's start time only when
it was initialized by node.
diff --git a/src/env.cc b/src/env.cc
index 7155ae67ac625b0d1503dbb8e5cd0a61a90dce24..28fbe05c6f9e41cb2a43fb3a99fd801a31fbdf23 100644
--- a/src/env.cc
+++ b/src/env.cc
@@ -377,9 +377,11 @@ Environment::Environment(IsolateData* isolate_data,
performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT);
performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_NODE_START,
per_process::node_start_time);
- performance_state_->Mark(
- performance::NODE_PERFORMANCE_MILESTONE_V8_START,
- performance::performance_v8_start);
+ if (per_process::v8_initialized) {
+ performance_state_->Mark(
+ performance::NODE_PERFORMANCE_MILESTONE_V8_START,
+ performance::performance_v8_start);
+ }
if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
TRACING_CATEGORY_NODE1(environment)) != 0) {

1
patches/pdfium/.patches Normal file
View File

@@ -0,0 +1 @@
m94_use_more_safe_arithmetic_in_cfx_dibbase.patch

View File

@@ -0,0 +1,142 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tom Sepez <tsepez@chromium.org>
Date: Thu, 14 Oct 2021 18:29:32 +0000
Subject: M94: Use more safe arithmetic in CFX_DIBBase
Most of the calculations are "safe" because we know that the DIB
has validated sizes before allocating a buffer, and that calculations
in terms of bytes won't overflow and will be within the buffer. But
calculations in terms of bits might create overflow in temporaries,
so use safe arithmetic there instead.
Re-arranging the order of operations thus converting to bytes first
might be one option, but we want to handle the 1 bpp case.
Test would require large images that might not be possible on
all platforms.
Bug: chromium:1253399
Change-Id: I3c6c5b8b1f1bf3f429c7d377a8a84c5ab53cafd9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/85510
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
(cherry picked from commit a8b293732a0160d1bc1d5b0ad5744922f0f820d5)
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/85950
diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp
index 6f9b42013f2abfc8dbb4a362f2b9ec75a89525cb..7da0f1cb3f811abe36a731e628d3b202e6d6d8ab 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.cpp
+++ b/core/fxge/dib/cfx_bitmapcomposer.cpp
@@ -6,6 +6,7 @@
#include "core/fxge/dib/cfx_bitmapcomposer.h"
+#include "core/fxcrt/fx_safe_types.h"
#include "core/fxge/cfx_cliprgn.h"
#include "core/fxge/dib/cfx_dibitmap.h"
@@ -110,9 +111,16 @@ void CFX_BitmapComposer::ComposeScanline(int line,
(m_DestLeft - m_pClipRgn->GetBox().left);
}
uint8_t* dest_scan = m_pBitmap->GetWritableScanline(line + m_DestTop);
- if (dest_scan)
- dest_scan += m_DestLeft * m_pBitmap->GetBPP() / 8;
+ if (dest_scan) {
+ FX_SAFE_UINT32 offset = m_DestLeft;
+ offset *= m_pBitmap->GetBPP();
+ offset /= 8;
+ if (!offset.IsValid())
+ return;
+ // Help some compilers perform pointer arithmetic against safe numerics.
+ dest_scan += static_cast<uint32_t>(offset.ValueOrDie());
+ }
uint8_t* dest_alpha_scan =
m_pBitmap->GetWritableAlphaMaskScanline(line + m_DestTop);
if (dest_alpha_scan)
diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index 4ec0ddbf9b178d9856045e3d01455fc8914fd90b..dfe3a3b694bf39242d92e8bf8c43277c66f70c16 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -632,15 +632,25 @@ RetainPtr<CFX_DIBitmap> CFX_DIBBase::Clone(const FX_RECT* pClip) const {
}
}
} else {
- int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8;
- if (m_Pitch < static_cast<uint32_t>(copy_len))
- copy_len = m_Pitch;
+ FX_SAFE_UINT32 copy_len = pNewBitmap->GetWidth();
+ copy_len *= pNewBitmap->GetBPP();
+ copy_len += 7;
+ copy_len /= 8;
+ if (!copy_len.IsValid())
+ return nullptr;
+
+ copy_len = std::min<uint32_t>(m_Pitch, copy_len.ValueOrDie());
+
+ FX_SAFE_UINT32 offset = rect.left;
+ offset *= GetBppFromFormat(m_Format);
+ offset /= 8;
+ if (!offset.IsValid())
+ return nullptr;
for (int row = rect.top; row < rect.bottom; ++row) {
- const uint8_t* src_scan =
- GetScanline(row) + rect.left * GetBppFromFormat(m_Format) / 8;
+ const uint8_t* src_scan = GetScanline(row) + offset.ValueOrDie();
uint8_t* dest_scan = pNewBitmap->GetWritableScanline(row - rect.top);
- memcpy(dest_scan, src_scan, copy_len);
+ memcpy(dest_scan, src_scan, copy_len.ValueOrDie());
}
}
return pNewBitmap;
diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp
index d7ccf6cfa0d144b51d327311b668d2a7c28b44e7..c810cde2cac439a3bbb6534763bf5ffa91226fa5 100644
--- a/core/fxge/dib/cfx_dibitmap.cpp
+++ b/core/fxge/dib/cfx_dibitmap.cpp
@@ -217,8 +217,14 @@ bool CFX_DIBitmap::TransferWithUnequalFormats(
if (GetBppFromFormat(m_Format) == 8)
dest_format = FXDIB_Format::k8bppMask;
+ FX_SAFE_UINT32 offset = dest_left;
+ offset *= GetBPP();
+ offset /= 8;
+ if (!offset.IsValid())
+ return false;
+
uint8_t* dest_buf =
- m_pBuffer.Get() + dest_top * m_Pitch + dest_left * GetBPP() / 8;
+ m_pBuffer.Get() + dest_top * m_Pitch + offset.ValueOrDie();
std::vector<uint32_t, FxAllocAllocator<uint32_t>> d_plt;
return ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height,
pSrcBitmap, src_left, src_top, &d_plt);
@@ -498,7 +504,13 @@ uint32_t CFX_DIBitmap::GetPixel(int x, int y) const {
if (!m_pBuffer)
return 0;
- uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8;
+ FX_SAFE_UINT32 offset = x;
+ offset *= GetBPP();
+ offset /= 8;
+ if (!offset.IsValid())
+ return 0;
+
+ uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + offset.ValueOrDie();
switch (GetFormat()) {
case FXDIB_Format::k1bppMask: {
if ((*pos) & (1 << (7 - x % 8))) {
@@ -537,7 +549,13 @@ void CFX_DIBitmap::SetPixel(int x, int y, uint32_t color) {
if (x < 0 || x >= m_Width || y < 0 || y >= m_Height)
return;
- uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8;
+ FX_SAFE_UINT32 offset = x;
+ offset *= GetBPP();
+ offset /= 8;
+ if (!offset.IsValid())
+ return;
+
+ uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + offset.ValueOrDie();
switch (GetFormat()) {
case FXDIB_Format::k1bppMask:
if (color >> 24) {

View File

@@ -9,3 +9,9 @@ regexp_add_a_currently_failing_cctest_for_irregexp_reentrancy.patch
regexp_allow_reentrant_irregexp_execution.patch
regexp_remove_the_stack_parameter_from_regexp_matchers.patch
cherry-pick-5c4acf2ae64a.patch
merge_inspector_use_ephemeron_table_for_exception_metadata.patch
cherry-pick-6de4e210688e.patch
merged_cppgc_fix_marking_of_ephemerons_with_keys_in_construction.patch
cherry-pick-014e1f857c33.patch
cherry-pick-feef10137b16.patch
cherry-pick-5d2b5e7c006c.patch

View File

@@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marja=20H=C3=B6ltt=C3=A4?= <marja@chromium.org>
Date: Mon, 25 Oct 2021 12:17:15 +0200
Subject: Merged: [super ic] Fix receiver vs lookup start object confusion
related to module exports
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Revision: e4dba97006ca20337deafb85ac00524a94a62fe
BUG=chromium:1260577
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
R=ishell@chromium.org
Change-Id: Ia85235fecdb37a5da6a28f7a0092a754a8620552
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3240826
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.4@{#48}
Cr-Branched-From: 3b51863bc25492549a8bf96ff67ce481b1a3337b-refs/heads/9.4.146@{#1}
Cr-Branched-From: 2890419fc8fb9bdb507fdd801d76fa7dd9f022b5-refs/heads/master@{#76233}
diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc
index 64d64cd017c354be04561e1c7487437420febb48..f27e3b7f590a76ad4ca995c21f2d279bc9d47042 100644
--- a/src/ic/accessor-assembler.cc
+++ b/src/ic/accessor-assembler.cc
@@ -846,8 +846,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
Comment("module export");
TNode<UintPtrT> index =
DecodeWord<LoadHandler::ExportsIndexBits>(handler_word);
- TNode<Module> module = LoadObjectField<Module>(
- CAST(p->receiver()), JSModuleNamespace::kModuleOffset);
+ TNode<Module> module =
+ LoadObjectField<Module>(CAST(holder), JSModuleNamespace::kModuleOffset);
TNode<ObjectHashTable> exports =
LoadObjectField<ObjectHashTable>(module, Module::kExportsOffset);
TNode<Cell> cell = CAST(LoadFixedArrayElement(exports, index));
diff --git a/src/ic/ic.cc b/src/ic/ic.cc
index 047a74cfd3a2608004b38278a1565fb818e5cc69..b1c76e371a7a5b2a1f37df38d64c96e719417408 100644
--- a/src/ic/ic.cc
+++ b/src/ic/ic.cc
@@ -983,7 +983,13 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
// We found the accessor, so the entry must exist.
DCHECK(entry.is_found());
int index = ObjectHashTable::EntryToValueIndex(entry);
- return LoadHandler::LoadModuleExport(isolate(), index);
+ Handle<Smi> smi_handler =
+ LoadHandler::LoadModuleExport(isolate(), index);
+ if (holder_is_lookup_start_object) {
+ return smi_handler;
+ }
+ return LoadHandler::LoadFromPrototype(isolate(), map, holder,
+ smi_handler);
}
Handle<Object> accessors = lookup->GetAccessors();

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nico Hartmann <nicohartmann@chromium.org>
Date: Mon, 25 Oct 2021 10:58:59 +0200
Subject: Merged: [TurboFan] Do not use NumberConstant as immediate in x86
Bug: chromium:1254189
(cherry picked from commit bdf31d5883607db4377b519d7308fb1e639a0448)
Change-Id: I1d4426fee8392c7a680ad67af4bf2745d04b2e52
No-Try: true
No-Presubmit: true
No-Tree-Checks: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3268905
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.6@{#22}
Cr-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
Cr-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
diff --git a/src/compiler/backend/ia32/instruction-selector-ia32.cc b/src/compiler/backend/ia32/instruction-selector-ia32.cc
index 5d7c8fbec25a371e3946939b97ac64b955158999..71ef02842c82ec2eb3b5d4ec86f26a1a3eb7a582 100644
--- a/src/compiler/backend/ia32/instruction-selector-ia32.cc
+++ b/src/compiler/backend/ia32/instruction-selector-ia32.cc
@@ -99,11 +99,14 @@ class IA32OperandGenerator final : public OperandGenerator {
bool CanBeImmediate(Node* node) {
switch (node->opcode()) {
case IrOpcode::kInt32Constant:
- case IrOpcode::kNumberConstant:
case IrOpcode::kExternalConstant:
case IrOpcode::kRelocatableInt32Constant:
case IrOpcode::kRelocatableInt64Constant:
return true;
+ case IrOpcode::kNumberConstant: {
+ const double value = OpParameter<double>(node->op());
+ return bit_cast<int64_t>(value) == 0;
+ }
case IrOpcode::kHeapConstant: {
// TODO(bmeurer): We must not dereference handles concurrently. If we
// really have to this here, then we need to find a way to put this

View File

@@ -0,0 +1,77 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marja=20H=C3=B6ltt=C3=A4?= <marja@chromium.org>
Date: Fri, 3 Sep 2021 11:46:26 +0200
Subject: Fix class variable redeclaration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
ParserBase::ParseClassLiteral and BaseConsumedPreparseData::RestoreDataForScope
both declare the class variable, but the logic is so complex
that they sometimes ended up both declaring it.
This is further complicated by some of the variable values (esp.
inner_scope_calls_eval_) potentially changing in between, so we can't
just redo the same logic any more.
Forcefully make it work by making RestoreDataForScope declare the variable
iff ParseClassLiteral didn't.
Bug: chromium:1245870
Change-Id: I777fd9d78145240448fc25709d2b118977d91056
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3140596
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76654}
diff --git a/src/parsing/preparse-data.cc b/src/parsing/preparse-data.cc
index 1643c6ba1a648e53f8b75bb9c910ed605ce82183..f368a11f9ab09c745feaffa8f406771bc3f858ea 100644
--- a/src/parsing/preparse-data.cc
+++ b/src/parsing/preparse-data.cc
@@ -666,12 +666,13 @@ void BaseConsumedPreparseData<Data>::RestoreDataForScope(
scope->AsDeclarationScope()->RecordNeedsPrivateNameContextChainRecalc();
}
if (ShouldSaveClassVariableIndexField::decode(scope_data_flags)) {
- Variable* var;
- // An anonymous class whose class variable needs to be saved do not
+ Variable* var = scope->AsClassScope()->class_variable();
+ // An anonymous class whose class variable needs to be saved might not
// have the class variable created during reparse since we skip parsing
// the inner scopes that contain potential access to static private
// methods. So create it now.
- if (scope->AsClassScope()->is_anonymous_class()) {
+ if (var == nullptr) {
+ DCHECK(scope->AsClassScope()->is_anonymous_class());
var = scope->AsClassScope()->DeclareClassVariable(
ast_value_factory, nullptr, kNoSourcePosition);
AstNodeFactory factory(ast_value_factory, zone);
@@ -679,9 +680,6 @@ void BaseConsumedPreparseData<Data>::RestoreDataForScope(
factory.NewVariableDeclaration(kNoSourcePosition);
scope->declarations()->Add(declaration);
declaration->set_var(var);
- } else {
- var = scope->AsClassScope()->class_variable();
- DCHECK_NOT_NULL(var);
}
var->set_is_used();
var->ForceContextAllocation();
diff --git a/test/mjsunit/regress/regress-crbug-1245870.js b/test/mjsunit/regress/regress-crbug-1245870.js
new file mode 100644
index 0000000000000000000000000000000000000000..2ef3f753d500880717f10f26ed8cca4a47079196
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-1245870.js
@@ -0,0 +1,14 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+class Outer {
+ test() {
+ return class {
+ static #a() { }
+ b = eval();
+ };
+ }
+}
+const obj = new Outer();
+obj.test();

View File

@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Toon Verwaest <verwaest@chromium.org>
Date: Wed, 27 Oct 2021 11:02:06 +0200
Subject: Merged: [runtime] Check if we have a pending exception before
returning it
Revision: be55c16e50e714475034b00ed2682f0813794d15
BUG=chromium:1263462
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
R=cbruni@chromium.org
Change-Id: Ib7de676fe614403674fcd2745c574f7e91ded23f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3247033
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.4@{#52}
Cr-Branched-From: 3b51863bc25492549a8bf96ff67ce481b1a3337b-refs/heads/9.4.146@{#1}
Cr-Branched-From: 2890419fc8fb9bdb507fdd801d76fa7dd9f022b5-refs/heads/master@{#76233}
diff --git a/src/execution/isolate-inl.h b/src/execution/isolate-inl.h
index a4dad038f0dcc593cddf0aed112e475bfca32e5a..225a096def07c5ffc4dee999177e3048fe2ac4c0 100644
--- a/src/execution/isolate-inl.h
+++ b/src/execution/isolate-inl.h
@@ -34,7 +34,7 @@ NativeContext Isolate::raw_native_context() {
}
Object Isolate::pending_exception() {
- DCHECK(has_pending_exception());
+ CHECK(has_pending_exception());
DCHECK(!thread_local_top()->pending_exception_.IsException(this));
return thread_local_top()->pending_exception_;
}

View File

@@ -0,0 +1,379 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jaroslav Sevcik <jarin@chromium.org>
Date: Tue, 14 Sep 2021 21:08:03 +0200
Subject: Merge: [inspector] Use ephemeron table for exception metadata
EphemeronHashTable does not trigger interrupts when accessed
(as opposed to calling the WeakMapGet builtin), so it avoids
the use-after-free problem when reading exception metadata
triggers session disconnect while holding a reference
to the session.
(cherry picked from commit 7994004493df2c9a24372587312ef6c458c7ed2b)
Bug: chromium:1241860
No-Try: true
No-Presubmit: true
No-Tree-Checks: true
Change-Id: I29264b04b8daf682e7c33a97faedf50e323d57c4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3218987
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.5@{#38}
Cr-Branched-From: 4a03d61accede9dd0e3e6dc0456ff5a0e3f792b4-refs/heads/9.5.172@{#1}
Cr-Branched-From: 9a607043cb3161f8ceae1583807bece595388108-refs/heads/main@{#76741}
diff --git a/src/api/api.h b/src/api/api.h
index 7d2a0c3e9cfb9501b21aca7ffed7b171b54831d7..047d43053ecbdc5da8821e27270f5eb5aa714e54 100644
--- a/src/api/api.h
+++ b/src/api/api.h
@@ -33,7 +33,7 @@ namespace debug {
class AccessorPair;
class GeneratorObject;
class Script;
-class WeakMap;
+class EphemeronTable;
} // namespace debug
// Constants used in the implementation of the API. The most natural thing
@@ -126,7 +126,7 @@ class RegisteredExtension {
V(Proxy, JSProxy) \
V(debug::GeneratorObject, JSGeneratorObject) \
V(debug::Script, Script) \
- V(debug::WeakMap, JSWeakMap) \
+ V(debug::EphemeronTable, EphemeronHashTable) \
V(debug::AccessorPair, AccessorPair) \
V(Promise, JSPromise) \
V(Primitive, Object) \
diff --git a/src/debug/debug-interface.cc b/src/debug/debug-interface.cc
index 7c12090b9946e406ecea5ac5883b9310716403a4..e4abd3dd2f171d6499ddcd6a77b9e4fe9c234f7f 100644
--- a/src/debug/debug-interface.cc
+++ b/src/debug/debug-interface.cc
@@ -1182,61 +1182,43 @@ TypeProfile::ScriptData TypeProfile::GetScriptData(size_t i) const {
return ScriptData(i, type_profile_);
}
-v8::MaybeLocal<v8::Value> WeakMap::Get(v8::Local<v8::Context> context,
- v8::Local<v8::Value> key) {
- PREPARE_FOR_EXECUTION(context, WeakMap, Get, Value);
- auto self = Utils::OpenHandle(this);
- Local<Value> result;
- i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
- has_pending_exception =
- !ToLocal<Value>(i::Execution::CallBuiltin(isolate, isolate->weakmap_get(),
- self, arraysize(argv), argv),
- &result);
- RETURN_ON_FAILED_EXECUTION(Value);
- RETURN_ESCAPED(result);
+MaybeLocal<v8::Value> EphemeronTable::Get(v8::Isolate* isolate,
+ v8::Local<v8::Value> key) {
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ auto self = i::Handle<i::EphemeronHashTable>::cast(Utils::OpenHandle(this));
+ i::Handle<i::Object> internal_key = Utils::OpenHandle(*key);
+ DCHECK(internal_key->IsJSReceiver());
+
+ i::Handle<i::Object> value(self->Lookup(internal_key), internal_isolate);
+
+ if (value->IsTheHole()) return {};
+ return Utils::ToLocal(value);
}
-v8::Maybe<bool> WeakMap::Delete(v8::Local<v8::Context> context,
- v8::Local<v8::Value> key) {
- PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, WeakMap, Delete, Nothing<bool>(),
- InternalEscapableScope, false);
- auto self = Utils::OpenHandle(this);
- Local<Value> result;
- i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
- has_pending_exception = !ToLocal<Value>(
- i::Execution::CallBuiltin(isolate, isolate->weakmap_delete(), self,
- arraysize(argv), argv),
- &result);
- RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
- return Just(result->IsTrue());
-}
-
-v8::MaybeLocal<WeakMap> WeakMap::Set(v8::Local<v8::Context> context,
- v8::Local<v8::Value> key,
- v8::Local<v8::Value> value) {
- PREPARE_FOR_EXECUTION(context, WeakMap, Set, WeakMap);
- auto self = Utils::OpenHandle(this);
- i::Handle<i::Object> result;
- i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
- Utils::OpenHandle(*value)};
- has_pending_exception =
- !i::Execution::CallBuiltin(isolate, isolate->weakmap_set(), self,
- arraysize(argv), argv)
- .ToHandle(&result);
- RETURN_ON_FAILED_EXECUTION(WeakMap);
- RETURN_ESCAPED(Local<WeakMap>::Cast(Utils::ToLocal(result)));
-}
-
-Local<WeakMap> WeakMap::New(v8::Isolate* isolate) {
+Local<EphemeronTable> EphemeronTable::Set(v8::Isolate* isolate,
+ v8::Local<v8::Value> key,
+ v8::Local<v8::Value> value) {
+ auto self = i::Handle<i::EphemeronHashTable>::cast(Utils::OpenHandle(this));
+ i::Handle<i::Object> internal_key = Utils::OpenHandle(*key);
+ i::Handle<i::Object> internal_value = Utils::OpenHandle(*value);
+ DCHECK(internal_key->IsJSReceiver());
+
+ i::Handle<i::EphemeronHashTable> result(
+ i::EphemeronHashTable::Put(self, internal_key, internal_value));
+
+ return ToApiHandle<EphemeronTable>(result);
+}
+
+Local<EphemeronTable> EphemeronTable::New(v8::Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
- LOG_API(i_isolate, WeakMap, New);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
- i::Handle<i::JSWeakMap> obj = i_isolate->factory()->NewJSWeakMap();
- return ToApiHandle<WeakMap>(obj);
+ i::Handle<i::EphemeronHashTable> table =
+ i::EphemeronHashTable::New(i_isolate, 0);
+ return ToApiHandle<EphemeronTable>(table);
}
-WeakMap* WeakMap::Cast(v8::Value* value) {
- return static_cast<WeakMap*>(value);
+EphemeronTable* EphemeronTable::Cast(v8::Value* value) {
+ return static_cast<EphemeronTable*>(value);
}
Local<Value> AccessorPair::getter() {
diff --git a/src/debug/debug-interface.h b/src/debug/debug-interface.h
index 833c26f691566d4d2c17998c85b9ee0cfb4a7bd6..3bc583e190a8e1e31786510a1150af0907945f14 100644
--- a/src/debug/debug-interface.h
+++ b/src/debug/debug-interface.h
@@ -568,19 +568,17 @@ class V8_NODISCARD DisableBreakScope {
std::unique_ptr<i::DisableBreak> scope_;
};
-class WeakMap : public v8::Object {
+class EphemeronTable : public v8::Object {
public:
- WeakMap() = delete;
+ EphemeronTable() = delete;
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> Get(
- v8::Local<v8::Context> context, v8::Local<v8::Value> key);
- V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::Maybe<bool> Delete(
- v8::Local<v8::Context> context, v8::Local<v8::Value> key);
- V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::MaybeLocal<WeakMap> Set(
- v8::Local<v8::Context> context, v8::Local<v8::Value> key,
+ v8::Isolate* isolate, v8::Local<v8::Value> key);
+ V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::Local<EphemeronTable> Set(
+ v8::Isolate* isolate, v8::Local<v8::Value> key,
v8::Local<v8::Value> value);
- V8_EXPORT_PRIVATE static Local<WeakMap> New(v8::Isolate* isolate);
- V8_INLINE static WeakMap* Cast(Value* obj);
+ V8_EXPORT_PRIVATE static Local<EphemeronTable> New(v8::Isolate* isolate);
+ V8_INLINE static EphemeronTable* Cast(Value* obj);
};
/**
diff --git a/src/inspector/inspected-context.cc b/src/inspector/inspected-context.cc
index a47df1ef123347a04da7e577bc1aa0958e77a1de..d9d38b2f32d8353900b1db399590b2b91fa0045f 100644
--- a/src/inspector/inspected-context.cc
+++ b/src/inspector/inspected-context.cc
@@ -126,12 +126,15 @@ void InspectedContext::discardInjectedScript(int sessionId) {
bool InspectedContext::addInternalObject(v8::Local<v8::Object> object,
V8InternalValueType type) {
if (m_internalObjects.IsEmpty()) {
- m_internalObjects.Reset(isolate(), v8::debug::WeakMap::New(isolate()));
+ m_internalObjects.Reset(isolate(),
+ v8::debug::EphemeronTable::New(isolate()));
}
- return !m_internalObjects.Get(isolate())
- ->Set(m_context.Get(isolate()), object,
- v8::Integer::New(isolate(), static_cast<int>(type)))
- .IsEmpty();
+ v8::Local<v8::debug::EphemeronTable> new_map =
+ m_internalObjects.Get(isolate())->Set(
+ isolate(), object,
+ v8::Integer::New(isolate(), static_cast<int>(type)));
+ m_internalObjects.Reset(isolate(), new_map);
+ return true;
}
V8InternalValueType InspectedContext::getInternalType(
@@ -139,7 +142,7 @@ V8InternalValueType InspectedContext::getInternalType(
if (m_internalObjects.IsEmpty()) return V8InternalValueType::kNone;
v8::Local<v8::Value> typeValue;
if (!m_internalObjects.Get(isolate())
- ->Get(m_context.Get(isolate()), object)
+ ->Get(isolate(), object)
.ToLocal(&typeValue) ||
!typeValue->IsUint32()) {
return V8InternalValueType::kNone;
diff --git a/src/inspector/inspected-context.h b/src/inspector/inspected-context.h
index d3f0fe012b899c7c63140909080e395ade3c1536..f59f7d6da5970184e890dfa0569de008fca02e92 100644
--- a/src/inspector/inspected-context.h
+++ b/src/inspector/inspected-context.h
@@ -71,7 +71,7 @@ class InspectedContext {
std::unordered_set<int> m_reportedSessionIds;
std::unordered_map<int, std::unique_ptr<InjectedScript>> m_injectedScripts;
WeakCallbackData* m_weakCallbackData;
- v8::Global<v8::debug::WeakMap> m_internalObjects;
+ v8::Global<v8::debug::EphemeronTable> m_internalObjects;
};
} // namespace v8_inspector
diff --git a/src/inspector/v8-inspector-impl.cc b/src/inspector/v8-inspector-impl.cc
index f0cfa9b2c7539d19ad51d5d5c0338661af5b8dfb..1f08ee4259bc3e2c84b648cbd1fae25b4b5dbb52 100644
--- a/src/inspector/v8-inspector-impl.cc
+++ b/src/inspector/v8-inspector-impl.cc
@@ -516,19 +516,17 @@ bool V8InspectorImpl::associateExceptionData(v8::Local<v8::Context>,
v8::Context::Scope contextScope(context);
v8::HandleScope handles(m_isolate);
if (m_exceptionMetaData.IsEmpty())
- m_exceptionMetaData.Reset(m_isolate, v8::debug::WeakMap::New(m_isolate));
+ m_exceptionMetaData.Reset(m_isolate,
+ v8::debug::EphemeronTable::New(m_isolate));
- v8::Local<v8::debug::WeakMap> map = m_exceptionMetaData.Get(m_isolate);
- v8::MaybeLocal<v8::Value> entry = map->Get(context, exception);
+ v8::Local<v8::debug::EphemeronTable> map = m_exceptionMetaData.Get(m_isolate);
+ v8::MaybeLocal<v8::Value> entry = map->Get(m_isolate, exception);
v8::Local<v8::Object> object;
if (entry.IsEmpty() || !entry.ToLocalChecked()->IsObject()) {
object =
v8::Object::New(m_isolate, v8::Null(m_isolate), nullptr, nullptr, 0);
- v8::MaybeLocal<v8::debug::WeakMap> new_map =
- map->Set(context, exception, object);
- if (!new_map.IsEmpty()) {
- m_exceptionMetaData.Reset(m_isolate, new_map.ToLocalChecked());
- }
+ m_exceptionMetaData.Reset(m_isolate,
+ map->Set(m_isolate, exception, object));
} else {
object = entry.ToLocalChecked().As<v8::Object>();
}
@@ -548,8 +546,8 @@ v8::MaybeLocal<v8::Object> V8InspectorImpl::getAssociatedExceptionData(
!exceptionMetaDataContext().ToLocal(&context)) {
return v8::MaybeLocal<v8::Object>();
}
- v8::Local<v8::debug::WeakMap> map = m_exceptionMetaData.Get(m_isolate);
- auto entry = map->Get(context, exception);
+ v8::Local<v8::debug::EphemeronTable> map = m_exceptionMetaData.Get(m_isolate);
+ auto entry = map->Get(m_isolate, exception);
v8::Local<v8::Value> object;
if (!entry.ToLocal(&object) || !object->IsObject())
return v8::MaybeLocal<v8::Object>();
diff --git a/src/inspector/v8-inspector-impl.h b/src/inspector/v8-inspector-impl.h
index e1607f88c0e6591d748d0c82634e327d2bbebad7..e6e4cde61c5845cac95d058b361260637be38722 100644
--- a/src/inspector/v8-inspector-impl.h
+++ b/src/inspector/v8-inspector-impl.h
@@ -56,7 +56,7 @@ class V8StackTraceImpl;
class V8InspectorImpl : public V8Inspector {
public:
- V8InspectorImpl(v8::Isolate*, V8InspectorClient*);
+ V8_EXPORT_PRIVATE V8InspectorImpl(v8::Isolate*, V8InspectorClient*);
~V8InspectorImpl() override;
V8InspectorImpl(const V8InspectorImpl&) = delete;
V8InspectorImpl& operator=(const V8InspectorImpl&) = delete;
@@ -112,10 +112,9 @@ class V8InspectorImpl : public V8Inspector {
std::shared_ptr<Counters> enableCounters() override;
- bool associateExceptionData(v8::Local<v8::Context>,
- v8::Local<v8::Value> exception,
- v8::Local<v8::Name> key,
- v8::Local<v8::Value> value) override;
+ V8_EXPORT_PRIVATE bool associateExceptionData(
+ v8::Local<v8::Context>, v8::Local<v8::Value> exception,
+ v8::Local<v8::Name> key, v8::Local<v8::Value> value) override;
unsigned nextExceptionId() { return ++m_lastExceptionId; }
void enableStackCapturingIfNeeded();
@@ -136,7 +135,7 @@ class V8InspectorImpl : public V8Inspector {
int contextGroupId,
const std::function<void(V8InspectorSessionImpl*)>& callback);
int64_t generateUniqueId();
- v8::MaybeLocal<v8::Object> getAssociatedExceptionData(
+ V8_EXPORT_PRIVATE v8::MaybeLocal<v8::Object> getAssociatedExceptionData(
v8::Local<v8::Value> exception);
class EvaluateScope {
@@ -164,7 +163,7 @@ class V8InspectorImpl : public V8Inspector {
std::unique_ptr<V8Debugger> m_debugger;
v8::Global<v8::Context> m_regexContext;
v8::Global<v8::Context> m_exceptionMetaDataContext;
- v8::Global<v8::debug::WeakMap> m_exceptionMetaData;
+ v8::Global<v8::debug::EphemeronTable> m_exceptionMetaData;
int m_capturingStackTracesCount;
unsigned m_lastExceptionId;
int m_lastContextId;
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 2effdabc1dbd0e993971fe175b2483a9e555d0dd..30c6b2674901a0004b773ae0f0204d83b1964697 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -594,10 +594,11 @@ TEST(BreakPointApiIntrinsics) {
CHECK_EQ(2, break_point_hit_count);
break_point_hit_count = 0;
- v8::Local<v8::debug::WeakMap> weakmap =
- v8::debug::WeakMap::New(env->GetIsolate());
- CHECK(!weakmap->Set(env.local(), weakmap, v8_num(1)).IsEmpty());
- CHECK(!weakmap->Get(env.local(), weakmap).IsEmpty());
+ v8::Local<v8::debug::EphemeronTable> weakmap =
+ v8::debug::EphemeronTable::New(env->GetIsolate());
+ v8::Local<v8::Object> key = v8::Object::New(env->GetIsolate());
+ CHECK(!weakmap->Set(env->GetIsolate(), key, v8_num(1)).IsEmpty());
+ CHECK(!weakmap->Get(env->GetIsolate(), key).IsEmpty());
CHECK_EQ(0, break_point_hit_count);
}
diff --git a/test/cctest/test-inspector.cc b/test/cctest/test-inspector.cc
index e36ce19eca04831f8a80c459590506e497836716..7fb3bef3bb9e7ef88cd441ce4023b780fff5d982 100644
--- a/test/cctest/test-inspector.cc
+++ b/test/cctest/test-inspector.cc
@@ -8,6 +8,7 @@
#include "include/v8.h"
#include "src/inspector/protocol/Runtime.h"
#include "src/inspector/string-util.h"
+#include "src/inspector/v8-inspector-impl.h"
#include "test/cctest/cctest.h"
using v8_inspector::StringBuffer;
@@ -168,3 +169,38 @@ TEST(BinaryBase64RoundTrip) {
CHECK_EQ(values[i], roundtrip_binary.data()[i]);
}
}
+
+TEST(NoInterruptOnGetAssociatedData) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ v8_inspector::V8InspectorClient default_client;
+ std::unique_ptr<v8_inspector::V8InspectorImpl> inspector(
+ new v8_inspector::V8InspectorImpl(isolate, &default_client));
+
+ v8::Local<v8::Context> context = env->GetIsolate()->GetCurrentContext();
+ v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
+ v8::Local<v8::Name> key = v8_str("key");
+ v8::Local<v8::Value> value = v8_str("value");
+ inspector->associateExceptionData(context, error, key, value);
+
+ struct InterruptRecorder {
+ static void handler(v8::Isolate* isolate, void* data) {
+ reinterpret_cast<InterruptRecorder*>(data)->WasInvoked = true;
+ }
+
+ bool WasInvoked = false;
+ } recorder;
+
+ isolate->RequestInterrupt(&InterruptRecorder::handler, &recorder);
+
+ v8::Local<v8::Object> data =
+ inspector->getAssociatedExceptionData(error).ToLocalChecked();
+ CHECK(!recorder.WasInvoked);
+
+ CHECK_EQ(data->Get(context, key).ToLocalChecked(), value);
+
+ CompileRun("0");
+ CHECK(recorder.WasInvoked);
+}

View File

@@ -0,0 +1,143 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Lippautz <mlippautz@chromium.org>
Date: Wed, 20 Oct 2021 10:10:56 +0200
Subject: Merged: cppgc: Fix marking of ephemerons with keys in construction
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Revision: 32a09a6bce6cc75806dee5ec748bb1d081048fd0
BUG=chromium:1259587
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
R=dinfuehr@chromium.org
Change-Id: Ief330b4b71705c16bc61a3aca6d3aa1db172cdf3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3234200
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.4@{#46}
Cr-Branched-From: 3b51863bc25492549a8bf96ff67ce481b1a3337b-refs/heads/9.4.146@{#1}
Cr-Branched-From: 2890419fc8fb9bdb507fdd801d76fa7dd9f022b5-refs/heads/master@{#76233}
diff --git a/src/heap/cppgc/marker.cc b/src/heap/cppgc/marker.cc
index 549a9fe1da8f89c91935e23419eebe455c618524..40d1c22a7ef50e9f4ebc18001ad01c1ce8d0a0a7 100644
--- a/src/heap/cppgc/marker.cc
+++ b/src/heap/cppgc/marker.cc
@@ -243,6 +243,7 @@ void MarkerBase::EnterAtomicPause(MarkingConfig::StackState stack_state) {
}
config_.stack_state = stack_state;
config_.marking_type = MarkingConfig::MarkingType::kAtomic;
+ mutator_marking_state_.set_in_atomic_pause();
// Lock guards against changes to {Weak}CrossThreadPersistent handles, that
// may conflict with marking. E.g., a WeakCrossThreadPersistent may be
diff --git a/src/heap/cppgc/marking-state.h b/src/heap/cppgc/marking-state.h
index b014bd6134391e469dac2ceda98e52d301abb3f3..4c0d78a30bd3610df6d713d27e4e07a369faf1e7 100644
--- a/src/heap/cppgc/marking-state.h
+++ b/src/heap/cppgc/marking-state.h
@@ -9,6 +9,7 @@
#include "include/cppgc/trace-trait.h"
#include "include/cppgc/visitor.h"
+#include "src/base/logging.h"
#include "src/heap/cppgc/compaction-worklists.h"
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap-object-header.h"
@@ -115,6 +116,8 @@ class MarkingStateBase {
movable_slots_worklist_.reset();
}
+ void set_in_atomic_pause() { in_atomic_pause_ = true; }
+
protected:
inline void MarkAndPush(HeapObjectHeader&, TraceDescriptor);
@@ -150,6 +153,7 @@ class MarkingStateBase {
movable_slots_worklist_;
size_t marked_bytes_ = 0;
+ bool in_atomic_pause_ = false;
};
MarkingStateBase::MarkingStateBase(HeapBase& heap,
@@ -284,10 +288,19 @@ void MarkingStateBase::ProcessWeakContainer(const void* object,
void MarkingStateBase::ProcessEphemeron(const void* key, const void* value,
TraceDescriptor value_desc,
Visitor& visitor) {
- // Filter out already marked keys. The write barrier for WeakMember
- // ensures that any newly set value after this point is kept alive and does
- // not require the callback.
- if (HeapObjectHeader::FromObject(key).IsMarked<AccessMode::kAtomic>()) {
+ // Keys are considered live even in incremental/concurrent marking settings
+ // because the write barrier for WeakMember ensures that any newly set value
+ // after this point is kept alive and does not require the callback.
+ const bool key_in_construction =
+ HeapObjectHeader::FromObject(key).IsInConstruction<AccessMode::kAtomic>();
+ const bool key_considered_as_live =
+ key_in_construction
+ ? in_atomic_pause_
+ : HeapObjectHeader::FromObject(key).IsMarked<AccessMode::kAtomic>();
+ DCHECK_IMPLIES(
+ key_in_construction && in_atomic_pause_,
+ HeapObjectHeader::FromObject(key).IsMarked<AccessMode::kAtomic>());
+ if (key_considered_as_live) {
if (value_desc.base_object_payload) {
MarkAndPush(value_desc.base_object_payload, value_desc);
} else {
diff --git a/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc b/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc
index c759308723d7f0635d329f5b571859700871fa35..1ff52904dd387c9772de810951619191dc79aea7 100644
--- a/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc
+++ b/test/unittests/heap/cppgc/ephemeron-pair-unittest.cc
@@ -239,5 +239,50 @@ TEST_F(EphemeronPairTest, EphemeronPairWithEmptyMixinValue) {
FinishMarking();
}
+namespace {
+
+class KeyWithCallback final : public GarbageCollected<KeyWithCallback> {
+ public:
+ template <typename Callback>
+ explicit KeyWithCallback(Callback callback) {
+ callback(this);
+ }
+ void Trace(Visitor*) const {}
+};
+
+class EphemeronHolderForKeyWithCallback final
+ : public GarbageCollected<EphemeronHolderForKeyWithCallback> {
+ public:
+ EphemeronHolderForKeyWithCallback(KeyWithCallback* key, GCed* value)
+ : ephemeron_pair_(key, value) {}
+ void Trace(cppgc::Visitor* visitor) const { visitor->Trace(ephemeron_pair_); }
+
+ private:
+ const EphemeronPair<KeyWithCallback, GCed> ephemeron_pair_;
+};
+
+} // namespace
+
+TEST_F(EphemeronPairTest, EphemeronPairWithKeyInConstruction) {
+ GCed* value = MakeGarbageCollected<GCed>(GetAllocationHandle());
+ Persistent<EphemeronHolderForKeyWithCallback> holder;
+ InitializeMarker(*Heap::From(GetHeap()), GetPlatformHandle().get());
+ FinishSteps();
+ MakeGarbageCollected<KeyWithCallback>(
+ GetAllocationHandle(), [this, &holder, value](KeyWithCallback* thiz) {
+ // The test doesn't use conservative stack scanning to retain key to
+ // avoid retaining value as a side effect.
+ EXPECT_TRUE(HeapObjectHeader::FromObject(thiz).TryMarkAtomic());
+ holder = MakeGarbageCollected<EphemeronHolderForKeyWithCallback>(
+ GetAllocationHandle(), thiz, value);
+ // Finishing marking at this point will leave an ephemeron pair
+ // reachable where the key is still in construction. The GC needs to
+ // mark the value for such pairs as live in the atomic pause as they key
+ // is considered live.
+ FinishMarking();
+ });
+ EXPECT_TRUE(HeapObjectHeader::FromObject(value).IsMarked());
+}
+
} // namespace internal
} // namespace cppgc

View File

@@ -1 +1,2 @@
add_thread_local_to_x_error_trap_cc.patch
merge_to_94_add_direction_indicator_to_transformableframes.patch

View File

@@ -0,0 +1,222 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tony Herre <toprice@chromium.org>
Date: Mon, 4 Oct 2021 10:02:51 +0000
Subject: Add Direction indicator to TransformableFrames
Currently the implementation of FrameTransformers uses distinct,
incompatible types for recevied vs about-to-be-sent frames. This adds a
flag in the interface so we can at least check that we are being given
the correct type. crbug.com/1250638 tracks removing the need for this.
Chrome will be updated after this to check the direction flag and provide
a javascript error if the wrong type of frame is written into the
encoded insertable streams writable stream, rather than crashing.
(cherry picked from commit 8fb41a39e1a2d151d1c00c409630dcee80adeb76)
Bug: chromium:1247260
Change-Id: I9cbb66962ea0718ed47c5e5dba19a8ff9635b0b1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/232301
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Tony Herre <toprice@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#35100}
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/233943
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/branch-heads/4606@{#4}
Cr-Branched-From: 8b18304e66524060eca390f143033ba51322b3a2-refs/heads/master@{#34737}
diff --git a/api/frame_transformer_interface.h b/api/frame_transformer_interface.h
index 2cfe6edb884b53b0b3fa87afad264aa411d112bd..d04acc098cb564c161f87c87d68511429895757c 100644
--- a/api/frame_transformer_interface.h
+++ b/api/frame_transformer_interface.h
@@ -35,6 +35,16 @@ class TransformableFrameInterface {
virtual uint32_t GetTimestamp() const = 0;
virtual uint32_t GetSsrc() const = 0;
+
+ enum class Direction {
+ kUnknown,
+ kReceiver,
+ kSender,
+ };
+ // TODO(crbug.com/1250638): Remove this distinction between receiver and
+ // sender frames to allow received frames to be directly re-transmitted on
+ // other PeerConnectionss.
+ virtual Direction GetDirection() const { return Direction::kUnknown; }
};
class TransformableVideoFrameInterface : public TransformableFrameInterface {
diff --git a/audio/channel_receive_frame_transformer_delegate.cc b/audio/channel_receive_frame_transformer_delegate.cc
index 7e617df78018ece3f619c7fb3288aa180468135d..d00e7176c5205be4a4faac36e8364c070fe7c014 100644
--- a/audio/channel_receive_frame_transformer_delegate.cc
+++ b/audio/channel_receive_frame_transformer_delegate.cc
@@ -18,15 +18,16 @@
namespace webrtc {
namespace {
-class TransformableAudioFrame : public TransformableAudioFrameInterface {
+class TransformableIncomingAudioFrame
+ : public TransformableAudioFrameInterface {
public:
- TransformableAudioFrame(rtc::ArrayView<const uint8_t> payload,
- const RTPHeader& header,
- uint32_t ssrc)
+ TransformableIncomingAudioFrame(rtc::ArrayView<const uint8_t> payload,
+ const RTPHeader& header,
+ uint32_t ssrc)
: payload_(payload.data(), payload.size()),
header_(header),
ssrc_(ssrc) {}
- ~TransformableAudioFrame() override = default;
+ ~TransformableIncomingAudioFrame() override = default;
rtc::ArrayView<const uint8_t> GetData() const override { return payload_; }
void SetData(rtc::ArrayView<const uint8_t> data) override {
@@ -36,6 +37,7 @@ class TransformableAudioFrame : public TransformableAudioFrameInterface {
uint32_t GetTimestamp() const override { return header_.timestamp; }
uint32_t GetSsrc() const override { return ssrc_; }
const RTPHeader& GetHeader() const override { return header_; }
+ Direction GetDirection() const override { return Direction::kReceiver; }
private:
rtc::Buffer payload_;
@@ -71,7 +73,7 @@ void ChannelReceiveFrameTransformerDelegate::Transform(
uint32_t ssrc) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
frame_transformer_->Transform(
- std::make_unique<TransformableAudioFrame>(packet, header, ssrc));
+ std::make_unique<TransformableIncomingAudioFrame>(packet, header, ssrc));
}
void ChannelReceiveFrameTransformerDelegate::OnTransformedFrame(
@@ -88,7 +90,10 @@ void ChannelReceiveFrameTransformerDelegate::ReceiveFrame(
RTC_DCHECK_RUN_ON(&sequence_checker_);
if (!receive_frame_callback_)
return;
- auto* transformed_frame = static_cast<TransformableAudioFrame*>(frame.get());
+ RTC_CHECK_EQ(frame->GetDirection(),
+ TransformableFrameInterface::Direction::kReceiver);
+ auto* transformed_frame =
+ static_cast<TransformableIncomingAudioFrame*>(frame.get());
receive_frame_callback_(transformed_frame->GetData(),
transformed_frame->GetHeader());
}
diff --git a/audio/channel_send_frame_transformer_delegate.cc b/audio/channel_send_frame_transformer_delegate.cc
index 72a459d89783f9b7bc498aabc15cd7c7b45f3783..5597e7553e956c9dc20e311f5e16d163d9a7119e 100644
--- a/audio/channel_send_frame_transformer_delegate.cc
+++ b/audio/channel_send_frame_transformer_delegate.cc
@@ -15,16 +15,16 @@
namespace webrtc {
namespace {
-class TransformableAudioFrame : public TransformableFrameInterface {
+class TransformableOutgoingAudioFrame : public TransformableFrameInterface {
public:
- TransformableAudioFrame(AudioFrameType frame_type,
- uint8_t payload_type,
- uint32_t rtp_timestamp,
- uint32_t rtp_start_timestamp,
- const uint8_t* payload_data,
- size_t payload_size,
- int64_t absolute_capture_timestamp_ms,
- uint32_t ssrc)
+ TransformableOutgoingAudioFrame(AudioFrameType frame_type,
+ uint8_t payload_type,
+ uint32_t rtp_timestamp,
+ uint32_t rtp_start_timestamp,
+ const uint8_t* payload_data,
+ size_t payload_size,
+ int64_t absolute_capture_timestamp_ms,
+ uint32_t ssrc)
: frame_type_(frame_type),
payload_type_(payload_type),
rtp_timestamp_(rtp_timestamp),
@@ -32,7 +32,7 @@ class TransformableAudioFrame : public TransformableFrameInterface {
payload_(payload_data, payload_size),
absolute_capture_timestamp_ms_(absolute_capture_timestamp_ms),
ssrc_(ssrc) {}
- ~TransformableAudioFrame() override = default;
+ ~TransformableOutgoingAudioFrame() override = default;
rtc::ArrayView<const uint8_t> GetData() const override { return payload_; }
void SetData(rtc::ArrayView<const uint8_t> data) override {
payload_.SetData(data.data(), data.size());
@@ -48,6 +48,7 @@ class TransformableAudioFrame : public TransformableFrameInterface {
int64_t GetAbsoluteCaptureTimestampMs() const {
return absolute_capture_timestamp_ms_;
}
+ Direction GetDirection() const override { return Direction::kSender; }
private:
AudioFrameType frame_type_;
@@ -90,9 +91,10 @@ void ChannelSendFrameTransformerDelegate::Transform(
size_t payload_size,
int64_t absolute_capture_timestamp_ms,
uint32_t ssrc) {
- frame_transformer_->Transform(std::make_unique<TransformableAudioFrame>(
- frame_type, payload_type, rtp_timestamp, rtp_start_timestamp,
- payload_data, payload_size, absolute_capture_timestamp_ms, ssrc));
+ frame_transformer_->Transform(
+ std::make_unique<TransformableOutgoingAudioFrame>(
+ frame_type, payload_type, rtp_timestamp, rtp_start_timestamp,
+ payload_data, payload_size, absolute_capture_timestamp_ms, ssrc));
}
void ChannelSendFrameTransformerDelegate::OnTransformedFrame(
@@ -111,9 +113,12 @@ void ChannelSendFrameTransformerDelegate::SendFrame(
std::unique_ptr<TransformableFrameInterface> frame) const {
MutexLock lock(&send_lock_);
RTC_DCHECK_RUN_ON(encoder_queue_);
+ RTC_CHECK_EQ(frame->GetDirection(),
+ TransformableFrameInterface::Direction::kSender);
if (!send_frame_callback_)
return;
- auto* transformed_frame = static_cast<TransformableAudioFrame*>(frame.get());
+ auto* transformed_frame =
+ static_cast<TransformableOutgoingAudioFrame*>(frame.get());
send_frame_callback_(transformed_frame->GetFrameType(),
transformed_frame->GetPayloadType(),
transformed_frame->GetTimestamp() -
diff --git a/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc b/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
index 23e66bf75744c49b5ee057263d989e58f36b39d3..77a4ca5c35ebe51d13267e5dccce7ff360a29a33 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
@@ -75,6 +75,8 @@ class TransformableVideoSenderFrame : public TransformableVideoFrameInterface {
return expected_retransmission_time_ms_;
}
+ Direction GetDirection() const override { return Direction::kSender; }
+
private:
rtc::scoped_refptr<EncodedImageBufferInterface> encoded_data_;
const RTPVideoHeader header_;
@@ -144,6 +146,8 @@ void RTPSenderVideoFrameTransformerDelegate::OnTransformedFrame(
void RTPSenderVideoFrameTransformerDelegate::SendVideo(
std::unique_ptr<TransformableFrameInterface> transformed_frame) const {
RTC_CHECK(encoder_queue_->IsCurrent());
+ RTC_CHECK_EQ(transformed_frame->GetDirection(),
+ TransformableFrameInterface::Direction::kSender);
MutexLock lock(&sender_lock_);
if (!sender_)
return;
diff --git a/video/rtp_video_stream_receiver_frame_transformer_delegate.cc b/video/rtp_video_stream_receiver_frame_transformer_delegate.cc
index f2f81df3ee76603c24ccc8ce93beaedb7d1eeaac..d6c6944e0efe999ea2e4b1a74184e8a74de7312a 100644
--- a/video/rtp_video_stream_receiver_frame_transformer_delegate.cc
+++ b/video/rtp_video_stream_receiver_frame_transformer_delegate.cc
@@ -58,6 +58,8 @@ class TransformableVideoReceiverFrame
return std::move(frame_);
}
+ Direction GetDirection() const override { return Direction::kReceiver; }
+
private:
std::unique_ptr<RtpFrameObject> frame_;
const VideoFrameMetadata metadata_;
@@ -110,6 +112,8 @@ void RtpVideoStreamReceiverFrameTransformerDelegate::OnTransformedFrame(
void RtpVideoStreamReceiverFrameTransformerDelegate::ManageFrame(
std::unique_ptr<TransformableFrameInterface> frame) {
RTC_DCHECK_RUN_ON(&network_sequence_checker_);
+ RTC_CHECK_EQ(frame->GetDirection(),
+ TransformableFrameInterface::Direction::kReceiver);
if (!receiver_)
return;
auto transformed_frame = absl::WrapUnique(

65
script/generate-config-gypi.py Executable file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env python
from __future__ import print_function
import ast
import os
import pprint
import re
import subprocess
import sys
ELECTRON_DIR = os.path.abspath(os.path.join(__file__, '..', '..'))
NODE_DIR = os.path.join(ELECTRON_DIR, '..', 'third_party', 'electron_node')
def run_node_configure(target_cpu):
configure = os.path.join(NODE_DIR, 'configure.py')
args = ['--dest-cpu', target_cpu]
# Enabled in Chromium's V8.
if target_cpu == 'arm64' or target_cpu == 'x64':
args += ['--experimental-enable-pointer-compression']
# Work around "No acceptable ASM compiler found" error on some System,
# it breaks nothing since Electron does not use OpenSSL.
args += ['--openssl-no-asm']
subprocess.check_call([sys.executable, configure] + args)
def read_node_config_gypi():
config_gypi = os.path.join(NODE_DIR, 'config.gypi')
with open(config_gypi, 'r') as f:
content = f.read()
return ast.literal_eval(content)
def read_electron_args():
all_gn = os.path.join(ELECTRON_DIR, 'build', 'args', 'all.gn')
args = {}
with open(all_gn, 'r') as f:
for line in f:
if line.startswith('#'):
continue
m = re.match('([\w_]+) = (.+)', line)
if m == None:
continue
args[m.group(1)] = m.group(2)
return args
def main(target_file, target_cpu):
run_node_configure(target_cpu)
config = read_node_config_gypi()
args = read_electron_args()
# Remove the generated config.gypi to make the parallel/test-process-config
# test pass.
os.remove(os.path.join(NODE_DIR, 'config.gypi'))
v = config['variables']
# Electron specific variables:
v['built_with_electron'] = 1
v['node_module_version'] = int(args['node_module_version'])
# Used by certain versions of node-gyp.
v['build_v8_with_gn'] = 'false'
with open(target_file, 'w+') as f:
f.write(pprint.pformat(config, indent=2))
if __name__ == '__main__':
sys.exit(main(*sys.argv[1:]))

View File

@@ -14,10 +14,6 @@ const DEPOT_TOOLS = path.resolve(SOURCE_ROOT, '..', 'third_party', 'depot_tools'
const IGNORELIST = new Set([
['shell', 'browser', 'resources', 'win', 'resource.h'],
['shell', 'browser', 'notifications', 'mac', 'notification_center_delegate.h'],
['shell', 'browser', 'ui', 'cocoa', 'event_dispatching_window.h'],
['shell', 'browser', 'ui', 'cocoa', 'NSColor+Hex.h'],
['shell', 'browser', 'ui', 'cocoa', 'NSString+ANSI.h'],
['shell', 'common', 'node_includes.h'],
['spec', 'static', 'jquery-2.0.3.min.js'],
['spec', 'ts-smoke', 'electron', 'main.ts'],
@@ -68,7 +64,7 @@ const LINTERS = [{
}, {
key: 'objc',
roots: ['shell'],
test: filename => filename.endsWith('.mm'),
test: filename => filename.endsWith('.mm') || (filename.endsWith('.h') && isObjCHeader(filename)),
run: (opts, filenames) => {
if (opts.fix) {
spawnAndCheckExitCode('python', ['script/run-clang-format.py', '--fix', ...filenames]);
@@ -81,7 +77,7 @@ const LINTERS = [{
'-whitespace/indent',
'-whitespace/parens'
];
cpplint(['--extensions=mm', `--filter=${filter.join(',')}`, ...filenames]);
cpplint(['--extensions=mm,h', `--filter=${filter.join(',')}`, ...filenames]);
}
}, {
key: 'python',

View File

@@ -8,24 +8,32 @@ const lambda = new AWS.Lambda({
region: 'us-east-1'
});
module.exports = function getUrlHash (targetUrl, algorithm = 'sha256') {
return new Promise((resolve, reject) => {
lambda.invoke({
FunctionName: 'hasher',
Payload: JSON.stringify({
targetUrl,
algorithm
})
}, (err, data) => {
if (err) return reject(err);
try {
const response = JSON.parse(data.Payload);
if (response.statusCode !== 200) return reject(new Error('non-200 status code received from hasher function'));
if (!response.hash) return reject(new Error('Successful lambda call but failed to get valid hash'));
resolve(response.hash);
} catch (err) {
return reject(err);
}
module.exports = async function getUrlHash (targetUrl, algorithm = 'sha256', attempts = 3) {
try {
return new Promise((resolve, reject) => {
lambda.invoke({
FunctionName: 'hasher',
Payload: JSON.stringify({
targetUrl,
algorithm
})
}, (err, data) => {
if (err) return reject(err);
try {
const response = JSON.parse(data.Payload);
if (response.statusCode !== 200) return reject(new Error('non-200 status code received from hasher function'));
if (!response.hash) return reject(new Error('Successful lambda call but failed to get valid hash'));
resolve(response.hash);
} catch (err) {
return reject(err);
}
});
});
});
} catch (err) {
if (attempts > 1) {
console.error('Failed to get URL hash for', targetUrl, 'we will retry', err);
return getUrlHash(targetUrl, algorithm, attempts - 1);
}
throw err;
}
};

View File

@@ -761,18 +761,16 @@ void BaseWindow::AddBrowserView(v8::Local<v8::Value> value) {
gin::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view == browser_views_.end()) {
if (browser_view->web_contents()) {
// If we're reparenting a BrowserView, ensure that it's detached from
// its previous owner window.
auto* owner_window = browser_view->web_contents()->owner_window();
if (owner_window && owner_window != window_.get()) {
owner_window->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr);
}
window_->AddBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(window_.get());
// If we're reparenting a BrowserView, ensure that it's detached from
// its previous owner window.
auto* owner_window = browser_view->owner_window();
if (owner_window && owner_window != window_.get()) {
owner_window->RemoveBrowserView(browser_view->view());
browser_view->SetOwnerWindow(nullptr);
}
window_->AddBrowserView(browser_view->view());
browser_view->SetOwnerWindow(window_.get());
browser_views_[browser_view->ID()].Reset(isolate(), value);
}
}
@@ -784,10 +782,8 @@ void BaseWindow::RemoveBrowserView(v8::Local<v8::Value> value) {
gin::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view != browser_views_.end()) {
if (browser_view->web_contents()) {
window_->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr);
}
window_->RemoveBrowserView(browser_view->view());
browser_view->SetOwnerWindow(nullptr);
(*get_that_view).second.Reset(isolate(), value);
browser_views_.erase(get_that_view);
}
@@ -799,9 +795,7 @@ void BaseWindow::SetTopBrowserView(v8::Local<v8::Value> value,
gin::Handle<BrowserView> browser_view;
if (value->IsObject() &&
gin::ConvertFromV8(isolate(), value, &browser_view)) {
if (!browser_view->web_contents())
return;
auto* owner_window = browser_view->web_contents()->owner_window();
auto* owner_window = browser_view->owner_window();
auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view == browser_views_.end() ||
(owner_window && owner_window != window_.get())) {
@@ -1130,12 +1124,10 @@ void BaseWindow::ResetBrowserViews() {
!browser_view.IsEmpty()) {
// There's a chance that the BrowserView may have been reparented - only
// reset if the owner window is *this* window.
if (browser_view->web_contents()) {
auto* owner_window = browser_view->web_contents()->owner_window();
if (owner_window && owner_window == window_.get()) {
browser_view->web_contents()->SetOwnerWindow(nullptr);
owner_window->RemoveBrowserView(browser_view->view());
}
auto* owner_window = browser_view->owner_window();
if (owner_window && owner_window == window_.get()) {
browser_view->SetOwnerWindow(nullptr);
owner_window->RemoveBrowserView(browser_view->view());
}
}

View File

@@ -99,10 +99,18 @@ BrowserView::BrowserView(gin::Arguments* args,
NativeBrowserView::Create(api_web_contents_->inspectable_web_contents()));
}
void BrowserView::SetOwnerWindow(NativeWindow* window) {
// Ensure WebContents and BrowserView owner windows are in sync.
if (web_contents())
web_contents()->SetOwnerWindow(window);
owner_window_ = window ? window->GetWeakPtr() : nullptr;
}
BrowserView::~BrowserView() {
if (api_web_contents_) { // destroy() called without closing WebContents
api_web_contents_->RemoveObserver(this);
api_web_contents_->Destroy();
if (web_contents()) { // destroy() called without closing WebContents
web_contents()->RemoveObserver(this);
web_contents()->Destroy();
}
}
@@ -148,6 +156,11 @@ gfx::Rect BrowserView::GetBounds() {
void BrowserView::SetBackgroundColor(const std::string& color_name) {
view_->SetBackgroundColor(ParseHexColor(color_name));
if (web_contents()) {
auto* wc = web_contents()->web_contents();
wc->SetPageBaseBackgroundColor(ParseHexColor(color_name));
}
}
v8::Local<v8::Value> BrowserView::GetWebContents(v8::Isolate* isolate) {

View File

@@ -14,6 +14,7 @@
#include "gin/wrappable.h"
#include "shell/browser/extended_web_contents_observer.h"
#include "shell/browser/native_browser_view.h"
#include "shell/browser/native_window.h"
#include "shell/common/api/api.mojom.h"
#include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/error_thrower.h"
@@ -54,6 +55,10 @@ class BrowserView : public gin::Wrappable<BrowserView>,
WebContents* web_contents() const { return api_web_contents_; }
NativeBrowserView* view() const { return view_.get(); }
NativeWindow* owner_window() const { return owner_window_.get(); }
void SetOwnerWindow(NativeWindow* window);
int32_t ID() const { return id_; }
protected:
@@ -78,6 +83,7 @@ class BrowserView : public gin::Wrappable<BrowserView>,
class WebContents* api_web_contents_ = nullptr;
std::unique_ptr<NativeBrowserView> view_;
base::WeakPtr<NativeWindow> owner_window_;
int32_t id_;

View File

@@ -246,7 +246,7 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
ScheduleUnresponsiveEvent(5000);
// Already closed by renderer.
if (!web_contents())
if (!web_contents() || !api_web_contents_)
return;
// Required to make beforeunload handler work.

View File

@@ -10,6 +10,7 @@
#include "base/containers/contains.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/extensions/command.h"
#include "gin/dictionary.h"
#include "gin/object_template_builder.h"
#include "shell/browser/api/electron_api_system_preferences.h"
@@ -22,6 +23,7 @@
#include "base/mac/mac_util.h"
#endif
using extensions::Command;
using extensions::GlobalShortcutListener;
namespace {
@@ -29,22 +31,23 @@ namespace {
#if defined(OS_MAC)
bool RegisteringMediaKeyForUntrustedClient(const ui::Accelerator& accelerator) {
if (base::mac::IsAtLeastOS10_14()) {
constexpr ui::KeyboardCode mediaKeys[] = {
ui::VKEY_MEDIA_PLAY_PAUSE, ui::VKEY_MEDIA_NEXT_TRACK,
ui::VKEY_MEDIA_PREV_TRACK, ui::VKEY_MEDIA_STOP,
ui::VKEY_VOLUME_UP, ui::VKEY_VOLUME_DOWN,
ui::VKEY_VOLUME_MUTE};
if (std::find(std::begin(mediaKeys), std::end(mediaKeys),
accelerator.key_code()) != std::end(mediaKeys)) {
bool trusted =
electron::api::SystemPreferences::IsTrustedAccessibilityClient(false);
if (!trusted)
if (Command::IsMediaKey(accelerator)) {
if (!electron::api::SystemPreferences::IsTrustedAccessibilityClient(
false))
return true;
}
}
return false;
}
bool MapHasMediaKeys(
const std::map<ui::Accelerator, base::RepeatingClosure>& accelerator_map) {
auto media_key = std::find_if(
accelerator_map.begin(), accelerator_map.end(),
[](const auto& ac) { return Command::IsMediaKey(ac.first); });
return media_key != accelerator_map.end();
}
#endif
} // namespace
@@ -84,7 +87,7 @@ bool GlobalShortcut::RegisterAll(
for (auto& accelerator : accelerators) {
if (!Register(accelerator, callback)) {
// unregister all shortcuts if any failed
// Unregister all shortcuts if any failed.
UnregisterSome(registered);
return false;
}
@@ -102,8 +105,12 @@ bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
return false;
}
#if defined(OS_MAC)
if (RegisteringMediaKeyForUntrustedClient(accelerator))
return false;
if (Command::IsMediaKey(accelerator)) {
if (RegisteringMediaKeyForUntrustedClient(accelerator))
return false;
GlobalShortcutListener::SetShouldUseInternalMediaKeyHandling(false);
}
#endif
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
@@ -124,6 +131,13 @@ void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
if (accelerator_callback_map_.erase(accelerator) == 0)
return;
#if defined(OS_MAC)
if (Command::IsMediaKey(accelerator) &&
!MapHasMediaKeys(accelerator_callback_map_)) {
GlobalShortcutListener::SetShouldUseInternalMediaKeyHandling(true);
}
#endif
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
this);
}

View File

@@ -47,7 +47,10 @@ printing::PrinterList GetPrinterList() {
// TODO(deepak1556): Deprecate this api in favor of an
// async version and post a non blocing task call.
base::ThreadRestrictions::ScopedAllowIO allow_io;
print_backend->EnumeratePrinters(&printers);
printing::mojom::ResultCode code =
print_backend->EnumeratePrinters(&printers);
if (code != printing::mojom::ResultCode::kSuccess)
LOG(INFO) << "Failed to enumerate printers";
}
return printers;
}

View File

@@ -430,7 +430,7 @@ bool IsDeviceNameValid(const std::u16string& device_name) {
return true;
}
std::u16string GetDefaultPrinterAsync() {
std::pair<std::string, std::u16string> GetDefaultPrinterAsync() {
#if defined(OS_WIN)
// Blocking is needed here because Windows printer drivers are oftentimes
// not thread-safe and have to be accessed on the UI thread.
@@ -441,18 +441,25 @@ std::u16string GetDefaultPrinterAsync() {
printing::PrintBackend::CreateInstance(
g_browser_process->GetApplicationLocale());
std::string printer_name;
print_backend->GetDefaultPrinterName(printer_name);
printing::mojom::ResultCode code =
print_backend->GetDefaultPrinterName(printer_name);
// Some devices won't have a default printer, so we should
// also check for existing printers and pick the first
// one should it exist.
// We don't want to return if this fails since some devices won't have a
// default printer.
if (code != printing::mojom::ResultCode::kSuccess)
LOG(ERROR) << "Failed to get default printer name";
// Check for existing printers and pick the first one should it exist.
if (printer_name.empty()) {
printing::PrinterList printers;
print_backend->EnumeratePrinters(&printers);
if (print_backend->EnumeratePrinters(&printers) !=
printing::mojom::ResultCode::kSuccess)
return std::make_pair("Failed to enumerate printers", std::u16string());
if (!printers.empty())
printer_name = printers.front().printer_name;
}
return base::UTF8ToUTF16(printer_name);
return std::make_pair(std::string(), base::UTF8ToUTF16(printer_name));
}
// Copied from
@@ -928,8 +935,6 @@ WebContents::~WebContents() {
}
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
if (guest_delegate_)
guest_delegate_->WillDestroy();
// This event is only for internal use, which is emitted when WebContents is
// being destroyed.
@@ -967,8 +972,7 @@ void WebContents::DeleteThisIfAlive() {
void WebContents::Destroy() {
// The content::WebContents should be destroyed asyncronously when possible
// as user may choose to destroy WebContents during an event of it.
if (Browser::Get()->is_shutting_down() || IsGuest() ||
type_ == Type::kBrowserView) {
if (Browser::Get()->is_shutting_down() || IsGuest()) {
DeleteThisIfAlive();
} else {
base::PostTask(FROM_HERE, {content::BrowserThread::UI},
@@ -1396,14 +1400,16 @@ void WebContents::HandleNewRenderFrame(
&color_name)) {
web_contents()->SetPageBaseBackgroundColor(ParseHexColor(color_name));
} else {
web_contents()->SetPageBaseBackgroundColor(absl::nullopt);
bool guest = IsGuest() || type_ == Type::kBrowserView;
web_contents()->SetPageBaseBackgroundColor(
guest ? absl::make_optional(SK_ColorTRANSPARENT) : absl::nullopt);
}
// When a page base background color is set, transparency needs to be
// explicitly set by calling
// RenderWidgetHostOwnerDelegate::SetBackgroundOpaque(false).
// RenderWidgetHostViewBase::SetBackgroundColor() will do this for us.
if (web_preferences->IsEnabled(options::kTransparent)) {
if (web_preferences->IsEnabled(options::kTransparent) || IsGuest()) {
rwhv->SetBackgroundColor(SK_ColorTRANSPARENT);
}
}
@@ -1689,6 +1695,9 @@ void WebContents::MessageTo(int32_t web_contents_id,
gin::Handle<WebFrameMain> web_frame_main =
WebFrameMain::From(JavascriptEnvironment::GetIsolate(), frame);
if (!web_frame_main->CheckRenderFrame())
return;
int32_t sender_id = ID();
web_frame_main->GetRendererApi()->Message(false /* internal */, channel,
std::move(arguments), sender_id);
@@ -1937,6 +1946,10 @@ void WebContents::WebContentsDestroyed() {
return;
wrapper->SetAlignedPointerInInternalField(0, nullptr);
// Tell WebViewGuestDelegate that the WebContents has been destroyed.
if (guest_delegate_)
guest_delegate_->WillDestroy();
Observe(nullptr);
Emit("destroyed");
}
@@ -2428,7 +2441,8 @@ void WebContents::OnGetDefaultPrinter(
printing::CompletionCallback print_callback,
std::u16string device_name,
bool silent,
std::u16string default_printer) {
// <error, default_printer>
std::pair<std::string, std::u16string> info) {
// The content::WebContents might be already deleted at this point, and the
// PrintViewManagerElectron class does not do null check.
if (!web_contents()) {
@@ -2437,8 +2451,14 @@ void WebContents::OnGetDefaultPrinter(
return;
}
std::u16string printer_name =
device_name.empty() ? default_printer : device_name;
if (!info.first.empty()) {
if (print_callback)
std::move(print_callback).Run(false, info.first);
return;
}
// If the user has passed a deviceName use it, otherwise use default printer.
std::u16string printer_name = device_name.empty() ? info.second : device_name;
// If there are no valid printers available on the network, we bail.
if (printer_name.empty() || !IsDeviceNameValid(printer_name)) {

View File

@@ -220,7 +220,8 @@ class WebContents : public gin::Wrappable<WebContents>,
printing::CompletionCallback print_callback,
std::u16string device_name,
bool silent,
std::u16string default_printer);
// <error, default_printer_name>
std::pair<std::string, std::u16string> info);
void Print(gin::Arguments* args);
// Print current page as PDF.
v8::Local<v8::Promise> PrintToPDF(base::DictionaryValue settings);

View File

@@ -100,7 +100,7 @@ void WebFrameMain::MarkRenderFrameDisposed() {
void WebFrameMain::UpdateRenderFrameHost(content::RenderFrameHost* rfh) {
// Should only be called when swapping frames.
DCHECK(render_frame_);
render_frame_disposed_ = false;
render_frame_ = rfh;
renderer_api_.reset();
}

View File

@@ -132,8 +132,10 @@ v8::Local<v8::Value> HttpResponseHeadersToV8(
net::HttpContentDisposition header(value, std::string());
std::string decodedFilename =
header.is_attachment() ? " attachment" : " inline";
decodedFilename += "; filename=" + header.filename();
value = decodedFilename;
// The filename must be encased in double quotes for serialization
// to happen correctly.
std::string filename = "\"" + header.filename() + "\"";
value = decodedFilename + "; filename=" + filename;
}
if (!values)
values = response_headers.SetKey(key, base::ListValue());

View File

@@ -21,6 +21,7 @@
#include "shell/browser/electron_browser_client.h"
#include "shell/browser/electron_browser_main_parts.h"
#include "shell/browser/hid/hid_chooser_context.h"
#include "shell/browser/serial/serial_chooser_context.h"
#include "shell/browser/web_contents_permission_helper.h"
#include "shell/browser/web_contents_preferences.h"
#include "shell/common/gin_converters/content_converter.h"
@@ -327,6 +328,31 @@ bool ElectronPermissionManager::CheckDevicePermission(
if (serial_number && device_serial_number &&
*device_serial_number == *serial_number)
return true;
} else if (permission ==
static_cast<content::PermissionType>(
WebContentsPermissionHelper::PermissionType::SERIAL)) {
#if defined(OS_WIN)
if (device->FindStringKey(kDeviceInstanceIdKey) ==
granted_device.FindStringKey(kDeviceInstanceIdKey))
return true;
#else
if (device->FindIntKey(kVendorIdKey) !=
granted_device.FindIntKey(kVendorIdKey) ||
device->FindIntKey(kProductIdKey) !=
granted_device.FindIntKey(kProductIdKey) ||
*device->FindStringKey(kSerialNumberKey) !=
*granted_device.FindStringKey(kSerialNumberKey)) {
continue;
}
#if defined(OS_MAC)
if (*device->FindStringKey(kUsbDriverKey) !=
*granted_device.FindStringKey(kUsbDriverKey)) {
continue;
}
#endif // defined(OS_MAC)
return true;
#endif // defined(OS_WIN)
}
}
}

View File

@@ -2,6 +2,9 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_MAC_ELECTRON_APPLICATION_H_
#define SHELL_BROWSER_MAC_ELECTRON_APPLICATION_H_
#include "base/callback.h"
#include "base/mac/scoped_nsobject.h"
#include "base/mac/scoped_sending_event.h"
@@ -45,3 +48,5 @@
withUserInfo:(NSDictionary*)userInfo;
@end
#endif // SHELL_BROWSER_MAC_ELECTRON_APPLICATION_H_

View File

@@ -2,6 +2,9 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_MAC_ELECTRON_APPLICATION_DELEGATE_H_
#define SHELL_BROWSER_MAC_ELECTRON_APPLICATION_DELEGATE_H_
#import <Cocoa/Cocoa.h>
#import "shell/browser/ui/cocoa/electron_menu_controller.h"
@@ -15,3 +18,5 @@
- (void)setApplicationDockMenu:(electron::ElectronMenuModel*)model;
@end
#endif // SHELL_BROWSER_MAC_ELECTRON_APPLICATION_DELEGATE_H_

View File

@@ -323,6 +323,13 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
window_ = static_cast<ElectronNSWindow*>(
widget()->GetNativeWindow().GetNativeNSWindow());
RegisterDeleteDelegateCallback(base::BindOnce(
[](NativeWindowMac* window) {
if (window->window_)
window->window_ = nil;
},
this));
[window_ setEnableLargerThanScreen:enable_larger_than_screen()];
window_delegate_.reset([[ElectronNSWindowDelegate alloc] initWithShell:this]);

View File

@@ -1125,8 +1125,17 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
void NativeWindowViews::SetContentProtection(bool enable) {
#if defined(OS_WIN)
HWND hwnd = GetAcceleratedWidget();
DWORD affinity = enable ? WDA_EXCLUDEFROMCAPTURE : WDA_NONE;
::SetWindowDisplayAffinity(GetAcceleratedWidget(), affinity);
::SetWindowDisplayAffinity(hwnd, affinity);
if (!layered_) {
// Workaround to prevent black window on screen capture after hiding and
// showing the BrowserWindow.
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
ex_style |= WS_EX_LAYERED;
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
layered_ = true;
}
#endif
}

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 14,1,1,0
PRODUCTVERSION 14,1,1,0
FILEVERSION 14,2,2,0
PRODUCTVERSION 14,2,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "14.1.1"
VALUE "FileVersion", "14.2.2"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "14.1.1"
VALUE "ProductVersion", "14.2.2"
VALUE "SquirrelAwareVersion", "1"
END
END

View File

@@ -60,8 +60,7 @@ bool ElectronSerialDelegate::HasPortPermission(
auto* chooser_context =
SerialChooserContextFactory::GetForBrowserContext(browser_context);
return chooser_context->HasPortPermission(
frame->GetLastCommittedOrigin(),
web_contents->GetMainFrame()->GetLastCommittedOrigin(), port);
web_contents->GetMainFrame()->GetLastCommittedOrigin(), port, frame);
}
device::mojom::SerialPortManager* ElectronSerialDelegate::GetPortManager(

View File

@@ -11,22 +11,25 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "shell/browser/web_contents_permission_helper.h"
namespace electron {
constexpr char kPortNameKey[] = "name";
constexpr char kTokenKey[] = "token";
#if defined(OS_WIN)
constexpr char kDeviceInstanceIdKey[] = "device_instance_id";
const char kDeviceInstanceIdKey[] = "device_instance_id";
#else
constexpr char kVendorIdKey[] = "vendor_id";
constexpr char kProductIdKey[] = "product_id";
constexpr char kSerialNumberKey[] = "serial_number";
const char kVendorIdKey[] = "vendor_id";
const char kProductIdKey[] = "product_id";
const char kSerialNumberKey[] = "serial_number";
#if defined(OS_MAC)
constexpr char kUsbDriverKey[] = "usb_driver";
const char kUsbDriverKey[] = "usb_driver";
#endif // defined(OS_MAC)
#endif // defined(OS_WIN)
#endif // defined(OS_WIN
std::string EncodeToken(const base::UnguessableToken& token) {
const uint64_t data[2] = {token.GetHighForSerialization(),
@@ -82,30 +85,51 @@ base::Value PortInfoToValue(const device::mojom::SerialPortInfo& port) {
}
SerialChooserContext::SerialChooserContext() = default;
SerialChooserContext::~SerialChooserContext() = default;
void SerialChooserContext::GrantPortPermission(
const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
const device::mojom::SerialPortInfo& port) {
const url::Origin& origin,
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host) {
base::Value value = PortInfoToValue(port);
port_info_.insert({port.token, value.Clone()});
ephemeral_ports_[{requesting_origin, embedding_origin}].insert(port.token);
if (CanStorePersistentEntry(port)) {
auto* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
auto* permission_helper =
WebContentsPermissionHelper::FromWebContents(web_contents);
permission_helper->GrantSerialPortPermission(origin, std::move(value),
render_frame_host);
return;
}
ephemeral_ports_[origin].insert(port.token);
}
bool SerialChooserContext::HasPortPermission(
const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
const device::mojom::SerialPortInfo& port) {
auto it = ephemeral_ports_.find({requesting_origin, embedding_origin});
const url::Origin& origin,
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host) {
auto it = ephemeral_ports_.find(origin);
if (it != ephemeral_ports_.end()) {
const std::set<base::UnguessableToken> ports = it->second;
if (base::Contains(ports, port.token))
return true;
}
return false;
if (!CanStorePersistentEntry(port)) {
return false;
}
auto* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
auto* permission_helper =
WebContentsPermissionHelper::FromWebContents(web_contents);
base::Value value = PortInfoToValue(port);
return permission_helper->CheckSerialPortPermission(origin, std::move(value),
render_frame_host);
}
// static
@@ -169,14 +193,6 @@ void SerialChooserContext::OnPortRemoved(
for (auto& observer : port_observer_list_)
observer.OnPortRemoved(*port);
std::vector<std::pair<url::Origin, url::Origin>> revoked_url_pairs;
for (auto& map_entry : ephemeral_ports_) {
std::set<base::UnguessableToken>& ports = map_entry.second;
if (ports.erase(port->token) > 0) {
revoked_url_pairs.push_back(map_entry.first);
}
}
port_info_.erase(port->token);
}

View File

@@ -30,6 +30,20 @@ class Value;
namespace electron {
extern const char kHidVendorIdKey[];
extern const char kHidProductIdKey[];
#if defined(OS_WIN)
extern const char kDeviceInstanceIdKey[];
#else
extern const char kVendorIdKey[];
extern const char kProductIdKey[];
extern const char kSerialNumberKey[];
#if defined(OS_MAC)
extern const char kUsbDriverKey[];
#endif // defined(OS_MAC)
#endif // defined(OS_WIN)
class SerialChooserContext : public KeyedService,
public device::mojom::SerialPortManagerClient {
public:
@@ -39,12 +53,12 @@ class SerialChooserContext : public KeyedService,
~SerialChooserContext() override;
// Serial-specific interface for granting and checking permissions.
void GrantPortPermission(const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
const device::mojom::SerialPortInfo& port);
bool HasPortPermission(const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
const device::mojom::SerialPortInfo& port);
void GrantPortPermission(const url::Origin& origin,
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host);
bool HasPortPermission(const url::Origin& origin,
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host);
static bool CanStorePersistentEntry(
const device::mojom::SerialPortInfo& port);
@@ -64,16 +78,9 @@ class SerialChooserContext : public KeyedService,
void SetUpPortManagerConnection(
mojo::PendingRemote<device::mojom::SerialPortManager> manager);
void OnPortManagerConnectionError();
void OnGetPorts(const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
blink::mojom::SerialService::GetPortsCallback callback,
std::vector<device::mojom::SerialPortInfoPtr> ports);
// Tracks the set of ports to which an origin (potentially embedded in another
// origin) has access to. Key is (requesting_origin, embedding_origin).
std::map<std::pair<url::Origin, url::Origin>,
std::set<base::UnguessableToken>>
ephemeral_ports_;
// Tracks the set of ports to which an origin has access to.
std::map<url::Origin, std::set<base::UnguessableToken>> ephemeral_ports_;
// Holds information about ports in |ephemeral_ports_|.
std::map<base::UnguessableToken, base::Value> port_info_;

View File

@@ -67,9 +67,9 @@ SerialChooserController::SerialChooserController(
: WebContentsObserver(web_contents),
filters_(std::move(filters)),
callback_(std::move(callback)),
serial_delegate_(serial_delegate) {
requesting_origin_ = render_frame_host->GetLastCommittedOrigin();
embedding_origin_ = web_contents->GetMainFrame()->GetLastCommittedOrigin();
serial_delegate_(serial_delegate),
render_frame_host_id_(render_frame_host->GetGlobalId()) {
origin_ = web_contents->GetMainFrame()->GetLastCommittedOrigin();
chooser_context_ = SerialChooserContextFactory::GetForBrowserContext(
web_contents->GetBrowserContext())
@@ -125,8 +125,8 @@ void SerialChooserController::OnDeviceChosen(const std::string& port_id) {
return ptr->token.ToString() == port_id;
});
if (it != ports_.end()) {
chooser_context_->GrantPortPermission(requesting_origin_,
embedding_origin_, *it->get());
auto* rfh = content::RenderFrameHost::FromID(render_frame_host_id_);
chooser_context_->GrantPortPermission(origin_, *it->get(), rfh);
RunCallback(it->Clone());
} else {
RunCallback(/*port=*/nullptr);

View File

@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/serial_chooser.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
@@ -53,8 +54,7 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
std::vector<blink::mojom::SerialPortFilterPtr> filters_;
content::SerialChooser::Callback callback_;
url::Origin requesting_origin_;
url::Origin embedding_origin_;
url::Origin origin_;
base::WeakPtr<SerialChooserContext> chooser_context_;
@@ -62,6 +62,8 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
base::WeakPtr<ElectronSerialDelegate> serial_delegate_;
content::GlobalRenderFrameHostId render_frame_host_id_;
base::WeakPtrFactory<SerialChooserController> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SerialChooserController);

View File

@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#ifndef SHELL_BROWSER_UI_COCOA_BRY_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#define SHELL_BROWSER_UI_COCOA_BRY_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#ifndef SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#define SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#import <AppKit/AppKit.h>
@@ -52,4 +52,4 @@ using electron::InspectableWebContentsViewMac;
@end
#endif // SHELL_BROWSER_UI_COCOA_BRY_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#endif // SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_

View File

@@ -369,6 +369,20 @@ void FileChooserDialog::AddFilters(const Filters& filters) {
}
}
bool CanPreview(const struct stat& st) {
// Only preview regular files; pipes may hang.
// See https://crbug.com/534754.
if (!S_ISREG(st.st_mode)) {
return false;
}
// Don't preview huge files; they may crash.
// https://github.com/electron/electron/issues/31630
// Setting an arbitrary filesize max t at 100 MB here.
constexpr off_t ArbitraryMax = 100000000ULL;
return st.st_size < ArbitraryMax;
}
void FileChooserDialog::OnUpdatePreview(GtkFileChooser* chooser) {
CHECK(!*supports_gtk_file_chooser_native);
gchar* filename = gtk_file_chooser_get_preview_filename(chooser);
@@ -377,10 +391,8 @@ void FileChooserDialog::OnUpdatePreview(GtkFileChooser* chooser) {
return;
}
// Don't attempt to open anything which isn't a regular file. If a named
// pipe, this may hang. See https://crbug.com/534754.
struct stat stat_buf;
if (stat(filename, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode)) {
struct stat sb;
if (stat(filename, &sb) != 0 || !CanPreview(sb)) {
g_free(filename);
gtk_file_chooser_set_preview_widget_active(chooser, FALSE);
return;

View File

@@ -17,10 +17,11 @@
#include "third_party/skia/include/core/SkUnPreMultiply.h"
#include "ui/gtk/gtk_compat.h" // nogncheck
namespace gtk_util {
// The following utilities are pulled from
// https://source.chromium.org/chromium/chromium/src/+/main:ui/gtk/select_file_dialog_impl_gtk.cc;l=43-74
namespace gtk_util {
namespace {
const char* GettextPackage() {
static base::NoDestructor<std::string> gettext_package(
@@ -32,44 +33,34 @@ const char* GtkGettext(const char* str) {
return g_dgettext(GettextPackage(), str);
}
} // namespace
const char* GetCancelLabel() {
if (!gtk::GtkCheckVersion(4))
return "gtk-cancel"; // In GTK3, this is GTK_STOCK_CANCEL.
static const char* cancel = GtkGettext("_Cancel");
return cancel;
}
const char* GetOpenLabel() {
if (!gtk::GtkCheckVersion(4))
return "gtk-open"; // In GTK3, this is GTK_STOCK_OPEN.
static const char* open = GtkGettext("_Open");
return open;
}
const char* GetSaveLabel() {
if (!gtk::GtkCheckVersion(4))
return "gtk-save"; // In GTK3, this is GTK_STOCK_SAVE.
static const char* save = GtkGettext("_Save");
return save;
}
const char* GetOkLabel() {
if (!gtk::GtkCheckVersion(4))
return "gtk-ok"; // In GTK3, this is GTK_STOCK_OK.
static const char* ok = GtkGettext("_Ok");
return ok;
}
const char* GetNoLabel() {
if (!gtk::GtkCheckVersion(4))
return "gtk-no"; // In GTK3, this is GTK_STOCK_NO.
static const char* no = GtkGettext("_No");
return no;
}
const char* GetYesLabel() {
if (!gtk::GtkCheckVersion(4))
return "gtk-yes"; // In GTK3, this is GTK_STOCK_YES.
static const char* yes = GtkGettext("_Yes");
return yes;
}

View File

@@ -11,9 +11,6 @@ class SkBitmap;
namespace gtk_util {
const char* GettextPackage();
const char* GtkGettext(const char* str);
const char* GetCancelLabel();
const char* GetOpenLabel();
const char* GetSaveLabel();

View File

@@ -140,6 +140,7 @@ void WebContentsPermissionHelper::RequestMediaAccessPermission(
media_types->AppendString("video");
}
details.SetList("mediaTypes", std::move(media_types));
details.SetString("securityOrigin", request.security_origin.spec());
// The permission type doesn't matter here, AUDIO_CAPTURE/VIDEO_CAPTURE
// are presented as same type in content_converter.h.
@@ -190,6 +191,24 @@ bool WebContentsPermissionHelper::CheckSerialAccessPermission(
static_cast<content::PermissionType>(PermissionType::SERIAL), &details);
}
bool WebContentsPermissionHelper::CheckSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const {
return CheckDevicePermission(
static_cast<content::PermissionType>(PermissionType::SERIAL), origin,
&device, render_frame_host);
}
void WebContentsPermissionHelper::GrantSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const {
return GrantDevicePermission(
static_cast<content::PermissionType>(PermissionType::SERIAL), origin,
&device, render_frame_host);
}
bool WebContentsPermissionHelper::CheckHIDAccessPermission(
const url::Origin& embedding_origin) const {
base::DictionaryValue details;

View File

@@ -42,6 +42,14 @@ class WebContentsPermissionHelper
bool CheckMediaAccessPermission(const GURL& security_origin,
blink::mojom::MediaStreamType type) const;
bool CheckSerialAccessPermission(const url::Origin& embedding_origin) const;
bool CheckSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const;
void GrantSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const;
bool CheckHIDAccessPermission(const url::Origin& embedding_origin) const;
bool CheckHIDDevicePermission(
const url::Origin& origin,

View File

@@ -21,7 +21,7 @@ namespace gin {
template <typename T>
v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate, T&& input) {
return Converter<typename std::remove_reference<T>::type>::ToV8(
isolate, std::move(input));
isolate, std::forward<T>(input));
}
#if !defined(OS_LINUX) && !defined(OS_FREEBSD)

View File

@@ -282,9 +282,9 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
ignore_result(source_promise->Then(
source_context,
gin::ConvertToV8(destination_context->GetIsolate(), then_cb)
gin::ConvertToV8(destination_context->GetIsolate(), std::move(then_cb))
.As<v8::Function>(),
gin::ConvertToV8(destination_context->GetIsolate(), catch_cb)
gin::ConvertToV8(destination_context->GetIsolate(), std::move(catch_cb))
.As<v8::Function>()));
object_cache->CacheProxiedObject(value, proxied_promise_handle);

View File

@@ -50,6 +50,10 @@ void WebWorkerObserver::WorkerScriptReadyForEvaluation(
// Start the embed thread.
node_bindings_->PrepareMessageLoop();
// Setup node tracing controller.
if (!node::tracing::TraceEventHelper::GetAgent())
node::tracing::TraceEventHelper::SetAgent(node::CreateAgent());
// Setup node environment for each window.
bool initialized = node::InitializeContext(worker_context);
CHECK(initialized);

View File

@@ -151,7 +151,7 @@ describe('BrowserView module', () => {
w.addBrowserView(view);
});
it('does not crash if the BrowserView webContents are destroyed prior to window removal', () => {
it('does not crash if the BrowserView webContents are destroyed prior to window addition', () => {
expect(() => {
const view1 = new BrowserView();
(view1.webContents as any).destroy();
@@ -159,6 +159,15 @@ describe('BrowserView module', () => {
}).to.not.throw();
});
it('does not crash if the webContents is destroyed after a URL is loaded', () => {
view = new BrowserView();
expect(async () => {
view.setBounds({ x: 0, y: 0, width: 400, height: 300 });
await view.webContents.loadURL('data:text/html,hello there');
view.webContents.destroy();
}).to.not.throw();
});
it('can handle BrowserView reparenting', async () => {
view = new BrowserView();

View File

@@ -110,6 +110,11 @@ describe('BrowserWindow module', () => {
await closed;
});
it('should not crash if called after webContents is destroyed', () => {
w.webContents.destroy();
w.webContents.on('destroyed', () => w.close());
});
it('should emit unload handler', async () => {
await w.loadFile(path.join(fixtures, 'api', 'unload.html'));
const closed = emittedOnce(w, 'closed');
@@ -948,6 +953,17 @@ describe('BrowserWindow module', () => {
await resize;
expectBoundsEqual(w.getSize(), size);
});
it('doesn\'t change bounds when maximum size is set', () => {
w.setMenu(null);
w.setMaximumSize(400, 400);
// Without https://github.com/electron/electron/pull/29101
// following call would shrink the window to 384x361.
// There would be also DCHECK in resize_utils.cc on
// debug build.
w.setAspectRatio(1.0);
expectBoundsEqual(w.getSize(), [400, 400]);
});
});
describe('BrowserWindow.setPosition(x, y)', () => {
@@ -3498,7 +3514,7 @@ describe('BrowserWindow module', () => {
const w = new BrowserWindow({ show: false });
const c = new BrowserWindow({ show: false, parent: w });
expect(c.isVisible()).to.be.false('child is visible');
expect(c.getParentWindow().isVisible()).to.be.false('parent is visible');
expect(c.getParentWindow()!.isVisible()).to.be.false('parent is visible');
});
});
@@ -4170,8 +4186,6 @@ describe('BrowserWindow module', () => {
const leaveFullScreen = emittedOnce(w, 'leave-full-screen');
w.setFullScreen(false);
await leaveFullScreen;
w.close();
});
it('can be changed with setFullScreen method', async () => {

View File

@@ -354,7 +354,7 @@ describe('webRequest module', () => {
it('does not change content-disposition header by default', async () => {
ses.webRequest.onHeadersReceived((details, callback) => {
expect(details.responseHeaders!['content-disposition']).to.deep.equal([' attachment; filename=aa中aa.txt']);
expect(details.responseHeaders!['content-disposition']).to.deep.equal([' attachment; filename="aa中aa.txt"']);
callback({});
});
const { data, headers } = await ajax(defaultURL + 'contentDisposition');

View File

@@ -945,6 +945,7 @@ describe('chromium features', () => {
afterEach(closeAllWindows);
afterEach(() => {
session.defaultSession.setPermissionCheckHandler(null);
session.defaultSession.setPermissionRequestHandler(null);
});
it('can return labels of enumerated devices', async () => {
@@ -994,6 +995,32 @@ describe('chromium features', () => {
const [, secondDeviceIds] = await emittedOnce(ipcMain, 'deviceIds', () => w.webContents.reload());
expect(firstDeviceIds).to.not.deep.equal(secondDeviceIds);
});
it('provides a securityOrigin to the request handler', async () => {
session.defaultSession.setPermissionRequestHandler(
(wc, permission, callback, details) => {
if (details.securityOrigin !== undefined) {
callback(true);
} else {
callback(false);
}
}
);
const w = new BrowserWindow({ show: false });
w.loadFile(path.join(fixturesPath, 'pages', 'blank.html'));
const labels = await w.webContents.executeJavaScript(`navigator.mediaDevices.getUserMedia({
video: {
mandatory: {
chromeMediaSource: "desktop",
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
}).then((stream) => stream.getVideoTracks())`);
expect(labels.some((l: any) => l)).to.be.true();
});
});
describe('window.opener access', () => {

View File

@@ -54,24 +54,26 @@ testStorage(function (
syncForRemove, localForRemove,
syncForClear, localForClear
) {
const message = JSON.stringify({
runtimeId: chrome.runtime.id,
tabId: chrome.devtools.inspectedWindow.tabId,
i18nString: chrome.i18n.getMessage('foo', ['bar', 'baz']),
storageItems: {
local: {
set: localForSet,
remove: localForRemove,
clear: localForClear
},
sync: {
set: syncForSet,
remove: syncForRemove,
clear: syncForClear
setTimeout(() => {
const message = JSON.stringify({
runtimeId: chrome.runtime.id,
tabId: chrome.devtools.inspectedWindow.tabId,
i18nString: chrome.i18n.getMessage('foo', ['bar', 'baz']),
storageItems: {
local: {
set: localForSet,
remove: localForRemove,
clear: localForClear
},
sync: {
set: syncForSet,
remove: syncForRemove,
clear: syncForClear
}
}
}
});
});
const sendMessage = `require('electron').ipcRenderer.send('answer', ${message})`;
window.chrome.devtools.inspectedWindow.eval(sendMessage, function () {});
const sendMessage = `require('electron').ipcRenderer.send('answer', ${message})`;
window.chrome.devtools.inspectedWindow.eval(sendMessage, function () {});
});
});

View File

@@ -397,6 +397,23 @@ describe('<webview> tag', function () {
expect(webview.getZoomFactor()).to.equal(1.2);
await w.loadURL(`${zoomScheme}://host1`);
});
it('does not crash when changing zoom level after webview is destroyed', async () => {
const w = new BrowserWindow({
show: false,
webPreferences: {
webviewTag: true,
nodeIntegration: true,
session: webviewSession,
contextIsolation: false
}
});
const attachPromise = emittedOnce(w.webContents, 'did-attach-webview');
await w.loadFile(path.join(fixtures, 'pages', 'webview-zoom-inherited.html'));
await attachPromise;
await w.webContents.executeJavaScript('view.remove()');
w.webContents.setZoomLevel(0.5);
});
});
describe('requestFullscreen from webview', () => {