Compare commits

...

49 Commits

Author SHA1 Message Date
Sudowoodo Release Bot
d93629321e Bump v13.5.0 2021-09-27 12:26:06 -07:00
trop[bot]
b505de0765 fix: first mouse not dragging BrowserView (#31098)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-09-27 21:24:57 +02:00
Michaela Laurencin
4c4d29eb73 fix: add casing for WCO edge (#31097)
* fix: add casing for WCO edge

* fix linting error

* apply fix for linting error
2021-09-27 12:00:35 -04:00
Robo
993ecb5bdd fix: crash in seccomp sandbox with glibc 2.34 (#31091)
Refs https://bugs.chromium.org/p/chromium/issues/detail?id=1244383
Refs https://bugs.chromium.org/p/chromium/issues/detail?id=1213452
2021-09-23 13:53:08 -07:00
Michaela Laurencin
d0ba8d1f69 feat: enable windows control overlay on Windows (#30887)
* feat: enable window controls overlay on macOS (#29253)

* feat: enable windows control overlay on macOS

* address review feedback

* chore: address review feedback

* Address review feedback

* update doc per review

* only enable WCO when titleBarStyle is overlay

* Revert "only enable WCO when titleBarStyle is overlay"

This reverts commit 1b58b5b1fc.

* Add new titleBarOverlay property to manage feature

* spelling fix

* Update docs/api/frameless-window.md

Co-authored-by: Samuel Attard <sam@electronjs.org>

* Update shell/browser/api/electron_api_browser_window.cc

Co-authored-by: Samuel Attard <sam@electronjs.org>

* update per review feedback

Co-authored-by: Samuel Attard <sam@electronjs.org>
(cherry picked from commit 1f8a46c9c6)

* feat: enable windows control overlay on Windows (#30678)

cherry-picked from 41646d1

Co-Authored-By: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com>

Co-authored-by: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com>

* modify included header files and update patches

* kick off missed ci

* fix lint error

* chore: update patches

* chore: update patches

* remove version control marker

* correct `resizeable_` backport

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2021-09-23 13:04:13 -07:00
trop[bot]
d03fd85a90 fix: update Windows' cache after changing window's style (#31078)
To enable/disable window resizing we set/unset WS_THICKFRAME style
flag on the window. Window's frame styles are cached so we need to
call SetWindowPos with the SWP_FRAMECHANGED flag set to update
cache properly.

Co-authored-by: Cezary Kulakowski <cezary@openfin.co>
2021-09-23 19:49:10 +09:00
trop[bot]
2387d10956 fix: maximized state calculation for non-resizable windows (#31039)
* fix: maximized state calculation for non-resizable windows

* refactor: clean up NSRect comparison

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-09-22 09:30:44 +09:00
Pedro Pontes
558350e4bf chore: cherry pick 9723e3c13c from chromium (#30964)
Co-authored-by: Electron Bot <electron@github.com>
2021-09-22 08:49:04 +09:00
trop[bot]
4d960873a4 fix: BrowserViews not painting their WebContents (#31047)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-09-21 22:02:35 +02:00
trop[bot]
dfcb2afffd fix: suppress insecure resource warning for more local hostnames (#31035) 2021-09-21 11:29:02 +02:00
Pedro Pontes
221fd9d6ce chore: cherry-pick 6215793f008f from chromium (#30952)
* chore: cherry-pick 6215793f008f 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-09-21 16:25:26 +09:00
Pedro Pontes
ecad7c2441 chore: cherry-pick ddc4cf156505 from chromium (#30962)
* chore: cherry-pick ddc4cf156505 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-09-21 15:23:31 +09:00
Pedro Pontes
a9acc050ee chore: cherry-pick 72473550f6ff from angle (#30960)
* chore: cherry-pick 72473550f6ff from angle

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Electron Bot <electron@github.com>
2021-09-21 14:41:16 +09:00
Pedro Pontes
29311b7d1d chore: cherry-pick 6048fcd52f42 from chromium (#30943)
* chore: cherry-pick 6048fcd52f42 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-09-21 14:39:56 +09:00
Pedro Pontes
949ec0c7c9 chore: cherry-pick 0c6f5c65fa from chromium (#30950)
Co-authored-by: Electron Bot <electron@github.com>
2021-09-21 10:35:51 +09:00
Pedro Pontes
91b1c0162e chore: cherry-pick 13842c96c2 from chromium and 018f85dea1 from angle (#30957) 2021-09-21 08:49:27 +09:00
Pedro Pontes
e20eab42d3 chore: cherry-pick 7699615c0d and 2f5740f50f from chromium (#30941)
Co-authored-by: Electron Bot <electron@github.com>
2021-09-21 08:48:36 +09:00
Pedro Pontes
fe44e01dbb chore: cherry-pick 034c2003be31 from v8 (#30939)
* chore: cherry-pick 034c2003be31 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-09-21 08:47:22 +09:00
trop[bot]
bc987209f8 chore: update links of documentation of chromes (#31006)
chrome now use developer.chrome.com/docs/extensions/* instead of developer.chrome.com/extensions/*

Co-authored-by: 祈緒ちゃん - Kiochan <sunxingchen@live.com>
2021-09-17 16:46:50 +09:00
Pedro Pontes
7c2889d93a chore: cherry-pick 8623d711677d from chromium (#30945)
* chore: cherry-pick 8623d711677d from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-09-16 18:13:22 -04:00
John Kleinschmidt
fa46c67bd3 feat: enable window controls overlay on macOS (#29253) (#30698)
* feat: enable windows control overlay on macOS

* address review feedback

* chore: address review feedback

* Address review feedback

* update doc per review

* only enable WCO when titleBarStyle is overlay

* Revert "only enable WCO when titleBarStyle is overlay"

This reverts commit 1b58b5b1fc.

* Add new titleBarOverlay property to manage feature

* spelling fix

* Update docs/api/frameless-window.md

Co-authored-by: Samuel Attard <sam@electronjs.org>

* Update shell/browser/api/electron_api_browser_window.cc

Co-authored-by: Samuel Attard <sam@electronjs.org>

* update per review feedback

Co-authored-by: Samuel Attard <sam@electronjs.org>
(cherry picked from commit 1f8a46c9c6)
2021-09-16 09:34:32 +09:00
trop[bot]
82679f4335 fix: always include pepper flash font file (#30969)
Co-authored-by: Micha Hanselmann <micha.hanselmann@gmail.com>
2021-09-16 09:30:11 +09:00
Sudowoodo Release Bot
75f366f4d0 Bump v13.4.0 2021-09-13 08:48:20 -07:00
Robo
1d531f29ee fix: crash when launching app with systemd v249 (#30893)
* fix: crash when launching app with systemd v249

Backports https://chromium-review.googlesource.com/c/chromium/src/+/3060345

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-09-09 14:34:57 -07:00
trop[bot]
f75b755f21 feat: add webContents.fromDevToolsTargetId() (#30731)
* feat: add webContents.fromDevToolsTargetId()

* refactor: avoid using FromOrCreate

Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>
2021-09-09 11:54:13 +02:00
trop[bot]
a2929226d2 Fix wrong code example for preload property (#30872)
The text mentions that `preload` should be a property of `webPreferences`, but the code example shows something else.

Co-authored-by: Christian Engel <chrispy@parastudios.de>
2021-09-08 15:20:59 +09:00
trop[bot]
6655694cc7 refactor: remove dead code in NeedsCompleteGpuInfoCollection (#30875)
Refs https://chromium-review.googlesource.com/c/chromium/src/+/1208362

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-09-08 15:20:10 +09:00
Robo
1ac4d27e22 fix: crash when navigating with render process reuse disabled (#30852) 2021-09-07 18:50:39 -07:00
trop[bot]
681d02a77d docs: Update windows info for auto-updater (#30870)
Squirrel.Mac can be served from a static host as well.

Co-authored-by: Finn Behrens <me@kloenk.dev>
2021-09-08 08:44:34 +09:00
trop[bot]
14eefd58c1 fix: show maximized frameless window (#30862)
* fix: show maximized frameless window

* test: show maximized transparent window

* fix: test using wrong bounds

BrowserWindow will be sized to the workArea when the Windows taskbar is
visible.

Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>
2021-09-08 08:42:44 +09:00
Pedro Pontes
2beec61a50 chore: cherry-pick 490c04beac from chromium (#30824)
Co-authored-by: Electron Bot <electron@github.com>
2021-09-08 08:24:18 +09:00
Pedro Pontes
e1ae36210b chore: cherry-pick d1eade9d39 from chromium (#30817)
* chore: cherry-pick d1eade9d39 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-09-07 08:48:58 +09:00
trop[bot]
e74eac61ae docs: updated webview tag documentation to accurately reflect preload behavior with asar archives (#30850)
Co-authored-by: ike <isaactaylor124@gmail.com>
2021-09-06 19:18:03 +09:00
trop[bot]
f8a5c3d8ee fix: remove CHECK_EQ for swapped RFH (#30834)
|old_host| may be nullptr if the previous RFH was shutdown.

Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>
2021-09-06 14:52:16 +09:00
Pedro Pontes
efd18b09ca chore: cherry-pick fbfd2557c2ab from v8 (#30821)
* chore: cherry-pick fbfd2557c2ab from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-09-06 14:48:26 +09:00
Pedro Pontes
cd062ac26e chore: cherry-pick d727013bb543 from chromium (#30815)
* chore: cherry-pick d727013bb543 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-09-06 14:48:01 +09:00
Cheng Zhao
a3e47196f7 chore: cherry-pick fix for 1230767 from chromium (#30638)
* chore: cherry-pick fix for 1230767 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-09-01 20:49:59 +09:00
trop[bot]
1930d972fc fix(linux): OpenURI portal support for shell.showItemInFolder() (#30782)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-09-01 20:49:29 +09:00
trop[bot]
0c4ac78dea docs: improve documentation about macOS entitlement usage security (#30779)
Co-authored-by: ComplexSpaces <complexspacescode@gmail.com>
2021-09-01 20:47:09 +09:00
Sudowoodo Release Bot
5771f3826a Bump v13.3.0 2021-08-31 12:08:57 -07:00
Cheng Zhao
a55bc6a870 chore: cherry-pick fix for 1231134 from chromium (#30637)
* chore: cherry-pick fix for 1231134 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-31 10:37:30 +09:00
Cheng Zhao
dcb311d5c9 chore: cherry-pick fix for 1228036 from v8 (#30639)
* chore: cherry-pick fix for 1228036 from v8

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-30 21:26:58 +09:00
Cheng Zhao
e5935eaff9 chore: cherry-pick fix for 1233564 from chromium (#30636)
* chore: cherry-pick fix for 1233564 from chromium

Protect HRTF database loader thread from access by different threads

This patch add a new mutex locker around the HRTF database loader
thread to ensure the safe exclusive access of the loader thread
and the HRTF database.

(cherry picked from commit 6811e850ee10847da16c4d5fdc0f845494586b65)

Bug: 1233564
Change-Id: Ie12b99ffe520d3747e34af387a37637a10aab38a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3068260
Auto-Submit: Hongchan Choi <hongchan@chromium.org>
Commit-Queue: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>

[modify] https://crrev.com/033f0bdcbe538c61f532e97b03cb9c092a94b413/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
[modify] https://crrev.com/033f0bdcbe538c61f532e97b03cb9c092a94b413/third_party/blink/renderer/platform/audio/hrtf_database_loader.h

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-30 21:26:27 +09:00
Cheng Zhao
d927f1dc02 chore: cherry-pick fix for 1234009 from chromium (#30635)
* chore: cherry-pick for for 1234009 from chromium

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2021-08-30 19:34:56 +09:00
Jeremy Rose
ca1cae64d9 fix: remove ipc wrapper for nativeImage.createThumbnailFromPath (#30736) 2021-08-30 19:32:21 +09:00
Sudowoodo Release Bot
69df216a9c Bump v13.2.3 2021-08-27 10:18:31 -07:00
trop[bot]
2917eb1589 docs: explain the null webContents case in permission checks (#30686)
* docs: explain the null webContents case in permission checks

* Update docs/api/session.md

Co-authored-by: Erick Zhao <erick@hotmail.ca>

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Samuel Attard <sam@electronjs.org>
Co-authored-by: Erick Zhao <erick@hotmail.ca>
2021-08-26 15:47:37 +09:00
trop[bot]
ec282ff385 fix: titlebar and buttons state under simple fullscreen (#30706)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2021-08-26 15:47:05 +09:00
trop[bot]
5d98e5e78a fix: crash when using TouchBarScrubber arrow button (#30680)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-08-25 10:06:12 +09:00
90 changed files with 7866 additions and 195 deletions

View File

@@ -1 +1 @@
13.2.2
13.5.0

View File

@@ -66,8 +66,11 @@ static_library("chrome") {
"//chrome/browser/extensions/global_shortcut_listener_win.cc",
"//chrome/browser/extensions/global_shortcut_listener_win.h",
"//chrome/browser/icon_loader_win.cc",
"//chrome/browser/ui/frame/window_frame_util.h",
"//chrome/browser/ui/view_ids.h",
"//chrome/browser/win/chrome_process_finder.cc",
"//chrome/browser/win/chrome_process_finder.h",
"//chrome/browser/win/titlebar_config.h",
"//chrome/child/v8_crashpad_support_win.cc",
"//chrome/child/v8_crashpad_support_win.h",
]
@@ -347,17 +350,13 @@ source_set("plugins") {
sources += [
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
]
if (enable_pdf_viewer) {
sources += [
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
]
if (enable_pdf_viewer) {
deps += [ "//components/pdf/renderer" ]
}
deps += [ "//components/pdf/renderer" ]
}
deps += [
"//components/strings",

View File

@@ -43,7 +43,7 @@ The installer generated with Squirrel will create a shortcut icon with an
same ID for your app with `app.setAppUserModelId` API, otherwise Windows will
not be able to pin your app properly in task bar.
Unlike Squirrel.Mac, Windows can host updates on S3 or any other static file host.
Like Squirrel.Mac, Windows can host updates on S3 or any other static file host.
You can read the documents of [Squirrel.Windows][squirrel-windows] to get more details
about how Squirrel.Windows works.

View File

@@ -213,16 +213,13 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
* `followWindow` - The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.
* `active` - The backdrop should always appear active.
* `inactive` - The backdrop should always appear inactive.
* `titleBarStyle` String (optional) - The style of window title bar.
* `titleBarStyle` String (optional) _macOS_ _Windows_ - The style of window title bar.
Default is `default`. Possible values are:
* `default` - Results in the standard gray opaque Mac title
bar.
* `hidden` - Results in a hidden title bar and a full size content window, yet
the title bar still has the standard window controls ("traffic lights") in
the top left.
* `hiddenInset` - Results in a hidden title bar with an alternative look
* `default` - Results in the standard title bar for macOS or Windows respectively.
* `hidden` - Results in a hidden title bar and a full size content window. On macOS, the window still has the standard window controls (“traffic lights”) in the top left. On Windows, when combined with `titleBarOverlay: true` it will activate the Window Controls Overlay (see `titleBarOverlay` for more information), otherwise no window controls will be shown.
* `hiddenInset` - Only on macOS, results in a hidden title bar with an alternative look
where the traffic light buttons are slightly more inset from the window edge.
* `customButtonsOnHover` - Results in a hidden title bar and a full size
* `customButtonsOnHover` - Only on macOS, results in a hidden title bar and a full size
content window, the traffic light buttons will display when being hovered
over in the top left of the window. **Note:** This option is currently
experimental.
@@ -403,6 +400,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
contain the layout of the document—without requiring scrolling. Enabling
this will cause the `preferred-size-changed` event to be emitted on the
`WebContents` when the preferred size changes. Default is `false`.
* `titleBarOverlay` [OverlayOptions](structures/overlay-options.md) | Boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`. On Windows, the [OverlayOptions](structures/overlay-options.md) can be used instead of a boolean to specify colors for the overlay.
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
@@ -985,7 +983,7 @@ the player itself we would call this function with arguments of 16/9 and
are within the content view--only that they exist. Sum any extra width and
height areas you have within the overall content view.
The aspect ratio is not respected when window is resized programmingly with
The aspect ratio is not respected when window is resized programmatically with
APIs like `win.setSize`.
#### `win.setBackgroundColor(backgroundColor)`
@@ -1809,3 +1807,5 @@ removed in future Electron releases.
[window-levels]: https://developer.apple.com/documentation/appkit/nswindow/level
[chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables

View File

@@ -18,17 +18,17 @@ const win = new BrowserWindow({ width: 800, height: 600, frame: false })
win.show()
```
### Alternatives on macOS
### Alternatives
There's an alternative way to specify a chromeless window.
There's an alternative way to specify a chromeless window on macOS and Windows.
Instead of setting `frame` to `false` which disables both the titlebar and window controls,
you may want to have the title bar hidden and your content extend to the full window size,
yet still preserve the window controls ("traffic lights") for standard window actions.
yet still preserve the window controls ("traffic lights" on macOS) for standard window actions.
You can do so by specifying the `titleBarStyle` option:
#### `hidden`
Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls (“traffic lights”) in the top left.
Results in a hidden title bar and a full size content window. On macOS, the title bar still has the standard window controls (“traffic lights”) in the top left.
```javascript
const { BrowserWindow } = require('electron')
@@ -36,6 +36,8 @@ const win = new BrowserWindow({ titleBarStyle: 'hidden' })
win.show()
```
### Alternatives on macOS
#### `hiddenInset`
Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.
@@ -61,6 +63,35 @@ const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: fa
win.show()
```
## Windows Control Overlay
When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS, using one of the `titleBarStyle`s as described above so
that the traffic lights are visible, or using `titleBarStyle: hidden` on Windows, you can access the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and
[CSS Environment Variables][overlay-css-env-vars] by setting the `titleBarOverlay` option to true. Specifying `true` will result in an overlay with default system colors.
On Windows, you can also specify the color of the overlay and its symbols by setting `titleBarOverlay` to an object with the options `color` and `symbolColor`. If an option is not specified, the color will default to its system color for the window control buttons:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
titleBarStyle: 'hidden',
titleBarOverlay: true
})
win.show()
```
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
titleBarStyle: 'hidden',
titleBarOverlay: {
color: '#2f3241',
symbolColor: '#74b1be'
}
})
win.show()
```
## Transparent window
By setting the `transparent` option to `true`, you can also make the frameless
@@ -186,3 +217,5 @@ behave correctly on all platforms you should never use a custom context menu on
draggable areas.
[ignore-mouse-events]: browser-window.md#winsetignoremouseeventsignore-options
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables

View File

@@ -531,7 +531,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
#### `ses.setPermissionCheckHandler(handler)`
* `handler` Function\<Boolean> | null
* `webContents` ([WebContents](web-contents.md) | null) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. Cross origin sub frames making permission checks will pass a `null` webContents to this handler. You should use `embeddingOrigin` and `requestingOrigin` to determine what origin the owning frame and the requesting frame are on respectively.
* `webContents` ([WebContents](web-contents.md) | null) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. All cross origin sub frames making permission checks will pass a `null` webContents to this handler, while certain other permission checks such as `notifications` checks will always pass `null`. You should use `embeddingOrigin` and `requestingOrigin` to determine what origin the owning frame and the requesting frame are on respectively.
* `permission` String - Type of permission check. Valid values are `midiSysex`, `notifications`, `geolocation`, `media`,`mediaKeySystem`,`midi`, `pointerLock`, `fullscreen`, `openExternal`, or `serial`.
* `requestingOrigin` String - The origin URL of the permission check
* `details` Object - Some properties are only available on certain permission types.

View File

@@ -0,0 +1,4 @@
# OverlayOptions Object
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.

View File

@@ -14,7 +14,7 @@ Process: [Main](../glossary.md#main-process)
* `highlightedIndex` Integer - The index of the item the user touched.
* `selectedStyle` String (optional) - Selected item style. Can be `background`, `outline` or `none`. Defaults to `none`.
* `overlayStyle` String (optional) - Selected overlay item style. Can be `background`, `outline` or `none`. Defaults to `none`.
* `showArrowButtons` Boolean (optional) - Defaults to `false`.
* `showArrowButtons` Boolean (optional) - Whether to show arrow buttons. Defaults to `false` and is only shown if `items` is non-empty.
* `mode` String (optional) - Can be `fixed` or `free`. The default is `free`.
* `continuous` Boolean (optional) - Defaults to `true`.

View File

@@ -45,6 +45,26 @@ returns `null`.
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
`undefined` if there is no WebContents associated with the given ID.
### `webContents.fromDevToolsTargetId(targetId)`
* `targetId` String - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.
Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or
`undefined` if there is no WebContents associated with the given TargetID.
When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/),
it can be useful to lookup a WebContents instance based on its assigned TargetID.
```js
async function lookupTargetId (browserWindow) {
const wc = browserWindow.webContents
await wc.debugger.attach('1.3')
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
const { targetId } = targetInfo
const targetWebContents = await webContents.fromDevToolsTargetId(targetId)
}
```
## Class: WebContents
> Render and control the contents of a BrowserWindow instance.

View File

@@ -151,12 +151,16 @@ browser plugins. Plugins are disabled by default.
### `preload`
```html
<!-- from a file -->
<webview src="https://www.github.com/" preload="./test.js"></webview>
<!-- or if you want to load from an asar archive -->
<webview src="https://www.github.com/" preload="./app.asar/test.js"></webview>
```
A `String` that specifies a script that will be loaded before other scripts run in the guest
page. The protocol of script's URL must be either `file:` or `asar:`, because it
will be loaded by `require` in guest page under the hood.
page. The protocol of script's URL must be `file:` (even when using `asar:` archives) because
it will be loaded by Node's `require` under the hood, which treats `asar:` archives as virtual
directories.
When the guest page doesn't have node integration this script will still have
access to all Node APIs, but global objects injected by Node will be deleted

View File

@@ -88,14 +88,15 @@ without meaning any harm:
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
</dict>
</plist>
```
Note that up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
as well. However, it should not be used anymore if it can be avoided.
To see all of this in action, check out Electron Fiddle's source code,
[especially its `electron-forge` configuration
file](https://github.com/electron/fiddle/blob/master/forge.config.js).
@@ -165,14 +166,15 @@ without meaning any harm:
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
</dict>
</plist>
```
Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
as well. However, it should not be used anymore if it can be avoided.
## Mac App Store
See the [Mac App Store Guide].

View File

@@ -148,7 +148,9 @@ A preload script can be attached to the main process in the `BrowserWindow` cons
const { BrowserWindow } = require('electron')
//...
const win = new BrowserWindow({
preload: 'path/to/preload.js'
webPreferences: {
preload: 'path/to/preload.js'
}
})
//...
```

View File

@@ -1,5 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<!-- Windows Caption Buttons -->
<message name="IDS_APP_ACCNAME_CLOSE" desc="The accessible name for the Close button.">
Close
</message>
<message name="IDS_APP_ACCNAME_MINIMIZE" desc="The accessible name for the Minimize button.">
Minimize
</message>
<message name="IDS_APP_ACCNAME_MAXIMIZE" desc="The accessible name for the Maximize button.">
Maximize
</message>
<message name="IDS_APP_ACCNAME_RESTORE" desc="The accessible name for the Restore button.">
Restore
</message>
<!-- Printing Service -->
<message name="IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME" desc="The name of the utility process used for printing conversions.">
Printing Service

View File

@@ -101,6 +101,7 @@ auto_filenames = {
"docs/api/structures/new-window-web-contents-event.md",
"docs/api/structures/notification-action.md",
"docs/api/structures/notification-response.md",
"docs/api/structures/overlay-options.md",
"docs/api/structures/point.md",
"docs/api/structures/post-body.md",
"docs/api/structures/printer-info.md",

View File

@@ -90,6 +90,10 @@ filenames = {
"shell/browser/ui/views/electron_views_delegate_win.cc",
"shell/browser/ui/views/win_frame_view.cc",
"shell/browser/ui/views/win_frame_view.h",
"shell/browser/ui/views/win_caption_button.cc",
"shell/browser/ui/views/win_caption_button.h",
"shell/browser/ui/views/win_caption_button_container.cc",
"shell/browser/ui/views/win_caption_button_container.h",
"shell/browser/ui/win/dialog_thread.cc",
"shell/browser/ui/win/dialog_thread.h",
"shell/browser/ui/win/electron_desktop_native_widget_aura.cc",

View File

@@ -723,6 +723,10 @@ export function fromId (id: string) {
return binding.fromId(id);
}
export function fromDevToolsTargetId (targetId: string) {
return binding.fromDevToolsTargetId(targetId);
}
export function getFocusedWebContents () {
let focused = null;
for (const contents of binding.getAllWebContents()) {

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';
@@ -119,7 +119,3 @@ ipcMainInternal.on(IPC_MESSAGES.NAVIGATION_CONTROLLER_LENGTH, 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

@@ -104,10 +104,14 @@ const warnAboutInsecureResources = function () {
return;
}
const isLocal = (url: URL): boolean =>
['localhost', '127.0.0.1', '[::1]', ''].includes(url.hostname);
const isInsecure = (url: URL): boolean =>
['http:', 'ftp:'].includes(url.protocol) && !isLocal(url);
const resources = window.performance
.getEntriesByType('resource')
.filter(({ name }) => /^(http|ftp):/gi.test(name || ''))
.filter(({ name }) => new URL(name).hostname !== 'localhost')
.filter(({ name }) => isInsecure(new URL(name)))
.map(({ name }) => `- ${name}`)
.join('\n');

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "13.2.2",
"version": "13.5.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 @@
cherry-pick-d8cb996.patch
cherry-pick-1fb846c.patch
cherry-pick-72473550f6ff.patch
webgl_make_unsuccessful_links_fail_subsequent_draw_calls.patch

View File

@@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jamie Madill <jmadill@chromium.org>
Date: Wed, 1 Sep 2021 12:17:26 -0400
Subject: D3D11: Fix overflow in GenerateInitialTextureData.
Our use of unchecked math was causing OOB accesses with very large
textures. Unfortunately it's not easy to make a passing test that
reproduces this OOB access.
Bug: chromium:1241036
Change-Id: Icd2749f5b3116bb51390ce769fef22c49a11f307
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3136733
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
(cherry picked from commit 794b13ce9f874d472729ebd69897bc7ab9340a4b)
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3149277
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index 3915a89de6fd161fa72519d4b9b6e82db68c6c66..6d721bd6e72d21454a868965993d930fe138b58c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -2181,28 +2181,35 @@ angle::Result GenerateInitialTextureData(
const d3d11::DXGIFormatSize &dxgiFormatInfo =
d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
- unsigned int rowPitch = dxgiFormatInfo.pixelBytes * width;
- unsigned int depthPitch = rowPitch * height;
- unsigned int maxImageSize = depthPitch * depth;
+ using CheckedSize = angle::CheckedNumeric<size_t>;
+ CheckedSize rowPitch = CheckedSize(dxgiFormatInfo.pixelBytes) * CheckedSize(width);
+ CheckedSize depthPitch = rowPitch * CheckedSize(height);
+ CheckedSize maxImageSize = depthPitch * CheckedSize(depth);
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_GL_ALLOC(context11, maxImageSize.IsValid());
angle::MemoryBuffer *scratchBuffer = nullptr;
- ANGLE_CHECK_GL_ALLOC(GetImplAs<Context11>(context),
- context->getScratchBuffer(maxImageSize, &scratchBuffer));
+ ANGLE_CHECK_GL_ALLOC(context11,
+ context->getScratchBuffer(maxImageSize.ValueOrDie(), &scratchBuffer));
- d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(), rowPitch,
- depthPitch);
+ d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(),
+ rowPitch.ValueOrDie(), depthPitch.ValueOrDie());
for (unsigned int i = 0; i < mipLevels; i++)
{
unsigned int mipWidth = std::max(width >> i, 1U);
unsigned int mipHeight = std::max(height >> i, 1U);
- unsigned int mipRowPitch = dxgiFormatInfo.pixelBytes * mipWidth;
- unsigned int mipDepthPitch = mipRowPitch * mipHeight;
+ using CheckedUINT = angle::CheckedNumeric<UINT>;
+ CheckedUINT mipRowPitch = CheckedUINT(dxgiFormatInfo.pixelBytes) * CheckedUINT(mipWidth);
+ CheckedUINT mipDepthPitch = mipRowPitch * CheckedUINT(mipHeight);
+
+ ANGLE_CHECK_GL_ALLOC(context11, mipRowPitch.IsValid() && mipDepthPitch.IsValid());
outSubresourceData->at(i).pSysMem = scratchBuffer->data();
- outSubresourceData->at(i).SysMemPitch = mipRowPitch;
- outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch;
+ outSubresourceData->at(i).SysMemPitch = mipRowPitch.ValueOrDie();
+ outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch.ValueOrDie();
}
return angle::Result::Continue;

View File

@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jamie Madill <jmadill@chromium.org>
Date: Fri, 3 Sep 2021 09:34:10 -0400
Subject: WebGL: Make unsuccessful links fail subsequent draw calls.
This protects against incomplete state updates during a failed
link call that can interfere with draw calls.
Bug: angleproject:6358
Bug: chromium:1241123
Change-Id: Ie892654c3a58c69d6e35ba3c41758ab6269d8193
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3140496
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3152556
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 412b9aa0f1d75c40ce02522589c53e943d049228..7826233f206b2ae7b926cd2564c887c726b79930 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -3958,6 +3958,12 @@ const char *ValidateDrawStates(const Context *context)
{
return kVertexBufferBoundForTransformFeedback;
}
+
+ // Validate that we are rendering with a linked program.
+ if (!program->isLinked())
+ {
+ return kProgramNotLinked;
+ }
}
}

View File

@@ -125,3 +125,24 @@ cherry-pick-ac9dc1235e28.patch
cherry-pick-4ce2abc17078.patch
cherry-pick-e2123a8e0943.patch
cherry-pick-1227933.patch
cherry-pick-1230767.patch
cherry-pick-1231134.patch
cherry-pick-1233564.patch
cherry-pick-1234009.patch
attach_to_correct_frame_in.patch
merge_m92_speculative_fix_for_crash_in.patch
cherry-pick-d727013bb543.patch
pa_make_getusablesize_handle_nullptr_gracefully.patch
dpwas_window_control_overlay_api_values_account_for_page_zoom_factor.patch
reland_make_clientview_a_child_of_the_nonclientframeview.patch
content-visibility_force_range_base_extent_when_computing_visual.patch
cherry-pick-6215793f008f.patch
cherry-pick-6048fcd52f42.patch
contentindex_add_origin_checks_to_mojo_methods.patch
m93_indexeddb_add_browser-side_checks_for_committing_transactions.patch
m93_indexeddb_don_t_reportbadmessage_for_commit_calls.patch
cherry-pick-8623d711677d.patch
cherry-pick-ddc4cf156505.patch
skip_webgl_conformance_programs_program-test_html_on_all_platforms.patch
linux_sandbox_update_syscall_numbers_for_all_platforms.patch
linux_sandbox_return_enosys_for_clone3.patch

View File

@@ -0,0 +1,353 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kevin McNee <mcnee@chromium.org>
Date: Fri, 4 Jun 2021 22:52:55 +0000
Subject: Attach to correct frame in
WebContentsImplBrowserTest.AttachNestedInnerWebContents
This test attempts to attach an inner contents at the outer contents'
main frame which is incorrect. This appears to have been done for
testing convenience rather than being part of the repro case based on
the comments on the CL that introduced it [1]. Indeed, the inner
contents don't render with the test as is.
We adjust the test, enforce the assumption of a subframe in
|AttachInnerWebContents|, and remove a bail-out from a
WebContentsObserver that was confused by this.
Furthermore, in the corrected version of the test, we experience a bad
cast on Mac and Android, but not Aura, as replacing the platform
WebContentsView does not necessarily destroy the platform
RenderWidgetHostView which is later assumed to be a
RenderWidgetHostViewChildFrame. We now perform that destruction if
needed.
[1] https://chromium-review.googlesource.com/c/chromium/src/+/1498458/6#message-c6af19c82b27d707044a5c1cbbecf48f491bc1bd
Bug: 1133361, 1208438, 1216595
Change-Id: I4de002ab25726f1c05044c764156b69a15bdde41
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2895924
Commit-Queue: Kevin McNee <mcnee@chromium.org>
Reviewed-by: Chris Hamilton <chrisha@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: W. James MacLean <wjmaclean@chromium.org>
Cr-Commit-Position: refs/heads/master@{#889495}
diff --git a/components/performance_manager/performance_manager_tab_helper.cc b/components/performance_manager/performance_manager_tab_helper.cc
index 7b2672713e705060ea3d2100492f29d6aa4ad35b..7463423c065e0b74b65b41c2bcf80e9b2025d574 100644
--- a/components/performance_manager/performance_manager_tab_helper.cc
+++ b/components/performance_manager/performance_manager_tab_helper.cc
@@ -394,16 +394,7 @@ void PerformanceManagerTabHelper::InnerWebContentsAttached(
// severed.
}
DCHECK_NE(PageNode::OpenedType::kInvalid, opened_type);
- if (!frame) {
- DCHECK(!render_frame_host->IsRenderFrameCreated());
- DCHECK(!inner_web_contents->IsPortal());
- // TODO(crbug.com/1133361):
- // WebContentsImplBrowserTest.AttachNestedInnerWebContents calls
- // WebContents::AttachInnerWebContents without creating RenderFrame.
- // Removing this conditional once either the test is fixed or this function
- // is adjusted to handle the case without the render frame.
- return;
- }
+ DCHECK(frame);
PerformanceManagerImpl::CallOnGraphImpl(
FROM_HERE, base::BindOnce(&PageNodeImpl::SetOpenerFrameNodeAndOpenedType,
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 4af3384ebbd000926a1f7606511fd6b94dc8aabe..29571b8ab59518fe93e35c1cc7f113e65ed39420 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -5714,11 +5714,10 @@ void RenderFrameHostImpl::AdoptPortal(const blink::PortalToken& portal_token,
// |frame_sink_id| should be set to the associated frame. See
// https://crbug.com/966119 for details.
- viz::FrameSinkId frame_sink_id =
- static_cast<RenderWidgetHostViewBase*>(proxy_host->frame_tree_node()
- ->render_manager()
- ->GetRenderWidgetHostView())
- ->GetFrameSinkId();
+ viz::FrameSinkId frame_sink_id = proxy_host->frame_tree_node()
+ ->render_manager()
+ ->GetRenderWidgetHostView()
+ ->GetFrameSinkId();
proxy_host->GetAssociatedRemoteFrame()->SetFrameSinkId(frame_sink_id);
std::move(callback).Run(
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 74f9fe3a0a0de20d48bc8b2d397109381ea66481..ce524db677e36ca60f3f9be5493d974975eb82c5 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -43,6 +43,8 @@
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/content_navigation_policy.h"
@@ -282,9 +284,11 @@ void RenderFrameHostManager::InitChild(
/*renderer_initiated_creation=*/false));
}
-RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const {
+RenderWidgetHostViewBase* RenderFrameHostManager::GetRenderWidgetHostView()
+ const {
if (render_frame_host_)
- return render_frame_host_->GetView();
+ return static_cast<RenderWidgetHostViewBase*>(
+ render_frame_host_->GetView());
return nullptr;
}
@@ -2793,8 +2797,9 @@ void RenderFrameHostManager::SwapOuterDelegateFrame(
}
void RenderFrameHostManager::SetRWHViewForInnerContents(
- RenderWidgetHostView* child_rwhv) {
+ RenderWidgetHostViewChildFrame* child_rwhv) {
DCHECK(IsMainFrameForInnerDelegate());
+ DCHECK(GetProxyToOuterDelegate());
GetProxyToOuterDelegate()->SetChildRWHView(child_rwhv, nullptr);
}
@@ -3400,8 +3405,11 @@ void RenderFrameHostManager::CommitPending(
// Note: We do this after unloading the old RFH because that may create
// the proxy we're looking for.
RenderFrameProxyHost* proxy_to_parent = GetProxyToParent();
- if (proxy_to_parent)
- proxy_to_parent->SetChildRWHView(new_view, old_size ? &*old_size : nullptr);
+ if (proxy_to_parent) {
+ proxy_to_parent->SetChildRWHView(
+ static_cast<RenderWidgetHostViewChildFrame*>(new_view),
+ old_size ? &*old_size : nullptr);
+ }
if (render_frame_host_->is_local_root()) {
// RenderFrames are created with a hidden RenderWidgetHost. When navigation
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h
index f4ff686226002e926190829a192993cb92ed0a3e..6ca00c16ac6031bb0357cf8a43e6b77e63455807 100644
--- a/content/browser/renderer_host/render_frame_host_manager.h
+++ b/content/browser/renderer_host/render_frame_host_manager.h
@@ -44,7 +44,8 @@ class RenderFrameHostManagerTest;
class RenderFrameProxyHost;
class RenderViewHost;
class RenderViewHostImpl;
-class RenderWidgetHostView;
+class RenderWidgetHostViewBase;
+class RenderWidgetHostViewChildFrame;
class TestWebContents;
using PageBroadcastMethodCallback =
@@ -196,7 +197,7 @@ class CONTENT_EXPORT RenderFrameHostManager
// Returns the view associated with the current RenderViewHost, or null if
// there is no current one.
- RenderWidgetHostView* GetRenderWidgetHostView() const;
+ RenderWidgetHostViewBase* GetRenderWidgetHostView() const;
// Returns whether this manager is a main frame and belongs to a FrameTreeNode
// that belongs to an inner WebContents.
@@ -453,7 +454,7 @@ class CONTENT_EXPORT RenderFrameHostManager
// Sets the child RenderWidgetHostView for this frame, which must be part of
// an inner WebContents.
- void SetRWHViewForInnerContents(RenderWidgetHostView* child_rwhv);
+ void SetRWHViewForInnerContents(RenderWidgetHostViewChildFrame* child_rwhv);
// Returns the number of RenderFrameProxyHosts for this frame.
size_t GetProxyCount();
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc
index 54fa3b7a788de7f80a096badeac11a2b6f9b9771..343ea5e1821f55cdea16ae93a055302016d2198f 100644
--- a/content/browser/renderer_host/render_frame_proxy_host.cc
+++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -214,10 +214,9 @@ RenderFrameProxyHost::~RenderFrameProxyHost() {
}
void RenderFrameProxyHost::SetChildRWHView(
- RenderWidgetHostView* view,
+ RenderWidgetHostViewChildFrame* view,
const gfx::Size* initial_frame_size) {
- cross_process_frame_connector_->SetView(
- static_cast<RenderWidgetHostViewChildFrame*>(view));
+ cross_process_frame_connector_->SetView(view);
if (initial_frame_size)
cross_process_frame_connector_->SetLocalFrameSize(*initial_frame_size);
}
@@ -226,13 +225,6 @@ RenderViewHostImpl* RenderFrameProxyHost::GetRenderViewHost() {
return render_view_host_.get();
}
-RenderWidgetHostView* RenderFrameProxyHost::GetRenderWidgetHostView() {
- return frame_tree_node_->parent()
- ->frame_tree_node()
- ->render_manager()
- ->GetRenderWidgetHostView();
-}
-
bool RenderFrameProxyHost::Send(IPC::Message* msg) {
return GetAgentSchedulingGroup().Send(msg);
}
diff --git a/content/browser/renderer_host/render_frame_proxy_host.h b/content/browser/renderer_host/render_frame_proxy_host.h
index cd6c90f3b7f77de0df9de1228628cde8c4333b98..e414a1665d43cc773850b23b6fcd568f9baa494a 100644
--- a/content/browser/renderer_host/render_frame_proxy_host.h
+++ b/content/browser/renderer_host/render_frame_proxy_host.h
@@ -36,7 +36,7 @@ class CrossProcessFrameConnector;
class FrameTreeNode;
class RenderProcessHost;
class RenderViewHostImpl;
-class RenderWidgetHostView;
+class RenderWidgetHostViewChildFrame;
// When a page's frames are rendered by multiple processes, each renderer has a
// full copy of the frame tree. It has full RenderFrames for the frames it is
@@ -121,11 +121,10 @@ class CONTENT_EXPORT RenderFrameProxyHost
// the child frame will wait until the CrossProcessFrameConnector
// receives its size from the parent via FrameHostMsg_UpdateResizeParams
// before it begins parsing the content.
- void SetChildRWHView(RenderWidgetHostView* view,
+ void SetChildRWHView(RenderWidgetHostViewChildFrame* view,
const gfx::Size* initial_frame_size);
RenderViewHostImpl* GetRenderViewHost();
- RenderWidgetHostView* GetRenderWidgetHostView();
// IPC::Sender
bool Send(IPC::Message* msg) override;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 14eadcb063b2b9d4734db3d6160f320ab26ffe04..ca51a8a45570fafc0dfe2b400cbb7172a9be632d 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2164,6 +2164,7 @@ void WebContentsImpl::AttachInnerWebContents(
auto* render_frame_host_impl =
static_cast<RenderFrameHostImpl*>(render_frame_host);
DCHECK_EQ(&frame_tree_, render_frame_host_impl->frame_tree());
+ DCHECK(render_frame_host_impl->GetParent());
// Mark |render_frame_host_impl| as outer delegate frame.
render_frame_host_impl->SetIsOuterDelegateFrame(true);
@@ -2184,6 +2185,16 @@ void WebContentsImpl::AttachInnerWebContents(
GetContentClient()->browser()->GetWebContentsViewDelegate(
inner_web_contents_impl),
&inner_web_contents_impl->render_view_host_delegate_view_);
+ // On platforms where destroying the WebContents' view does not also destroy
+ // the platform RenderWidgetHostView, we need to destroy it if it exists.
+ // TODO(mcnee): Should all platforms' WebContentsView destroy the platform
+ // RWHV?
+ if (RenderWidgetHostViewBase* prev_rwhv =
+ inner_render_manager->GetRenderWidgetHostView()) {
+ if (!prev_rwhv->IsRenderWidgetHostViewChildFrame()) {
+ prev_rwhv->Destroy();
+ }
+ }
// When the WebContents being initialized has an opener, the browser side
// Render{View,Frame}Host must be initialized and the RenderWidgetHostView
@@ -2330,8 +2341,11 @@ void WebContentsImpl::ReattachToOuterWebContentsFrame() {
auto* render_manager = GetRenderManager();
auto* parent_frame =
node_.OuterContentsFrameTreeNode()->current_frame_host()->GetParent();
+ auto* child_rwhv = render_manager->GetRenderWidgetHostView();
+ DCHECK(child_rwhv);
+ DCHECK(child_rwhv->IsRenderWidgetHostViewChildFrame());
render_manager->SetRWHViewForInnerContents(
- render_manager->GetRenderWidgetHostView());
+ static_cast<RenderWidgetHostViewChildFrame*>(child_rwhv));
RecursivelyRegisterFrameSinkIds();
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index cd32d333d2810fde1fc25c80b2bc443b04568c8d..2e75cbf168dbfa48d9f094ed84398197fd0487aa 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -3550,44 +3550,70 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, SetVisibilityBeforeLoad) {
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
AttachNestedInnerWebContents) {
ASSERT_TRUE(embedded_test_server()->Start());
- GURL main_url(embedded_test_server()->GetURL(
+ const GURL url_a(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a)"));
- EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
+ const GURL url_b(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(b)"));
+ ASSERT_TRUE(NavigateToURL(shell(), url_a));
auto* root_web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
- FrameTreeNode* root = root_web_contents->GetFrameTree()->root();
- ASSERT_EQ(1u, root->child_count());
- FrameTreeNode* child_to_replace = root->child_at(0);
- auto* child_to_replace_rfh = child_to_replace->current_frame_host();
+ // Create a child WebContents but don't attach it to the root contents yet.
WebContents::CreateParams inner_params(
root_web_contents->GetBrowserContext());
-
std::unique_ptr<WebContents> child_contents_ptr =
WebContents::Create(inner_params);
- auto* child_rfh =
- static_cast<RenderFrameHostImpl*>(child_contents_ptr->GetMainFrame());
+ WebContents* child_contents = child_contents_ptr.get();
+ // Navigate the child to a page with a subframe, at which we will attach the
+ // grandchild.
+ ASSERT_TRUE(NavigateToURL(child_contents, url_b));
+ // Create and attach grandchild to child.
std::unique_ptr<WebContents> grandchild_contents_ptr =
WebContents::Create(inner_params);
-
- // Attach grandchild to child.
- child_contents_ptr->AttachInnerWebContents(
- std::move(grandchild_contents_ptr), child_rfh, false /* is_full_page */);
+ WebContents* grandchild_contents = grandchild_contents_ptr.get();
+ RenderFrameHost* child_contents_subframe =
+ ChildFrameAt(child_contents->GetMainFrame(), 0);
+ ASSERT_TRUE(child_contents_subframe);
+ child_contents->AttachInnerWebContents(std::move(grandchild_contents_ptr),
+ child_contents_subframe,
+ false /* is_full_page */);
// At this point the child hasn't been attached to the root.
- EXPECT_EQ(1U, root_web_contents->GetInputEventRouter()
- ->RegisteredViewCountForTesting());
+ {
+ auto* root_view = static_cast<RenderWidgetHostViewBase*>(
+ root_web_contents->GetRenderWidgetHostView());
+ ASSERT_TRUE(root_view);
+ auto* root_event_router = root_web_contents->GetInputEventRouter();
+ EXPECT_EQ(1U, root_event_router->RegisteredViewCountForTesting());
+ EXPECT_TRUE(root_event_router->IsViewInMap(root_view));
+ }
// Attach child+grandchild subtree to root.
+ RenderFrameHost* root_contents_subframe =
+ ChildFrameAt(root_web_contents->GetMainFrame(), 0);
+ ASSERT_TRUE(root_contents_subframe);
root_web_contents->AttachInnerWebContents(std::move(child_contents_ptr),
- child_to_replace_rfh,
+ root_contents_subframe,
false /* is_full_page */);
// Verify views registered for both child and grandchild.
- EXPECT_EQ(3U, root_web_contents->GetInputEventRouter()
- ->RegisteredViewCountForTesting());
+ {
+ auto* root_view = static_cast<RenderWidgetHostViewBase*>(
+ root_web_contents->GetRenderWidgetHostView());
+ auto* child_view = static_cast<RenderWidgetHostViewBase*>(
+ child_contents->GetRenderWidgetHostView());
+ auto* grandchild_view = static_cast<RenderWidgetHostViewBase*>(
+ grandchild_contents->GetRenderWidgetHostView());
+ ASSERT_TRUE(root_view);
+ ASSERT_TRUE(child_view);
+ ASSERT_TRUE(grandchild_view);
+ auto* root_event_router = root_web_contents->GetInputEventRouter();
+ EXPECT_EQ(3U, root_event_router->RegisteredViewCountForTesting());
+ EXPECT_TRUE(root_event_router->IsViewInMap(root_view));
+ EXPECT_TRUE(root_event_router->IsViewInMap(child_view));
+ EXPECT_TRUE(root_event_router->IsViewInMap(grandchild_view));
+ }
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,

View File

@@ -0,0 +1,115 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Harald Alvestrand <hta@chromium.org>
Date: Tue, 10 Aug 2021 10:49:27 +0000
Subject: Protect candidate better from garbage collection during negotiation.
Includes a test that was reliably observed to produce an UAF on Linux
when compiled with ASAN before the fix.
Bug: chromium:1230767
Change-Id: I02dd29332a6d00790dcace41b6584b96413ef6f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3057049
Reviewed-by: Florent Castelli <orphis@chromium.org>
Commit-Queue: Harald Alvestrand <hta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#910244}
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index 9265e14be8f86d2f1a2d888a789c121ddb514e88..84a8825ec87bcd9f1c0d7c502034bfbc3bfcafd1 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -1629,7 +1629,8 @@ void RTCPeerConnectionHandler::AddICECandidate(
handler_weak_ptr = weak_factory_.GetWeakPtr(),
tracker_weak_ptr =
WrapCrossThreadWeakPersistent(peer_connection_tracker_.Get()),
- candidate, persistent_request = WrapCrossThreadPersistent(request),
+ persistent_candidate = WrapCrossThreadPersistent(candidate),
+ persistent_request = WrapCrossThreadPersistent(request),
callback_on_task_runner =
std::move(callback_on_task_runner)](webrtc::RTCError result) {
// Grab a snapshot of all the session descriptions. AddIceCandidate may
@@ -1657,7 +1658,7 @@ void RTCPeerConnectionHandler::AddICECandidate(
std::move(current_local_description),
std::move(pending_remote_description),
std::move(current_remote_description),
- WrapCrossThreadPersistent(candidate), std::move(result),
+ std::move(persistent_candidate), std::move(result),
std::move(persistent_request)));
});
}
diff --git a/third_party/blink/web_tests/fast/peerconnection/poc-123067.html b/third_party/blink/web_tests/fast/peerconnection/poc-123067.html
new file mode 100644
index 0000000000000000000000000000000000000000..ff169f1d1e1333b9ccfcae7eaa833ec645779218
--- /dev/null
+++ b/third_party/blink/web_tests/fast/peerconnection/poc-123067.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ <script src="../../resources/gc.js"></script>
+ </head>
+ <body>
+ <script>
+ 'use strict';
+ promise_test(async t => {
+ const var_caller_1 = new RTCPeerConnection();
+ const var_callee_1 = new RTCPeerConnection();
+ var_caller_1.addTransceiver('audio');
+ const var_prom_1 = new Promise(resolve => {
+ var_caller_1.onicecandidate = e => resolve(e.candidate);
+ });
+ await var_caller_1.setLocalDescription(await var_caller_1.createOffer());
+ await var_callee_1.setRemoteDescription(var_caller_1.localDescription);
+ const candidate = await var_prom_1;
+ var arrProm = [];
+ gc();
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.setLocalDescription().then(() => {
+ })
+ var_callee_1.addIceCandidate(candidate).then(() => {
+ })
+ await Promise.all(arrProm);
+ }, 'Running this script does not cause an UAF');
+ </script>
+</head>
+
+<body></body>
+
+</html>

View File

@@ -0,0 +1,163 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lei Zhang <thestig@chromium.org>
Date: Tue, 10 Aug 2021 21:38:36 +0000
Subject: Do more class validity checks in PrintViewManagerBase.
PrintViewManagerBase runs a nested loop. In some situations,
PrintViewManagerBase and related classes like PrintViewManager and
PrintPreviewHandler can get deleted while the nested loop is running.
When this happens, the nested loop exists to a PrintViewManagerBase
that is no longer valid.
Use base::WeakPtrs liberally to check for this condition and exit
safely.
(cherry picked from commit a2cb1fb333d2faacb2fe1380f8d2621b5ee6af7e)
Bug: 1231134
Change-Id: I21ec131574331ce973d22594c11e70088147e149
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3057880
Reviewed-by: Alan Screen <awscreen@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#906269}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3086110
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/4515@{#2024}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index 26271f6689f1f887b82333d281f26012d2752d63..e73d0972b1b6d6db1fbb3825791e5b90146c2c5e 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -89,7 +89,11 @@ bool PrintViewManager::PrintForSystemDialogNow(
DCHECK(!on_print_dialog_shown_callback_);
on_print_dialog_shown_callback_ = std::move(dialog_shown_callback);
is_switching_to_system_dialog_ = true;
+
+ auto weak_this = weak_factory_.GetWeakPtr();
DisconnectFromCurrentPrintJob();
+ if (!weak_this)
+ return false;
// Don't print / print preview crashed tabs.
if (IsCrashed())
diff --git a/chrome/browser/printing/print_view_manager.h b/chrome/browser/printing/print_view_manager.h
index 8b2f150a1e6a042898cba14c971e1f80d04116ca..b5cba8a2dfb9021527e4cc5569635770e85949b3 100644
--- a/chrome/browser/printing/print_view_manager.h
+++ b/chrome/browser/printing/print_view_manager.h
@@ -128,6 +128,11 @@ class PrintViewManager : public PrintViewManagerBase,
WEB_CONTENTS_USER_DATA_KEY_DECL();
+ // Keep this last so that all weak pointers will be invalidated at the
+ // beginning of destruction. Note that PrintViewManagerBase has its own
+ // base::WeakPtrFactory as well, but PrintViewManager should use this one.
+ base::WeakPtrFactory<PrintViewManager> weak_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(PrintViewManager);
};
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 3b6e1d2609af952fa825688833387518cafdb352..3ddd927654e0134c28a7f73c6ec30b0c1ffe5c49 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -370,7 +370,10 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
bool silent,
base::Value settings,
CompletionCallback callback) {
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
DisconnectFromCurrentPrintJob();
+ if (!weak_this)
+ return false;
// Don't print / print preview crashed tabs.
if (IsCrashed())
@@ -850,6 +853,8 @@ bool PrintViewManagerBase::RenderAllMissingPagesNow() {
// or in DidPrintDocument(). The check is done in
// ShouldQuitFromInnerMessageLoop().
// BLOCKS until all the pages are received. (Need to enable recursive task)
+ // WARNING: Do not do any work after RunInnerMessageLoop() returns, as `this`
+ // may have gone away.
if (!RunInnerMessageLoop()) {
// This function is always called from DisconnectFromCurrentPrintJob() so we
// know that the job will be stopped/canceled in any case.
@@ -876,8 +881,11 @@ bool PrintViewManagerBase::CreateNewPrintJob(
DCHECK(query);
if (callback_.is_null()) {
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
// Disconnect the current |print_job_| only when calling window.print()
DisconnectFromCurrentPrintJob();
+ if (!weak_this)
+ return false;
}
// We can't print if there is no renderer.
@@ -906,7 +914,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
void PrintViewManagerBase::DisconnectFromCurrentPrintJob() {
// Make sure all the necessary rendered page are done. Don't bother with the
// return value.
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
bool result = RenderAllMissingPagesNow();
+ if (!weak_this)
+ return;
// Verify that assertion.
if (print_job_ && print_job_->document() &&
@@ -988,7 +999,10 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
quit_inner_loop_ = run_loop.QuitClosure();
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
run_loop.Run();
+ if (!weak_this)
+ return false;
// If the inner-loop quit closure is still set then we timed out.
bool success = !quit_inner_loop_;
diff --git a/chrome/browser/printing/print_view_manager_base.h b/chrome/browser/printing/print_view_manager_base.h
index ccb9808bdb334a78ed7b64dd3030caff52055ad6..b2ad5c1010b233e038cad9e2b5e39f3c0027d63e 100644
--- a/chrome/browser/printing/print_view_manager_base.h
+++ b/chrome/browser/printing/print_view_manager_base.h
@@ -122,6 +122,8 @@ class PrintViewManagerBase : public content::NotificationObserver,
// Makes sure the current print_job_ has all its data before continuing, and
// disconnect from it.
+ // WARNING: `this` may not be alive after DisconnectFromCurrentPrintJob()
+ // returns.
void DisconnectFromCurrentPrintJob();
// Manages the low-level talk to the printer.
@@ -168,6 +170,7 @@ class PrintViewManagerBase : public content::NotificationObserver,
// Requests the RenderView to render all the missing pages for the print job.
// No-op if no print job is pending. Returns true if at least one page has
// been requested to the renderer.
+ // WARNING: `this` may not be alive after RenderAllMissingPagesNow() returns.
bool RenderAllMissingPagesNow();
// Checks that synchronization is correct with |print_job_| based on |cookie|.
@@ -201,6 +204,7 @@ class PrintViewManagerBase : public content::NotificationObserver,
// while the blocking inner message loop is running. This is useful in cases
// where the RenderView is about to be destroyed while a printing job isn't
// finished.
+ // WARNING: `this` may not be alive after RunInnerMessageLoop() returns.
bool RunInnerMessageLoop();
// In the case of Scripted Printing, where the renderer is controlling the
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 82a2ac9bc0e5d32438a6ec6bd500cae7da8739fe..fe8a580e2fc5dbb74a57bf8488888a9696ce0007 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -726,9 +726,12 @@ void PrintPreviewHandler::HandleShowSystemDialog(
if (!initiator)
return;
+ auto weak_this = weak_factory_.GetWeakPtr();
auto* print_view_manager = PrintViewManager::FromWebContents(initiator);
print_view_manager->PrintForSystemDialogNow(base::BindOnce(
&PrintPreviewHandler::ClosePreviewDialog, weak_factory_.GetWeakPtr()));
+ if (!weak_this)
+ return;
// Cancel the pending preview request if exists.
print_preview_ui()->OnCancelPendingPreviewRequest();

View File

@@ -0,0 +1,77 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hongchan Choi <hongchan@chromium.org>
Date: Mon, 9 Aug 2021 18:43:22 +0000
Subject: Protect HRTF database loader thread from access by different threads
This patch add a new mutex locker around the HRTF database loader
thread to ensure the safe exclusive access of the loader thread
and the HRTF database.
(cherry picked from commit 6811e850ee10847da16c4d5fdc0f845494586b65)
Bug: 1233564
Change-Id: Ie12b99ffe520d3747e34af387a37637a10aab38a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3068260
Auto-Submit: Hongchan Choi <hongchan@chromium.org>
Commit-Queue: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#908269}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3082114
Reviewed-by: Chris Mumford <cmumford@google.com>
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/branch-heads/4577@{#601}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
index 034ded03d11fa42f0d0f62c6a91f6e20ee5f93e1..01cb98a1116fe1eb6a13ff6345b6bdf4e136badc 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
@@ -86,6 +86,8 @@ void HRTFDatabaseLoader::LoadTask() {
void HRTFDatabaseLoader::LoadAsynchronously() {
DCHECK(IsMainThread());
+ MutexLocker locker(lock_);
+
// m_hrtfDatabase and m_thread should both be unset because this should be a
// new HRTFDatabaseLoader object that was just created by
// createAndLoadAsynchronouslyIfNecessary and because we haven't started
@@ -122,6 +124,10 @@ void HRTFDatabaseLoader::CleanupTask(base::WaitableEvent* sync) {
}
void HRTFDatabaseLoader::WaitForLoaderThreadCompletion() {
+ // We can lock this because this is called from either the main thread or
+ // the offline audio rendering thread.
+ MutexLocker locker(lock_);
+
if (!thread_)
return;
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
index 3ce476fa68e066d6faf40011e94203f0fb778e71..a94997b4f7e06f96018187967faa524d4acfd5f6 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
+++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
@@ -64,8 +64,8 @@ class PLATFORM_EXPORT HRTFDatabaseLoader final
// must be called from the audio thread.
bool IsLoaded() { return Database(); }
- // waitForLoaderThreadCompletion() may be called more than once and is
- // thread-safe.
+ // May be called from both main and audio thread, and also can be called more
+ // than once.
void WaitForLoaderThreadCompletion();
// Returns the database or nullptr if the database doesn't yet exist. Must
@@ -87,11 +87,10 @@ class PLATFORM_EXPORT HRTFDatabaseLoader final
void LoadTask();
void CleanupTask(base::WaitableEvent*);
- // Holding a m_lock is required when accessing m_hrtfDatabase since we access
- // it from multiple threads.
+ // |lock_| MUST be held when accessing |hrtf_database_| or |thread_| because
+ // it can be accessed by multiple threads (e.g multiple AudioContexts).
Mutex lock_;
std::unique_ptr<HRTFDatabase> hrtf_database_;
-
std::unique_ptr<Thread> thread_;
float database_sample_rate_;

View File

@@ -0,0 +1,138 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sam McNally <sammc@chromium.org>
Date: Tue, 10 Aug 2021 02:14:43 +0000
Subject: Defer looking up the WebContents for the directory confirmation
dialog.
Look up the WebContents to use for the sensitive directory confirmation
dialog immediately before it's used instead of before performing some
blocking file access to determine whether it's necessary.
(cherry picked from commit 18236a0db8341302120c60781ae3129e94fbaf1c)
Bug: 1234009
Change-Id: I5e00c7fa199b3da522e1fdb73242891d7f5f7423
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3063743
Reviewed-by: Alex Danilo <adanilo@chromium.org>
Reviewed-by: Ben Wells <benwells@chromium.org>
Commit-Queue: Sam McNally <sammc@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#907467}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3083204
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/4577@{#648}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/extensions/browser/api/file_system/file_system_api.cc b/extensions/browser/api/file_system/file_system_api.cc
index e9023c877b7b35c0067642f05bc540858cbd7706..110f768c12d94fcfae0ac509fd0ce61c0e6049b8 100644
--- a/extensions/browser/api/file_system/file_system_api.cc
+++ b/extensions/browser/api/file_system/file_system_api.cc
@@ -197,6 +197,9 @@ void PassFileInfoToUIThread(FileInfoOptCallback callback,
content::WebContents* GetWebContentsForRenderFrameHost(
content::BrowserContext* browser_context,
content::RenderFrameHost* render_frame_host) {
+ if (!render_frame_host)
+ return nullptr;
+
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
// Check if there is an app window associated with the web contents; if not,
@@ -508,15 +511,6 @@ void FileSystemChooseEntryFunction::FilesSelected(
}
if (is_directory_) {
- // Get the WebContents for the app window to be the parent window of the
- // confirmation dialog if necessary.
- content::WebContents* const web_contents = GetWebContentsForRenderFrameHost(
- browser_context(), render_frame_host());
- if (!web_contents) {
- Respond(Error(kInvalidCallingPage));
- return;
- }
-
DCHECK_EQ(paths.size(), 1u);
bool non_native_path = false;
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -530,7 +524,7 @@ void FileSystemChooseEntryFunction::FilesSelected(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(
&FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this,
- non_native_path, paths, web_contents));
+ non_native_path, paths));
return;
}
@@ -543,8 +537,7 @@ void FileSystemChooseEntryFunction::FileSelectionCanceled() {
void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
bool non_native_path,
- const std::vector<base::FilePath>& paths,
- content::WebContents* web_contents) {
+ const std::vector<base::FilePath>& paths) {
const base::FilePath check_path =
non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]);
if (check_path.empty()) {
@@ -576,7 +569,7 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
FROM_HERE,
base::BindOnce(
&FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess,
- this, paths, web_contents));
+ this, paths));
return;
}
@@ -587,8 +580,7 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
}
void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
- const std::vector<base::FilePath>& paths,
- content::WebContents* web_contents) {
+ const std::vector<base::FilePath>& paths) {
if (ExtensionsBrowserClient::Get()->IsShuttingDown()) {
FileSelectionCanceled();
return;
@@ -601,6 +593,13 @@ void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
return;
}
+ content::WebContents* const web_contents =
+ GetWebContentsForRenderFrameHost(browser_context(), render_frame_host());
+ if (!web_contents) {
+ Respond(Error(kInvalidCallingPage));
+ return;
+ }
+
delegate->ConfirmSensitiveDirectoryAccess(
app_file_handler_util::HasFileSystemWritePermission(extension_.get()),
base::UTF8ToUTF16(extension_->name()), web_contents,
diff --git a/extensions/browser/api/file_system/file_system_api.h b/extensions/browser/api/file_system/file_system_api.h
index ae1588ce8536e4cee5474c3d4db370e95018c52e..0895a174a0dd1ba031fa358fe6451a1ebf198594 100644
--- a/extensions/browser/api/file_system/file_system_api.h
+++ b/extensions/browser/api/file_system/file_system_api.h
@@ -19,10 +19,6 @@
#include "extensions/common/api/file_system.h"
#include "ui/shell_dialogs/select_file_dialog.h"
-namespace content {
-class WebContents;
-} // namespace content
-
namespace extensions {
class ExtensionPrefs;
@@ -168,13 +164,12 @@ class FileSystemChooseEntryFunction : public FileSystemEntryFunction {
// directory. If so, calls ConfirmSensitiveDirectoryAccess. Otherwise, calls
// OnDirectoryAccessConfirmed.
void ConfirmDirectoryAccessAsync(bool non_native_path,
- const std::vector<base::FilePath>& paths,
- content::WebContents* web_contents);
+ const std::vector<base::FilePath>& paths);
// Shows a dialog to confirm whether the user wants to open the directory.
// Calls OnDirectoryAccessConfirmed or FileSelectionCanceled.
- void ConfirmSensitiveDirectoryAccess(const std::vector<base::FilePath>& paths,
- content::WebContents* web_contents);
+ void ConfirmSensitiveDirectoryAccess(
+ const std::vector<base::FilePath>& paths);
void OnDirectoryAccessConfirmed(const std::vector<base::FilePath>& paths);

View File

@@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Koji Ishii <kojii@chromium.org>
Date: Thu, 9 Sep 2021 23:25:48 +0000
Subject: Merge 4577: Apply list item quirks only when the nested list is
block-level
This patch changes to apply quirks for a list-item occupying
the whole line only if the nested list is block-level.
When applying this quirks, list markers are handled like a
regular child. r883403 crrev.com/c/2885398 changed to handle
list markers at |NGBlockLayoutAlgorithm| to support NG block
fragmentation. These two when combined causes the list marker
not laid out if the nested list is not block-level.
This may change some visual behaviors, but I think this is ok:
a) This quirks is not in the quirks spec[1] and not
implemented in Gecko.
b) The previous CL had a visual difference in this case in M92
but no reports so far.
[1]: https://quirks.spec.whatwg.org/
(cherry picked from commit 6f5d97da873f0e193a732fb7281d3484258aef6d)
Bug: 1246932, 1206409
Change-Id: Ia58a1b788313d3d9f221fd010cdd1a906551ab8b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3145018
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#919158}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3151681
Auto-Submit: Koji Ishii <kojii@chromium.org>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/branch-heads/4577@{#1225}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
index 15a3c0a3018301e40d336c8893e987b491da66d3..9b7c0e075cb5a89108c22824c5522de26eb904da 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
@@ -26,8 +26,11 @@ bool LayoutNGOutsideListMarker::NeedsOccupyWholeLine() const {
if (!GetDocument().InQuirksMode())
return false;
+ // Apply the quirks when the next sibling is a block-level `<ul>` or `<ol>`.
LayoutObject* next_sibling = NextSibling();
- if (next_sibling && next_sibling->GetNode() &&
+ if (next_sibling && !next_sibling->IsInline() &&
+ !next_sibling->IsFloatingOrOutOfFlowPositioned() &&
+ next_sibling->GetNode() &&
(IsA<HTMLUListElement>(*next_sibling->GetNode()) ||
IsA<HTMLOListElement>(*next_sibling->GetNode())))
return true;
diff --git a/third_party/blink/web_tests/external/wpt/quirks/crashtests/list-item-whole-line-quirks-crash.html b/third_party/blink/web_tests/external/wpt/quirks/crashtests/list-item-whole-line-quirks-crash.html
new file mode 100644
index 0000000000000000000000000000000000000000..b91b09db0e37727e2d3a3e13ca2c7cae25b8d761
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/quirks/crashtests/list-item-whole-line-quirks-crash.html
@@ -0,0 +1,5 @@
+<!-- quirks -->
+<div>a<ul><li><ul style='float: left'></ul></li></ul></div>
+<div>a<ul><li><ul style='position: absolute'></ul></li></ul></div>
+<div>a<ul><li><ul style='display: inline'></ul></li></ul></div>
+<div>a<ul><li><ul style='display: inline-block'></ul></li></ul></div>

View File

@@ -0,0 +1,121 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Scott Violet <sky@chromium.org>
Date: Wed, 8 Sep 2021 18:45:42 +0000
Subject: compositor: fix bug in sending damage regions
Specifically if a layer is added when sending damaged regions the
iterator would be invalidated. This converts to iterating over the
size.
BUG=1242257
TEST=CompositorTestWithMessageLoop.AddLayerDuringUpdateVisualState
(cherry picked from commit 7c0b0577c3ac1060945b7d05ad69f0dec33479b4)
Change-Id: I09f2bd34afce5d3c9402ef470f14923bbc76b8ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3140178
Reviewed-by: Ian Vollick <vollick@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#917886}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3149110
Commit-Queue: enne <enne@chromium.org>
Auto-Submit: Scott Violet <sky@chromium.org>
Reviewed-by: enne <enne@chromium.org>
Cr-Commit-Position: refs/branch-heads/4577@{#1206}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 34f84bbdc2c21e3f8b8085edaf3fcad86c584672..350efae9200e1646449902e201c985b09ad47e0d 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -653,8 +653,10 @@ void Compositor::BeginMainFrameNotExpectedUntil(base::TimeTicks time) {}
static void SendDamagedRectsRecursive(ui::Layer* layer) {
layer->SendDamagedRects();
- for (auto* child : layer->children())
- SendDamagedRectsRecursive(child);
+ // Iterate using the size for the case of mutation during sending damaged
+ // regions. https://crbug.com/1242257.
+ for (size_t i = 0; i < layer->children().size(); ++i)
+ SendDamagedRectsRecursive(layer->children()[i]);
}
void Compositor::UpdateLayerTreeHost() {
diff --git a/ui/compositor/compositor_unittest.cc b/ui/compositor/compositor_unittest.cc
index 7eaa8bbe4ab34e455c2afc67511c867a1d6d7e39..389b8630b4db323458aae65b61ef0b7d91a9797c 100644
--- a/ui/compositor/compositor_unittest.cc
+++ b/ui/compositor/compositor_unittest.cc
@@ -12,12 +12,14 @@
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "cc/metrics/frame_sequence_tracker.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_delegate.h"
#include "ui/compositor/test/draw_waiter_for_test.h"
#include "ui/compositor/test/in_process_context_factory.h"
#include "ui/compositor/test/test_context_factories.h"
@@ -356,4 +358,58 @@ TEST_F(CompositorTestWithMessageLoop, MAYBE_CreateAndReleaseOutputSurface) {
compositor()->SetRootLayer(nullptr);
}
+class LayerDelegateThatAddsDuringUpdateVisualState : public LayerDelegate {
+ public:
+ explicit LayerDelegateThatAddsDuringUpdateVisualState(Layer* parent)
+ : parent_(parent) {}
+
+ bool update_visual_state_called() const {
+ return update_visual_state_called_;
+ }
+
+ // LayerDelegate:
+ void UpdateVisualState() override {
+ added_layers_.push_back(std::make_unique<Layer>(ui::LAYER_SOLID_COLOR));
+ parent_->Add(added_layers_.back().get());
+ update_visual_state_called_ = true;
+ }
+ void OnPaintLayer(const PaintContext& context) override {}
+ void OnDeviceScaleFactorChanged(float old_device_scale_factor,
+ float new_device_scale_factor) override {}
+
+ private:
+ Layer* parent_;
+ std::vector<std::unique_ptr<Layer>> added_layers_;
+ bool update_visual_state_called_ = false;
+};
+
+TEST_F(CompositorTestWithMessageLoop, AddLayerDuringUpdateVisualState) {
+ std::unique_ptr<Layer> root_layer =
+ std::make_unique<Layer>(ui::LAYER_SOLID_COLOR);
+ std::unique_ptr<Layer> child_layer =
+ std::make_unique<Layer>(ui::LAYER_TEXTURED);
+ std::unique_ptr<Layer> child_layer2 =
+ std::make_unique<Layer>(ui::LAYER_SOLID_COLOR);
+ LayerDelegateThatAddsDuringUpdateVisualState child_layer_delegate(
+ root_layer.get());
+ child_layer->set_delegate(&child_layer_delegate);
+ root_layer->Add(child_layer.get());
+ root_layer->Add(child_layer2.get());
+
+ viz::ParentLocalSurfaceIdAllocator allocator;
+ allocator.GenerateId();
+ root_layer->SetBounds(gfx::Rect(10, 10));
+ compositor()->SetRootLayer(root_layer.get());
+ compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10),
+ allocator.GetCurrentLocalSurfaceId());
+ ASSERT_TRUE(compositor()->IsVisible());
+ compositor()->ScheduleDraw();
+ DrawWaiterForTest::WaitForCompositingEnded(compositor());
+ EXPECT_TRUE(child_layer_delegate.update_visual_state_called());
+ compositor()->SetRootLayer(nullptr);
+ child_layer2.reset();
+ child_layer.reset();
+ root_layer.reset();
+}
+
} // namespace ui

View File

@@ -0,0 +1,274 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ian Kilpatrick <ikilpatrick@chromium.org>
Date: Thu, 9 Sep 2021 23:20:48 +0000
Subject: Remove limit from LayoutInline::SplitInlines.
After 200 elements the code "gave up" causing the layout tree to be
"strange".
This caused a To<LayoutInline> to fail in the OOF code. Relaxing this
To<> to a DynamicTo<> caused additional CHECKs / DCHECKs all over the
place (not just in NG but in Legacy as well).
This patch removes the limit at which we "give up". This may cause
additional render hangs.
However we currently have a project "block-in-inline" which will (for
most cases) stop inline-splitting for occuring (except in legacy
fallback).
(cherry picked from commit bbd315efb49a4ae257509dd0f0d85c6b5906e0e4)
(cherry picked from commit d760d2ae1d51c0b4fda87a0a3af4e7ed30d2ff4c)
Bug: 1245786
Change-Id: I5f1c4d6a4b81a8345974de40c0c50a27a839b7b4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3140144
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Original-Original-Commit-Position: refs/heads/main@{#917771}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3149698
Cr-Original-Commit-Position: refs/branch-heads/4606@{#876}
Cr-Original-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3152301
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/4577@{#1224}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
index e59adae1204e5ecb6e399f4fe0ca8a3642701717..d3fa773216bc507208fc6bde3e216e1b8bacf390 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -574,15 +574,13 @@ void LayoutInline::SplitInlines(LayoutBlockFlow* from_block,
// nest to a much greater depth (see bugzilla bug 13430) but for now we have a
// limit. This *will* result in incorrect rendering, but the alternative is to
// hang forever.
- const unsigned kCMaxSplitDepth = 200;
Vector<LayoutInline*> inlines_to_clone;
LayoutInline* top_most_inline = this;
for (LayoutObject* o = this; o != from_block; o = o->Parent()) {
if (o->IsLayoutNGInsideListMarker())
continue;
top_most_inline = To<LayoutInline>(o);
- if (inlines_to_clone.size() < kCMaxSplitDepth)
- inlines_to_clone.push_back(top_most_inline);
+ inlines_to_clone.push_back(top_most_inline);
// Keep walking up the chain to ensure |topMostInline| is a child of
// |fromBlock|, to avoid assertion failure when |fromBlock|'s children are
// moved to |toBlock| below.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html b/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html
new file mode 100644
index 0000000000000000000000000000000000000000..65008f74ce6e0b4397a5b333099c692382d64353
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1245786">
+<style>
+ nav{ position: absolute; }
+ body > * { position: relative; }
+</style>
+<body>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<div>
+<nav>

View File

@@ -0,0 +1,85 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Bostr=C3=B6m?= <hbos@chromium.org>
Date: Thu, 8 Jul 2021 12:16:10 +0000
Subject: Fix UAF in VideoCaptureDeviceAVFoundation's dealloc.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Despite dealloc performing stopCapture prior to clearing variables like
_sampleBufferTransformer, it appears possible for callbacks that are
already running concurrently to be using these variables, resulting in
rare use-after-free races. By grabbing the _lock, we avoid this issue.
We also have to introduce a new lock, _destructionLock, to ensure |this|
is not destroyed while -captureOutput is still running.
Bug: chromium:1227228
Change-Id: I8c2c4d9834ee995d3f4154fae13e262398e6f2e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3013796
Reviewed-by: Evan Shrubsole <eshr@google.com>
Reviewed-by: Ilya Nikolaevskiy <ilnik@chromium.org>
Commit-Queue: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#899503}
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.h b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
index 2e2b3f65bac58a29bfbae080baa2657c92791984..416984c16de161aa35f7783ceea4706427103980 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.h
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
@@ -95,6 +95,8 @@ CAPTURE_EXPORT
// Protects concurrent setting and using |frameReceiver_|. Note that the
// GUARDED_BY decoration below does not have any effect.
base::Lock _lock;
+ // Used to avoid UAF in -captureOutput.
+ base::Lock _destructionLock;
media::VideoCaptureDeviceAVFoundationFrameReceiver* _frameReceiver
GUARDED_BY(_lock); // weak.
bool _capturedFirstFrame GUARDED_BY(_lock);
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
index 1cc1bdbcec259cd6d2da14b2c120d895d3e3c7fe..93749e8e4d444cbf76f8e8a36c13ea6d71c6d9ba 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -187,12 +187,26 @@ - (id)initWithFrameReceiver:
}
- (void)dealloc {
- [self stopStillImageOutput];
- [self stopCapture];
- _sampleBufferTransformer.reset();
- _weakPtrFactoryForTakePhoto = nullptr;
- _mainThreadTaskRunner = nullptr;
- _sampleQueue.reset();
+ {
+ // To avoid races with concurrent callbacks, grab the lock before stopping
+ // capture and clearing all the variables.
+ base::AutoLock lock(_lock);
+ [self stopStillImageOutput];
+ [self stopCapture];
+ _frameReceiver = nullptr;
+ _sampleBufferTransformer.reset();
+ _weakPtrFactoryForTakePhoto = nullptr;
+ _mainThreadTaskRunner = nullptr;
+ _sampleQueue.reset();
+ }
+ {
+ // Ensures -captureOutput has finished before we continue the destruction
+ // steps. If -captureOutput grabbed the destruction lock before us this
+ // prevents UAF. If -captureOutput grabbed the destruction lock after us
+ // it will exit early because |_frameReceiver| is already null at this
+ // point.
+ base::AutoLock destructionLock(_destructionLock);
+ }
[super dealloc];
}
@@ -889,7 +903,9 @@ - (void)captureOutput:(AVCaptureOutput*)captureOutput
VLOG(3) << __func__;
// Concurrent calls into |_frameReceiver| are not supported, so take |_lock|
- // before any of the subsequent paths.
+ // before any of the subsequent paths. The |_destructionLock| must be grabbed
+ // first to avoid races with -dealloc.
+ base::AutoLock destructionLock(_destructionLock);
base::AutoLock lock(_lock);
_capturedFrameSinceLastStallCheck = YES;
if (!_frameReceiver)

View File

@@ -0,0 +1,336 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jiewei Qian <qjw@chromium.org>
Date: Fri, 3 Sep 2021 04:38:53 +0000
Subject: webui: make WebUIAllowlist and WebUIAllowlistProvider thread-safe
This CL adds synchronization lock to WebUIAllowlist, and expose it as
scoped_refptr, so it provides thread-safety when used in
WebUIAllowlistProvider (per requirements of HostContentSettingsMap).
(cherry picked from commit 56489e04b7c39e7b6d2b3fb33549d2657dad23a9)
(cherry picked from commit 58eda7adb82e7fcc8001482334bfa6f9482aee78)
Fixed: 1238178
Change-Id: I4d8112f7792a7113b412af2eb67cbcef0bdcec1d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3102499
Commit-Queue: Jiewei Qian <qjw@chromium.org>
Reviewed-by: Christian Dullweber <dullweber@chromium.org>
Reviewed-by: calamity <calamity@chromium.org>
Reviewed-by: Victor Costan <pwnall@chromium.org>
Cr-Original-Original-Commit-Position: refs/heads/main@{#914567}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3115817
Auto-Submit: Jiewei Qian <qjw@chromium.org>
Commit-Queue: calamity <calamity@chromium.org>
Cr-Original-Commit-Position: refs/branch-heads/4606@{#340}
Cr-Original-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3141052
Cr-Commit-Position: refs/branch-heads/4577@{#1170}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/ui/webui/webui_allowlist.cc b/ui/webui/webui_allowlist.cc
index 525848a9d2f9baccc95b59581ad2aa53494c449e..cd231550094e410d26a5267427bcb578af451530 100644
--- a/ui/webui/webui_allowlist.cc
+++ b/ui/webui/webui_allowlist.cc
@@ -6,7 +6,11 @@
#include <memory>
+#include "base/memory/scoped_refptr.h"
+#include "base/sequence_checker.h"
+#include "base/supports_user_data.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_constants.h"
#include "ui/webui/webui_allowlist_provider.h"
#include "url/gurl.h"
@@ -19,15 +23,27 @@ class AllowlistRuleIterator : public content_settings::RuleIterator {
using MapType = std::map<url::Origin, ContentSetting>;
public:
- explicit AllowlistRuleIterator(const MapType& map)
- : it_(map.cbegin()), end_(map.cend()) {}
+ // Hold a reference to `allowlist` to keep it alive during iteration.
+ explicit AllowlistRuleIterator(scoped_refptr<const WebUIAllowlist> allowlist,
+ const MapType& map,
+ std::unique_ptr<base::AutoLock> auto_lock)
+ : auto_lock_(std::move(auto_lock)),
+ allowlist_(std::move(allowlist)),
+ it_(map.cbegin()),
+ end_(map.cend()) {}
AllowlistRuleIterator(const AllowlistRuleIterator&) = delete;
void operator=(const AllowlistRuleIterator&) = delete;
- ~AllowlistRuleIterator() override = default;
+ ~AllowlistRuleIterator() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ }
- bool HasNext() const override { return it_ != end_; }
+ bool HasNext() const override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return it_ != end_;
+ }
content_settings::Rule Next() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const auto& origin = it_->first;
const auto& setting = it_->second;
it_++;
@@ -38,8 +54,18 @@ class AllowlistRuleIterator : public content_settings::RuleIterator {
}
private:
- MapType::const_iterator it_;
- const MapType::const_iterator end_;
+ const std::unique_ptr<base::AutoLock> auto_lock_;
+ const scoped_refptr<const WebUIAllowlist> allowlist_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ MapType::const_iterator it_ GUARDED_BY_CONTEXT(sequence_checker_);
+ MapType::const_iterator end_ GUARDED_BY_CONTEXT(sequence_checker_);
+};
+
+struct WebUIAllowlistHolder : base::SupportsUserData::Data {
+ explicit WebUIAllowlistHolder(scoped_refptr<WebUIAllowlist> list)
+ : allow_list(std::move(list)) {}
+ const scoped_refptr<WebUIAllowlist> allow_list;
};
} // namespace
@@ -48,11 +74,14 @@ class AllowlistRuleIterator : public content_settings::RuleIterator {
WebUIAllowlist* WebUIAllowlist::GetOrCreate(
content::BrowserContext* browser_context) {
if (!browser_context->GetUserData(kWebUIAllowlistKeyName)) {
- browser_context->SetUserData(kWebUIAllowlistKeyName,
- std::make_unique<WebUIAllowlist>());
+ auto list = base::MakeRefCounted<WebUIAllowlist>();
+ browser_context->SetUserData(
+ kWebUIAllowlistKeyName,
+ std::make_unique<WebUIAllowlistHolder>(std::move(list)));
}
- return static_cast<WebUIAllowlist*>(
- browser_context->GetUserData(kWebUIAllowlistKeyName));
+ return static_cast<WebUIAllowlistHolder*>(
+ browser_context->GetUserData(kWebUIAllowlistKeyName))
+ ->allow_list.get();
}
WebUIAllowlist::WebUIAllowlist() = default;
@@ -62,6 +91,9 @@ WebUIAllowlist::~WebUIAllowlist() = default;
void WebUIAllowlist::RegisterAutoGrantedPermission(const url::Origin& origin,
ContentSettingsType type,
ContentSetting setting) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
// It doesn't make sense to grant a default content setting.
DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
@@ -70,13 +102,16 @@ void WebUIAllowlist::RegisterAutoGrantedPermission(const url::Origin& origin,
DCHECK(origin.scheme() == content::kChromeUIScheme ||
origin.scheme() == content::kChromeUIUntrustedScheme ||
origin.scheme() == content::kChromeDevToolsScheme);
+ {
+ base::AutoLock auto_lock(lock_);
- // If the same permission is already registered, do nothing. We don't want to
- // notify the provider of ContentSettingChange when it is unnecessary.
- if (permissions_[type][origin] == setting)
- return;
+ // If the same permission is already registered, do nothing. We don't want
+ // to notify the provider of ContentSettingChange when it is unnecessary.
+ if (permissions_[type][origin] == setting)
+ return;
- permissions_[type][origin] = setting;
+ permissions_[type][origin] = setting;
+ }
// Notify the provider. |provider_| can be nullptr if
// HostContentSettingsRegistry is shutting down i.e. when Chrome shuts down.
@@ -92,25 +127,36 @@ void WebUIAllowlist::RegisterAutoGrantedPermission(const url::Origin& origin,
void WebUIAllowlist::RegisterAutoGrantedPermissions(
const url::Origin& origin,
std::initializer_list<ContentSettingsType> types) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
for (const ContentSettingsType& type : types)
RegisterAutoGrantedPermission(origin, type);
}
void WebUIAllowlist::SetWebUIAllowlistProvider(
WebUIAllowlistProvider* provider) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
provider_ = provider;
}
void WebUIAllowlist::ResetWebUIAllowlistProvider() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
provider_ = nullptr;
}
std::unique_ptr<content_settings::RuleIterator> WebUIAllowlist::GetRuleIterator(
ContentSettingsType content_type) const {
- const auto& type_to_origin_rules = permissions_.find(content_type);
- if (type_to_origin_rules != permissions_.cend()) {
- return std::make_unique<AllowlistRuleIterator>(
- type_to_origin_rules->second);
+ auto auto_lock_ = std::make_unique<base::AutoLock>(lock_);
+
+ auto permissions_it = permissions_.find(content_type);
+ if (permissions_it != permissions_.end()) {
+ return std::make_unique<AllowlistRuleIterator>(this, permissions_it->second,
+ std::move(auto_lock_));
}
return nullptr;
diff --git a/ui/webui/webui_allowlist.h b/ui/webui/webui_allowlist.h
index b1623b89f5ed12416e71d5f1505d57b74073f764..9c6ab47b16a4fcc6478e6ad4672ce5c95166156f 100644
--- a/ui/webui/webui_allowlist.h
+++ b/ui/webui/webui_allowlist.h
@@ -8,7 +8,9 @@
#include <initializer_list>
#include <map>
-#include "base/supports_user_data.h"
+#include "base/memory/ref_counted.h"
+#include "base/thread_annotations.h"
+#include "base/threading/thread_checker.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
@@ -23,14 +25,13 @@ class WebUIAllowlistProvider;
// list of origins and permissions to be auto-granted to WebUIs. This class is
// created before HostContentSettingsMap is registered and has the same lifetime
// as the profile it's attached to. It outlives WebUIAllowlistProvider.
-class WebUIAllowlist : public base::SupportsUserData::Data {
+class WebUIAllowlist : public base::RefCountedThreadSafe<WebUIAllowlist> {
public:
static WebUIAllowlist* GetOrCreate(content::BrowserContext* browser_context);
WebUIAllowlist();
WebUIAllowlist(const WebUIAllowlist&) = delete;
void operator=(const WebUIAllowlist&) = delete;
- ~WebUIAllowlist() override;
// Register auto-granted |type| permission for |origin|.
//
@@ -53,16 +54,29 @@ class WebUIAllowlist : public base::SupportsUserData::Data {
const url::Origin& origin,
std::initializer_list<ContentSettingsType> types);
+ // Returns a content_settings::RuleIterator, this method is thread-safe.
+ //
+ // This method acquires `lock_` and transfers it to the returned iterator.
+ // NO_THREAD_SAFETY_ANALYSIS because the analyzer doesn't recognize acquiring
+ // the lock in a unique_ptr.
std::unique_ptr<content_settings::RuleIterator> GetRuleIterator(
- ContentSettingsType content_type) const;
+ ContentSettingsType content_type) const NO_THREAD_SAFETY_ANALYSIS;
void SetWebUIAllowlistProvider(WebUIAllowlistProvider* provider);
void ResetWebUIAllowlistProvider();
private:
+ friend class base::RefCountedThreadSafe<WebUIAllowlist>;
+ ~WebUIAllowlist();
+
+ THREAD_CHECKER(thread_checker_);
+
+ mutable base::Lock lock_;
std::map<ContentSettingsType, std::map<url::Origin, ContentSetting>>
- permissions_;
- WebUIAllowlistProvider* provider_ = nullptr;
+ permissions_ GUARDED_BY(lock_);
+
+ WebUIAllowlistProvider* provider_ GUARDED_BY_CONTEXT(thread_checker_) =
+ nullptr;
};
#endif // UI_WEBUI_WEBUI_ALLOWLIST_H_
diff --git a/ui/webui/webui_allowlist_provider.cc b/ui/webui/webui_allowlist_provider.cc
index 779e8022fce378d2a64c78e6e20c36202e9261ac..055a3cf3934ed43373a4a3fdd4166bd3c096e922 100644
--- a/ui/webui/webui_allowlist_provider.cc
+++ b/ui/webui/webui_allowlist_provider.cc
@@ -7,8 +7,9 @@
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "ui/webui/webui_allowlist.h"
-WebUIAllowlistProvider::WebUIAllowlistProvider(WebUIAllowlist* allowlist)
- : allowlist_(allowlist) {
+WebUIAllowlistProvider::WebUIAllowlistProvider(
+ scoped_refptr<WebUIAllowlist> allowlist)
+ : allowlist_(std::move(allowlist)) {
DCHECK(allowlist_);
allowlist_->SetWebUIAllowlistProvider(this);
}
@@ -16,12 +17,8 @@ WebUIAllowlistProvider::WebUIAllowlistProvider(WebUIAllowlist* allowlist)
WebUIAllowlistProvider::~WebUIAllowlistProvider() = default;
std::unique_ptr<content_settings::RuleIterator>
-WebUIAllowlistProvider::GetRuleIterator(
- ContentSettingsType content_type,
- bool incognito) const {
- if (!allowlist_)
- return nullptr;
-
+WebUIAllowlistProvider::GetRuleIterator(ContentSettingsType content_type,
+ bool incognito) const {
return allowlist_->GetRuleIterator(content_type);
}
@@ -48,7 +45,8 @@ void WebUIAllowlistProvider::ClearAllContentSettingsRules(
}
void WebUIAllowlistProvider::ShutdownOnUIThread() {
+ DCHECK(CalledOnValidThread());
+
RemoveAllObservers();
allowlist_->ResetWebUIAllowlistProvider();
- allowlist_ = nullptr;
}
diff --git a/ui/webui/webui_allowlist_provider.h b/ui/webui/webui_allowlist_provider.h
index 9f7f9776fd6e8212d3dbd196698b036f24f75f2e..c18f64e6f2051091f40504c2ba47feb62103aee3 100644
--- a/ui/webui/webui_allowlist_provider.h
+++ b/ui/webui/webui_allowlist_provider.h
@@ -5,6 +5,8 @@
#ifndef UI_WEBUI_WEBUI_ALLOWLIST_PROVIDER_H_
#define UI_WEBUI_WEBUI_ALLOWLIST_PROVIDER_H_
+#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "components/content_settings/core/browser/content_settings_observable_provider.h"
#include "components/content_settings/core/common/content_settings.h"
#include "ui/webui/webui_allowlist.h"
@@ -15,8 +17,7 @@ class ContentSettingsPattern;
// permissions from the underlying WebUIAllowlist.
class WebUIAllowlistProvider : public content_settings::ObservableProvider {
public:
- // Note, |allowlist| must outlive this instance.
- explicit WebUIAllowlistProvider(WebUIAllowlist* allowlist);
+ explicit WebUIAllowlistProvider(scoped_refptr<WebUIAllowlist> allowlist);
WebUIAllowlistProvider(const WebUIAllowlistProvider&) = delete;
void operator=(const WebUIAllowlistProvider&) = delete;
~WebUIAllowlistProvider() override;
@@ -27,6 +28,7 @@ class WebUIAllowlistProvider : public content_settings::ObservableProvider {
ContentSettingsType content_type);
// content_settings::ObservableProvider:
+ // The following methods are thread-safe.
std::unique_ptr<content_settings::RuleIterator> GetRuleIterator(
ContentSettingsType content_type,
bool incognito) const override;
@@ -40,7 +42,7 @@ class WebUIAllowlistProvider : public content_settings::ObservableProvider {
void ClearAllContentSettingsRules(ContentSettingsType content_type) override;
private:
- WebUIAllowlist* allowlist_;
+ const scoped_refptr<WebUIAllowlist> allowlist_;
};
#endif // UI_WEBUI_WEBUI_ALLOWLIST_PROVIDER_H_

View File

@@ -0,0 +1,119 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Vladimir Levin <vmpstr@chromium.org>
Date: Tue, 7 Sep 2021 21:32:03 +0000
Subject: content-visibility: Force range base/extent when computing visual
selection.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some of the code that does visual selection ends up updating style and
layout for node. This means that it will temporarily unlock c-v nodes
and may cause a state rewind from layout clean to visual update pending.
That's not an operation we support, verified by DCHECKs. So, instead
we should unlock any c-v nodes prior to getting to layout clean.
R=chrishtr@chromium.org, yosin@chromium.org
(cherry picked from commit 484bc1abffcdee33648695244c86daca15ab6539)
Bug: 1237533
Change-Id: Ib30036c4536bea3da2ae4fa54c19ad5684829597
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3114230
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#914631}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3145452
Auto-Submit: vmpstr <vmpstr@chromium.org>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/branch-heads/4515@{#2115}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
index b751822d19f703984a4e65ef465667ac2f592533..715a830c65d39bd240a5d858674d428885538520 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -173,6 +173,9 @@ DisplayLockUtilities::ScopedForcedUpdate::Impl::Impl(const Node* node,
if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return;
+ if (!node_)
+ return;
+
auto* owner_node = GetFrameOwnerNode(node);
if (owner_node)
parent_frame_impl_ = MakeGarbageCollected<Impl>(owner_node, true);
@@ -215,6 +218,8 @@ DisplayLockUtilities::ScopedForcedUpdate::Impl::Impl(const Node* node,
}
void DisplayLockUtilities::ScopedForcedUpdate::Impl::Destroy() {
+ if (!node_)
+ return;
if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
node_->GetDocument().GetDisplayLockDocumentState().EndNodeForcedScope(this);
if (parent_frame_impl_)
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.h b/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
index 6e6839e2c1222a6f05d89dca97e7513989476165..022ac073ca6eb92023014933f2f1d12d774f8a30 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
@@ -51,6 +52,8 @@ class CORE_EXPORT DisplayLockUtilities {
friend void Document::EnsurePaintLocationDataValidForNode(
const Node* node,
DocumentUpdateReason reason);
+ friend VisibleSelection
+ FrameSelection::ComputeVisibleSelectionInDOMTreeDeprecated() const;
friend class DisplayLockContext;
diff --git a/third_party/blink/renderer/core/editing/frame_selection.cc b/third_party/blink/renderer/core/editing/frame_selection.cc
index d0133cc8da39300c4fc3b5ae225afd9e3aeceeca..f59557caeb9fa1bc460e199a7dae8d218d27c089 100644
--- a/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -158,6 +158,10 @@ VisibleSelection FrameSelection::ComputeVisibleSelectionInDOMTreeDeprecated()
const {
// TODO(editing-dev): Hoist UpdateStyleAndLayout
// to caller. See http://crbug.com/590369 for more details.
+ DisplayLockUtilities::ScopedForcedUpdate base_scope(
+ GetSelectionInDOMTree().Base().AnchorNode());
+ DisplayLockUtilities::ScopedForcedUpdate extent_scope(
+ GetSelectionInDOMTree().Extent().AnchorNode());
GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
return ComputeVisibleSelectionInDOMTree();
}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/meter-selection-crash.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/meter-selection-crash.html
new file mode 100644
index 0000000000000000000000000000000000000000..9edca97568e288c0231ac942eeadfe397ea9e00f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/meter-selection-crash.html
@@ -0,0 +1,21 @@
+<!doctype HTML>
+<link rel=author href="mailto:vmpstr@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
+<meta name="assert" content="meter, iframe, and selection API should not crash">
+
+<style>
+* {
+ all: initial;
+ content-visibility: hidden;
+}
+</style>
+
+<meter></meter><iframe id="frame"></iframe>
+<script>
+function runTest() {
+ var range_beadc = window.getSelection();
+ var elem1 = document.getElementById("frame");
+ range_beadc.setBaseAndExtent(elem1, 0, document.getElementById("none"), 0);
+}
+onload = runTest;
+</script>

View File

@@ -0,0 +1,214 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rayan Kanso <rayankans@google.com>
Date: Thu, 9 Sep 2021 11:16:13 +0000
Subject: Add Origin checks to mojo methods.
(cherry picked from commit 6ef569fd764a8e5f8fba4dcff830d460e406362b)
Bug: 1244568
Change-Id: I5a63a2e478577913a3b35154464c1808f7291f40
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3140385
Reviewed-by: Richard Knoll <knollr@chromium.org>
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#918606}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3149996
Reviewed-by: Michael van Ouwerkerk <mvanouwerkerk@chromium.org>
Cr-Commit-Position: refs/branch-heads/4577@{#1220}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/content/browser/content_index/content_index_database.cc b/content/browser/content_index/content_index_database.cc
index 2ce59c40e2d8e319b68d9df61a496606f4bf5bb6..438798fe658bf148c09a9bcf65c3b40dbf96325e 100644
--- a/content/browser/content_index/content_index_database.cc
+++ b/content/browser/content_index/content_index_database.cc
@@ -183,6 +183,11 @@ void ContentIndexDatabase::AddEntryOnCoreThread(
return;
}
+ if (!service_worker_registration->origin().IsSameOriginWith(origin)) {
+ std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR);
+ return;
+ }
+
auto serialized_icons = std::make_unique<proto::SerializedIcons>();
proto::SerializedIcons* serialized_icons_ptr = serialized_icons.get();
@@ -284,6 +289,15 @@ void ContentIndexDatabase::DeleteEntryOnCoreThread(
blink::mojom::ContentIndexService::DeleteCallback callback) {
DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration =
+ service_worker_context_->GetLiveRegistration(
+ service_worker_registration_id);
+ if (!service_worker_registration ||
+ !service_worker_registration->origin().IsSameOriginWith(origin)) {
+ std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR);
+ return;
+ }
+
service_worker_context_->ClearRegistrationUserData(
service_worker_registration_id, {EntryKey(entry_id), IconsKey(entry_id)},
base::BindOnce(&ContentIndexDatabase::DidDeleteEntry,
@@ -316,6 +330,7 @@ void ContentIndexDatabase::DidDeleteEntry(
void ContentIndexDatabase::GetDescriptions(
int64_t service_worker_registration_id,
+ const url::Origin& origin,
blink::mojom::ContentIndexService::GetDescriptionsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -333,15 +348,26 @@ void ContentIndexDatabase::GetDescriptions(
FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
base::BindOnce(&ContentIndexDatabase::GetDescriptionsOnCoreThread,
weak_ptr_factory_core_.GetWeakPtr(),
- service_worker_registration_id,
+ service_worker_registration_id, origin,
std::move(wrapped_callback)));
}
void ContentIndexDatabase::GetDescriptionsOnCoreThread(
int64_t service_worker_registration_id,
+ const url::Origin& origin,
blink::mojom::ContentIndexService::GetDescriptionsCallback callback) {
DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration =
+ service_worker_context_->GetLiveRegistration(
+ service_worker_registration_id);
+ if (!service_worker_registration ||
+ !service_worker_registration->origin().IsSameOriginWith(origin)) {
+ std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR,
+ /* descriptions= */ {});
+ return;
+ }
+
service_worker_context_->GetRegistrationUserDataByKeyPrefix(
service_worker_registration_id, kEntryPrefix,
base::BindOnce(&ContentIndexDatabase::DidGetDescriptions,
diff --git a/content/browser/content_index/content_index_database.h b/content/browser/content_index/content_index_database.h
index 89c23e8d3595a114c3a24530c8afd1e3a67b79a3..86a7830a72b25fc4a76575138e29284a2debba52 100644
--- a/content/browser/content_index/content_index_database.h
+++ b/content/browser/content_index/content_index_database.h
@@ -51,6 +51,7 @@ class CONTENT_EXPORT ContentIndexDatabase {
void GetDescriptions(
int64_t service_worker_registration_id,
+ const url::Origin& origin,
blink::mojom::ContentIndexService::GetDescriptionsCallback callback);
// Gets the icon for |description_id| and invokes |callback| on the UI
@@ -95,6 +96,7 @@ class CONTENT_EXPORT ContentIndexDatabase {
blink::mojom::ContentIndexService::DeleteCallback callback);
void GetDescriptionsOnCoreThread(
int64_t service_worker_registration_id,
+ const url::Origin& origin,
blink::mojom::ContentIndexService::GetDescriptionsCallback callback);
void GetIconsOnCoreThread(int64_t service_worker_registration_id,
const std::string& description_id,
diff --git a/content/browser/content_index/content_index_database_unittest.cc b/content/browser/content_index/content_index_database_unittest.cc
index 3787ffbff591410f90065b78fd5c177567e335b3..4058a334ee229c0e2bf58e78f3884e6ad910eb7e 100644
--- a/content/browser/content_index/content_index_database_unittest.cc
+++ b/content/browser/content_index/content_index_database_unittest.cc
@@ -114,7 +114,7 @@ class ContentIndexDatabaseTest : public ::testing::Test {
void SetUp() override {
// Register Service Worker.
- service_worker_registration_id_ = RegisterServiceWorker();
+ service_worker_registration_id_ = RegisterServiceWorker(origin_);
ASSERT_NE(service_worker_registration_id_,
blink::mojom::kInvalidServiceWorkerRegistrationId);
database_ = std::make_unique<ContentIndexDatabase>(
@@ -164,7 +164,7 @@ class ContentIndexDatabaseTest : public ::testing::Test {
base::RunLoop run_loop;
std::vector<blink::mojom::ContentDescriptionPtr> descriptions;
database_->GetDescriptions(
- service_worker_registration_id_,
+ service_worker_registration_id_, origin_,
base::BindOnce(&GetDescriptionsCallback, run_loop.QuitClosure(),
out_error, &descriptions));
run_loop.Run();
@@ -222,6 +222,11 @@ class ContentIndexDatabaseTest : public ::testing::Test {
return service_worker_registration_id_;
}
+ void set_service_worker_registration_id(
+ int64_t service_worker_registration_id) {
+ service_worker_registration_id_ = service_worker_registration_id;
+ }
+
ContentIndexDatabase* database() { return database_.get(); }
BrowserTaskEnvironment& task_environment() { return task_environment_; }
@@ -230,15 +235,14 @@ class ContentIndexDatabaseTest : public ::testing::Test {
GURL launch_url() { return origin_.GetURL(); }
- private:
- int64_t RegisterServiceWorker() {
- GURL script_url(origin_.GetURL().spec() + "sw.js");
+ int64_t RegisterServiceWorker(const url::Origin& origin) {
+ GURL script_url(origin.GetURL().spec() + "sw.js");
int64_t service_worker_registration_id =
blink::mojom::kInvalidServiceWorkerRegistrationId;
{
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = origin_.GetURL();
+ options.scope = origin.GetURL();
base::RunLoop run_loop;
embedded_worker_test_helper_.context()->RegisterServiceWorker(
script_url, options, blink::mojom::FetchClientSettingsObject::New(),
@@ -258,7 +262,7 @@ class ContentIndexDatabaseTest : public ::testing::Test {
{
base::RunLoop run_loop;
embedded_worker_test_helper_.context()->registry()->FindRegistrationForId(
- service_worker_registration_id, origin_,
+ service_worker_registration_id, origin,
base::BindOnce(&DidFindServiceWorkerRegistration,
&service_worker_registration_,
run_loop.QuitClosure()));
@@ -276,6 +280,7 @@ class ContentIndexDatabaseTest : public ::testing::Test {
return service_worker_registration_id;
}
+ private:
BrowserTaskEnvironment task_environment_; // Must be first member.
ContentIndexTestBrowserContext browser_context_;
url::Origin origin_ = url::Origin::Create(GURL("https://example.com"));
@@ -314,6 +319,24 @@ TEST_F(ContentIndexDatabaseTest, DatabaseOperations) {
EXPECT_TRUE(descriptions[0]->Equals(*expected_description));
}
+TEST_F(ContentIndexDatabaseTest, DatabaseOperationsBadSWID) {
+ url::Origin other_origin = url::Origin::Create(GURL("https://other.com"));
+ int64_t other_service_worker_registration_id =
+ RegisterServiceWorker(other_origin);
+ ASSERT_NE(other_service_worker_registration_id,
+ blink::mojom::kInvalidServiceWorkerRegistrationId);
+ set_service_worker_registration_id(other_service_worker_registration_id);
+
+ blink::mojom::ContentIndexError error;
+ auto descriptions = GetDescriptions(&error);
+ EXPECT_TRUE(descriptions.empty());
+ EXPECT_EQ(error, blink::mojom::ContentIndexError::STORAGE_ERROR);
+
+ EXPECT_EQ(AddEntry(CreateDescription("id1")),
+ blink::mojom::ContentIndexError::STORAGE_ERROR);
+ EXPECT_EQ(DeleteEntry("id2"), blink::mojom::ContentIndexError::STORAGE_ERROR);
+}
+
TEST_F(ContentIndexDatabaseTest, AddDuplicateIdWillOverwrite) {
auto description1 = CreateDescription("id");
description1->title = "title1";
diff --git a/content/browser/content_index/content_index_service_impl.cc b/content/browser/content_index/content_index_service_impl.cc
index 81135e8b431d87ee371c0ca8912ee5dc93adfc17..73d54a16bb759156eb2869d2e8a6293f9cf0de0a 100644
--- a/content/browser/content_index/content_index_service_impl.cc
+++ b/content/browser/content_index/content_index_service_impl.cc
@@ -153,7 +153,7 @@ void ContentIndexServiceImpl::GetDescriptions(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content_index_context_->database().GetDescriptions(
- service_worker_registration_id, std::move(callback));
+ service_worker_registration_id, origin_, std::move(callback));
}
} // namespace content

View File

@@ -0,0 +1,701 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mike Jackson <mjackson@microsoft.com>
Date: Wed, 9 Jun 2021 16:48:30 +0000
Subject: dpwas: Window Control Overlay API values account for page zoom factor
The overlay's bounding rect passed from the browser process
to the render process doesn't take the page's zoom factor
(browser zoom - Ctrl+/-) into account. The bounding rect is
exposed via a JS API/Event and CSS environment variables, so
we need to convert from Frame space coordinates to unzoomed
CSS pixels. When calculating the new rect, ensure that we return
a slightly larger rect if needed to avoid rendering contents
smaller than the Window Control Overlay. e.g. If the height of
the Window Control Overlay is 32, and page's zoom factor is 500%
we will return a height of 7, instead of 6.
LocalFrame is notified of page zoom change via
SynchronizeVisualProperties, to ensure we are only computing this
in a single pass, we also add the Window Control Overlay rect
to the SynchronizeVisualProperties message.
Manual testing:
1) Enable 'Desktop PWA Window Controls Overlay' flags
2) Install https://amandabaker.github.io/pwa/windowControlsOverlay-newCSSVars/index.html
3) Toggle Window Control Overlay on
4) Change zoom level for PWA via the 3 dots menu
5) As you increase the zoom level, the values returned should decrease
6) As you decrease the zoom level, the values returned should increase
Screenshots:
100%: https://imgur.com/a/L4MV4RW
80%: https://imgur.com/a/xH79oZg
125%: https://imgur.com/a/CcqlkPV
Explainer: https://github.com/WICG/window-controls-overlay/blob/master/explainer.md
Design Doc: https://docs.google.com/document/d/1k0YL_-VMLIfjYCgJ2v6cMvuUv2qMKg4BgLI2tJ4qtyo/edit?usp=sharing
I2P: https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/cper6nNLFRQ/hU91kfCWBQAJ
Bug: 937121, 1213123
Change-Id: I6744bb5a64b4021195734464b9a024e15277baa7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2918946
Commit-Queue: Mike Jackson <mjackson@microsoft.com>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#890815}
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc
index 26c7a93644bb2b9f58817294265b80de33e9ef1b..3780835536c56f076831aadac63878133f21a0cd 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -91,6 +91,10 @@ blink::mojom::DisplayMode RenderWidgetHostDelegate::GetDisplayMode() const {
return blink::mojom::DisplayMode::kBrowser;
}
+gfx::Rect RenderWidgetHostDelegate::GetWindowsControlsOverlayRect() const {
+ return gfx::Rect();
+}
+
bool RenderWidgetHostDelegate::HasMouseLock(
RenderWidgetHostImpl* render_widget_host) {
return false;
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index 51bcc78ecd8f5f40e90a5e9077ac59b37c5c3e13..74d81a2a91ef515c3b89e2ceaa197b894c9fd9b7 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -215,6 +215,10 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// to frame-based widgets. Other widgets are always kBrowser.
virtual blink::mojom::DisplayMode GetDisplayMode() const;
+ // Returns the Window Control Overlay rectangle. Only applies to an
+ // outermost main frame's widget. Other widgets always returns an empty rect.
+ virtual gfx::Rect GetWindowsControlsOverlayRect() const;
+
// Notification that the widget has lost capture.
virtual void LostCapture(RenderWidgetHostImpl* render_widget_host) {}
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index fc8916ac6dc76968e0cbd06877ffb80c95f3abf4..18f0ea3b8ea34f6287e92299ef147bccaedd302a 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -879,6 +879,8 @@ blink::VisualProperties RenderWidgetHostImpl::GetVisualProperties() {
auto& current_screen_info = visual_properties.screen_infos.mutable_current();
visual_properties.is_fullscreen_granted = delegate_->IsFullscreen();
+ visual_properties.window_controls_overlay_rect =
+ delegate_->GetWindowsControlsOverlayRect();
if (is_frame_widget)
visual_properties.display_mode = delegate_->GetDisplayMode();
@@ -2659,7 +2661,9 @@ bool RenderWidgetHostImpl::StoredVisualPropertiesNeedsUpdate(
old_visual_properties->is_pinch_gesture_active !=
new_visual_properties.is_pinch_gesture_active ||
old_visual_properties->root_widget_window_segments !=
- new_visual_properties.root_widget_window_segments;
+ new_visual_properties.root_widget_window_segments ||
+ old_visual_properties->window_controls_overlay_rect !=
+ new_visual_properties.window_controls_overlay_rect;
}
void RenderWidgetHostImpl::AutoscrollStart(const gfx::PointF& position) {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index ca51a8a45570fafc0dfe2b400cbb7172a9be632d..835a100a98882e3fff1e679ed596171ce865a653 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -7872,10 +7872,22 @@ gfx::Size WebContentsImpl::GetSize() {
#endif // !defined(OS_MAC)
+gfx::Rect WebContentsImpl::GetWindowsControlsOverlayRect() const {
+ return window_controls_overlay_rect_;
+}
+
void WebContentsImpl::UpdateWindowControlsOverlay(
const gfx::Rect& bounding_rect) {
- GetMainFrame()->GetAssociatedLocalMainFrame()->UpdateWindowControlsOverlay(
- bounding_rect);
+ if (window_controls_overlay_rect_ == bounding_rect)
+ return;
+
+ window_controls_overlay_rect_ = bounding_rect;
+
+ // Updates to the |window_controls_overlay_rect_| are sent via
+ // the VisualProperties message.
+ if (RenderWidgetHost* render_widget_host =
+ GetMainFrame()->GetRenderWidgetHost())
+ render_widget_host->SynchronizeVisualProperties();
}
BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 17034e75d2ab5bd4e716e9c72277c77a53387808..3e32a9b4e17bb515066acaf014d1fe659cc83772 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -960,6 +960,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool IsWidgetForMainFrame(RenderWidgetHostImpl* render_widget_host) override;
bool IsShowingContextMenuOnPage() const override;
void DidChangeScreenOrientation() override;
+ gfx::Rect GetWindowsControlsOverlayRect() const override;
// RenderFrameHostManager::Delegate ------------------------------------------
@@ -2091,6 +2092,12 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// with OOPIF renderers.
blink::mojom::TextAutosizerPageInfo text_autosizer_page_info_;
+ // Stores the rect of the Windows Control Overlay, which contains system UX
+ // affordances (e.g. close), for installed desktop Progress Web Apps (PWAs),
+ // if the app specifies the 'window-controls-overlay' DisplayMode in its
+ // manifest. This is in frame space coordinates.
+ gfx::Rect window_controls_overlay_rect_;
+
// Observe native theme for changes to dark mode, preferred color scheme, and
// preferred contrast. Used to notify the renderer of preferred color scheme
// and preferred contrast changes.
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 2e75cbf168dbfa48d9f094ed84398197fd0487aa..73dc93a8afd6fa1ff38e900590681e22d43f7ca4 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -43,6 +43,7 @@
#include "content/public/browser/back_forward_cache.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/file_select_listener.h"
+#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/load_notification_details.h"
@@ -88,6 +89,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "url/gurl.h"
@@ -4466,19 +4468,74 @@ class WebContentsImplBrowserTestWindowControlsOverlay
}
void ValidateTitlebarAreaCSSValue(const std::string& name,
- const std::string& expected_result) {
+ int expected_result) {
SCOPED_TRACE(name);
-
EXPECT_EQ(
expected_result,
EvalJs(shell()->web_contents(),
JsReplace(
- "(() => {const e = document.getElementById('target');const "
- "style = window.getComputedStyle(e, null); return "
- "style.getPropertyValue($1);})();",
+ "(() => {"
+ "const e = document.getElementById('target');"
+ "const style = window.getComputedStyle(e, null);"
+ "return Math.round(style.getPropertyValue($1).replace('px', "
+ "''));"
+ "})();",
name)));
}
+
+ void ValidateWindowsControlOverlayState(WebContents* web_contents,
+ const gfx::Rect& expected_rect,
+ int css_fallback_value) {
+ EXPECT_EQ(!expected_rect.IsEmpty(),
+ EvalJs(web_contents, "navigator.windowControlsOverlay.visible"));
+ EXPECT_EQ(
+ expected_rect.x(),
+ EvalJs(web_contents,
+ "navigator.windowControlsOverlay.getBoundingClientRect().x"));
+ EXPECT_EQ(
+ expected_rect.y(),
+ EvalJs(web_contents,
+ "navigator.windowControlsOverlay.getBoundingClientRect().y"));
+ EXPECT_EQ(
+ expected_rect.width(),
+ EvalJs(
+ web_contents,
+ "navigator.windowControlsOverlay.getBoundingClientRect().width"));
+ EXPECT_EQ(
+ expected_rect.height(),
+ EvalJs(
+ web_contents,
+ "navigator.windowControlsOverlay.getBoundingClientRect().height"));
+
+ // When the overlay is not visible, the environment variables should be
+ // undefined, and the the fallback value should be used.
+ gfx::Rect css_rect = expected_rect;
+ if (css_rect.IsEmpty()) {
+ css_rect.SetRect(css_fallback_value, css_fallback_value,
+ css_fallback_value, css_fallback_value);
+ }
+
+ ValidateTitlebarAreaCSSValue("left", css_rect.x());
+ ValidateTitlebarAreaCSSValue("top", css_rect.y());
+ ValidateTitlebarAreaCSSValue("width", css_rect.width());
+ ValidateTitlebarAreaCSSValue("height", css_rect.height());
+ }
+
+ void WaitForWindowControlsOverlayUpdate(
+ WebContents* web_contents,
+ const gfx::Rect& bounding_client_rect) {
+ EXPECT_TRUE(
+ ExecJs(web_contents->GetMainFrame(),
+ "navigator.windowControlsOverlay.ongeometrychange = (e) => {"
+ " document.title = 'ongeometrychange'"
+ "}"));
+
+ web_contents->UpdateWindowControlsOverlay(bounding_client_rect);
+ TitleWatcher title_watcher(web_contents, u"ongeometrychange");
+ ignore_result(title_watcher.WaitAndGetTitle());
+ }
+
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
@@ -4500,24 +4557,12 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestWindowControlsOverlay,
// empty.
int empty_rect_value = 0;
- EXPECT_EQ(false,
- EvalJs(web_contents, "navigator.windowControlsOverlay.visible"));
- EXPECT_EQ(
- empty_rect_value,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().x"));
- EXPECT_EQ(
- empty_rect_value,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().y"));
- EXPECT_EQ(
- empty_rect_value,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().width"));
- EXPECT_EQ(
- empty_rect_value,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().height"));
+
+ // Update bounds and ensure that JS APIs and CSS variables are updated.
+ gfx::Rect bounding_client_rect(1, 2, 3, 4);
+ WaitForWindowControlsOverlayUpdate(web_contents, bounding_client_rect);
+ ValidateWindowsControlOverlayState(web_contents, bounding_client_rect, 50);
+}
// When the overlay is not visble, the environment variables should be
// undefined, and the the fallback value of 50px should be used.
@@ -4535,31 +4580,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestWindowControlsOverlay,
gfx::Rect bounding_client_rect =
gfx::Rect(new_x, new_y, new_width, new_height);
- web_contents->UpdateWindowControlsOverlay(bounding_client_rect);
-
- EXPECT_EQ(true,
- EvalJs(web_contents, "navigator.windowControlsOverlay.visible"));
- EXPECT_EQ(
- new_x,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().x"));
- EXPECT_EQ(
- new_y,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().y"));
- EXPECT_EQ(
- new_width,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().width"));
- EXPECT_EQ(
- new_height,
- EvalJs(web_contents,
- "navigator.windowControlsOverlay.getBoundingClientRect().height"));
-
- ValidateTitlebarAreaCSSValue("left", "1px");
- ValidateTitlebarAreaCSSValue("top", "2px");
- ValidateTitlebarAreaCSSValue("width", "3px");
- ValidateTitlebarAreaCSSValue("height", "4px");
+ // Update bounds and ensure that JS APIs and CSS variables are updated.
+ gfx::Rect bounding_client_rect(0, 0, 100, 32);
+ WaitForWindowControlsOverlayUpdate(web_contents, bounding_client_rect);
+ ValidateWindowsControlOverlayState(web_contents, bounding_client_rect, 55);
+
+ // Now toggle Windows Controls Overlay off.
+ gfx::Rect empty_rect;
+ WaitForWindowControlsOverlayUpdate(web_contents, empty_rect);
+ ValidateWindowsControlOverlayState(web_contents, empty_rect, 55);
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestWindowControlsOverlay,
@@ -4568,14 +4597,16 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestWindowControlsOverlay,
GURL url(url::kAboutBlankURL);
EXPECT_TRUE(NavigateToURL(shell(), url));
- EXPECT_TRUE(ExecuteScript(
- web_contents->GetMainFrame(),
- "geometrychangeCount = 0;"
- "navigator.windowControlsOverlay.ongeometrychange = (e) => {"
- " geometrychangeCount++;"
- " rect = e.boundingRect;"
- " visible = e.visible;"
- "}"));
+
+ EXPECT_TRUE(
+ ExecJs(web_contents->GetMainFrame(),
+ "geometrychangeCount = 0;"
+ "navigator.windowControlsOverlay.ongeometrychange = (e) => {"
+ " geometrychangeCount++;"
+ " rect = e.boundingRect;"
+ " visible = e.visible;"
+ " document.title = 'ongeometrychange' + geometrychangeCount"
+ "}"));
WaitForLoadStop(web_contents);
@@ -4584,23 +4615,107 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestWindowControlsOverlay,
EXPECT_EQ(0, EvalJs(web_contents, "geometrychangeCount"));
// Information about the bounds should be updated.
- const int x = 2;
- const int y = 2;
- const int width = 2;
- const int height = 2;
-
- gfx::Rect bounding_client_rect = gfx::Rect(x, y, width, height);
-
+ gfx::Rect bounding_client_rect = gfx::Rect(2, 3, 4, 5);
web_contents->UpdateWindowControlsOverlay(bounding_client_rect);
+ TitleWatcher title_watcher(web_contents, u"ongeometrychange1");
+ ignore_result(title_watcher.WaitAndGetTitle());
// Expect the "geometrychange" event to have fired once.
EXPECT_EQ(1, EvalJs(web_contents, "geometrychangeCount"));
// Validate the event payload.
EXPECT_EQ(true, EvalJs(web_contents, "visible"));
- EXPECT_EQ(x, EvalJs(web_contents, "rect.x;"));
- EXPECT_EQ(y, EvalJs(web_contents, "rect.y"));
- EXPECT_EQ(width, EvalJs(web_contents, "rect.width"));
- EXPECT_EQ(height, EvalJs(web_contents, "rect.height"));
+ EXPECT_EQ(bounding_client_rect.x(), EvalJs(web_contents, "rect.x;"));
+ EXPECT_EQ(bounding_client_rect.y(), EvalJs(web_contents, "rect.y"));
+ EXPECT_EQ(bounding_client_rect.width(), EvalJs(web_contents, "rect.width"));
+ EXPECT_EQ(bounding_client_rect.height(), EvalJs(web_contents, "rect.height"));
+}
+
+#if !defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestWindowControlsOverlay,
+ ValidatePageScaleChangesInfoAndFiresEvent) {
+ auto* web_contents = shell()->web_contents();
+ GURL url(
+ R"(data:text/html,<body><div id=target style="position=absolute;
+ left: env(titlebar-area-x, 60px);
+ top: env(titlebar-area-y, 60px);
+ width: env(titlebar-area-width, 60px);
+ height: env(titlebar-area-height, 60px);"></div></body>)");
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ WaitForLoadStop(web_contents);
+
+ gfx::Rect bounding_client_rect = gfx::Rect(5, 10, 15, 20);
+ WaitForWindowControlsOverlayUpdate(web_contents, bounding_client_rect);
+
+ // Update zoom level, confirm the "geometrychange" event is fired,
+ // and CSS variables are updated
+ EXPECT_TRUE(
+ ExecJs(web_contents->GetMainFrame(),
+ "geometrychangeCount = 0;"
+ "navigator.windowControlsOverlay.ongeometrychange = (e) => {"
+ " geometrychangeCount++;"
+ " rect = e.boundingRect;"
+ " visible = e.visible;"
+ " document.title = 'ongeometrychangefromzoomlevel'"
+ "}"));
+ content::HostZoomMap::SetZoomLevel(web_contents, 1.5);
+ TitleWatcher title_watcher(web_contents, u"ongeometrychangefromzoomlevel");
+ ignore_result(title_watcher.WaitAndGetTitle());
+
+ // Validate the event payload.
+ double zoom_factor = blink::PageZoomLevelToZoomFactor(
+ content::HostZoomMap::GetZoomLevel(web_contents));
+ gfx::Rect scaled_rect =
+ gfx::ScaleToEnclosingRectSafe(bounding_client_rect, 1.0f / zoom_factor);
+
+ EXPECT_EQ(true, EvalJs(web_contents, "visible"));
+ EXPECT_EQ(scaled_rect.x(), EvalJs(web_contents, "rect.x"));
+ EXPECT_EQ(scaled_rect.y(), EvalJs(web_contents, "rect.y"));
+ EXPECT_EQ(scaled_rect.width(), EvalJs(web_contents, "rect.width"));
+ EXPECT_EQ(scaled_rect.height(), EvalJs(web_contents, "rect.height"));
+ ValidateWindowsControlOverlayState(web_contents, scaled_rect, 60);
+}
+#endif
+
+class WebContentsImplBrowserTestWindowControlsOverlayNonOneDeviceScaleFactor
+ : public WebContentsImplBrowserTestWindowControlsOverlay {
+ public:
+ void SetUp() override {
+#if defined(OS_MAC)
+ // Device scale factor on MacOSX is always an integer.
+ EnablePixelOutput(2.0f);
+#else
+ EnablePixelOutput(1.25f);
+#endif
+ WebContentsImplBrowserTestWindowControlsOverlay::SetUp();
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(
+ WebContentsImplBrowserTestWindowControlsOverlayNonOneDeviceScaleFactor,
+ ValidateScaledCorrectly) {
+ auto* web_contents = shell()->web_contents();
+ GURL url(
+ R"(data:text/html,<body><div id=target style="position=absolute;
+ left: env(titlebar-area-x, 70px);
+ top: env(titlebar-area-y, 70px);
+ width: env(titlebar-area-width, 70px);
+ height: env(titlebar-area-height, 70px);"></div></body>)");
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ WaitForLoadStop(web_contents);
+#if defined(OS_MAC)
+ // Device scale factor on MacOSX is always an integer.
+ ASSERT_EQ(2.0f,
+ web_contents->GetRenderWidgetHostView()->GetDeviceScaleFactor());
+#else
+ ASSERT_EQ(1.25f,
+ web_contents->GetRenderWidgetHostView()->GetDeviceScaleFactor());
+#endif
+
+ gfx::Rect bounding_client_rect = gfx::Rect(5, 10, 15, 20);
+ WaitForWindowControlsOverlayUpdate(web_contents, bounding_client_rect);
+ ValidateWindowsControlOverlayState(web_contents, bounding_client_rect, 70);
}
} // namespace content
diff --git a/third_party/blink/common/widget/visual_properties.cc b/third_party/blink/common/widget/visual_properties.cc
index 433ca5954c9f316905f289948ab2e4ebe66b7833..55932091bafe8959c855529d49b9f66cd6e386f0 100644
--- a/third_party/blink/common/widget/visual_properties.cc
+++ b/third_party/blink/common/widget/visual_properties.cc
@@ -33,7 +33,8 @@ bool VisualProperties::operator==(const VisualProperties& other) const {
page_scale_factor == other.page_scale_factor &&
compositing_scale_factor == other.compositing_scale_factor &&
root_widget_window_segments == other.root_widget_window_segments &&
- is_pinch_gesture_active == other.is_pinch_gesture_active;
+ is_pinch_gesture_active == other.is_pinch_gesture_active &&
+ window_controls_overlay_rect == other.window_controls_overlay_rect;
}
bool VisualProperties::operator!=(const VisualProperties& other) const {
diff --git a/third_party/blink/common/widget/visual_properties_mojom_traits.cc b/third_party/blink/common/widget/visual_properties_mojom_traits.cc
index d378def431a2643de08951ff861b68868b1d7250..262eec364918a668a2f5e65af2044c24d3380aa7 100644
--- a/third_party/blink/common/widget/visual_properties_mojom_traits.cc
+++ b/third_party/blink/common/widget/visual_properties_mojom_traits.cc
@@ -24,6 +24,7 @@ bool StructTraits<
!data.ReadBrowserControlsParams(&out->browser_controls_params) ||
!data.ReadLocalSurfaceId(&out->local_surface_id) ||
!data.ReadRootWidgetWindowSegments(&out->root_widget_window_segments) ||
+ !data.ReadWindowControlsOverlayRect(&out->window_controls_overlay_rect) ||
data.page_scale_factor() <= 0 || data.compositing_scale_factor() <= 0)
return false;
out->auto_resize_enabled = data.auto_resize_enabled();
diff --git a/third_party/blink/public/common/widget/visual_properties.h b/third_party/blink/public/common/widget/visual_properties.h
index 3c16c86e704558b40e00b40264a4d7018d89fb5e..e020adae74d1f061bbbfc5bc10e8a40a69f93410 100644
--- a/third_party/blink/public/common/widget/visual_properties.h
+++ b/third_party/blink/public/common/widget/visual_properties.h
@@ -129,6 +129,13 @@ struct BLINK_COMMON_EXPORT VisualProperties {
// main frame's renderer, and needs to be shared with subframes.
bool is_pinch_gesture_active = false;
+ // The rect of the Windows Control Overlay, which contains system UX
+ // affordances (e.g. close), for installed desktop Progress Web Apps (PWAs),
+ // if the app specifies the 'window-controls-overlay' DisplayMode in its
+ // manifest. This is only valid and to be consumed by the outermost main
+ // frame.
+ gfx::Rect window_controls_overlay_rect;
+
VisualProperties();
VisualProperties(const VisualProperties& other);
~VisualProperties();
diff --git a/third_party/blink/public/common/widget/visual_properties_mojom_traits.h b/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
index f6634310fd17acc7299db892d68aea770578a0f1..8d7ab89e5d434e4098a55c6b78d06bfb6f3faa29 100644
--- a/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
+++ b/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
@@ -97,6 +97,11 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::VisualPropertiesDataView,
return r.is_pinch_gesture_active;
}
+ static const gfx::Rect& window_controls_overlay_rect(
+ const blink::VisualProperties& r) {
+ return r.window_controls_overlay_rect;
+ }
+
static bool Read(blink::mojom::VisualPropertiesDataView r,
blink::VisualProperties* out);
};
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index add4a22fe76818d5fa7c124f85a781da387ba3f4..cbbbdfd799135d8c86f9f2eecd558771627991f2 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -1116,10 +1116,6 @@ interface LocalMainFrame {
UpdateBrowserControlsState(cc.mojom.BrowserControlsState constraints,
cc.mojom.BrowserControlsState current,
bool animate);
-
- // Notify renderer that the window controls overlay has changed size or
- // visibility.
- UpdateWindowControlsOverlay(gfx.mojom.Rect window_controls_overlay_rect);
};
// Implemented in Blink, this interface defines remote main-frame-specific
diff --git a/third_party/blink/public/mojom/widget/visual_properties.mojom b/third_party/blink/public/mojom/widget/visual_properties.mojom
index b2fe7bf659bcfdc183e57ad7c4e45f1c422a246f..43a4874cfae908754c476a508544154e1088634e 100644
--- a/third_party/blink/public/mojom/widget/visual_properties.mojom
+++ b/third_party/blink/public/mojom/widget/visual_properties.mojom
@@ -92,4 +92,12 @@ struct VisualProperties {
// Indicates whether a pinch gesture is currently active. Originates in the
// main frame's renderer, and needs to be shared with subframes.
bool is_pinch_gesture_active;
+
+ // The rect of the Windows Control Overlay, which contains system UX
+ // affordances (e.g. close), for installed desktop Progress Web Apps (PWAs),
+ // if the app specifies the 'window-controls-overlay' DisplayMode in its
+ // manifest. This is only valid and to be consumed by the outermost main
+ // frame.
+ gfx.mojom.Rect window_controls_overlay_rect;
+
};
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index d6cf1cbb0beb65f0003051f67d5fa5b723c77a74..5f991049ea325368543d134cbe95614625b30004 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -2930,31 +2930,71 @@ void LocalFrame::UpdateBrowserControlsState(
}
void LocalFrame::UpdateWindowControlsOverlay(
- const gfx::Rect& window_controls_overlay_rect) {
+
+ const gfx::Rect& bounding_rect_in_dips) {
+ if (!RuntimeEnabledFeatures::WebAppWindowControlsOverlayEnabled(nullptr))
+ return;
+
+ // The rect passed to us from content is in DIP screen space, relative to the
+ // main frame, and needs to move to CSS space. This doesn't take the page's
+ // zoom factor into account so we must scale by the inverse of the page zoom
+ // in order to get correct CSS space coordinates. Note that when
+ // use-zoom-for-dsf is enabled, WindowToViewportScalar will be the true device
+ // scale factor, and PageZoomFactor will be the combination of the device
+ // scale factor and the zoom percent of the page. It is preferable to compute
+ // a rect that is slightly larger than one that would render smaller than the
+ // window control overlay.
+ LocalFrame& local_frame_root = LocalFrameRoot();
+ const float window_to_viewport_factor =
+ GetPage()->GetChromeClient().WindowToViewportScalar(&local_frame_root,
+ 1.0f);
+ const float zoom_factor = local_frame_root.PageZoomFactor();
+ const float scale_factor = zoom_factor / window_to_viewport_factor;
+ gfx::Rect window_controls_overlay_rect =
+ gfx::ScaleToEnclosingRectSafe(bounding_rect_in_dips, 1.0f / scale_factor);
+
+ bool fire_event =
+ (window_controls_overlay_rect != window_controls_overlay_rect_);
+
is_window_controls_overlay_visible_ = !window_controls_overlay_rect.IsEmpty();
window_controls_overlay_rect_ = window_controls_overlay_rect;
DocumentStyleEnvironmentVariables& vars =
GetDocument()->GetStyleEngine().EnsureEnvironmentVariables();
- vars.SetVariable(
- UADefinedVariable::kTitlebarAreaX,
- StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.x()));
- vars.SetVariable(
- UADefinedVariable::kTitlebarAreaY,
- StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.y()));
- vars.SetVariable(UADefinedVariable::kTitlebarAreaWidth,
- StyleEnvironmentVariables::FormatPx(
- window_controls_overlay_rect_.width()));
- vars.SetVariable(UADefinedVariable::kTitlebarAreaHeight,
- StyleEnvironmentVariables::FormatPx(
- window_controls_overlay_rect_.height()));
-
- auto* window_controls_overlay =
- WindowControlsOverlay::FromIfExists(*DomWindow()->navigator());
-
- if (window_controls_overlay) {
- window_controls_overlay->WindowControlsOverlayChanged(
- window_controls_overlay_rect);
+
+ if (is_window_controls_overlay_visible_) {
+ vars.SetVariable(
+ UADefinedVariable::kTitlebarAreaX,
+ StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.x()));
+ vars.SetVariable(
+ UADefinedVariable::kTitlebarAreaY,
+ StyleEnvironmentVariables::FormatPx(window_controls_overlay_rect_.y()));
+ vars.SetVariable(UADefinedVariable::kTitlebarAreaWidth,
+ StyleEnvironmentVariables::FormatPx(
+ window_controls_overlay_rect_.width()));
+ vars.SetVariable(UADefinedVariable::kTitlebarAreaHeight,
+ StyleEnvironmentVariables::FormatPx(
+ window_controls_overlay_rect_.height()));
+ } else {
+ const UADefinedVariable vars_to_remove[] = {
+ UADefinedVariable::kTitlebarAreaX,
+ UADefinedVariable::kTitlebarAreaY,
+ UADefinedVariable::kTitlebarAreaWidth,
+ UADefinedVariable::kTitlebarAreaHeight,
+ };
+ for (auto var_to_remove : vars_to_remove) {
+ vars.RemoveVariable(StyleEnvironmentVariables::GetVariableName(var_to_remove));
+ }
+ }
+
+ if (fire_event) {
+ auto* window_controls_overlay =
+ WindowControlsOverlay::FromIfExists(*DomWindow()->navigator());
+
+ if (window_controls_overlay) {
+ window_controls_overlay->WindowControlsOverlayChanged(
+ window_controls_overlay_rect_);
+ }
}
}
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 38ad1f729ffc7416ae56c771f5b518fb63520c08..d725460b26f25ca5746126f76efdfc8722943492 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -732,8 +732,7 @@ class CORE_EXPORT LocalFrame final
void UpdateBrowserControlsState(cc::BrowserControlsState constraints,
cc::BrowserControlsState current,
bool animate) override;
- void UpdateWindowControlsOverlay(
- const gfx::Rect& window_controls_overlay_rect) override;
+ void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect_in_dips);
// mojom::FullscreenVideoElementHandler implementation:
void RequestFullscreenVideoElement() final;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 1f13dc8bce4a41b96bb2bfce776d6b55500db5b6..d33496ce445cb2af4b21cdd23bdc011d6214b352 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -1516,6 +1516,10 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
widget_base_->VisibleViewportSizeInDIPs()),
visual_properties.browser_controls_params);
}
+
+ LocalRootImpl()->GetFrame()->UpdateWindowControlsOverlay(
+ visual_properties.window_controls_overlay_rect);
+
} else {
// Widgets in a WebView's frame tree without a local main frame
// set the size of the WebView to be the |visible_viewport_size|, in order
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 2816268f68d8910b11c5b6ea6d0c2a1a92bd2e1a..ac95c2f8e18081cca7a2c14899c9d7a9444fa565 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -279,6 +279,7 @@ _CONFIG = [
'gfx::RectF',
'gfx::RRectF',
'gfx::ScaleToCeiledSize',
+ 'gfx::ScaleToEnclosingRectSafe',
'gfx::ScaleVector2d',
'gfx::Size',
'gfx::SizeF',

View File

@@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Denton <mpdenton@chromium.org>
Date: Thu, 3 Jun 2021 20:06:13 +0000
Subject: Linux sandbox: return ENOSYS for clone3
Because clone3 uses a pointer argument rather than a flags argument, we
cannot examine the contents with seccomp, which is essential to
preventing sandboxed processes from starting other processes. So, we
won't be able to support clone3 in Chromium. This CL modifies the
BPF policy to return ENOSYS for clone3 so glibc always uses the fallback
to clone.
Bug: 1213452
Change-Id: I7c7c585a319e0264eac5b1ebee1a45be2d782303
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2936184
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Commit-Queue: Matthew Denton <mpdenton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#888980}
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 05c39f0f564e3fc67abcf9941094b67be3257771..086c56a2be46120767db716b5e4376d68bd00581 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -178,6 +178,12 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
return RestrictCloneToThreadsAndEPERMFork();
}
+ // clone3 takes a pointer argument which we cannot examine, so return ENOSYS
+ // to force the libc to use clone. See https://crbug.com/1213452.
+ if (sysno == __NR_clone3) {
+ return Error(ENOSYS);
+ }
+
if (sysno == __NR_fcntl)
return RestrictFcntlCommands();

View File

@@ -0,0 +1,437 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Denton <mpdenton@chromium.org>
Date: Thu, 3 Jun 2021 19:02:10 +0000
Subject: Linux sandbox: update syscall numbers for all platforms.
This includes clone3 and the landlock system calls.
Bug: 1213452
Change-Id: Iaf14a7c9d455c7a22ad179b13541a60dcabaac09
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2934620
Auto-Submit: Matthew Denton <mpdenton@chromium.org>
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#888958}
diff --git a/sandbox/linux/system_headers/arm64_linux_syscalls.h b/sandbox/linux/system_headers/arm64_linux_syscalls.h
index a242c18c84213edb2f17443cb5a3e437add9d4c2..ab86b36353c22330241b0fc9b9be904490212313 100644
--- a/sandbox/linux/system_headers/arm64_linux_syscalls.h
+++ b/sandbox/linux/system_headers/arm64_linux_syscalls.h
@@ -1119,4 +1119,100 @@
#define __NR_rseq 293
#endif
+#if !defined(__NR_kexec_file_load)
+#define __NR_kexec_file_load 294
+#endif
+
+#if !defined(__NR_pidfd_send_signal)
+#define __NR_pidfd_send_signal 424
+#endif
+
+#if !defined(__NR_io_uring_setup)
+#define __NR_io_uring_setup 425
+#endif
+
+#if !defined(__NR_io_uring_enter)
+#define __NR_io_uring_enter 426
+#endif
+
+#if !defined(__NR_io_uring_register)
+#define __NR_io_uring_register 427
+#endif
+
+#if !defined(__NR_open_tree)
+#define __NR_open_tree 428
+#endif
+
+#if !defined(__NR_move_mount)
+#define __NR_move_mount 429
+#endif
+
+#if !defined(__NR_fsopen)
+#define __NR_fsopen 430
+#endif
+
+#if !defined(__NR_fsconfig)
+#define __NR_fsconfig 431
+#endif
+
+#if !defined(__NR_fsmount)
+#define __NR_fsmount 432
+#endif
+
+#if !defined(__NR_fspick)
+#define __NR_fspick 433
+#endif
+
+#if !defined(__NR_pidfd_open)
+#define __NR_pidfd_open 434
+#endif
+
+#if !defined(__NR_clone3)
+#define __NR_clone3 435
+#endif
+
+#if !defined(__NR_close_range)
+#define __NR_close_range 436
+#endif
+
+#if !defined(__NR_openat2)
+#define __NR_openat2 437
+#endif
+
+#if !defined(__NR_pidfd_getfd)
+#define __NR_pidfd_getfd 438
+#endif
+
+#if !defined(__NR_faccessat2)
+#define __NR_faccessat2 439
+#endif
+
+#if !defined(__NR_process_madvise)
+#define __NR_process_madvise 440
+#endif
+
+#if !defined(__NR_epoll_pwait2)
+#define __NR_epoll_pwait2 441
+#endif
+
+#if !defined(__NR_mount_setattr)
+#define __NR_mount_setattr 442
+#endif
+
+#if !defined(__NR_quotactl_path)
+#define __NR_quotactl_path 443
+#endif
+
+#if !defined(__NR_landlock_create_ruleset)
+#define __NR_landlock_create_ruleset 444
+#endif
+
+#if !defined(__NR_landlock_add_rule)
+#define __NR_landlock_add_rule 445
+#endif
+
+#if !defined(__NR_landlock_restrict_self)
+#define __NR_landlock_restrict_self 446
+#endif
+
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/system_headers/arm_linux_syscalls.h b/sandbox/linux/system_headers/arm_linux_syscalls.h
index 85da6f41c669969f43734ffbc9b50ddffb553066..9c44368a8eeaa5e755856af446229662287db927 100644
--- a/sandbox/linux/system_headers/arm_linux_syscalls.h
+++ b/sandbox/linux/system_headers/arm_linux_syscalls.h
@@ -1605,6 +1605,18 @@
#define __NR_mount_setattr (__NR_SYSCALL_BASE + 442)
#endif
+#if !defined(__NR_landlock_create_ruleset)
+#define __NR_landlock_create_ruleset (__NR_SYSCALL_BASE + 444)
+#endif
+
+#if !defined(__NR_landlock_add_rule)
+#define __NR_landlock_add_rule (__NR_SYSCALL_BASE + 445)
+#endif
+
+#if !defined(__NR_landlock_restrict_self)
+#define __NR_landlock_restrict_self (__NR_SYSCALL_BASE + 446)
+#endif
+
// ARM private syscalls.
#if !defined(__ARM_NR_BASE)
#define __ARM_NR_BASE (__NR_SYSCALL_BASE + 0xF0000)
diff --git a/sandbox/linux/system_headers/mips64_linux_syscalls.h b/sandbox/linux/system_headers/mips64_linux_syscalls.h
index ec75815a8424f94da18ea5fd5b419b1704ef4bfe..ae7cb48f57cc9b4cabca5ab28481780658bb8847 100644
--- a/sandbox/linux/system_headers/mips64_linux_syscalls.h
+++ b/sandbox/linux/system_headers/mips64_linux_syscalls.h
@@ -1271,4 +1271,148 @@
#define __NR_memfd_create (__NR_Linux + 314)
#endif
+#if !defined(__NR_bpf)
+#define __NR_bpf (__NR_Linux + 315)
+#endif
+
+#if !defined(__NR_execveat)
+#define __NR_execveat (__NR_Linux + 316)
+#endif
+
+#if !defined(__NR_userfaultfd)
+#define __NR_userfaultfd (__NR_Linux + 317)
+#endif
+
+#if !defined(__NR_membarrier)
+#define __NR_membarrier (__NR_Linux + 318)
+#endif
+
+#if !defined(__NR_mlock2)
+#define __NR_mlock2 (__NR_Linux + 319)
+#endif
+
+#if !defined(__NR_copy_file_range)
+#define __NR_copy_file_range (__NR_Linux + 320)
+#endif
+
+#if !defined(__NR_preadv2)
+#define __NR_preadv2 (__NR_Linux + 321)
+#endif
+
+#if !defined(__NR_pwritev2)
+#define __NR_pwritev2 (__NR_Linux + 322)
+#endif
+
+#if !defined(__NR_pkey_mprotect)
+#define __NR_pkey_mprotect (__NR_Linux + 323)
+#endif
+
+#if !defined(__NR_pkey_alloc)
+#define __NR_pkey_alloc (__NR_Linux + 324)
+#endif
+
+#if !defined(__NR_pkey_free)
+#define __NR_pkey_free (__NR_Linux + 325)
+#endif
+
+#if !defined(__NR_statx)
+#define __NR_statx (__NR_Linux + 326)
+#endif
+
+#if !defined(__NR_rseq)
+#define __NR_rseq (__NR_Linux + 327)
+#endif
+
+#if !defined(__NR_io_pgetevents)
+#define __NR_io_pgetevents (__NR_Linux + 328)
+#endif
+
+#if !defined(__NR_pidfd_send_signal)
+#define __NR_pidfd_send_signal (__NR_Linux + 424)
+#endif
+
+#if !defined(__NR_io_uring_setup)
+#define __NR_io_uring_setup (__NR_Linux + 425)
+#endif
+
+#if !defined(__NR_io_uring_enter)
+#define __NR_io_uring_enter (__NR_Linux + 426)
+#endif
+
+#if !defined(__NR_io_uring_register)
+#define __NR_io_uring_register (__NR_Linux + 427)
+#endif
+
+#if !defined(__NR_open_tree)
+#define __NR_open_tree (__NR_Linux + 428)
+#endif
+
+#if !defined(__NR_move_mount)
+#define __NR_move_mount (__NR_Linux + 429)
+#endif
+
+#if !defined(__NR_fsopen)
+#define __NR_fsopen (__NR_Linux + 430)
+#endif
+
+#if !defined(__NR_fsconfig)
+#define __NR_fsconfig (__NR_Linux + 431)
+#endif
+
+#if !defined(__NR_fsmount)
+#define __NR_fsmount (__NR_Linux + 432)
+#endif
+
+#if !defined(__NR_fspick)
+#define __NR_fspick (__NR_Linux + 433)
+#endif
+
+#if !defined(__NR_pidfd_open)
+#define __NR_pidfd_open (__NR_Linux + 434)
+#endif
+
+#if !defined(__NR_clone3)
+#define __NR_clone3 (__NR_Linux + 435)
+#endif
+
+#if !defined(__NR_close_range)
+#define __NR_close_range (__NR_Linux + 436)
+#endif
+
+#if !defined(__NR_openat2)
+#define __NR_openat2 (__NR_Linux + 437)
+#endif
+
+#if !defined(__NR_pidfd_getfd)
+#define __NR_pidfd_getfd (__NR_Linux + 438)
+#endif
+
+#if !defined(__NR_faccessat2)
+#define __NR_faccessat2 (__NR_Linux + 439)
+#endif
+
+#if !defined(__NR_process_madvise)
+#define __NR_process_madvise (__NR_Linux + 440)
+#endif
+
+#if !defined(__NR_epoll_pwait2)
+#define __NR_epoll_pwait2 (__NR_Linux + 441)
+#endif
+
+#if !defined(__NR_mount_setattr)
+#define __NR_mount_setattr (__NR_Linux + 442)
+#endif
+
+#if !defined(__NR_landlock_create_ruleset)
+#define __NR_landlock_create_ruleset (__NR_Linux + 444)
+#endif
+
+#if !defined(__NR_landlock_add_rule)
+#define __NR_landlock_add_rule (__NR_Linux + 445)
+#endif
+
+#if !defined(__NR_landlock_restrict_self)
+#define __NR_landlock_restrict_self (__NR_Linux + 446)
+#endif
+
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/system_headers/mips_linux_syscalls.h b/sandbox/linux/system_headers/mips_linux_syscalls.h
index 50d9ea11bfa48e8aff37b6c81214c4e72cb9fe5b..093778288bbbeb35305eac5ac1a1cfcd6e67c1dc 100644
--- a/sandbox/linux/system_headers/mips_linux_syscalls.h
+++ b/sandbox/linux/system_headers/mips_linux_syscalls.h
@@ -1685,4 +1685,16 @@
#define __NR_mount_setattr (__NR_Linux + 442)
#endif
+#if !defined(__NR_landlock_create_ruleset)
+#define __NR_landlock_create_ruleset (__NR_Linux + 444)
+#endif
+
+#if !defined(__NR_landlock_add_rule)
+#define __NR_landlock_add_rule (__NR_Linux + 445)
+#endif
+
+#if !defined(__NR_landlock_restrict_self)
+#define __NR_landlock_restrict_self (__NR_Linux + 446)
+#endif
+
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/system_headers/x86_32_linux_syscalls.h b/sandbox/linux/system_headers/x86_32_linux_syscalls.h
index 1720edb18103f93d009f5745ebda7fd52b7eba26..2c81a9301381812f4625d2a8b70d703c12a2df0f 100644
--- a/sandbox/linux/system_headers/x86_32_linux_syscalls.h
+++ b/sandbox/linux/system_headers/x86_32_linux_syscalls.h
@@ -1738,5 +1738,17 @@
#define __NR_mount_setattr 442
#endif
+#if !defined(__NR_landlock_create_ruleset)
+#define __NR_landlock_create_ruleset 444
+#endif
+
+#if !defined(__NR_landlock_add_rule)
+#define __NR_landlock_add_rule 445
+#endif
+
+#if !defined(__NR_landlock_restrict_self)
+#define __NR_landlock_restrict_self 446
+#endif
+
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/system_headers/x86_64_linux_syscalls.h b/sandbox/linux/system_headers/x86_64_linux_syscalls.h
index b0ae0a2edf6fd60f6f67440e6c2f32a9b9d33af0..e618c6237b068c5bcb85f03f24deccd6fcecf30b 100644
--- a/sandbox/linux/system_headers/x86_64_linux_syscalls.h
+++ b/sandbox/linux/system_headers/x86_64_linux_syscalls.h
@@ -1350,5 +1350,93 @@
#define __NR_rseq 334
#endif
+#if !defined(__NR_pidfd_send_signal)
+#define __NR_pidfd_send_signal 424
+#endif
+
+#if !defined(__NR_io_uring_setup)
+#define __NR_io_uring_setup 425
+#endif
+
+#if !defined(__NR_io_uring_enter)
+#define __NR_io_uring_enter 426
+#endif
+
+#if !defined(__NR_io_uring_register)
+#define __NR_io_uring_register 427
+#endif
+
+#if !defined(__NR_open_tree)
+#define __NR_open_tree 428
+#endif
+
+#if !defined(__NR_move_mount)
+#define __NR_move_mount 429
+#endif
+
+#if !defined(__NR_fsopen)
+#define __NR_fsopen 430
+#endif
+
+#if !defined(__NR_fsconfig)
+#define __NR_fsconfig 431
+#endif
+
+#if !defined(__NR_fsmount)
+#define __NR_fsmount 432
+#endif
+
+#if !defined(__NR_fspick)
+#define __NR_fspick 433
+#endif
+
+#if !defined(__NR_pidfd_open)
+#define __NR_pidfd_open 434
+#endif
+
+#if !defined(__NR_clone3)
+#define __NR_clone3 435
+#endif
+
+#if !defined(__NR_close_range)
+#define __NR_close_range 436
+#endif
+
+#if !defined(__NR_openat2)
+#define __NR_openat2 437
+#endif
+
+#if !defined(__NR_pidfd_getfd)
+#define __NR_pidfd_getfd 438
+#endif
+
+#if !defined(__NR_faccessat2)
+#define __NR_faccessat2 439
+#endif
+
+#if !defined(__NR_process_madvise)
+#define __NR_process_madvise 440
+#endif
+
+#if !defined(__NR_epoll_pwait2)
+#define __NR_epoll_pwait2 441
+#endif
+
+#if !defined(__NR_mount_setattr)
+#define __NR_mount_setattr 442
+#endif
+
+#if !defined(__NR_landlock_create_ruleset)
+#define __NR_landlock_create_ruleset 444
+#endif
+
+#if !defined(__NR_landlock_add_rule)
+#define __NR_landlock_add_rule 445
+#endif
+
+#if !defined(__NR_landlock_restrict_self)
+#define __NR_landlock_restrict_self 446
+#endif
+
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_

View File

@@ -0,0 +1,290 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Marijn Kruisselbrink <mek@chromium.org>
Date: Fri, 10 Sep 2021 21:31:17 +0000
Subject: M93: [IndexedDB] Add browser-side checks for committing transactions.
No new IPCs should come in for a transaction after it starts committing.
This CL adds browser-side checks in addition to the existing
renderer-side checks for this.
(cherry picked from commit ec3ddd67bae4c491ec1faba7be7cc988c425506c)
Bug: 1247766
Change-Id: If9d69d5a0320bfd3b615446710358dd439074795
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3149409
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Reviewed-by: Joshua Bell <jsbell@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#919898}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3154684
Auto-Submit: Victor Costan <pwnall@chromium.org>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/4577@{#1234}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index d6ee1e0e10530785da57ca32dce62f4ab488893f..037345a2f626936acdbf60c824aef10d21e893ea 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -87,6 +87,13 @@ void DatabaseImpl::RenameObjectStore(int64_t transaction_id,
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "RenameObjectStore was called after committing or aborting the "
+ "transaction");
+ return;
+ }
+
transaction->ScheduleTask(
blink::mojom::IDBTaskType::Preemptive,
BindWeakOperation(&IndexedDBDatabase::RenameObjectStoreOperation,
@@ -175,6 +182,12 @@ void DatabaseImpl::Get(int64_t transaction_id,
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "Get was called after committing or aborting the transaction");
+ return;
+ }
+
blink::mojom::IDBDatabase::GetCallback aborting_callback =
CreateCallbackAbortOnDestruct<blink::mojom::IDBDatabase::GetCallback,
blink::mojom::IDBDatabaseGetResultPtr>(
@@ -225,6 +238,12 @@ void DatabaseImpl::GetAll(int64_t transaction_id,
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "GetAll was called after committing or aborting the transaction");
+ return;
+ }
+
// Hypothetically, this could pass the receiver to the callback immediately.
// However, for result ordering issues, we need to PostTask to mimic
// all of the other operations.
@@ -264,6 +283,12 @@ void DatabaseImpl::SetIndexKeys(
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "SetIndexKeys was called after committing or aborting the transaction");
+ return;
+ }
+
transaction->ScheduleTask(
blink::mojom::IDBTaskType::Preemptive,
BindWeakOperation(&IndexedDBDatabase::SetIndexKeysOperation,
@@ -290,6 +315,13 @@ void DatabaseImpl::SetIndexesReady(int64_t transaction_id,
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "SetIndexesReady was called after committing or aborting the "
+ "transaction");
+ return;
+ }
+
transaction->ScheduleTask(
blink::mojom::IDBTaskType::Preemptive,
BindWeakOperation(&IndexedDBDatabase::SetIndexesReadyOperation,
@@ -327,6 +359,12 @@ void DatabaseImpl::OpenCursor(
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "OpenCursor was called after committing or aborting the transaction");
+ return;
+ }
+
blink::mojom::IDBDatabase::OpenCursorCallback aborting_callback =
CreateCallbackAbortOnDestruct<
blink::mojom::IDBDatabase::OpenCursorCallback,
@@ -376,6 +414,12 @@ void DatabaseImpl::Count(
if (!transaction)
return;
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "Count was called after committing or aborting the transaction");
+ return;
+ }
+
transaction->ScheduleTask(BindWeakOperation(
&IndexedDBDatabase::CountOperation, connection_->database()->AsWeakPtr(),
object_store_id, index_id,
@@ -401,6 +445,12 @@ void DatabaseImpl::DeleteRange(
if (!transaction)
return;
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "DeleteRange was called after committing or aborting the transaction");
+ return;
+ }
+
transaction->ScheduleTask(BindWeakOperation(
&IndexedDBDatabase::DeleteRangeOperation,
connection_->database()->AsWeakPtr(), object_store_id,
@@ -424,6 +474,13 @@ void DatabaseImpl::GetKeyGeneratorCurrentNumber(
if (!transaction)
return;
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "GetKeyGeneratorCurrentNumber was called after committing or aborting "
+ "the transaction");
+ return;
+ }
+
transaction->ScheduleTask(BindWeakOperation(
&IndexedDBDatabase::GetKeyGeneratorCurrentNumberOperation,
connection_->database()->AsWeakPtr(), object_store_id,
@@ -447,6 +504,12 @@ void DatabaseImpl::Clear(
if (!transaction)
return;
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "Clear was called after committing or aborting the transaction");
+ return;
+ }
+
transaction->ScheduleTask(BindWeakOperation(
&IndexedDBDatabase::ClearOperation, connection_->database()->AsWeakPtr(),
object_store_id, std::move(callbacks)));
@@ -474,6 +537,12 @@ void DatabaseImpl::CreateIndex(int64_t transaction_id,
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "CreateIndex was called after committing or aborting the transaction");
+ return;
+ }
+
transaction->ScheduleTask(
blink::mojom::IDBTaskType::Preemptive,
BindWeakOperation(&IndexedDBDatabase::CreateIndexOperation,
@@ -499,6 +568,12 @@ void DatabaseImpl::DeleteIndex(int64_t transaction_id,
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "DeleteIndex was called after committing or aborting the transaction");
+ return;
+ }
+
transaction->ScheduleTask(BindWeakOperation(
&IndexedDBDatabase::DeleteIndexOperation,
connection_->database()->AsWeakPtr(), object_store_id, index_id));
@@ -523,6 +598,12 @@ void DatabaseImpl::RenameIndex(int64_t transaction_id,
return;
}
+ if (!transaction->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "RenameIndex was called after committing or aborting the transaction");
+ return;
+ }
+
transaction->ScheduleTask(
BindWeakOperation(&IndexedDBDatabase::RenameIndexOperation,
connection_->database()->AsWeakPtr(), object_store_id,
diff --git a/content/browser/indexed_db/indexed_db_transaction.h b/content/browser/indexed_db/indexed_db_transaction.h
index 6acdd5db56dedeffdd613b04784045d25345aaf7..7536d35f00a4bd71d5f9a604448a5913bc48d156 100644
--- a/content/browser/indexed_db/indexed_db_transaction.h
+++ b/content/browser/indexed_db/indexed_db_transaction.h
@@ -67,6 +67,14 @@ class CONTENT_EXPORT IndexedDBTransaction {
// Signals the transaction for commit.
void SetCommitFlag();
+ // Returns false if the transaction has been signalled to commit, is in the
+ // process of committing, or finished committing or was aborted. Essentially
+ // when this returns false no tasks should be scheduled that try to modify
+ // the transaction.
+ bool IsAcceptingRequests() {
+ return !is_commit_pending_ && state_ != COMMITTING && state_ != FINISHED;
+ }
+
// This transaction is ultimately backed by a LevelDBScope. Aborting a
// transaction rolls back the LevelDBScopes, which (if LevelDBScopes is in
// single-sequence mode) can fail. This returns the result of that rollback,
diff --git a/content/browser/indexed_db/transaction_impl.cc b/content/browser/indexed_db/transaction_impl.cc
index 1abde1c7848ddc6ba40f1541a039088ff2848373..88227f763720c55cc3bfe0d8e226cb1246863068 100644
--- a/content/browser/indexed_db/transaction_impl.cc
+++ b/content/browser/indexed_db/transaction_impl.cc
@@ -57,6 +57,13 @@ void TransactionImpl::CreateObjectStore(int64_t object_store_id,
return;
}
+ if (!transaction_->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "CreateObjectStore was called after committing or aborting the "
+ "transaction");
+ return;
+ }
+
IndexedDBConnection* connection = transaction_->connection();
if (!connection->IsConnected())
return;
@@ -79,6 +86,13 @@ void TransactionImpl::DeleteObjectStore(int64_t object_store_id) {
return;
}
+ if (!transaction_->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "DeleteObjectStore was called after committing or aborting the "
+ "transaction");
+ return;
+ }
+
IndexedDBConnection* connection = transaction_->connection();
if (!connection->IsConnected())
return;
@@ -111,6 +125,12 @@ void TransactionImpl::Put(
return;
}
+ if (!transaction_->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "Put was called after committing or aborting the transaction");
+ return;
+ }
+
IndexedDBConnection* connection = transaction_->connection();
if (!connection->IsConnected()) {
IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
@@ -170,6 +190,12 @@ void TransactionImpl::PutAll(int64_t object_store_id,
return;
}
+ if (!transaction_->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "PutAll was called after committing or aborting the transaction");
+ return;
+ }
+
std::vector<std::vector<IndexedDBExternalObject>> external_objects_per_put(
puts.size());
for (size_t i = 0; i < puts.size(); i++) {
@@ -268,6 +294,12 @@ void TransactionImpl::Commit(int64_t num_errors_handled) {
if (!transaction_)
return;
+ if (!transaction_->IsAcceptingRequests()) {
+ mojo::ReportBadMessage(
+ "Commit was called after committing or aborting the transaction");
+ return;
+ }
+
IndexedDBConnection* connection = transaction_->connection();
if (!connection->IsConnected())
return;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Victor Costan <pwnall@chromium.org>
Date: Fri, 10 Sep 2021 22:37:26 +0000
Subject: M93: [IndexedDB] Don't ReportBadMessage for Commit calls.
We do seem to be getting commit calls quite a lot even after a
transaction has already started to be committed or aborted, so for now
just avoid killing the renderer until we figure out where these calls
are coming from.
(cherry picked from commit f9bf7be854ed80a792953e94dd56e1269a5bbe98)
Bug: 1247766
Change-Id: If7a4d4b12574c894addddbfcaf336295bd90e0a3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3154398
Reviewed-by: Daniel Murphy <dmurph@chromium.org>
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#920304}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3154726
Commit-Queue: Victor Costan <pwnall@chromium.org>
Reviewed-by: enne <enne@chromium.org>
Cr-Commit-Position: refs/branch-heads/4577@{#1235}
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
diff --git a/content/browser/indexed_db/transaction_impl.cc b/content/browser/indexed_db/transaction_impl.cc
index 88227f763720c55cc3bfe0d8e226cb1246863068..b0b19dd059d96320b4411f32d54d1d85ceb405ac 100644
--- a/content/browser/indexed_db/transaction_impl.cc
+++ b/content/browser/indexed_db/transaction_impl.cc
@@ -295,8 +295,8 @@ void TransactionImpl::Commit(int64_t num_errors_handled) {
return;
if (!transaction_->IsAcceptingRequests()) {
- mojo::ReportBadMessage(
- "Commit was called after committing or aborting the transaction");
+ // This really shouldn't be happening, but seems to be happening anyway. So
+ // rather than killing the renderer, simply ignore the request.
return;
}

View File

@@ -0,0 +1,527 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Clark DuVall <cduvall@chromium.org>
Date: Fri, 20 Aug 2021 00:52:03 +0000
Subject: Speculative fix for crash in URLLoader::OnBeforeSendHeadersComplete
I wasn't able to reproduce the crash, but this should prevent crashing
when accessing an invalid pointer for the HttpRequestHeaders. Instead of
passing a raw pointer, OnBeforeStartTransaction will now take optional
headers in the callback to modify the extra headers. If the job has been
destroyed, the callback will not be run since it was bound with a
WeakPtr to the job.
(cherry picked from commit c06b3928469bfd0e0a9fa6045b95a7be70ef393f)
Bug: 1221047
Change-Id: I93d5838b778e7283f7043fd2c841844941f52a85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3042975
Commit-Queue: Clark DuVall <cduvall@chromium.org>
Reviewed-by: Matt Mueller <mattm@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#905539}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3108058
Auto-Submit: Clark DuVall <cduvall@chromium.org>
Cr-Commit-Position: refs/branch-heads/4515@{#2070}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc
index e8a345b195cb282da8472d8776f474db38938d07..4345802376a414c2d497a52861554dfddf6926c2 100644
--- a/net/base/network_delegate.cc
+++ b/net/base/network_delegate.cc
@@ -35,14 +35,13 @@ int NetworkDelegate::NotifyBeforeURLRequest(URLRequest* request,
int NetworkDelegate::NotifyBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
TRACE_EVENT0(NetTracingCategory(),
"NetworkDelegate::NotifyBeforeStartTransation");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(headers);
DCHECK(!callback.is_null());
- return OnBeforeStartTransaction(request, std::move(callback), headers);
+ return OnBeforeStartTransaction(request, headers, std::move(callback));
}
int NetworkDelegate::NotifyHeadersReceived(
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h
index f93f91c0bd3af2b213314106838b3c318f9a67e4..8f35b2096b04b76a23a9ec8e6928af21c543d8b2 100644
--- a/net/base/network_delegate.h
+++ b/net/base/network_delegate.h
@@ -55,9 +55,11 @@ class NET_EXPORT NetworkDelegate {
int NotifyBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url);
+ using OnBeforeStartTransactionCallback =
+ base::OnceCallback<void(int, const base::Optional<HttpRequestHeaders>&)>;
int NotifyBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers);
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback);
int NotifyHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
@@ -132,7 +134,8 @@ class NET_EXPORT NetworkDelegate {
GURL* new_url) = 0;
// Called right before the network transaction starts. Allows the delegate to
- // read/write |headers| before they get sent out.
+ // read |headers| and modify them by passing a new copy to |callback| before
+ // they get sent out.
//
// Returns OK to continue with the request, ERR_IO_PENDING if the result is
// not ready yet, and any other status code to cancel the request. If
@@ -141,11 +144,11 @@ class NET_EXPORT NetworkDelegate {
// or OnCompleted. Once cancelled, |request| and |headers| become invalid and
// |callback| may not be called.
//
- // The default implementation returns OK (continue with request) without
- // modifying |headers|.
- virtual int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) = 0;
+ // The default implementation returns OK (continue with request).
+ virtual int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) = 0;
// Called for HTTP requests when the headers have been received.
// |original_response_headers| contains the headers as received over the
diff --git a/net/base/network_delegate_impl.cc b/net/base/network_delegate_impl.cc
index b944aae5f8dcb8f0db31e8cb4efa98318372be58..e0553d34432fc7cb7ea3f6446cd76fedb7e2e51c 100644
--- a/net/base/network_delegate_impl.cc
+++ b/net/base/network_delegate_impl.cc
@@ -16,8 +16,8 @@ int NetworkDelegateImpl::OnBeforeURLRequest(URLRequest* request,
int NetworkDelegateImpl::OnBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
return OK;
}
diff --git a/net/base/network_delegate_impl.h b/net/base/network_delegate_impl.h
index 5c33624ee828d785fcf34d66285c15e9ccab8b6c..08355f46f8120a880dd904fb7b33654db1e60c80 100644
--- a/net/base/network_delegate_impl.h
+++ b/net/base/network_delegate_impl.h
@@ -39,9 +39,10 @@ class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
CompletionOnceCallback callback,
GURL* new_url) override;
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override;
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
diff --git a/net/proxy_resolution/network_delegate_error_observer_unittest.cc b/net/proxy_resolution/network_delegate_error_observer_unittest.cc
index bd3ce6bbbea98fa3b62f2ca11e8895a7b6887559..542f57cb8f019cc6f5d13910353de12c295519ac 100644
--- a/net/proxy_resolution/network_delegate_error_observer_unittest.cc
+++ b/net/proxy_resolution/network_delegate_error_observer_unittest.cc
@@ -35,9 +35,10 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
GURL* new_url) override {
return OK;
}
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override {
return OK;
}
int OnHeadersReceived(
diff --git a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
index 786c6709addd276a6452b46a0de758668fb8c648..1e2b05b15cc7a70965cd3824369e93bc13e7c78d 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
+++ b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -146,9 +146,10 @@ class BasicNetworkDelegate : public NetworkDelegateImpl {
return OK;
}
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override {
return OK;
}
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 8773ed5a1b193e03b573ea7d6ffdc370a12a217f..9dd042ff4b910e9e8a17ce90f1de3cf7b0a87e79 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -80,9 +80,10 @@ class BasicNetworkDelegate : public NetworkDelegateImpl {
return OK;
}
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override {
return OK;
}
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 393b89a5624a3ad3e4fe76be62eb1698839bad96..680f38a72bd9eb237b0641d82aa307c1d2202fa8 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -381,15 +381,10 @@ void URLRequestHttpJob::StartTransaction() {
if (network_delegate) {
OnCallToDelegate(
NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
- // The NetworkDelegate must watch for OnRequestDestroyed and not modify
- // |extra_headers| after it's called.
- // TODO(mattm): change the API to remove the out-params and take the
- // results as params of the callback.
int rv = network_delegate->NotifyBeforeStartTransaction(
- request_,
+ request_, request_info_.extra_headers,
base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
- weak_factory_.GetWeakPtr()),
- &request_info_.extra_headers);
+ weak_factory_.GetWeakPtr()));
// If an extension blocks the request, we rely on the callback to
// MaybeStartTransactionInternal().
if (rv == ERR_IO_PENDING)
@@ -400,10 +395,14 @@ void URLRequestHttpJob::StartTransaction() {
StartTransactionInternal();
}
-void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(int result) {
+void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(
+ int result,
+ const base::Optional<HttpRequestHeaders>& headers) {
// The request should not have been cancelled or have already completed.
DCHECK(!is_done());
+ if (headers)
+ request_info_.extra_headers = headers.value();
MaybeStartTransactionInternal(result);
}
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 4b09404d87fd6109b6f7dfb67ee66bf43f59c2e4..ada9591ff4b57edcf05302243096b129afd3eed9 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -123,7 +123,9 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
void OnHeadersReceivedCallback(int result);
void OnStartCompleted(int result);
void OnReadCompleted(int result);
- void NotifyBeforeStartTransactionCallback(int result);
+ void NotifyBeforeStartTransactionCallback(
+ int result,
+ const base::Optional<HttpRequestHeaders>& headers);
// This just forwards the call to URLRequestJob::NotifyConnected().
// We need it because that method is protected and cannot be bound in a
// callback in this class.
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 6ec09da926d87b8edb833afa3cef233ba96ccda0..4e60f98bbffa3d22ddb65d3e6736fb71b5333d62 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -450,8 +450,8 @@ int TestNetworkDelegate::OnBeforeURLRequest(URLRequest* request,
int TestNetworkDelegate::OnBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
if (before_start_transaction_fails_)
return ERR_FAILED;
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h
index 4fffcb55df0c4dfc71a05c1bcc2f5e9c99cba920..765218450a9fbf39ce783088021c3df14282dc75 100644
--- a/net/url_request/url_request_test_util.h
+++ b/net/url_request/url_request_test_util.h
@@ -347,9 +347,10 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
int OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) override;
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override;
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 4b694307e4b8ba56fe03b8a03051bf24225440f2..897937fc200d4df939d48c23ee721f03de514780 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -444,9 +444,10 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
CompletionOnceCallback callback,
GURL* new_url) override;
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override;
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
@@ -545,13 +546,19 @@ int BlockingNetworkDelegate::OnBeforeURLRequest(URLRequest* request,
int BlockingNetworkDelegate::OnBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
// TestNetworkDelegate always completes synchronously.
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
- request, base::NullCallback(), headers));
+ request, headers, base::NullCallback()));
- return MaybeBlockStage(ON_BEFORE_SEND_HEADERS, std::move(callback));
+ return MaybeBlockStage(
+ ON_BEFORE_SEND_HEADERS,
+ base::BindOnce(
+ [](OnBeforeStartTransactionCallback callback, int result) {
+ std::move(callback).Run(result, absl::nullopt);
+ },
+ std::move(callback)));
}
int BlockingNetworkDelegate::OnHeadersReceived(
@@ -4876,13 +4883,19 @@ class AsyncLoggingNetworkDelegate : public TestNetworkDelegate {
return RunCallbackAsynchronously(request, std::move(callback));
}
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override {
// TestNetworkDelegate always completes synchronously.
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
- request, base::NullCallback(), headers));
- return RunCallbackAsynchronously(request, std::move(callback));
+ request, headers, base::NullCallback()));
+ return RunCallbackAsynchronously(
+ request, base::BindOnce(
+ [](OnBeforeStartTransactionCallback callback, int result) {
+ std::move(callback).Run(result, absl::nullopt);
+ },
+ std::move(callback)));
}
int OnHeadersReceived(
diff --git a/services/network/network_service_network_delegate.cc b/services/network/network_service_network_delegate.cc
index cd21d0ece5ae07225126f889dd84daecee728a3a..098fd068de46cb6213f2d75bf14f17baa4ff8ae4 100644
--- a/services/network/network_service_network_delegate.cc
+++ b/services/network/network_service_network_delegate.cc
@@ -103,16 +103,16 @@ int NetworkServiceNetworkDelegate::OnBeforeURLRequest(
int NetworkServiceNetworkDelegate::OnBeforeStartTransaction(
net::URLRequest* request,
- net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* headers) {
+ const net::HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
URLLoader* url_loader = URLLoader::ForRequest(*request);
if (url_loader)
- return url_loader->OnBeforeStartTransaction(std::move(callback), headers);
+ return url_loader->OnBeforeStartTransaction(headers, std::move(callback));
#if !defined(OS_IOS)
WebSocket* web_socket = WebSocket::ForRequest(*request);
if (web_socket)
- return web_socket->OnBeforeStartTransaction(std::move(callback), headers);
+ return web_socket->OnBeforeStartTransaction(headers, std::move(callback));
#endif // !defined(OS_IOS)
return net::OK;
diff --git a/services/network/network_service_network_delegate.h b/services/network/network_service_network_delegate.h
index 1e81d8ec2cde1d8e710adc8c447d325bb104421f..76d53dfc914162cfff72d2ee8aeabee8f9879e5a 100644
--- a/services/network/network_service_network_delegate.h
+++ b/services/network/network_service_network_delegate.h
@@ -38,9 +38,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceNetworkDelegate
int OnBeforeURLRequest(net::URLRequest* request,
net::CompletionOnceCallback callback,
GURL* new_url) override;
- int OnBeforeStartTransaction(net::URLRequest* request,
- net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* headers) override;
+ int OnBeforeStartTransaction(
+ net::URLRequest* request,
+ const net::HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
net::URLRequest* request,
net::CompletionOnceCallback callback,
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 6f0cb6f4ed60b7043febc4e940523cc8863566c5..2360f5a0ce03543134e3aea583c92115226b0029 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -1655,13 +1655,14 @@ void URLLoader::OnReadCompleted(net::URLRequest* url_request, int bytes_read) {
// |this| may have been deleted.
}
-int URLLoader::OnBeforeStartTransaction(net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* headers) {
+int URLLoader::OnBeforeStartTransaction(
+ const net::HttpRequestHeaders& headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback) {
if (header_client_) {
header_client_->OnBeforeSendHeaders(
- *headers, base::BindOnce(&URLLoader::OnBeforeSendHeadersComplete,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(callback), headers));
+ headers,
+ base::BindOnce(&URLLoader::OnBeforeSendHeadersComplete,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
return net::ERR_IO_PENDING;
}
return net::OK;
@@ -2029,13 +2030,10 @@ void URLLoader::ResumeStart() {
}
void URLLoader::OnBeforeSendHeadersComplete(
- net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* out_headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const base::Optional<net::HttpRequestHeaders>& headers) {
- if (headers)
- *out_headers = headers.value();
- std::move(callback).Run(result);
+ std::move(callback).Run(result, headers);
}
void URLLoader::OnHeadersReceivedComplete(
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 00976c56702ed3e77505438344b214ce134e8a4f..ec1ebdc3ea1af904343c42d31b1afcca435d20f8 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -24,6 +24,7 @@
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/load_states.h"
+#include "net/base/network_delegate.h"
#include "net/http/http_raw_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
@@ -172,8 +173,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// These methods are called by the network delegate to forward these events to
// the |header_client_|.
- int OnBeforeStartTransaction(net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* headers);
+ int OnBeforeStartTransaction(
+ const net::HttpRequestHeaders& headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback);
int OnHeadersReceived(
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
@@ -342,8 +344,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
void RecordBodyReadFromNetBeforePausedIfNeeded();
void ResumeStart();
void OnBeforeSendHeadersComplete(
- net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* out_headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const base::Optional<net::HttpRequestHeaders>& headers);
void OnHeadersReceivedComplete(
diff --git a/services/network/websocket.cc b/services/network/websocket.cc
index 8b73bc115c96d404b6ca538a62a34789272d282b..0b8e554c2b1823d83ed493e52e3bfc75ebcacdbd 100644
--- a/services/network/websocket.cc
+++ b/services/network/websocket.cc
@@ -537,13 +537,14 @@ bool WebSocket::AllowCookies(const GURL& url) const {
url, site_for_cookies_) == net::OK;
}
-int WebSocket::OnBeforeStartTransaction(net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* headers) {
+int WebSocket::OnBeforeStartTransaction(
+ const net::HttpRequestHeaders& headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback) {
if (header_client_) {
header_client_->OnBeforeSendHeaders(
- *headers, base::BindOnce(&WebSocket::OnBeforeSendHeadersComplete,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(callback), headers));
+ headers,
+ base::BindOnce(&WebSocket::OnBeforeSendHeadersComplete,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
return net::ERR_IO_PENDING;
}
return net::OK;
@@ -840,17 +841,14 @@ void WebSocket::OnAuthRequiredComplete(
}
void WebSocket::OnBeforeSendHeadersComplete(
- net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* out_headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const base::Optional<net::HttpRequestHeaders>& headers) {
if (!channel_) {
// Something happened before the OnBeforeSendHeaders response arrives.
return;
}
- if (headers)
- *out_headers = headers.value();
- std::move(callback).Run(result);
+ std::move(callback).Run(result, headers);
}
void WebSocket::OnHeadersReceivedComplete(
diff --git a/services/network/websocket.h b/services/network/websocket.h
index 2b0c877a4175ccd664e927359301637949b20f1d..4557b7eb7e410e95fb2722362ae70b708bee3d2a 100644
--- a/services/network/websocket.h
+++ b/services/network/websocket.h
@@ -22,6 +22,7 @@
#include "base/types/strong_alias.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/network_delegate.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/websockets/websocket_event_interface.h"
#include "services/network/network_service.h"
@@ -88,8 +89,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
// These methods are called by the network delegate to forward these events to
// the |header_client_|.
- int OnBeforeStartTransaction(net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* headers);
+ int OnBeforeStartTransaction(
+ const net::HttpRequestHeaders& headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback);
int OnHeadersReceived(
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
@@ -148,8 +150,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
base::OnceCallback<void(const net::AuthCredentials*)> callback,
const base::Optional<net::AuthCredentials>& credential);
void OnBeforeSendHeadersComplete(
- net::CompletionOnceCallback callback,
- net::HttpRequestHeaders* out_headers,
+ net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const base::Optional<net::HttpRequestHeaders>& headers);
void OnHeadersReceivedComplete(

View File

@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bartek Nowierski <bartekn@chromium.org>
Date: Thu, 29 Jul 2021 10:38:19 +0000
Subject: Make GetUsableSize() handle nullptr gracefully
malloc_usable_size() is expected to not crush on NULL and return 0.
(cherry picked from commit 61e16c92ff24bb71b9b7309a9d6d470ee91738bc)
Bug: 1221442
Change-Id: I6a3b90dcf3a8ad18114c206d87b98f60d5f50eb1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3042177
Commit-Queue: Bartek Nowierski <bartekn@chromium.org>
Commit-Queue: Kentaro Hara <haraken@chromium.org>
Auto-Submit: Bartek Nowierski <bartekn@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#903900}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3060345
Cr-Commit-Position: refs/branch-heads/4515@{#1905}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
index bb6faf759ed9829c7fa644a09521674d89898abc..d494f02d4e9db705823e92c670fb4d352ad7f8ea 100644
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -2752,6 +2752,10 @@ TEST_F(PartitionAllocTest, OptimizedGetSlotNumber) {
}
}
+TEST_F(PartitionAllocTest, GetUsableSizeNull) {
+ EXPECT_EQ(0ULL, PartitionRoot<ThreadSafe>::GetUsableSize(nullptr));
+}
+
TEST_F(PartitionAllocTest, GetUsableSize) {
size_t delta = SystemPageSize() + 1;
for (size_t size = 1; size <= kMinDirectMappedDownsize; size += delta) {
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h
index 742ac8937c495811e0694157ca49b35afe4a06d3..de427e66bfb3c910bf7fbc638feff61b4d3ed418 100644
--- a/base/allocator/partition_allocator/partition_root.h
+++ b/base/allocator/partition_allocator/partition_root.h
@@ -1164,6 +1164,9 @@ ALWAYS_INLINE bool PartitionRoot<thread_safe>::TryRecommitSystemPagesForData(
// PartitionAlloc's internal data. Used as malloc_usable_size.
template <bool thread_safe>
ALWAYS_INLINE size_t PartitionRoot<thread_safe>::GetUsableSize(void* ptr) {
+ // malloc_usable_size() is expected to handle NULL gracefully and return 0.
+ if (!ptr)
+ return 0;
auto* slot_span = SlotSpan::FromSlotInnerPtr(ptr);
auto* root = FromSlotSpan(slot_span);
return slot_span->GetUsableSize(root);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yuly Novikov <ynovikov@chromium.org>
Date: Thu, 9 Sep 2021 20:00:43 +0000
Subject: Skip WebGL conformance/programs/program-test.html on all platforms
To unblock ANGLE CL http://crrev.com/c/3140496, which modifies behaviour
to make it an error to draw after the current program fails to re-link.
(cherry picked from commit 8ef1e4544ed5214608039d969940347d8f98e543)
Bug: 1241123
Bug: angleproject:6358
Change-Id: I40a1f4843f902533745cc9527379def9d777a578
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3140226
Auto-Submit: Yuly Novikov <ynovikov@chromium.org>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Original-Commit-Position: refs/heads/main@{#918281}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3150594
Auto-Submit: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
Cr-Commit-Position: refs/branch-heads/4515@{#2117}
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 597fb2319f2994f993821033d4a5751f376443e6..69b8eac78f12345d843d9e603f3fcbf62ad42a58 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -171,6 +171,10 @@ crbug.com/1085222 [ win10 intel-0x5912 ] deqp/functional/gles3/shaderoperator/un
crbug.com/1085222 [ catalina intel-0xa2e ] deqp/functional/gles3/shaderoperator/binary_operator_* [ RetryOnFailure ]
crbug.com/1085222 [ catalina intel-0xa2e ] deqp/functional/gles3/shaderoperator/unary_operator_* [ RetryOnFailure ]
+# Temporary suppression while we wait for a spec update.
+# TODO(jmadill): Remove when possible.
+crbug.com/angleproject/6358 conformance/programs/program-test.html [ Failure ]
+
####################
# Win failures #
####################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 87b310449dafc66701105e996cd1f564b2dbd601..bea1dc72f4709709552eefdfffe5fa8f250afdab 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -257,6 +257,10 @@ crbug.com/1163292 [ win nvidia angle-d3d9 ] conformance/textures/misc/texture-co
crbug.com/1105129 [ linux ] conformance/context/context-creation.html [ RetryOnFailure ]
crbug.com/1105129 [ win ] conformance/context/context-creation.html [ RetryOnFailure ]
+# Temporary suppression while we wait for a spec update.
+# TODO(jmadill): Remove when possible.
+crbug.com/angleproject/6358 conformance/programs/program-test.html [ Failure ]
+
# Win / AMD / Passthrough command decoder / D3D11
crbug.com/772037 [ win amd angle-d3d11 passthrough ] conformance/textures/misc/texture-sub-image-cube-maps.html [ RetryOnFailure ]

View File

@@ -9,4 +9,7 @@ fix_build_deprecated_attirbute_for_older_msvc_versions.patch
cherry-pick-e38d55313ad9.patch
cherry-pick-1234770.patch
cherry-pick-1231950.patch
cherry-pick-1228036.patch
cherry-pick-1234764.patch
cherry-pick-fbfd2557c2ab.patch
cherry-pick-034c2003be31.patch

View File

@@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Georg Neis <neis@chromium.org>
Date: Thu, 9 Sep 2021 14:41:58 +0200
Subject: Merged: [compiler] Fix a bug in global property access reduction
Bug: chromium:1247763
(cherry picked from commit 6391d7a58d0c58cd5d096d22453b954b3ecc6fec)
Change-Id: Ifa775224ed30a2d680c6e3653063483c733de831
No-Try: true
No-Presubmit: true
No-Tree-Checks: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3151960
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Michael Hablich <hablich@chromium.org>
Cr-Commit-Position: refs/branch-heads/9.3@{#37}
Cr-Branched-From: 7744dce208a555494e4a33e24fadc71ea20b3895-refs/heads/9.3.345@{#1}
Cr-Branched-From: 4b6b4cabf3b6a20cdfda72b369df49f3311c4344-refs/heads/master@{#75728}
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
index 3d9290a0bf9d3f0f638c7e0c4bb16ce84c125c32..df83ab6db85dd53ccba30c78d3866110f1ee0685 100644
--- a/src/compiler/js-native-context-specialization.cc
+++ b/src/compiler/js-native-context-specialization.cc
@@ -841,6 +841,12 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
return NoChange();
} else if (property_cell_type == PropertyCellType::kUndefined) {
return NoChange();
+ } else if (property_cell_type == PropertyCellType::kConstantType) {
+ // We rely on stability further below.
+ if (property_cell_value.IsHeapObject() &&
+ !property_cell_value.AsHeapObject().map().is_stable()) {
+ return NoChange();
+ }
}
} else if (access_mode == AccessMode::kHas) {
DCHECK_EQ(receiver, lookup_start_object);
@@ -957,17 +963,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
if (property_cell_value.IsHeapObject()) {
MapRef property_cell_value_map =
property_cell_value.AsHeapObject().map();
- if (property_cell_value_map.is_stable()) {
- dependencies()->DependOnStableMap(property_cell_value_map);
- } else {
- // The value's map is already unstable. If this store were to go
- // through the C++ runtime, it would transition the PropertyCell to
- // kMutable. We don't want to change the cell type from generated
- // code (to simplify concurrent heap access), however, so we keep
- // it as kConstantType and do the store anyways (if the new value's
- // map matches). This is safe because it merely prolongs the limbo
- // state that we are in already.
- }
+ dependencies()->DependOnStableMap(property_cell_value_map);
// Check that the {value} is a HeapObject.
value = effect = graph()->NewNode(simplified()->CheckHeapObject(),

View File

@@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Georg Neis <neis@chromium.org>
Date: Mon, 26 Jul 2021 16:40:39 +0200
Subject: Finish concurrent sweeping before overwriting ByteArrays
Bug: chromium:1228036
Change-Id: I5abe7009920d2c8f81f024c9ae7bb6b13607da1a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3054119
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: Hannes Payer <hpayer@chromium.org>
diff --git a/src/deoptimizer/translated-state.cc b/src/deoptimizer/translated-state.cc
index 02c473d22b18a0a4c288e655afdb73340a0d0ffc..b5378a553a49e41c96713cf3f2ed901f7cfe4626 100644
--- a/src/deoptimizer/translated-state.cc
+++ b/src/deoptimizer/translated-state.cc
@@ -514,6 +514,12 @@ Handle<Object> TranslatedValue::GetValue() {
// pass the verifier.
container_->EnsureObjectAllocatedAt(this);
+ // Finish any sweeping so that it becomes safe to overwrite the ByteArray
+ // headers.
+ // TODO(hpayer): Find a cleaner way to support a group of
+ // non-fully-initialized objects.
+ isolate()->heap()->mark_compact_collector()->EnsureSweepingCompleted();
+
// 2. Initialize the objects. If we have allocated only byte arrays
// for some objects, we now overwrite the byte arrays with the
// correct object fields. Note that this phase does not allocate
@@ -1397,9 +1403,9 @@ TranslatedValue* TranslatedState::GetValueByObjectIndex(int object_index) {
}
Handle<HeapObject> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
- slot = ResolveCapturedObject(slot);
-
DisallowGarbageCollection no_gc;
+
+ slot = ResolveCapturedObject(slot);
if (slot->materialization_state() != TranslatedValue::kFinished) {
std::stack<int> worklist;
worklist.push(slot->object_index());

View File

@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mythri A <mythria@chromium.org>
Date: Fri, 21 May 2021 11:12:41 +0100
Subject: Return early when initializing feedback cell for AsmWasm functions
AsmWasmFunctions don't allocate / use feedback vectors.
Bug: chromium:1206289
Change-Id: I970d5eaba6603809a844c2fc5753efba411cd719
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2909854
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74708}
diff --git a/src/objects/js-function.cc b/src/objects/js-function.cc
index 35010be838ea1a5a3bebbb8a86d3358092da5199..b17550a29668d3dab082a515c7287b219becd01d 100644
--- a/src/objects/js-function.cc
+++ b/src/objects/js-function.cc
@@ -361,6 +361,14 @@ void JSFunction::InitializeFeedbackCell(
Handle<JSFunction> function, IsCompiledScope* is_compiled_scope,
bool reset_budget_for_feedback_allocation) {
Isolate* const isolate = function->GetIsolate();
+#if V8_ENABLE_WEBASSEMBLY
+ // The following checks ensure that the feedback vectors are compatible with
+ // the feedback metadata. For Asm / Wasm functions we never allocate / use
+ // feedback vectors, so a mismatch between the metadata and feedback vector is
+ // harmless. The checks could fail for functions that has has_asm_wasm_broken
+ // set at runtime (for ex: failed instantiation).
+ if (function->shared().HasAsmWasmData()) return;
+#endif // V8_ENABLE_WEBASSEMBLY
if (function->has_feedback_vector()) {
CHECK_EQ(function->feedback_vector().length(),

View File

@@ -59,6 +59,17 @@ BrowserWindow::BrowserWindow(gin::Arguments* args,
web_preferences.Set(options::kShow, show);
}
bool titleBarOverlay = false;
options.Get(options::ktitleBarOverlay, &titleBarOverlay);
if (titleBarOverlay) {
std::string enabled_features = "";
if (web_preferences.Get(options::kEnableBlinkFeatures, &enabled_features)) {
enabled_features += ",";
}
enabled_features += features::kWebAppWindowControlsOverlay.name;
web_preferences.Set(options::kEnableBlinkFeatures, enabled_features);
}
// Copy the webContents option to webPreferences. This is only used internally
// to implement nativeWindowOpen option.
if (options.Get("webContents", &value)) {
@@ -326,6 +337,11 @@ void BrowserWindow::OnWindowLeaveFullScreen() {
BaseWindow::OnWindowLeaveFullScreen();
}
void BrowserWindow::UpdateWindowControlsOverlay(
const gfx::Rect& bounding_rect) {
web_contents()->UpdateWindowControlsOverlay(bounding_rect);
}
void BrowserWindow::Focus() {
if (api_web_contents_->IsOffScreen())
FocusOnWebView();

View File

@@ -69,6 +69,7 @@ class BrowserWindow : public BaseWindow,
void RequestPreferredWidth(int* width) override;
void OnCloseButtonClicked(bool* prevent_default) override;
void OnWindowIsKeyChanged(bool is_key) override;
void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override;
// BaseWindow:
void OnWindowClosed() override;

View File

@@ -1387,8 +1387,19 @@ void WebContents::HandleNewRenderFrame(
rwh_impl->disable_hidden_ = !background_throttling_;
auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host);
if (web_frame)
if (web_frame) {
// When render process reuse is disabled a new siteinstance will always be
// forced for every navigation, if a WebFrameMain instance was created
// for a FrameTreeNodeId before navigation started, the corresponding
// RenderFrameHost will not be the same when the navigation completes.
// Compare GlobalFrameRoutingId to avoid incorrect behavior.
if (!ElectronBrowserClient::Get()->CanUseCustomSiteInstance() &&
web_frame->render_frame_host()->GetGlobalFrameRoutingId() !=
render_frame_host->GetGlobalFrameRoutingId()) {
return;
}
web_frame->Connect();
}
}
void WebContents::RenderFrameCreated(
@@ -1420,12 +1431,11 @@ void WebContents::RenderFrameHostChanged(content::RenderFrameHost* old_host,
// If an instance of WebFrameMain exists, it will need to have its RFH
// swapped as well.
//
// |old_host| can be a nullptr in so we use |new_host| for looking up the
// |old_host| can be a nullptr so we use |new_host| for looking up the
// WebFrameMain instance.
auto* web_frame =
WebFrameMain::FromFrameTreeNodeId(new_host->GetFrameTreeNodeId());
if (web_frame) {
CHECK_EQ(web_frame->render_frame_host(), old_host);
web_frame->UpdateRenderFrameHost(new_host);
}
}
@@ -1710,6 +1720,10 @@ void WebContents::ReadyToCommitNavigation(
void WebContents::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (owner_window_) {
owner_window_->NotifyLayoutWindowControlsOverlay();
}
if (!navigation_handle->HasCommitted())
return;
bool is_main_frame = navigation_handle->IsInMainFrame();
@@ -3924,6 +3938,16 @@ gin::Handle<WebContents> WebContentsFromID(v8::Isolate* isolate, int32_t id) {
: gin::Handle<WebContents>();
}
gin::Handle<WebContents> WebContentsFromDevToolsTargetID(
v8::Isolate* isolate,
std::string target_id) {
auto agent_host = content::DevToolsAgentHost::GetForId(target_id);
WebContents* contents =
agent_host ? WebContents::From(agent_host->GetWebContents()) : nullptr;
return contents ? gin::CreateHandle(isolate, contents)
: gin::Handle<WebContents>();
}
std::vector<gin::Handle<WebContents>> GetAllWebContentsAsV8(
v8::Isolate* isolate) {
std::vector<gin::Handle<WebContents>> list;
@@ -3942,6 +3966,7 @@ void Initialize(v8::Local<v8::Object> exports,
gin_helper::Dictionary dict(isolate, exports);
dict.Set("WebContents", WebContents::GetConstructor(context));
dict.SetMethod("fromId", &WebContentsFromID);
dict.SetMethod("fromDevToolsTargetId", &WebContentsFromDevToolsTargetID);
dict.SetMethod("getAllWebContents", &GetAllWebContentsAsV8);
}

View File

@@ -31,9 +31,7 @@ GPUInfoManager::~GPUInfoManager() {
// Based on
// https://chromium.googlesource.com/chromium/src.git/+/69.0.3497.106/content/browser/gpu/gpu_data_manager_impl_private.cc#838
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() const {
#if defined(OS_MAC)
return gpu_data_manager_->GetGPUInfo().gl_vendor.empty();
#elif defined(OS_WIN)
#if defined(OS_WIN)
return gpu_data_manager_->DxdiagDx12VulkanRequested() &&
gpu_data_manager_->GetGPUInfo().dx_diagnostics.IsEmpty();
#else

View File

@@ -62,6 +62,10 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
return NO;
}
- (BOOL)acceptsFirstMouse:(NSEvent*)event {
return YES;
}
- (BOOL)shouldIgnoreMouseEvent {
NSEventType type = [[NSApp currentEvent] type];
return type != NSEventTypeLeftMouseDragged &&

View File

@@ -9,7 +9,7 @@
#include <vector>
#include "shell/browser/ui/drag_util.h"
#include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/ui/views/inspectable_web_contents_view_views.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/background.h"
#include "ui/views/view.h"
@@ -49,7 +49,7 @@ void NativeBrowserViewViews::SetAutoResizeProportions(
const gfx::Size& window_size) {
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeHorizontal) &&
!auto_horizontal_proportion_set_) {
auto* iwc_view = GetInspectableWebContentsView();
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
if (!iwc_view)
return;
auto* view = iwc_view->GetView();
@@ -63,7 +63,7 @@ void NativeBrowserViewViews::SetAutoResizeProportions(
}
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeVertical) &&
!auto_vertical_proportion_set_) {
auto* iwc_view = GetInspectableWebContentsView();
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
if (!iwc_view)
return;
auto* view = iwc_view->GetView();
@@ -80,7 +80,7 @@ void NativeBrowserViewViews::SetAutoResizeProportions(
void NativeBrowserViewViews::AutoResize(const gfx::Rect& new_window,
int width_delta,
int height_delta) {
auto* iwc_view = GetInspectableWebContentsView();
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
if (!iwc_view)
return;
auto* view = iwc_view->GetView();
@@ -124,7 +124,7 @@ void NativeBrowserViewViews::ResetAutoResizeProportions() {
}
void NativeBrowserViewViews::SetBounds(const gfx::Rect& bounds) {
auto* iwc_view = GetInspectableWebContentsView();
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
if (!iwc_view)
return;
auto* view = iwc_view->GetView();
@@ -133,14 +133,20 @@ void NativeBrowserViewViews::SetBounds(const gfx::Rect& bounds) {
}
gfx::Rect NativeBrowserViewViews::GetBounds() {
auto* iwc_view = GetInspectableWebContentsView();
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
if (!iwc_view)
return gfx::Rect();
return iwc_view->GetView()->bounds();
}
void NativeBrowserViewViews::RenderViewReady() {
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
if (iwc_view)
iwc_view->GetView()->Layout();
}
void NativeBrowserViewViews::SetBackgroundColor(SkColor color) {
auto* iwc_view = GetInspectableWebContentsView();
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
if (!iwc_view)
return;
auto* view = iwc_view->GetView();

View File

@@ -33,6 +33,9 @@ class NativeBrowserViewViews : public NativeBrowserView {
void UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions) override;
// WebContentsObserver:
void RenderViewReady() override;
SkRegion* draggable_region() const { return draggable_region_.get(); }
private:

View File

@@ -24,6 +24,34 @@
#include "ui/display/win/screen_win.h"
#endif
namespace gin {
template <>
struct Converter<electron::NativeWindow::TitleBarStyle> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
electron::NativeWindow::TitleBarStyle* out) {
using TitleBarStyle = electron::NativeWindow::TitleBarStyle;
std::string title_bar_style;
if (!ConvertFromV8(isolate, val, &title_bar_style))
return false;
if (title_bar_style == "hidden") {
*out = TitleBarStyle::kHidden;
#if defined(OS_MAC)
} else if (title_bar_style == "hiddenInset") {
*out = TitleBarStyle::kHiddenInset;
} else if (title_bar_style == "customButtonsOnHover") {
*out = TitleBarStyle::kCustomButtonsOnHover;
#endif
} else {
return false;
}
return true;
}
};
} // namespace gin
namespace electron {
namespace {
@@ -54,6 +82,19 @@ NativeWindow::NativeWindow(const gin_helper::Dictionary& options,
options.Get(options::kFrame, &has_frame_);
options.Get(options::kTransparent, &transparent_);
options.Get(options::kEnableLargerThanScreen, &enable_larger_than_screen_);
options.Get(options::kTitleBarStyle, &title_bar_style_);
v8::Local<v8::Value> titlebar_overlay;
if (options.Get(options::ktitleBarOverlay, &titlebar_overlay)) {
if (titlebar_overlay->IsBoolean()) {
options.Get(options::ktitleBarOverlay, &titlebar_overlay_);
} else if (titlebar_overlay->IsObject()) {
titlebar_overlay_ = true;
#if !defined(OS_WIN)
DCHECK(false);
#endif
}
}
if (parent)
options.Get("modal", &is_modal_);
@@ -391,6 +432,14 @@ void NativeWindow::PreviewFile(const std::string& path,
void NativeWindow::CloseFilePreview() {}
gfx::Rect NativeWindow::GetWindowControlsOverlayRect() {
return overlay_rect_;
}
void NativeWindow::SetWindowControlsOverlayRect(const gfx::Rect& overlay_rect) {
overlay_rect_ = overlay_rect;
}
void NativeWindow::NotifyWindowRequestPreferredWith(int* width) {
for (NativeWindowObserver& observer : observers_)
observer.RequestPreferredWidth(width);
@@ -489,6 +538,7 @@ void NativeWindow::NotifyWindowWillMove(const gfx::Rect& new_bounds,
}
void NativeWindow::NotifyWindowResize() {
NotifyLayoutWindowControlsOverlay();
for (NativeWindowObserver& observer : observers_)
observer.OnWindowResize();
}
@@ -587,6 +637,14 @@ void NativeWindow::NotifyWindowSystemContextMenu(int x,
observer.OnSystemContextMenu(x, y, prevent_default);
}
void NativeWindow::NotifyLayoutWindowControlsOverlay() {
gfx::Rect bounding_rect = GetWindowControlsOverlayRect();
if (!bounding_rect.IsEmpty()) {
for (NativeWindowObserver& observer : observers_)
observer.UpdateWindowControlsOverlay(bounding_rect);
}
}
#if defined(OS_WIN)
void NativeWindow::NotifyWindowMessage(UINT message,
WPARAM w_param,

View File

@@ -255,6 +255,9 @@ class NativeWindow : public base::SupportsUserData,
return weak_factory_.GetWeakPtr();
}
virtual gfx::Rect GetWindowControlsOverlayRect();
virtual void SetWindowControlsOverlayRect(const gfx::Rect& overlay_rect);
// Methods called by the WebContents.
virtual void HandleKeyboardEvent(
content::WebContents*,
@@ -298,6 +301,7 @@ class NativeWindow : public base::SupportsUserData,
const base::DictionaryValue& details);
void NotifyNewWindowForTab();
void NotifyWindowSystemContextMenu(int x, int y, bool* prevent_default);
void NotifyLayoutWindowControlsOverlay();
#if defined(OS_WIN)
void NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param);
@@ -311,6 +315,14 @@ class NativeWindow : public base::SupportsUserData,
views::Widget* widget() const { return widget_.get(); }
views::View* content_view() const { return content_view_; }
enum class TitleBarStyle {
kNormal,
kHidden,
kHiddenInset,
kCustomButtonsOnHover,
};
TitleBarStyle title_bar_style() const { return title_bar_style_; }
bool has_frame() const { return has_frame_; }
void set_has_frame(bool has_frame) { has_frame_ = has_frame; }
@@ -342,6 +354,12 @@ class NativeWindow : public base::SupportsUserData,
[&browser_view](NativeBrowserView* n) { return (n == browser_view); });
}
// The boolean parsing of the "titleBarOverlay" option
bool titlebar_overlay_ = false;
// The "titleBarStyle" option.
TitleBarStyle title_bar_style_ = TitleBarStyle::kNormal;
private:
std::unique_ptr<views::Widget> widget_;
@@ -390,6 +408,8 @@ class NativeWindow : public base::SupportsUserData,
// Accessible title.
std::u16string accessible_title_;
gfx::Rect overlay_rect_;
base::WeakPtrFactory<NativeWindow> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(NativeWindow);

View File

@@ -147,6 +147,7 @@ class NativeWindowMac : public NativeWindow,
void CloseFilePreview() override;
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
gfx::Rect GetWindowControlsOverlayRect() override;
void NotifyWindowEnterFullScreen() override;
void NotifyWindowLeaveFullScreen() override;
void SetActive(bool is_key) override;
@@ -182,19 +183,24 @@ class NativeWindowMac : public NativeWindow,
kInactive,
};
enum class TitleBarStyle {
kNormal,
kHidden,
kHiddenInset,
kCustomButtonsOnHover,
};
TitleBarStyle title_bar_style() const { return title_bar_style_; }
ElectronPreviewItem* preview_item() const { return preview_item_.get(); }
ElectronTouchBar* touch_bar() const { return touch_bar_.get(); }
bool zoom_to_page_width() const { return zoom_to_page_width_; }
bool always_simple_fullscreen() const { return always_simple_fullscreen_; }
// We need to save the result of windowWillUseStandardFrame:defaultFrame
// because macOS calls it with what it refers to as the "best fit" frame for a
// zoom. This means that even if an aspect ratio is set, macOS might adjust it
// to better fit the screen.
//
// Thus, we can't just calculate the maximized aspect ratio'd sizing from
// the current visible screen and compare that to the current window's frame
// to determine whether a window is maximized.
NSRect default_frame_for_zoom() const { return default_frame_for_zoom_; }
void set_default_frame_for_zoom(NSRect frame) {
default_frame_for_zoom_ = frame;
}
protected:
// views::WidgetDelegate:
bool CanResize() const override;
@@ -249,9 +255,6 @@ class NativeWindowMac : public NativeWindow,
// The presentation options before entering kiosk mode.
NSApplicationPresentationOptions kiosk_options_;
// The "titleBarStyle" option.
TitleBarStyle title_bar_style_ = TitleBarStyle::kNormal;
// The "visualEffectState" option.
VisualEffectState visual_effect_state_ = VisualEffectState::kFollowWindow;
@@ -274,6 +277,7 @@ class NativeWindowMac : public NativeWindow,
NSRect original_frame_;
NSInteger original_level_;
NSUInteger simple_fullscreen_mask_;
NSRect default_frame_for_zoom_;
std::string vibrancy_type_;

View File

@@ -164,28 +164,6 @@
namespace gin {
template <>
struct Converter<electron::NativeWindowMac::TitleBarStyle> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
electron::NativeWindowMac::TitleBarStyle* out) {
using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
std::string title_bar_style;
if (!ConvertFromV8(isolate, val, &title_bar_style))
return false;
if (title_bar_style == "hidden") {
*out = TitleBarStyle::kHidden;
} else if (title_bar_style == "hiddenInset") {
*out = TitleBarStyle::kHiddenInset;
} else if (title_bar_style == "customButtonsOnHover") {
*out = TitleBarStyle::kCustomButtonsOnHover;
} else {
return false;
}
return true;
}
};
template <>
struct Converter<electron::NativeWindowMac::VisualEffectState> {
static bool FromV8(v8::Isolate* isolate,
@@ -274,7 +252,6 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
height);
options.Get(options::kResizable, &resizable_);
options.Get(options::kTitleBarStyle, &title_bar_style_);
options.Get(options::kZoomToPageWidth, &zoom_to_page_width_);
options.Get(options::kSimpleFullScreen, &always_simple_fullscreen_);
options.GetOptional(options::kTrafficLightPosition, &traffic_light_position_);
@@ -630,16 +607,14 @@ void NativeWindowMac::Unmaximize() {
}
bool NativeWindowMac::IsMaximized() {
if (([window_ styleMask] & NSWindowStyleMaskResizable) != 0) {
if (([window_ styleMask] & NSWindowStyleMaskResizable) != 0)
return [window_ isZoomed];
} else {
NSRect rectScreen = [[NSScreen mainScreen] visibleFrame];
NSRect rectWindow = [window_ frame];
return (rectScreen.origin.x == rectWindow.origin.x &&
rectScreen.origin.y == rectWindow.origin.y &&
rectScreen.size.width == rectWindow.size.width &&
rectScreen.size.height == rectWindow.size.height);
}
NSRect rectScreen = GetAspectRatio() > 0.0
? default_frame_for_zoom()
: [[NSScreen mainScreen] visibleFrame];
return NSEqualRects([window_ frame], rectScreen);
}
void NativeWindowMac::Minimize() {
@@ -1026,6 +1001,13 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
window.level = NSPopUpMenuWindowLevel;
}
// Always hide the titlebar in simple fullscreen mode.
//
// Note that we must remove the NSWindowStyleMaskTitled style instead of
// using the [window_ setTitleVisibility:], as the latter would leave the
// window with rounded corners.
SetStyleMask(false, NSWindowStyleMaskTitled);
if (!window_button_visibility_.has_value()) {
// Lets keep previous behaviour - hide window controls in titled
// fullscreen mode when not specified otherwise.
@@ -1042,16 +1024,6 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
} else if (!simple_fullscreen && is_simple_fullscreen_) {
is_simple_fullscreen_ = false;
// Restore default window controls visibility state.
if (!window_button_visibility_.has_value()) {
bool visibility;
if (has_frame())
visibility = true;
else
visibility = title_bar_style_ != TitleBarStyle::kNormal;
InternalSetWindowButtonVisibility(visibility);
}
[window setFrame:original_frame_ display:YES animate:YES];
window.level = original_level_;
@@ -1064,6 +1036,19 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
// Restore window manipulation abilities
SetMaximizable(was_maximizable_);
SetMovable(was_movable_);
// Restore default window controls visibility state.
if (!window_button_visibility_.has_value()) {
bool visibility;
if (has_frame())
visibility = true;
else
visibility = title_bar_style_ != TitleBarStyle::kNormal;
InternalSetWindowButtonVisibility(visibility);
}
if (buttons_proxy_)
[buttons_proxy_ redraw];
}
}
@@ -1495,6 +1480,7 @@ void NativeWindowMac::SetWindowButtonVisibility(bool visible) {
[buttons_proxy_ setVisible:visible];
else
InternalSetWindowButtonVisibility(visible);
NotifyLayoutWindowControlsOverlay();
}
bool NativeWindowMac::GetWindowButtonVisibility() const {
@@ -1508,6 +1494,7 @@ void NativeWindowMac::SetTrafficLightPosition(
traffic_light_position_ = std::move(position);
if (buttons_proxy_) {
[buttons_proxy_ setMargin:traffic_light_position_];
NotifyLayoutWindowControlsOverlay();
}
}
@@ -1825,6 +1812,27 @@ void NativeWindowMac::SetForwardMouseMessages(bool forward) {
[window_ setAcceptsMouseMovedEvents:forward];
}
gfx::Rect NativeWindowMac::GetWindowControlsOverlayRect() {
gfx::Rect bounding_rect;
if (titlebar_overlay_ && !has_frame() && buttons_proxy_ &&
[buttons_proxy_ isVisible]) {
NSRect button_frame = [buttons_proxy_ getButtonsBounds];
gfx::Point buttons_view_margin = [buttons_proxy_ getMargin];
const int overlay_width = GetContentSize().width() - NSWidth(button_frame) -
buttons_view_margin.x();
CGFloat overlay_height =
NSHeight(button_frame) + buttons_view_margin.y() * 2;
if (base::i18n::IsRTL()) {
bounding_rect = gfx::Rect(0, 0, overlay_width, overlay_height);
} else {
bounding_rect =
gfx::Rect(button_frame.size.width + buttons_view_margin.x(), 0,
overlay_width, overlay_height);
}
}
return bounding_rect;
}
// static
NativeWindow* NativeWindow::Create(const gin_helper::Dictionary& options,
NativeWindow* parent) {

View File

@@ -102,6 +102,8 @@ class NativeWindowObserver : public base::CheckedObserver {
// Called on Windows when App Commands arrive (WM_APPCOMMAND)
// Some commands are implemented on on other platforms as well
virtual void OnExecuteAppCommand(const std::string& command_name) {}
virtual void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) {}
};
} // namespace electron

View File

@@ -71,12 +71,14 @@
#elif defined(OS_WIN)
#include "base/win/win_util.h"
#include "extensions/common/image_util.h"
#include "shell/browser/ui/views/win_frame_view.h"
#include "shell/browser/ui/win/electron_desktop_native_widget_aura.h"
#include "skia/ext/skia_utils_win.h"
#include "ui/base/win/shell.h"
#include "ui/display/screen.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/color_utils.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#endif
@@ -110,6 +112,11 @@ void FlipWindowStyle(HWND handle, bool on, DWORD flag) {
else
style &= ~flag;
::SetWindowLong(handle, GWL_STYLE, style);
// Window's frame styles are cached so we need to call SetWindowPos
// with the SWP_FRAMECHANGED flag to update cache properly.
::SetWindowPos(handle, 0, 0, 0, 0, 0, // ignored
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_NOACTIVATE | SWP_NOOWNERZORDER);
}
gfx::Rect DIPToScreenRect(HWND hwnd, const gfx::Rect& pixel_bounds) {
@@ -165,6 +172,37 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
options.Get("thickFrame", &thick_frame_);
if (transparent())
thick_frame_ = false;
overlay_button_color_ = color_utils::GetSysSkColor(COLOR_BTNFACE);
overlay_symbol_color_ = color_utils::GetSysSkColor(COLOR_BTNTEXT);
v8::Local<v8::Value> titlebar_overlay;
if (options.Get(options::ktitleBarOverlay, &titlebar_overlay) &&
titlebar_overlay->IsObject()) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
gin_helper::Dictionary titlebar_overlay_obj =
gin::Dictionary::CreateEmpty(isolate);
options.Get(options::ktitleBarOverlay, &titlebar_overlay_obj);
std::string overlay_color_string;
if (titlebar_overlay_obj.Get(options::kOverlayButtonColor,
&overlay_color_string)) {
bool success = extensions::image_util::ParseCssColorString(
overlay_color_string, &overlay_button_color_);
DCHECK(success);
}
std::string overlay_symbol_color_string;
if (titlebar_overlay_obj.Get(options::kOverlaySymbolColor,
&overlay_symbol_color_string)) {
bool success = extensions::image_util::ParseCssColorString(
overlay_symbol_color_string, &overlay_symbol_color_);
DCHECK(success);
}
}
if (title_bar_style_ != TitleBarStyle::kNormal)
set_has_frame(false);
#endif
if (enable_larger_than_screen())
@@ -1584,8 +1622,17 @@ void NativeWindowViews::OnMouseEvent(ui::MouseEvent* event) {
}
ui::WindowShowState NativeWindowViews::GetRestoredState() {
if (IsMaximized())
if (IsMaximized()) {
#if defined(OS_WIN)
// Only restore Maximized state when window is NOT transparent style
if (!transparent()) {
return ui::SHOW_STATE_MAXIMIZED;
}
#else
return ui::SHOW_STATE_MAXIMIZED;
#endif
}
if (IsFullscreen())
return ui::SHOW_STATE_FULLSCREEN;

View File

@@ -19,6 +19,7 @@
#if defined(OS_WIN)
#include "base/win/scoped_gdi_object.h"
#include "shell/browser/ui/win/taskbar_host.h"
#endif
namespace views {
@@ -174,6 +175,15 @@ class NativeWindowViews : public NativeWindow,
TaskbarHost& taskbar_host() { return taskbar_host_; }
#endif
#if defined(OS_WIN)
bool IsWindowControlsOverlayEnabled() const {
return (title_bar_style_ == NativeWindowViews::TitleBarStyle::kHidden) &&
titlebar_overlay_;
}
SkColor overlay_button_color() const { return overlay_button_color_; }
SkColor overlay_symbol_color() const { return overlay_symbol_color_; }
#endif
private:
// views::WidgetObserver:
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
@@ -294,6 +304,11 @@ class NativeWindowViews : public NativeWindow,
// Whether the window is currently being moved.
bool is_moving_ = false;
// The color to use as the theme and symbol colors respectively for Window
// Controls Overlay if enabled on Windows.
SkColor overlay_button_color_;
SkColor overlay_symbol_color_;
#endif
// Handles unhandled keyboard messages coming back from the renderer process.

View File

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

View File

@@ -62,8 +62,11 @@ using FullScreenTransitionState =
// menu to determine the "standard size" of the window.
- (NSRect)windowWillUseStandardFrame:(NSWindow*)window
defaultFrame:(NSRect)frame {
if (!shell_->zoom_to_page_width())
if (!shell_->zoom_to_page_width()) {
if (shell_->GetAspectRatio() > 0.0)
shell_->set_default_frame_for_zoom(frame);
return frame;
}
// If the shift key is down, maximize.
if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
@@ -88,6 +91,9 @@ using FullScreenTransitionState =
// Set the width. Don't touch y or height.
frame.size.width = zoomed_width;
if (shell_->GetAspectRatio() > 0.0)
shell_->set_default_frame_for_zoom(frame);
return frame;
}

View File

@@ -735,7 +735,10 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
bool showsArrowButtons = false;
settings.Get("showArrowButtons", &showsArrowButtons);
scrubber.showsArrowButtons = showsArrowButtons;
// The scrubber will crash if the user tries to scroll
// and there are no items.
if ([self numberOfItemsForScrubber:scrubber] > 0)
scrubber.showsArrowButtons = showsArrowButtons;
std::string selectedStyle;
std::string overlayStyle;

View File

@@ -25,13 +25,6 @@
@interface WindowButtonsProxy : NSObject {
@private
NSWindow* window_;
// The view that contains the window buttons and title.
NSView* titlebar_container_;
// The window buttons.
NSButton* left_;
NSButton* right_;
NSButton* middle_;
// Current left-top margin of buttons.
gfx::Point margin_;
@@ -61,6 +54,9 @@
- (void)redraw;
- (void)updateTrackingAreas;
- (gfx::Point)getMargin;
- (NSRect)getButtonsBounds;
@end
#endif // SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_PROXY_H_

View File

@@ -34,25 +34,6 @@
show_on_hover_ = NO;
mouse_inside_ = NO;
// Save the sequence of the buttons for later computation.
if (base::i18n::IsRTL()) {
left_ = [window_ standardWindowButton:NSWindowZoomButton];
right_ = [window_ standardWindowButton:NSWindowCloseButton];
} else {
left_ = [window_ standardWindowButton:NSWindowCloseButton];
right_ = [window_ standardWindowButton:NSWindowZoomButton];
}
middle_ = [window_ standardWindowButton:NSWindowMiniaturizeButton];
// Safety check just in case Apple changes the view structure in a macOS
// upgrade.
if (!left_.superview || !left_.superview.superview) {
NOTREACHED() << "macOS has changed its window buttons view structure.";
titlebar_container_ = nullptr;
return self;
}
titlebar_container_ = left_.superview.superview;
// Remember the default margin.
margin_ = default_margin_ = [self getCurrentMargin];
@@ -66,19 +47,22 @@
}
- (void)setVisible:(BOOL)visible {
if (!titlebar_container_)
NSView* titleBarContainer = [self titleBarContainer];
if (!titleBarContainer)
return;
[titlebar_container_ setHidden:!visible];
[titleBarContainer setHidden:!visible];
}
- (BOOL)isVisible {
if (!titlebar_container_)
NSView* titleBarContainer = [self titleBarContainer];
if (!titleBarContainer)
return YES;
return ![titlebar_container_ isHidden];
return ![titleBarContainer isHidden];
}
- (void)setShowOnHover:(BOOL)yes {
if (!titlebar_container_)
NSView* titleBarContainer = [self titleBarContainer];
if (!titleBarContainer)
return;
show_on_hover_ = yes;
// Put a transparent view above the window buttons so we can track mouse
@@ -86,7 +70,7 @@
if (show_on_hover_) {
hover_view_.reset([[ButtonsAreaHoverView alloc] initWithProxy:self]);
[hover_view_ setFrame:[self getButtonsBounds]];
[titlebar_container_ addSubview:hover_view_.get()];
[titleBarContainer addSubview:hover_view_.get()];
} else {
[hover_view_ removeFromSuperview];
hover_view_.reset();
@@ -107,12 +91,17 @@
}
- (void)redraw {
if (!titlebar_container_)
NSView* titleBarContainer = [self titleBarContainer];
if (!titleBarContainer)
return;
float button_width = NSWidth(left_.frame);
float button_height = NSHeight(left_.frame);
float padding = NSMinX(middle_.frame) - NSMaxX(left_.frame);
NSView* left = [self leftButton];
NSView* middle = [self middleButton];
NSView* right = [self rightButton];
float button_width = NSWidth(left.frame);
float button_height = NSHeight(left.frame);
float padding = NSMinX(middle.frame) - NSMaxX(left.frame);
float start;
if (base::i18n::IsRTL())
start =
@@ -120,16 +109,16 @@
else
start = margin_.x();
NSRect cbounds = titlebar_container_.frame;
NSRect cbounds = titleBarContainer.frame;
cbounds.size.height = button_height + 2 * margin_.y();
cbounds.origin.y = NSHeight(window_.frame) - NSHeight(cbounds);
[titlebar_container_ setFrame:cbounds];
[titleBarContainer setFrame:cbounds];
[left_ setFrameOrigin:NSMakePoint(start, margin_.y())];
[left setFrameOrigin:NSMakePoint(start, margin_.y())];
start += button_width + padding;
[middle_ setFrameOrigin:NSMakePoint(start, margin_.y())];
[middle setFrameOrigin:NSMakePoint(start, margin_.y())];
start += button_width + padding;
[right_ setFrameOrigin:NSMakePoint(start, margin_.y())];
[right setFrameOrigin:NSMakePoint(start, margin_.y())];
if (hover_view_)
[hover_view_ setFrame:[self getButtonsBounds]];
@@ -176,25 +165,63 @@
// Return the bounds of all 3 buttons.
- (NSRect)getButtonsBounds {
return NSMakeRect(NSMinX(left_.frame), NSMinY(left_.frame),
NSMaxX(right_.frame) - NSMinX(left_.frame),
NSHeight(left_.frame));
NSView* left = [self leftButton];
NSView* right = [self rightButton];
return NSMakeRect(NSMinX(left.frame), NSMinY(left.frame),
NSMaxX(right.frame) - NSMinX(left.frame),
NSHeight(left.frame));
}
// Compute margin from position of current buttons.
- (gfx::Point)getCurrentMargin {
gfx::Point result;
if (!titlebar_container_)
NSView* titleBarContainer = [self titleBarContainer];
if (!titleBarContainer)
return result;
result.set_y((NSHeight(titlebar_container_.frame) - NSHeight(left_.frame)) /
2);
NSView* left = [self leftButton];
NSView* right = [self rightButton];
result.set_y((NSHeight(titleBarContainer.frame) - NSHeight(left.frame)) / 2);
if (base::i18n::IsRTL())
result.set_x(NSWidth(window_.frame) - NSMaxX(right_.frame));
result.set_x(NSWidth(window_.frame) - NSMaxX(right.frame));
else
result.set_x(NSMinX(left_.frame));
result.set_x(NSMinX(left.frame));
return result;
}
- (gfx::Point)getMargin {
return margin_;
}
// Receive the titlebar container, which might be nil if the window does not
// have the NSWindowStyleMaskTitled style.
- (NSView*)titleBarContainer {
NSView* left = [self leftButton];
if (!left.superview)
return nil;
return left.superview.superview;
}
// Receive the window buttons, note that the buttons might be removed and
// re-added on the fly so we should not cache them.
- (NSButton*)leftButton {
if (base::i18n::IsRTL())
return [window_ standardWindowButton:NSWindowZoomButton];
else
return [window_ standardWindowButton:NSWindowCloseButton];
}
- (NSButton*)middleButton {
return [window_ standardWindowButton:NSWindowMiniaturizeButton];
}
- (NSButton*)rightButton {
if (base::i18n::IsRTL())
return [window_ standardWindowButton:NSWindowCloseButton];
else
return [window_ standardWindowButton:NSWindowZoomButton];
}
@end

View File

@@ -85,17 +85,17 @@ int FramelessView::NonClientHitTest(const gfx::Point& cursor) {
return HTCAPTION;
}
// Support resizing frameless window by dragging the border.
int frame_component = ResizingBorderHitTest(cursor);
if (frame_component != HTNOWHERE)
return frame_component;
// Check for possible draggable region in the client area for the frameless
// window.
SkRegion* draggable_region = window_->draggable_region();
if (draggable_region && draggable_region->contains(cursor.x(), cursor.y()))
return HTCAPTION;
// Support resizing frameless window by dragging the border.
int frame_component = ResizingBorderHitTest(cursor);
if (frame_component != HTNOWHERE)
return frame_component;
return HTCLIENT;
}

View File

@@ -48,6 +48,8 @@ class FramelessView : public views::NonClientFrameView {
NativeWindowViews* window_ = nullptr;
views::Widget* frame_ = nullptr;
friend class NativeWindowsViews;
private:
DISALLOW_COPY_AND_ASSIGN(FramelessView);
};

View File

@@ -41,6 +41,9 @@ class InspectableWebContentsViewViews : public InspectableWebContentsView,
const DevToolsContentsResizingStrategy& strategy) override;
void SetTitle(const std::u16string& title) override;
// views::View:
void Layout() override;
InspectableWebContents* inspectable_web_contents() {
return inspectable_web_contents_;
}
@@ -48,9 +51,6 @@ class InspectableWebContentsViewViews : public InspectableWebContentsView,
const std::u16string& GetTitle() const { return title_; }
private:
// views::View:
void Layout() override;
// Owns us.
InspectableWebContents* inspectable_web_contents_;

View File

@@ -0,0 +1,220 @@
// Copyright (c) 2016 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 "shell/browser/ui/views/win_caption_button.h"
#include <utility>
#include "base/i18n/rtl.h"
#include "base/numerics/safe_conversions.h"
#include "chrome/browser/ui/frame/window_frame_util.h"
#include "chrome/grit/theme_resources.h"
#include "shell/browser/ui/views/win_frame_view.h"
#include "shell/common/color_util.h"
#include "ui/base/theme_provider.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/views/metadata/metadata_impl_macros.h"
namespace electron {
WinCaptionButton::WinCaptionButton(PressedCallback callback,
WinFrameView* frame_view,
ViewID button_type,
const std::u16string& accessible_name)
: views::Button(std::move(callback)),
frame_view_(frame_view),
button_type_(button_type) {
SetAnimateOnStateChange(true);
// Not focusable by default, only for accessibility.
SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
SetAccessibleName(accessible_name);
}
gfx::Size WinCaptionButton::CalculatePreferredSize() const {
// TODO(bsep): The sizes in this function are for 1x device scale and don't
// match Windows button sizes at hidpi.
int height = WindowFrameUtil::kWindows10GlassCaptionButtonHeightRestored;
int base_width = WindowFrameUtil::kWindows10GlassCaptionButtonWidth;
return gfx::Size(base_width + GetBetweenButtonSpacing(), height);
}
void WinCaptionButton::OnPaintBackground(gfx::Canvas* canvas) {
// Paint the background of the button (the semi-transparent rectangle that
// appears when you hover or press the button).
const SkColor bg_color = frame_view_->window()->overlay_button_color();
const SkAlpha theme_alpha = SkColorGetA(bg_color);
gfx::Rect bounds = GetContentsBounds();
bounds.Inset(0, 0, 0, 0);
canvas->FillRect(bounds, SkColorSetA(bg_color, theme_alpha));
SkColor base_color;
SkAlpha hovered_alpha, pressed_alpha;
if (button_type_ == VIEW_ID_CLOSE_BUTTON) {
base_color = SkColorSetRGB(0xE8, 0x11, 0x23);
hovered_alpha = SK_AlphaOPAQUE;
pressed_alpha = 0x98;
} else {
// Match the native buttons.
base_color = frame_view_->GetReadableFeatureColor(bg_color);
hovered_alpha = 0x1A;
pressed_alpha = 0x33;
if (theme_alpha > 0) {
// Theme buttons have slightly increased opacity to make them stand out
// against a visually-busy frame image.
constexpr float kAlphaScale = 1.3f;
hovered_alpha = base::ClampRound<SkAlpha>(hovered_alpha * kAlphaScale);
pressed_alpha = base::ClampRound<SkAlpha>(pressed_alpha * kAlphaScale);
}
}
SkAlpha alpha;
if (GetState() == STATE_PRESSED)
alpha = pressed_alpha;
else
alpha = gfx::Tween::IntValueBetween(hover_animation().GetCurrentValue(),
SK_AlphaTRANSPARENT, hovered_alpha);
canvas->FillRect(bounds, SkColorSetA(base_color, alpha));
}
void WinCaptionButton::PaintButtonContents(gfx::Canvas* canvas) {
PaintSymbol(canvas);
}
int WinCaptionButton::GetBetweenButtonSpacing() const {
const int display_order_index = GetButtonDisplayOrderIndex();
return display_order_index == 0
? 0
: WindowFrameUtil::kWindows10GlassCaptionButtonVisualSpacing;
}
int WinCaptionButton::GetButtonDisplayOrderIndex() const {
int button_display_order = 0;
switch (button_type_) {
case VIEW_ID_MINIMIZE_BUTTON:
button_display_order = 0;
break;
case VIEW_ID_MAXIMIZE_BUTTON:
case VIEW_ID_RESTORE_BUTTON:
button_display_order = 1;
break;
case VIEW_ID_CLOSE_BUTTON:
button_display_order = 2;
break;
default:
NOTREACHED();
return 0;
}
// Reverse the ordering if we're in RTL mode
if (base::i18n::IsRTL())
button_display_order = 2 - button_display_order;
return button_display_order;
}
namespace {
// Canvas::DrawRect's stroke can bleed out of |rect|'s bounds, so this draws a
// rectangle inset such that the result is constrained to |rect|'s size.
void DrawRect(gfx::Canvas* canvas,
const gfx::Rect& rect,
const cc::PaintFlags& flags) {
gfx::RectF rect_f(rect);
float stroke_half_width = flags.getStrokeWidth() / 2;
rect_f.Inset(stroke_half_width, stroke_half_width);
canvas->DrawRect(rect_f, flags);
}
} // namespace
void WinCaptionButton::PaintSymbol(gfx::Canvas* canvas) {
SkColor symbol_color = frame_view_->window()->overlay_symbol_color();
if (button_type_ == VIEW_ID_CLOSE_BUTTON &&
hover_animation().is_animating()) {
symbol_color = gfx::Tween::ColorValueBetween(
hover_animation().GetCurrentValue(), symbol_color, SK_ColorWHITE);
} else if (button_type_ == VIEW_ID_CLOSE_BUTTON &&
(GetState() == STATE_HOVERED || GetState() == STATE_PRESSED)) {
symbol_color = SK_ColorWHITE;
}
gfx::ScopedCanvas scoped_canvas(canvas);
const float scale = canvas->UndoDeviceScaleFactor();
const int symbol_size_pixels = std::round(10 * scale);
gfx::RectF bounds_rect(GetContentsBounds());
bounds_rect.Scale(scale);
gfx::Rect symbol_rect(gfx::ToEnclosingRect(bounds_rect));
symbol_rect.ClampToCenteredSize(
gfx::Size(symbol_size_pixels, symbol_size_pixels));
cc::PaintFlags flags;
flags.setAntiAlias(false);
flags.setColor(symbol_color);
flags.setStyle(cc::PaintFlags::kStroke_Style);
// Stroke width jumps up a pixel every time we reach a new integral scale.
const int stroke_width = std::floor(scale);
flags.setStrokeWidth(stroke_width);
switch (button_type_) {
case VIEW_ID_MINIMIZE_BUTTON: {
const int y = symbol_rect.CenterPoint().y();
const gfx::Point p1 = gfx::Point(symbol_rect.x(), y);
const gfx::Point p2 = gfx::Point(symbol_rect.right(), y);
canvas->DrawLine(p1, p2, flags);
return;
}
case VIEW_ID_MAXIMIZE_BUTTON:
DrawRect(canvas, symbol_rect, flags);
return;
case VIEW_ID_RESTORE_BUTTON: {
// Bottom left ("in front") square.
const int separation = std::floor(2 * scale);
symbol_rect.Inset(0, separation, separation, 0);
DrawRect(canvas, symbol_rect, flags);
// Top right ("behind") square.
canvas->ClipRect(symbol_rect, SkClipOp::kDifference);
symbol_rect.Offset(separation, -separation);
DrawRect(canvas, symbol_rect, flags);
return;
}
case VIEW_ID_CLOSE_BUTTON: {
flags.setAntiAlias(true);
// The close button's X is surrounded by a "halo" of transparent pixels.
// When the X is white, the transparent pixels need to be a bit brighter
// to be visible.
const float stroke_halo =
stroke_width * (symbol_color == SK_ColorWHITE ? 0.1f : 0.05f);
flags.setStrokeWidth(stroke_width + stroke_halo);
// TODO(bsep): This sometimes draws misaligned at fractional device scales
// because the button's origin isn't necessarily aligned to pixels.
canvas->ClipRect(symbol_rect);
SkPath path;
path.moveTo(symbol_rect.x(), symbol_rect.y());
path.lineTo(symbol_rect.right(), symbol_rect.bottom());
path.moveTo(symbol_rect.right(), symbol_rect.y());
path.lineTo(symbol_rect.x(), symbol_rect.bottom());
canvas->DrawPath(path, flags);
return;
}
default:
NOTREACHED();
return;
}
}
} // namespace electron

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2016 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 SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_H_
#define SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_H_
#include "chrome/browser/ui/view_ids.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/metadata/metadata_header_macros.h"
namespace electron {
class WinFrameView;
class WinCaptionButton : public views::Button {
public:
WinCaptionButton(PressedCallback callback,
WinFrameView* frame_view,
ViewID button_type,
const std::u16string& accessible_name);
WinCaptionButton(const WinCaptionButton&) = delete;
WinCaptionButton& operator=(const WinCaptionButton&) = delete;
// // views::Button:
gfx::Size CalculatePreferredSize() const override;
void OnPaintBackground(gfx::Canvas* canvas) override;
void PaintButtonContents(gfx::Canvas* canvas) override;
// private:
// Returns the amount we should visually reserve on the left (right in RTL)
// for spacing between buttons. We do this instead of repositioning the
// buttons to avoid the sliver of deadspace that would result.
int GetBetweenButtonSpacing() const;
// Returns the order in which this button will be displayed (with 0 being
// drawn farthest to the left, and larger indices being drawn to the right of
// smaller indices).
int GetButtonDisplayOrderIndex() const;
// The base color to use for the button symbols and background blending. Uses
// the more readable of black and white.
SkColor GetBaseColor() const;
// Paints the minimize/maximize/restore/close icon for the button.
void PaintSymbol(gfx::Canvas* canvas);
WinFrameView* frame_view_;
ViewID button_type_;
};
} // namespace electron
#endif // SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_H_

View File

@@ -0,0 +1,143 @@
// Copyright 2020 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 "shell/browser/ui/views/win_caption_button_container.h"
#include <memory>
#include <utility>
#include "shell/browser/ui/views/win_caption_button.h"
#include "shell/browser/ui/views/win_frame_view.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/view_class_properties.h"
namespace electron {
namespace {
std::unique_ptr<WinCaptionButton> CreateCaptionButton(
views::Button::PressedCallback callback,
WinFrameView* frame_view,
ViewID button_type,
int accessible_name_resource_id) {
return std::make_unique<WinCaptionButton>(
std::move(callback), frame_view, button_type,
l10n_util::GetStringUTF16(accessible_name_resource_id));
}
bool HitTestCaptionButton(WinCaptionButton* button, const gfx::Point& point) {
return button && button->GetVisible() && button->bounds().Contains(point);
}
} // anonymous namespace
WinCaptionButtonContainer::WinCaptionButtonContainer(WinFrameView* frame_view)
: frame_view_(frame_view),
minimize_button_(AddChildView(CreateCaptionButton(
base::BindRepeating(&views::Widget::Minimize,
base::Unretained(frame_view_->frame())),
frame_view_,
VIEW_ID_MINIMIZE_BUTTON,
IDS_APP_ACCNAME_MINIMIZE))),
maximize_button_(AddChildView(CreateCaptionButton(
base::BindRepeating(&views::Widget::Maximize,
base::Unretained(frame_view_->frame())),
frame_view_,
VIEW_ID_MAXIMIZE_BUTTON,
IDS_APP_ACCNAME_MAXIMIZE))),
restore_button_(AddChildView(CreateCaptionButton(
base::BindRepeating(&views::Widget::Restore,
base::Unretained(frame_view_->frame())),
frame_view_,
VIEW_ID_RESTORE_BUTTON,
IDS_APP_ACCNAME_RESTORE))),
close_button_(AddChildView(CreateCaptionButton(
base::BindRepeating(&views::Widget::CloseWithReason,
base::Unretained(frame_view_->frame()),
views::Widget::ClosedReason::kCloseButtonClicked),
frame_view_,
VIEW_ID_CLOSE_BUTTON,
IDS_APP_ACCNAME_CLOSE))) {
// Layout is horizontal, with buttons placed at the trailing end of the view.
// This allows the container to expand to become a faux titlebar/drag handle.
auto* const layout = SetLayoutManager(std::make_unique<views::FlexLayout>());
layout->SetOrientation(views::LayoutOrientation::kHorizontal)
.SetMainAxisAlignment(views::LayoutAlignment::kEnd)
.SetCrossAxisAlignment(views::LayoutAlignment::kStart)
.SetDefault(
views::kFlexBehaviorKey,
views::FlexSpecification(views::LayoutOrientation::kHorizontal,
views::MinimumFlexSizeRule::kPreferred,
views::MaximumFlexSizeRule::kPreferred,
/* adjust_width_for_height */ false,
views::MinimumFlexSizeRule::kScaleToZero));
}
WinCaptionButtonContainer::~WinCaptionButtonContainer() {}
int WinCaptionButtonContainer::NonClientHitTest(const gfx::Point& point) const {
DCHECK(HitTestPoint(point))
<< "should only be called with a point inside this view's bounds";
if (HitTestCaptionButton(minimize_button_, point)) {
return HTMINBUTTON;
}
if (HitTestCaptionButton(maximize_button_, point)) {
return HTMAXBUTTON;
}
if (HitTestCaptionButton(restore_button_, point)) {
return HTMAXBUTTON;
}
if (HitTestCaptionButton(close_button_, point)) {
return HTCLOSE;
}
return HTCAPTION;
}
void WinCaptionButtonContainer::ResetWindowControls() {
minimize_button_->SetState(views::Button::STATE_NORMAL);
maximize_button_->SetState(views::Button::STATE_NORMAL);
restore_button_->SetState(views::Button::STATE_NORMAL);
close_button_->SetState(views::Button::STATE_NORMAL);
InvalidateLayout();
}
void WinCaptionButtonContainer::AddedToWidget() {
views::Widget* const widget = GetWidget();
DCHECK(!widget_observation_.IsObserving());
widget_observation_.Observe(widget);
UpdateButtons();
if (frame_view_->window()->IsWindowControlsOverlayEnabled()) {
SetPaintToLayer();
}
}
void WinCaptionButtonContainer::RemovedFromWidget() {
DCHECK(widget_observation_.IsObserving());
widget_observation_.Reset();
}
void WinCaptionButtonContainer::OnWidgetBoundsChanged(
views::Widget* widget,
const gfx::Rect& new_bounds) {
UpdateButtons();
}
void WinCaptionButtonContainer::UpdateButtons() {
const bool is_maximized = frame_view_->frame()->IsMaximized();
restore_button_->SetVisible(is_maximized);
maximize_button_->SetVisible(!is_maximized);
// In touch mode, windows cannot be taken out of fullscreen or tiled mode, so
// the maximize/restore button should be disabled.
const bool is_touch = ui::TouchUiController::Get()->touch_ui();
restore_button_->SetEnabled(!is_touch);
maximize_button_->SetEnabled(!is_touch);
InvalidateLayout();
}
} // namespace electron

View File

@@ -0,0 +1,70 @@
// Copyright 2020 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 SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_CONTAINER_H_
#define SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_CONTAINER_H_
#include "base/scoped_observation.h"
#include "ui/base/pointer/touch_ui_controller.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace electron {
class WinFrameView;
class WinCaptionButton;
// Provides a container for Windows 10 caption buttons that can be moved between
// frame and browser window as needed. When extended horizontally, becomes a
// grab bar for moving the window.
class WinCaptionButtonContainer : public views::View,
public views::WidgetObserver {
public:
explicit WinCaptionButtonContainer(WinFrameView* frame_view);
~WinCaptionButtonContainer() override;
// Tests to see if the specified |point| (which is expressed in this view's
// coordinates and which must be within this view's bounds) is within one of
// the caption buttons. Returns one of HitTestCompat enum defined in
// ui/base/hit_test.h, HTCAPTION if the area hit would be part of the window's
// drag handle, and HTNOWHERE otherwise.
// See also ClientView::NonClientHitTest.
int NonClientHitTest(const gfx::Point& point) const;
private:
// views::View:
void AddedToWidget() override;
void RemovedFromWidget() override;
// views::WidgetObserver:
void OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) override;
void ResetWindowControls();
// Sets caption button visibility and enabled state based on window state.
// Only one of maximize or restore button should ever be visible at the same
// time, and both are disabled in tablet UI mode.
void UpdateButtons();
WinFrameView* const frame_view_;
WinCaptionButton* const minimize_button_;
WinCaptionButton* const maximize_button_;
WinCaptionButton* const restore_button_;
WinCaptionButton* const close_button_;
base::ScopedObservation<views::Widget, views::WidgetObserver>
widget_observation_{this};
base::CallbackListSubscription subscription_ =
ui::TouchUiController::Get()->RegisterCallback(
base::BindRepeating(&WinCaptionButtonContainer::UpdateButtons,
base::Unretained(this)));
};
} // namespace electron
#endif // SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_CONTAINER_H_

View File

@@ -1,11 +1,24 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
//
// Portions of this file are sourced from
// chrome/browser/ui/views/frame/glass_browser_frame_view.cc,
// Copyright (c) 2012 The Chromium Authors,
// which is governed by a BSD-style license
#include "shell/browser/ui/views/win_frame_view.h"
#include <dwmapi.h>
#include <memory>
#include "base/win/windows_version.h"
#include "shell/browser/native_window_views.h"
#include "shell/browser/ui/views/win_caption_button_container.h"
#include "ui/base/win/hwnd_metrics.h"
#include "ui/display/win/dpi.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/views/widget/widget.h"
#include "ui/views/win/hwnd_util.h"
@@ -17,6 +30,30 @@ WinFrameView::WinFrameView() {}
WinFrameView::~WinFrameView() {}
void WinFrameView::Init(NativeWindowViews* window, views::Widget* frame) {
window_ = window;
frame_ = frame;
if (window->IsWindowControlsOverlayEnabled()) {
caption_button_container_ =
AddChildView(std::make_unique<WinCaptionButtonContainer>(this));
} else {
caption_button_container_ = nullptr;
}
}
SkColor WinFrameView::GetReadableFeatureColor(SkColor background_color) {
// color_utils::GetColorWithMaxContrast()/IsDark() aren't used here because
// they switch based on the Chrome light/dark endpoints, while we want to use
// the system native behavior below.
const auto windows_luma = [](SkColor c) {
return 0.25f * SkColorGetR(c) + 0.625f * SkColorGetG(c) +
0.125f * SkColorGetB(c);
};
return windows_luma(background_color) <= 128.0f ? SK_ColorWHITE
: SK_ColorBLACK;
}
gfx::Rect WinFrameView::GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const {
return views::GetWindowBoundsForClientBounds(
@@ -24,15 +61,196 @@ gfx::Rect WinFrameView::GetWindowBoundsForClientBounds(
client_bounds);
}
int WinFrameView::FrameBorderThickness() const {
return (IsMaximized() || frame()->IsFullscreen())
? 0
: display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXSIZEFRAME);
}
int WinFrameView::NonClientHitTest(const gfx::Point& point) {
if (window_->has_frame())
return frame_->client_view()->NonClientHitTest(point);
else
return FramelessView::NonClientHitTest(point);
if (ShouldCustomDrawSystemTitlebar()) {
// See if the point is within any of the window controls.
if (caption_button_container_) {
gfx::Point local_point = point;
ConvertPointToTarget(parent(), caption_button_container_, &local_point);
if (caption_button_container_->HitTestPoint(local_point)) {
const int hit_test_result =
caption_button_container_->NonClientHitTest(local_point);
if (hit_test_result != HTNOWHERE)
return hit_test_result;
}
}
// On Windows 8+, the caption buttons are almost butted up to the top right
// corner of the window. This code ensures the mouse isn't set to a size
// cursor while hovering over the caption buttons, thus giving the incorrect
// impression that the user can resize the window.
if (base::win::GetVersion() >= base::win::Version::WIN8) {
RECT button_bounds = {0};
if (SUCCEEDED(DwmGetWindowAttribute(
views::HWNDForWidget(frame()), DWMWA_CAPTION_BUTTON_BOUNDS,
&button_bounds, sizeof(button_bounds)))) {
gfx::RectF button_bounds_in_dips = gfx::ConvertRectToDips(
gfx::Rect(button_bounds), display::win::GetDPIScale());
// TODO(crbug.com/1131681): GetMirroredRect() requires an integer rect,
// but the size in DIPs may not be an integer with a fractional device
// scale factor. If we want to keep using integers, the choice to use
// ToFlooredRectDeprecated() seems to be doing the wrong thing given the
// comment below about insetting 1 DIP instead of 1 physical pixel. We
// should probably use ToEnclosedRect() and then we could have inset 1
// physical pixel here.
gfx::Rect buttons = GetMirroredRect(
gfx::ToFlooredRectDeprecated(button_bounds_in_dips));
// There is a small one-pixel strip right above the caption buttons in
// which the resize border "peeks" through.
constexpr int kCaptionButtonTopInset = 1;
// The sizing region at the window edge above the caption buttons is
// 1 px regardless of scale factor. If we inset by 1 before converting
// to DIPs, the precision loss might eliminate this region entirely. The
// best we can do is to inset after conversion. This guarantees we'll
// show the resize cursor when resizing is possible. The cost of which
// is also maybe showing it over the portion of the DIP that isn't the
// outermost pixel.
buttons.Inset(0, kCaptionButtonTopInset, 0, 0);
if (buttons.Contains(point))
return HTNOWHERE;
}
}
int top_border_thickness = FrameTopBorderThickness(false);
// At the window corners the resize area is not actually bigger, but the 16
// pixels at the end of the top and bottom edges trigger diagonal resizing.
constexpr int kResizeCornerWidth = 16;
int window_component = GetHTComponentForFrame(
point, top_border_thickness, top_border_thickness, top_border_thickness,
kResizeCornerWidth - FrameBorderThickness(),
frame()->widget_delegate()->CanResize());
if (window_component != HTNOWHERE)
return window_component;
}
// Use the parent class's hittest last
return FramelessView::NonClientHitTest(point);
}
const char* WinFrameView::GetClassName() const {
return kViewClassName;
}
bool WinFrameView::IsMaximized() const {
return frame()->IsMaximized();
}
bool WinFrameView::ShouldCustomDrawSystemTitlebar() const {
return window()->IsWindowControlsOverlayEnabled();
}
void WinFrameView::Layout() {
LayoutCaptionButtons();
if (window()->IsWindowControlsOverlayEnabled()) {
LayoutWindowControlsOverlay();
}
NonClientFrameView::Layout();
}
int WinFrameView::FrameTopBorderThickness(bool restored) const {
// Mouse and touch locations are floored but GetSystemMetricsInDIP is rounded,
// so we need to floor instead or else the difference will cause the hittest
// to fail when it ought to succeed.
return std::floor(
FrameTopBorderThicknessPx(restored) /
display::win::ScreenWin::GetScaleFactorForHWND(HWNDForView(this)));
}
int WinFrameView::FrameTopBorderThicknessPx(bool restored) const {
// Distinct from FrameBorderThickness() because we can't inset the top
// border, otherwise Windows will give us a standard titlebar.
// For maximized windows this is not true, and the top border must be
// inset in order to avoid overlapping the monitor above.
// See comments in BrowserDesktopWindowTreeHostWin::GetClientAreaInsets().
const bool needs_no_border =
(ShouldCustomDrawSystemTitlebar() && frame()->IsMaximized()) ||
frame()->IsFullscreen();
if (needs_no_border && !restored)
return 0;
// Note that this method assumes an equal resize handle thickness on all
// sides of the window.
// TODO(dfried): Consider having it return a gfx::Insets object instead.
return ui::GetFrameThickness(
MonitorFromWindow(HWNDForView(this), MONITOR_DEFAULTTONEAREST));
}
int WinFrameView::TitlebarMaximizedVisualHeight() const {
int maximized_height =
display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYCAPTION);
return maximized_height;
}
int WinFrameView::TitlebarHeight(bool restored) const {
if (frame()->IsFullscreen() && !restored)
return 0;
return TitlebarMaximizedVisualHeight() + FrameTopBorderThickness(false);
}
int WinFrameView::WindowTopY() const {
// The window top is SM_CYSIZEFRAME pixels when maximized (see the comment in
// FrameTopBorderThickness()) and floor(system dsf) pixels when restored.
// Unfortunately we can't represent either of those at hidpi without using
// non-integral dips, so we return the closest reasonable values instead.
if (IsMaximized())
return FrameTopBorderThickness(false);
return 1;
}
void WinFrameView::LayoutCaptionButtons() {
if (!caption_button_container_)
return;
// Non-custom system titlebar already contains caption buttons.
if (!ShouldCustomDrawSystemTitlebar()) {
caption_button_container_->SetVisible(false);
return;
}
caption_button_container_->SetVisible(true);
const gfx::Size preferred_size =
caption_button_container_->GetPreferredSize();
int height = preferred_size.height();
height = IsMaximized() ? TitlebarMaximizedVisualHeight()
: TitlebarHeight(false) - WindowTopY();
// TODO(mlaurencin): This -1 creates a 1 pixel gap between the right
// edge of the overlay and the edge of the window, allowing for this edge
// portion to return the correct hit test and be manually resized properly.
// Alternatives can be explored, but the differences in view structures
// between Electron and Chromium may result in this as the best option.
int variable_width =
IsMaximized() ? preferred_size.width() : preferred_size.width() - 1;
caption_button_container_->SetBounds(width() - preferred_size.width(),
WindowTopY(), variable_width, height);
}
void WinFrameView::LayoutWindowControlsOverlay() {
int overlay_height = caption_button_container_->size().height();
int overlay_width = caption_button_container_->size().width();
int bounding_rect_width = width() - overlay_width;
auto bounding_rect =
GetMirroredRect(gfx::Rect(0, 0, bounding_rect_width, overlay_height));
window()->SetWindowControlsOverlayRect(bounding_rect);
window()->NotifyLayoutWindowControlsOverlay();
}
} // namespace electron

View File

@@ -1,11 +1,18 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
//
// Portions of this file are sourced from
// chrome/browser/ui/views/frame/glass_browser_frame_view.h,
// Copyright (c) 2012 The Chromium Authors,
// which is governed by a BSD-style license
#ifndef SHELL_BROWSER_UI_VIEWS_WIN_FRAME_VIEW_H_
#define SHELL_BROWSER_UI_VIEWS_WIN_FRAME_VIEW_H_
#include "shell/browser/native_window_views.h"
#include "shell/browser/ui/views/frameless_view.h"
#include "shell/browser/ui/views/win_caption_button.h"
namespace electron {
@@ -15,6 +22,14 @@ class WinFrameView : public FramelessView {
WinFrameView();
~WinFrameView() override;
void Init(NativeWindowViews* window, views::Widget* frame) override;
// Alpha to use for features in the titlebar (the window title and caption
// buttons) when the window is inactive. They are opaque when active.
static constexpr SkAlpha kInactiveTitlebarFeatureAlpha = 0x66;
SkColor GetReadableFeatureColor(SkColor background_color);
// views::NonClientFrameView:
gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const override;
@@ -23,7 +38,50 @@ class WinFrameView : public FramelessView {
// views::View:
const char* GetClassName() const override;
NativeWindowViews* window() const { return window_; }
views::Widget* frame() const { return frame_; }
bool IsMaximized() const;
bool ShouldCustomDrawSystemTitlebar() const;
// Visual height of the titlebar when the window is maximized (i.e. excluding
// the area above the top of the screen).
int TitlebarMaximizedVisualHeight() const;
protected:
// views::View:
void Layout() override;
private:
friend class WinCaptionButtonContainer;
int FrameBorderThickness() const;
// Returns the thickness of the window border for the top edge of the frame,
// which is sometimes different than FrameBorderThickness(). Does not include
// the titlebar/tabstrip area. If |restored| is true, this is calculated as if
// the window was restored, regardless of its current state.
int FrameTopBorderThickness(bool restored) const;
int FrameTopBorderThicknessPx(bool restored) const;
// Returns the height of the titlebar for popups or other browser types that
// don't have tabs.
int TitlebarHeight(bool restored) const;
// Returns the y coordinate for the top of the frame, which in maximized mode
// is the top of the screen and in restored mode is 1 pixel below the top of
// the window to leave room for the visual border that Windows draws.
int WindowTopY() const;
void LayoutCaptionButtons();
void LayoutWindowControlsOverlay();
// The container holding the caption buttons (minimize, maximize, close, etc.)
// May be null if the caption button container is destroyed before the frame
// view. Always check for validity before using!
WinCaptionButtonContainer* caption_button_container_;
DISALLOW_COPY_AND_ASSIGN(WinFrameView);
};

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

@@ -31,6 +31,11 @@ const char kFullscreen[] = "fullscreen";
const char kTrafficLightPosition[] = "trafficLightPosition";
const char kRoundedCorners[] = "roundedCorners";
// The color to use as the theme and symbol colors respectively for Window
// Controls Overlay if enabled on Windows.
const char kOverlayButtonColor[] = "color";
const char kOverlaySymbolColor[] = "symbolColor";
// Whether the window should show in taskbar.
const char kSkipTaskbar[] = "skipTaskbar";
@@ -201,6 +206,8 @@ const char kEnableWebSQL[] = "enableWebSQL";
const char kEnablePreferredSizeMode[] = "enablePreferredSizeMode";
const char ktitleBarOverlay[] = "titleBarOverlay";
} // namespace options
namespace switches {

View File

@@ -57,6 +57,9 @@ extern const char kVibrancyType[];
extern const char kVisualEffectState[];
extern const char kTrafficLightPosition[];
extern const char kRoundedCorners[];
extern const char ktitleBarOverlay[];
extern const char kOverlayButtonColor[];
extern const char kOverlaySymbolColor[];
// WebPreferences.
extern const char kZoomFactor[];

View File

@@ -4,13 +4,19 @@
#include "shell/common/platform_util.h"
#include <fcntl.h>
#include <stdio.h>
#include <string>
#include <vector>
#include "base/cancelable_callback.h"
#include "base/containers/contains.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/nix/xdg_util.h"
#include "base/no_destructor.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/threading/thread_restrictions.h"
@@ -20,6 +26,7 @@
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "shell/common/platform_util_internal.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gtk/gtk_util.h"
#include "url/gurl.h"
@@ -31,11 +38,20 @@ void OpenFolder(const base::FilePath& full_path);
namespace {
const char kMethodListActivatableNames[] = "ListActivatableNames";
const char kMethodNameHasOwner[] = "NameHasOwner";
const char kFreedesktopFileManagerName[] = "org.freedesktop.FileManager1";
const char kFreedesktopFileManagerPath[] = "/org/freedesktop/FileManager1";
const char kMethodShowItems[] = "ShowItems";
const char kFreedesktopPortalName[] = "org.freedesktop.portal.Desktop";
const char kFreedesktopPortalPath[] = "/org/freedesktop/portal/desktop";
const char kFreedesktopPortalOpenURI[] = "org.freedesktop.portal.OpenURI";
const char kMethodOpenDirectory[] = "OpenDirectory";
class ShowItemHelper {
public:
static ShowItemHelper& GetInstance() {
@@ -58,8 +74,136 @@ class ShowItemHelper {
bus_ = base::MakeRefCounted<dbus::Bus>(bus_options);
}
if (!filemanager_proxy_) {
filemanager_proxy_ =
if (!dbus_proxy_) {
dbus_proxy_ = bus_->GetObjectProxy(DBUS_SERVICE_DBUS,
dbus::ObjectPath(DBUS_PATH_DBUS));
}
if (prefer_filemanager_interface_.has_value()) {
if (prefer_filemanager_interface_.value()) {
ShowItemUsingFileManager(full_path);
} else {
ShowItemUsingFreedesktopPortal(full_path);
}
} else {
CheckFileManagerRunning(full_path);
}
}
private:
void CheckFileManagerRunning(const base::FilePath& full_path) {
dbus::MethodCall method_call(DBUS_INTERFACE_DBUS, kMethodNameHasOwner);
dbus::MessageWriter writer(&method_call);
writer.AppendString(kFreedesktopFileManagerName);
dbus_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&ShowItemHelper::CheckFileManagerRunningResponse,
base::Unretained(this), full_path));
}
void CheckFileManagerRunningResponse(const base::FilePath& full_path,
dbus::Response* response) {
if (prefer_filemanager_interface_.has_value()) {
ShowItemInFolder(full_path);
return;
}
bool is_running = false;
if (!response) {
LOG(ERROR) << "Failed to call " << kMethodNameHasOwner;
} else {
dbus::MessageReader reader(response);
bool owned = false;
if (!reader.PopBool(&owned)) {
LOG(ERROR) << "Failed to read " << kMethodNameHasOwner << " resposne";
} else if (owned) {
is_running = true;
}
}
if (is_running) {
prefer_filemanager_interface_ = true;
ShowItemInFolder(full_path);
} else {
CheckFileManagerActivatable(full_path);
}
}
void CheckFileManagerActivatable(const base::FilePath& full_path) {
dbus::MethodCall method_call(DBUS_INTERFACE_DBUS,
kMethodListActivatableNames);
dbus_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&ShowItemHelper::CheckFileManagerActivatableResponse,
base::Unretained(this), full_path));
}
void CheckFileManagerActivatableResponse(const base::FilePath& full_path,
dbus::Response* response) {
if (prefer_filemanager_interface_.has_value()) {
ShowItemInFolder(full_path);
return;
}
bool is_activatable = false;
if (!response) {
LOG(ERROR) << "Failed to call " << kMethodListActivatableNames;
} else {
dbus::MessageReader reader(response);
std::vector<std::string> names;
if (!reader.PopArrayOfStrings(&names)) {
LOG(ERROR) << "Failed to read " << kMethodListActivatableNames
<< " response";
} else if (base::Contains(names, kFreedesktopFileManagerName)) {
is_activatable = true;
}
}
prefer_filemanager_interface_ = is_activatable;
ShowItemInFolder(full_path);
}
void ShowItemUsingFreedesktopPortal(const base::FilePath& full_path) {
if (!object_proxy_) {
object_proxy_ = bus_->GetObjectProxy(
kFreedesktopPortalName, dbus::ObjectPath(kFreedesktopPortalPath));
}
base::ScopedFD fd(
HANDLE_EINTR(open(full_path.value().c_str(), O_RDONLY | O_CLOEXEC)));
if (!fd.is_valid()) {
LOG(ERROR) << "Failed to open " << full_path << " for URI portal";
// If the call fails, at least open the parent folder.
platform_util::OpenFolder(full_path.DirName());
return;
}
dbus::MethodCall open_directory_call(kFreedesktopPortalOpenURI,
kMethodOpenDirectory);
dbus::MessageWriter writer(&open_directory_call);
writer.AppendString("");
// Note that AppendFileDescriptor() duplicates the fd, so we shouldn't
// release ownership of it here.
writer.AppendFileDescriptor(fd.get());
dbus::MessageWriter options_writer(nullptr);
writer.OpenArray("{sv}", &options_writer);
writer.CloseContainer(&options_writer);
ShowItemUsingBusCall(&open_directory_call, full_path);
}
void ShowItemUsingFileManager(const base::FilePath& full_path) {
if (!object_proxy_) {
object_proxy_ =
bus_->GetObjectProxy(kFreedesktopFileManagerName,
dbus::ObjectPath(kFreedesktopFileManagerPath));
}
@@ -72,25 +216,33 @@ class ShowItemHelper {
{"file://" + full_path.value()}); // List of file(s) to highlight.
writer.AppendString({}); // startup-id
filemanager_proxy_->CallMethod(
&show_items_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&ShowItemHelper::ShowItemInFolderResponse,
base::Unretained(this), full_path));
ShowItemUsingBusCall(&show_items_call, full_path);
}
void ShowItemUsingBusCall(dbus::MethodCall* call,
const base::FilePath& full_path) {
object_proxy_->CallMethod(
call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&ShowItemHelper::ShowItemInFolderResponse,
base::Unretained(this), full_path, call->GetMember()));
}
private:
void ShowItemInFolderResponse(const base::FilePath& full_path,
const std::string& method,
dbus::Response* response) {
if (response)
return;
LOG(ERROR) << "Error calling " << kMethodShowItems;
// If the FileManager1 call fails, at least open the parent folder.
LOG(ERROR) << "Error calling " << method;
// If the bus call fails, at least open the parent folder.
platform_util::OpenFolder(full_path.DirName());
}
scoped_refptr<dbus::Bus> bus_;
dbus::ObjectProxy* filemanager_proxy_ = nullptr;
dbus::ObjectProxy* dbus_proxy_ = nullptr;
dbus::ObjectProxy* object_proxy_ = nullptr;
absl::optional<bool> prefer_filemanager_interface_;
};
// Descriptions pulled from https://linux.die.net/man/1/xdg-open

View File

@@ -5,6 +5,7 @@ import * as fs from 'fs';
import * as os from 'os';
import * as qs from 'querystring';
import * as http from 'http';
import * as semver from 'semver';
import { AddressInfo } from 'net';
import { app, BrowserWindow, BrowserView, dialog, ipcMain, OnBeforeSendHeadersListenerDetails, protocol, screen, webContents, session, WebContents, BrowserWindowConstructorOptions } from 'electron/main';
@@ -1100,6 +1101,24 @@ describe('BrowserWindow module', () => {
await unmaximize;
expect(w.isMaximized()).to.equal(false);
});
it('returns the correct value for windows with an aspect ratio', async () => {
w.destroy();
w = new BrowserWindow({
show: false,
fullscreenable: false
});
w.setAspectRatio(16 / 11);
const maximize = emittedOnce(w, 'resize');
w.show();
w.maximize();
await maximize;
expect(w.isMaximized()).to.equal(true);
w.resizable = false;
expect(w.isMaximized()).to.equal(true);
});
});
ifdescribe(process.platform !== 'linux')('Minimized state', () => {
@@ -1864,8 +1883,47 @@ describe('BrowserWindow module', () => {
});
});
ifdescribe(process.platform === 'darwin' && parseInt(os.release().split('.')[0]) >= 14)('"titleBarStyle" option', () => {
ifdescribe(process.platform === 'win32' || (process.platform === 'darwin' && semver.gte(os.release(), '14.0.0')))('"titleBarStyle" option', () => {
const testWindowsOverlay = async (style: any) => {
const w = new BrowserWindow({
show: false,
width: 400,
height: 400,
titleBarStyle: style,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
titleBarOverlay: true
});
const overlayHTML = path.join(__dirname, 'fixtures', 'pages', 'overlay.html');
if (process.platform === 'darwin') {
await w.loadFile(overlayHTML);
} else {
const overlayReady = emittedOnce(ipcMain, 'geometrychange');
await w.loadFile(overlayHTML);
await overlayReady;
}
const overlayEnabled = await w.webContents.executeJavaScript('navigator.windowControlsOverlay.visible');
expect(overlayEnabled).to.be.true('overlayEnabled');
const overlayRect = await w.webContents.executeJavaScript('getJSOverlayProperties()');
expect(overlayRect.y).to.equal(0);
if (process.platform === 'darwin') {
expect(overlayRect.x).to.be.greaterThan(0);
} else {
expect(overlayRect.x).to.equal(0);
}
expect(overlayRect.width).to.be.greaterThan(0);
expect(overlayRect.height).to.be.greaterThan(0);
const cssOverlayRect = await w.webContents.executeJavaScript('getCssOverlayProperties();');
expect(cssOverlayRect).to.deep.equal(overlayRect);
const geometryChange = emittedOnce(ipcMain, 'geometrychange');
w.setBounds({ width: 800 });
const [, newOverlayRect] = await geometryChange;
expect(newOverlayRect.width).to.equal(overlayRect.width + 400);
};
afterEach(closeAllWindows);
afterEach(() => { ipcMain.removeAllListeners('geometrychange'); });
it('creates browser window with hidden title bar', () => {
const w = new BrowserWindow({
show: false,
@@ -1876,7 +1934,7 @@ describe('BrowserWindow module', () => {
const contentSize = w.getContentSize();
expect(contentSize).to.deep.equal([400, 400]);
});
it('creates browser window with hidden inset title bar', () => {
ifit(process.platform === 'darwin')('creates browser window with hidden inset title bar', () => {
const w = new BrowserWindow({
show: false,
width: 400,
@@ -1886,6 +1944,12 @@ describe('BrowserWindow module', () => {
const contentSize = w.getContentSize();
expect(contentSize).to.deep.equal([400, 400]);
});
it('sets Window Control Overlay with hidden title bar', async () => {
await testWindowsOverlay('hidden');
});
ifit(process.platform === 'darwin')('sets Window Control Overlay with hidden inset title bar', async () => {
await testWindowsOverlay('hiddenInset');
});
});
ifdescribe(process.platform === 'darwin')('"enableLargerThanScreen" option', () => {
@@ -4745,4 +4809,32 @@ describe('BrowserWindow module', () => {
});
});
});
describe('"transparent" option', () => {
afterEach(closeAllWindows);
// Only applicable on Windows where transparent windows can't be maximized.
ifit(process.platform === 'win32')('can show maximized frameless window', async () => {
const display = screen.getPrimaryDisplay();
const w = new BrowserWindow({
...display.bounds,
frame: false,
transparent: true,
show: true
});
w.loadURL('about:blank');
await emittedOnce(w, 'ready-to-show');
expect(w.isMaximized()).to.be.true();
// Fails when the transparent HWND is in an invalid maximized state.
expect(w.getBounds()).to.deep.equal(display.workArea);
const newBounds = { width: 256, height: 256, x: 0, y: 0 };
w.setBounds(newBounds);
expect(w.getBounds()).to.deep.equal(newBounds);
});
});
});

View File

@@ -47,6 +47,24 @@ describe('webContents module', () => {
});
});
describe('fromDevToolsTargetId()', () => {
it('returns WebContents for attached DevTools target', async () => {
const w = new BrowserWindow({ show: false });
await w.loadURL('about:blank');
try {
await w.webContents.debugger.attach('1.3');
const { targetInfo } = await w.webContents.debugger.sendCommand('Target.getTargetInfo');
expect(webContents.fromDevToolsTargetId(targetInfo.targetId)).to.equal(w.webContents);
} finally {
await w.webContents.debugger.detach();
}
});
it('returns undefined for an unknown id', () => {
expect(webContents.fromDevToolsTargetId('nope')).to.be.undefined();
});
});
describe('will-prevent-unload event', function () {
afterEach(closeAllWindows);
it('does not emit if beforeunload returns undefined', async () => {

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<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>Hello One!</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>

View File

@@ -0,0 +1,37 @@
const { app, BrowserWindow, webContents, protocol } = require('electron');
const path = require('path');
app.allowRendererProcessReuse = false;
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { standard: true, secure: true } }
]);
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
mainWindow.webContents.session.protocol.registerFileProtocol('foo', (request, callback) => {
const url = new URL(request.url);
callback({ path: `${__dirname}${url.pathname}` });
});
mainWindow.webContents.on('did-finish-load', () => {
setImmediate(() => app.quit());
});
// Creates WebFrameMain instance before initiating the navigation.
mainWindow.webContents.send('test', 'ping');
mainWindow.loadURL('foo://app/index.html');
}
app.whenReady().then(() => {
createWindow();
});

View File

@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
:root {
--fallback-title-bar-height: 40px;
}
.draggable {
app-region: drag;
/* Pre-fix app-region during standardization process */
-webkit-app-region: drag;
}
.nonDraggable {
app-region: no-drag;
/* Pre-fix app-region during standardization process */
-webkit-app-region: no-drag;
}
#titleBarContainer {
position: absolute;
top: env(titlebar-area-y, 0);
height: env(titlebar-area-height, var(--fallback-title-bar-height));
width: 100%;
}
#titleBar {
position: absolute;
top: 0;
display: flex;
user-select: none;
height: 100%;
left: env(titlebar-area-x, 0);
width: env(titlebar-area-width, 100%);
}
#mainContent {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: env(titlebar-area-height, var(--fallback-title-bar-height));
overflow-y: scroll;
}
</style>
</head>
<body>
<script>
const {ipcRenderer} = require('electron');
navigator.windowControlsOverlay.ongeometrychange = function() {
const {x, y, width, height} = navigator.windowControlsOverlay.getBoundingClientRect();
ipcRenderer.send('geometrychange', {x, y, width, height});
};
</script>
<div id="titleBarContainer">
<div id="titleBar" class=" draggable">
<span class="draggable">Title goes here</span>
<input class="nonDraggable" type="text" placeholder="Search"></input>
</div>
</div>
<div id="mainContent"><!-- The rest of the webpage --></div>
<script>
function getCssOverlayProperties() {
const cssOverlayProps = {};
const titleBarContainer = document.getElementById('titleBarContainer');
const titleBar = document.getElementById('titleBar');
cssOverlayProps.y = titleBarContainer.computedStyleMap().get('top').value;
cssOverlayProps.height = titleBarContainer.computedStyleMap().get('height').value;
cssOverlayProps.x = titleBar.computedStyleMap().get('left').value;
cssOverlayProps.width = titleBar.computedStyleMap().get('width').value;
return cssOverlayProps;
}
function getJSOverlayProperties() {
const {x, y, width, height} = navigator.windowControlsOverlay.getBoundingClientRect();
return {x, y, width, height};
}
</script>
</body>
</html>

View File

@@ -31,6 +31,7 @@ app.on('window-all-closed', () => null);
// Use fake device for Media Stream to replace actual camera and microphone.
app.commandLine.appendSwitch('use-fake-device-for-media-stream');
app.commandLine.appendSwitch('host-rules', 'MAP localhost2 127.0.0.1');
global.standardScheme = 'app';
global.zoomScheme = 'zoom';

View File

@@ -62,7 +62,7 @@ describe('security warnings', () => {
});
});
}).listen(0, '127.0.0.1', () => {
serverUrl = `http://127.0.0.1:${(server.address() as AddressInfo).port}`;
serverUrl = `http://localhost2:${(server.address() as AddressInfo).port}`;
done();
});
});

View File

@@ -316,7 +316,7 @@ declare namespace ElectronInternal {
declare namespace Chrome {
namespace Tabs {
// https://developer.chrome.com/extensions/tabs#method-executeScript
// https://developer.chrome.com/docs/extensions/tabs#method-executeScript
interface ExecuteScriptDetails {
code?: string;
file?: string;
@@ -329,7 +329,7 @@ declare namespace Chrome {
type ExecuteScriptCallback = (result: Array<any>) => void;
// https://developer.chrome.com/extensions/tabs#method-sendMessage
// https://developer.chrome.com/docs/extensions/tabs#method-sendMessage
interface SendMessageDetails {
frameId?: number;
}