mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d93629321e | ||
|
|
b505de0765 | ||
|
|
4c4d29eb73 | ||
|
|
993ecb5bdd | ||
|
|
d0ba8d1f69 | ||
|
|
d03fd85a90 | ||
|
|
2387d10956 | ||
|
|
558350e4bf | ||
|
|
4d960873a4 | ||
|
|
dfcb2afffd | ||
|
|
221fd9d6ce | ||
|
|
ecad7c2441 | ||
|
|
a9acc050ee | ||
|
|
29311b7d1d | ||
|
|
949ec0c7c9 | ||
|
|
91b1c0162e | ||
|
|
e20eab42d3 | ||
|
|
fe44e01dbb | ||
|
|
bc987209f8 | ||
|
|
7c2889d93a | ||
|
|
fa46c67bd3 | ||
|
|
82679f4335 | ||
|
|
75f366f4d0 | ||
|
|
1d531f29ee | ||
|
|
f75b755f21 | ||
|
|
a2929226d2 | ||
|
|
6655694cc7 | ||
|
|
1ac4d27e22 | ||
|
|
681d02a77d | ||
|
|
14eefd58c1 | ||
|
|
2beec61a50 | ||
|
|
e1ae36210b | ||
|
|
e74eac61ae | ||
|
|
f8a5c3d8ee | ||
|
|
efd18b09ca | ||
|
|
cd062ac26e | ||
|
|
a3e47196f7 | ||
|
|
1930d972fc | ||
|
|
0c4ac78dea | ||
|
|
5771f3826a | ||
|
|
a55bc6a870 | ||
|
|
dcb311d5c9 | ||
|
|
e5935eaff9 | ||
|
|
d927f1dc02 | ||
|
|
ca1cae64d9 | ||
|
|
69df216a9c | ||
|
|
2917eb1589 | ||
|
|
ec282ff385 | ||
|
|
5d98e5e78a |
@@ -1 +1 @@
|
||||
13.2.2
|
||||
13.5.0
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
4
docs/api/structures/overlay-options.md
Normal file
4
docs/api/structures/overlay-options.md
Normal 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.
|
||||
@@ -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`.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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].
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
})
|
||||
//...
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
|
||||
69
patches/angle/cherry-pick-72473550f6ff.patch
Normal file
69
patches/angle/cherry-pick-72473550f6ff.patch
Normal 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;
|
||||
@@ -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;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
353
patches/chromium/attach_to_correct_frame_in.patch
Normal file
353
patches/chromium/attach_to_correct_frame_in.patch
Normal 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,
|
||||
115
patches/chromium/cherry-pick-1230767.patch
Normal file
115
patches/chromium/cherry-pick-1230767.patch
Normal 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>
|
||||
163
patches/chromium/cherry-pick-1231134.patch
Normal file
163
patches/chromium/cherry-pick-1231134.patch
Normal 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();
|
||||
77
patches/chromium/cherry-pick-1233564.patch
Normal file
77
patches/chromium/cherry-pick-1233564.patch
Normal 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_;
|
||||
138
patches/chromium/cherry-pick-1234009.patch
Normal file
138
patches/chromium/cherry-pick-1234009.patch
Normal 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);
|
||||
|
||||
65
patches/chromium/cherry-pick-6048fcd52f42.patch
Normal file
65
patches/chromium/cherry-pick-6048fcd52f42.patch
Normal 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>
|
||||
121
patches/chromium/cherry-pick-6215793f008f.patch
Normal file
121
patches/chromium/cherry-pick-6215793f008f.patch
Normal 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
|
||||
274
patches/chromium/cherry-pick-8623d711677d.patch
Normal file
274
patches/chromium/cherry-pick-8623d711677d.patch
Normal 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>
|
||||
85
patches/chromium/cherry-pick-d727013bb543.patch
Normal file
85
patches/chromium/cherry-pick-d727013bb543.patch
Normal 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)
|
||||
336
patches/chromium/cherry-pick-ddc4cf156505.patch
Normal file
336
patches/chromium/cherry-pick-ddc4cf156505.patch
Normal 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_
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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',
|
||||
@@ -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();
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
527
patches/chromium/merge_m92_speculative_fix_for_crash_in.patch
Normal file
527
patches/chromium/merge_m92_speculative_fix_for_crash_in.patch
Normal 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(
|
||||
@@ -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
@@ -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 ]
|
||||
|
||||
@@ -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
|
||||
|
||||
56
patches/v8/cherry-pick-034c2003be31.patch
Normal file
56
patches/v8/cherry-pick-034c2003be31.patch
Normal 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(),
|
||||
40
patches/v8/cherry-pick-1228036.patch
Normal file
40
patches/v8/cherry-pick-1228036.patch
Normal 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());
|
||||
33
patches/v8/cherry-pick-fbfd2557c2ab.patch
Normal file
33
patches/v8/cherry-pick-fbfd2557c2ab.patch
Normal 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(),
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
220
shell/browser/ui/views/win_caption_button.cc
Normal file
220
shell/browser/ui/views/win_caption_button.cc
Normal 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
|
||||
54
shell/browser/ui/views/win_caption_button.h
Normal file
54
shell/browser/ui/views/win_caption_button.h
Normal 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_
|
||||
143
shell/browser/ui/views/win_caption_button_container.cc
Normal file
143
shell/browser/ui/views/win_caption_button_container.cc
Normal 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
|
||||
70
shell/browser/ui/views/win_caption_button_container.h
Normal file
70
shell/browser/ui/views/win_caption_button_container.h
Normal 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_
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
});
|
||||
84
spec-main/fixtures/pages/overlay.html
Normal file
84
spec-main/fixtures/pages/overlay.html
Normal 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>
|
||||
@@ -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';
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
4
typings/internal-electron.d.ts
vendored
4
typings/internal-electron.d.ts
vendored
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user