Compare commits

..

20 Commits

Author SHA1 Message Date
chen jing
d06db5f30c test: skip webFrameMain.copyVideoFrameAt on win32 CI due Chromium DCHECK 2026-03-19 14:02:07 +08:00
dodola
67eec6ceb3 Merge branch 'electron:main' into videoframe 2026-03-17 19:27:30 +08:00
David Sanders
36350d78d0 chore: add missing timers-shim.ts to filenames.auto.gni (#50311) 2026-03-17 09:46:15 +01:00
dependabot[bot]
9b80324d7f build(deps): bump github/codeql-action from 4.32.6 to 4.33.0 (#50308)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.6 to 4.33.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](0d579ffd05...b1bff81932)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 22:15:03 -07:00
dependabot[bot]
a549c56faa build(deps): bump slackapi/slack-github-action from 2.1.1 to 3.0.1 (#50307)
Bumps [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action) from 2.1.1 to 3.0.1.
- [Release notes](https://github.com/slackapi/slack-github-action/releases)
- [Commits](91efab103c...af78098f53)

---
updated-dependencies:
- dependency-name: slackapi/slack-github-action
  dependency-version: 3.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 22:14:43 -07:00
Keeley Hammond
958278c273 feat: add id and groupId options to macOS notifications (#50097)
* feat: add custom `id` property to Notification API (macOS only)

* feat: add `groupId` property to Notification API (macOS). Notifications with the same groupId will be visually grouped together in Notification Center

* fix: move validation to construction time, add empty string check, remove setters

* docs: clarify id/group id properties, make instance properties read-only

* test: update tests to reflect read-only properties
2026-03-16 21:24:29 +01:00
Shelley Vohr
b7e9bbed0c fix: restore sdk_inputs cross-toolchain deps for macOS (#50297)
fix: restore sdk_inputs cross-toolchain deps for macOS

The change in CL:7652975 restricted sdk_inputs public_deps
to iOS only, to avoid setting up Xcode symlinks for the Linux
toolchain when cross-building chrome/linux on Mac. However, this
also broke cross-arch macOS builds (e.g. ffmpeg with target_cpu=x64)
where the mig target in the clang_arm64 toolchain depends on
sdk_inputs from the default clang_x64 toolchain.

Add target_os == \"mac\" alongside the existing iOS check to preserve
the original intent while restoring the cross-toolchain dependency
for macOS builds.
2026-03-16 20:12:38 +00:00
Justin Mayfield
eec3fe967e fix: user resizable transparent windows on win32 (#49428)
test: revert win32 frameless and transparent resizable expectations
2026-03-16 15:31:07 -04:00
David Sanders
01714757e3 ci: ignore test timeouts in audit (#50259) 2026-03-16 14:33:37 -04:00
Shelley Vohr
ffad67222d test: fix esm issue in node-spec-runner (#50289)
Chromium added a top-level package.json in CL:7485999 that sets
the type to module and breaks commonjs tests run via
node-spec-runner.js. This commit temporarily changes the type to
commonjs while running the tests, then changes it back to module when done.
2026-03-16 12:55:03 -04:00
ZHUO Xu
078586fab0 docs: update the example of webContents.setWindowOpenHandler to cla… (#49379)
docs: reorganize the comments for clarifying `webContents.setWindowOpenHandler` example
2026-03-16 12:12:52 -04:00
Noah Gregory
a561dd97a6 fix: add ASAR support to additional copy methods (#50226)
* fix: add ASAR support for additional copy methods

* test: add tests for ASAR support for additional copy messages
2026-03-16 14:36:48 +01:00
Shelley Vohr
b9cbcde600 build: remove redundant bits of ncrypto node patch (#50252)
build: remove redundant ncrypto node patch
2026-03-16 12:13:47 +01:00
electron-roller[bot]
36b0709942 chore: bump chromium to 148.0.7733.0 (main) (#50197)
* chore: bump chromium in DEPS to 147.0.7727.2

* chore: bump chromium in DEPS to 148.0.7728.0

* chore: bump chromium in DEPS to 148.0.7729.0

* chore: bump chromium in DEPS to 148.0.7730.0

* chore: bump chromium in DEPS to 148.0.7732.0

* chore: update WrappablePointerTag patch
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7641766

* chore: update custom protocol patch for removed code
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7653454

* chore: update patches

* fix: cleanup removed CHILD_PLUGIN code
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7653455

* fix: move from int to ChildProcessId
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7621912

* fix: update extensions CreateTab signature
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7644389

* fix: draggable hit region test interface update for mac windows
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7655245

* chore: bump chromium in DEPS to 148.0.7733.0

* feat: restore macos child plugin process
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7653455

* fixup! chore: merge main

* chore: update patches

* fix: replace clipboard IsFormatAvailable with async GetAllAvailableFormats
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7631097

Async API pending RFC https://github.com/electron/rfcs/pull/19

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Samuel Maddock <samuelmaddock@electronjs.org>
2026-03-16 10:55:06 +01:00
Shelley Vohr
cf84efbbb9 fix: prefer browser runtime over node in DevTools HostRuntime detection (#50241)
Upstream DevTools' HostRuntime checks `IS_NODE` before `IS_BROWSER` when
selecting the platform runtime. In Electron, `process` is available in
renderer processes, so `IS_NODE` evaluates to `true` in the DevTools
context. This causes DevTools to dynamically import the Node.js platform
runtime, which uses `node:worker_threads`. DevTools Web Workers running
under the `devtools://` protocol cannot load Node.js built-in modules,
so the import fails and breaks features like the formatter worker.

Fix by swapping the check order to prefer `IS_BROWSER` when both are
true. This is safe because in pure Node.js environments (the only case
where the node runtime is needed), `window` and `self` are both
undefined, so `IS_BROWSER` is always `false` regardless of check order.
2026-03-16 10:29:35 +01:00
David Sanders
58cd1aba10 ci: fix unsupported major in release board automation (#50260) 2026-03-14 15:34:50 -07:00
dependabot[bot]
26a3a8679a build(deps-dev): bump folder-hash from 4.1.1 to 4.1.2 (#50258)
Bumps [folder-hash](https://github.com/marc136/node-folder-hash) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/marc136/node-folder-hash/releases)
- [Changelog](https://github.com/marc136/node-folder-hash/blob/v5/CHANGELOG.md)
- [Commits](https://github.com/marc136/node-folder-hash/compare/v4.1.1...v4.1.2)

---
updated-dependencies:
- dependency-name: folder-hash
  dependency-version: 4.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-13 22:46:05 -07:00
John Kleinschmidt
a1e4c260ea ci: create PR triage project automation (#50248)
* ci: create PR triage project automation

* chore: use ubuntu-slim

---------

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2026-03-14 02:35:29 +00:00
dodola
ea6da976eb Merge branch 'electron:main' into videoframe 2026-02-24 10:57:39 +08:00
chenjing
b568504d8d feat: add copyVideoFrameAt and saveVideoFrameAs Method on Webcontent
chore: change the description of savevideoframe api

chore: add the description of the restrictive elements for using the APIs.

move to webframemain

fixed mediaPlayerAction to kSaveVideoFrameAs

Update spec/api-web-frame-main-spec.ts

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

Update spec/api-web-frame-main-spec.ts

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

fixed clipboard tests for video frame copying

fixed test for copying video frame to clipboard. check video loaded before copy video frame in test.

chore: try non-proprietary video format

Revert "chore: try non-proprietary video format"

This reverts commit ef085f88a1af53b6408a7af695cc60b8681398cf.

fix: format video as file url
2025-12-10 18:25:52 +08:00
16 changed files with 217 additions and 31 deletions

View File

@@ -86,6 +86,7 @@ jobs:
!message.startsWith("Response status code does not indicate success") &&
!message.startsWith("The hosted runner lost communication with the server") &&
!message.startsWith("Dependabot encountered an error performing the update") &&
!message.startsWith("The action 'Run Electron Tests' has timed out") &&
!/Unable to make request/.test(message) &&
!/The requested URL returned error/.test(message),
)
@@ -154,7 +155,7 @@ jobs:
await core.summary.write();
- name: Send Slack message if errors
if: ${{ always() && steps.audit-errors.outputs.errorsFound && github.ref == 'refs/heads/main' }}
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
with:
payload: |
link: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

View File

@@ -31,8 +31,8 @@ jobs:
else
echo "Not a release branch: $BRANCH_NAME"
fi
- name: Determine Unsupported Major Version
id: determine-unsupported-major
- name: Determine Next Unsupported Major Version
id: determine-next-unsupported-major
if: ${{ steps.check-major-version.outputs.MAJOR }}
env:
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
@@ -50,26 +50,27 @@ jobs:
# Find the oldest version where eolDate >= stableDate of the new major
# This gives us the oldest supported version when the new major goes stable
UNSUPPORTED_MAJOR=$(echo "$SCHEDULE" | jq -r --arg stableDate "$STABLE_DATE" '
NEXT_UNSUPPORTED_MAJOR=$(echo "$SCHEDULE" | jq -r --arg stableDate "$STABLE_DATE" '
[.[] | select(.eolDate != null and .eolDate >= $stableDate)] | sort_by(.version | split(".")[0] | tonumber) | first | .version | split(".")[0]
')
if [[ -z "$UNSUPPORTED_MAJOR" || "$UNSUPPORTED_MAJOR" == "null" ]]; then
if [[ -z "$NEXT_UNSUPPORTED_MAJOR" || "$NEXT_UNSUPPORTED_MAJOR" == "null" ]]; then
echo "Could not determine oldest supported version"
exit 1
fi
echo "SCHEDULE=$SCHEDULE" >> "$GITHUB_OUTPUT"
echo "UNSUPPORTED_MAJOR=$UNSUPPORTED_MAJOR" >> "$GITHUB_OUTPUT"
echo "NEXT_UNSUPPORTED_MAJOR=$NEXT_UNSUPPORTED_MAJOR" >> "$GITHUB_OUTPUT"
- name: New Release Branch Tasks
if: ${{ steps.check-major-version.outputs.MAJOR }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: electron/electron
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
UNSUPPORTED_MAJOR: ${{ steps.determine-unsupported-major.outputs.UNSUPPORTED_MAJOR }}
NEXT_UNSUPPORTED_MAJOR: ${{ steps.determine-next-unsupported-major.outputs.NEXT_UNSUPPORTED_MAJOR }}
run: |
PREVIOUS_MAJOR=$((MAJOR - 1))
UNSUPPORTED_MAJOR=$((NEXT_UNSUPPORTED_MAJOR - 1))
# Create new labels
gh label create $MAJOR-x-y --color 8d9ee8 || true
@@ -108,8 +109,8 @@ jobs:
id: generate-project-metadata
env:
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
UNSUPPORTED_MAJOR: ${{ steps.determine-unsupported-major.outputs.UNSUPPORTED_MAJOR }}
SCHEDULE: ${{ steps.determine-unsupported-major.outputs.SCHEDULE }}
NEXT_UNSUPPORTED_MAJOR: ${{ steps.determine-next-unsupported-major.outputs.NEXT_UNSUPPORTED_MAJOR }}
SCHEDULE: ${{ steps.determine-next-unsupported-major.outputs.SCHEDULE }}
with:
script: |
const schedule = JSON.parse(process.env.SCHEDULE)
@@ -144,7 +145,7 @@ jobs:
major,
"next-major": nextMajor,
"prev-major": prevMajor,
"ending-support-major": parseInt(process.env.UNSUPPORTED_MAJOR),
"ending-support-major": parseInt(process.env.NEXT_UNSUPPORTED_MAJOR),
"beta-date": betaDate,
"beta-prep-week": betaPrepWeek.toISOString().split('T')[0],
"beta-prep-week-end": betaPrepWeekEnd.toISOString().split('T')[0],

View File

@@ -0,0 +1,37 @@
name: PR Triage Automation
on:
pull_request_target:
types: [synchronize, review_requested]
issue_comment:
types: [created]
permissions: {}
jobs:
set-needs-review:
name: Set status to Needs Review
if: >-
(github.event_name == 'pull_request_target' && github.event.action == 'synchronize')
|| (github.event_name == 'pull_request_target' && github.event.action == 'review_requested')
|| (github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.comment.user.login == github.event.issue.user.login)
runs-on: ubuntu-slim
permissions:
contents: read
steps:
- name: Generate GitHub App token
uses: electron/github-app-auth-action@e14e47722ed120360649d0789e25b9baece12725 # v2.0.0
id: generate-token
with:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Set status to Needs Review
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 118
field: Status
field-value: 🌀 Needs Review
fail-if-item-not-found: false

View File

@@ -14,7 +14,7 @@ jobs:
permissions: {}
steps:
- name: Trigger Slack workflow
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
with:
webhook: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
webhook-type: webhook-trigger

View File

@@ -51,6 +51,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v3.29.5
uses: github/codeql-action/upload-sarif@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v3.29.5
with:
sarif_file: results.sarif

View File

@@ -1585,6 +1585,20 @@ Centers the current text selection in web page.
Copy the image at the given position to the clipboard.
#### `contents.copyVideoFrameAt(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, copies the frame at (x, y) to the clipboard.
#### `contents.saveVideoFrameAs(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, shows a save dialog and saves the frame at (x, y) to disk.
#### `contents.paste()`
Executes the editing command `paste` in web page.

View File

@@ -175,6 +175,20 @@ app.on('web-contents-created', (_, webContents) => {
})
```
#### `frame.copyVideoFrameAt(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, copies the frame at (x, y) to the clipboard.
#### `frame.saveVideoFrameAs(x, y)`
* `x` Integer
* `y` Integer
When executed on a video media element, shows a save dialog and saves the frame at (x, y) to disk.
### Instance Properties
#### `frame.ipc` _Readonly_

View File

@@ -179,6 +179,7 @@ auto_filenames = {
"lib/common/define-properties.ts",
"lib/common/deprecate.ts",
"lib/common/ipc-messages.ts",
"lib/common/timers-shim.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",

View File

@@ -437,6 +437,14 @@ WebContents.prototype.loadURL = function (url, options) {
return p;
};
WebContents.prototype.copyVideoFrameAt = function (x: number, y: number) {
this.mainFrame.copyVideoFrameAt(x, y);
};
WebContents.prototype.saveVideoFrameAs = function (x: number, y: number) {
this.mainFrame.saveVideoFrameAs(x, y);
};
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => Electron.WindowOpenHandlerResponse) {
this._windowOpenHandler = handler;
};

View File

@@ -35,7 +35,7 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.6.0",
"events": "^3.2.0",
"folder-hash": "^4.1.1",
"folder-hash": "^4.1.2",
"got": "^11.8.5",
"husky": "^9.1.7",
"lint-staged": "^16.1.0",

View File

@@ -36,6 +36,8 @@
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
#include "third_party/blink/public/mojom/frame/media_player_action.mojom.h"
#include "ui/gfx/geometry/point.h"
namespace {
@@ -260,6 +262,28 @@ v8::Local<v8::Promise> WebFrameMain::ExecuteJavaScript(
return handle;
}
void WebFrameMain::CopyVideoFrameAt(int x, int y) {
if (!CheckRenderFrame())
return;
auto location = gfx::Point(x, y);
auto action = blink::mojom::MediaPlayerAction(
blink::mojom::MediaPlayerActionType::kCopyVideoFrame,
/*enable=*/true);
return render_frame_host()->ExecuteMediaPlayerActionAtLocation(location,
action);
}
void WebFrameMain::SaveVideoFrameAs(int x, int y) {
if (!CheckRenderFrame())
return;
auto location = gfx::Point(x, y);
auto action = blink::mojom::MediaPlayerAction(
blink::mojom::MediaPlayerActionType::kSaveVideoFrameAs,
/*enable=*/true);
return render_frame_host()->ExecuteMediaPlayerActionAtLocation(location,
action);
}
bool WebFrameMain::Reload() {
if (!CheckRenderFrame())
return false;
@@ -593,6 +617,8 @@ void WebFrameMain::FillObjectTemplate(v8::Isolate* isolate,
.SetMethod("executeJavaScript", &WebFrameMain::ExecuteJavaScript)
.SetMethod("collectJavaScriptCallStack",
&WebFrameMain::CollectDocumentJSCallStack)
.SetMethod("copyVideoFrameAt", &WebFrameMain::CopyVideoFrameAt)
.SetMethod("saveVideoFrameAs", &WebFrameMain::SaveVideoFrameAs)
.SetMethod("reload", &WebFrameMain::Reload)
.SetMethod("isDestroyed", &WebFrameMain::IsDestroyed)
.SetMethod("_send", &WebFrameMain::Send)

View File

@@ -118,6 +118,8 @@ class WebFrameMain final : public gin_helper::DeprecatedWrappable<WebFrameMain>,
v8::Local<v8::Promise> ExecuteJavaScript(gin::Arguments* args,
const std::u16string& code);
void CopyVideoFrameAt(int x, int y);
void SaveVideoFrameAs(int x, int y);
bool Reload();
bool IsDestroyed() const;
void Send(v8::Isolate* isolate,

View File

@@ -1018,17 +1018,13 @@ void NativeWindowViews::MoveTop() {
bool NativeWindowViews::CanResize() const {
#if BUILDFLAG(IS_WIN)
return resizable_ && thick_frame_;
return has_frame() ? resizable_ && thick_frame_ : resizable_;
#else
return resizable_;
#endif
}
bool NativeWindowViews::IsResizable() const {
#if BUILDFLAG(IS_WIN)
if (has_frame())
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
#endif
return CanResize();
}

View File

@@ -5611,7 +5611,7 @@ describe('BrowserWindow module', () => {
thickFrame: true,
transparent: true
});
expect(w.isResizable()).to.be.false('resizable');
expect(w.isResizable()).to.be.true('resizable');
w.maximize();
expect(w.isMaximized()).to.be.true('maximized');
const bounds = w.getBounds();

View File

@@ -1,3 +1,4 @@
import { clipboard } from 'electron/common';
import { BrowserWindow, WebFrameMain, webFrameMain, ipcMain, app, WebContents } from 'electron/main';
import { expect } from 'chai';
@@ -534,6 +535,91 @@ describe('webFrameMain module', () => {
});
});
describe('webFrameMain.copyVideoFrameAt', () => {
const insertVideoInFrame = async (frame: WebFrameMain) => {
const videoFilePath = url.pathToFileURL(path.join(fixtures, 'cat-spin.mp4')).href;
await frame.executeJavaScript(`
const video = document.createElement('video');
video.src = '${videoFilePath}';
video.muted = true;
video.loop = true;
video.play();
document.body.appendChild(video);
`);
};
const getFramePosition = async (frame: WebFrameMain) => {
const point = await frame.executeJavaScript(`(${() => {
const iframe = document.querySelector('iframe');
if (!iframe) return;
const rect = iframe.getBoundingClientRect();
return { x: Math.floor(rect.x), y: Math.floor(rect.y) };
}})()`) as Electron.Point;
expect(point).to.be.an('object');
return point;
};
const copyVideoFrameInFrame = async (frame: WebFrameMain) => {
const point = await frame.executeJavaScript(`(${() => {
const video = document.querySelector('video');
if (!video) return;
const rect = video.getBoundingClientRect();
return {
x: Math.floor(rect.x + rect.width / 2),
y: Math.floor(rect.y + rect.height / 2)
};
}})()`) as Electron.Point;
expect(point).to.be.an('object');
// Translate coordinate to be relative of main frame
if (frame.parent) {
const framePosition = await getFramePosition(frame.parent);
point.x += framePosition.x;
point.y += framePosition.y;
}
expect(clipboard.readImage().isEmpty()).to.be.true();
// wait for video to load
await frame.executeJavaScript(`(${() => {
const video = document.querySelector('video');
if (!video) return;
return new Promise(resolve => {
if (video.readyState >= 4) resolve(null);
else video.addEventListener('canplaythrough', resolve, { once: true });
});
}})()`);
frame.copyVideoFrameAt(point.x, point.y);
await waitUntil(() => clipboard.availableFormats().includes('image/png'));
expect(clipboard.readImage().isEmpty()).to.be.false();
};
beforeEach(() => {
clipboard.clear();
});
// TODO: Re-enable on Windows CI once Chromium fixes the intermittent
// backwards-time DCHECK hit while copying video frames:
// DCHECK failed: !delta.is_negative().
ifit(!(process.platform === 'win32' && process.env.CI))('copies video frame in main frame', async () => {
const w = new BrowserWindow({ show: false });
await w.webContents.loadFile(path.join(fixtures, 'blank.html'));
await insertVideoInFrame(w.webContents.mainFrame);
await copyVideoFrameInFrame(w.webContents.mainFrame);
await waitUntil(() => clipboard.availableFormats().includes('image/png'));
});
ifit(!(process.platform === 'win32' && process.env.CI))('copies video frame in subframe', async () => {
const w = new BrowserWindow({ show: false });
await w.webContents.loadFile(path.join(subframesPath, 'frame-with-frame.html'));
const subframe = w.webContents.mainFrame.frames[0];
expect(subframe).to.exist();
await insertVideoInFrame(subframe);
await copyVideoFrameInFrame(subframe);
await waitUntil(() => clipboard.availableFormats().includes('image/png'));
});
});
describe('"frame-created" event', () => {
it('emits when the main frame is created', async () => {
const w = new BrowserWindow({ show: false });

View File

@@ -588,7 +588,7 @@ __metadata:
eslint-plugin-node: "npm:^11.1.0"
eslint-plugin-promise: "npm:^6.6.0"
events: "npm:^3.2.0"
folder-hash: "npm:^4.1.1"
folder-hash: "npm:^4.1.2"
got: "npm:^11.8.5"
husky: "npm:^9.1.7"
lint-staged: "npm:^16.1.0"
@@ -3416,7 +3416,7 @@ __metadata:
languageName: node
linkType: hard
"brace-expansion@npm:^2.0.1":
"brace-expansion@npm:^2.0.1, brace-expansion@npm:^2.0.2":
version: 2.0.2
resolution: "brace-expansion@npm:2.0.2"
dependencies:
@@ -6180,15 +6180,15 @@ __metadata:
languageName: node
linkType: hard
"folder-hash@npm:^4.1.1":
version: 4.1.1
resolution: "folder-hash@npm:4.1.1"
"folder-hash@npm:^4.1.2":
version: 4.1.2
resolution: "folder-hash@npm:4.1.2"
dependencies:
debug: "npm:4.4.0"
minimatch: "npm:7.4.6"
minimatch: "npm:7.4.9"
bin:
folder-hash: bin/folder-hash
checksum: 10c0/71597548cccda43c3d4bda940fd1277f63839a86322d66dec2aa883dce4f51c4c0a6e274d7cb30cfbf4df9897d7a5649a09257e5ffada2fa50cd3a2b09da5a32
checksum: 10c0/7c26f7322820cff61745e168ed7c0d3fe9f9afafe7157d01de5cb708effc66761c2f4d1eda59d2925661baaac2adb8a04a51d0d1f01f8003d7e275610ca3f452
languageName: node
linkType: hard
@@ -9256,12 +9256,12 @@ __metadata:
languageName: node
linkType: hard
"minimatch@npm:7.4.6":
version: 7.4.6
resolution: "minimatch@npm:7.4.6"
"minimatch@npm:7.4.9":
version: 7.4.9
resolution: "minimatch@npm:7.4.9"
dependencies:
brace-expansion: "npm:^2.0.1"
checksum: 10c0/e587bf3d90542555a3d58aca94c549b72d58b0a66545dd00eef808d0d66e5d9a163d3084da7f874e83ca8cc47e91c670e6c6f6593a3e7bb27fcc0e6512e87c67
brace-expansion: "npm:^2.0.2"
checksum: 10c0/8d5406a9697edb9b7ea02697d58cabcb3d3a9a4a02caa1cf57b9ab5ae22c78b2945600661a78f91d1545f77521f97f3cb5f8cb066e58356a121b50e4e60ccdbe
languageName: node
linkType: hard