mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
73 Commits
v33.0.0-al
...
v34.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45bae950d5 | ||
|
|
3c8321a987 | ||
|
|
74b54278bf | ||
|
|
dea6a4e5fb | ||
|
|
90fbf30491 | ||
|
|
5580349c3a | ||
|
|
309d5dade3 | ||
|
|
a3df950281 | ||
|
|
0cc60500ed | ||
|
|
f1019c2c4a | ||
|
|
5718ea4e1e | ||
|
|
2844e346b9 | ||
|
|
e2fe8f50e2 | ||
|
|
8c5e7bbf6b | ||
|
|
0d4d752c1b | ||
|
|
0568686340 | ||
|
|
44a4328ea8 | ||
|
|
18b1b33adc | ||
|
|
fe0d4274e2 | ||
|
|
cc5aa65cb4 | ||
|
|
25f4691e78 | ||
|
|
3fde574db1 | ||
|
|
eff862b083 | ||
|
|
32d5f9e3ef | ||
|
|
69df09dc90 | ||
|
|
6aae1264dd | ||
|
|
4b5a831979 | ||
|
|
2c3840af76 | ||
|
|
73d480d401 | ||
|
|
2d868ecb8d | ||
|
|
0467790aee | ||
|
|
8ae5aacc8c | ||
|
|
94f2722fa3 | ||
|
|
054cbcd6eb | ||
|
|
4c83016cf3 | ||
|
|
53dcda1fe9 | ||
|
|
635d421123 | ||
|
|
b42c0ae00d | ||
|
|
90ba2df4fa | ||
|
|
c41a28d7c8 | ||
|
|
41b8fdca5c | ||
|
|
38512efd25 | ||
|
|
7cea992926 | ||
|
|
2390706030 | ||
|
|
56829f75c1 | ||
|
|
5994b34a5d | ||
|
|
e6555ac5e1 | ||
|
|
5a1eeea102 | ||
|
|
7f34b0e6f5 | ||
|
|
c1eee18e41 | ||
|
|
9ce0ca74c3 | ||
|
|
3a5a1ea7bd | ||
|
|
6e4d90fcdb | ||
|
|
fd8d9f06fd | ||
|
|
ca0837c852 | ||
|
|
1aeca6fd0e | ||
|
|
b481966f02 | ||
|
|
baf0182a42 | ||
|
|
50ce448556 | ||
|
|
7391db93e2 | ||
|
|
b27dc7514e | ||
|
|
ae0c8881c3 | ||
|
|
4ae43dcb3b | ||
|
|
46bed807ca | ||
|
|
755c6640fd | ||
|
|
4fbf18a021 | ||
|
|
f366caac84 | ||
|
|
4874233aae | ||
|
|
b7af0537c8 | ||
|
|
7da9c0b2f7 | ||
|
|
46af43db49 | ||
|
|
93a6f3e607 | ||
|
|
a2de94dda1 |
6
.github/CODEOWNERS
vendored
6
.github/CODEOWNERS
vendored
@@ -20,3 +20,9 @@ appveyor-woa.yml @electron/wg-releases
|
||||
/lib/browser/guest-view-manager.ts @electron/wg-security
|
||||
/lib/browser/rpc-server.ts @electron/wg-security
|
||||
/lib/renderer/security-warnings.ts @electron/wg-security
|
||||
|
||||
# Infra WG
|
||||
/.github/actions/ @electron/wg-infra
|
||||
/.github/workflows/*-publish.yml @electron/wg-infra
|
||||
/.github/workflows/build.yml @electron/wg-infra
|
||||
/.github/workflows/pipeline-*.yml @electron/wg-infra
|
||||
|
||||
9
.github/config.yml
vendored
9
.github/config.yml
vendored
@@ -2,6 +2,8 @@
|
||||
newPRWelcomeComment: |
|
||||
💖 Thanks for opening this pull request! 💖
|
||||
|
||||
### Semantic PR titles
|
||||
|
||||
We use [semantic commit messages](https://github.com/electron/electron/blob/main/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix.
|
||||
|
||||
Examples of commit messages with semantic prefixes:
|
||||
@@ -10,6 +12,13 @@ newPRWelcomeComment: |
|
||||
- `feat: add app.isPackaged() method`
|
||||
- `docs: app.isDefaultProtocolClient is now available on Linux`
|
||||
|
||||
### Commit signing
|
||||
|
||||
This repo enforces [commit signatures](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits) for all incoming PRs.
|
||||
To sign your commits, see GitHub's documentation on [Telling Git about your signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key).
|
||||
|
||||
### PR tips
|
||||
|
||||
Things that will help get your PR across the finish line:
|
||||
|
||||
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/main/docs/development/coding-style.md).
|
||||
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
id: set-output
|
||||
run: |
|
||||
if [ -z "${{ inputs.build-image-sha }}" ]; then
|
||||
echo "build-image-sha=cf814a4d2501e8e843caea071a6b70a48e78b855" >> "$GITHUB_OUTPUT"
|
||||
echo "build-image-sha=77262e58c37631ab082482f42c33cdf68c6c394b" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "build-image-sha=${{ inputs.build-image-sha }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
6
.github/workflows/issue-commented.yml
vendored
6
.github/workflows/issue-commented.yml
vendored
@@ -9,8 +9,8 @@ permissions: {}
|
||||
|
||||
jobs:
|
||||
issue-commented:
|
||||
name: Remove blocked/need-repro on comment
|
||||
if: ${{ contains(github.event.issue.labels.*.name, 'blocked/need-repro') && !contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) && github.event.comment.user.type != 'Bot' }}
|
||||
name: Remove blocked/{need-info,need-repro} on comment
|
||||
if: ${{ (contains(github.event.issue.labels.*.name, 'blocked/need-repro') || contains(github.event.issue.labels.*.name, 'blocked/need-info ❌')) && !contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) && github.event.comment.user.type != 'Bot' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
@@ -23,4 +23,4 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
ISSUE_URL: ${{ github.event.issue.html_url }}
|
||||
run: |
|
||||
gh issue edit $ISSUE_URL --remove-label 'blocked/need-repro'
|
||||
gh issue edit $ISSUE_URL --remove-label 'blocked/need-repro','blocked/need-info ❌'
|
||||
|
||||
@@ -188,7 +188,7 @@ jobs:
|
||||
fi
|
||||
- name: Upload Test Artifacts
|
||||
if: always() && !cancelled()
|
||||
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
|
||||
with:
|
||||
name: test_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: src/electron/spec/artifacts
|
||||
|
||||
2
.github/workflows/pull-request-labeled.yml
vendored
2
.github/workflows/pull-request-labeled.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
uses: slackapi/slack-github-action@37ebaef184d7626c5f204ab8d3baff4262dd30f0 # v1.27.0
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
|
||||
4
.github/workflows/scorecards.yml
vendored
4
.github/workflows/scorecards.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -50,6 +50,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@883d8588e56d1753a8a58c1c86e88976f0c23449 # v3.26.3
|
||||
uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -36,7 +36,6 @@ TEMPLATE_CC = """
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,7 +20,11 @@ app.whenReady().then(() => {
|
||||
// Grant access to the first screen found.
|
||||
callback({ video: sources[0], audio: 'loopback' })
|
||||
})
|
||||
})
|
||||
// If true, use the system picker if available.
|
||||
// Note: this is currently experimental. If the system picker
|
||||
// is available, it will be used and the media request handler
|
||||
// will not be invoked.
|
||||
}, { useSystemPicker: true })
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
})
|
||||
|
||||
@@ -953,7 +953,7 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
|
||||
})
|
||||
```
|
||||
|
||||
#### `ses.setDisplayMediaRequestHandler(handler)`
|
||||
#### `ses.setDisplayMediaRequestHandler(handler[, opts])`
|
||||
|
||||
* `handler` Function | null
|
||||
* `request` Object
|
||||
@@ -980,12 +980,18 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
|
||||
and this is set to `true`, then local playback of audio will not be muted (e.g. using `MediaRecorder`
|
||||
to record `WebFrameMain` with this flag set to `true` will allow audio to pass through to the speakers
|
||||
while recording). Default is `false`.
|
||||
* `opts` Object (optional) _macOS_ _Experimental_
|
||||
* `useSystemPicker` Boolean - true if the available native system picker should be used. Default is `false`. _macOS_ _Experimental_
|
||||
|
||||
This handler will be called when web content requests access to display media
|
||||
via the `navigator.mediaDevices.getDisplayMedia` API. Use the
|
||||
[desktopCapturer](desktop-capturer.md) API to choose which stream(s) to grant
|
||||
access to.
|
||||
|
||||
`useSystemPicker` allows an application to use the system picker instead of providing a specific video source from `getSources`.
|
||||
This option is experimental, and currently available for MacOS 15+ only. If the system picker is available and `useSystemPicker`
|
||||
is set to `true`, the handler will not be invoked.
|
||||
|
||||
```js
|
||||
const { session, desktopCapturer } = require('electron')
|
||||
|
||||
@@ -994,7 +1000,11 @@ session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
|
||||
// Grant access to the first screen found.
|
||||
callback({ video: sources[0] })
|
||||
})
|
||||
})
|
||||
// Use the system picker if available.
|
||||
// Note: this is currently experimental. If the system picker
|
||||
// is available, it will be used and the media request handler
|
||||
// will not be invoked.
|
||||
}, { useSystemPicker: true })
|
||||
```
|
||||
|
||||
Passing a [WebFrameMain](web-frame-main.md) object as a video or audio stream
|
||||
|
||||
24
docs/api/structures/offscreen-shared-texture.md
Normal file
24
docs/api/structures/offscreen-shared-texture.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# OffscreenSharedTexture Object
|
||||
|
||||
* `textureInfo` Object - The shared texture info.
|
||||
* `widgetType` string - The widget type of the texture. Can be `popup` or `frame`.
|
||||
* `pixelFormat` string - The pixel format of the texture. Can be `rgba` or `bgra`.
|
||||
* `codedSize` [Size](size.md) - The full dimensions of the video frame.
|
||||
* `visibleRect` [Rectangle](rectangle.md) - A subsection of [0, 0, codedSize.width(), codedSize.height()]. In OSR case, it is expected to have the full section area.
|
||||
* `contentRect` [Rectangle](rectangle.md) - The region of the video frame that capturer would like to populate. In OSR case, it is the same with `dirtyRect` that needs to be painted.
|
||||
* `timestamp` number - The time in microseconds since the capture start.
|
||||
* `metadata` Object - Extra metadata. See comments in src\media\base\video_frame_metadata.h for accurate details.
|
||||
* `captureUpdateRect` [Rectangle](rectangle.md) (optional) - Updated area of frame, can be considered as the `dirty` area.
|
||||
* `regionCaptureRect` [Rectangle](rectangle.md) (optional) - May reflect the frame's contents origin if region capture is used internally.
|
||||
* `sourceSize` [Rectangle](rectangle.md) (optional) - Full size of the source frame.
|
||||
* `frameCount` number (optional) - The increasing count of captured frame. May contain gaps if frames are dropped between two consecutively received frames.
|
||||
* `sharedTextureHandle` Buffer _Windows_ _macOS_ - The handle to the shared texture.
|
||||
* `planes` Object[] _Linux_ - Each plane's info of the shared texture.
|
||||
* `stride` number - The strides and offsets in bytes to be used when accessing the buffers via a memory mapping. One per plane per entry.
|
||||
* `offset` number - The strides and offsets in bytes to be used when accessing the buffers via a memory mapping. One per plane per entry.
|
||||
* `size` number - Size in bytes of the plane. This is necessary to map the buffers.
|
||||
* `fd` number - File descriptor for the underlying memory object (usually dmabuf).
|
||||
* `modifier` string _Linux_ - The modifier is retrieved from GBM library and passed to EGL driver.
|
||||
* `release` Function - Release the resources. The `texture` cannot be directly passed to another process, users need to maintain texture lifecycles in
|
||||
main process, but it is safe to pass the `textureInfo` to another process. Only a limited number of textures can exist at the same time, so it's important
|
||||
that you call `texture.release()` as soon as you're done with the texture.
|
||||
@@ -79,10 +79,14 @@
|
||||
[browserWindow](../browser-window.md) has disabled `backgroundThrottling` then
|
||||
frames will be drawn and swapped for the whole window and other
|
||||
[webContents](../web-contents.md) displayed by it. Defaults to `true`.
|
||||
* `offscreen` boolean (optional) - Whether to enable offscreen rendering for the browser
|
||||
* `offscreen` Object | boolean (optional) - Whether to enable offscreen rendering for the browser
|
||||
window. Defaults to `false`. See the
|
||||
[offscreen rendering tutorial](../../tutorial/offscreen-rendering.md) for
|
||||
more details.
|
||||
* `useSharedTexture` boolean (optional) _Experimental_ - Whether to use GPU shared texture for accelerated
|
||||
paint event. Defaults to `false`. See the
|
||||
[offscreen rendering tutorial](../../tutorial/offscreen-rendering.md) for
|
||||
more details.
|
||||
* `contextIsolation` boolean (optional) - Whether to run Electron APIs and
|
||||
the specified `preload` script in a separate JavaScript context. Defaults
|
||||
to `true`. The context that the `preload` script runs in will only have
|
||||
|
||||
@@ -869,12 +869,12 @@ app.whenReady().then(() => {
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Event\<\>
|
||||
* `texture` [OffscreenSharedTexture](structures/offscreen-shared-texture.md) (optional) _Experimental_ - The GPU shared texture of the frame, when `webPreferences.offscreen.useSharedTexture` is `true`.
|
||||
* `dirtyRect` [Rectangle](structures/rectangle.md)
|
||||
* `image` [NativeImage](native-image.md) - The image data of the whole frame.
|
||||
|
||||
Emitted when a new frame is generated. Only the dirty area is passed in the
|
||||
buffer.
|
||||
Emitted when a new frame is generated. Only the dirty area is passed in the buffer.
|
||||
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
@@ -886,6 +886,33 @@ win.webContents.on('paint', (event, dirty, image) => {
|
||||
win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
When using shared texture (set `webPreferences.offscreen.useSharedTexture` to `true`) feature, you can pass the texture handle to external rendering pipeline without the overhead of
|
||||
copying data between CPU and GPU memory, with Chromium's hardware acceleration support. This feature is helpful for high-performance rendering scenarios.
|
||||
|
||||
Only a limited number of textures can exist at the same time, so it's important that you call `texture.release()` as soon as you're done with the texture.
|
||||
By managing the texture lifecycle by yourself, you can safely pass the `texture.textureInfo` to other processes through IPC.
|
||||
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow({ webPreferences: { offscreen: { useSharedTexture: true } } })
|
||||
win.webContents.on('paint', async (e, dirty, image) => {
|
||||
if (e.texture) {
|
||||
// By managing lifecycle yourself, you can handle the event in async handler or pass the `e.texture.textureInfo`
|
||||
// to other processes (not `e.texture`, the `e.texture.release` function is not passable through IPC).
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
// You can send the native texture handle to native code for importing into your rendering pipeline.
|
||||
// For example: https://github.com/electron/electron/tree/main/spec/fixtures/native-addon/osr-gpu
|
||||
// importTextureHandle(dirty, e.texture.textureInfo)
|
||||
|
||||
// You must call `e.texture.release()` as soon as possible, before the underlying frame pool is drained.
|
||||
e.texture.release()
|
||||
}
|
||||
})
|
||||
win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
#### Event: 'devtools-reload-page'
|
||||
|
||||
Emitted when the devtools window instructs the webContents to reload
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
## Overview
|
||||
|
||||
Offscreen rendering lets you obtain the content of a `BrowserWindow` in a
|
||||
bitmap, so it can be rendered anywhere, for example, on texture in a 3D scene.
|
||||
bitmap or a shared GPU texture, so it can be rendered anywhere, for example,
|
||||
on texture in a 3D scene.
|
||||
The offscreen rendering in Electron uses a similar approach to that of the
|
||||
[Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef)
|
||||
project.
|
||||
@@ -17,22 +18,39 @@ the dirty area is passed to the `paint` event to be more efficient.
|
||||
losses with no benefits.
|
||||
* When nothing is happening on a webpage, no frames are generated.
|
||||
* An offscreen window is always created as a
|
||||
[Frameless Window](../tutorial/window-customization.md)..
|
||||
[Frameless Window](../tutorial/window-customization.md).
|
||||
|
||||
### Rendering Modes
|
||||
|
||||
#### GPU accelerated
|
||||
|
||||
GPU accelerated rendering means that the GPU is used for composition. Because of
|
||||
that, the frame has to be copied from the GPU which requires more resources,
|
||||
thus this mode is slower than the Software output device. The benefit of this
|
||||
mode is that WebGL and 3D CSS animations are supported.
|
||||
GPU accelerated rendering means that the GPU is used for composition. The benefit
|
||||
of this mode is that WebGL and 3D CSS animations are supported. There are two
|
||||
different approaches depending on the `webPreferences.offscreen.useSharedTexture`
|
||||
setting.
|
||||
|
||||
1. Use GPU shared texture
|
||||
|
||||
Used when `webPreferences.offscreen.useSharedTexture` is set to `true`.
|
||||
|
||||
This is an advanced feature requiring a native node module to work with your own code.
|
||||
The frames are directly copied in GPU textures, thus this mode is very fast because
|
||||
there's no CPU-GPU memory copies overhead, and you can directly import the shared
|
||||
texture to your own rendering program.
|
||||
|
||||
2. Use CPU shared memory bitmap
|
||||
|
||||
Used when `webPreferences.offscreen.useSharedTexture` is set to `false` (default behavior).
|
||||
|
||||
The texture is accessible using the `NativeImage` API at the cost of performance.
|
||||
The frame has to be copied from the GPU to the CPU bitmap which requires more system
|
||||
resources, thus this mode is slower than the Software output device mode. But it supports
|
||||
GPU related functionalities.
|
||||
|
||||
#### Software output device
|
||||
|
||||
This mode uses a software output device for rendering in the CPU, so the frame
|
||||
generation is much faster. As a result, this mode is preferred over the GPU
|
||||
accelerated one.
|
||||
generation is faster than shared memory bitmap GPU accelerated mode.
|
||||
|
||||
To enable this mode, GPU acceleration has to be disabled by calling the
|
||||
[`app.disableHardwareAcceleration()`][disablehardwareacceleration] API.
|
||||
|
||||
@@ -97,7 +97,7 @@ The [Window Controls Overlay API][] is a web standard that gives web apps the ab
|
||||
customize their title bar region when installed on desktop. Electron exposes this API
|
||||
through the `BrowserWindow` constructor option `titleBarOverlay`.
|
||||
|
||||
This option only works whenever a custom `titlebarStyle` is applied on macOS or Windows.
|
||||
This option only works whenever a custom `titlebarStyle` is applied.
|
||||
When `titleBarOverlay` is enabled, the window controls become exposed in their default
|
||||
position, and DOM elements cannot use the area underneath this region.
|
||||
|
||||
@@ -107,7 +107,6 @@ Specifying `true` on either platform will result in an overlay region with defau
|
||||
system colors:
|
||||
|
||||
```js title='main.js'
|
||||
// on macOS or Windows
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
titleBarStyle: 'hidden',
|
||||
|
||||
@@ -108,6 +108,7 @@ auto_filenames = {
|
||||
"docs/api/structures/navigation-entry.md",
|
||||
"docs/api/structures/notification-action.md",
|
||||
"docs/api/structures/notification-response.md",
|
||||
"docs/api/structures/offscreen-shared-texture.md",
|
||||
"docs/api/structures/open-external-permission-request.md",
|
||||
"docs/api/structures/payment-discount.md",
|
||||
"docs/api/structures/permission-request.md",
|
||||
|
||||
@@ -270,6 +270,7 @@ filenames = {
|
||||
"shell/browser/api/electron_api_debugger.h",
|
||||
"shell/browser/api/electron_api_desktop_capturer.cc",
|
||||
"shell/browser/api/electron_api_desktop_capturer.h",
|
||||
"shell/browser/api/electron_api_desktop_capturer_mac.mm",
|
||||
"shell/browser/api/electron_api_dialog.cc",
|
||||
"shell/browser/api/electron_api_download_item.cc",
|
||||
"shell/browser/api/electron_api_download_item.h",
|
||||
@@ -469,6 +470,8 @@ filenames = {
|
||||
"shell/browser/notifications/platform_notification_service.h",
|
||||
"shell/browser/osr/osr_host_display_client.cc",
|
||||
"shell/browser/osr/osr_host_display_client.h",
|
||||
"shell/browser/osr/osr_paint_event.cc",
|
||||
"shell/browser/osr/osr_paint_event.h",
|
||||
"shell/browser/osr/osr_render_widget_host_view.cc",
|
||||
"shell/browser/osr/osr_render_widget_host_view.h",
|
||||
"shell/browser/osr/osr_video_consumer.cc",
|
||||
@@ -612,6 +615,8 @@ filenames = {
|
||||
"shell/common/gin_converters/net_converter.cc",
|
||||
"shell/common/gin_converters/net_converter.h",
|
||||
"shell/common/gin_converters/optional_converter.h",
|
||||
"shell/common/gin_converters/osr_converter.cc",
|
||||
"shell/common/gin_converters/osr_converter.h",
|
||||
"shell/common/gin_converters/serial_port_info_converter.h",
|
||||
"shell/common/gin_converters/std_converter.h",
|
||||
"shell/common/gin_converters/time_converter.cc",
|
||||
|
||||
@@ -145,6 +145,12 @@ export default class BrowserView {
|
||||
if (this.#autoHorizontalProportion || this.#autoVerticalProportion) {
|
||||
this.#webContentsView.setBounds(newViewBounds);
|
||||
}
|
||||
|
||||
// Update #lastWindowSize value after browser windows resize
|
||||
this.#lastWindowSize = {
|
||||
width: newBounds.width,
|
||||
height: newBounds.height
|
||||
};
|
||||
}
|
||||
|
||||
get webContentsView () {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BrowserWindow } from 'electron/main';
|
||||
const { createDesktopCapturer } = process._linkedBinding('electron_browser_desktop_capturer');
|
||||
const { createDesktopCapturer, isDisplayMediaSystemPickerAvailable } = process._linkedBinding('electron_browser_desktop_capturer');
|
||||
|
||||
const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b);
|
||||
|
||||
@@ -13,6 +13,8 @@ function isValid (options: Electron.SourcesOptions) {
|
||||
return Array.isArray(options?.types);
|
||||
}
|
||||
|
||||
export { isDisplayMediaSystemPickerAvailable };
|
||||
|
||||
export async function getSources (args: Electron.SourcesOptions) {
|
||||
if (!isValid(args)) throw new Error('Invalid options');
|
||||
|
||||
|
||||
@@ -1,11 +1,37 @@
|
||||
import { fetchWithSession } from '@electron/internal/browser/api/net-fetch';
|
||||
import { net } from 'electron/main';
|
||||
const { fromPartition, fromPath, Session } = process._linkedBinding('electron_browser_session');
|
||||
const { isDisplayMediaSystemPickerAvailable } = process._linkedBinding('electron_browser_desktop_capturer');
|
||||
|
||||
// Fake video source that activates the native system picker
|
||||
// This is used to get around the need for a screen/window
|
||||
// id in Chrome's desktopCapturer.
|
||||
let fakeVideoSourceId = -1;
|
||||
const systemPickerVideoSource = Object.create(null);
|
||||
Object.defineProperty(systemPickerVideoSource, 'id', {
|
||||
get () {
|
||||
return `window:${fakeVideoSourceId--}:0`;
|
||||
}
|
||||
});
|
||||
systemPickerVideoSource.name = '';
|
||||
Object.freeze(systemPickerVideoSource);
|
||||
|
||||
Session.prototype.fetch = function (input: RequestInfo, init?: RequestInit) {
|
||||
return fetchWithSession(input, init, this, net.request);
|
||||
};
|
||||
|
||||
Session.prototype.setDisplayMediaRequestHandler = function (handler, opts) {
|
||||
if (!handler) return this._setDisplayMediaRequestHandler(handler, opts);
|
||||
|
||||
this._setDisplayMediaRequestHandler(async (req, callback) => {
|
||||
if (opts && opts.useSystemPicker && isDisplayMediaSystemPickerAvailable()) {
|
||||
return callback({ video: systemPickerVideoSource });
|
||||
}
|
||||
|
||||
return handler(req, callback);
|
||||
}, opts);
|
||||
};
|
||||
|
||||
export default {
|
||||
fromPartition,
|
||||
fromPath,
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
"ts-node": "6.2.0",
|
||||
"typescript": "^5.1.2",
|
||||
"url": "^0.11.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack": "^5.94.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"wrapper-webpack-plugin": "^2.2.0"
|
||||
},
|
||||
|
||||
@@ -129,3 +129,5 @@ feat_enable_passing_exit_code_on_service_process_crash.patch
|
||||
chore_remove_reference_to_chrome_browser_themes.patch
|
||||
feat_enable_customizing_symbol_color_in_framecaptionbutton.patch
|
||||
build_expose_webplugininfo_interface_to_electron.patch
|
||||
osr_shared_texture_remove_keyed_mutex_on_win_dxgi.patch
|
||||
feat_allow_usage_of_sccontentsharingpicker_on_supported_platforms.patch
|
||||
|
||||
@@ -210,15 +210,15 @@ index c576ace24e81cc877aa2595d40e0a13a7af9f6a2..210fb97d44c19c29af424cc7b9cb3169
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
index 96d7ba915e3d4248ad801237b0b43ff0b55be1a2..24cf1a2aa6f821c4d5597d98f3bf98a10bd30555 100644
|
||||
index 96d7ba915e3d4248ad801237b0b43ff0b55be1a2..8da4acbde65e933740a53de1dc45e7c779a688fb 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
@@ -2245,6 +2245,8 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
|
||||
@@ -2246,6 +2246,8 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
WebWindowFeatures window_features =
|
||||
GetWindowFeaturesFromString(features, entered_window);
|
||||
+
|
||||
+ window_features.raw_features = features;
|
||||
|
||||
+ window_features.raw_features = features;
|
||||
+
|
||||
if (window_features.is_partitioned_popin &&
|
||||
!IsFeatureEnabled(
|
||||
mojom::blink::PermissionsPolicyFeature::kPartitionedPopins,
|
||||
|
||||
@@ -199,10 +199,21 @@ index 58985ce62dc569256bad5e94de9c0d125fc470d0..33436784b691c860d58f8b4dfcc6718e
|
||||
&SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse, this,
|
||||
parent));
|
||||
diff --git a/ui/shell_dialogs/select_file_dialog_linux_portal.cc b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||
index 61ddcbf7bf57e423099c7d392a19b3ec79b5d03f..8c3f4058ad7e9f6460c8d0516a150db612e8f574 100644
|
||||
index 61ddcbf7bf57e423099c7d392a19b3ec79b5d03f..b2d2e11f72dcca5b3791a6dd3e9e5ae930a1f701 100644
|
||||
--- a/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||
+++ b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||
@@ -221,6 +221,8 @@ void SelectFileDialogLinuxPortal::SelectFileImpl(
|
||||
@@ -44,7 +44,9 @@ constexpr char kMethodStartServiceByName[] = "StartServiceByName";
|
||||
constexpr char kXdgPortalService[] = "org.freedesktop.portal.Desktop";
|
||||
constexpr char kXdgPortalObject[] = "/org/freedesktop/portal/desktop";
|
||||
|
||||
-constexpr int kXdgPortalRequiredVersion = 3;
|
||||
+// Version 4 includes support for current_folder option to the OpenFile method via
|
||||
+// https://github.com/flatpak/xdg-desktop-portal/commit/71165a5.
|
||||
+constexpr int kXdgPortalRequiredVersion = 4;
|
||||
|
||||
constexpr char kXdgPortalRequestInterfaceName[] =
|
||||
"org.freedesktop.portal.Request";
|
||||
@@ -221,6 +223,8 @@ void SelectFileDialogLinuxPortal::SelectFileImpl(
|
||||
weak_factory_.GetWeakPtr()));
|
||||
info_->type = type;
|
||||
info_->main_task_runner = base::SequencedTaskRunner::GetCurrentDefault();
|
||||
@@ -211,7 +222,7 @@ index 61ddcbf7bf57e423099c7d392a19b3ec79b5d03f..8c3f4058ad7e9f6460c8d0516a150db6
|
||||
|
||||
if (owning_window) {
|
||||
if (auto* root = owning_window->GetRootWindow()) {
|
||||
@@ -557,7 +559,9 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
||||
@@ -557,7 +561,9 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
||||
response_handle_token);
|
||||
|
||||
if (type == SelectFileDialog::Type::SELECT_UPLOAD_FOLDER) {
|
||||
@@ -222,7 +233,7 @@ index 61ddcbf7bf57e423099c7d392a19b3ec79b5d03f..8c3f4058ad7e9f6460c8d0516a150db6
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON));
|
||||
}
|
||||
@@ -566,6 +570,8 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
||||
@@ -566,6 +572,8 @@ void SelectFileDialogLinuxPortal::DialogInfo::AppendOptions(
|
||||
type == SelectFileDialog::Type::SELECT_UPLOAD_FOLDER ||
|
||||
type == SelectFileDialog::Type::SELECT_EXISTING_FOLDER) {
|
||||
AppendBoolOption(&options_writer, kFileChooserOptionDirectory, true);
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <marshallofsound@electronjs.org>
|
||||
Date: Thu, 8 Aug 2024 08:39:10 -0700
|
||||
Subject: feat: allow usage of SCContentSharingPicker on supported platforms
|
||||
|
||||
This is implemented as a magic "window id" that instead of pulling an SCStream manually
|
||||
instead farms out to the screen picker.
|
||||
|
||||
diff --git a/content/browser/media/capture/desktop_capture_device_mac.cc b/content/browser/media/capture/desktop_capture_device_mac.cc
|
||||
index 88c56f4dfcc1f8517ef1e8b6f1d37f5ba4d0b2c7..a75493a6d4d8ce8340a2d820eff5eed4e6a95109 100644
|
||||
--- a/content/browser/media/capture/desktop_capture_device_mac.cc
|
||||
+++ b/content/browser/media/capture/desktop_capture_device_mac.cc
|
||||
@@ -28,7 +28,7 @@ class DesktopCaptureDeviceMac : public IOSurfaceCaptureDeviceBase {
|
||||
~DesktopCaptureDeviceMac() override = default;
|
||||
|
||||
// IOSurfaceCaptureDeviceBase:
|
||||
- void OnStart() override {
|
||||
+ void OnStart(std::optional<bool> use_native_picker) override {
|
||||
requested_format_ = capture_params().requested_format;
|
||||
requested_format_.pixel_format = media::PIXEL_FORMAT_NV12;
|
||||
DCHECK_GT(requested_format_.frame_size.GetArea(), 0);
|
||||
diff --git a/content/browser/media/capture/io_surface_capture_device_base_mac.cc b/content/browser/media/capture/io_surface_capture_device_base_mac.cc
|
||||
index 8a774911ce0f610b2c993976d108f840696c1d02..5ead7287e2d765d043f8b9c0229a2ee825d9f544 100644
|
||||
--- a/content/browser/media/capture/io_surface_capture_device_base_mac.cc
|
||||
+++ b/content/browser/media/capture/io_surface_capture_device_base_mac.cc
|
||||
@@ -20,7 +20,7 @@ void IOSurfaceCaptureDeviceBase::AllocateAndStart(
|
||||
client_ = std::move(client);
|
||||
capture_params_ = params;
|
||||
|
||||
- OnStart();
|
||||
+ OnStart(params.use_native_picker);
|
||||
}
|
||||
|
||||
void IOSurfaceCaptureDeviceBase::StopAndDeAllocate() {
|
||||
diff --git a/content/browser/media/capture/io_surface_capture_device_base_mac.h b/content/browser/media/capture/io_surface_capture_device_base_mac.h
|
||||
index 8ac12480f663a74dfbdcf7128a582a81b4474d25..db6802a2603e1d3c3039e49737438124bf2ee1f1 100644
|
||||
--- a/content/browser/media/capture/io_surface_capture_device_base_mac.h
|
||||
+++ b/content/browser/media/capture/io_surface_capture_device_base_mac.h
|
||||
@@ -25,7 +25,7 @@ class CONTENT_EXPORT IOSurfaceCaptureDeviceBase
|
||||
~IOSurfaceCaptureDeviceBase() override;
|
||||
|
||||
// OnStart is called by AllocateAndStart.
|
||||
- virtual void OnStart() = 0;
|
||||
+ virtual void OnStart(std::optional<bool> use_native_picker) = 0;
|
||||
|
||||
// OnStop is called by StopAndDeAllocate.
|
||||
virtual void OnStop() = 0;
|
||||
diff --git a/content/browser/media/capture/screen_capture_kit_device_mac.mm b/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||
index b6129282c6807702cf88e0a3e2ba233e41a20960..1c2d0c6dd4101fe0bac69e3018bbbedadce224cc 100644
|
||||
--- a/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||
+++ b/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||
@@ -24,24 +24,83 @@
|
||||
std::optional<gfx::Size>,
|
||||
std::optional<gfx::Rect>)>;
|
||||
using ErrorCallback = base::RepeatingClosure;
|
||||
+using CancelCallback = base::RepeatingClosure;
|
||||
+
|
||||
+API_AVAILABLE(macos(15.0))
|
||||
+@interface ScreenCaptureKitPickerHelper
|
||||
+ : NSObject <SCContentSharingPickerObserver>
|
||||
+
|
||||
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||
+ didCancelForStream:(SCStream *)stream;
|
||||
+
|
||||
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||
+ didUpdateWithFilter:(SCContentFilter *)filter
|
||||
+ forStream:(SCStream *)stream;
|
||||
+
|
||||
+- (void)contentSharingPickerStartDidFailWithError:(NSError *)error;
|
||||
+
|
||||
+@end
|
||||
+
|
||||
+@implementation ScreenCaptureKitPickerHelper {
|
||||
+ base::RepeatingCallback<void(SCContentFilter *)> _pickerCallback;
|
||||
+ ErrorCallback _errorCallback;
|
||||
+ CancelCallback _cancelCallback;
|
||||
+}
|
||||
+
|
||||
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||
+ didCancelForStream:(SCStream *)stream {
|
||||
+ // TODO: This doesn't appear to be called on Apple's side;
|
||||
+ // implement this logic
|
||||
+ _cancelCallback.Run();
|
||||
+}
|
||||
+
|
||||
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||
+ didUpdateWithFilter:(SCContentFilter *)filter
|
||||
+ forStream:(SCStream *)stream {
|
||||
+ if (stream == nil) {
|
||||
+ _pickerCallback.Run(filter);
|
||||
+ [picker removeObserver:self];
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+- (void)contentSharingPickerStartDidFailWithError:(NSError *)error {
|
||||
+ _errorCallback.Run();
|
||||
+}
|
||||
+
|
||||
+- (instancetype)initWithStreamPickCallback:(base::RepeatingCallback<void(SCContentFilter *)>)pickerCallback
|
||||
+ cancelCallback:(CancelCallback)cancelCallback
|
||||
+ errorCallback:(ErrorCallback)errorCallback {
|
||||
+ if (self = [super init]) {
|
||||
+ _pickerCallback = pickerCallback;
|
||||
+ _cancelCallback = cancelCallback;
|
||||
+ _errorCallback = errorCallback;
|
||||
+ }
|
||||
+ return self;
|
||||
+}
|
||||
+
|
||||
+@end
|
||||
|
||||
API_AVAILABLE(macos(12.3))
|
||||
@interface ScreenCaptureKitDeviceHelper
|
||||
: NSObject <SCStreamDelegate, SCStreamOutput>
|
||||
|
||||
- (instancetype)initWithSampleCallback:(SampleCallback)sampleCallback
|
||||
+ cancelCallback:(CancelCallback)cancelCallback
|
||||
errorCallback:(ErrorCallback)errorCallback;
|
||||
@end
|
||||
|
||||
@implementation ScreenCaptureKitDeviceHelper {
|
||||
SampleCallback _sampleCallback;
|
||||
+ CancelCallback _cancelCallback;
|
||||
ErrorCallback _errorCallback;
|
||||
}
|
||||
|
||||
- (instancetype)initWithSampleCallback:(SampleCallback)sampleCallback
|
||||
+ cancelCallback:(CancelCallback)cancelCallback
|
||||
errorCallback:(ErrorCallback)errorCallback {
|
||||
if (self = [super init]) {
|
||||
_sampleCallback = sampleCallback;
|
||||
+ _cancelCallback = cancelCallback;
|
||||
_errorCallback = errorCallback;
|
||||
}
|
||||
return self;
|
||||
@@ -141,7 +200,8 @@ + (SCStreamConfiguration*)streamConfigurationWithFrameSize:(gfx::Size)frameSize
|
||||
|
||||
class API_AVAILABLE(macos(12.3)) ScreenCaptureKitDeviceMac
|
||||
: public IOSurfaceCaptureDeviceBase,
|
||||
- public ScreenCaptureKitResetStreamInterface {
|
||||
+ public ScreenCaptureKitResetStreamInterface
|
||||
+ {
|
||||
public:
|
||||
explicit ScreenCaptureKitDeviceMac(const DesktopMediaID& source,
|
||||
SCContentFilter* filter)
|
||||
@@ -152,18 +212,41 @@ explicit ScreenCaptureKitDeviceMac(const DesktopMediaID& source,
|
||||
device_task_runner_,
|
||||
base::BindRepeating(&ScreenCaptureKitDeviceMac::OnStreamSample,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
+ CancelCallback cancel_callback = base::BindPostTask(
|
||||
+ device_task_runner_,
|
||||
+ base::BindRepeating(&ScreenCaptureKitDeviceMac::OnStreamError,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
ErrorCallback error_callback = base::BindPostTask(
|
||||
device_task_runner_,
|
||||
base::BindRepeating(&ScreenCaptureKitDeviceMac::OnStreamError,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
helper_ = [[ScreenCaptureKitDeviceHelper alloc]
|
||||
initWithSampleCallback:sample_callback
|
||||
+ cancelCallback:cancel_callback
|
||||
errorCallback:error_callback];
|
||||
+
|
||||
+ if (@available(macOS 15.0, *)) {
|
||||
+ auto picker_callback = base::BindPostTask(
|
||||
+ device_task_runner_,
|
||||
+ base::BindRepeating(&ScreenCaptureKitDeviceMac::OnContentFilterReady, weak_factory_.GetWeakPtr())
|
||||
+ );
|
||||
+ auto* picker_observer = [[ScreenCaptureKitPickerHelper alloc] initWithStreamPickCallback:picker_callback cancelCallback:cancel_callback errorCallback:error_callback];
|
||||
+ [[SCContentSharingPicker sharedPicker] addObserver:picker_observer];
|
||||
+ }
|
||||
}
|
||||
ScreenCaptureKitDeviceMac(const ScreenCaptureKitDeviceMac&) = delete;
|
||||
ScreenCaptureKitDeviceMac& operator=(const ScreenCaptureKitDeviceMac&) =
|
||||
delete;
|
||||
- ~ScreenCaptureKitDeviceMac() override = default;
|
||||
+ ~ScreenCaptureKitDeviceMac() override {
|
||||
+ if (@available(macOS 15.0, *)) {
|
||||
+ auto* picker = [SCContentSharingPicker sharedPicker];
|
||||
+ ScreenCaptureKitDeviceMac::active_streams_--;
|
||||
+ picker.maximumStreamCount = @(ScreenCaptureKitDeviceMac::active_streams_);
|
||||
+ if (ScreenCaptureKitDeviceMac::active_streams_ == 0 && picker.active) {
|
||||
+ picker.active = false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
void OnShareableContentCreated(SCShareableContent* content) {
|
||||
DCHECK(device_task_runner_->RunsTasksInCurrentSequence());
|
||||
@@ -232,7 +315,7 @@ void CreateStream(SCContentFilter* filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
- if (@available(macOS 14.0, *)) {
|
||||
+ if (@available(macOS 15.0, *)) {
|
||||
// Update the content size. This step is neccessary when used together
|
||||
// with SCContentSharingPicker. If the Chrome picker is used, it will
|
||||
// change to retina resolution if applicable.
|
||||
@@ -241,6 +324,9 @@ void CreateStream(SCContentFilter* filter) {
|
||||
filter.contentRect.size.height * filter.pointPixelScale);
|
||||
}
|
||||
|
||||
+ OnContentFilterReady(filter);
|
||||
+ }
|
||||
+ void OnContentFilterReady(SCContentFilter* filter) {
|
||||
gfx::RectF dest_rect_in_frame;
|
||||
actual_capture_format_ = capture_params().requested_format;
|
||||
actual_capture_format_.pixel_format = media::PIXEL_FORMAT_NV12;
|
||||
@@ -254,6 +340,7 @@ void CreateStream(SCContentFilter* filter) {
|
||||
stream_ = [[SCStream alloc] initWithFilter:filter
|
||||
configuration:config
|
||||
delegate:helper_];
|
||||
+
|
||||
{
|
||||
NSError* error = nil;
|
||||
bool add_stream_output_result =
|
||||
@@ -395,7 +482,7 @@ void OnStreamError() {
|
||||
if (fullscreen_module_) {
|
||||
fullscreen_module_->Reset();
|
||||
}
|
||||
- OnStart();
|
||||
+ OnStart(std::nullopt);
|
||||
} else {
|
||||
client()->OnError(media::VideoCaptureError::kScreenCaptureKitStreamError,
|
||||
FROM_HERE, "Stream delegate called didStopWithError");
|
||||
@@ -418,23 +505,39 @@ void OnUpdateConfigurationError() {
|
||||
}
|
||||
|
||||
// IOSurfaceCaptureDeviceBase:
|
||||
- void OnStart() override {
|
||||
+ void OnStart(std::optional<bool> use_native_picker) override {
|
||||
DCHECK(device_task_runner_->RunsTasksInCurrentSequence());
|
||||
- if (filter_) {
|
||||
- // SCContentSharingPicker is used where filter_ is set on creation.
|
||||
- CreateStream(filter_);
|
||||
- } else {
|
||||
- // Chrome picker is used.
|
||||
- auto content_callback = base::BindPostTask(
|
||||
- device_task_runner_,
|
||||
- base::BindRepeating(
|
||||
- &ScreenCaptureKitDeviceMac::OnShareableContentCreated,
|
||||
- weak_factory_.GetWeakPtr()));
|
||||
- auto handler = ^(SCShareableContent* content, NSError* error) {
|
||||
- content_callback.Run(content);
|
||||
- };
|
||||
- [SCShareableContent getShareableContentWithCompletionHandler:handler];
|
||||
+
|
||||
+ if (@available(macOS 15.0, *)) {
|
||||
+ constexpr bool DefaultUseNativePicker = true;
|
||||
+ if (use_native_picker.value_or(DefaultUseNativePicker) && source_.id < 0 && source_.window_id == 0) {
|
||||
+ auto* picker = [SCContentSharingPicker sharedPicker];
|
||||
+ ScreenCaptureKitDeviceMac::active_streams_++;
|
||||
+ picker.maximumStreamCount = @(ScreenCaptureKitDeviceMac::active_streams_);
|
||||
+ if (!picker.active) {
|
||||
+ picker.active = true;
|
||||
+ }
|
||||
+ NSMutableArray<NSNumber*>* exclude_ns_windows = [NSMutableArray array];
|
||||
+ [[[[NSApplication sharedApplication] windows] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSWindow* win, NSDictionary *bindings) {
|
||||
+ return [win sharingType] == NSWindowSharingNone;
|
||||
+ }]] enumerateObjectsUsingBlock:^(NSWindow* win, NSUInteger idx, BOOL *stop) {
|
||||
+ [exclude_ns_windows addObject:@([win windowNumber])];
|
||||
+ }];
|
||||
+ picker.defaultConfiguration.excludedWindowIDs = exclude_ns_windows;
|
||||
+ [picker present];
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ auto content_callback = base::BindPostTask(
|
||||
+ device_task_runner_,
|
||||
+ base::BindRepeating(
|
||||
+ &ScreenCaptureKitDeviceMac::OnShareableContentCreated,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
+ auto handler = ^(SCShareableContent* content, NSError* error) {
|
||||
+ content_callback.Run(content);
|
||||
+ };
|
||||
+ [SCShareableContent getShareableContentWithCompletionHandler:handler];
|
||||
}
|
||||
void OnStop() override {
|
||||
DCHECK(device_task_runner_->RunsTasksInCurrentSequence());
|
||||
@@ -492,6 +595,8 @@ void ResetStreamTo(SCWindow* window) override {
|
||||
}
|
||||
|
||||
private:
|
||||
+ static int active_streams_;
|
||||
+
|
||||
const DesktopMediaID source_;
|
||||
SCContentFilter* const filter_;
|
||||
const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
|
||||
@@ -521,6 +626,8 @@ void ResetStreamTo(SCWindow* window) override {
|
||||
base::WeakPtrFactory<ScreenCaptureKitDeviceMac> weak_factory_{this};
|
||||
};
|
||||
|
||||
+int ScreenCaptureKitDeviceMac::active_streams_ = 0;
|
||||
+
|
||||
} // namespace
|
||||
|
||||
// Although ScreenCaptureKit is available in 12.3 there were some bugs that
|
||||
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
|
||||
index 7adf8264cfa9980c4a8414bf0f8bfa9ad70ec0b3..d162612dc70a2b57190aaf558aca8f46cbdedcad 100644
|
||||
--- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
|
||||
+++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
|
||||
@@ -360,13 +360,15 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
|
||||
std::move(after_start_capture_callback));
|
||||
break;
|
||||
#else
|
||||
+ media::VideoCaptureParams updated_params = params;
|
||||
+ updated_params.use_native_picker = stream_type != blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE;
|
||||
// All cases other than tab capture or Aura desktop/window capture.
|
||||
TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
|
||||
"UsingDesktopCapturer", TRACE_EVENT_SCOPE_THREAD);
|
||||
start_capture_closure = base::BindOnce(
|
||||
&InProcessVideoCaptureDeviceLauncher::
|
||||
DoStartDesktopCaptureOnDeviceThread,
|
||||
- base::Unretained(this), desktop_id, params,
|
||||
+ base::Unretained(this), desktop_id, updated_params,
|
||||
CreateDeviceClient(media::VideoCaptureBufferType::kSharedMemory,
|
||||
kMaxNumberOfBuffers, std::move(receiver),
|
||||
std::move(receiver_on_io_thread)),
|
||||
diff --git a/media/capture/video_capture_types.h b/media/capture/video_capture_types.h
|
||||
index f2b75f5b2f547ad135c1288bf3639b26dedc8053..ef18724d9f2ea68a47b66fc3981f58a73ac1b51d 100644
|
||||
--- a/media/capture/video_capture_types.h
|
||||
+++ b/media/capture/video_capture_types.h
|
||||
@@ -355,6 +355,8 @@ struct CAPTURE_EXPORT VideoCaptureParams {
|
||||
// Flag indicating whether HiDPI mode should be enabled for tab capture
|
||||
// sessions.
|
||||
bool is_high_dpi_enabled = true;
|
||||
+
|
||||
+ std::optional<bool> use_native_picker;
|
||||
};
|
||||
|
||||
CAPTURE_EXPORT std::ostream& operator<<(
|
||||
@@ -0,0 +1,97 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: reito <cnschwarzer@qq.com>
|
||||
Date: Thu, 15 Aug 2024 14:05:52 +0800
|
||||
Subject: Remove DXGI GMB keyed-mutex
|
||||
|
||||
This patch removes the keyed mutex of the d3d11 texture only when the texture is requested by offscreen rendering and on Windows.
|
||||
|
||||
The keyed mutex introduce extra performance cost and spikes. However, at offscreen rendering scenario, the shared resources will not be simultaneously read from & written to, typically just one reader, so it doesn't need such exclusive guarantee, and it's safe to remove this mutex for extra performance gain.
|
||||
|
||||
For resolving complex conflict please pin @reitowo
|
||||
For more reason please see: https://crrev.com/c/5465148
|
||||
|
||||
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc
|
||||
index 2096591596a26464ab8f71a399ccb16a04edfd59..9eb966b3ddc3551d6beeff123071b2c99a576620 100644
|
||||
--- a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc
|
||||
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc
|
||||
@@ -179,7 +179,8 @@ gfx::GpuMemoryBufferHandle GpuMemoryBufferFactoryDXGI::CreateGpuMemoryBuffer(
|
||||
// so make sure that the usage is one that we support.
|
||||
DCHECK(usage == gfx::BufferUsage::GPU_READ ||
|
||||
usage == gfx::BufferUsage::SCANOUT ||
|
||||
- usage == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE)
|
||||
+ usage == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE ||
|
||||
+ usage == gfx::BufferUsage::SCANOUT_VEA_CPU_READ)
|
||||
<< "Incorrect usage, usage=" << gfx::BufferUsageToString(usage);
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc = {
|
||||
@@ -193,7 +194,9 @@ gfx::GpuMemoryBufferHandle GpuMemoryBufferFactoryDXGI::CreateGpuMemoryBuffer(
|
||||
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,
|
||||
0,
|
||||
D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
|
||||
- D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX};
|
||||
+ static_cast<UINT>(usage == gfx::BufferUsage::SCANOUT_VEA_CPU_READ
|
||||
+ ? D3D11_RESOURCE_MISC_SHARED
|
||||
+ : D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)};
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
|
||||
|
||||
diff --git a/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc b/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc
|
||||
index 208d048ee68fd92d1fa7b5e8ad79e02e29b8be40..c8c8c32cd44a96dc6a476b8bc02bb13b02f86300 100644
|
||||
--- a/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc
|
||||
+++ b/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc
|
||||
@@ -205,7 +205,7 @@ gfx::Size GetBufferSizeInPixelsForVideoPixelFormat(
|
||||
bool FrameResources::Initialize() {
|
||||
auto* context = pool_->GetContext();
|
||||
|
||||
- constexpr gfx::BufferUsage kBufferUsage =
|
||||
+ gfx::BufferUsage buffer_usage =
|
||||
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
|
||||
gfx::BufferUsage::SCANOUT_VEA_CPU_READ
|
||||
#else
|
||||
@@ -219,6 +219,23 @@ bool FrameResources::Initialize() {
|
||||
const gfx::Size buffer_size_in_pixels =
|
||||
GetBufferSizeInPixelsForVideoPixelFormat(format_, coded_size_);
|
||||
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+ // For CEF OSR feature, currently there's no other place in chromium use RGBA.
|
||||
+ // If the format is RGBA, currently CEF do not write to the texture anymore
|
||||
+ // once the GMB is returned from CopyRequest. So there will be no race
|
||||
+ // condition on that texture. We can request a GMB without a keyed mutex to
|
||||
+ // accelerate and probably prevent some driver deadlock.
|
||||
+ if (format_ == PIXEL_FORMAT_ARGB || format_ == PIXEL_FORMAT_ABGR) {
|
||||
+ // This value is 'borrowed', SCANOUT_VEA_CPU_READ is probably invalid
|
||||
+ // cause there's no real SCANOUT on Windows. We simply use this enum as a
|
||||
+ // flag to disable mutex in the GMBFactoryDXGI because this enum is also
|
||||
+ // used above in macOS and CrOS for similar usage (claim no other one will
|
||||
+ // concurrently use the resource).
|
||||
+ // https://chromium-review.googlesource.com/c/chromium/src/+/5302103
|
||||
+ buffer_usage = gfx::BufferUsage::SCANOUT_VEA_CPU_READ;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
// Create the GpuMemoryBuffer if MappableSharedImages is not enabled. When its
|
||||
// enabled, clients only create a mappable shared image directly without
|
||||
// needing to create a GMB.
|
||||
@@ -226,11 +243,11 @@ bool FrameResources::Initialize() {
|
||||
kUseMappableSIForRenderableGpuMemoryBufferVideoFramePool);
|
||||
if (!is_mappable_si_enabled) {
|
||||
gpu_memory_buffer_ = context->CreateGpuMemoryBuffer(
|
||||
- buffer_size_in_pixels, buffer_format, kBufferUsage);
|
||||
+ buffer_size_in_pixels, buffer_format, buffer_usage);
|
||||
if (!gpu_memory_buffer_) {
|
||||
LOG(ERROR) << "Failed to allocate GpuMemoryBuffer for frame: coded_size="
|
||||
<< coded_size_.ToString()
|
||||
- << ", usage=" << static_cast<int>(kBufferUsage);
|
||||
+ << ", usage=" << static_cast<int>(buffer_usage);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -264,7 +281,7 @@ bool FrameResources::Initialize() {
|
||||
|
||||
if (is_mappable_si_enabled) {
|
||||
shared_image_ = context->CreateSharedImage(
|
||||
- buffer_size_in_pixels, kBufferUsage, si_format, color_space_,
|
||||
+ buffer_size_in_pixels, buffer_usage, si_format, color_space_,
|
||||
kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, kSharedImageUsage,
|
||||
sync_token_);
|
||||
} else {
|
||||
@@ -50,5 +50,6 @@ src_do_not_use_soon-to-be-deprecated_v8_api.patch
|
||||
fix_add_property_query_interceptors.patch
|
||||
src_account_for_openssl_unexpected_version.patch
|
||||
src_stop_using_deprecated_fields_of_fastapicallbackoptions.patch
|
||||
build_don_t_redefine_win32_lean_and_mean.patch
|
||||
src_use_supported_api_to_get_stalled_tla_messages.patch
|
||||
build_don_t_redefine_win32_lean_and_mean.patch
|
||||
build_compile_with_c_20_support.patch
|
||||
|
||||
42
patches/node/build_compile_with_c_20_support.patch
Normal file
42
patches/node/build_compile_with_c_20_support.patch
Normal file
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Wed, 4 Sep 2024 16:39:23 +0200
|
||||
Subject: build: compile with C++20 support
|
||||
|
||||
Refs https://github.com/nodejs/node/pull/45427
|
||||
|
||||
V8 requires C++20 support as of https://chromium-review.googlesource.com/c/v8/v8/+/5587859.
|
||||
|
||||
This can be removed when Electron upgrades to a version of Node.js containing the required V8 version.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 8736ad12eec294070a5160a64248044cd16347c9..216200c279c599f6dee228120ff5f3943fa52ffd 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -307,7 +307,7 @@
|
||||
'VCCLCompilerTool': {
|
||||
'AdditionalOptions': [
|
||||
'/Zc:__cplusplus',
|
||||
- '-std:c++17'
|
||||
+ '-std:c++20'
|
||||
],
|
||||
'BufferSecurityCheck': 'true',
|
||||
'DebugInformationFormat': 1, # /Z7 embed info in .obj files
|
||||
@@ -489,7 +489,7 @@
|
||||
}],
|
||||
[ 'OS in "linux freebsd openbsd solaris android aix os400 cloudabi"', {
|
||||
'cflags': [ '-Wall', '-Wextra', '-Wno-unused-parameter', ],
|
||||
- 'cflags_cc': [ '-fno-rtti', '-fno-exceptions', '-std=gnu++17' ],
|
||||
+ 'cflags_cc': [ '-fno-rtti', '-fno-exceptions', '-std=gnu++20' ],
|
||||
'defines': [ '__STDC_FORMAT_MACROS' ],
|
||||
'ldflags': [ '-rdynamic' ],
|
||||
'target_conditions': [
|
||||
@@ -660,7 +660,7 @@
|
||||
['clang==1', {
|
||||
'xcode_settings': {
|
||||
'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
|
||||
- 'CLANG_CXX_LANGUAGE_STANDARD': 'gnu++17', # -std=gnu++17
|
||||
+ 'CLANG_CXX_LANGUAGE_STANDARD': 'gnu++20', # -std=gnu++20
|
||||
'CLANG_CXX_LIBRARY': 'libc++',
|
||||
},
|
||||
}],
|
||||
@@ -1,3 +1,2 @@
|
||||
chore_allow_customizing_microtask_policy_per_context.patch
|
||||
deps_add_v8_object_setinternalfieldfornodecore.patch
|
||||
fix_disable_scope_reuse_associated_dchecks.patch
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Calvin Watford <cwatford@slack-corp.com>
|
||||
Date: Wed, 17 Jul 2024 12:52:10 -0600
|
||||
Subject: fix: disable scope reuse & associated dchecks
|
||||
|
||||
This change was introduced in https://crrev.com/c/5630974 which reuses
|
||||
scope info objects across allocations. Unfortunately, this change seems
|
||||
to be not yet fully cooked and causes crashes with normal usage of V8.
|
||||
|
||||
In particular, Node.js call's V8's `v8::ScriptCompiler::CompileFunction`
|
||||
method. This ends up wrapping the source code in a function, which this
|
||||
code is not yet prepared to handle. The generated function wrapper
|
||||
(created by V8) has no source position, so it reports being at the start
|
||||
of the source, which may overlap with other scopes that are in the
|
||||
original source. This new feature adds a "UniqueIdInScript" concept that
|
||||
is derived from the source position of a scope, along with the invariant
|
||||
that inner scopes have a higher ID than outer scopes, which does not
|
||||
hold for the above situation.
|
||||
|
||||
This patch is not intended to remain indefinitely. Once the upstream
|
||||
feature stabilizes, we can remove this patch. Unfortunately, there is no
|
||||
public tracking bug for this feature nor the crashes its been causing,
|
||||
so we'll have to keep an eye on this for the time being.
|
||||
|
||||
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
|
||||
index 57a9dca1a84dee95d36c2b296fc170399db3e213..5db78a650068faa0bacf05b13d86860c9616e20e 100644
|
||||
--- a/src/ast/scopes.cc
|
||||
+++ b/src/ast/scopes.cc
|
||||
@@ -2731,10 +2731,10 @@ void Scope::AllocateScopeInfosRecursively(
|
||||
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
|
||||
#ifdef DEBUG
|
||||
if (!scope->is_hidden_catch_scope()) {
|
||||
- DCHECK_GT(scope->UniqueIdInScript(), UniqueIdInScript());
|
||||
- DCHECK_IMPLIES(
|
||||
- scope->sibling_ && !scope->sibling_->is_hidden_catch_scope(),
|
||||
- scope->sibling_->UniqueIdInScript() != scope->UniqueIdInScript());
|
||||
+ // DCHECK_GT(scope->UniqueIdInScript(), UniqueIdInScript());
|
||||
+ // DCHECK_IMPLIES(
|
||||
+ // scope->sibling_ && !scope->sibling_->is_hidden_catch_scope(),
|
||||
+ // scope->sibling_->UniqueIdInScript() != scope->UniqueIdInScript());
|
||||
}
|
||||
#endif
|
||||
if (!scope->is_function_scope() ||
|
||||
diff --git a/src/flags/flag-definitions.h b/src/flags/flag-definitions.h
|
||||
index 670cb9f3658737acd953a4dcbb502c407a79212b..42765a8069d62df908ada15b3b89b7d8476744bb 100644
|
||||
--- a/src/flags/flag-definitions.h
|
||||
+++ b/src/flags/flag-definitions.h
|
||||
@@ -964,7 +964,12 @@ DEFINE_BOOL(trace_track_allocation_sites, false,
|
||||
DEFINE_BOOL(trace_migration, false, "trace object migration")
|
||||
DEFINE_BOOL(trace_generalization, false, "trace map generalization")
|
||||
|
||||
-DEFINE_BOOL(reuse_scope_infos, true, "reuse scope infos from previous compiles")
|
||||
+// ELECTRON: The following flag should remain false by default until we can
|
||||
+// remove `fix_disable_scope_reuse_associated_dchecks.patch`
|
||||
+DEFINE_BOOL(reuse_scope_infos, false,
|
||||
+ "reuse scope infos from previous compiles")
|
||||
+
|
||||
+DEFINE_IMPLICATION(fuzzing, reuse_scope_infos)
|
||||
|
||||
// Flags for Sparkplug
|
||||
#undef FLAG
|
||||
@@ -186,13 +186,9 @@ async function runMainProcessElectronTests () {
|
||||
}
|
||||
|
||||
async function installSpecModules (dir) {
|
||||
// v8 headers use c++17 so override the gyp default of -std=c++14,
|
||||
// but don't clobber any other CXXFLAGS that were passed into spec-runner.js
|
||||
const CXXFLAGS = ['-std=c++17', process.env.CXXFLAGS].filter(x => !!x).join(' ');
|
||||
|
||||
const env = {
|
||||
...process.env,
|
||||
CXXFLAGS,
|
||||
CXXFLAGS: process.env.CXXFLAGS,
|
||||
npm_config_msvs_version: '2019',
|
||||
npm_config_yes: 'true'
|
||||
};
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"bullseye_amd64": {
|
||||
"Key": "20230329T085712Z-1",
|
||||
"Sha256Sum": "6a468814ee3200152b9ccda8876ac86cd9d28b442fe30a59356a22296277d3a1",
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "7c93e71bf9c4cd0825aa59fb2479054d981e36ba9be34ecf4c1d73051cae40fe",
|
||||
"SysrootDir": "debian_bullseye_amd64-sysroot",
|
||||
"Tarball": "debian_bullseye_amd64_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_arm64": {
|
||||
"Key": "20230329T085712Z-1",
|
||||
"Sha256Sum": "af4575c58e4d4222a3634db24bc6c1d158dd456f9c0ad551c2e019324e7091ff",
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "d649177e37aef2c043e54e670e42934f18558c0e730c1b854719ca7463e2b1eb",
|
||||
"SysrootDir": "debian_bullseye_arm64-sysroot",
|
||||
"Tarball": "debian_bullseye_arm64_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
@@ -21,29 +21,29 @@
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_armhf": {
|
||||
"Key": "20230329T085712Z-1",
|
||||
"Sha256Sum": "f04411e56cc721ac5de94eb2cbc7f3845ff60f286f18b97b30ae03a583465cc3",
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "fe3b9203e30e70f533776d565501bc1e3d4ebf6eeb909b2c2bfca0df807e1be0",
|
||||
"SysrootDir": "debian_bullseye_armhf-sysroot",
|
||||
"Tarball": "debian_bullseye_armhf_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_i386": {
|
||||
"Key": "20230329T085712Z-1",
|
||||
"Sha256Sum": "6cc59a7b46a08af691cd692bd9fa48ddc0dbee4ec94dea09b0ea043aee024b96",
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "4efcb1870129da1ad5c3b634903a4efcc0ca9abd67dd5a993cca144ea9b5d31f",
|
||||
"SysrootDir": "debian_bullseye_i386-sysroot",
|
||||
"Tarball": "debian_bullseye_i386_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_mips64el": {
|
||||
"Key": "20230329T085712Z-1",
|
||||
"Sha256Sum": "c4ac483a88e74b8dc58ff39687478502f18fb1b356d6b8fc86d684ec1a82e670",
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "c3a3bf3b0aa40ec90747c951942d40077ff6796b336818eaba6fa21564249a00",
|
||||
"SysrootDir": "debian_bullseye_mips64el-sysroot",
|
||||
"Tarball": "debian_bullseye_mips64el_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_mipsel": {
|
||||
"Key": "20230329T085712Z-1",
|
||||
"Sha256Sum": "561adb4d26d2cca7589fe0ae6fa75ae9b811baf77a8a641b19ae11aa4948ed58",
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "564de884ed1810e1cf3a20d94edfa21972ac2be9568bf1526d093c31f15ef225",
|
||||
"SysrootDir": "debian_bullseye_mipsel-sysroot",
|
||||
"Tarball": "debian_bullseye_mipsel_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <utility>
|
||||
|
||||
#include "base/at_exit.h"
|
||||
#include "base/base_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
#include "content/public/app/content_main.h"
|
||||
|
||||
@@ -98,8 +98,8 @@ BaseWindow::BaseWindow(v8::Isolate* isolate,
|
||||
}
|
||||
|
||||
// Creates NativeWindow.
|
||||
window_.reset(NativeWindow::Create(
|
||||
options, parent.IsEmpty() ? nullptr : parent->window_.get()));
|
||||
window_ = NativeWindow::Create(
|
||||
options, parent.IsEmpty() ? nullptr : parent->window_.get());
|
||||
window_->AddObserver(this);
|
||||
|
||||
SetContentView(View::Create(isolate));
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
@@ -39,7 +38,6 @@
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
#include "base/containers/span.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/uuid.h"
|
||||
#include "components/crash/core/common/crash_keys.h"
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include "shell/browser/api/electron_api_debugger.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <string_view>
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "chrome/browser/media/webrtc/desktop_capturer_wrapper.h"
|
||||
@@ -43,6 +42,7 @@
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "ui/base/cocoa/permissions_utils.h"
|
||||
#endif
|
||||
|
||||
@@ -503,6 +503,13 @@ gin::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
#if !BUILDFLAG(IS_MAC)
|
||||
bool DesktopCapturer::IsDisplayMediaSystemPickerAvailable() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
gin::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return gin::Wrappable<DesktopCapturer>::GetObjectTemplateBuilder(isolate)
|
||||
@@ -524,6 +531,9 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
gin_helper::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("createDesktopCapturer",
|
||||
&electron::api::DesktopCapturer::Create);
|
||||
dict.SetMethod(
|
||||
"isDisplayMediaSystemPickerAvailable",
|
||||
&electron::api::DesktopCapturer::IsDisplayMediaSystemPickerAvailable);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -36,6 +36,8 @@ class DesktopCapturer final : public gin::Wrappable<DesktopCapturer>,
|
||||
|
||||
static gin::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||
|
||||
static bool IsDisplayMediaSystemPickerAvailable();
|
||||
|
||||
void StartHandling(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size,
|
||||
|
||||
17
shell/browser/api/electron_api_desktop_capturer_mac.mm
Normal file
17
shell/browser/api/electron_api_desktop_capturer_mac.mm
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2024 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/api/electron_api_desktop_capturer.h"
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
// static
|
||||
bool DesktopCapturer::IsDisplayMediaSystemPickerAvailable() {
|
||||
if (@available(macOS 15.0, *)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "content/public/browser/console_message.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
|
||||
@@ -261,7 +261,7 @@ class ClearDataTask {
|
||||
}
|
||||
|
||||
private:
|
||||
// An individiual |content::BrowsingDataRemover::Remove...| operation as part
|
||||
// An individual |content::BrowsingDataRemover::Remove...| operation as part
|
||||
// of a full |ClearDataTask|. This class manages its own lifetime, cleaning
|
||||
// itself up after the operation completes and notifies the task of the
|
||||
// result.
|
||||
@@ -1607,7 +1607,7 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
|
||||
&Session::SetPermissionRequestHandler)
|
||||
.SetMethod("setPermissionCheckHandler",
|
||||
&Session::SetPermissionCheckHandler)
|
||||
.SetMethod("setDisplayMediaRequestHandler",
|
||||
.SetMethod("_setDisplayMediaRequestHandler",
|
||||
&Session::SetDisplayMediaRequestHandler)
|
||||
.SetMethod("setDevicePermissionHandler",
|
||||
&Session::SetDevicePermissionHandler)
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
#include "shell/common/gin_converters/image_converter.h"
|
||||
#include "shell/common/gin_converters/net_converter.h"
|
||||
#include "shell/common/gin_converters/optional_converter.h"
|
||||
#include "shell/common/gin_converters/osr_converter.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/error_thrower.h"
|
||||
@@ -760,9 +761,23 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
// Get transparent for guest view
|
||||
options.Get("transparent", &guest_transparent_);
|
||||
|
||||
bool b = false;
|
||||
if (options.Get(options::kOffscreen, &b) && b)
|
||||
type_ = Type::kOffScreen;
|
||||
// Offscreen rendering
|
||||
v8::Local<v8::Value> use_offscreen;
|
||||
if (options.Get(options::kOffscreen, &use_offscreen)) {
|
||||
if (use_offscreen->IsBoolean()) {
|
||||
bool b = false;
|
||||
if (options.Get(options::kOffscreen, &b) && b) {
|
||||
type_ = Type::kOffScreen;
|
||||
}
|
||||
} else if (use_offscreen->IsObject()) {
|
||||
type_ = Type::kOffScreen;
|
||||
auto use_offscreen_dict =
|
||||
gin_helper::Dictionary::CreateEmpty(options.isolate());
|
||||
options.Get(options::kOffscreen, &use_offscreen_dict);
|
||||
use_offscreen_dict.Get(options::kUseSharedTexture,
|
||||
&offscreen_use_shared_texture_);
|
||||
}
|
||||
}
|
||||
|
||||
// Init embedder earlier
|
||||
options.Get("embedder", &embedder_);
|
||||
@@ -798,7 +813,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
|
||||
if (embedder_ && embedder_->IsOffScreen()) {
|
||||
auto* view = new OffScreenWebContentsView(
|
||||
false,
|
||||
false, offscreen_use_shared_texture_,
|
||||
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
|
||||
params.view = view;
|
||||
params.delegate_view = view;
|
||||
@@ -818,7 +833,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
|
||||
content::WebContents::CreateParams params(session->browser_context());
|
||||
auto* view = new OffScreenWebContentsView(
|
||||
transparent,
|
||||
transparent, offscreen_use_shared_texture_,
|
||||
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
|
||||
params.view = view;
|
||||
params.delegate_view = view;
|
||||
@@ -3535,8 +3550,23 @@ bool WebContents::IsOffScreen() const {
|
||||
return type_ == Type::kOffScreen;
|
||||
}
|
||||
|
||||
void WebContents::OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap) {
|
||||
Emit("paint", dirty_rect, gfx::Image::CreateFrom1xBitmap(bitmap));
|
||||
void WebContents::OnPaint(const gfx::Rect& dirty_rect,
|
||||
const SkBitmap& bitmap,
|
||||
const OffscreenSharedTexture& tex) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
gin::Handle<gin_helper::internal::Event> event =
|
||||
gin_helper::internal::Event::New(isolate);
|
||||
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>();
|
||||
gin_helper::Dictionary dict(isolate, event_object);
|
||||
|
||||
if (offscreen_use_shared_texture_) {
|
||||
dict.Set("texture", tex);
|
||||
}
|
||||
|
||||
EmitWithoutEvent("paint", event, dirty_rect,
|
||||
gfx::Image::CreateFrom1xBitmap(bitmap));
|
||||
}
|
||||
|
||||
void WebContents::StartPainting() {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "shell/browser/background_throttling_source.h"
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/browser/extended_web_contents_observer.h"
|
||||
#include "shell/browser/osr/osr_paint_event.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
|
||||
#include "shell/common/gin_helper/cleaned_up_at_exit.h"
|
||||
@@ -310,7 +311,9 @@ class WebContents final : public ExclusiveAccessContext,
|
||||
|
||||
// Methods for offscreen rendering
|
||||
bool IsOffScreen() const;
|
||||
void OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap);
|
||||
void OnPaint(const gfx::Rect& dirty_rect,
|
||||
const SkBitmap& bitmap,
|
||||
const OffscreenSharedTexture& info);
|
||||
void StartPainting();
|
||||
void StopPainting();
|
||||
bool IsPainting() const;
|
||||
@@ -842,6 +845,9 @@ class WebContents final : public ExclusiveAccessContext,
|
||||
|
||||
bool offscreen_ = false;
|
||||
|
||||
// Whether offscreen rendering use gpu shared texture
|
||||
bool offscreen_use_shared_texture_ = false;
|
||||
|
||||
// Whether window is fullscreened by HTML5 api.
|
||||
bool html_fullscreen_ = false;
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "gin/dictionary.h"
|
||||
#include "gin/handle.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "net/http/http_content_disposition.h"
|
||||
#include "shell/browser/api/electron_api_session.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/api/electron_api_web_frame_main.h"
|
||||
@@ -100,22 +99,6 @@ v8::Local<v8::Value> HttpResponseHeadersToV8(
|
||||
std::string key;
|
||||
std::string value;
|
||||
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
||||
// Note that Web servers not developed with nodejs allow non-utf8
|
||||
// characters in content-disposition's filename field. Use Chromium's
|
||||
// HttpContentDisposition class to decode the correct encoding instead of
|
||||
// arbitrarily converting it to UTF8. It should also be noted that if the
|
||||
// encoding is not specified, HttpContentDisposition will transcode
|
||||
// according to the system's encoding.
|
||||
if (base::EqualsCaseInsensitiveASCII("Content-Disposition", key) &&
|
||||
!value.empty()) {
|
||||
net::HttpContentDisposition header(value, std::string());
|
||||
std::string decodedFilename =
|
||||
header.is_attachment() ? " attachment" : " inline";
|
||||
// The filename must be encased in double quotes for serialization
|
||||
// to happen correctly.
|
||||
std::string filename = "\"" + header.filename() + "\"";
|
||||
value = decodedFilename + "; filename=" + filename;
|
||||
}
|
||||
response_headers.EnsureList(key)->Append(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/containers/to_vector.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "gin/arguments.h"
|
||||
#include "gin/data_object_builder.h"
|
||||
@@ -30,12 +29,12 @@ namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsValidWrappable(const v8::Local<v8::Value>& obj) {
|
||||
v8::Local<v8::Object> port = v8::Local<v8::Object>::Cast(obj);
|
||||
|
||||
if (!port->IsObject())
|
||||
bool IsValidWrappable(const v8::Local<v8::Value>& val) {
|
||||
if (!val->IsObject())
|
||||
return false;
|
||||
|
||||
v8::Local<v8::Object> port = val.As<v8::Object>();
|
||||
|
||||
if (port->InternalFieldCount() != gin::kNumberOfInternalFields)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "shell/browser/badging/badge_manager_factory.h"
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
||||
#include "shell/browser/badging/badge_manager.h"
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "content/public/browser/navigation_handle.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "base/path_service.h"
|
||||
#include "base/process/process_metrics.h"
|
||||
#include "base/strings/escape.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#include "shell/browser/electron_download_manager_delegate.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <string_view>
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
|
||||
@@ -4,8 +4,14 @@
|
||||
|
||||
#include "shell/browser/electron_pdf_document_helper_client.h"
|
||||
|
||||
#include "chrome/browser/pdf/pdf_viewer_stream_manager.h"
|
||||
#include "chrome/common/content_restriction.h"
|
||||
#include "components/pdf/browser/pdf_frame_util.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
|
||||
#include "pdf/content_restriction.h"
|
||||
#include "pdf/pdf_features.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
|
||||
ElectronPDFDocumentHelperClient::ElectronPDFDocumentHelperClient() = default;
|
||||
@@ -15,8 +21,8 @@ void ElectronPDFDocumentHelperClient::UpdateContentRestrictions(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
int content_restrictions) {
|
||||
// UpdateContentRestrictions potentially gets called twice from
|
||||
// pdf/pdf_view_web_plugin.cc. The first time it is potentially called is
|
||||
// when loading starts and it is called with a restriction on printing. The
|
||||
// pdf/pdf_view_web_plugin.cc. The first time it is potentially called is
|
||||
// when loading starts and it is called with a restriction on printing. The
|
||||
// second time it is called is when loading is finished and if printing is
|
||||
// allowed there won't be a printing restriction passed, so we can use this
|
||||
// second call to notify that the pdf document is ready to print.
|
||||
@@ -31,3 +37,29 @@ void ElectronPDFDocumentHelperClient::UpdateContentRestrictions(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ElectronPDFDocumentHelperClient::SetPluginCanSave(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
bool can_save) {
|
||||
if (chrome_pdf::features::IsOopifPdfEnabled()) {
|
||||
auto* pdf_viewer_stream_manager =
|
||||
pdf::PdfViewerStreamManager::FromWebContents(
|
||||
content::WebContents::FromRenderFrameHost(render_frame_host));
|
||||
if (!pdf_viewer_stream_manager) {
|
||||
return;
|
||||
}
|
||||
|
||||
content::RenderFrameHost* embedder_host =
|
||||
pdf_frame_util::GetEmbedderHost(render_frame_host);
|
||||
CHECK(embedder_host);
|
||||
|
||||
pdf_viewer_stream_manager->SetPluginCanSave(embedder_host, can_save);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* guest_view =
|
||||
extensions::MimeHandlerViewGuest::FromRenderFrameHost(render_frame_host);
|
||||
if (guest_view) {
|
||||
guest_view->SetPluginCanSave(can_save);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,12 @@ class ElectronPDFDocumentHelperClient : public pdf::PDFDocumentHelperClient {
|
||||
|
||||
private:
|
||||
// pdf::PDFDocumentHelperClient
|
||||
|
||||
void UpdateContentRestrictions(content::RenderFrameHost* render_frame_host,
|
||||
int content_restrictions) override;
|
||||
void OnPDFHasUnsupportedFeature(content::WebContents* contents) override {}
|
||||
void OnSaveURL(content::WebContents* contents) override {}
|
||||
void SetPluginCanSave(content::RenderFrameHost* render_frame_host,
|
||||
bool can_save) override {}
|
||||
bool can_save) override;
|
||||
};
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_ELECTRON_PDF_DOCUMENT_HELPER_CLIENT_H_
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "extensions/browser/event_router.h"
|
||||
#include "extensions/browser/extension_prefs.h"
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/common/extensions/extension_metrics.h"
|
||||
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
|
||||
#include "chrome/common/webui_url_constants.h"
|
||||
|
||||
@@ -519,7 +519,7 @@ api::scripting::RegisteredContentScript CreateRegisteredContentScriptInfo(
|
||||
converted.reserve(sources.size());
|
||||
for (auto& source : sources) {
|
||||
CHECK(source.file)
|
||||
<< "Content scripts don't allow arbtirary code strings";
|
||||
<< "Content scripts don't allow arbitrary code strings";
|
||||
converted.push_back(std::move(*source.file));
|
||||
}
|
||||
return converted;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "extensions/browser/media_capture_util.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <utility>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/json/json_string_value_serializer.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/values.h"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "shell/browser/extensions/electron_process_manager_delegate.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/one_shot_event.h"
|
||||
#include "extensions/browser/extension_system.h"
|
||||
#include "extensions/browser/process_manager.h"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "shell/browser/fake_location_provider.h"
|
||||
|
||||
#include "base/time/time.h"
|
||||
#include "services/device/public/mojom/geoposition.mojom-shared.h"
|
||||
#include "services/device/public/mojom/geoposition.mojom.h"
|
||||
|
||||
|
||||
@@ -58,6 +58,11 @@ void InitializeFeatureList() {
|
||||
if (platform_specific_enable_features.size() > 0) {
|
||||
enable_features += std::string(",") + platform_specific_enable_features;
|
||||
}
|
||||
std::string platform_specific_disable_features =
|
||||
DisablePlatformSpecificFeatures();
|
||||
if (platform_specific_disable_features.size() > 0) {
|
||||
disable_features += std::string(",") + platform_specific_disable_features;
|
||||
}
|
||||
base::FeatureList::InitInstance(enable_features, disable_features);
|
||||
}
|
||||
|
||||
@@ -73,6 +78,9 @@ void InitializeFieldTrials() {
|
||||
std::string EnablePlatformSpecificFeatures() {
|
||||
return "";
|
||||
}
|
||||
std::string DisablePlatformSpecificFeatures() {
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace electron {
|
||||
void InitializeFeatureList();
|
||||
void InitializeFieldTrials();
|
||||
std::string EnablePlatformSpecificFeatures();
|
||||
std::string DisablePlatformSpecificFeatures();
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_FEATURE_LIST_H_
|
||||
|
||||
@@ -31,4 +31,13 @@ std::string EnablePlatformSpecificFeatures() {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string DisablePlatformSpecificFeatures() {
|
||||
if (@available(macOS 14.4, *)) {
|
||||
// Required to stop timing out getDisplayMedia while waiting for
|
||||
// the user to select a window with the picker
|
||||
return "TimeoutHangingVideoCaptureStarts";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "shell/browser/file_system_access/file_system_access_permission_context_factory.h"
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "base/bits.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/task/thread_pool/initialization_util.h"
|
||||
|
||||
@@ -71,8 +71,9 @@ class NativeWindow : public base::SupportsUserData,
|
||||
|
||||
// Create window with existing WebContents, the caller is responsible for
|
||||
// managing the window's live.
|
||||
static NativeWindow* Create(const gin_helper::Dictionary& options,
|
||||
NativeWindow* parent = nullptr);
|
||||
static std::unique_ptr<NativeWindow> Create(
|
||||
const gin_helper::Dictionary& options,
|
||||
NativeWindow* parent = nullptr);
|
||||
|
||||
void InitFromOptions(const gin_helper::Dictionary& options);
|
||||
|
||||
@@ -448,7 +449,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||
// Minimum and maximum size.
|
||||
std::optional<extensions::SizeConstraints> size_constraints_;
|
||||
// Same as above but stored as content size, we are storing 2 types of size
|
||||
// constraints beacause converting between them will cause rounding errors
|
||||
// constraints because converting between them will cause rounding errors
|
||||
// on HiDPI displays on some environments.
|
||||
std::optional<extensions::SizeConstraints> content_size_constraints_;
|
||||
|
||||
|
||||
@@ -1814,9 +1814,10 @@ std::optional<gfx::Rect> NativeWindowMac::GetWindowControlsOverlayRect() {
|
||||
}
|
||||
|
||||
// static
|
||||
NativeWindow* NativeWindow::Create(const gin_helper::Dictionary& options,
|
||||
NativeWindow* parent) {
|
||||
return new NativeWindowMac(options, parent);
|
||||
std::unique_ptr<NativeWindow> NativeWindow::Create(
|
||||
const gin_helper::Dictionary& options,
|
||||
NativeWindow* parent) {
|
||||
return std::make_unique<NativeWindowMac>(options, parent);
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -570,7 +570,7 @@ bool NativeWindowViews::IsVisible() const {
|
||||
// current window.
|
||||
bool visible =
|
||||
::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_VISIBLE;
|
||||
// WS_VISIBLE is true even if a window is miminized - explicitly check that.
|
||||
// WS_VISIBLE is true even if a window is minimized - explicitly check that.
|
||||
return visible && !IsMinimized();
|
||||
#else
|
||||
return widget()->IsVisible();
|
||||
@@ -1789,9 +1789,10 @@ void NativeWindowViews::MoveBehindTaskBarIfNeeded() {
|
||||
}
|
||||
|
||||
// static
|
||||
NativeWindow* NativeWindow::Create(const gin_helper::Dictionary& options,
|
||||
NativeWindow* parent) {
|
||||
return new NativeWindowViews(options, parent);
|
||||
std::unique_ptr<NativeWindow> NativeWindow::Create(
|
||||
const gin_helper::Dictionary& options,
|
||||
NativeWindow* parent) {
|
||||
return std::make_unique<NativeWindowViews>(options, parent);
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "crypto/sha2.h"
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <string_view>
|
||||
#include "base/task/thread_pool.h"
|
||||
#include "content/public/browser/file_url_loader.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace mojo {
|
||||
template <typename T>
|
||||
class PendingReciever;
|
||||
class PendingReceiver;
|
||||
template <typename T>
|
||||
class PendingRemote;
|
||||
} // namespace mojo
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
namespace mojo {
|
||||
template <typename T>
|
||||
class PendingReciever;
|
||||
class PendingReceiver;
|
||||
template <typename T>
|
||||
class PendingRemote;
|
||||
} // namespace mojo
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <string_view>
|
||||
#include "base/values.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/hash/md5.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/time/time.h"
|
||||
#include "shell/browser/notifications/win/windows_toast_notification.h"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "base/hash/hash.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util_win.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
@@ -69,7 +69,7 @@ void LayeredWindowUpdater::Draw(const gfx::Rect& damage_rect,
|
||||
|
||||
if (active_ && canvas_->peekPixels(&pixmap)) {
|
||||
bitmap.installPixels(pixmap);
|
||||
callback_.Run(damage_rect, bitmap);
|
||||
callback_.Run(damage_rect, bitmap, {});
|
||||
}
|
||||
|
||||
std::move(draw_callback).Run();
|
||||
|
||||
@@ -11,15 +11,16 @@
|
||||
#include "base/memory/shared_memory_mapping.h"
|
||||
#include "components/viz/host/host_display_client.h"
|
||||
#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
|
||||
#include "shell/browser/osr/osr_paint_event.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
|
||||
class SkBitmap;
|
||||
class SkCanvas;
|
||||
|
||||
namespace electron {
|
||||
|
||||
typedef base::RepeatingCallback<void(const gfx::Rect&, const SkBitmap&)>
|
||||
OnPaintCallback;
|
||||
|
||||
class LayeredWindowUpdater : public viz::mojom::LayeredWindowUpdater {
|
||||
public:
|
||||
explicit LayeredWindowUpdater(
|
||||
|
||||
@@ -32,7 +32,7 @@ void OffScreenHostDisplayClient::OnDisplayReceivedCALayerParams(
|
||||
kPremul_SkAlphaType),
|
||||
pixels, stride);
|
||||
bitmap.setImmutable();
|
||||
callback_.Run(ca_layer_params.damage, bitmap);
|
||||
callback_.Run(ca_layer_params.damage, bitmap, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
31
shell/browser/osr/osr_paint_event.cc
Normal file
31
shell/browser/osr/osr_paint_event.cc
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
// Copyright (c) 2024 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
#include "shell/browser/osr/osr_paint_event.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
OffscreenNativePixmapPlaneInfo::~OffscreenNativePixmapPlaneInfo() = default;
|
||||
OffscreenNativePixmapPlaneInfo::OffscreenNativePixmapPlaneInfo(
|
||||
const OffscreenNativePixmapPlaneInfo& other) = default;
|
||||
OffscreenNativePixmapPlaneInfo::OffscreenNativePixmapPlaneInfo(uint32_t stride,
|
||||
uint64_t offset,
|
||||
uint64_t size,
|
||||
int fd)
|
||||
: stride(stride), offset(offset), size(size), fd(fd) {}
|
||||
|
||||
OffscreenReleaserHolder::~OffscreenReleaserHolder() = default;
|
||||
OffscreenReleaserHolder::OffscreenReleaserHolder(
|
||||
gfx::GpuMemoryBufferHandle gmb_handle,
|
||||
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
releaser)
|
||||
: gmb_handle(std::move(gmb_handle)), releaser(std::move(releaser)) {}
|
||||
|
||||
OffscreenSharedTextureValue::OffscreenSharedTextureValue() = default;
|
||||
OffscreenSharedTextureValue::~OffscreenSharedTextureValue() = default;
|
||||
OffscreenSharedTextureValue::OffscreenSharedTextureValue(
|
||||
const OffscreenSharedTextureValue& other) = default;
|
||||
|
||||
} // namespace electron
|
||||
113
shell/browser/osr/osr_paint_event.h
Normal file
113
shell/browser/osr/osr_paint_event.h
Normal file
@@ -0,0 +1,113 @@
|
||||
|
||||
// Copyright (c) 2024 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_OSR_OSR_PAINT_EVENT_H
|
||||
#define ELECTRON_SHELL_BROWSER_OSR_OSR_PAINT_EVENT_H
|
||||
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "content/public/common/widget_type.h"
|
||||
#include "media/base/video_types.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "ui/gfx/canvas.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace electron {
|
||||
|
||||
struct OffscreenNativePixmapPlaneInfo {
|
||||
// The strides and offsets in bytes to be used when accessing the buffers
|
||||
// via a memory mapping. One per plane per entry. Size in bytes of the
|
||||
// plane is necessary to map the buffers.
|
||||
uint32_t stride;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
|
||||
// File descriptor for the underlying memory object (usually dmabuf).
|
||||
int fd;
|
||||
|
||||
OffscreenNativePixmapPlaneInfo() = delete;
|
||||
~OffscreenNativePixmapPlaneInfo();
|
||||
OffscreenNativePixmapPlaneInfo(const OffscreenNativePixmapPlaneInfo& other);
|
||||
OffscreenNativePixmapPlaneInfo(uint32_t stride,
|
||||
uint64_t offset,
|
||||
uint64_t size,
|
||||
int fd);
|
||||
};
|
||||
|
||||
struct OffscreenReleaserHolder {
|
||||
OffscreenReleaserHolder() = delete;
|
||||
~OffscreenReleaserHolder();
|
||||
OffscreenReleaserHolder(
|
||||
gfx::GpuMemoryBufferHandle gmb_handle,
|
||||
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
releaser);
|
||||
|
||||
// GpuMemoryBufferHandle, keep the scoped handle alive
|
||||
gfx::GpuMemoryBufferHandle gmb_handle;
|
||||
|
||||
// Releaser, hold this to prevent FrameSinkVideoCapturer recycle frame
|
||||
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
releaser;
|
||||
};
|
||||
|
||||
struct OffscreenSharedTextureValue {
|
||||
OffscreenSharedTextureValue();
|
||||
~OffscreenSharedTextureValue();
|
||||
OffscreenSharedTextureValue(const OffscreenSharedTextureValue& other);
|
||||
|
||||
// It is user's responsibility to compose popup widget textures.
|
||||
content::WidgetType widget_type;
|
||||
|
||||
// The pixel format of the shared texture, RGBA or BGRA depends on platform.
|
||||
media::VideoPixelFormat pixel_format;
|
||||
|
||||
// The full dimensions of the video frame data.
|
||||
gfx::Size coded_size;
|
||||
|
||||
// A subsection of [0, 0, coded_size().width(), coded_size.height()].
|
||||
// In OSR case, it is expected to have the full area of the section.
|
||||
gfx::Rect visible_rect;
|
||||
|
||||
// The region of the video frame that capturer would like to populate.
|
||||
// In OSR case, it is the same with `dirtyRect` that needs to be painted.
|
||||
gfx::Rect content_rect;
|
||||
|
||||
// Extra metadata for the video frame.
|
||||
// See comments in src\media\base\video_frame_metadata.h for more details.
|
||||
std::optional<gfx::Rect> capture_update_rect;
|
||||
std::optional<gfx::Size> source_size;
|
||||
std::optional<gfx::Rect> region_capture_rect;
|
||||
|
||||
// The capture timestamp, microseconds since capture start
|
||||
int64_t timestamp;
|
||||
|
||||
// The frame count
|
||||
int64_t frame_count;
|
||||
|
||||
// Releaser holder
|
||||
raw_ptr<OffscreenReleaserHolder> releaser_holder;
|
||||
|
||||
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
|
||||
// On Windows it is a HANDLE to the shared D3D11 texture.
|
||||
// On macOS it is a IOSurface* to the shared IOSurface.
|
||||
uintptr_t shared_texture_handle;
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
std::vector<OffscreenNativePixmapPlaneInfo> planes;
|
||||
uint64_t modifier;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef std::optional<OffscreenSharedTextureValue> OffscreenSharedTexture;
|
||||
|
||||
typedef base::RepeatingCallback<
|
||||
void(const gfx::Rect&, const SkBitmap&, const OffscreenSharedTexture&)>
|
||||
OnPaintCallback;
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_OSR_OSR_PAINT_EVENT_H
|
||||
@@ -177,6 +177,7 @@ class ElectronDelegatedFrameHostClient
|
||||
|
||||
OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
bool transparent,
|
||||
bool offscreen_use_shared_texture,
|
||||
bool painting,
|
||||
int frame_rate,
|
||||
const OnPaintCallback& callback,
|
||||
@@ -187,6 +188,7 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
render_widget_host_(content::RenderWidgetHostImpl::From(host)),
|
||||
parent_host_view_(parent_host_view),
|
||||
transparent_(transparent),
|
||||
offscreen_use_shared_texture_(offscreen_use_shared_texture),
|
||||
callback_(callback),
|
||||
frame_rate_(frame_rate),
|
||||
size_(initial_size),
|
||||
@@ -544,8 +546,9 @@ OffScreenRenderWidgetHostView::CreateViewForWidget(
|
||||
}
|
||||
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, true, embedder_host_view->frame_rate(), callback_,
|
||||
render_widget_host, embedder_host_view, size());
|
||||
transparent_, offscreen_use_shared_texture_, true,
|
||||
embedder_host_view->frame_rate(), callback_, render_widget_host,
|
||||
embedder_host_view, size());
|
||||
}
|
||||
|
||||
const viz::FrameSinkId& OffScreenRenderWidgetHostView::GetFrameSinkId() const {
|
||||
@@ -654,8 +657,15 @@ uint64_t OffScreenRenderWidgetHostView::GetNSViewId() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnPaint(const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap) {
|
||||
void OffScreenRenderWidgetHostView::OnPaint(
|
||||
const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap,
|
||||
const OffscreenSharedTexture& texture) {
|
||||
if (texture.has_value()) {
|
||||
callback_.Run(damage_rect, {}, texture);
|
||||
return;
|
||||
}
|
||||
|
||||
backing_ = std::make_unique<SkBitmap>();
|
||||
backing_->allocN32Pixels(bitmap.width(), bitmap.height(), !transparent_);
|
||||
bitmap.readPixels(backing_->pixmap());
|
||||
@@ -711,7 +721,7 @@ void OffScreenRenderWidgetHostView::CompositeFrame(
|
||||
}
|
||||
|
||||
callback_.Run(gfx::IntersectRects(gfx::Rect(size_in_pixels), damage_rect),
|
||||
frame);
|
||||
frame, {});
|
||||
|
||||
ReleaseResize();
|
||||
}
|
||||
|
||||
@@ -25,14 +25,17 @@
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h" // nogncheck
|
||||
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
|
||||
#include "content/browser/web_contents/web_contents_view.h" // nogncheck
|
||||
#include "shell/browser/osr/osr_host_display_client.h"
|
||||
#include "shell/browser/osr/osr_video_consumer.h"
|
||||
#include "shell/browser/osr/osr_view_proxy.h"
|
||||
#include "third_party/blink/public/mojom/widget/record_content_to_visible_time_request.mojom-forward.h"
|
||||
#include "third_party/blink/public/platform/web_vector.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "ui/base/ime/text_input_client.h"
|
||||
#include "ui/compositor/compositor.h"
|
||||
#include "ui/compositor/layer_delegate.h"
|
||||
#include "ui/compositor/layer_owner.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
#include "components/viz/host/host_display_client.h"
|
||||
|
||||
@@ -59,8 +62,6 @@ class ElectronCopyFrameGenerator;
|
||||
class ElectronDelegatedFrameHostClient;
|
||||
class OffScreenHostDisplayClient;
|
||||
|
||||
using OnPaintCallback =
|
||||
base::RepeatingCallback<void(const gfx::Rect&, const SkBitmap&)>;
|
||||
using OnPopupPaintCallback = base::RepeatingCallback<void(const gfx::Rect&)>;
|
||||
|
||||
class OffScreenRenderWidgetHostView
|
||||
@@ -70,6 +71,7 @@ class OffScreenRenderWidgetHostView
|
||||
private OffscreenViewProxyObserver {
|
||||
public:
|
||||
OffScreenRenderWidgetHostView(bool transparent,
|
||||
bool offscreen_use_shared_texture,
|
||||
bool painting,
|
||||
int frame_rate,
|
||||
const OnPaintCallback& callback,
|
||||
@@ -204,7 +206,9 @@ class OffScreenRenderWidgetHostView
|
||||
void RemoveViewProxy(OffscreenViewProxy* proxy);
|
||||
void ProxyViewDestroyed(OffscreenViewProxy* proxy) override;
|
||||
|
||||
void OnPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
|
||||
void OnPaint(const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap,
|
||||
const OffscreenSharedTexture& texture);
|
||||
void OnPopupPaint(const gfx::Rect& damage_rect);
|
||||
void OnProxyViewPaint(const gfx::Rect& damage_rect) override;
|
||||
|
||||
@@ -231,6 +235,10 @@ class OffScreenRenderWidgetHostView
|
||||
void SetFrameRate(int frame_rate);
|
||||
int frame_rate() const { return frame_rate_; }
|
||||
|
||||
bool offscreen_use_shared_texture() const {
|
||||
return offscreen_use_shared_texture_;
|
||||
}
|
||||
|
||||
ui::Layer* root_layer() const { return root_layer_.get(); }
|
||||
|
||||
content::DelegatedFrameHost* delegated_frame_host() const {
|
||||
@@ -274,6 +282,7 @@ class OffScreenRenderWidgetHostView
|
||||
std::set<OffscreenViewProxy*> proxy_views_;
|
||||
|
||||
const bool transparent_;
|
||||
const bool offscreen_use_shared_texture_;
|
||||
OnPaintCallback callback_;
|
||||
OnPopupPaintCallback parent_callback_;
|
||||
|
||||
|
||||
@@ -16,21 +16,6 @@
|
||||
#include "third_party/skia/include/core/SkRegion.h"
|
||||
#include "ui/gfx/skbitmap_operations.h"
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsValidMinAndMaxFrameSize(gfx::Size min_frame_size,
|
||||
gfx::Size max_frame_size) {
|
||||
// Returns true if
|
||||
// 0 < |min_frame_size| <= |max_frame_size| <= media::limits::kMaxDimension.
|
||||
return 0 < min_frame_size.width() && 0 < min_frame_size.height() &&
|
||||
min_frame_size.width() <= max_frame_size.width() &&
|
||||
min_frame_size.height() <= max_frame_size.height() &&
|
||||
max_frame_size.width() <= media::limits::kMaxDimension &&
|
||||
max_frame_size.height() <= media::limits::kMaxDimension;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace electron {
|
||||
|
||||
OffScreenVideoConsumer::OffScreenVideoConsumer(
|
||||
@@ -43,7 +28,23 @@ OffScreenVideoConsumer::OffScreenVideoConsumer(
|
||||
video_capturer_->SetMinSizeChangePeriod(base::TimeDelta());
|
||||
video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB);
|
||||
|
||||
SizeChanged(view_->SizeInPixels());
|
||||
// Previous design of OSR try to set the resolution constraint to match the
|
||||
// view's size. It is actually not necessary and creates faulty textures
|
||||
// when the window/view's size changes frequently. The constraint may not
|
||||
// take effect before the internal frame size changes, and makes the capturer
|
||||
// try to resize the new frame size to the old constraint size, which makes
|
||||
// the output image blurry. (For example, small window suddenly expands to
|
||||
// maximum size, will actually produce a small output image with maximized
|
||||
// window resized to fit the small image, however, the expected output is
|
||||
// a maximized image without resizing).
|
||||
// So, we just set the constraint to no limit (1x1 to max). When the window
|
||||
// size changed, a new frame with new size will be automatically generated.
|
||||
// There's no need to manually set the constraint and request a new frame.
|
||||
video_capturer_->SetResolutionConstraints(
|
||||
gfx::Size(1, 1),
|
||||
gfx::Size(media::limits::kMaxDimension, media::limits::kMaxDimension),
|
||||
false);
|
||||
|
||||
SetFrameRate(view_->frame_rate());
|
||||
}
|
||||
|
||||
@@ -51,7 +52,10 @@ OffScreenVideoConsumer::~OffScreenVideoConsumer() = default;
|
||||
|
||||
void OffScreenVideoConsumer::SetActive(bool active) {
|
||||
if (active) {
|
||||
video_capturer_->Start(this, viz::mojom::BufferFormatPreference::kDefault);
|
||||
video_capturer_->Start(
|
||||
this, view_->offscreen_use_shared_texture()
|
||||
? viz::mojom::BufferFormatPreference::kPreferGpuMemoryBuffer
|
||||
: viz::mojom::BufferFormatPreference::kDefault);
|
||||
} else {
|
||||
video_capturer_->Stop();
|
||||
}
|
||||
@@ -61,43 +65,77 @@ void OffScreenVideoConsumer::SetFrameRate(int frame_rate) {
|
||||
video_capturer_->SetMinCapturePeriod(base::Seconds(1) / frame_rate);
|
||||
}
|
||||
|
||||
void OffScreenVideoConsumer::SizeChanged(const gfx::Size& size_in_pixels) {
|
||||
DCHECK(IsValidMinAndMaxFrameSize(size_in_pixels, size_in_pixels));
|
||||
video_capturer_->SetResolutionConstraints(size_in_pixels, size_in_pixels,
|
||||
true);
|
||||
video_capturer_->RequestRefreshFrame();
|
||||
}
|
||||
|
||||
void OffScreenVideoConsumer::OnFrameCaptured(
|
||||
::media::mojom::VideoBufferHandlePtr data,
|
||||
::media::mojom::VideoFrameInfoPtr info,
|
||||
const gfx::Rect& content_rect,
|
||||
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
callbacks) {
|
||||
auto& data_region = data->get_read_only_shmem_region();
|
||||
// Since we don't call ProvideFeedback, just need Done to release the frame,
|
||||
// there's no need to call the callbacks, see in_flight_frame_delivery.cc
|
||||
// The destructor will call Done for us once the pipe closed.
|
||||
|
||||
if (!CheckContentRect(content_rect)) {
|
||||
SizeChanged(view_->SizeInPixels());
|
||||
// Offscreen using GPU shared texture
|
||||
if (view_->offscreen_use_shared_texture()) {
|
||||
CHECK(data->is_gpu_memory_buffer_handle());
|
||||
|
||||
auto& orig_handle = data->get_gpu_memory_buffer_handle();
|
||||
CHECK(!orig_handle.is_null());
|
||||
|
||||
// Clone the handle to support keep the handle alive after the callback
|
||||
auto gmb_handle = orig_handle.Clone();
|
||||
|
||||
OffscreenSharedTextureValue texture;
|
||||
texture.pixel_format = info->pixel_format;
|
||||
texture.coded_size = info->coded_size;
|
||||
texture.visible_rect = info->visible_rect;
|
||||
texture.content_rect = content_rect;
|
||||
texture.timestamp = info->timestamp.InMicroseconds();
|
||||
texture.frame_count = info->metadata.capture_counter.value_or(0);
|
||||
texture.capture_update_rect = info->metadata.capture_update_rect;
|
||||
texture.source_size = info->metadata.source_size;
|
||||
texture.region_capture_rect = info->metadata.region_capture_rect;
|
||||
texture.widget_type = view_->GetWidgetType();
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
texture.shared_texture_handle =
|
||||
reinterpret_cast<uintptr_t>(gmb_handle.dxgi_handle.Get());
|
||||
#elif BUILDFLAG(IS_APPLE)
|
||||
texture.shared_texture_handle =
|
||||
reinterpret_cast<uintptr_t>(gmb_handle.io_surface.get());
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
const auto& native_pixmap = gmb_handle.native_pixmap_handle;
|
||||
texture.modifier = native_pixmap.modifier;
|
||||
for (const auto& plane : native_pixmap.planes) {
|
||||
texture.planes.emplace_back(plane.stride, plane.offset, plane.size,
|
||||
plane.fd.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
// The release holder will be released from JS side when `release` called
|
||||
texture.releaser_holder = new OffscreenReleaserHolder(std::move(gmb_handle),
|
||||
std::move(callbacks));
|
||||
|
||||
callback_.Run(content_rect, {}, std::move(texture));
|
||||
return;
|
||||
}
|
||||
|
||||
mojo::Remote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
|
||||
callbacks_remote(std::move(callbacks));
|
||||
// Regular shared texture capture using shared memory
|
||||
const auto& data_region = data->get_read_only_shmem_region();
|
||||
|
||||
if (!data_region.IsValid()) {
|
||||
callbacks_remote->Done();
|
||||
return;
|
||||
}
|
||||
|
||||
base::ReadOnlySharedMemoryMapping mapping = data_region.Map();
|
||||
if (!mapping.IsValid()) {
|
||||
DLOG(ERROR) << "Shared memory mapping failed.";
|
||||
callbacks_remote->Done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapping.size() <
|
||||
media::VideoFrame::AllocationSize(info->pixel_format, info->coded_size)) {
|
||||
DLOG(ERROR) << "Shared memory size was less than expected.";
|
||||
callbacks_remote->Done();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,30 +165,17 @@ void OffScreenVideoConsumer::OnFrameCaptured(
|
||||
[](void* addr, void* context) {
|
||||
delete static_cast<FramePinner*>(context);
|
||||
},
|
||||
new FramePinner{std::move(mapping), callbacks_remote.Unbind()});
|
||||
new FramePinner{std::move(mapping), std::move(callbacks)});
|
||||
bitmap.setImmutable();
|
||||
|
||||
// Since update_rect is already offset-ed with same origin of content_rect,
|
||||
// there's nothing more to do with the imported bitmap.
|
||||
std::optional<gfx::Rect> update_rect = info->metadata.capture_update_rect;
|
||||
if (!update_rect.has_value() || update_rect->IsEmpty()) {
|
||||
update_rect = content_rect;
|
||||
}
|
||||
|
||||
callback_.Run(*update_rect, bitmap);
|
||||
}
|
||||
|
||||
bool OffScreenVideoConsumer::CheckContentRect(const gfx::Rect& content_rect) {
|
||||
gfx::Size view_size = view_->SizeInPixels();
|
||||
gfx::Size content_size = content_rect.size();
|
||||
|
||||
if (std::abs(view_size.width() - content_size.width()) > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::abs(view_size.height() - content_size.height()) > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
callback_.Run(*update_rect, bitmap, {});
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -14,14 +14,12 @@
|
||||
#include "components/viz/host/client_frame_sink_video_capturer.h"
|
||||
#include "media/capture/mojom/video_capture_buffer.mojom-forward.h"
|
||||
#include "media/capture/mojom/video_capture_types.mojom.h"
|
||||
#include "shell/browser/osr/osr_paint_event.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
class OffScreenRenderWidgetHostView;
|
||||
|
||||
typedef base::RepeatingCallback<void(const gfx::Rect&, const SkBitmap&)>
|
||||
OnPaintCallback;
|
||||
|
||||
class OffScreenVideoConsumer : public viz::mojom::FrameSinkVideoConsumer {
|
||||
public:
|
||||
OffScreenVideoConsumer(OffScreenRenderWidgetHostView* view,
|
||||
@@ -34,7 +32,6 @@ class OffScreenVideoConsumer : public viz::mojom::FrameSinkVideoConsumer {
|
||||
|
||||
void SetActive(bool active);
|
||||
void SetFrameRate(int frame_rate);
|
||||
void SizeChanged(const gfx::Size& size_in_pixels);
|
||||
|
||||
private:
|
||||
// viz::mojom::FrameSinkVideoConsumer implementation.
|
||||
@@ -49,8 +46,6 @@ class OffScreenVideoConsumer : public viz::mojom::FrameSinkVideoConsumer {
|
||||
void OnStopped() override {}
|
||||
void OnLog(const std::string& message) override {}
|
||||
|
||||
bool CheckContentRect(const gfx::Rect& content_rect);
|
||||
|
||||
OnPaintCallback callback_;
|
||||
|
||||
raw_ptr<OffScreenRenderWidgetHostView> view_;
|
||||
|
||||
@@ -15,8 +15,11 @@ namespace electron {
|
||||
|
||||
OffScreenWebContentsView::OffScreenWebContentsView(
|
||||
bool transparent,
|
||||
bool offscreen_use_shared_texture,
|
||||
const OnPaintCallback& callback)
|
||||
: transparent_(transparent), callback_(callback) {
|
||||
: transparent_(transparent),
|
||||
offscreen_use_shared_texture_(offscreen_use_shared_texture),
|
||||
callback_(callback) {
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
PlatformCreate();
|
||||
#endif
|
||||
@@ -109,8 +112,8 @@ OffScreenWebContentsView::CreateViewForWidget(
|
||||
return static_cast<content::RenderWidgetHostViewBase*>(rwhv);
|
||||
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, painting_, GetFrameRate(), callback_, render_widget_host,
|
||||
nullptr, GetSize());
|
||||
transparent_, offscreen_use_shared_texture_, painting_, GetFrameRate(),
|
||||
callback_, render_widget_host, nullptr, GetSize());
|
||||
}
|
||||
|
||||
content::RenderWidgetHostViewBase*
|
||||
@@ -124,9 +127,9 @@ OffScreenWebContentsView::CreateViewForChildWidget(
|
||||
? web_contents_impl->GetOuterWebContents()->GetRenderWidgetHostView()
|
||||
: web_contents_impl->GetRenderWidgetHostView());
|
||||
|
||||
return new OffScreenRenderWidgetHostView(transparent_, painting_,
|
||||
view->frame_rate(), callback_,
|
||||
render_widget_host, view, GetSize());
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, offscreen_use_shared_texture_, painting_,
|
||||
view->frame_rate(), callback_, render_widget_host, view, GetSize());
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::RenderViewReady() {
|
||||
|
||||
@@ -34,7 +34,9 @@ class OffScreenWebContentsView : public content::WebContentsView,
|
||||
public content::RenderViewHostDelegateView,
|
||||
private NativeWindowObserver {
|
||||
public:
|
||||
OffScreenWebContentsView(bool transparent, const OnPaintCallback& callback);
|
||||
OffScreenWebContentsView(bool transparent,
|
||||
bool offscreen_use_shared_texture,
|
||||
const OnPaintCallback& callback);
|
||||
~OffScreenWebContentsView() override;
|
||||
|
||||
void SetWebContents(content::WebContents*);
|
||||
@@ -105,6 +107,7 @@ class OffScreenWebContentsView : public content::WebContentsView,
|
||||
raw_ptr<NativeWindow> native_window_ = nullptr;
|
||||
|
||||
const bool transparent_;
|
||||
const bool offscreen_use_shared_texture_;
|
||||
bool painting_ = true;
|
||||
int frame_rate_ = 60;
|
||||
OnPaintCallback callback_;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include "shell/browser/serial/serial_chooser_context.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <string_view>
|
||||
#include "base/base64.h"
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/values.h"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "shell/browser/special_storage_policy.h"
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "services/network/public/cpp/session_cookie_delete_predicate.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -15,13 +15,9 @@ DelayedNativeViewHost::~DelayedNativeViewHost() = default;
|
||||
|
||||
void DelayedNativeViewHost::ViewHierarchyChanged(
|
||||
const views::ViewHierarchyChangedDetails& details) {
|
||||
// NativeViewHost doesn't expect to have children, so filter the
|
||||
// ViewHierarchyChanged events before passing them on.
|
||||
if (details.child == this) {
|
||||
NativeViewHost::ViewHierarchyChanged(details);
|
||||
if (details.is_add && GetWidget() && !native_view())
|
||||
Attach(native_view_);
|
||||
}
|
||||
NativeViewHost::ViewHierarchyChanged(details);
|
||||
if (details.is_add && GetWidget() && !native_view())
|
||||
Attach(native_view_);
|
||||
}
|
||||
|
||||
bool DelayedNativeViewHost::OnMousePressed(const ui::MouseEvent& ui_event) {
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include "base/apple/foundation_util.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "shell/browser/ui/cocoa/window_buttons_proxy.h"
|
||||
|
||||
#include "base/i18n/rtl.h"
|
||||
#include "base/notreached.h"
|
||||
|
||||
@implementation ButtonsAreaHoverView : NSView
|
||||
|
||||
|
||||
@@ -10,12 +10,10 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <string_view>
|
||||
#include "base/base64.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/metrics/histogram.h"
|
||||
#include "base/strings/pattern.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
@@ -785,6 +783,7 @@ void InspectableWebContents::SetEyeDropperActive(bool active) {
|
||||
if (delegate_)
|
||||
delegate_->DevToolsSetEyeDropperActive(active);
|
||||
}
|
||||
|
||||
void InspectableWebContents::ZoomIn() {
|
||||
double new_level = GetNextZoomLevel(GetDevToolsZoomLevel(), false);
|
||||
SetZoomLevelForWebContents(GetDevToolsWebContents(), new_level);
|
||||
@@ -966,6 +965,13 @@ void InspectableWebContents::CloseContents(content::WebContents* source) {
|
||||
CloseDevTools();
|
||||
}
|
||||
|
||||
std::unique_ptr<content::EyeDropper> InspectableWebContents::OpenEyeDropper(
|
||||
content::RenderFrameHost* frame,
|
||||
content::EyeDropperListener* listener) {
|
||||
auto* delegate = web_contents_->GetDelegate();
|
||||
return delegate ? delegate->OpenEyeDropper(frame, listener) : nullptr;
|
||||
}
|
||||
|
||||
void InspectableWebContents::RunFileChooser(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
scoped_refptr<content::FileSelectListener> listener,
|
||||
|
||||
@@ -208,6 +208,9 @@ class InspectableWebContents
|
||||
bool HandleKeyboardEvent(content::WebContents*,
|
||||
const input::NativeWebKeyboardEvent&) override;
|
||||
void CloseContents(content::WebContents* source) override;
|
||||
std::unique_ptr<content::EyeDropper> OpenEyeDropper(
|
||||
content::RenderFrameHost* frame,
|
||||
content::EyeDropperListener* listener) override;
|
||||
void RunFileChooser(content::RenderFrameHost* render_frame_host,
|
||||
scoped_refptr<content::FileSelectListener> listener,
|
||||
const blink::mojom::FileChooserParams& params) override;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <utility>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "shell/browser/ui/drag_util.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
|
||||
|
||||
@@ -27,7 +27,7 @@ class RenderFrameHost;
|
||||
|
||||
namespace mojo {
|
||||
template <typename T>
|
||||
class PendingReciever;
|
||||
class PendingReceiver;
|
||||
template <typename T>
|
||||
class PendingRemote;
|
||||
} // namespace mojo
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include "shell/browser/usb/usb_chooser_context.h"
|
||||
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <string_view>
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace mojo {
|
||||
template <typename T>
|
||||
class PendingReciever;
|
||||
class PendingReceiver;
|
||||
template <typename T>
|
||||
class PendingRemote;
|
||||
} // namespace mojo
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/browser/window_list_observer.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user