Compare commits

..

47 Commits

Author SHA1 Message Date
Sudowoodo Release Bot
ea234f9cb9 Bump v12.1.0 2021-08-31 12:05:51 -07:00
trop[bot]
013825c986 chore: cherry-pick fix for 1234770 from v8 (#30634)
* chore: cherry-pick fix for 1234770 from v8 (#30586)

* chore: cherry-pick fix for 1234770 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>

* Update .patches

* chore: update patches

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-30 21:26:02 +09:00
Cheng Zhao
c7d61b6ac6 chore: cherry-pick fix for 1234829 from angle (#30624)
* chore: cherry-pick fix for 1234829 from angle

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-30 19:34:03 +09:00
trop[bot]
cdf0387f6f chore: cherry-pick fix for 1234764 from v8 (#30660)
* chore: cherry-pick fix for 1234764 from v8 (#30587)

* chore: cherry-pick fix for 1234764 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>

* Update .patches

* chore: update patches

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-30 19:33:37 +09:00
Jeremy Rose
d3e7f2b302 fix: remove ipc wrapper for nativeImage.createThumbnailFromPath (#30737) 2021-08-30 19:32:36 +09:00
Sudowoodo Release Bot
21258845f0 Bump v12.0.18 2021-08-27 10:19:01 -07:00
trop[bot]
96bcadd290 fix: {exit|enter}-html-fullscreen emitted after esc in webview (#30669)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-08-24 10:47:02 +02:00
trop[bot]
ee1030e044 chore: cherry-pick fix for 1227933 from chromium (#30615)
* chore: cherry-pick 1227933 from chromium

* chore: update patches

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-23 17:06:27 +09:00
trop[bot]
11d1bfa071 chore: cherry-pick 4ce2abc17078 from chromium (#30581)
* chore: cherry-pick 4ce2abc17078 from chromium (#30449)

* chore: cherry-pick 4ce2abc17078 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>

* Update .patches

* chore: update patches

Co-authored-by: Steven Barbaro <StevenEBarbaro@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2021-08-19 15:11:48 +09:00
trop[bot]
131be8cefd chore: cherry-pick e2123a8e0943 from chromium (#30580)
* chore: cherry-pick e2123a8e0943 from chromium

* chore: update patches

* chore: update patches

Co-authored-by: Steven Barbaro <StevenEBarbaro@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-19 08:25:58 +09:00
Sudowoodo Release Bot
61b6ede68c Bump v12.0.17 2021-08-17 15:41:48 -07:00
Keeley Hammond
c1c02e172e ci: update git on CI machines (#30526) (#30574) 2021-08-17 15:40:45 -07:00
Sudowoodo Release Bot
8c399548b5 Revert "Bump v12.0.17"
This reverts commit 118f8c4b88.
2021-08-17 09:30:33 -07:00
Sudowoodo Release Bot
118f8c4b88 Bump v12.0.17 2021-08-17 08:45:49 -07:00
trop[bot]
8210faeb09 fix: color select eyedropper not working within DevTools (#29729) (#30490)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-08-13 09:46:47 +09:00
Jeremy Rose
1c927dbbe8 fix: check DCHECK_IS_ON() instead of #ifdef DCHECK_IS_ON (#29674) (#30504)
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
2021-08-12 11:50:16 -07:00
Jeremy Rose
56cb0d52b9 build: decode error output as utf8 (#30093) (#30505) 2021-08-12 11:44:13 -07:00
Jeremy Rose
083913c738 test: disable failing node tests (#30098) (#30506)
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
2021-08-12 11:08:39 -04:00
trop[bot]
b164a0506d docs: add missing <webview> event documentation (#30464)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-08-10 10:20:48 +02:00
Jeremy Rose
494c3f8c04 fix: backport 774cfcb from sqlite (#30398) 2021-08-09 09:58:17 -07:00
trop[bot]
f5321177e7 build: rebase release branch before reverting bump (#30416)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2021-08-09 09:54:23 +02:00
Electron Bot
58f180201e Bump v12.0.16 2021-08-03 10:22:35 -07:00
trop[bot]
767f98b213 build: set the export goma auth fallback flag for the control process (#30316)
Co-authored-by: Samuel Attard <sam@electronjs.org>
2021-08-02 09:55:54 +09:00
trop[bot]
c8da588479 chore: update deps (#30343)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2021-07-30 14:56:49 -07:00
trop[bot]
d9538c7fd4 fix: use contentAspectRatio not aspectRatio (#30329)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-07-30 02:28:35 -07:00
Pedro Pontes
c51aec4911 chore: cherry-pick 1168f81092 from sqlite (#30295)
* chore: cherry-pick 1168f81092 from sqlite

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-07-30 09:00:28 +09:00
Pedro Pontes
73d9a14c6f chore: cherry-pick 24293de155 from chromium (#30261)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-07-30 08:57:53 +09:00
Pedro Pontes
02f9078c92 chore: cherry-pick e60cc80ff744 from chromium (#30227)
* chore: cherry-pick e60cc80ff744 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-07-29 19:46:14 +09:00
Pedro Pontes
9a77e2b07b chore: cherry-pick 0e7f91956cec from v8 (#30198) 2021-07-29 09:23:06 +09:00
Pedro Pontes
e2e85fb8fc chore: cherry-pick 3feda0244490 from chromium (#30195)
* chore: cherry-pick 3feda0244490 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-07-29 09:22:34 +09:00
trop[bot]
4e68a33c60 chore: update publish to npm to use GitHub token (#30289)
ensures that we don't get hit with a rate limit while trying to publish a release.

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2021-07-28 12:25:09 -07:00
Pedro Pontes
6e1e2399c7 chore: cherry-pick ac9dc1235e28 from chromium (#30266)
* chore: cherry-pick ac9dc1235e28 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-07-28 15:55:44 +02:00
Pedro Pontes
99413641d1 chore: cherry-pick 79fc7bcbc9 from chromium. (#30182) 2021-07-27 09:16:25 +09:00
Pedro Pontes
ab0f3fd8ff chore: cherry-pick cd98d7c0dae9 from chromium (#30252)
* chore: cherry-pick cd98d7c0dae9 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-07-26 17:50:45 +09:00
trop[bot]
9ce16a44db fix: increase stack size on windows x86 (#30244)
* fix: increace main thread stack size on windows x86

* chore: improve quit-on-crashed-event spec

* chore: add debug logs

* Revert "chore: add debug logs"

This reverts commit 0be81ae07c.

* chore: use a reliable crash endpoint

Co-authored-by: Stephen Wang <wangwenqiang.wwq@bytedance.com>
Co-authored-by: Deepak Mohan <hop2deep@gmail.com>
2021-07-26 17:49:23 +09:00
trop[bot]
f551883fb8 build: handle release failure by existing with code 1 (#30220)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2021-07-21 11:14:15 -04:00
Pedro Pontes
3ec9f58c8e chore: cherry-pick e76178b896f2 from v8 (#30185)
* chore: cherry-pick e76178b896f2 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-07-19 09:22:18 -07:00
Electron Bot
a52eaeb6e1 Bump v12.0.15 2021-07-15 10:18:21 -07:00
trop[bot]
08ce5bbd33 docs: fix fiddle path (#30143)
This is breaking the build in `electron/electronjs.org-new` and will
most likely not work when clicking the "Fiddle" button.

Rel: https://github.com/electron/electronjs.org-new/pull/65

Co-authored-by: Antón Molleda <amolleda@gmail.com>
2021-07-15 15:26:31 +09:00
Milan Burda
488fbfe469 fix: potential crash on macOS app exit (#29941) (#30138)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-07-15 11:42:24 +09:00
Milan Burda
705a9a39c4 fix: pressing ESC should exit fullscreen from webview (#30063) (#30137)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2021-07-15 11:42:02 +09:00
trop[bot]
d98b2a760c docs: add <webview> 'did-attach' event documentation (#30130)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-07-15 10:40:52 +09:00
trop[bot]
e48e899807 docs: update quick-start.md (#30132)
Change app-quit link definition, so both window-all-closed and app-quit redirects to appropriate sites.

Co-authored-by: Davenury <57959794+Davenury@users.noreply.github.com>
2021-07-14 22:26:01 +09:00
Jeremy Rose
d84ef8bfb3 fix: crash when invoking login callback synchronously (#30092) 2021-07-14 20:47:56 +09:00
trop[bot]
a8cdc21731 chore: cherry-pick 9bab573a37 from chromium (#30099)
* chore: cherry-pick 9bab573a37 from chromium

Refs https://chromium-review.googlesource.com/c/chromium/src/+/3010140

* Update .patches

* chore: update patches

Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-07-13 10:54:43 -07:00
trop[bot]
fc06c55bc0 fix: window ordering on mac (#30067)
* fix: window ordering on mac

* chore: fix flaky fullscreen inheritance test

Co-authored-by: deepak1556 <hop2deep@gmail.com>
2021-07-12 00:22:49 -07:00
trop[bot]
f459315060 docs: modernize protocol-handler docs (#30056)
* docs: modernize protocol-handler docs

* docs: iadd contextIsolation

* docs: add guide for launch-app-from-URL-in-other-app

* docs: address comments

* chore: fix brackets

* chore: add escaped brackets

Co-authored-by: George Xu <gxu@slack-corp.com>
2021-07-09 14:37:43 -04:00
61 changed files with 2848 additions and 208 deletions

View File

@@ -79,7 +79,7 @@ executors:
# Build machines configs.
docker-image: &docker-image
docker:
- image: electron.azurecr.io/build:4cec2c5ab66765caa724e37bae2bffb9b29722a5
- image: electron.azurecr.io/build:d818f06a9b1540c7fd38f75ad5a2c493dd6843b6
machine-linux-medium: &machine-linux-medium
<<: *docker-image
@@ -337,6 +337,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
npm install
mkdir third_party
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
export GOMA_FALLBACK_ON_AUTH_FAILURE=true
third_party/goma/goma_ctl.py ensure_start
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV

View File

@@ -1 +1 @@
12.0.14
12.1.0

View File

@@ -21,6 +21,6 @@ except subprocess.CalledProcessError as e:
+ "' failed with code '"
+ str(e.returncode)
+ "':\n"
+ e.output
+ e.output.decode('utf8')
)
sys.exit(e.returncode)

View File

@@ -139,6 +139,8 @@ static_library("chrome") {
if (enable_color_chooser) {
sources += [
"//chrome/browser/devtools/devtools_eye_dropper.cc",
"//chrome/browser/devtools/devtools_eye_dropper.h",
"//chrome/browser/platform_util.cc",
"//chrome/browser/platform_util.h",
"//chrome/browser/ui/browser_dialogs.h",

View File

@@ -718,6 +718,10 @@ Corresponds to the points in time when the spinner of the tab starts spinning.
Corresponds to the points in time when the spinner of the tab stops spinning.
### Event: 'did-attach'
Fired when attached to the embedder web contents.
### Event: 'dom-ready'
Fired when document in the given frame is loaded.
@@ -838,6 +842,19 @@ this purpose.
Calling `event.preventDefault()` does __NOT__ have any effect.
### Event: 'did-start-navigation'
Returns:
* `url` String
* `isInPlace` Boolean
* `isMainFrame` Boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer
Emitted when any frame (including main) starts navigating. `isInPlace` will be
`true` for in-page navigations.
### Event: 'did-navigate'
Returns:
@@ -850,6 +867,23 @@ This event is not emitted for in-page navigations, such as clicking anchor links
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
this purpose.
### Event: 'did-frame-navigate'
Returns:
* `url` String
* `httpResponseCode` Integer - -1 for non HTTP navigations
* `httpStatusText` String - empty for non HTTP navigations,
* `isMainFrame` Boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer
Emitted when any frame navigation is done.
This event is not emitted for in-page navigations, such as clicking anchor links
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
this purpose.
### Event: 'did-navigate-in-page'
Returns:

View File

@@ -1,92 +1,81 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>app.setAsDefaultProtocol Demo</title>
</head>
<body>
<section>
<header>
<h1>
Protocol Handler
</h1>
<h3>The <code>app</code> module provides methods for handling protocols.</h3>
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a browser asks to be your default for viewing web pages.</p>
<h1>App Default Protocol Demo</h1>
<p>Open the <a href="https://electronjs.org/docs/api/app">full app API documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> in your browser.</p>
</header>
<p>The protocol API allows us to register a custom protocol and intercept existing protocol requests.</p>
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a
browser asks to be your default for viewing web pages.</p>
<div >
<button id="open-in-browser" class="js-container-target demo-toggle-button">Launch current page in browser
<div class="demo-meta u-avoid-clicks">Supports: Win, macOS <span class="demo-meta-divider">|</span> Process: Main</div>
</button>
<section id='open-app-link'>
<a href="electron-api-demos://open">Now... launch the app from a web link</a>
</section>
<div >
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app as the default for <code>electron-api-demos://</code>. The demo button above will launch a page in your default browser with a link. Click that link and it will re-launch this app.</p>
<h5>Packaging</h5>
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code> for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this app is below.</p>
<h5>Renderer Process</h5>
<pre><code>
const {shell} = require('electron')
const path = require('path')
const protocolHandlerBtn = document.getElementById('protocol-handler')
protocolHandlerBtn.addEventListener('click', () => {
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
const pagePath = path.join('file://', pageDirectory, '../../sections/system/protocol-link.html')
shell.openExternal(pagePath)
})
</code></pre>
<h5>Main Process</h5>
<pre><code>
const {app, dialog} = require('electron')
const path = require('path')
<p>Open the <a href="https://www.electronjs.org/docs/api/protocol">full protocol API documentation</a> in your
browser.</p>
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
}
} else {
app.setAsDefaultProtocolClient('electron-api-demos')
}
-----
app.on('open-url', (event, url) => {
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
})
<h3>Demo</h3>
<p>
First: Launch current page in browser
<button id="open-in-browser" class="js-container-target demo-toggle-button">
Click to Launch Browser
</button>
</p>
</code></pre>
<h5>macOS plist</h5>
<pre><code>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>electron-api-demos</string>
</array>
<key>CFBundleURLName</key>
<string>Electron API Demos Protocol</string>
</dict>
</array>
<key>ElectronTeamID</key>
<string>VEKTX9H2N7</string>
</dict>
</plist>
</code>
</pre>
</div>
</div>
<script type="text/javascript">
require('./renderer.js')
</script>
</section>
<p>
Then: Launch the app from a web link!
<a href="electron-fiddle://open">Click here to launch the app</a>
</p>
----
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app
as the default for <code>electron-fiddle://</code>. The demo button above will launch a page in your default
browser with a link. Click that link and it will re-launch this app.</p>
<h3>Packaging</h3>
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in
development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code>
for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you
can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this
app is below:</p>
<p>
<h5>macOS plist</h5>
<pre><code>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
&lt;key&gt;CFBundleURLTypes&lt;/key&gt;
&lt;array&gt;
&lt;dict&gt;
&lt;key&gt;CFBundleURLSchemes&lt;/key&gt;
&lt;array&gt;
&lt;string&gt;electron-api-demos&lt;/string&gt;
&lt;/array&gt;
&lt;key&gt;CFBundleURLName&lt;/key&gt;
&lt;string&gt;Electron API Demos Protocol&lt;/string&gt;
&lt;/dict&gt;
&lt;/array&gt;
&lt;key&gt;ElectronTeamID&lt;/key&gt;
&lt;string&gt;VEKTX9H2N7&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</code>
</pre>
<p>
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
</body>
</html>
</html>

View File

@@ -1,10 +1,39 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, dialog } = require('electron')
const { app, BrowserWindow, ipcMain, shell } = require('electron')
const path = require('path')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
let mainWindow;
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
}
} else {
app.setAsDefaultProtocolClient('electron-fiddle')
}
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
})
// Create mainWindow, load the rest of the app, etc...
app.whenReady().then(() => {
createWindow()
})
app.on('open-url', (event, url) => {
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
})
}
function createWindow () {
// Create the browser window.
@@ -12,58 +41,23 @@ function createWindow () {
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
preload: path.join(__dirname, 'preload.js'),
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
if (process.platform !== 'darwin') app.quit()
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
}
} else {
app.setAsDefaultProtocolClient('electron-api-demos')
}
app.on('open-url', (event, url) => {
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
// Handle window controls via IPC
ipcMain.on('shell:open', () => {
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
const pagePath = path.join('file://', pageDirectory, 'index.html')
shell.openExternal(pagePath)
})

View File

@@ -0,0 +1,11 @@
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
const { contextBridge, ipcRenderer } = require('electron')
// Set up context bridge between the renderer process and the main process
contextBridge.exposeInMainWorld(
'shell',
{
open: () => ipcRenderer.send('shell:open'),
}
)

View File

@@ -1,14 +1,8 @@
const { shell } = require('electron')
const path = require('path')
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All APIs exposed by the context bridge are available here.
const openInBrowserButton = document.getElementById('open-in-browser')
const openAppLink = document.getElementById('open-app-link')
// Hides openAppLink when loaded inside Electron
openAppLink.style.display = 'none'
openInBrowserButton.addEventListener('click', () => {
console.log('clicked')
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
const pagePath = path.join('file://', pageDirectory, 'index.html')
shell.openExternal(pagePath)
})
// Binds the buttons to the context bridge API.
document.getElementById('open-in-browser').addEventListener('click', () => {
shell.open();
});

View File

@@ -0,0 +1,175 @@
---
title: launch-app-from-URL-in-another-app
description: This guide will take you through the process of setting your electron app as the default handler for a specific protocol.
slug: launch-app-from-url-in-another-app
hide_title: true
---
# Launching Your Electron App From A URL In Another App
## Overview
<!-- ✍ Update this section if you want to provide more details -->
This guide will take you through the process of setting your electron app as the default
handler for a specific [protocol](https://www.electronjs.org/docs/api/protocol).
By the end of this tutorial, we will have set our app to intercept and handle
any clicked URLs that start with a specific protocol. In this guide, the protocol
we will use will be "`electron-fiddle://`".
## Examples
### Main Process (main.js)
First we will import the required modules from `electron`. These modules help control our application life and create a native browser window.
```js
const { app, BrowserWindow, shell } = require('electron')
const path = require('path')
```
Next, we will proceed to register our application to handle all "`electron-fiddle://`" protocols.
```js
if (process.defaultApp) {
if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
}
} else {
app.setAsDefaultProtocolClient('electron-fiddle')
}
```
We will now define the function in charge of creating our browser window and load our application's `index.html` file.
```js
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html')
}
```
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
This code will be different in WindowsOS compared to MacOS and Linux. This is due to Windows requiring additional code in order to open the contents of the protocol link within the same electron instance. Read more about this [here](https://www.electronjs.org/docs/api/app#apprequestsingleinstancelock).
### Windows code:
```js
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
})
// Create mainWindow, load the rest of the app, etc...
app.whenReady().then(() => {
createWindow()
})
// handling the protocol. In this case, we choose to show an Error Box.
app.on('open-url', (event, url) => {
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
})
}
```
### MacOS and Linux code:
```js
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
})
// handling the protocol. In this case, we choose to show an Error Box.
app.on('open-url', (event, url) => {
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
})
```
Finally, we will add some additional code to handle when someone closes our application
```js
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
```
## Important Note:
### Packaging
This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS `plist` for the app is updated to include the new protocol handler. If you're using [`electron-packager`](https://github.com/electron/electron-packager) then you
can add the flag `--extend-info` with a path to the `plist` you've created. The one for this app is below:
### Plist
```XML
<p>
<h5>macOS plist</h5>
<pre><code>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>electron-api-demos</string>
</array>
<key>CFBundleURLName</key>
<string>Electron API Demos Protocol</string>
</dict>
</array>
<key>ElectronTeamID</key>
<string>VEKTX9H2N7</string>
</dict>
</plist>
</code>
</pre>
<p>
```
## Conclusion
After you start your electron app, you can now enter in a URL in your browser that contains the custom protocol, for example `"electron-fiddle://open"` and observe that the application will respond and show an error dialog box.
<!--
Because Electron examples usually require multiple files (HTML, CSS, JS
for the main and renderer process, etc.), we use this custom code block
for Fiddle (https://www.electronjs.org/fiddle).
Please modify any of the files in the referenced folder to fit your
example.
The content in this codeblock will not be rendered in the website so you
can leave it empty.
-->
```fiddle docs/fiddles/system/protocol-handler/launch-app-from-URL-in-another-app
```
<!-- ✍ Explanation of the code below -->

View File

@@ -223,7 +223,7 @@ app.on('window-all-closed', function () {
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
[window-all-closed]: ../api/app.md#event-window-all-closed
[window-all-closed]: ../api/app.md#appquit
[app-quit]: ../api/app.md#appquit
#### Open a window if none are open (macOS)

View File

@@ -1,6 +1,6 @@
import { app } from 'electron/main';
import type { WebContents } from 'electron/main';
import { clipboard, nativeImage } from 'electron/common';
import { clipboard } from 'electron/common';
import * as fs from 'fs';
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
@@ -113,7 +113,3 @@ ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event
ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadPath: string, error: Error) {
event.sender.emit('preload-error', event, preloadPath, error);
});
ipcMainInternal.handle(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, async (_, path: string, size: Electron.Size) => {
return typeUtils.serialize(await nativeImage.createThumbnailFromPath(path, size));
});

View File

@@ -39,5 +39,4 @@ export const enum IPC_MESSAGES {
INSPECTOR_SELECT_FILE = 'INSPECTOR_SELECT_FILE',
DESKTOP_CAPTURER_GET_SOURCES = 'DESKTOP_CAPTURER_GET_SOURCES',
NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH = 'NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH',
}

View File

@@ -1,11 +1,3 @@
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
import { deserialize } from '@electron/internal/common/type-utils';
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
const { nativeImage } = process._linkedBinding('electron_common_native_image');
nativeImage.createThumbnailFromPath = async (path: string, size: Electron.Size) => {
return deserialize(await ipcRendererInternal.invoke(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, path, size));
};
export default nativeImage;

View File

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

View File

@@ -1,2 +1,4 @@
d3d11_skip_blits_if_there_is_no_intersection_of_dest_areas.patch
cherry-pick-3d4f87ab5b9b.patch
cherry-pick-d8cb996.patch
cherry-pick-1fb846c.patch

View File

@@ -0,0 +1,90 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Knyazev <lexa.knyazev@gmail.com>
Date: Tue, 3 Aug 2021 01:57:49 +0400
Subject: Validate texStorage dimensions with compressed formats
Bug: angleproject:6230
Change-Id: I501ec1e6974bdc7e6731dcb88045edb0aa22b888
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3067329
Commit-Queue: Alexey Knyazev <lexa.knyazev@gmail.com>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 1d93a066580818c7616fa66252e6465f6137aceb..3935c52a894c5584eef66bea34a8684176909358 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -1339,17 +1339,26 @@ bool ValidateES3TexStorageParametersBase(const Context *context,
return false;
}
- if (formatInfo.compressed && target == TextureType::Rectangle)
+ if (formatInfo.compressed)
{
- context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
- return false;
- }
+ if (target == TextureType::Rectangle)
+ {
+ context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
+ return false;
+ }
- if (formatInfo.compressed && target == TextureType::_3D)
- {
- if (!ValidateES3CompressedFormatForTexture3D(context, formatInfo.internalFormat))
+ if (target == TextureType::_3D)
{
- // Error already generated.
+ if (!ValidateES3CompressedFormatForTexture3D(context, formatInfo.internalFormat))
+ {
+ // Error already generated.
+ return false;
+ }
+ }
+
+ if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, depth))
+ {
+ context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
return false;
}
}
diff --git a/src/tests/gl_tests/SRGBTextureTest.cpp b/src/tests/gl_tests/SRGBTextureTest.cpp
index 68fd9f7165ff237ed3c86a42be0b2a24dd9819c7..6c65740cb406e1c598dc41ff0e8998230a926883 100644
--- a/src/tests/gl_tests/SRGBTextureTest.cpp
+++ b/src/tests/gl_tests/SRGBTextureTest.cpp
@@ -340,7 +340,7 @@ TEST_P(SRGBTextureTestES3, SRGBOverrideFormats)
{
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get());
- glTexStorage2D(GL_TEXTURE_2D, 1, format, 1, 1);
+ glTexStorage2D(GL_TEXTURE_2D, 1, format, 4, 4);
GLenum error = glGetError();
if (error == GL_INVALID_ENUM)
{
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
index 89eb4d639a3853636524ad112a24f15d46fa1119..b9380bb10ad434acfc858c08db8a629db0bfaecf 100644
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
@@ -5023,6 +5023,21 @@ void WebGLCompatibilityTest::testCompressedTexLevelDimension(GLenum format,
{
EXPECT_GL_ERROR(expectedError) << explanation;
}
+
+ if (level == 0 && width > 0 && getClientMajorVersion() >= 3)
+ {
+ GLTexture sourceTextureStorage;
+ glBindTexture(GL_TEXTURE_2D, sourceTextureStorage);
+ glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
+ if (expectedError == 0)
+ {
+ EXPECT_GL_NO_ERROR() << explanation << " (texStorage)";
+ }
+ else
+ {
+ EXPECT_GL_ERROR(expectedError) << explanation << " (texStorage)";
+ }
+ }
}
void WebGLCompatibilityTest::testCompressedTexImage(GLenum format)

View File

@@ -0,0 +1,300 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kenneth Russell <kbr@chromium.org>
Date: Wed, 4 Aug 2021 18:15:51 -0700
Subject: In WebGL, constrain base level of compressed textures.
Enforce that if a mipmap level > 0 is specified for a compressed
texture, that it implies that the size of the base level of the
texture is a multiple of the format's block size.
Makes the test changes in
https://github.com/KhronosGroup/WebGL/pull/3304 largely pass. There
are some needed follow-on fixes to that PR, and this CL changes a
sub-test result in the existing S3TC and S3TC-sRGB tests which will
need to be suppressed Chromium-side first.
Bug: angleproject:6245
Change-Id: I7723d7882091b78a353d8d273e80b819dd384021
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3072568
Commit-Queue: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 74acb9e0c4d87c08478dd334a1b38124fab9f94f..4ed0ea4f47c89090d06f706199d32bb0f5b745b9 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -985,6 +985,15 @@ bool ValidCompressedDimension(GLsizei size, GLuint blockSize, GLint level)
return (level > 0) || (size % blockSize == 0);
}
+bool ValidCompressedBaseLevelForWebGL(GLsizei size, GLuint blockSize, GLint level)
+{
+ // Avoid C++ undefined behavior.
+ constexpr int maxValidShifts = 31;
+ if (level > maxValidShifts)
+ return false;
+ return ((size << level) % blockSize) == 0;
+}
+
bool ValidCompressedImageSize(const Context *context,
GLenum internalFormat,
GLint level,
@@ -1005,11 +1014,27 @@ bool ValidCompressedImageSize(const Context *context,
if (CompressedTextureFormatRequiresExactSize(internalFormat))
{
- if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth, level) ||
- !ValidCompressedDimension(height, formatInfo.compressedBlockHeight, level) ||
- !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth, level))
+ // In WebGL compatibility mode, enforce that the base level implied
+ // by the compressed texture's mip level would conform to the block
+ // size. This is more strict than the non-WebGL check.
+ if (context->getExtensions().webglCompatibility)
{
- return false;
+ if (!ValidCompressedBaseLevelForWebGL(width, formatInfo.compressedBlockWidth, level) ||
+ !ValidCompressedBaseLevelForWebGL(height, formatInfo.compressedBlockHeight,
+ level) ||
+ !ValidCompressedBaseLevelForWebGL(depth, formatInfo.compressedBlockDepth, level))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth, level) ||
+ !ValidCompressedDimension(height, formatInfo.compressedBlockHeight, level) ||
+ !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth, level))
+ {
+ return false;
+ }
}
}
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
index bfa8f3066fa418c87477dd553e66a34b79974455..89eb4d639a3853636524ad112a24f15d46fa1119 100644
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
@@ -296,6 +296,16 @@ void main()
GLsizei blockSize,
const std::string &extName,
bool subImageAllowed);
+
+ GLint expectedByteLength(GLenum format, GLsizei width, GLsizei height);
+ void testCompressedTexLevelDimension(GLenum format,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei expectedByteLength,
+ GLenum expectedError,
+ const char *explanation);
+ void testCompressedTexImage(GLenum format);
};
class WebGL2CompatibilityTest : public WebGLCompatibilityTest
@@ -3056,6 +3066,84 @@ TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
}
+// Test WebGL-specific constraints on sizes of S3TC textures' mipmap levels.
+TEST_P(WebGLCompatibilityTest, CompressedTexImageS3TC)
+{
+ const char *extensions[] = {
+ "GL_EXT_texture_compression_dxt1",
+ "GL_ANGLE_texture_compression_dxt3",
+ "GL_ANGLE_texture_compression_dxt5",
+ };
+
+ for (const char *extension : extensions)
+ {
+ if (IsGLExtensionRequestable(extension))
+ {
+ glRequestExtensionANGLE(extension);
+ }
+
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extension));
+ }
+
+ // Ported from WebGL conformance suite:
+ // sdk/tests/conformance/extensions/s3tc-and-srgb.html
+ constexpr GLenum formats[] = {
+ GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ };
+
+ for (GLenum format : formats)
+ {
+ testCompressedTexImage(format);
+ }
+}
+
+// Test WebGL-specific constraints on sizes of RGTC textures' mipmap levels.
+TEST_P(WebGLCompatibilityTest, CompressedTexImageRGTC)
+{
+ if (IsGLExtensionRequestable("GL_EXT_texture_compression_rgtc"))
+ {
+ glRequestExtensionANGLE("GL_EXT_texture_compression_rgtc");
+ }
+
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_rgtc"));
+
+ // Ported from WebGL conformance suite:
+ // sdk/tests/conformance/extensions/ext-texture-compression-rgtc.html
+ constexpr GLenum formats[] = {GL_COMPRESSED_RED_RGTC1_EXT, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT,
+ GL_COMPRESSED_RED_GREEN_RGTC2_EXT,
+ GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT};
+
+ for (GLenum format : formats)
+ {
+ testCompressedTexImage(format);
+ }
+}
+
+// Test WebGL-specific constraints on sizes of BPTC textures' mipmap levels.
+TEST_P(WebGLCompatibilityTest, CompressedTexImageBPTC)
+{
+ if (IsGLExtensionRequestable("GL_EXT_texture_compression_bptc"))
+ {
+ glRequestExtensionANGLE("GL_EXT_texture_compression_bptc");
+ }
+
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
+
+ // Ported from WebGL conformance suite:
+ // sdk/tests/conformance/extensions/ext-texture-compression-bptc.html
+ constexpr GLenum formats[] = {
+ GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT,
+ GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT};
+
+ for (GLenum format : formats)
+ {
+ testCompressedTexImage(format);
+ }
+}
+
TEST_P(WebGLCompatibilityTest, L32FTextures)
{
constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f};
@@ -4887,6 +4975,119 @@ void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum fo
}
}
+GLint WebGLCompatibilityTest::expectedByteLength(GLenum format, GLsizei width, GLsizei height)
+{
+ switch (format)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ return ((width + 3) / 4) * ((height + 3) / 4) * 8;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ return ((width + 3) / 4) * ((height + 3) / 4) * 16;
+ }
+
+ UNREACHABLE();
+ return 0;
+}
+
+void WebGLCompatibilityTest::testCompressedTexLevelDimension(GLenum format,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei expectedByteLength,
+ GLenum expectedError,
+ const char *explanation)
+{
+ std::vector<uint8_t> tempVector(expectedByteLength, 0);
+
+ EXPECT_GL_NO_ERROR();
+
+ GLTexture sourceTexture;
+ glBindTexture(GL_TEXTURE_2D, sourceTexture);
+ glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, expectedByteLength,
+ tempVector.data());
+ if (expectedError == 0)
+ {
+ EXPECT_GL_NO_ERROR() << explanation;
+ }
+ else
+ {
+ EXPECT_GL_ERROR(expectedError) << explanation;
+ }
+}
+
+void WebGLCompatibilityTest::testCompressedTexImage(GLenum format)
+{
+ struct TestCase
+ {
+ GLint level;
+ GLsizei width;
+ GLsizei height;
+ GLenum expectedError;
+ const char *explanation;
+ };
+
+ constexpr TestCase testCases[] = {
+ {0, 4, 3, GL_INVALID_OPERATION, "level is 0, height is not a multiple of 4"},
+ {0, 3, 4, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"},
+ {0, 2, 2, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"},
+ {0, 4, 4, GL_NO_ERROR, "is valid"},
+ {1, 1, 1, GL_INVALID_OPERATION, "implied base mip 2x2 is invalid"},
+ {1, 1, 2, GL_INVALID_OPERATION, "implied base mip 2x4 is invalid"},
+ {1, 2, 1, GL_INVALID_OPERATION, "implied base mip 4x2 is invalid"},
+ {1, 2, 2, GL_NO_ERROR, "implied base mip 4x4 is valid"},
+ };
+
+ constexpr TestCase webgl2TestCases[] = {
+ {0, 0, 0, GL_NO_ERROR, "0: 0x0 is valid"},
+ {0, 1, 1, GL_INVALID_OPERATION, "0: 1x1 is invalid"},
+ {0, 2, 2, GL_INVALID_OPERATION, "0: 2x2 is invalid"},
+ {0, 3, 3, GL_INVALID_OPERATION, "0: 3x3 is invalid"},
+ {0, 10, 10, GL_INVALID_OPERATION, "0: 10x10 is invalid"},
+ {0, 11, 11, GL_INVALID_OPERATION, "0: 11x11 is invalid"},
+ {0, 11, 12, GL_INVALID_OPERATION, "0: 11x12 is invalid"},
+ {0, 12, 11, GL_INVALID_OPERATION, "0: 12x11 is invalid"},
+ {0, 12, 12, GL_NO_ERROR, "0: 12x12 is valid"},
+ {1, 0, 0, GL_NO_ERROR, "1: 0x0 is valid"},
+ {1, 3, 3, GL_INVALID_OPERATION, "1: 3x3 is invalid"},
+ {1, 5, 5, GL_INVALID_OPERATION, "1: 5x5 is invalid"},
+ {1, 5, 6, GL_INVALID_OPERATION, "1: 5x6 is invalid"},
+ {1, 6, 5, GL_INVALID_OPERATION, "1: 6x5 is invalid"},
+ {1, 6, 6, GL_NO_ERROR, "1: 6x6 is valid"},
+ {2, 0, 0, GL_NO_ERROR, "2: 0x0 is valid"},
+ {2, 3, 3, GL_NO_ERROR, "2: 3x3 is valid"},
+ {3, 1, 3, GL_NO_ERROR, "3: 1x3 is valid"},
+ {3, 1, 1, GL_NO_ERROR, "3: 1x1 is valid"},
+ {2, 1, 3, GL_NO_ERROR, "implied base mip 4x12 is valid"},
+ };
+
+ for (const TestCase &test : testCases)
+ {
+ testCompressedTexLevelDimension(format, test.level, test.width, test.height,
+ expectedByteLength(format, test.width, test.height),
+ test.expectedError, test.explanation);
+ }
+
+ if (getClientMajorVersion() >= 3)
+ {
+ for (const TestCase &test : webgl2TestCases)
+ {
+ testCompressedTexLevelDimension(format, test.level, test.width, test.height,
+ expectedByteLength(format, test.width, test.height),
+ test.expectedError, test.explanation);
+ }
+ }
+}
+
// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT
TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB)
{

View File

@@ -138,3 +138,12 @@ cherry-pick-910e9e40d376.patch
cherry-pick-d9556a80a790.patch
cherry-pick-ee6aee64e24c.patch
webview_fullscreen.patch
set_svgimage_page_after_document_install.patch
cherry-pick-e60cc80ff744.patch
cherry-pick-3feda0244490.patch
cherry-pick-cd98d7c0dae9.patch
replace_first_of_two_waitableevents_in_creditcardaccessmanager.patch
cherry-pick-ac9dc1235e28.patch
cherry-pick-4ce2abc17078.patch
cherry-pick-e2123a8e0943.patch
cherry-pick-1227933.patch

View File

@@ -0,0 +1,215 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Koji Ishii <kojii@chromium.org>
Date: Mon, 26 Jul 2021 07:09:18 +0000
Subject: Fix nested inline box fragmentation
This patch fixes when nested inline boxes are fragmented in a
line due to bidi reordering.
Before this change, the fragmented boxes are appended to the
end of |box_data_list_|. Then when |NGInlineLayoutStateStack::
CreateBoxFragments| creates inline boxes in the ascending
order of |box_data_list_|, it failed to add the fragmented
boxes into their parent inline boxes.
This is critical for out-of-flow positioned objects whose
containing block is an inline box, because they expect to be
propagated through all ancestor inline boxes.
|UpdateBoxDataFragmentRange| is a little tricky by appending
to a vector it is iterating. Changing it to insert to the
correct position makes the function even trickier. This patch
changes it to add fragmented boxes to a separate vector, and
let later process |UpdateFragmentedBoxDataEdges| to merge the
vector to |box_data_list_|.
(cherry picked from commit 9c8a39c14a9c80556468593cddf436f5047a16ce)
Bug: 1227933, 1229999
Change-Id: I7edcd209e1fdac06bab01b16d660383e7e9c37bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3038308
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#903356}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3053212
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Auto-Submit: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/branch-heads/4577@{#145}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
index b257014513cb881d4531694b86c05fd21edb6732..9a3f6f3af7839ebed24f7d8a32b7f95fba66cd9a 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h"
+#include "base/containers/adapters.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
@@ -387,13 +388,14 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
box_data.fragment_start = box_data.fragment_end = 0;
// Scan children and update start/end from their box_data_index.
- unsigned box_count = box_data_list_.size();
+ Vector<BoxData> fragmented_boxes;
for (unsigned index = 0; index < line_box->size();)
- index = UpdateBoxDataFragmentRange(line_box, index);
+ index = UpdateBoxDataFragmentRange(line_box, index, &fragmented_boxes);
- // If any inline fragmentation due to BiDi reorder, adjust box edges.
- if (box_count != box_data_list_.size())
- UpdateFragmentedBoxDataEdges();
+ // If any inline fragmentation occurred due to BiDi reorder, append them and
+ // adjust box edges.
+ if (UNLIKELY(!fragmented_boxes.IsEmpty()))
+ UpdateFragmentedBoxDataEdges(&fragmented_boxes);
#if DCHECK_IS_ON()
// Check all BoxData have ranges.
@@ -410,7 +412,8 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
NGLogicalLineItems* line_box,
- unsigned index) {
+ unsigned index,
+ Vector<BoxData>* fragmented_boxes) {
// Find the first line box item that should create a box fragment.
for (; index < line_box->size(); index++) {
NGLogicalLineItem* start = &(*line_box)[index];
@@ -438,7 +441,7 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
// It also changes other BoxData, but not the one we're dealing with here
// because the update is limited only when its |box_data_index| is lower.
while (end->box_data_index && end->box_data_index < box_data_index) {
- UpdateBoxDataFragmentRange(line_box, index);
+ UpdateBoxDataFragmentRange(line_box, index, fragmented_boxes);
}
if (box_data_index != end->box_data_index)
@@ -453,14 +456,9 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
} else {
// This box is fragmented by BiDi reordering. Add a new BoxData for the
// fragmented range.
- box_data_list_[box_data_index - 1].fragmented_box_data_index =
- box_data_list_.size();
- // Do not use `emplace_back()` here because adding to |box_data_list_| may
- // reallocate the buffer, but the `BoxData` ctor must run before the
- // reallocation. Create a new instance and |push_back()| instead.
- BoxData fragmented_box_data(box_data_list_[box_data_index - 1],
- start_index, index);
- box_data_list_.push_back(fragmented_box_data);
+ BoxData& fragmented_box = fragmented_boxes->emplace_back(
+ box_data_list_[box_data_index - 1], start_index, index);
+ fragmented_box.fragmented_box_data_index = box_data_index;
}
// If this box has parent boxes, we need to process it again.
if (box_data_list_[box_data_index - 1].parent_box_data_index)
@@ -470,7 +468,43 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
return index;
}
-void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges() {
+void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges(
+ Vector<BoxData>* fragmented_boxes) {
+ DCHECK(!fragmented_boxes->IsEmpty());
+ // Append in the descending order of |fragmented_box_data_index| because the
+ // indices will change as boxes are inserted into |box_data_list_|.
+ std::sort(fragmented_boxes->begin(), fragmented_boxes->end(),
+ [](const BoxData& a, const BoxData& b) {
+ if (a.fragmented_box_data_index != b.fragmented_box_data_index) {
+ return a.fragmented_box_data_index <
+ b.fragmented_box_data_index;
+ }
+ DCHECK_NE(a.fragment_start, b.fragment_start);
+ return a.fragment_start < b.fragment_start;
+ });
+ for (BoxData& fragmented_box : base::Reversed(*fragmented_boxes)) {
+ // Insert the fragmented box to right after the box it was fragmented from.
+ // The order in the |box_data_list_| is critical when propagating child
+ // fragment data such as OOF to ancestors.
+ const unsigned insert_at = fragmented_box.fragmented_box_data_index;
+ DCHECK_GT(insert_at, 0u);
+ fragmented_box.fragmented_box_data_index = 0;
+ box_data_list_.insert(insert_at, fragmented_box);
+
+ // Adjust box data indices by the insertion.
+ for (BoxData& box_data : box_data_list_) {
+ if (box_data.fragmented_box_data_index >= insert_at)
+ ++box_data.fragmented_box_data_index;
+ }
+
+ // Set the index of the last fragment to the original box. This is needed to
+ // update fragment edges.
+ const unsigned fragmented_from = insert_at - 1;
+ if (!box_data_list_[fragmented_from].fragmented_box_data_index)
+ box_data_list_[fragmented_from].fragmented_box_data_index = insert_at;
+ }
+
+ // Move the line-right edge to the last fragment.
for (BoxData& box_data : box_data_list_) {
if (box_data.fragmented_box_data_index)
box_data.UpdateFragmentEdges(box_data_list_);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
index 82ecfef8fe4d404d5713f0f67d83b38ecfbfca4c..9d079266efd7f2ccc43cef40d8d89e4fc6edda9e 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
@@ -156,17 +156,6 @@ class CORE_EXPORT NGInlineLayoutStateStack {
// reordering.
void UpdateAfterReorder(NGLogicalLineItems*);
- // Update start/end of the first BoxData found at |index|.
- //
- // If inline fragmentation is found, a new BoxData is added.
- //
- // Returns the index to process next. It should be given to the next call to
- // this function.
- unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*, unsigned index);
-
- // Update edges of inline fragmented boxes.
- void UpdateFragmentedBoxDataEdges();
-
// Compute inline positions of fragments and boxes.
LayoutUnit ComputeInlinePositions(NGLogicalLineItems*, LayoutUnit position);
@@ -259,6 +248,19 @@ class CORE_EXPORT NGInlineLayoutStateStack {
scoped_refptr<const NGLayoutResult> CreateBoxFragment(NGLogicalLineItems*);
};
+ // Update start/end of the first BoxData found at |index|.
+ //
+ // If inline fragmentation is found, a new BoxData is added.
+ //
+ // Returns the index to process next. It should be given to the next call to
+ // this function.
+ unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*,
+ unsigned index,
+ Vector<BoxData>* fragmented_boxes);
+
+ // Update edges of inline fragmented boxes.
+ void UpdateFragmentedBoxDataEdges(Vector<BoxData>* fragmented_boxes);
+
Vector<NGInlineBoxState, 4> stack_;
Vector<BoxData, 4> box_data_list_;
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
new file mode 100644
index 0000000000000000000000000000000000000000..b701d2b5688ace54aa99530c12fa8143f1e6a508
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<link rel="author" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://crbug.com/1229999">
+<div style="direction:rtl; width:500px">
+ <span style="border:solid">
+ <span style="position:relative">
+ <div style="display:inline-block; width:1000%; height:10px"></div>
+ <span dir="ltr">
+ <div style="position:absolute"></div>
+ </span>
+ </span>
+ </span>
+</div>

View File

@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Reilly Grant <reillyg@chromium.org>
Date: Mon, 28 Jun 2021 21:55:24 +0000
Subject: serial: Fix parent class tracing for SerialPort
When SerialPort was updated to be ActiveScriptWrappable and an
EventTarget the Trace method was not updated to call the parent class
trace methods.
(cherry picked from commit 4059ecc3a5352601a4d79196f90c8ca19262afe1)
Bug: 1220078
Change-Id: If6967a913268bce86d4488359a9418a814530f84
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2965255
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#893039}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2992740
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/branch-heads/4472@{#1531}
Cr-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
diff --git a/third_party/blink/renderer/modules/serial/serial_port.cc b/third_party/blink/renderer/modules/serial/serial_port.cc
index b485935f6cfd1b397d86acb90ebf344e22e18a2c..835ac5f3526d1a933f81e3546344aa409a5eec09 100644
--- a/third_party/blink/renderer/modules/serial/serial_port.cc
+++ b/third_party/blink/renderer/modules/serial/serial_port.cc
@@ -508,7 +508,8 @@ void SerialPort::Trace(Visitor* visitor) const {
visitor->Trace(open_resolver_);
visitor->Trace(signal_resolvers_);
visitor->Trace(close_resolver_);
- ScriptWrappable::Trace(visitor);
+ EventTargetWithInlineData::Trace(visitor);
+ ActiveScriptWrappable<SerialPort>::Trace(visitor);
}
bool SerialPort::HasPendingActivity() const {

View File

@@ -0,0 +1,135 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Flack <flackr@chromium.org>
Date: Fri, 30 Jul 2021 18:51:38 +0000
Subject: Forbid script execution for entire lifecycle update
We should not execute script during the lifecycle update except in cases where we we know it is safe to do so, either because we will rerun the lifecycle steps if anything is invalidated (resize observers, intersection observers) or because the script does not have access to invalidate the DOM (e.g. paint worklets).
(cherry picked from commit a73237da91de8aa49aaa5d9479bae51cf387f090)
Bug: 1196853
Change-Id: Id1fdbbb25107cfdc6c234123f845406c28d32914
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2815619
Reviewed-by: Stefan Zager <szager@chromium.org>
Commit-Queue: Robert Flack <flackr@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#901110}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3058973
Auto-Submit: Robert Flack <flackr@chromium.org>
Commit-Queue: Stefan Zager <szager@chromium.org>
Cr-Commit-Position: refs/branch-heads/4472@{#1588}
Cr-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
index d3512edd4cad7b7dafbb1c3a6da5cd45ea367e79..69f8e8a598a4aefef652e603f1590c702e288b59 100644
--- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -96,6 +96,7 @@
#include "third_party/blink/renderer/core/script/classic_script.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
@@ -804,6 +805,8 @@ void WebPluginContainerImpl::Dispose() {
}
if (web_plugin_) {
+ // Plugins may execute script on being detached during the lifecycle update.
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
CHECK(web_plugin_->Container() == this);
web_plugin_->Destroy();
web_plugin_ = nullptr;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index dd320dd900b7f556c9216c7faedc2ad35588b0d7..a9e724432440c05d1b3bb9863acb4345e07f77b4 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2484,6 +2484,7 @@ bool LocalFrameView::UpdateLifecyclePhases(
void LocalFrameView::UpdateLifecyclePhasesInternal(
DocumentLifecycle::LifecycleState target_state) {
+ ScriptForbiddenScope forbid_script;
// RunScrollTimelineSteps must not run more than once.
bool should_run_scroll_timeline_steps = true;
@@ -2564,6 +2565,10 @@ void LocalFrameView::UpdateLifecyclePhasesInternal(
continue;
}
+ // At this point in time, script is allowed to run as we will repeat the
+ // lifecycle update if anything is invalidated.
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
+
// ResizeObserver and post-layout IntersectionObserver observation
// deliveries may dirty style and layout. RunResizeObserverSteps will return
// true if any observer ran that may have dirtied style or layout;
@@ -2816,6 +2821,7 @@ bool LocalFrameView::AnyFrameIsPrintingOrPaintingPreview() {
}
void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
+ DCHECK(ScriptForbiddenScope::IsScriptForbidden());
TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase");
// While printing or capturing a paint preview of a document, the paint walk
// is done into a special canvas. There is no point doing a normal paint step
@@ -2850,17 +2856,11 @@ void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
for (PaintLayerScrollableArea* area : *animating_scrollable_areas)
area->UpdateCompositorScrollAnimations();
}
- {
- // Updating animations can notify ready promises which could mutate
- // the DOM. We should delay these until we have finished the lifecycle
- // update. https://crbug.com/1196781
- ScriptForbiddenScope forbid_script;
- frame_view.GetLayoutView()
- ->GetDocument()
- .GetDocumentAnimations()
- .UpdateAnimations(DocumentLifecycle::kPaintClean,
- paint_artifact_compositor_.get());
- }
+ frame_view.GetLayoutView()
+ ->GetDocument()
+ .GetDocumentAnimations()
+ .UpdateAnimations(DocumentLifecycle::kPaintClean,
+ paint_artifact_compositor_.get());
Document& document = frame_view.GetLayoutView()->GetDocument();
total_animations_count +=
document.GetDocumentAnimations().GetAnimationsCount();
@@ -4454,6 +4454,7 @@ void LocalFrameView::RenderThrottlingStatusChanged() {
// so painting the tree should just clear the previous painted output.
DCHECK(!IsUpdatingLifecycle());
AllowThrottlingScope allow_throtting(*this);
+ ScriptForbiddenScope forbid_script;
RunPaintLifecyclePhase();
}
@@ -4989,6 +4990,7 @@ void LocalFrameView::RunPaintBenchmark(int repeat_count,
// quantization when the time is very small.
base::LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval);
do {
+ ScriptForbiddenScope forbid_script;
RunPaintLifecyclePhase(mode);
timer.NextLap();
} while (!timer.HasTimeLimitExpired());
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
index e6e0c5b909c4d073963bcbb074bfb091a6ccb83b..618e08fbb5157c06348feee5f0120bd28ed0bc44 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h"
+#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/graphics/paint_generated_image.h"
namespace blink {
@@ -126,6 +127,10 @@ scoped_refptr<Image> PaintWorklet::Paint(const String& name,
layout_object.GetDocument(), layout_object.StyleRef(),
paint_definition->NativeInvalidationProperties(),
paint_definition->CustomInvalidationProperties());
+ // The PaintWorkletGlobalScope is sufficiently isolated that it is safe to
+ // run during the lifecycle update without concern for it causing
+ // invalidations to the lifecycle.
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
sk_sp<PaintRecord> paint_record = paint_definition->Paint(
container_size, zoom, style_map, data, device_scale_factor);
if (!paint_record)

View File

@@ -0,0 +1,103 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ilya Nikolaevskiy <ilnik@chromium.org>
Date: Mon, 17 May 2021 08:34:41 +0000
Subject: Add locks and empty string checks to FakeV4L2Impl
FakeV4L2Impl is crashed by fuzzer with some weird ASAN errors, which
turned out to be a threading issue.
Bug: 1205059,1196302
Change-Id: Ieb3a917c9a4549b655862e69214774e183a70bc3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2883613
Reviewed-by: Ricky Liang <jcliang@chromium.org>
Commit-Queue: Ilya Nikolaevskiy <ilnik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#883390}
diff --git a/media/capture/video/linux/fake_v4l2_impl.cc b/media/capture/video/linux/fake_v4l2_impl.cc
index 4a976815d009e68b3740aa71e8c8fd641bf91493..09647474bed3c7c7b34cd9fb161edd2a7d2e170f 100644
--- a/media/capture/video/linux/fake_v4l2_impl.cc
+++ b/media/capture/video/linux/fake_v4l2_impl.cc
@@ -380,10 +380,16 @@ FakeV4L2Impl::~FakeV4L2Impl() = default;
void FakeV4L2Impl::AddDevice(const std::string& device_name,
const FakeV4L2DeviceConfig& config) {
+ base::AutoLock lock(lock_);
device_configs_.emplace(device_name, config);
}
int FakeV4L2Impl::open(const char* device_name, int flags) {
+ if (!device_name)
+ return kInvalidId;
+
+ base::AutoLock lock(lock_);
+
std::string device_name_as_string(device_name);
auto device_configs_iter = device_configs_.find(device_name_as_string);
if (device_configs_iter == device_configs_.end())
@@ -403,6 +409,7 @@ int FakeV4L2Impl::open(const char* device_name, int flags) {
}
int FakeV4L2Impl::close(int fd) {
+ base::AutoLock lock(lock_);
auto device_iter = opened_devices_.find(fd);
if (device_iter == opened_devices_.end())
return kErrorReturnValue;
@@ -412,6 +419,7 @@ int FakeV4L2Impl::close(int fd) {
}
int FakeV4L2Impl::ioctl(int fd, int request, void* argp) {
+ base::AutoLock lock(lock_);
auto device_iter = opened_devices_.find(fd);
if (device_iter == opened_devices_.end())
return EBADF;
@@ -518,6 +526,7 @@ void* FakeV4L2Impl::mmap(void* /*start*/,
int flags,
int fd,
off_t offset) {
+ base::AutoLock lock(lock_);
if (flags & MAP_FIXED) {
errno = EINVAL;
return MAP_FAILED;
@@ -543,10 +552,12 @@ void* FakeV4L2Impl::mmap(void* /*start*/,
}
int FakeV4L2Impl::munmap(void* start, size_t length) {
+ base::AutoLock lock(lock_);
return kSuccessReturnValue;
}
int FakeV4L2Impl::poll(struct pollfd* ufds, unsigned int nfds, int timeout) {
+ base::AutoLock lock(lock_);
if (nfds != 1) {
// We only support polling of a single device.
errno = EINVAL;
diff --git a/media/capture/video/linux/fake_v4l2_impl.h b/media/capture/video/linux/fake_v4l2_impl.h
index 0a035a97dd8761b08eb4cfdbe2865efc346f0e23..ae7167f95163581c756ab4951717fd4352c67757 100644
--- a/media/capture/video/linux/fake_v4l2_impl.h
+++ b/media/capture/video/linux/fake_v4l2_impl.h
@@ -10,6 +10,7 @@
#include <linux/videodev2.h>
+#include "base/synchronization/lock.h"
#include "media/capture/capture_export.h"
#include "media/capture/video/linux/v4l2_capture_device.h"
#include "media/capture/video/video_capture_device_descriptor.h"
@@ -52,11 +53,13 @@ class CAPTURE_EXPORT FakeV4L2Impl : public V4L2CaptureDevice {
private:
class OpenedDevice;
- int next_id_to_return_from_open_;
- std::map<std::string, FakeV4L2DeviceConfig> device_configs_;
- std::map<std::string, int> device_name_to_open_id_map_;
+ base::Lock lock_;
+
+ int next_id_to_return_from_open_ GUARDED_BY(lock_);
+ std::map<std::string, FakeV4L2DeviceConfig> device_configs_ GUARDED_BY(lock_);
+ std::map<std::string, int> device_name_to_open_id_map_ GUARDED_BY(lock_);
std::map<int /*value returned by open()*/, std::unique_ptr<OpenedDevice>>
- opened_devices_;
+ opened_devices_ GUARDED_BY(lock_);
};
} // namespace media

View File

@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peng Huang <penghuang@chromium.org>
Date: Wed, 7 Jul 2021 20:50:53 +0000
Subject: Fix UAF problem in SharedImageInterfaceInProcess
(cherry picked from commit 38b4905f8d877b27bc2d4ccd4cfc0f82b636deea)
Bug: 1216822
Change-Id: I8ae1f7c406e1899e500ee7ddeaaf18230b1cbcb2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2971144
Commit-Queue: Peng Huang <penghuang@chromium.org>
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
Auto-Submit: Peng Huang <penghuang@chromium.org>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#893931}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3011895
Auto-Submit: Mason Freed <masonf@chromium.org>
Reviewed-by: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/branch-heads/4515@{#1369}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/gpu/ipc/shared_image_interface_in_process.cc b/gpu/ipc/shared_image_interface_in_process.cc
index 54f9777201827e4bca5221af373e39dc021ac6a4..53c2dc489c50367986c46a34e8aaf48b68888ec7 100644
--- a/gpu/ipc/shared_image_interface_in_process.cc
+++ b/gpu/ipc/shared_image_interface_in_process.cc
@@ -86,6 +86,8 @@ void SharedImageInterfaceInProcess::DestroyOnGpu(
sync_point_client_state_->Destroy();
sync_point_client_state_ = nullptr;
}
+
+ context_state_ = nullptr;
completion->Signal();
}
diff --git a/gpu/ipc/shared_image_interface_in_process.h b/gpu/ipc/shared_image_interface_in_process.h
index 8d74513f041564a416c20cab5616c9453555c547..c169b5a86af3e02ec869aae9cf1bfb150fa2ad69 100644
--- a/gpu/ipc/shared_image_interface_in_process.h
+++ b/gpu/ipc/shared_image_interface_in_process.h
@@ -229,10 +229,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT SharedImageInterfaceInProcess
// Accessed on GPU thread.
// TODO(weiliangc): Check whether can be removed when !UsesSync().
MailboxManager* mailbox_manager_;
- // Used to check if context is lost at destruction time.
- // TODO(weiliangc): SharedImageInterface should become active observer of
- // whether context is lost.
- SharedContextState* context_state_;
+ scoped_refptr<SharedContextState> context_state_;
// Created and only used by this SharedImageInterface.
SyncPointManager* sync_point_manager_;
scoped_refptr<SyncPointClientState> sync_point_client_state_;

View File

@@ -0,0 +1,64 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tal Pressman <talp@chromium.org>
Date: Wed, 21 Jul 2021 09:11:13 +0000
Subject: Manually post task to bind FileUtilitiesHost.
The FileUtilitiesHost binder is posted to a separate sequence, and the
ServiceWorkerHost may be destroyed by the time the it runs, causing a
UAF.
This CL changes it so that, when we try to bind a new receiver, the
host's worker_process_id() is obtained first (on the service worker's
core thread) and then a task is posted to do the actual binding on a
USER_VISIBLE task runner.
Credit: This issue was first reported (with analysis) by
soulchen8650@gmail.com.
Bug: 1229298
Change-Id: I6d5c05a830ba30f6cb98bf2df70a3df3333f3dd9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3041006
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
Commit-Queue: Tal Pressman <talp@google.com>
Cr-Commit-Position: refs/heads/master@{#903832}
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index a45f9d3db09dbc4827c41c254b2b532968930e96..b6f69c1813fc9c66cc6a20205c02cb6e5d810fc5 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -367,10 +367,22 @@ void BindTextSuggestionHostForFrame(
}
#endif
+// Get the service worker's worker process ID and post a task to bind the
+// receiver on a USER_VISIBLE task runner.
+// This is necessary because:
+// - Binding the host itself and checking the ID on the task's thread may cause
+// a UAF if the host has been deleted in the meantime.
+// - The process ID is not yet populated at the time `PopulateInterfaceBinders`
+// is called.
void BindFileUtilitiesHost(
- const ServiceWorkerHost* host,
+ ServiceWorkerHost* host,
mojo::PendingReceiver<blink::mojom::FileUtilitiesHost> receiver) {
- FileUtilitiesHostImpl::Create(host->worker_process_id(), std::move(receiver));
+ auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FileUtilitiesHostImpl::Create, host->worker_process_id(),
+ std::move(receiver)));
}
template <typename WorkerHost, typename Interface>
@@ -1122,9 +1134,7 @@ void PopulateServiceWorkerBinders(ServiceWorkerHost* host,
// static binders
map->Add<blink::mojom::FileUtilitiesHost>(
- base::BindRepeating(&BindFileUtilitiesHost, host),
- base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE}));
+ base::BindRepeating(&BindFileUtilitiesHost, host));
map->Add<shape_detection::mojom::BarcodeDetectionProvider>(
base::BindRepeating(&BindBarcodeDetectionProvider));
map->Add<shape_detection::mojom::FaceDetectionProvider>(

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shrek Shao <shrekshao@google.com>
Date: Tue, 29 Jun 2021 01:17:03 +0000
Subject: Fix multidraw validation drawcount + offset out of bounds
(cherry picked from commit 7d0a12ce19fed024d56b95a692d888fe3ef14e2f)
Bug: 1219886
Change-Id: I8a84664150758370d9a77ee22ac5549bead0e37e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2977850
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Kenneth Russell <kbr@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#895423}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2988885
Reviewed-by: Shrek Shao <shrekshao@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Cr-Commit-Position: refs/branch-heads/4515@{#1101}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
index 91de853db2b382a7797d22cf741a84f463a2d5f2..c3cae01c63046ce4b8be2c0b03243e9105ed4f23 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
@@ -34,6 +34,11 @@ bool WebGLMultiDrawCommon::ValidateArray(WebGLExtensionScopedContext* scoped,
outOfBoundsDescription);
return false;
}
+ if (static_cast<uint64_t>(drawcount) + offset > size) {
+ scoped->Context()->SynthesizeGLError(GL_INVALID_OPERATION, function_name,
+ "drawcount plus offset out of bounds");
+ return false;
+ }
return true;
}

View File

@@ -0,0 +1,574 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominic Battre <battre@chromium.org>
Date: Wed, 7 Jul 2021 20:02:45 +0000
Subject: Replace first of two WaitableEvents in CreditCardAccessManager
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
(cherry picked from commit 48cf01e4039fecbe119d8223d1f6072aaf44f258)
Bug: 1214234
Change-Id: I38171be7b38982f25abfbb3dff7a41f19a167764
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3001123
Reviewed-by: Jared Saul <jsaul@google.com>
Commit-Queue: Dominic Battré <battre@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#898237}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3011066
Reviewed-by: Dominic Battré <battre@chromium.org>
Reviewed-by: Prudhvi Kumar Bommana <pbommana@google.com>
Owners-Override: Prudhvi Kumar Bommana <pbommana@google.com>
Cr-Commit-Position: refs/branch-heads/4515@{#1366}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 5031372d31e25f8f14905ab1be721c4aaefed7c5..d6254700a20445078cc4c4fa0e821cd2fc3b1a7b 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -237,6 +237,8 @@ static_library("browser") {
"payments/payments_util.cc",
"payments/payments_util.h",
"payments/risk_data_loader.h",
+ "payments/wait_for_signal_or_timeout.cc",
+ "payments/wait_for_signal_or_timeout.h",
"payments/strike_database.cc",
"payments/strike_database.h",
"payments/strike_database_integrator_base.cc",
@@ -680,6 +682,7 @@ source_set("unit_tests") {
"payments/payments_client_unittest.cc",
"payments/payments_service_url_unittest.cc",
"payments/payments_util_unittest.cc",
+ "payments/wait_for_signal_or_timeout_unittest.cc",
"payments/strike_database_integrator_test_strike_database_unittest.cc",
"payments/strike_database_unittest.cc",
"personal_data_manager_unittest.cc",
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc
index 560f30b57c88049842390095ca53eb2e4302bf63..7cab68d4cc6696329dd4739f51e809aa7877cb53 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -18,7 +18,6 @@
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
-#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_client.h"
@@ -46,12 +45,6 @@ constexpr int64_t kUnmaskDetailsResponseTimeoutMs = 3 * 1000; // 3 sec
// Time to wait between multiple calls to GetUnmaskDetails().
constexpr int64_t kDelayForGetUnmaskDetails = 3 * 60 * 1000; // 3 min
-// Used for asynchronously waiting for |event| to be signaled.
-bool WaitForEvent(base::WaitableEvent* event) {
- event->declare_only_used_while_idle();
- return event->TimedWait(
- base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeoutMs));
-}
} // namespace
CreditCardAccessManager::CreditCardAccessManager(
@@ -64,9 +57,6 @@ CreditCardAccessManager::CreditCardAccessManager(
payments_client_(client_->GetPaymentsClient()),
personal_data_manager_(personal_data_manager),
form_event_logger_(form_event_logger),
- ready_to_start_authentication_(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
can_fetch_unmask_details_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::SIGNALED) {
}
@@ -329,12 +319,10 @@ void CreditCardAccessManager::FetchCreditCard(
// Wait for |ready_to_start_authentication_| to be signaled by
// OnDidGetUnmaskDetails() or until timeout before calling Authenticate().
- auto task_runner = base::ThreadPool::CreateTaskRunner({base::MayBlock()});
- cancelable_authenticate_task_tracker_.PostTaskAndReplyWithResult(
- task_runner.get(), FROM_HERE,
- base::BindOnce(&WaitForEvent, &ready_to_start_authentication_),
+ ready_to_start_authentication_.OnEventOrTimeOut(
base::BindOnce(&CreditCardAccessManager::Authenticate,
- weak_ptr_factory_.GetWeakPtr()));
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeoutMs));
} else {
Authenticate(get_unmask_details_returned);
}
@@ -699,7 +687,6 @@ void CreditCardAccessManager::HandleDialogUserResponse(
case WebauthnDialogCallbackType::kVerificationCancelled:
// TODO(crbug.com/949269): Add tests and logging for canceling verify
// pending dialog.
- cancelable_authenticate_task_tracker_.TryCancelAll();
payments_client_->CancelRequest();
SignalCanFetchUnmaskDetails();
ready_to_start_authentication_.Reset();
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h
index 6bdf8b8c647f885aad5784f737e117b3a55bd2be..99f6581b7320312776f52383b8e8e3b7845268a8 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.h
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -22,6 +22,7 @@
#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
#include "components/autofill/core/browser/payments/credit_card_cvc_authenticator.h"
#include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/payments/wait_for_signal_or_timeout.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#if !defined(OS_IOS)
@@ -295,11 +296,7 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// Resets when PrepareToFetchCreditCard() is called, if not already reset.
// Signaled when OnDidGetUnmaskDetails() is called or after timeout.
// Authenticate() is called when signaled.
- base::WaitableEvent ready_to_start_authentication_;
-
- // Tracks the Authenticate() task that is signaled by
- // |ready_to_start_authentication_|, allowing it to be canceled if necessary.
- base::CancelableTaskTracker cancelable_authenticate_task_tracker_;
+ WaitForSignalOrTimeout ready_to_start_authentication_;
// Required to avoid any unnecessary preflight calls to Payments servers.
// Initial state is signaled. Resets when PrepareToFetchCreditCard() is
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
index faa396e337d60167d759f9a616f4a901ac5b9db6..39507d6f45e318d632d73583ebaf9048120ae15a 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -139,8 +139,23 @@ class CreditCardAccessManagerTest : public testing::Test {
public:
CreditCardAccessManagerTest()
: task_environment_(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME,
base::test::TaskEnvironment::MainThreadType::DEFAULT,
- base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {
+ // Advance the mock clock to 2021-01-01, 00:00:00.000.
+ base::Time year_2021;
+ CHECK(base::Time::FromUTCExploded({.year = 2021,
+ .month = 1,
+ .day_of_week = 4,
+ .day_of_month = 1,
+ .hour = 0,
+ .minute = 0,
+ .second = 0,
+ .millisecond = 0},
+ &year_2021));
+ task_environment_.AdvanceClock(year_2021 -
+ task_environment_.GetMockClock()->Now());
+ }
void SetUp() override {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
@@ -930,6 +945,7 @@ TEST_F(CreditCardAccessManagerTest,
ResetFetchCreditCard();
credit_card_access_manager_->PrepareToFetchCreditCard();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
credit_card_access_manager_->FetchCreditCard(local_card,
@@ -950,6 +966,7 @@ TEST_F(CreditCardAccessManagerTest,
credit_card_access_manager_->PrepareToFetchCreditCard();
credit_card_access_manager_->FetchCreditCard(server_card,
accessor_->GetWeakPtr());
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
@@ -1023,6 +1040,8 @@ TEST_F(CreditCardAccessManagerTest, Metrics_LoggingTimedOutCvcFallback) {
// Mock a delayed response.
InvokeDelayedGetUnmaskDetailsResponse();
+
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
@@ -1044,6 +1063,7 @@ TEST_F(CreditCardAccessManagerTest, Metrics_LoggingTimedOutCvcFallback) {
credit_card_access_manager_->PrepareToFetchCreditCard();
credit_card_access_manager_->FetchCreditCard(server_card,
accessor_->GetWeakPtr());
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
diff --git a/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc
new file mode 100644
index 0000000000000000000000000000000000000000..713a53e0f006e51f5d9bd64466712bf75b3ba095
--- /dev/null
+++ b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc
@@ -0,0 +1,78 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/payments/wait_for_signal_or_timeout.h"
+
+#include "base/threading/sequenced_task_runner_handle.h"
+
+WaitForSignalOrTimeout::WaitForSignalOrTimeout() = default;
+WaitForSignalOrTimeout::~WaitForSignalOrTimeout() = default;
+
+void WaitForSignalOrTimeout::Signal() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ SignalHandler(/*triggered_by_signal=*/true);
+}
+
+bool WaitForSignalOrTimeout::IsSignaled() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ return state_ == State::kSignalReceived || state_ == State::kDone;
+}
+
+void WaitForSignalOrTimeout::OnEventOrTimeOut(Callback callback,
+ base::TimeDelta timeout) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ switch (state_) {
+ case State::kInitialState:
+ callback_ = std::move(callback);
+ ++generation_id_; // Invalidate previous OnTimeOut tasks.
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&WaitForSignalOrTimeout::OnTimeOut,
+ weak_factory_.GetWeakPtr(), generation_id_),
+ timeout);
+ break;
+
+ case State::kSignalReceived:
+ state_ = State::kDone;
+ std::move(callback).Run(
+ /*triggered_by_signal=*/in_state_signal_received_due_to_signal_call_);
+ break;
+
+ case State::kDone:
+ Reset();
+ OnEventOrTimeOut(std::move(callback), timeout);
+ break;
+ }
+}
+
+void WaitForSignalOrTimeout::Reset() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ state_ = State::kInitialState;
+ ++generation_id_;
+ callback_ = Callback();
+}
+
+void WaitForSignalOrTimeout::OnTimeOut(int generation_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ if (generation_id == generation_id_)
+ SignalHandler(/*triggered_by_signal=*/false);
+}
+
+void WaitForSignalOrTimeout::SignalHandler(bool triggered_by_signal) {
+ switch (state_) {
+ case State::kInitialState:
+ if (callback_.is_null()) {
+ state_ = State::kSignalReceived;
+ in_state_signal_received_due_to_signal_call_ = triggered_by_signal;
+ } else {
+ state_ = State::kDone;
+ std::move(callback_).Run(triggered_by_signal);
+ }
+ break;
+
+ case State::kSignalReceived:
+ case State::kDone:
+ break;
+ }
+}
diff --git a/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b2c451245441f784938e4132e2ab03e7d85f9b6
--- /dev/null
+++ b/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+
+// A WaitForSignalOrTimeout waits for Signal() or a time out and calls a
+// callback when either of these happens for the first time.
+//
+// The WaitForSignalOrTimeout is Reset()-able and ensures that the callback will
+// be called at most once (unless Reset() resets the state). The
+// WaitForSignalOrTimeout can be destroyed at any time without negative
+// side-effects. The callback won't be called in this case. If the Signal()
+// arrives before a call for OnEventOrTimeOut(), the callback will be called
+// immediately. If a second Signal() arrives, nothing happens. The
+// WaitForSignalOrTimeout must be used on single task sequence.
+//
+// This class provides the bare minimum needed for a Payment task. If there are
+// more use cases, feel free to spice it up and move it to base/.
+class WaitForSignalOrTimeout {
+ public:
+ // The passed boolean is true if the callback happened by a call of Signal()
+ // (as opposed to a timeout).
+ using Callback = base::OnceCallback<void(bool)>;
+
+ WaitForSignalOrTimeout();
+ ~WaitForSignalOrTimeout();
+ WaitForSignalOrTimeout(const WaitForSignalOrTimeout&) = delete;
+ WaitForSignalOrTimeout& operator=(const WaitForSignalOrTimeout&) = delete;
+
+ // Triggers |callback_| if it has not been called before, or registers that
+ // the signal occurred, so that |callback| of OnEventOrTimeOut() can be
+ // called immediately.
+ void Signal();
+
+ // Returns whether Signal() was called at least once or a timeout happened,
+ // and Reset() has not been called afterwards. Note that this function does
+ // not discriminate whether Signal() was called or a timeout happened.
+ // The |callback_|'s parameter has this distinction, though.
+ bool IsSignaled() const;
+
+ // Registers the |callback| and calls it immediately if Signal() was called
+ // already. Starts a timeout task, so that |callback| is called if no call of
+ // Signal() is observed within |timeout|. A previous timeout is replaced by a
+ // new one.
+ void OnEventOrTimeOut(Callback callback, base::TimeDelta timeout);
+
+ // Resets the state machine so that no Signal() was observed, no callback is
+ // registered and no timeout task is running.
+ void Reset();
+
+ private:
+ enum class State {
+ // Signal() has not been called, yet.
+ kInitialState,
+ // Signal() has been called, but callback is not specified.
+ kSignalReceived,
+ // callback has been called.
+ kDone,
+ };
+
+ // Internal callback for the timeout. |generation_id| is a generation counter
+ // to ensure that old, delayed timeout tasks are ignored.
+ void OnTimeOut(int generation_id);
+
+ // Handler for Signal() and OnTimeOut(). Calls |callback_| if appropriate.
+ // The parameter is true if this function is called via Signal() and false if
+ // the function is called via OnTimeOut(). This parameter is passed to
+ // callback.
+ void SignalHandler(bool triggered_by_signal);
+
+ State state_ = State::kInitialState;
+
+ // This variable is only valid if state_ == State::kSignalReceived. It is
+ // true if we moved into this state due to a Signal() call, and false if
+ // we moved into this state due to an OnTimeOut() call.
+ bool in_state_signal_received_due_to_signal_call_;
+
+ // As the base::ThreadPool does not support cancelable tasks, we just rely on
+ // a generation counter. Every time Reset() or OnEventOrTimeOut() are called,
+ // the generation id is incremented. If outdated delayed OnTimeOut() tasks
+ // trickle in, we recognize them as tasks for which the |generation_id|
+ // parameter is less than the current generation_id_ and ignore them.
+ int generation_id_ = 0;
+
+ // Callback to be called in case of a Signal() or a time out.
+ Callback callback_;
+
+ SEQUENCE_CHECKER(my_sequence_checker_);
+
+ base::WeakPtrFactory<WaitForSignalOrTimeout> weak_factory_{this};
+};
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
diff --git a/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc b/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eda3fd362221cb9c08c893af02ce33a2826c5d6f
--- /dev/null
+++ b/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc
@@ -0,0 +1,188 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/payments/wait_for_signal_or_timeout.h"
+
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class WaitForSignalOrTimeoutTest : public testing::Test {
+ public:
+ WaitForSignalOrTimeoutTest() = default;
+ ~WaitForSignalOrTimeoutTest() override = default;
+
+ WaitForSignalOrTimeout::Callback GetCallback() {
+ return base::BindOnce(&WaitForSignalOrTimeoutTest::Callback,
+ base::Unretained(this));
+ }
+
+ protected:
+ void Callback(bool triggered_by_signal) {
+ callbacks_++;
+ last_callback_triggered_by_signal_ = triggered_by_signal;
+ }
+
+ // Number of observed callbacks.
+ int callbacks_ = 0;
+
+ bool last_callback_triggered_by_signal_ = false;
+
+ base::test::TaskEnvironment task_env_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+};
+
+// WaitForSignalOrTimeout is initialized with a callback and then the Signal()
+// happens.
+TEST_F(WaitForSignalOrTimeoutTest, InitThenSignal) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(0, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ // Another signal call should be ignored.
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+
+ // Also the pending timeout should not trigger further callbacks.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+}
+
+// A Signal() is registered before the callback.
+TEST_F(WaitForSignalOrTimeoutTest, SignalThenInit) {
+ WaitForSignalOrTimeout wait;
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // Trigger the signal before a callback handler is registered.
+ wait.Signal();
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(0, callbacks_);
+
+ // Once the callback handler is registered, it should be called immediately.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ // Another signal call should be ignored.
+ wait.Signal();
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+
+ // Also the pending timeout should not trigger further callbacks.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+}
+
+// A timeout occurs before Signal() is called.
+TEST_F(WaitForSignalOrTimeoutTest, InitThenTimeout) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_FALSE(wait.IsSignaled());
+ EXPECT_EQ(0, callbacks_);
+
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+
+ // A late signal will be ignored.
+ wait.Signal();
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+}
+
+// The WaitForSignalOrTimeout gets destroyed before a Signal() or timeout
+// happens.
+TEST_F(WaitForSignalOrTimeoutTest, DestroyedBeforeSignal) {
+ {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ }
+ EXPECT_EQ(0, callbacks_);
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_EQ(0, callbacks_);
+}
+
+// The WaitForSignalOrTimeout gets signaled, reset, and signaled again.
+TEST_F(WaitForSignalOrTimeoutTest, Reset) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(0, callbacks_);
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ wait.Reset();
+
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // This signal does not trigger a callback because none is registered.
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ // Now the callback happens immediately.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(2, callbacks_);
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ wait.Reset();
+
+ // Finally, we simulate a timeout after the reset.
+ EXPECT_FALSE(wait.IsSignaled());
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_EQ(3, callbacks_);
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+}
+
+TEST_F(WaitForSignalOrTimeoutTest, OnEventOrTimeOutCalledTwice) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(0, callbacks_);
+
+ // Wait some time but not long enough for the timeout to trigger.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
+ EXPECT_EQ(0, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // This resets the state machine (currently waiting for a signal or timeout)
+ // and starts a new wait.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+
+ // Wait some time but not long enough for the timeout to trigger.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
+ // The first timeout should not have triggered anything.
+ EXPECT_EQ(0, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // Wait some more time for the second timeout to kick in.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+
+ // This resets the state machine (currently in done state) once more and
+ // starts a new wait.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+
+ // Wait some time but not long enough for the timeout to trigger.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
+ // The first timeout should not have triggered anything.
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // Wait some more time for the second timeout to kick in.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+ EXPECT_EQ(2, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+}

View File

@@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20S=C3=B6derqvist?= <fs@opera.com>
Date: Fri, 9 Jul 2021 08:44:55 +0000
Subject: Set SVGImage::page_ after document install
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We can end up having the associated ImageResource call
SVGImage::ResetAnimation() before the Document has been associated with
the SVGImage's LocalFrame, but after the link to the initial Document
was severed, if a GC is triggered within that window and ends up
collecting the last observer of the ImageResource.
By assigning |SVGImage::page_| after the installing the document, we
close this hole since SVGImage::RootElement() (called by
SVGImage::ResetAnimation()) will now observe a null Page and return null
without attempting to dereference the document.
Bug: 1216190
Change-Id: I26e08848e5b9bd52e3377841eee35e4acc03d320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3010140
Reviewed-by: Stephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#899922}
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
index 2ce8a78b3537c72206e2d3e6d55f9cc1fc5d3208..0dec91614edb0caa6f8e473f027c3be7b8bf1e4e 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -830,12 +830,15 @@ Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) {
// SVG Images are transparent.
frame->View()->SetBaseBackgroundColor(Color::kTransparent);
- page_ = page;
-
TRACE_EVENT0("blink", "SVGImage::dataChanged::load");
frame->ForceSynchronousDocumentInstall("image/svg+xml", Data());
+ // Set up our Page reference after installing our document. This avoids
+ // tripping on a non-existing (null) Document if a GC is triggered during the
+ // set up and ends up collecting the last owner/observer of this image.
+ page_ = page;
+
// Intrinsic sizing relies on computed style (e.g. font-size and
// writing-mode).
frame->GetDocument()->UpdateStyleAndLayoutTree();

View File

@@ -19,5 +19,7 @@
"src/electron/patches/angle": "src/third_party/angle",
"src/electron/patches/usrsctp": "src/third_party/usrsctp/usrsctplib"
"src/electron/patches/usrsctp": "src/third_party/usrsctp/usrsctplib",
"src/electron/patches/sqlite": "src/third_party/sqlite/src"
}

2
patches/sqlite/.patches Normal file
View File

@@ -0,0 +1,2 @@
utf-8_q_when_20constructing_20the_20synthensized_20select_20sta.patch
sqlite_fix_an_undefined-integer-overflow_problem_in_fts3_c.patch

View File

@@ -0,0 +1,157 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Darwin Huang <huangdarwin@chromium.org>
Date: Wed, 19 May 2021 14:13:15 -0700
Subject: sqlite: Fix an undefined-integer-overflow problem in fts3.c.
Original change: https://sqlite.org/src/info/a0bf931bd712037e
Bug: 1204066
Change-Id: I34704f1cfe36672d10065f4103c91fb4f35d3895
diff --git a/amalgamation/sqlite3.c b/amalgamation/sqlite3.c
index d19e25f98d37686a7fd1bfefe4bd044575abf5d4..175c55f86fa02cbe443b53f656519879f9192765 100644
--- a/amalgamation/sqlite3.c
+++ b/amalgamation/sqlite3.c
@@ -169123,7 +169123,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
@@ -169139,8 +169139,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -169193,20 +169193,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
diff --git a/amalgamation_dev/sqlite3.c b/amalgamation_dev/sqlite3.c
index f4c985513fb7cac3930fe9706ddfc5c440dd3e85..c3ec02ed9124d59ee008548491b2b30e996472ef 100644
--- a/amalgamation_dev/sqlite3.c
+++ b/amalgamation_dev/sqlite3.c
@@ -169636,7 +169636,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
@@ -169652,8 +169652,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -169706,20 +169706,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
index 79dc5c88ceacb823d16889bd36250597361d6186..62b31373c3c3e9b61b3e1daae8d87d9393779b61 100644
--- a/ext/fts3/fts3.c
+++ b/ext/fts3/fts3.c
@@ -1897,7 +1897,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
@@ -1913,8 +1913,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -1967,20 +1967,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);

View File

@@ -0,0 +1,178 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: drh <>
Date: Wed, 19 May 2021 21:55:56 +0000
Subject: When constructing the synthensized SELECT statement that is used to
choose the rows in an UPDATE FROM, make sure the first table is really the
table being updated, and not some common-table expression that happens to
have the same name. [forum:/forumpost/a274248080|forum post a274248080]. More
changes associated with CTE name resolution are pending.
FossilOrigin-Name: 0f0959c6f95046e8e7887716e0a7de95da18d1e926ab1f919527083a56541db5
(cherry picked from commit 1168f810929ede4d8d323a6acf721ff9cd89de90)
diff --git a/amalgamation/sqlite3.c b/amalgamation/sqlite3.c
index 6b4a7899d336d07cf150530440755d25207b594f..d19e25f98d37686a7fd1bfefe4bd044575abf5d4 100644
--- a/amalgamation/sqlite3.c
+++ b/amalgamation/sqlite3.c
@@ -1173,7 +1173,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -111305,7 +111305,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
struct SrcList_item *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
@@ -138346,6 +138346,10 @@ static void updateFromSelect(
assert( pTabList->nSrc>1 );
if( pSrc ){
+ if( pSrc->a[0].zDatabase==0 ){
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
+ }
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
@@ -231234,9 +231238,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=231237
+#if __LINE__!=231241
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/amalgamation/sqlite3.h b/amalgamation/sqlite3.h
index 44be7872663c9216b30ce6e13b1683ca2d807bd6..4935dd32d6aab4261b758c4c199ef0ad18c23ce9 100644
--- a/amalgamation/sqlite3.h
+++ b/amalgamation/sqlite3.h
@@ -125,7 +125,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
diff --git a/amalgamation_dev/sqlite3.c b/amalgamation_dev/sqlite3.c
index d30c9b7dea35e5b4785f78b8bc5789fbc56bba84..f4c985513fb7cac3930fe9706ddfc5c440dd3e85 100644
--- a/amalgamation_dev/sqlite3.c
+++ b/amalgamation_dev/sqlite3.c
@@ -1173,7 +1173,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -111318,7 +111318,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
struct SrcList_item *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
@@ -138359,6 +138359,10 @@ static void updateFromSelect(
assert( pTabList->nSrc>1 );
if( pSrc ){
+ if( pSrc->a[0].zDatabase==0 ){
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
+ }
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
@@ -231747,9 +231751,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=231750
+#if __LINE__!=231754
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/amalgamation_dev/sqlite3.h b/amalgamation_dev/sqlite3.h
index 44be7872663c9216b30ce6e13b1683ca2d807bd6..4935dd32d6aab4261b758c4c199ef0ad18c23ce9 100644
--- a/amalgamation_dev/sqlite3.h
+++ b/amalgamation_dev/sqlite3.h
@@ -125,7 +125,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.34.0"
#define SQLITE_VERSION_NUMBER 3034000
-#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 571f9642d6a6caff9ea5ea572e2f1275e75c8385fbe1b7fb41cf72e4c13ealt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
diff --git a/manifest b/manifest
index 6c9cbb5ed81ca973f03931cea4d861209dee7037..76872d8b3a63cf623a1903ac0ccfc9b80f5c47d3 100644
--- a/manifest
+++ b/manifest
@@ -483,7 +483,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c ee14224322b9e4172d01e691e2f289f6c630ae39b7906f84b72dc780b9e42a76
F src/btree.h dcdff4037d75b3f032a5de0d922fcfaf35d48589417f634fa8627362709315f9
F src/btreeInt.h ffd66480520d9d70222171b3a026d78b80833b5cea49c89867949f3e023d5f43
-F src/build.c f6449d4e85e998e14d3f537e8ea898dca2fcb83c277db3e60945af9b9177db81
+F src/build.c 0803beedb8312c4ee4d60e63390ad0480a4ef471a329a56f8887a4b6ffc66da5
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
@@ -606,7 +606,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 4dc01b267593537e2a0d0efe9f80dabe24c5b6f7627bc6971c487fa6a1dacbbf
F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
F src/trigger.c 515e79206d40d1d4149129318582e79a6e9db590a7b74e226fdb5b2a6c7e1b10
-F src/update.c 9f126204a6acb96bbe47391ae48e0fc579105d8e76a6d9c4fab3271367476580
+F src/update.c 3e767f6605ed3adf6085d7e3eb8bbcf7e845b60ebf5590720123b24f907d7414
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002
diff --git a/src/build.c b/src/build.c
index 9779e93732b6d2f50cf5ac3822df1fbe6802eaa6..29d8ea66c105f9098c49ade70246828c92465f96 100644
--- a/src/build.c
+++ b/src/build.c
@@ -451,7 +451,7 @@ Table *sqlite3LocateTableItem(
struct SrcList_item *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
+ /* assert( p->pSchema==0 || p->zDatabase==0 ); FIX-ME */
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
diff --git a/src/update.c b/src/update.c
index f8cb2afedb6f9f2931d29d266f65fabcd2cd443c..3e0ec2544a274356c68416d978c8585a143bf8a4 100644
--- a/src/update.c
+++ b/src/update.c
@@ -220,6 +220,10 @@ static void updateFromSelect(
assert( pTabList->nSrc>1 );
if( pSrc ){
+ if( pSrc->a[0].zDatabase==0 ){
+ int iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iSchema].zDbSName);
+ }
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;

View File

@@ -24,3 +24,7 @@ cherry-pick-d0aadee1a60a.patch
m90-lts_squashed_multiple_commits.patch
cherry-pick-b9ad6a864c79.patch
cherry-pick-50de6a8ddad9.patch
cherry-pick-e76178b896f2.patch
merged_compiler_fix_a_bug_in.patch
cherry-pick-1234770.patch
cherry-pick-1234764.patch

View File

@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Georg Neis <neis@chromium.org>
Date: Tue, 10 Aug 2021 09:29:33 +0200
Subject: Merged: [compiler] Harden
JSCallReducer::ReduceArrayIteratorPrototypeNext
Revision: 65b20a0e65e1078f5dd230a5203e231bec790ab4
BUG=chromium:1234764
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
R=vahl@chromium.org
Change-Id: I45faf253695011092de144c8e29bafac5337adec
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3084363
Reviewed-by: Lutz Vahl <vahl@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.2@{#53}
Cr-Branched-From: 51238348f95a1f5e0acc321efac7942d18a687a2-refs/heads/9.2.230@{#1}
Cr-Branched-From: 587a04f02ab0487d194b55a7137dc2045e071597-refs/heads/master@{#74656}
diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
index 2c7b6788953092ffb3cf6fa75501dcbb02dce581..56f0ca99e252e715c9792222f95397950a451149 100644
--- a/src/compiler/js-call-reducer.cc
+++ b/src/compiler/js-call-reducer.cc
@@ -5854,11 +5854,12 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
Node* etrue = effect;
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
{
- // We know that the {index} is range of the {length} now.
+ // This extra check exists to refine the type of {index} but also to break
+ // an exploitation technique that abuses typer mismatches.
index = etrue = graph()->NewNode(
- common()->TypeGuard(
- Type::Range(0.0, length_access.type.Max() - 1.0, graph()->zone())),
- index, etrue, if_true);
+ simplified()->CheckBounds(p.feedback(),
+ CheckBoundsFlag::kAbortOnOutOfBounds),
+ index, length, etrue, if_true);
done_true = jsgraph()->FalseConstant();
if (iteration_kind == IterationKind::kKeys) {

View File

@@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Georg Neis <neis@chromium.org>
Date: Mon, 9 Aug 2021 09:57:12 +0200
Subject: Merged: [compiler] Fix a bug in MachineOperatorReducer's
BitfieldCheck
Revision: 574ca6b71c6160d38b5fcf4b8e133bc7f6ba2387
BUG=chromium:1234770
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
R=nicohartmann@chromium.org
Change-Id: I15af5a94e89b54c2a540442c3544ed459b832e0a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3080564
Reviewed-by: Lutz Vahl <vahl@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.3@{#21}
Cr-Branched-From: 7744dce208a555494e4a33e24fadc71ea20b3895-refs/heads/9.3.345@{#1}
Cr-Branched-From: 4b6b4cabf3b6a20cdfda72b369df49f3311c4344-refs/heads/master@{#75728}
diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc
index 918caaf8fd446750d9d4c38350b3af2f25c9a91f..facfadc3ca99f9d2a554f17b577a3833a9974470 100644
--- a/src/compiler/machine-operator-reducer.cc
+++ b/src/compiler/machine-operator-reducer.cc
@@ -1706,11 +1706,21 @@ Reduction MachineOperatorReducer::ReduceWordNAnd(Node* node) {
namespace {
// Represents an operation of the form `(source & mask) == masked_value`.
+// where each bit set in masked_value also has to be set in mask.
struct BitfieldCheck {
- Node* source;
- uint32_t mask;
- uint32_t masked_value;
- bool truncate_from_64_bit;
+ Node* const source;
+ uint32_t const mask;
+ uint32_t const masked_value;
+ bool const truncate_from_64_bit;
+
+ BitfieldCheck(Node* source, uint32_t mask, uint32_t masked_value,
+ bool truncate_from_64_bit)
+ : source(source),
+ mask(mask),
+ masked_value(masked_value),
+ truncate_from_64_bit(truncate_from_64_bit) {
+ CHECK_EQ(masked_value & ~mask, 0);
+ }
static base::Optional<BitfieldCheck> Detect(Node* node) {
// There are two patterns to check for here:
@@ -1725,14 +1735,16 @@ struct BitfieldCheck {
if (eq.left().IsWord32And()) {
Uint32BinopMatcher mand(eq.left().node());
if (mand.right().HasResolvedValue() && eq.right().HasResolvedValue()) {
- BitfieldCheck result{mand.left().node(), mand.right().ResolvedValue(),
- eq.right().ResolvedValue(), false};
+ uint32_t mask = mand.right().ResolvedValue();
+ uint32_t masked_value = eq.right().ResolvedValue();
+ if ((masked_value & ~mask) != 0) return {};
if (mand.left().IsTruncateInt64ToInt32()) {
- result.truncate_from_64_bit = true;
- result.source =
- NodeProperties::GetValueInput(mand.left().node(), 0);
+ return BitfieldCheck(
+ NodeProperties::GetValueInput(mand.left().node(), 0), mask,
+ masked_value, true);
+ } else {
+ return BitfieldCheck(mand.left().node(), mask, masked_value, false);
}
- return result;
}
}
} else {

View File

@@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Victor Gomes <victorgomes@chromium.org>
Date: Mon, 31 May 2021 13:16:54 +0200
Subject: Merged: [JSON] Fix GC issue in BuildJsonObject
We must ensure that the sweeper is not running or has already swept
mutable_double_buffer. Otherwise the GC can add it to the free list.
Change-Id: If0fc7617acdb6690f0567215b78f8728e1643ec0
No-Try: true
No-Presubmit: true
No-Tree-Checks: true
Bug: v8:11837, chromium:1214842
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2993033
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.1@{#75}
Cr-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
Cr-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 3f4348b063995eb5c23ddd8af2aa2ac900a88723..5239523c23d63c2af57a3a9795939bd582d7d10c 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -2125,6 +2125,10 @@ void Heap::CompleteSweepingYoung(GarbageCollector collector) {
array_buffer_sweeper()->EnsureFinished();
}
+void Heap::EnsureSweepingCompleted() {
+ mark_compact_collector()->EnsureSweepingCompleted();
+}
+
void Heap::UpdateCurrentEpoch(GarbageCollector collector) {
if (IsYoungGenerationCollector(collector)) {
epoch_young_ = next_epoch();
diff --git a/src/heap/heap.h b/src/heap/heap.h
index 7dc9ef7d447521012c9b110e4fc94589ada3e6f4..b56641f2e1c51197a68d7c96d5bfca428feb1484 100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -1068,6 +1068,8 @@ class Heap {
void CompleteSweepingFull();
void CompleteSweepingYoung(GarbageCollector collector);
+ void EnsureSweepingCompleted();
+
IncrementalMarking* incremental_marking() {
return incremental_marking_.get();
}
diff --git a/src/json/json-parser.cc b/src/json/json-parser.cc
index c0109bb77a01f7b6e8e23cd1b2f5d85c4473385b..c9844251cc8659587b3de85066cb0ea993d87014 100644
--- a/src/json/json-parser.cc
+++ b/src/json/json-parser.cc
@@ -633,6 +633,11 @@ Handle<Object> JsonParser<Char>::BuildJsonObject(
DCHECK_EQ(mutable_double_address, end);
}
#endif
+ // Before setting the length of mutable_double_buffer back to zero, we
+ // must ensure that the sweeper is not running or has already swept the
+ // object's page. Otherwise the GC can add the contents of
+ // mutable_double_buffer to the free list.
+ isolate()->heap()->EnsureSweepingCompleted();
mutable_double_buffer->set_length(0);
}
}

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Georg Neis <neis@chromium.org>
Date: Tue, 13 Jul 2021 17:26:47 +0200
Subject: Merged: [compiler] Fix a bug in
CodeGenerator::AddTranslationForOperand
(cherry picked from commit 374354bfe4a30740b96936b33e522d6fcd1cda67)
Bug: chromium:1228407
No-Try: true
No-Presubmit: true
No-Tree-Checks: true
Change-Id: I358d8736b7b5f87300496cbb39a7689d8207d85f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3027260
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Adam Klein <adamk@chromium.org>
Commit-Queue: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.1@{#77}
Cr-Branched-From: 0e4ac64a8cf298b14034a22f9fe7b085d2cb238d-refs/heads/9.1.269@{#1}
Cr-Branched-From: f565e72d5ba88daae35a59d0f978643e2343e912-refs/heads/master@{#73847}
diff --git a/src/compiler/backend/code-generator.cc b/src/compiler/backend/code-generator.cc
index 83f8fbc4e8fdbbfea81ae5b368f0dbcf5b32b5bb..647444fa58b559cda4aaf257b0a477282eafd569 100644
--- a/src/compiler/backend/code-generator.cc
+++ b/src/compiler/backend/code-generator.cc
@@ -1389,7 +1389,8 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
default:
UNREACHABLE();
}
- if (literal.object().equals(info()->closure())) {
+ if (literal.object().equals(info()->closure()) &&
+ info()->function_context_specializing()) {
translation->StoreJSFrameFunction();
} else {
int literal_id = DefineDeoptimizationLiteral(literal);

View File

@@ -14,6 +14,8 @@
"parallel/test-child-process-fork-exec-path",
"parallel/test-cli-node-print-help",
"parallel/test-code-cache",
"parallel/test-cluster-bind-privileged-port",
"parallel/test-cluster-shared-handle-bind-privileged-port",
"parallel/test-crypto",
"parallel/test-crypto-aes-wrap",
"parallel/test-crypto-authenticated",

View File

@@ -9,7 +9,8 @@ const rootPackageJson = require('../../package.json');
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({
userAgent: 'electron-npm-publisher'
userAgent: 'electron-npm-publisher',
auth: process.env.ELECTRON_GITHUB_TOKEN
});
if (!process.env.ELECTRON_NPM_OTP) {

View File

@@ -26,6 +26,7 @@ function getLastBumpCommit (tag) {
async function revertBumpCommit (tag) {
const branch = await getCurrentBranch();
const commitToRevert = getLastBumpCommit(tag).hash;
await GitProcess.exec(['pull', '--rebase']);
await GitProcess.exec(['revert', commitToRevert], ELECTRON_DIR);
const pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], ELECTRON_DIR);
if (pushDetails.exitCode === 0) {

View File

@@ -524,4 +524,8 @@ async function validateChecksums (validationArgs) {
`shasums defined in ${validationArgs.shaSumFile}.`);
}
makeRelease(args.validateRelease);
makeRelease(args.validateRelease)
.catch((err) => {
console.error('Error occurred while making release:', err);
process.exit(1);
});

View File

@@ -103,7 +103,75 @@ namespace crash_reporter {
extern const char kCrashpadProcess[];
}
// In 32-bit builds, the main thread starts with the default (small) stack size.
// The ARCH_CPU_32_BITS blocks here and below are in support of moving the main
// thread to a fiber with a larger stack size.
#if defined(ARCH_CPU_32_BITS)
// The information needed to transfer control to the large-stack fiber and later
// pass the main routine's exit code back to the small-stack fiber prior to
// termination.
struct FiberState {
HINSTANCE instance;
LPVOID original_fiber;
int fiber_result;
};
// A PFIBER_START_ROUTINE function run on a large-stack fiber that calls the
// main routine, stores its return value, and returns control to the small-stack
// fiber. |params| must be a pointer to a FiberState struct.
void WINAPI FiberBinder(void* params) {
auto* fiber_state = static_cast<FiberState*>(params);
// Call the wWinMain routine from the fiber. Reusing the entry point minimizes
// confusion when examining call stacks in crash reports - seeing wWinMain on
// the stack is a handy hint that this is the main thread of the process.
fiber_state->fiber_result =
wWinMain(fiber_state->instance, nullptr, nullptr, 0);
// Switch back to the main thread to exit.
::SwitchToFiber(fiber_state->original_fiber);
}
#endif // defined(ARCH_CPU_32_BITS)
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
#if defined(ARCH_CPU_32_BITS)
enum class FiberStatus { kConvertFailed, kCreateFiberFailed, kSuccess };
FiberStatus fiber_status = FiberStatus::kSuccess;
// GetLastError result if fiber conversion failed.
DWORD fiber_error = ERROR_SUCCESS;
if (!::IsThreadAFiber()) {
// Make the main thread's stack size 4 MiB so that it has roughly the same
// effective size as the 64-bit build's 8 MiB stack.
constexpr size_t kStackSize = 4 * 1024 * 1024; // 4 MiB
// Leak the fiber on exit.
LPVOID original_fiber =
::ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH);
if (original_fiber) {
FiberState fiber_state = {instance, original_fiber};
// Create a fiber with a bigger stack and switch to it. Leak the fiber on
// exit.
LPVOID big_stack_fiber = ::CreateFiberEx(
0, kStackSize, FIBER_FLAG_FLOAT_SWITCH, FiberBinder, &fiber_state);
if (big_stack_fiber) {
::SwitchToFiber(big_stack_fiber);
// The fibers must be cleaned up to avoid obscure TLS-related shutdown
// crashes.
::DeleteFiber(big_stack_fiber);
::ConvertFiberToThread();
// Control returns here after Chrome has finished running on FiberMain.
return fiber_state.fiber_result;
}
fiber_status = FiberStatus::kCreateFiberFailed;
} else {
fiber_status = FiberStatus::kConvertFailed;
}
// If we reach here then creating and switching to a fiber has failed. This
// probably means we are low on memory and will soon crash. Try to report
// this error once crash reporting is initialized.
fiber_error = ::GetLastError();
base::debug::Alias(&fiber_error);
}
// If we are already a fiber then continue normal execution.
#endif // defined(ARCH_CPU_32_BITS)
struct Arguments {
int argc = 0;
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
@@ -198,6 +266,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
return crashpad_status;
}
#if defined(ARCH_CPU_32_BITS)
// Intentionally crash if converting to a fiber failed.
CHECK_EQ(fiber_status, FiberStatus::kSuccess);
#endif // defined(ARCH_CPU_32_BITS)
if (!electron::CheckCommandLineArguments(arguments.argc, arguments.argv))
return -1;

View File

@@ -236,7 +236,7 @@ base::string16 Menu::GetToolTipAt(int index) const {
return model_->GetToolTipAt(index);
}
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
base::string16 Menu::GetAcceleratorTextAtForTesting(int index) const {
ui::Accelerator accelerator;
model_->GetAcceleratorAtWithParams(index, true, &accelerator);
@@ -297,7 +297,7 @@ v8::Local<v8::ObjectTemplate> Menu::FillObjectTemplate(
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
.SetMethod("popupAt", &Menu::PopupAt)
.SetMethod("closePopupAt", &Menu::ClosePopupAt)
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
.SetMethod("getAcceleratorTextAt", &Menu::GetAcceleratorTextAtForTesting)
#endif
.Build();

View File

@@ -78,7 +78,7 @@ class Menu : public gin::Wrappable<Menu>,
int positioning_item,
base::OnceClosure callback) = 0;
virtual void ClosePopupAt(int32_t window_id) = 0;
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
virtual base::string16 GetAcceleratorTextAtForTesting(int index) const;
#endif

View File

@@ -35,7 +35,7 @@ class MenuMac : public Menu {
int positioning_item,
base::OnceClosure callback);
void ClosePopupAt(int32_t window_id) override;
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
base::string16 GetAcceleratorTextAtForTesting(int index) const override;
#endif

View File

@@ -127,7 +127,7 @@ void MenuMac::ClosePopupAt(int32_t window_id) {
std::move(close_popup));
}
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
base::string16 MenuMac::GetAcceleratorTextAtForTesting(int index) const {
// A least effort to get the real shortcut text of NSMenuItem, the code does
// not need to be perfect since it is test only.

View File

@@ -1230,31 +1230,29 @@ void WebContents::OnEnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options,
bool allowed) {
if (!allowed)
return;
if (!owner_window_)
if (!allowed || !owner_window_)
return;
auto* source = content::WebContents::FromRenderFrameHost(requesting_frame);
if (IsFullscreenForTabOrPending(source)) {
DCHECK_EQ(fullscreen_frame_, source->GetFocusedFrame());
return;
}
SetHtmlApiFullscreen(true);
owner_window_->NotifyWindowEnterHtmlFullScreen();
if (native_fullscreen_) {
// Explicitly trigger a view resize, as the size is not actually changing if
// the browser is fullscreened, too.
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
}
Emit("enter-html-full-screen");
}
void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
if (!owner_window_)
return;
SetHtmlApiFullscreen(false);
owner_window_->NotifyWindowLeaveHtmlFullScreen();
if (native_fullscreen_) {
// Explicitly trigger a view resize, as the size is not actually changing if
@@ -1262,7 +1260,6 @@ void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
// `chrome/browser/ui/exclusive_access/fullscreen_controller.cc`.
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
}
Emit("leave-html-full-screen");
}
void WebContents::RendererUnresponsive(
@@ -3467,6 +3464,30 @@ void WebContents::DevToolsSearchInPath(int request_id,
file_system_path));
}
void WebContents::DevToolsSetEyeDropperActive(bool active) {
auto* web_contents = GetWebContents();
if (!web_contents)
return;
if (active) {
eye_dropper_ = std::make_unique<DevToolsEyeDropper>(
web_contents, base::BindRepeating(&WebContents::ColorPickedInEyeDropper,
base::Unretained(this)));
} else {
eye_dropper_.reset();
}
}
void WebContents::ColorPickedInEyeDropper(int r, int g, int b, int a) {
base::DictionaryValue color;
color.SetInteger("r", r);
color.SetInteger("g", g);
color.SetInteger("b", b);
color.SetInteger("a", a);
inspectable_web_contents_->CallClientFunction(
"DevToolsAPI.eyeDropperPickedColor", &color, nullptr, nullptr);
}
#if defined(TOOLKIT_VIEWS) && !defined(OS_MAC)
gfx::ImageSkia WebContents::GetDevToolsWindowIcon() {
if (!owner_window())
@@ -3561,7 +3582,7 @@ void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
}
void WebContents::UpdateHtmlApiFullscreen(bool fullscreen) {
if (fullscreen == html_fullscreen_)
if (fullscreen == is_html_fullscreen())
return;
html_fullscreen_ = fullscreen;
@@ -3572,20 +3593,26 @@ void WebContents::UpdateHtmlApiFullscreen(bool fullscreen) {
->GetWidget()
->SynchronizeVisualProperties();
// The embedder WebContents is spearated from the frame tree of webview, so
// The embedder WebContents is separated from the frame tree of webview, so
// we must manually sync their fullscreen states.
if (embedder_)
embedder_->SetHtmlApiFullscreen(fullscreen);
if (fullscreen) {
Emit("enter-html-full-screen");
owner_window_->NotifyWindowEnterHtmlFullScreen();
} else {
Emit("leave-html-full-screen");
owner_window_->NotifyWindowLeaveHtmlFullScreen();
}
// Make sure all child webviews quit html fullscreen.
if (!fullscreen && !IsGuest()) {
auto* manager = WebViewManager::GetWebViewManager(web_contents());
manager->ForEachGuest(
web_contents(), base::BindRepeating([](content::WebContents* guest) {
WebContents* api_web_contents = WebContents::From(guest);
// Use UpdateHtmlApiFullscreen instead of SetXXX becuase there is no
// need to interact with the owner window.
api_web_contents->UpdateHtmlApiFullscreen(false);
api_web_contents->SetHtmlApiFullscreen(false);
return false;
}));
}

View File

@@ -14,6 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "chrome/browser/devtools/devtools_eye_dropper.h"
#include "chrome/browser/devtools/devtools_file_system_indexer.h"
#include "content/common/cursors/webcursor.h"
#include "content/common/frame.mojom.h"
@@ -665,6 +666,7 @@ class WebContents : public gin::Wrappable<WebContents>,
void DevToolsSearchInPath(int request_id,
const std::string& file_system_path,
const std::string& query) override;
void DevToolsSetEyeDropperActive(bool active) override;
// InspectableWebContentsViewDelegate:
#if defined(TOOLKIT_VIEWS) && !defined(OS_MAC)
@@ -678,6 +680,8 @@ class WebContents : public gin::Wrappable<WebContents>,
// Destroy the managed InspectableWebContents object.
void ResetManagedWebContents(bool async);
void ColorPickedInEyeDropper(int r, int g, int b, int a);
// DevTools index event callbacks.
void OnDevToolsIndexingWorkCalculated(int request_id,
const std::string& file_system_path,
@@ -749,6 +753,8 @@ class WebContents : public gin::Wrappable<WebContents>,
scoped_refptr<DevToolsFileSystemIndexer> devtools_file_system_indexer_;
std::unique_ptr<DevToolsEyeDropper> eye_dropper_;
ElectronBrowserContext* browser_context_;
// The stored InspectableWebContents object.

View File

@@ -70,11 +70,15 @@ void LoginHandler::EmitEvent(
details.Set("firstAuthAttempt", first_auth_attempt);
details.Set("responseHeaders", response_headers.get());
auto weak_this = weak_factory_.GetWeakPtr();
bool default_prevented =
api_web_contents->Emit("login", std::move(details), auth_info,
base::BindOnce(&LoginHandler::CallbackFromJS,
weak_factory_.GetWeakPtr()));
if (!default_prevented && auth_required_callback_) {
// ⚠️ NB, if CallbackFromJS is called during Emit(), |this| will have been
// deleted. Check the weak ptr before accessing any member variables to
// prevent UAF.
if (weak_this && !default_prevented && auth_required_callback_) {
std::move(auth_required_callback_).Run(base::nullopt);
}
}

View File

@@ -498,7 +498,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
// Use an NSEvent monitor to listen for the wheel event.
BOOL __block began = NO;
wheel_event_monitor_ = [NSEvent
addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel
handler:^(NSEvent* event) {
if ([[event window] windowNumber] !=
[window_ windowNumber])
@@ -539,7 +539,10 @@ void NativeWindowMac::Cleanup() {
DCHECK(!IsClosed());
ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this);
display::Screen::GetScreen()->RemoveObserver(this);
[NSEvent removeMonitor:wheel_event_monitor_];
if (wheel_event_monitor_) {
[NSEvent removeMonitor:wheel_event_monitor_];
wheel_event_monitor_ = nil;
}
}
void NativeWindowMac::RedrawTrafficLights() {
@@ -959,7 +962,7 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio,
// Reset the behaviour to default if aspect_ratio is set to 0 or less.
if (aspect_ratio > 0.0)
[window_ setAspectRatio:NSMakeSize(aspect_ratio, 1.0)];
[window_ setContentAspectRatio:NSMakeSize(aspect_ratio, 1.0)];
else
[window_ setResizeIncrements:NSMakeSize(1.0, 1.0)];
}
@@ -1781,8 +1784,6 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
}
void NativeWindowMac::SetActive(bool is_key) {
if (is_key)
widget()->Activate();
is_active_ = is_key;
}

View File

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

View File

@@ -787,7 +787,10 @@ void InspectableWebContents::SearchInPath(int request_id,
void InspectableWebContents::SetWhitelistedShortcuts(
const std::string& message) {}
void InspectableWebContents::SetEyeDropperActive(bool active) {}
void InspectableWebContents::SetEyeDropperActive(bool active) {
if (delegate_)
delegate_->DevToolsSetEyeDropperActive(active);
}
void InspectableWebContents::ShowCertificateViewer(
const std::string& cert_chain) {}

View File

@@ -35,6 +35,7 @@ class InspectableWebContentsDelegate {
virtual void DevToolsSearchInPath(int request_id,
const std::string& file_system_path,
const std::string& query) {}
virtual void DevToolsSetEyeDropperActive(bool active) {}
};
} // namespace electron

View File

@@ -12,6 +12,7 @@
#include <string>
#include <vector>
#include "base/win/scoped_com_initializer.h"
#include "shell/common/gin_converters/image_converter.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/skia_util.h"
@@ -26,6 +27,8 @@ v8::Local<v8::Promise> NativeImage::CreateThumbnailFromPath(
v8::Isolate* isolate,
const base::FilePath& path,
const gfx::Size& size) {
base::win::ScopedCOMInitializer scoped_com_initializer;
gin_helper::Promise<gfx::Image> promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
HRESULT hr;

View File

@@ -107,7 +107,7 @@ bool IsSameOrigin(const GURL& l, const GURL& r) {
return url::Origin::Create(l).IsSameOriginWith(url::Origin::Create(r));
}
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
std::vector<v8::Global<v8::Value>> weakly_tracked_values;
void WeaklyTrackValue(v8::Isolate* isolate, v8::Local<v8::Value> value) {
@@ -157,7 +157,7 @@ void Initialize(v8::Local<v8::Object> exports,
dict.SetMethod("requestGarbageCollectionForTesting",
&RequestGarbageCollectionForTesting);
dict.SetMethod("isSameOrigin", &IsSameOrigin);
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
dict.SetMethod("triggerFatalErrorForTesting", &TriggerFatalErrorForTesting);
dict.SetMethod("getWeaklyTrackedValues", &GetWeaklyTrackedValues);
dict.SetMethod("clearWeaklyTrackedValues", &ClearWeaklyTrackedValues);

View File

@@ -678,7 +678,7 @@ void Initialize(v8::Local<v8::Object> exports,
&electron::api::OverrideGlobalPropertyFromIsolatedWorld);
dict.SetMethod("_isCalledFromMainWorld",
&electron::api::IsCalledFromMainWorld);
#ifdef DCHECK_IS_ON
#if DCHECK_IS_ON()
dict.Set("_isDebug", true);
#endif
}

View File

@@ -4256,6 +4256,20 @@ describe('BrowserWindow module', () => {
await leaveFullScreen;
expect(w.isFullScreen()).to.be.false('isFullScreen');
});
it('multiple windows inherit correct fullscreen state', async () => {
const w = new BrowserWindow();
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
w.setFullScreen(true);
await enterFullScreen;
expect(w.isFullScreen()).to.be.true('isFullScreen');
await delay();
const w2 = new BrowserWindow({ show: false });
const enterFullScreen2 = emittedOnce(w2, 'enter-full-screen');
w2.show();
await enterFullScreen2;
expect(w2.isFullScreen()).to.be.true('isFullScreen');
});
});
describe('closable state', () => {

View File

@@ -1,6 +1,6 @@
const { app, BrowserWindow } = require('electron');
app.once('ready', () => {
app.once('ready', async () => {
const w = new BrowserWindow({
show: false,
webPreferences: {
@@ -8,9 +8,12 @@ app.once('ready', () => {
nodeIntegration: true
}
});
w.webContents.once('crashed', () => {
app.quit();
w.webContents.once('render-process-gone', (_, details) => {
if (details.reason === 'crashed') {
process.exit(0);
} else {
process.exit(details.exitCode);
}
});
w.webContents.loadURL('about:blank');
w.webContents.executeJavaScript('process.crash()');
await w.webContents.loadURL('chrome://checkcrash');
});

View File

@@ -3,7 +3,7 @@ import * as url from 'url';
import { BrowserWindow, session, ipcMain, app, WebContents } from 'electron/main';
import { closeAllWindows } from './window-helpers';
import { emittedOnce, emittedUntil } from './events-helpers';
import { ifdescribe } from './spec-helpers';
import { ifdescribe, ifit, delay } from './spec-helpers';
import { expect } from 'chai';
const features = process._linkedBinding('electron_common_features');
@@ -184,6 +184,26 @@ describe('<webview> tag', function () {
});
});
describe('did-attach event', () => {
it('is emitted when a webview has been attached', async () => {
const w = new BrowserWindow({
webPreferences: {
webviewTag: true
}
});
await w.loadURL('about:blank');
const message = await w.webContents.executeJavaScript(`new Promise((resolve, reject) => {
const webview = new WebView()
webview.setAttribute('src', 'about:blank')
webview.addEventListener('did-attach', (e) => {
resolve('ok')
})
document.body.appendChild(webview)
})`);
expect(message).to.equal('ok');
});
});
describe('did-change-theme-color event', () => {
it('emits when theme color changes', async () => {
const w = new BrowserWindow({
@@ -409,6 +429,63 @@ describe('<webview> tag', function () {
await parentFullscreen;
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.true();
});
// FIXME(zcbenz): Fullscreen events do not work on Linux.
// This test is flaky on arm64 macOS.
ifit(process.platform !== 'linux' && process.arch !== 'arm64')('exiting fullscreen should unfullscreen window', async () => {
const [w, webview] = await loadWebViewWindow();
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
await enterFullScreen;
const leaveFullScreen = emittedOnce(w, 'leave-full-screen');
await webview.executeJavaScript('document.exitFullscreen()', true);
await leaveFullScreen;
await delay(0);
expect(w.isFullScreen()).to.be.false();
});
// Sending ESC via sendInputEvent only works on Windows.
ifit(process.platform === 'win32')('pressing ESC should unfullscreen window', async () => {
const [w, webview] = await loadWebViewWindow();
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
await enterFullScreen;
const leaveFullScreen = emittedOnce(w, 'leave-full-screen');
w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
await leaveFullScreen;
await delay(0);
expect(w.isFullScreen()).to.be.false();
});
it('pressing ESC should emit the leave-html-full-screen event', async () => {
const w = new BrowserWindow({
show: false,
webPreferences: {
webviewTag: true,
nodeIntegration: true,
contextIsolation: false
}
});
const didAttachWebview = emittedOnce(w.webContents, 'did-attach-webview');
w.loadFile(path.join(fixtures, 'pages', 'webview-did-attach-event.html'));
const [, webContents] = await didAttachWebview;
const enterFSWindow = emittedOnce(w, 'enter-html-full-screen');
const enterFSWebview = emittedOnce(webContents, 'enter-html-full-screen');
await webContents.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
await enterFSWindow;
await enterFSWebview;
const leaveFSWindow = emittedOnce(w, 'leave-html-full-screen');
const leaveFSWebview = emittedOnce(webContents, 'leave-html-full-screen');
webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
await leaveFSWindow;
await leaveFSWebview;
});
});
describe('nativeWindowOpen option', () => {

View File

@@ -3,6 +3,7 @@
<link rel="icon" type="image/png" href="http://test.com/favicon.png"/>
<meta http-equiv="content-security-policy" content="script-src 'self' 'unsafe-inline'" />
<body>
<div id="div">Hello World</div>
<script type="text/javascript" charset="utf-8">
console.log('a');
document.title = "test"

View File

@@ -4900,7 +4900,7 @@ minimist@^1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
minipass@^2.2.1, minipass@^2.3.5:
minipass@^2.2.1:
version "2.3.5"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848"
integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==
@@ -4908,6 +4908,14 @@ minipass@^2.2.1, minipass@^2.3.5:
safe-buffer "^5.1.2"
yallist "^3.0.0"
minipass@^2.8.6:
version "2.9.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
dependencies:
safe-buffer "^5.1.2"
yallist "^3.0.0"
minizlib@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614"
@@ -7613,13 +7621,13 @@ tapable@^1.0.0, tapable@^1.1.3:
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar@^4, tar@^4.4.7:
version "4.4.10"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1"
integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==
version "4.4.15"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.15.tgz#3caced4f39ebd46ddda4d6203d48493a919697f8"
integrity sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==
dependencies:
chownr "^1.1.1"
fs-minipass "^1.2.5"
minipass "^2.3.5"
minipass "^2.8.6"
minizlib "^1.2.1"
mkdirp "^0.5.0"
safe-buffer "^5.1.2"