Compare commits

..

27 Commits

Author SHA1 Message Date
trop[bot]
a47b724c99 chore: bump chromium to 124.0.6359.0 (30-x-y) (#41606)
* chore: bump chromium in DEPS to 124.0.6355.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* 5341411: view-transition: Ensure resources are cleaned up in all cases.

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: fixup patch indices

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* 5354013: Return nullopt on error from ProcessMetrics CPU measurements

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: bump chromium in DEPS to 124.0.6357.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* 5368769: Reland "[mojo] Use large worker for mojom_parser action"

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5336171: [Extensions] Introduce a CoreExtensionsRendererAPIProvider

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5367334: [FS Shortcut] Refactor ExclusiveAccessManager

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5354161: Rename GeolocationManager to GeolocationSystemPermissionManager

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* fixup: [Extensions] Introduce a CoreExtensionsRendererAPIProvider

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: bump chromium in DEPS to 124.0.6359.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* 5371370: [Extensions] Move core NativeHandler registration

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5370702: [Extensions] Introduce ShellExtensionsRendererAPIProvider

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2024-03-15 18:13:55 -04:00
trop[bot]
ee4bbb5851 fix: account for potentially swapped FrameTreeNodeId in WebFrameMain (#41594)
fix: account for potentially swapped FrameTreeNodeId in WebFrameMain

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-14 13:02:09 -04:00
electron-roller[bot]
b713e34947 chore: bump chromium to 124.0.6355.1 (30-x-y) (#41490)
* chore: bump chromium to 124.0.6351.0

* chore: bump chromium in DEPS to 124.0.6339.0

* chore: update patches

* chore: bump chromium in DEPS to 124.0.6341.0

* chore: update patches

* chore: bump chromium in DEPS to 124.0.6343.0

* chore: bump chromium in DEPS to 124.0.6345.0

* chore: update patches

* build: temporarily patch out usage of reclient inputs cfg

* chore: implement missing OnPortConnectedStateChanged

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/5039155

* fix: move NativeHandlers in extensions to new RendererAPIProvider

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/5332839
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/5334058

* chore: add missing websocket method

* refactor: use std::erase instead of base::Erase

Ref: https://issues.chromium.org/issues/40256229

* build: fix reclient inputs processor bug (workaround)

* fix: delay extensions::Dispatcher construction

* chore: bump chromium in DEPS to 124.0.6347.0

* chore: bump chromium in DEPS to 124.0.6349.0

* 5326217: [ViewsAX] Remove WebAXPlatformTreeManagerDelegate

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

* 5347916: Get origin from parent for process-isolated srcdoc.

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

* chore: patches fixup

* 4866222: [api] Deprecate vector<v8::Local>, part 1

https://chromium-review.googlesource.com/c/v8/v8/+/4866222

* 5337304: Remove DXDiag telemetry code.

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

* 5328275: Implement watermark routing to the BrowserView

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

* [libc++] Rename __fwd/hash.h to __fwd/functional.h and add reference_wrapper

* chore: bump chromium in DEPS to 124.0.6351.0

* chore: update patches

* 5342763: [object] Fast path for adding props with existing transition

https://chromium-review.googlesource.com/c/v8/v8/+/5342763

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: bump chromium to 124.0.6353.0

* chore: bump chromium in DEPS to 124.0.6353.0

* chore: update patches

* 5365462: Add missing perfetto::Flow and TRACE_EVENT includes

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

* 5356336: Ensure destruction of mojo channel when destructing KeySystemsImpl

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

* 5332839: [Extensions] Register NativeHandlers with the RendererAPIProvider

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

* 5148827: Add permission types for keyboard lock and pointer lock [1/N]

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

* 5358818: Revert "[object] Fast path for adding props with existing transition"

https://chromium-review.googlesource.com/c/v8/v8/+/5358818

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-14 10:42:18 -04:00
trop[bot]
b39f36496d fix: improve caption button appearance on Windows 11 (#41586)
https://chromium-review.googlesource.com/c/chromium/src/+/4428171

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-14 09:54:31 +01:00
trop[bot]
d16f1d52e8 docs: nativeImage api cleanup (#41570)
* docs: `nativeImage` api cleanup

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

* Update docs/api/native-image.md

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

* Update native-image.md

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

* Update docs/api/native-image.md

Co-authored-by: Felix Rieseberg <fr@makenotion.com>

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

* Update link to app icon

Co-authored-by: Alice Zhao <66543449+alicelovescake@users.noreply.github.com>

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

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Erick Zhao <erick@hotmail.ca>
2024-03-13 10:46:19 -04:00
trop[bot]
d3b182f8b9 fix: chrome://process-internals failing to load (#41540)
fix: chrome://process-internals failing to load

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2024-03-12 20:35:58 +01:00
trop[bot]
35099d9289 docs: Update code signing documentation (#41553)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Felix Rieseberg <fr@makenotion.com>
2024-03-12 12:51:35 -04:00
trop[bot]
b45f579eda test: disable CapturableScreen tests on Windows x64 (#41547)
* test: disable CapturableScreen tests on Windows x64

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* test: disable js-execute-iframe" case should not crash on win 32-bit

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2024-03-08 09:32:34 -05:00
trop[bot]
64c031f264 docs: correct release timeline inaccuracy (#41517)
docs: correct timeline inaccuracy

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-07 11:38:13 +01:00
trop[bot]
058c6b4af7 chore: bump chromium to 124.0.6331.0 (30-x-y) (#41515)
* chore: bump chromium in DEPS to 124.0.6329.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* 5319449: Activate popups after async opener fullscreen exit transitions | https://chromium-review.googlesource.com/c/chromium/src/+/5319449

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* 5321532: [//ui] Remove ContextFactory::SharedMainThreadContextProvider() | https://chromium-review.googlesource.com/c/chromium/src/+/5321532

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* fixup! 5319449: Activate popups after async opener fullscreen exit transitions | https://chromium-review.googlesource.com/c/chromium/src/+/5319449

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* 5319141: [OOPIF PDF] Create PdfNavigationThrottle for main frame navigations | https://chromium-review.googlesource.com/c/chromium/src/+/5319141

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* test: disable webview.capturePage test for mac arm64

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* chore: bump chromium in DEPS to 124.0.6337.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* build: roll back DEPS to 124.0.6331.0

Co-authored-by: VerteDinde <vertedinde@electronjs.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: VerteDinde <vertedinde@electronjs.org>
2024-03-06 13:07:52 -05:00
trop[bot]
333ee6d51a fix: user-did-{resign|become}-active events on macOS (#41528)
fix: user-did-{resign|become}-active events on macOS

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-06 17:09:56 +01:00
trop[bot]
e7300ad4c8 chore: add missing gin::Wrappable GetTypeName overrides (#41531)
chore: add missing gin::Wrappable GetTypeName overrides

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-06 15:58:45 +01:00
trop[bot]
58ee15905b chore: fix fs overrides for asar (#41525)
fix: fs overrides for asar

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-06 12:45:16 +01:00
trop[bot]
036e8502e0 chore: update src_preload_function_for_environment.patch (#41505)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2024-03-04 10:16:56 -05:00
trop[bot]
17856cf91a fix: webContents.print options should be optional (#41480)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-03-02 11:24:36 -05:00
trop[bot]
56dfcc5468 chore: bump chromium to 124.0.6323.0 (30-x-y) (#41475)
* chore: bump chromium in DEPS to 124.0.6315.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5279678: Stream AIDA responses

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5276439: Remove non_network_url_loader_factory_remotes_

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5310165: Add DevTools API to show search results

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: bump chromium in DEPS to 124.0.6317.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* Remove Setup.Install.CumulativeDiskUsage2 and supporting code

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* browser: Make cmd line non-const in process singleton callback

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: bump chromium in DEPS to 124.0.6319.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: bump chromium in DEPS to 124.0.6321.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: bump chromium in DEPS to 124.0.6323.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* 5318335: Roll src/third_party/boringssl/src 23824fa0f..4fe29ebc7

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* 5318051: [CBE Watermarking] Hoist `watermark_view` to a member variable.

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: fixup patch indices

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* 4946553: Delegate HID permission to Chrome App in webview

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* 5310001: DevTools UI binding for reporting client events to AIDA

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* Refactor the predicate taking variant of `__cxx_atomic_wait`

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: fix browser_view patch harder

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* 5293937: Reland "[gUM] Use preferred device if more than one is eligible"

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* fix: filter {video|audio} devices by eligible device id

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* 5267921: enable speak content under the pointer on PWA and WV2

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* 5310195: heap: Remove Blink's GCTaskRunner

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

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-02-29 09:50:27 -05:00
trop[bot]
105acec227 test: disable flaky macOS panel test & refactor screen capture testing (#41461)
* Disable flaky test

Co-authored-by: clavin <clavin@electronjs.org>

* Add helper for storing test artifacts

Co-authored-by: clavin <clavin@electronjs.org>

* Refactor screen capture tests

We have a pattern for inspecting a screen capture, so this refactor codifies that pattern into a helper. This gives us shorter test code, consistency (previously, the display in test code and the display captured could theoretically be different), and better debugging/observability on failure.

Co-authored-by: clavin <clavin@electronjs.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: clavin <clavin@electronjs.org>
2024-02-28 14:55:15 +09:00
trop[bot]
174aedf54c chore: remove deprecated inputFieldType (#41440)
chore: remove deprecated inputFieldType

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2024-02-28 14:52:01 +09:00
trop[bot]
47deb401b0 ci: add logging to uploading to GitHub releases (#41455)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2024-02-28 11:39:52 +09:00
trop[bot]
7331e5dfb1 refactor: prefer using base::NoDestructor to base::{Singleton,LazyInstance} (#41424)
refactor: prefer using base::NoDestructor to base::{Singleton,LazyInstance}

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-02-28 11:38:49 +09:00
trop[bot]
a55f23979e chore: add engflow-reclient-configs to gitignore (#41454)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2024-02-28 11:37:16 +09:00
trop[bot]
4a727c6a72 chore: fix import from patches.py in script/lib/git.py (#41436)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2024-02-26 10:05:33 +01:00
trop[bot]
fd8eec3585 build: update appveyor image to latest version-e-123.0.6312.5 (#41415)
build: update appveyor image to latest version

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: jkleinsc <jkleinsc@users.noreply.github.com>
2024-02-23 16:39:20 -08:00
trop[bot]
ef40e551cf feat: add support for configuring system network context proxies (#41417)
* feat: add support for configuring system network context proxies

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* chore: add specs

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* chore: fix lint

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* fix: address review feedback

Co-authored-by: deepak1556 <hop2deep@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2024-02-23 14:56:06 -06:00
trop[bot]
532039ea2c chore: bump chromium to 123.0.6312.5 (30-x-y) (#41402)
* chore: bump chromium in DEPS to 123.0.6300.2

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: bump chromium in DEPS to 123.0.6301.2

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* chore: bump chromium in DEPS to 123.0.6302.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: bump chromium in DEPS to 123.0.6304.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* chore: bump chromium in DEPS to 123.0.6306.2

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* chore: bump chromium in DEPS to 123.0.6308.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* Refactor //components/pdf/common constants

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

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* Rename URLLoaderFactoryParams::is_corb_enabled to is_orb_enabled.

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

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* Add placeholder of speaker-selection permission.

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

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* Move kPdfMimeType to //components/pdf/common/constants.h

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

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* chore: gen-libc++-filenames.js

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* Make GetClassName non virtual

Refs https://chromium-review.googlesource.com/c/chromium/src/+/5293075
Refs https://issues.chromium.org/issues/324596267

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* chore: bump chromium in DEPS to 123.0.6310.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update filenames.libcxx.gni

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* 5282732: Compute input region using correct pixel size.

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* fixup: Make GetClassName non virtual

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: bump chromium in DEPS to 123.0.6312.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* chore: bump chromium in DEPS to 123.0.6312.5

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* fixup: Make GetClassName non virtual

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* docs: document speaker-selection

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

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2024-02-22 10:29:09 -05:00
trop[bot]
25b0212fe6 fix: use ScreenCaptureKit exclusively on macOS 14.4 and higher (#41404)
This fixes a nasty warning / permission dialog that pops up to end-users
when consuming legacy APIs.  Chrome has flipped these flags via field trials
as have other Electron apps. It should just be the default.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>
2024-02-22 14:32:32 +01:00
trop[bot]
310598c43d docs: update breaking changes language (#41399)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
2024-02-21 12:09:39 -08:00
147 changed files with 1962 additions and 3453 deletions

View File

@@ -75,6 +75,10 @@ executors:
resource_class: << parameters.size >>
# Electron Runners
apple-silicon:
resource_class: electronjs/macos-arm64
machine: true
linux-arm:
resource_class: electronjs/aks-linux-arm-test
docker:
@@ -2294,10 +2298,8 @@ jobs:
- electron-tests:
artifact-key: darwin-x64
darwin-testing-arm64-tests:
executor:
name: macos
size: macos.m1.medium.gen1
darwin-testing-arm64-tests:
executor: apple-silicon
environment:
<<: *env-mac-large
<<: *env-stack-dumping
@@ -2321,9 +2323,7 @@ jobs:
artifact-key: mas-x64
mas-testing-arm64-tests:
executor:
name: macos
size: macos.m1.medium.gen1
executor: apple-silicon
environment:
<<: *env-mac-large
<<: *env-stack-dumping

View File

@@ -4,8 +4,12 @@
"onCreateCommand": ".devcontainer/on-create-command.sh",
"updateContentCommand": ".devcontainer/update-content-command.sh",
"workspaceFolder": "/workspaces/gclient/src/electron",
"forwardPorts": [6080, 5901],
"forwardPorts": [8088, 6080, 5901],
"portsAttributes": {
"8088": {
"label": "Goma Control Panel",
"onAutoForward": "silent"
},
"6080": {
"label": "VNC web client (noVNC)",
"onAutoForward": "silent"

3
.github/CODEOWNERS vendored
View File

@@ -11,9 +11,6 @@ DEPS @electron/wg-upgrades
/docs/breaking-changes.md @electron/wg-releases
/npm/ @electron/wg-releases
/script/release @electron/wg-releases
appveyor.yml @electron/wg-releases
appveyor-bake.yml @electron/wg-releases
appveyor-woa.yml @electron/wg-releases
# Security WG
/lib/browser/devtools.ts @electron/wg-security

View File

@@ -8,24 +8,6 @@ permissions: # added using https://github.com/step-security/secure-workflows
contents: read
jobs:
issue-labeled-with-status:
name: status/{confirmed,reviewed} label added
if: github.event.label.name == 'status/confirmed' || github.event.label.name == 'status/reviewed'
runs-on: ubuntu-latest
steps:
- name: Generate GitHub App token
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
id: generate-token
with:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Set status
uses: dsanders11/project-actions/edit-item@82e99438bd44a14ad18d92d036dbc25cbfb9a8c4 # v1.2.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 90
field: Status
field-value: ✅ Triaged
issue-labeled-blocked:
name: blocked/* label added
if: startsWith(github.event.label.name, 'blocked/')

View File

@@ -25,44 +25,3 @@ jobs:
field-value: ${{ github.event.issue.user.login }}
project-number: 90
token: ${{ steps.generate-token.outputs.token }}
set-labels:
if: ${{ contains(github.event.issue.labels.*.name, 'bug :beetle:') }}
runs-on: ubuntu-latest
steps:
- name: Generate GitHub App token
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
id: generate-token
with:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- run: npm install mdast-util-from-markdown@2.0.0 unist-util-select@5.1.0
- name: Add labels
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
ISSUE_BODY: ${{ github.event.issue.body }}
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const { fromMarkdown } = await import('${{ github.workspace }}/node_modules/mdast-util-from-markdown/index.js');
const { select } = await import('${{ github.workspace }}/node_modules/unist-util-select/index.js');
const [ owner, repo ] = '${{ github.repository }}'.split('/');
const issue_number = ${{ github.event.issue.number }};
const tree = fromMarkdown(process.env.ISSUE_BODY);
const labels = [];
const gistUrl = select('heading:has(> text[value="Testcase Gist URL"]) + paragraph > text', tree)?.value.trim();
if (gistUrl !== undefined && gistUrl.startsWith('https://gist.github.com/')) {
labels.push('has-repro-gist');
}
if (labels.length) {
await github.rest.issues.addLabels({
owner,
repo,
issue_number,
labels,
});
}

View File

@@ -6,23 +6,22 @@ on:
schedule:
- cron: '0 8 * * 1-5' # runs 8:00 every business day (see https://crontab.guru)
permissions: {}
permissions:
contents: write
pull-requests: write
jobs:
bake-appveyor-image:
name: Bake AppVeyor Image
permissions:
contents: write
pull-requests: write # to create a new PR with updated Appveyor images
runs-on: ubuntu-latest
steps:
- name: Generate GitHub App token
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
id: generate-token
with:
creds: ${{ secrets.APPVEYOR_UPDATER_GH_APP_CREDS }}
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
token: ${{ steps.generate-token.outputs.token }}
- name: Yarn install
run: |
node script/yarn.js install --frozen-lockfile
@@ -50,24 +49,26 @@ jobs:
diff -w -B appveyor.yml appveyor2.yml > appveyor.diff || true
patch -f appveyor.yml < appveyor.diff
rm appveyor2.yml appveyor.diff
git add appveyor.yml
- name: (Optionally) Generate Commit Diff for WOA
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
run: |
diff -w -B appveyor-woa.yml appveyor-woa2.yml > appveyor-woa.diff || true
patch -f appveyor-woa.yml < appveyor-woa.diff
rm appveyor-woa2.yml appveyor-woa.diff
git add appveyor-woa.yml
- name: (Optionally) Commit to Branch
- name: (Optionally) Commit and Pull Request
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
uses: dsanders11/github-app-commit-action@1dd0a2d22c564461d3f598b6858856e8842d7a16 # v1.1.0
uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 # v6.0.0
with:
message: 'build: update appveyor image to latest version'
ref: bump-appveyor-image
token: ${{ steps.generate-token.outputs.token }}
- name: (Optionally) Create Pull Request
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
run: |
printf "This PR updates appveyor.yml to the latest baked image, ${{ env.APPVEYOR_IMAGE_VERSION }}.\n\nNotes: none" | gh pr create --head bump-appveyor-image --label no-backport --label semver/none --title 'build: update appveyor image to latest version' --body-file=-
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: 'build: update appveyor image to latest version'
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: bump-appveyor-image
delete-branch: true
reviewers: electron/wg-releases
title: 'build: update appveyor image to latest version'
labels: semver/none,no-backport
body: |
This PR updates appveyor.yml to the latest baked image, ${{ env.APPVEYOR_IMAGE_VERSION }}.
Notes: none

View File

@@ -1,17 +1,3 @@
{
"extends": "@electron/lint-roller/configs/markdownlint.json",
"no-angle-brackets": true,
"no-inline-html": {
"allowed_elements": [
"br",
"details",
"img",
"li",
"summary",
"ul",
"unknown",
"Tabs",
"TabItem",
]
}
"extends": "@electron/lint-roller/configs/markdownlint.json"
}

View File

@@ -475,7 +475,6 @@ source_set("electron_lib") {
"//net:extras",
"//net:net_resources",
"//printing/buildflags",
"//services/device/public/cpp/bluetooth:bluetooth",
"//services/device/public/cpp/geolocation",
"//services/device/public/cpp/hid",
"//services/device/public/mojom",
@@ -503,7 +502,6 @@ source_set("electron_lib") {
"//ui/native_theme",
"//ui/shell_dialogs",
"//ui/views",
"//ui/views/controls/webview",
"//v8",
"//v8:v8_libplatform",
]
@@ -639,6 +637,7 @@ source_set("electron_lib") {
"//ui/gtk:gtk_config",
"//ui/linux:linux_ui",
"//ui/linux:linux_ui_factory",
"//ui/views/controls/webview",
"//ui/wm",
]
if (ozone_platform_x11) {
@@ -667,6 +666,7 @@ source_set("electron_lib") {
deps += [
"//components/crash/core/app:crash_export_thunks",
"//ui/native_theme:native_theme_browser",
"//ui/views/controls/webview",
"//ui/wm",
"//ui/wm/public",
]
@@ -856,7 +856,7 @@ if (is_mac) {
if (is_asan) {
# crashpad_handler requires the ASan runtime at its @executable_path.
sources += [ "$root_out_dir/libclang_rt.asan_osx_dynamic.dylib" ]
public_deps += [ "//build/config/sanitizers:copy_sanitizer_runtime" ]
public_deps += [ "//build/config/sanitizers:copy_asan_runtime" ]
}
}

View File

@@ -112,4 +112,4 @@ and more can be found on the [Community page](https://www.electronjs.org/communi
[MIT](https://github.com/electron/electron/blob/main/LICENSE)
When using Electron logos, make sure to follow [OpenJS Foundation Trademark Policy](https://trademark-policy.openjsf.org/).
When using Electron logos, make sure to follow [OpenJS Foundation Trademark Policy](https://openjsf.org/wp-content/uploads/sites/84/2021/01/OpenJS-Foundation-Trademark-Policy-2021-01-12.docx.pdf).

View File

@@ -29,7 +29,7 @@
version: 1.0.{build}
build_cloud: electronhq-16-core
image: e-124.0.6359.0
image: e-123.0.6312.5
environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default

View File

@@ -29,7 +29,7 @@
version: 1.0.{build}
build_cloud: electronhq-16-core
image: e-124.0.6359.0
image: e-123.0.6312.5
environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default

View File

@@ -32,7 +32,7 @@ In most cases, you should do everything in the `ready` event handler.
Returns:
* `event` Event
* `launchInfo` Record\<string, any\> | [NotificationResponse](structures/notification-response.md) _macOS_
* `launchInfo` Record<string, any> | [NotificationResponse](structures/notification-response.md) _macOS_
Emitted once, when Electron has finished initializing. On macOS, `launchInfo`
holds the `userInfo` of the [`NSUserNotification`](https://developer.apple.com/documentation/foundation/nsusernotification)
@@ -970,7 +970,7 @@ app.setJumpList([
### `app.requestSingleInstanceLock([additionalData])`
* `additionalData` Record\<any, any\> (optional) - A JSON object containing additional data to send to the first instance.
* `additionalData` Record<any, any> (optional) - A JSON object containing additional data to send to the first instance.
Returns `boolean`

View File

@@ -103,7 +103,7 @@ The `autoUpdater` object has the following methods:
* `options` Object
* `url` string
* `headers` Record\<string, string\> (optional) _macOS_ - HTTP request headers.
* `headers` Record<string, string> (optional) _macOS_ - HTTP request headers.
* `serverType` string (optional) _macOS_ - Can be `json` or `default`, see the [Squirrel.Mac][squirrel-mac]
README for more information.

View File

@@ -656,7 +656,7 @@ Closes the currently open [Quick Look][quick-look] panel.
#### `win.setBounds(bounds[, animate])`
* `bounds` Partial\<[Rectangle](structures/rectangle.md)\>
* `bounds` Partial<[Rectangle](structures/rectangle.md)>
* `animate` boolean (optional) _macOS_
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.

View File

@@ -779,7 +779,7 @@ Closes the currently open [Quick Look][quick-look] panel.
#### `win.setBounds(bounds[, animate])`
* `bounds` Partial\<[Rectangle](structures/rectangle.md)\>
* `bounds` Partial<[Rectangle](structures/rectangle.md)>
* `animate` boolean (optional) _macOS_
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.
@@ -1215,7 +1215,7 @@ win.loadURL('http://localhost:8000/post', {
* `filePath` string
* `options` Object (optional)
* `query` Record\<string, string\> (optional) - Passed to `url.format()`.
* `query` Record<string, string> (optional) - Passed to `url.format()`.
* `search` string (optional) - Passed to `url.format()`.
* `hash` string (optional) - Passed to `url.format()`.

View File

@@ -17,8 +17,6 @@ following properties:
method.
* `url` string (optional) - The request URL. Must be provided in the absolute
form with the protocol scheme specified as http or https.
* `headers` Record\<string, string | string[]\> (optional) - Headers to be sent
with the request.
* `session` Session (optional) - The [`Session`](session.md) instance with
which the request is associated.
* `partition` string (optional) - The name of the [`partition`](session.md)
@@ -160,7 +158,7 @@ Returns:
* `statusCode` Integer
* `method` string
* `redirectUrl` string
* `responseHeaders` Record\<string, string[]\>
* `responseHeaders` Record<string, string[]>
Emitted when the server returns a redirect response (e.g. 301 Moved
Permanently). Calling [`request.followRedirect`](#requestfollowredirect) will

View File

@@ -59,14 +59,14 @@ The `crashReporter` module has the following methods:
number of crashes uploaded to 1/hour. Default is `false`.
* `compress` boolean (optional) - If true, crash reports will be compressed
and uploaded with `Content-Encoding: gzip`. Default is `true`.
* `extra` Record\<string, string\> (optional) - Extra string key/value
* `extra` Record<string, string> (optional) - Extra string key/value
annotations that will be sent along with crash reports that are generated
in the main process. Only string values are supported. Crashes generated in
child processes will not contain these extra
parameters to crash reports generated from child processes, call
[`addExtraParameter`](#crashreporteraddextraparameterkey-value) from the
child process.
* `globalExtra` Record\<string, string\> (optional) - Extra string key/value
* `globalExtra` Record<string, string> (optional) - Extra string key/value
annotations that will be sent along with any crash reports generated in any
process. These annotations cannot be changed once the crash reporter has
been started. If a key is present in both the global extra parameters and

View File

@@ -72,7 +72,7 @@ Removes listeners of the specified `channel`.
### `ipcMain.handle(channel, listener)`
* `channel` string
* `listener` Function\<Promise\<any\> | any\>
* `listener` Function<Promise\<any&#62; | any&#62;
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
* `...args` any[]
@@ -109,7 +109,7 @@ provided to the renderer process. Please refer to
### `ipcMain.handleOnce(channel, listener)`
* `channel` string
* `listener` Function\<Promise\<any\> | any\>
* `listener` Function<Promise\<any&#62; | any&#62;
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
* `...args` any[]

View File

@@ -1,29 +0,0 @@
## Class: NavigationHistory
> Manage a list of navigation entries, representing the user's browsing history within the application.
Process: [Main](../glossary.md#main-process)<br />
_This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API._
Each navigation entry corresponds to a specific page. The indexing system follows a sequential order, where the first available navigation entry is at index 0, representing the earliest visited page, and the latest navigation entry is at index N, representing the most recent page. Maintaining this ordered list of navigation entries enables seamless navigation both backward and forward through the user's browsing history.
### Instance Methods
#### `navigationHistory.getActiveIndex()`
Returns `Integer` - The index of the current page, from which we would go back/forward or reload.
#### `navigationHistory.getEntryAtIndex(index)`
* `index` Integer
Returns `Object`:
* `url` string - The URL of the navigation entry at the given index.
* `title` string - The page title of the navigation entry at the given index.
If index is out of bounds (greater than history length or less than 0), null will be returned.
#### `navigationHistory.length()`
Returns `Integer` - History length.

View File

@@ -111,7 +111,7 @@ expect streaming responses.
* `scheme` string - scheme to handle, for example `https` or `my-app`. This is
the bit before the `:` in a URL.
* `handler` Function\<[GlobalResponse](https://nodejs.org/api/globals.html#response) | Promise\<GlobalResponse\>\>
* `handler` Function<[GlobalResponse](https://nodejs.org/api/globals.html#response) | Promise<GlobalResponse>>
* `request` [GlobalRequest](https://nodejs.org/api/globals.html#request)
Register a protocol handler for `scheme`. Requests made to URLs with this

View File

@@ -27,7 +27,7 @@ The `pushNotification` module emits the following events:
Returns:
* `event` Event
* `userInfo` Record\<String, any\>
* `userInfo` Record<String, any>
Emitted when the app receives a remote notification while running.
See: https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428430-application?language=objc

View File

@@ -814,8 +814,6 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
* `keyboardLock` - Request capture of keypresses for any or all of the keys on the physical keyboard via the [Keyboard Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/lock). These requests always appear to originate from the main frame.
* `openExternal` - Request to open links in external applications.
* `speaker-selection` - Request to enumerate and select audio output devices via the [speaker-selection permissions policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection).
* `storage-access` - Allows content loaded in a third-party context to request access to third-party cookies using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
* `top-level-storage-access` - Allow top-level sites to request third-party cookie access on behalf of embedded content originating from another site in the same related website set using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
* `window-management` - Request access to enumerate screens using the [`getScreenDetails`](https://developer.chrome.com/en/articles/multi-screen-window-placement/) API.
* `unknown` - An unrecognized permission request.
* `callback` Function
@@ -864,8 +862,6 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
* `openExternal` - Open links in external applications.
* `pointerLock` - Directly interpret mouse movements as an input method via the [Pointer Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API). These requests always appear to originate from the main frame.
* `serial` - Read from and write to serial devices with the [Web Serial API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API).
* `storage-access` - Allows content loaded in a third-party context to request access to third-party cookies using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
* `top-level-storage-access` - Allow top-level sites to request third-party cookie access on behalf of embedded content originating from another site in the same related website set using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
* `usb` - Expose non-standard Universal Serial Bus (USB) compatible devices services to the web with the [WebUSB API](https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API).
* `requestingOrigin` string - The origin URL of the permission check
* `details` Object - Some properties are only available on certain permission types.
@@ -1220,7 +1216,7 @@ Returns `Promise<Buffer>` - resolves with blob data.
* `url` string
* `options` Object (optional)
* `headers` Record\<string, string\> (optional) - HTTP request headers.
* `headers` Record<string, string> (optional) - HTTP request headers.
Initiates a download of the resource at `url`.
The API will generate a [DownloadItem](download-item.md) that can be accessed
@@ -1428,37 +1424,6 @@ is emitted.
Returns `string | null` - The absolute file system path where data for this
session is persisted on disk. For in memory sessions this returns `null`.
#### `ses.clearData([options])`
* `options` Object (optional)
* `dataTypes` String[] (optional) - The types of data to clear. By default, this will clear all types of data.
* `backgroundFetch` - Background Fetch
* `cache` - Cache
* `cookies` - Cookies
* `downloads` - Downloads
* `fileSystems` - File Systems
* `indexedDB` - IndexedDB
* `localStorage` - Local Storage
* `serviceWorkers` - Service Workers
* `webSQL` - WebSQL
* `origins` String[] (optional) - Clear data for only these origins. Cannot be used with `excludeOrigins`.
* `excludeOrigins` String[] (optional) - Clear data for all origins except these ones. Cannot be used with `origins`.
* `avoidClosingConnections` boolean (optional) - Skips deleting cookies that would close current network connections. (Default: `false`)
* `originMatchingMode` String (optional) - The behavior for matching data to origins.
* `third-parties-included` (default) - Storage is matched on origin in first-party contexts and top-level-site in third-party contexts.
* `origin-in-all-contexts` - Storage is matched on origin only in all contexts.
Returns `Promise<void>` - resolves when all data has been cleared.
Clears various different types of data.
This method clears more types of data and is more thourough than the
`clearStorageData` method.
**Note:** Cookies are stored at a broader scope than origins. When removing cookies and filtering by `origins` (or `excludeOrigins`), the cookies will be removed at the [registrable domain](https://url.spec.whatwg.org/#host-registrable-domain) level. For example, clearing cookies for the origin `https://really.specific.origin.example.com/` will end up clearing all cookies for `example.com`. Clearing cookies for the origin `https://my.website.example.co.uk/` will end up clearing all cookies for `example.co.uk`.
For more information, refer to Chromium's [`BrowsingDataRemover` interface](https://source.chromium.org/chromium/chromium/src/+/main:content/public/browser/browsing_data_remover.h).
### Instance Properties
The following properties are available on instances of `Session`:

View File

@@ -1,4 +1,4 @@
# FilePathWithHeaders Object
* `path` string - The path to the file to send.
* `headers` Record\<string, string\> (optional) - Additional headers to be sent.
* `headers` Record<string, string> (optional) - Additional headers to be sent.

View File

@@ -3,5 +3,5 @@
* `actionIdentifier` string - The identifier string of the action that the user selected.
* `date` number - The delivery date of the notification.
* `identifier` string - The unique identifier for this notification request.
* `userInfo` Record\<string, any\> - A dictionary of custom information associated with the notification.
* `userInfo` Record<string, any> - A dictionary of custom information associated with the notification.
* `userText` string (optional) - The text entered or chosen by the user.

View File

@@ -4,4 +4,4 @@
* `referrer` string
* `method` string
* `uploadData` [UploadData[]](upload-data.md) (optional)
* `headers` Record\<string, string\>
* `headers` Record<string, string>

View File

@@ -10,7 +10,7 @@
`"text/html"`. Setting `mimeType` would implicitly set the `content-type`
header in response, but if `content-type` is already set in `headers`, the
`mimeType` would be ignored.
* `headers` Record\<string, string | string[]\> (optional) - An object containing the response headers. The
* `headers` Record<string, string | string[]> (optional) - An object containing the response headers. The
keys must be string, and values must be either string or Array of string.
* `data` (Buffer | string | ReadableStream) (optional) - The response body. When
returning stream as response, this is a Node.js readable stream representing

View File

@@ -19,7 +19,7 @@
include in the trace. If not specified, trace all processes.
* `histogram_names` string[] (optional) - a list of [histogram][] names to report
with the trace.
* `memory_dump_config` Record\<string, any\> (optional) - if the
* `memory_dump_config` Record<string, any> (optional) - if the
`disabled-by-default-memory-infra` category is enabled, this contains
optional additional configuration for data collection. See the [Chromium
memory-infra docs][memory-infra docs] for more information.

View File

@@ -1,7 +0,0 @@
# WindowOpenHandlerResponse Object
* `action` string - Can be `allow` or `deny`. Controls whether new window should be created.
* `overrideBrowserWindowOptions` BrowserWindowConstructorOptions (optional) - Allows customization of the created window.
* `outlivesOpener` boolean (optional) - By default, child windows are closed when their opener is closed. This can be
changed by specifying `outlivesOpener: true`, in which case the opened window will not be closed when its opener is closed.
* `createWindow` (options: BrowserWindowConstructorOptions) => WebContents (optional) - If specified, will be called instead of `new BrowserWindow` to create the new child window and event [`did-create-window`](../web-contents.md#event-did-create-window) will not be emitted. Constructed child window should use passed `options` object. This can be used for example to have the new window open as a BrowserView instead of in a separate window.

View File

@@ -36,7 +36,7 @@ Returns `boolean` - Whether the Swipe between pages setting is on.
### `systemPreferences.postNotification(event, userInfo[, deliverImmediately])` _macOS_
* `event` string
* `userInfo` Record\<string, any\>
* `userInfo` Record<string, any>
* `deliverImmediately` boolean (optional) - `true` to post notifications immediately even when the subscribing app is inactive.
Posts `event` as native notifications of macOS. The `userInfo` is an Object
@@ -45,7 +45,7 @@ that contains the user information dictionary sent along with the notification.
### `systemPreferences.postLocalNotification(event, userInfo)` _macOS_
* `event` string
* `userInfo` Record\<string, any\>
* `userInfo` Record<string, any>
Posts `event` as native notifications of macOS. The `userInfo` is an Object
that contains the user information dictionary sent along with the notification.
@@ -53,7 +53,7 @@ that contains the user information dictionary sent along with the notification.
### `systemPreferences.postWorkspaceNotification(event, userInfo)` _macOS_
* `event` string
* `userInfo` Record\<string, any\>
* `userInfo` Record<string, any>
Posts `event` as native notifications of macOS. The `userInfo` is an Object
that contains the user information dictionary sent along with the notification.
@@ -63,7 +63,7 @@ that contains the user information dictionary sent along with the notification.
* `event` string | null
* `callback` Function
* `event` string
* `userInfo` Record\<string, unknown\>
* `userInfo` Record<string, unknown>
* `object` string
Returns `number` - The ID of this subscription
@@ -92,7 +92,7 @@ If `event` is null, the `NSDistributedNotificationCenter` doesnt use it as cr
* `event` string | null
* `callback` Function
* `event` string
* `userInfo` Record\<string, unknown\>
* `userInfo` Record<string, unknown>
* `object` string
Returns `number` - The ID of this subscription
@@ -107,7 +107,7 @@ If `event` is null, the `NSNotificationCenter` doesnt use it as criteria for
* `event` string | null
* `callback` Function
* `event` string
* `userInfo` Record\<string, unknown\>
* `userInfo` Record<string, unknown>
* `object` string
Returns `number` - The ID of this subscription
@@ -137,7 +137,7 @@ Same as `unsubscribeNotification`, but removes the subscriber from `NSWorkspace.
### `systemPreferences.registerDefaults(defaults)` _macOS_
* `defaults` Record\<string, string | boolean | number\> - a dictionary of (`key: value`) user defaults
* `defaults` Record<string, string | boolean | number> - a dictionary of (`key: value`) user defaults
Add the specified defaults to your application's `NSUserDefaults`.

View File

@@ -237,7 +237,7 @@ See [`window.open()`](window-open.md) for more details and how to use this in co
Returns:
* `details` Event\<\>
* `details` Event<>
* `url` string - The URL the frame is navigating to.
* `isSameDocument` boolean - This event does not fire for same document navigations using window.history api and reference fragment navigations.
This property is always set to `false` for this event.
@@ -270,7 +270,7 @@ Calling `event.preventDefault()` will prevent the navigation.
Returns:
* `details` Event\<\>
* `details` Event<>
* `url` string - The URL the frame is navigating to.
* `isSameDocument` boolean - This event does not fire for same document navigations using window.history api and reference fragment navigations.
This property is always set to `false` for this event.
@@ -300,7 +300,7 @@ Calling `event.preventDefault()` will prevent the navigation.
Returns:
* `details` Event\<\>
* `details` Event<>
* `url` string - The URL the frame is navigating to.
* `isSameDocument` boolean - Whether the navigation happened without changing
document. Examples of same document navigations are reference fragment
@@ -324,7 +324,7 @@ Emitted when any frame (including main) starts navigating.
Returns:
* `details` Event\<\>
* `details` Event<>
* `url` string - The URL the frame is navigating to.
* `isSameDocument` boolean - Whether the navigation happened without changing
document. Examples of same document navigations are reference fragment
@@ -355,7 +355,7 @@ redirect).
Returns:
* `details` Event\<\>
* `details` Event<>
* `url` string - The URL the frame is navigating to.
* `isSameDocument` boolean - Whether the navigation happened without changing
document. Examples of same document navigations are reference fragment
@@ -683,7 +683,7 @@ Emitted when media is paused or done playing.
Returns:
* `event` Event\<\>
* `event` Event<>
* `audible` boolean - True if one or more frames or child `webContents` are emitting audio.
Emitted when media becomes audible or inaudible.
@@ -900,7 +900,7 @@ Returns:
* `webPreferences` [WebPreferences](structures/web-preferences.md) - The web preferences that will be used by the guest
page. This object can be modified to adjust the preferences for the guest
page.
* `params` Record\<string, string\> - The other `<webview>` parameters such as the `src` URL.
* `params` Record<string, string> - The other `<webview>` parameters such as the `src` URL.
This object can be modified to adjust the parameters of the guest page.
Emitted when a `<webview>`'s web contents is being attached to this web
@@ -1020,7 +1020,7 @@ win.webContents.loadURL('https://github.com', options)
* `filePath` string
* `options` Object (optional)
* `query` Record\<string, string\> (optional) - Passed to `url.format()`.
* `query` Record<string, string> (optional) - Passed to `url.format()`.
* `search` string (optional) - Passed to `url.format()`.
* `hash` string (optional) - Passed to `url.format()`.
@@ -1051,7 +1051,7 @@ win.loadFile('src/index.html')
* `url` string
* `options` Object (optional)
* `headers` Record\<string, string\> (optional) - HTTP request headers.
* `headers` Record<string, string> (optional) - HTTP request headers.
Initiates a download of the resource at `url` without navigating. The
`will-download` event of `session` will be triggered.
@@ -1288,7 +1288,7 @@ Ignore application menu shortcuts while this web contents is focused.
#### `contents.setWindowOpenHandler(handler)`
* `handler` Function\<[WindowOpenHandlerResponse](structures/window-open-handler-response.md)\>
* `handler` Function<{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}>
* `details` Object
* `url` string - The _resolved_ version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
* `frameName` string - Name of the window provided in `window.open()`
@@ -1303,8 +1303,11 @@ Ignore application menu shortcuts while this web contents is focused.
be set. If no post data is to be sent, the value will be `null`. Only defined
when the window is being created by a form that set `target=_blank`.
Returns `WindowOpenHandlerResponse` - When set to `{ action: 'deny' }` cancels the creation of the new
window. `{ action: 'allow' }` will allow the new window to be created.
Returns `{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new
window. `allow` will allow the new window to be created. Specifying `overrideBrowserWindowOptions` allows customization of the created window.
By default, child windows are closed when their opener is closed. This can be
changed by specifying `outlivesOpener: true`, in which case the opened window
will not be closed when its opener is closed.
Returning an unrecognized value such as a null, undefined, or an object
without a recognized 'action' value will result in a console error and have
the same effect as returning `{action: 'deny'}`.
@@ -1315,26 +1318,6 @@ submitting a form with `<form target="_blank">`. See
[`window.open()`](window-open.md) for more details and how to use this in
conjunction with `did-create-window`.
An example showing how to customize the process of new `BrowserWindow` creation to be `BrowserView` attached to main window instead:
```js
const { BrowserView, BrowserWindow } = require('electron')
const mainWindow = new BrowserWindow()
mainWindow.webContents.setWindowOpenHandler((details) => {
return {
action: 'allow',
createWindow: (options) => {
const browserView = new BrowserView(options)
mainWindow.addBrowserView(browserView)
browserView.setBounds({ x: 0, y: 0, width: 640, height: 480 })
return browserView.webContents
}
}
})
```
#### `contents.setAudioMuted(muted)`
* `muted` boolean
@@ -1583,7 +1566,7 @@ Returns `Promise<PrinterInfo[]>` - Resolves with a [`PrinterInfo[]`](structures/
* `from` number - Index of the first page to print (0-based).
* `to` number - Index of the last page to print (inclusive) (0-based).
* `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
* `dpi` Record\<string, number\> (optional)
* `dpi` Record<string, number> (optional)
* `horizontal` number (optional) - The horizontal dpi.
* `vertical` number (optional) - The vertical dpi.
* `header` string (optional) - string to be printed as page header.
@@ -2223,10 +2206,6 @@ A `Integer` representing the unique ID of this WebContents. Each ID is unique am
A [`Session`](session.md) used by this webContents.
#### `contents.navigationHistory` _Readonly_
A [`NavigationHistory`](navigation-history.md) used by this webContents.
#### `contents.hostWebContents` _Readonly_
A [`WebContents`](web-contents.md) instance that might own this `WebContents`.

View File

@@ -99,11 +99,11 @@ Some examples of valid `urls`:
* `referrer` string
* `timestamp` Double
* `uploadData` [UploadData[]](structures/upload-data.md) (optional)
* `requestHeaders` Record\<string, string\>
* `requestHeaders` Record<string, string>
* `callback` Function
* `beforeSendResponse` Object
* `cancel` boolean (optional)
* `requestHeaders` Record\<string, string | string[]\> (optional) - When provided, request will be made
* `requestHeaders` Record<string, string | string[]> (optional) - When provided, request will be made
with these headers.
The `listener` will be called with `listener(details, callback)` before sending
@@ -126,7 +126,7 @@ The `callback` has to be called with a `response` object.
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
* `referrer` string
* `timestamp` Double
* `requestHeaders` Record\<string, string\>
* `requestHeaders` Record<string, string>
The `listener` will be called with `listener(details)` just before a request is
going to be sent to the server, modifications of previous `onBeforeSendHeaders`
@@ -148,11 +148,11 @@ response are visible by the time this listener is fired.
* `timestamp` Double
* `statusLine` string
* `statusCode` Integer
* `responseHeaders` Record\<string, string[]\> (optional)
* `responseHeaders` Record<string, string[]> (optional)
* `callback` Function
* `headersReceivedResponse` Object
* `cancel` boolean (optional)
* `responseHeaders` Record\<string, string | string[]\> (optional) - When provided, the server is assumed
* `responseHeaders` Record<string, string | string[]> (optional) - When provided, the server is assumed
to have responded with these headers.
* `statusLine` string (optional) - Should be provided when overriding
`responseHeaders` to change header status otherwise original response
@@ -177,7 +177,7 @@ The `callback` has to be called with a `response` object.
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
* `referrer` string
* `timestamp` Double
* `responseHeaders` Record\<string, string[]\> (optional)
* `responseHeaders` Record<string, string[]> (optional)
* `fromCache` boolean - Indicates whether the response was fetched from disk
cache.
* `statusCode` Integer
@@ -207,7 +207,7 @@ and response headers are available.
* `ip` string (optional) - The server IP address that the request was
actually sent to.
* `fromCache` boolean
* `responseHeaders` Record\<string, string[]\> (optional)
* `responseHeaders` Record<string, string[]> (optional)
The `listener` will be called with `listener(details)` when a server initiated
redirect is about to occur.
@@ -226,7 +226,7 @@ redirect is about to occur.
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
* `referrer` string
* `timestamp` Double
* `responseHeaders` Record\<string, string[]\> (optional)
* `responseHeaders` Record<string, string[]> (optional)
* `fromCache` boolean
* `statusCode` Integer
* `statusLine` string

View File

@@ -287,7 +287,7 @@ e.g. the `http://` or `file://`.
* `url` string
* `options` Object (optional)
* `headers` Record\<string, string\> (optional) - HTTP request headers.
* `headers` Record<string, string> (optional) - HTTP request headers.
Initiates a download of the resource at `url` without navigating.
@@ -580,7 +580,7 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
* `from` number - Index of the first page to print (0-based).
* `to` number - Index of the last page to print (inclusive) (0-based).
* `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
* `dpi` Record\<string, number\> (optional)
* `dpi` Record<string, number> (optional)
* `horizontal` number (optional) - The horizontal dpi.
* `vertical` number (optional) - The vertical dpi.
* `header` string (optional) - string to be printed as page header.

View File

@@ -1686,7 +1686,7 @@ folder
└── file3
```
In Electron &lt;=6, this would return a `FileList` with a `File` object for:
In Electron <=6, this would return a `FileList` with a `File` object for:
```console
path/to/folder

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

@@ -234,7 +234,7 @@ Notification) whereas camelCase modules are not instantiable (e.g. app, ipcRende
<details><summary>Typed import aliases</summary>
For better type checking when writing TypeScript code, you can choose to import
main process modules from `electron/main`.
main process modules from <code>electron/main</code>.
```js
const { app, BrowserWindow } = require('electron/main')

View File

@@ -34,7 +34,6 @@ auto_filenames = {
"docs/api/message-port-main.md",
"docs/api/native-image.md",
"docs/api/native-theme.md",
"docs/api/navigation-history.md",
"docs/api/net-log.md",
"docs/api/net.md",
"docs/api/notification.md",
@@ -145,7 +144,6 @@ auto_filenames = {
"docs/api/structures/web-preferences.md",
"docs/api/structures/web-request-filter.md",
"docs/api/structures/web-source.md",
"docs/api/structures/window-open-handler-response.md",
]
sandbox_bundle_deps = [

View File

@@ -155,8 +155,12 @@ filenames = {
"shell/browser/osr/osr_web_contents_view_mac.mm",
"shell/browser/relauncher_mac.cc",
"shell/browser/ui/certificate_trust_mac.mm",
"shell/browser/ui/cocoa/delayed_native_view_host.h",
"shell/browser/ui/cocoa/delayed_native_view_host.mm",
"shell/browser/ui/cocoa/electron_bundle_mover.h",
"shell/browser/ui/cocoa/electron_bundle_mover.mm",
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h",
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm",
"shell/browser/ui/cocoa/electron_menu_controller.h",
"shell/browser/ui/cocoa/electron_menu_controller.mm",
"shell/browser/ui/cocoa/electron_native_widget_mac.h",
@@ -183,6 +187,8 @@ filenames = {
"shell/browser/ui/cocoa/window_buttons_proxy.mm",
"shell/browser/ui/drag_util_mac.mm",
"shell/browser/ui/file_dialog_mac.mm",
"shell/browser/ui/inspectable_web_contents_view_mac.h",
"shell/browser/ui/inspectable_web_contents_view_mac.mm",
"shell/browser/ui/message_box_mac.mm",
"shell/browser/ui/tray_icon_cocoa.h",
"shell/browser/ui/tray_icon_cocoa.mm",
@@ -198,7 +204,6 @@ filenames = {
"shell/common/node_bindings_mac.cc",
"shell/common/node_bindings_mac.h",
"shell/common/platform_util_mac.mm",
"shell/browser/ui/views/inspectable_web_contents_view_mac.mm",
]
lib_sources_views = [
@@ -213,6 +218,8 @@ filenames = {
"shell/browser/ui/views/electron_views_delegate.h",
"shell/browser/ui/views/frameless_view.cc",
"shell/browser/ui/views/frameless_view.h",
"shell/browser/ui/views/inspectable_web_contents_view_views.cc",
"shell/browser/ui/views/inspectable_web_contents_view_views.h",
"shell/browser/ui/views/menu_bar.cc",
"shell/browser/ui/views/menu_bar.h",
"shell/browser/ui/views/menu_delegate.cc",
@@ -583,8 +590,6 @@ filenames = {
"shell/common/gin_converters/hid_device_info_converter.h",
"shell/common/gin_converters/image_converter.cc",
"shell/common/gin_converters/image_converter.h",
"shell/common/gin_converters/login_item_settings_converter.cc",
"shell/common/gin_converters/login_item_settings_converter.h",
"shell/common/gin_converters/media_converter.cc",
"shell/common/gin_converters/media_converter.h",
"shell/common/gin_converters/message_box_converter.cc",

View File

@@ -433,15 +433,14 @@ WebContents.prototype.loadURL = function (url, options) {
return p;
};
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => Electron.WindowOpenHandlerResponse) {
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, outlivesOpener?: boolean})) {
this._windowOpenHandler = handler;
};
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, outlivesOpener: boolean, createWindow?: Electron.CreateWindowFunction} {
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, outlivesOpener: boolean} {
const defaultResponse = {
browserWindowConstructorOptions: null,
outlivesOpener: false,
createWindow: undefined
outlivesOpener: false
};
if (!this._windowOpenHandler) {
return defaultResponse;
@@ -467,8 +466,7 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event,
} else if (response.action === 'allow') {
return {
browserWindowConstructorOptions: typeof response.overrideBrowserWindowOptions === 'object' ? response.overrideBrowserWindowOptions : null,
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false,
createWindow: typeof response.createWindow === 'function' ? response.createWindow : undefined
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false
};
} else {
event.preventDefault();
@@ -533,17 +531,6 @@ WebContents.prototype._init = function () {
enumerable: true
});
// Add navigationHistory property which handles session history,
// maintaining a list of navigation entries for backward and forward navigation.
Object.defineProperty(this, 'navigationHistory', {
value: {
getActiveIndex: this._getActiveIndex.bind(this),
length: this._historyLength.bind(this),
getEntryAtIndex: this._getNavigationEntryAtIndex.bind(this)
},
writable: false
});
// Dispatch IPC messages to the ipc module.
this.on('-ipc-message' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
addSenderToEvent(event, this);
@@ -666,16 +653,13 @@ WebContents.prototype._init = function () {
postData,
overrideBrowserWindowOptions: options || {},
windowOpenArgs: details,
outlivesOpener: result.outlivesOpener,
createWindow: result.createWindow
outlivesOpener: result.outlivesOpener
});
}
});
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
let windowOpenOutlivesOpenerOption: boolean = false;
let createWindow: Electron.CreateWindowFunction | undefined;
this.on('-will-add-new-contents' as any, (event: Electron.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => {
const postBody = postData ? {
data: postData,
@@ -700,7 +684,6 @@ WebContents.prototype._init = function () {
windowOpenOutlivesOpenerOption = result.outlivesOpener;
windowOpenOverriddenOptions = result.browserWindowConstructorOptions;
createWindow = result.createWindow;
if (!event.defaultPrevented) {
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
// Allow setting of backgroundColor as a webPreference even though
@@ -730,9 +713,6 @@ WebContents.prototype._init = function () {
referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => {
const overriddenOptions = windowOpenOverriddenOptions || undefined;
const outlivesOpener = windowOpenOutlivesOpenerOption;
const windowOpenFunction = createWindow;
createWindow = undefined;
windowOpenOverriddenOptions = null;
// false is the default
windowOpenOutlivesOpenerOption = false;
@@ -755,8 +735,7 @@ WebContents.prototype._init = function () {
frameName,
features: rawFeatures
},
outlivesOpener,
createWindow: windowOpenFunction
outlivesOpener
});
});
}

View File

@@ -16,16 +16,16 @@ export type WindowOpenArgs = {
features: string,
}
const frameNamesToWindow = new Map<string, WebContents>();
const registerFrameNameToGuestWindow = (name: string, webContents: WebContents) => frameNamesToWindow.set(name, webContents);
const frameNamesToWindow = new Map<string, BrowserWindow>();
const registerFrameNameToGuestWindow = (name: string, win: BrowserWindow) => frameNamesToWindow.set(name, win);
const unregisterFrameName = (name: string) => frameNamesToWindow.delete(name);
const getGuestWebContentsByFrameName = (name: string) => frameNamesToWindow.get(name);
const getGuestWindowByFrameName = (name: string) => frameNamesToWindow.get(name);
/**
* `openGuestWindow` is called to create and setup event handling for the new
* window.
*/
export function openGuestWindow ({ embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener, createWindow }: {
export function openGuestWindow ({ embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener }: {
embedder: WebContents,
guest?: WebContents,
referrer: Referrer,
@@ -34,8 +34,7 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
overrideBrowserWindowOptions?: BrowserWindowConstructorOptions,
windowOpenArgs: WindowOpenArgs,
outlivesOpener: boolean,
createWindow?: Electron.CreateWindowFunction
}): void {
}): BrowserWindow | undefined {
const { url, frameName, features } = windowOpenArgs;
const { options: parsedOptions } = parseFeatures(features);
const browserWindowOptions = {
@@ -49,42 +48,17 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
// To spec, subsequent window.open calls with the same frame name (`target` in
// spec parlance) will reuse the previous window.
// https://html.spec.whatwg.org/multipage/window-object.html#apis-for-creating-and-navigating-browsing-contexts-by-name
const existingWebContents = getGuestWebContentsByFrameName(frameName);
if (existingWebContents) {
if (existingWebContents.isDestroyed()) {
const existingWindow = getGuestWindowByFrameName(frameName);
if (existingWindow) {
if (existingWindow.isDestroyed() || existingWindow.webContents.isDestroyed()) {
// FIXME(t57ser): The webContents is destroyed for some reason, unregister the frame name
unregisterFrameName(frameName);
} else {
existingWebContents.loadURL(url);
return;
existingWindow.loadURL(url);
return existingWindow;
}
}
if (createWindow) {
const webContents = createWindow({
webContents: guest,
...browserWindowOptions
});
if (guest != null) {
if (webContents !== guest) {
throw new Error('Invalid webContents. Created window should be connected to webContents passed with options object.');
}
webContents.loadURL(url, {
httpReferrer: referrer,
...(postData && {
postData,
extraHeaders: formatPostDataHeaders(postData as Electron.UploadRawData[])
})
});
handleWindowLifecycleEvents({ embedder, frameName, guest, outlivesOpener });
}
return;
}
const window = new BrowserWindow({
webContents: guest,
...browserWindowOptions
@@ -103,9 +77,11 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
});
}
handleWindowLifecycleEvents({ embedder, frameName, guest: window.webContents, outlivesOpener });
handleWindowLifecycleEvents({ embedder, frameName, guest: window, outlivesOpener });
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData });
return window;
}
/**
@@ -116,12 +92,12 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
*/
const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outlivesOpener }: {
embedder: WebContents,
guest: WebContents,
guest: BrowserWindow,
frameName: string,
outlivesOpener: boolean
}) {
const closedByEmbedder = function () {
guest.removeListener('destroyed', closedByUser);
guest.removeListener('closed', closedByUser);
guest.destroy();
};
@@ -134,11 +110,11 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outl
if (!outlivesOpener) {
embedder.once('current-render-view-deleted' as any, closedByEmbedder);
}
guest.once('destroyed', closedByUser);
guest.once('closed', closedByUser);
if (frameName) {
registerFrameNameToGuestWindow(frameName, guest);
guest.once('destroyed', function () {
guest.once('closed', function () {
unregisterFrameName(frameName);
});
}

View File

@@ -209,22 +209,6 @@ type ExtraURLLoaderOptions = {
headers: Record<string, { name: string, value: string | string[] }>;
allowNonHttpProtocols: boolean;
}
function validateHeader (name: any, value: any): void {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)');
}
if (value == null) {
throw new Error('`value` required in setHeader("' + name + '", value)');
}
if (!isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`);
}
if (!isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
}
function parseOptions (optionsIn: ClientRequestConstructorOptions | string): NodeJS.CreateURLLoaderOptions & ExtraURLLoaderOptions {
// eslint-disable-next-line node/no-deprecated-api
const options: any = typeof optionsIn === 'string' ? url.parse(optionsIn) : { ...optionsIn };
@@ -291,7 +275,12 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
};
const headers: Record<string, string | string[]> = options.headers || {};
for (const [name, value] of Object.entries(headers)) {
validateHeader(name, value);
if (!isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`);
}
if (!isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
const key = name.toLowerCase();
urlLoaderOptions.headers[key] = { name, value };
}
@@ -362,10 +351,21 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
}
setHeader (name: string, value: string) {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)');
}
if (value == null) {
throw new Error('`value` required in setHeader("' + name + '", value)');
}
if (this._started || this._firstWrite) {
throw new Error('Can\'t set headers after they are sent');
}
validateHeader(name, value);
if (!isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`);
}
if (!isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
const key = name.toLowerCase();
this._urlLoaderOptions.headers[key] = { name, value };

View File

@@ -1,5 +1,5 @@
import { Buffer } from 'buffer';
import { Dirent, constants } from 'fs';
import { constants } from 'fs';
import * as path from 'path';
import * as util from 'util';
@@ -46,17 +46,7 @@ process._getOrCreateArchive = getOrCreateArchive;
const asarRe = /\.asar/i;
const {
getValidatedPath,
getOptions,
getDirent
} = __non_webpack_require__('internal/fs/utils');
const {
validateBoolean,
validateFunction
} = __non_webpack_require__('internal/validators');
const { getValidatedPath } = __non_webpack_require__('internal/fs/utils');
// In the renderer node internals use the node global URL but we do not set that to be
// the global URL instance. We need to do instanceof checks against the internal URL impl
const { URL: NodeURL } = __non_webpack_require__('internal/url');
@@ -88,23 +78,6 @@ const gid = process.getgid?.() ?? 0;
const fakeTime = new Date();
function getDirents (p: string, { 0: names, 1: types }: any[][]): Dirent[] {
for (let i = 0; i < names.length; i++) {
let type = types[i];
const info = splitPath(path.join(p, names[i]));
if (info.isAsar) {
const archive = getOrCreateArchive(info.asarPath);
if (!archive) continue;
const stats = archive.stat(info.filePath);
if (!stats) continue;
type = stats.type;
}
names[i] = getDirent(p, names[i], type);
}
return names;
}
enum AsarFileType {
kFile = (constants as any).UV_DIRENT_FILE,
kDirectory = (constants as any).UV_DIRENT_DIR,
@@ -689,27 +662,13 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
return (encoding) ? buffer.toString(encoding) : buffer;
};
type ReaddirOptions = { encoding: BufferEncoding | null; withFileTypes?: false, recursive?: false } | undefined | null;
type ReaddirCallback = (err: NodeJS.ErrnoException | null, files: string[]) => void;
const { readdir } = fs;
fs.readdir = function (pathArgument: string, options: ReaddirOptions, callback: ReaddirCallback) {
callback = typeof options === 'function' ? options : callback;
validateFunction(callback, 'callback');
options = getOptions(options);
pathArgument = getValidatedPath(pathArgument);
if (options?.recursive != null) {
validateBoolean(options?.recursive, 'options.recursive');
}
if (options?.recursive) {
nextTick(callback!, [null, readdirSyncRecursive(pathArgument, options)]);
return;
}
fs.readdir = function (pathArgument: string, options?: { encoding?: string | null; withFileTypes?: boolean } | null, callback?: Function) {
const pathInfo = splitPath(pathArgument);
if (typeof options === 'function') {
callback = options;
options = undefined;
}
if (!pathInfo.isAsar) return readdir.apply(this, arguments);
const { asarPath, filePath } = pathInfo;
@@ -746,62 +705,12 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
nextTick(callback!, [null, files]);
};
const { readdir: readdirPromise } = require('fs').promises;
fs.promises.readdir = async function (pathArgument: string, options: ReaddirOptions) {
options = getOptions(options);
pathArgument = getValidatedPath(pathArgument);
fs.promises.readdir = util.promisify(fs.readdir);
if (options?.recursive != null) {
validateBoolean(options?.recursive, 'options.recursive');
}
if (options?.recursive) {
return readdirRecursive(pathArgument, options);
}
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) return readdirPromise(pathArgument, options);
const { asarPath, filePath } = pathInfo;
const archive = getOrCreateArchive(asarPath);
if (!archive) {
return Promise.reject(createError(AsarError.INVALID_ARCHIVE, { asarPath }));
}
const files = archive.readdir(filePath);
if (!files) {
return Promise.reject(createError(AsarError.NOT_FOUND, { asarPath, filePath }));
}
if (options?.withFileTypes) {
const dirents = [];
for (const file of files) {
const childPath = path.join(filePath, file);
const stats = archive.stat(childPath);
if (!stats) {
throw createError(AsarError.NOT_FOUND, { asarPath, filePath: childPath });
}
dirents.push(new fs.Dirent(file, stats.type));
}
return Promise.resolve(dirents);
}
return Promise.resolve(files);
};
type ReaddirSyncOptions = { encoding: BufferEncoding | null; withFileTypes?: false };
const { readdirSync } = fs;
fs.readdirSync = function (pathArgument: string, options: ReaddirOptions) {
options = getOptions(options);
pathArgument = getValidatedPath(pathArgument);
if (options?.recursive != null) {
validateBoolean(options?.recursive, 'options.recursive');
}
if (options?.recursive) {
return readdirSyncRecursive(pathArgument, options);
}
fs.readdirSync = function (pathArgument: string, options: ReaddirSyncOptions | BufferEncoding | null) {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) return readdirSync.apply(this, arguments);
const { asarPath, filePath } = pathInfo;
@@ -816,7 +725,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
}
if (options?.withFileTypes) {
if (options && (options as ReaddirSyncOptions).withFileTypes) {
const dirents = [];
for (const file of files) {
const childPath = path.join(filePath, file);
@@ -832,8 +741,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
return files;
};
const binding = internalBinding('fs');
const { internalModuleReadJSON, kUsePromises } = binding;
const { internalModuleReadJSON } = internalBinding('fs');
internalBinding('fs').internalModuleReadJSON = (pathArgument: string) => {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) return internalModuleReadJSON(pathArgument);
@@ -879,187 +787,6 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
return (stats.type === AsarFileType.kDirectory) ? 1 : 0;
};
async function readdirRecursive (originalPath: string, options: ReaddirOptions) {
const result: any[] = [];
const pathInfo = splitPath(originalPath);
let queue: [string, string[]][] = [];
const withFileTypes = Boolean(options?.withFileTypes);
let initialItem = [];
if (pathInfo.isAsar) {
const archive = getOrCreateArchive(pathInfo.asarPath);
if (!archive) return result;
const files = archive.readdir(pathInfo.filePath);
if (!files) return result;
// If we're in an asar dir, we need to ensure the result is in the same format as the
// native call to readdir withFileTypes i.e. an array of arrays.
initialItem = files;
if (withFileTypes) {
initialItem = [
[...initialItem], initialItem.map((p: string) => {
return internalBinding('fs').internalModuleStat(path.join(originalPath, p));
})
];
}
} else {
initialItem = await binding.readdir(
path.toNamespacedPath(originalPath),
options!.encoding,
withFileTypes,
kUsePromises
);
}
queue = [[originalPath, initialItem]];
if (withFileTypes) {
while (queue.length > 0) {
// @ts-expect-error this is a valid array destructure assignment.
const { 0: pathArg, 1: readDir } = queue.pop();
for (const dirent of getDirents(pathArg, readDir)) {
result.push(dirent);
if (dirent.isDirectory()) {
const direntPath = path.join(pathArg, dirent.name);
const info = splitPath(direntPath);
let readdirResult;
if (info.isAsar) {
const archive = getOrCreateArchive(info.asarPath);
if (!archive) continue;
const files = archive.readdir(info.filePath);
if (!files) continue;
readdirResult = [
[...files], files.map((p: string) => {
return internalBinding('fs').internalModuleStat(path.join(direntPath, p));
})
];
} else {
readdirResult = await binding.readdir(
direntPath,
options!.encoding,
true,
kUsePromises
);
}
queue.push([direntPath, readdirResult]);
}
}
}
} else {
while (queue.length > 0) {
// @ts-expect-error this is a valid array destructure assignment.
const { 0: pathArg, 1: readDir } = queue.pop();
for (const ent of readDir) {
const direntPath = path.join(pathArg, ent);
const stat = internalBinding('fs').internalModuleStat(direntPath);
result.push(path.relative(originalPath, direntPath));
if (stat === 1) {
const subPathInfo = splitPath(direntPath);
let item = [];
if (subPathInfo.isAsar) {
const archive = getOrCreateArchive(subPathInfo.asarPath);
if (!archive) return;
const files = archive.readdir(subPathInfo.filePath);
if (!files) return result;
item = files;
} else {
item = await binding.readdir(
path.toNamespacedPath(direntPath),
options!.encoding,
false,
kUsePromises
);
}
queue.push([direntPath, item]);
}
}
}
}
return result;
}
function readdirSyncRecursive (basePath: string, options: ReaddirOptions) {
const withFileTypes = Boolean(options!.withFileTypes);
const encoding = options!.encoding;
const readdirResults: string[] = [];
const pathsQueue = [basePath];
function read (pathArg: string) {
let readdirResult;
const pathInfo = splitPath(pathArg);
if (pathInfo.isAsar) {
const { asarPath, filePath } = pathInfo;
const archive = getOrCreateArchive(asarPath);
if (!archive) return;
readdirResult = archive.readdir(filePath);
if (!readdirResult) return;
// If we're in an asar dir, we need to ensure the result is in the same format as the
// native call to readdir withFileTypes i.e. an array of arrays.
if (withFileTypes) {
readdirResult = [
[...readdirResult], readdirResult.map((p: string) => {
return internalBinding('fs').internalModuleStat(path.join(pathArg, p));
})
];
}
} else {
readdirResult = binding.readdir(
path.toNamespacedPath(pathArg),
encoding,
withFileTypes
);
}
if (readdirResult === undefined) return;
if (withFileTypes) {
const length = readdirResult[0].length;
for (let i = 0; i < length; i++) {
const resultPath = path.join(pathArg, readdirResult[0][i]);
const info = splitPath(resultPath);
let type = readdirResult[1][i];
if (info.isAsar) {
const archive = getOrCreateArchive(info.asarPath);
if (!archive) return;
const stats = archive.stat(info.filePath);
if (!stats) continue;
type = stats.type;
}
const dirent = getDirent(pathArg, readdirResult[0][i], type);
readdirResults.push(dirent);
if (dirent.isDirectory()) {
pathsQueue.push(path.join(dirent.path, dirent.name));
}
}
} else {
for (let i = 0; i < readdirResult.length; i++) {
const resultPath = path.join(pathArg, readdirResult[i]);
const relativeResultPath = path.relative(basePath, resultPath);
const stat = internalBinding('fs').internalModuleStat(resultPath);
readdirResults.push(relativeResultPath);
if (stat === 1) pathsQueue.push(resultPath);
}
}
}
for (let i = 0; i < pathsQueue.length; i++) {
read(pathsQueue[i]);
}
return readdirResults;
}
// Calling mkdir for directory inside asar archive should throw ENOTDIR
// error, but on Windows it throws ENOENT.
if (process.platform === 'win32') {

View File

@@ -9,7 +9,7 @@
"@electron/docs-parser": "^1.2.0",
"@electron/fiddle-core": "^1.0.4",
"@electron/github-app-auth": "^2.0.0",
"@electron/lint-roller": "^1.12.1",
"@electron/lint-roller": "^1.9.0",
"@electron/typescript-definitions": "^8.15.2",
"@octokit/rest": "^19.0.7",
"@primer/octicons": "^10.0.0",
@@ -49,7 +49,7 @@
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-unicorn": "^46.0.1",
"events": "^3.2.0",
"express": "^4.19.2",
"express": "^4.16.4",
"folder-hash": "^2.1.1",
"fs-extra": "^9.0.1",
"got": "^11.8.5",

View File

@@ -33,6 +33,7 @@ fix_assert_module_in_the_renderer_process.patch
fix_add_trusted_space_and_trusted_lo_space_to_the_v8_heap.patch
win_process_avoid_assert_after_spawning_store_app_4152.patch
chore_remove_use_of_deprecated_kmaxlength.patch
fix_missing_include_for_node_extern.patch
feat_optionally_prevent_calling_v8_enablewebassemblytraphandler.patch
build_only_create_cppgc_heap_on_non-32_bit_platforms.patch
fix_-wshadow_error_in_uvwasi_c.patch
@@ -46,4 +47,3 @@ build_ensure_v8_pointer_compression_sandbox_is_enabled_on_64bit.patch
fix_revert_src_lb_reducing_c_calls_of_esm_legacy_main_resolve.patch
src_preload_function_for_environment.patch
deprecate_vector_v8_local_in_v8.patch
fs_fix_wtf-8_decoding_issue.patch

View File

@@ -87,18 +87,10 @@ index 895ff3a5948add3513700ecc2f32fce4c2fbe4eb..3182a5e4aad2ba0be2b6769edb696b81
MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
diff --git a/src/module_wrap.h b/src/module_wrap.h
index e17048357feca2419087621ed280de30882a90bc..63682be31ce00a3bf7b9be909cac4b7f9ec02a8e 100644
index e17048357feca2419087621ed280de30882a90bc..061117dc3182d63e35d7e99ffd95801f96356322 100644
--- a/src/module_wrap.h
+++ b/src/module_wrap.h
@@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "base_object.h"
+#include "node.h"
namespace node {
@@ -31,7 +32,14 @@ enum HostDefinedOptions : int {
@@ -31,7 +31,14 @@ enum HostDefinedOptions : int {
kLength = 9,
};
@@ -114,7 +106,7 @@ index e17048357feca2419087621ed280de30882a90bc..63682be31ce00a3bf7b9be909cac4b7f
public:
enum InternalFields {
kModuleSlot = BaseObject::kInternalFieldCount,
@@ -68,6 +76,8 @@ class ModuleWrap : public BaseObject {
@@ -68,6 +75,8 @@ class ModuleWrap : public BaseObject {
return true;
}
@@ -123,7 +115,7 @@ index e17048357feca2419087621ed280de30882a90bc..63682be31ce00a3bf7b9be909cac4b7f
private:
ModuleWrap(Realm* realm,
v8::Local<v8::Object> object,
@@ -102,7 +112,6 @@ class ModuleWrap : public BaseObject {
@@ -102,7 +111,6 @@ class ModuleWrap : public BaseObject {
v8::Local<v8::String> specifier,
v8::Local<v8::FixedArray> import_attributes,
v8::Local<v8::Module> referrer);

View File

@@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Wed, 15 Nov 2023 12:25:39 +0100
Subject: fix: missing include for NODE_EXTERN
At some point it seems that node.h was removed from the include chain,
causing the following error:
../../third_party/electron_node/src/module_wrap.h:33:1: error: unknown type name 'NODE_EXTERN'
33 | NODE_EXTERN v8::MaybeLocal<v8::Promise> ImportModuleDynamically(
| ^
This should be upstreamed.
diff --git a/src/module_wrap.h b/src/module_wrap.h
index 061117dc3182d63e35d7e99ffd95801f96356322..63682be31ce00a3bf7b9be909cac4b7f9ec02a8e 100644
--- a/src/module_wrap.h
+++ b/src/module_wrap.h
@@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "base_object.h"
+#include "node.h"
namespace node {

View File

@@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Richard Lau <rlau@redhat.com>
Date: Fri, 1 Mar 2024 19:15:40 +0000
Subject: fs: fix WTF-8 decoding issue
Cherry-pick of libuv/libuv@d09441c
Refs: https://github.com/libuv/libuv/pull/2970
Fixes: https://github.com/nodejs/node/issues/48673
We forgot to mask off the high bits from the first byte, so we ended up
always failing the subsequent range check.
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index fc209c54f470edaa031009979061cff071cbf66d..4fc13b04bdae5bd9e2627027a10c534c2d9675dc 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -176,9 +176,11 @@ static int32_t fs__decode_wtf8_char(const char** input) {
if ((b4 & 0xC0) != 0x80)
return -1; /* invalid: not a continuation byte */
code_point = (code_point << 6) | (b4 & 0x3F);
- if (b1 <= 0xF4)
+ if (b1 <= 0xF4) {
+ code_point &= 0x1FFFFF;
if (code_point <= 0x10FFFF)
return code_point; /* four-byte character */
+ }
/* code point too large */
return -1;

View File

@@ -13,7 +13,7 @@ THREEWAY = "ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES" in os.environ
def apply_patches(target):
repo = target.get('repo')
if not os.path.exists(repo):
warnings.warn(f'repo not found: {repo}')
warnings.warn('repo not found: %s' % repo)
return
patch_dir = target.get('patch_dir')
git.import_patches(

View File

@@ -13,13 +13,13 @@ def stop():
DBusTestCase.stop_dbus(DBusTestCase.session_bus_pid)
def start():
with sys.stdout if is_verbose_mode() \
else open(os.devnull, 'w', encoding='utf-8') as log:
DBusTestCase.start_system_bus()
DBusTestCase.spawn_server_template('logind', None, log)
log = sys.stdout if is_verbose_mode() else open(os.devnull, 'w')
DBusTestCase.start_session_bus()
DBusTestCase.spawn_server_template('notification_daemon', None, log)
DBusTestCase.start_system_bus()
DBusTestCase.spawn_server_template('logind', None, log)
DBusTestCase.start_session_bus()
DBusTestCase.spawn_server_template('notification_daemon', None, log)
if __name__ == '__main__':
start()

View File

@@ -11,7 +11,7 @@ from lib import git
def export_patches(target, dry_run):
repo = target.get('repo')
if not os.path.exists(repo):
warnings.warn(f'repo not found: {repo}')
warnings.warn('repo not found: %s' % repo)
return
git.export_patches(
dry_run=dry_run,

View File

@@ -29,15 +29,15 @@ def run_node_configure(target_cpu):
def read_node_config_gypi():
config_gypi = os.path.join(NODE_DIR, 'config.gypi')
with open(config_gypi, 'r', encoding='utf-8') as file_in:
content = file_in.read()
with open(config_gypi, 'r') as f:
content = f.read()
return ast.literal_eval(content)
def read_electron_args():
all_gn = os.path.join(ELECTRON_DIR, 'build', 'args', 'all.gn')
args = {}
with open(all_gn, 'r', encoding='utf-8') as file_in:
for line in file_in:
with open(all_gn, 'r') as f:
for line in f:
if line.startswith('#'):
continue
m = re.match('([\w_]+) = (.+)', line)
@@ -62,8 +62,8 @@ def main(target_file, target_cpu):
# Used by certain versions of node-gyp.
v['build_v8_with_gn'] = 'false'
with open(target_file, 'w+', encoding='utf-8') as file_out:
file_out.write(pprint.pformat(config, indent=2))
with open(target_file, 'w+') as f:
f.write(pprint.pformat(config, indent=2))
if __name__ == '__main__':
sys.exit(main(sys.argv[1], sys.argv[2]))

View File

@@ -4,7 +4,7 @@ import zipfile
import sys
def main(zip_path, manifest_out):
with open(manifest_out, 'w', encoding='utf-8') as manifest, \
with open(manifest_out, 'w') as manifest, \
zipfile.ZipFile(zip_path, 'r', allowZip64=True) as z:
for name in sorted(z.namelist()):
manifest.write(name + '\n')

View File

@@ -8,8 +8,7 @@ NMV = None
if len(sys.argv) > 3:
NMV = sys.argv[3]
with open(node_version_file, 'r', encoding='utf-8') as in_file, \
open(out_file, 'w', encoding='utf-8') as out_file:
with open(node_version_file, 'r') as in_file, open(out_file, 'w') as out_file:
changed = False
contents = in_file.read()
new_contents = re.sub(

View File

@@ -43,7 +43,7 @@ def get_zip_name(name, version, suffix=''):
arch = get_target_arch()
if arch == 'arm':
arch += 'v7l'
zip_name = f'{name}-{version}-{get_platform_key()}-{arch}'
zip_name = '{0}-{1}-{2}-{3}'.format(name, version, get_platform_key(), arch)
if suffix:
zip_name += '-' + suffix
return zip_name + '.zip'

View File

@@ -72,10 +72,13 @@ def am(repo, patch_data, threeway=False, directory=None, exclude=None,
root_args += ['-c', 'user.email=' + committer_email]
root_args += ['-c', 'commit.gpgsign=false']
command = ['git'] + root_args + ['am'] + args
with subprocess.Popen(command, stdin=subprocess.PIPE) as proc:
proc.communicate(patch_data.encode('utf-8'))
if proc.returncode != 0:
raise RuntimeError(f"Command {command} returned {proc.returncode}")
proc = subprocess.Popen(
command,
stdin=subprocess.PIPE)
proc.communicate(patch_data.encode('utf-8'))
if proc.returncode != 0:
raise RuntimeError("Command {} returned {}".format(command,
proc.returncode))
def import_patches(repo, ref=UPSTREAM_HEAD, **kwargs):
@@ -226,19 +229,19 @@ def export_patches(repo, out_dir,
dry_run=False, grep=None):
if not os.path.exists(repo):
sys.stderr.write(
f"Skipping patches in {repo} because it does not exist.\n"
"Skipping patches in {} because it does not exist.\n".format(repo)
)
return
if patch_range is None:
patch_range, n_patches = guess_base_commit(repo, ref)
msg = f"Exporting {n_patches} patches in {repo} since {patch_range[0:7]}\n"
sys.stderr.write(msg)
patch_range, num_patches = guess_base_commit(repo, ref)
sys.stderr.write("Exporting {} patches in {} since {}\n".format(
num_patches, repo, patch_range[0:7]))
patch_data = format_patch(repo, patch_range)
patches = split_patches(patch_data)
if grep:
olen = len(patches)
patches = filter_patches(patches, grep)
sys.stderr.write(f"Exporting {len(patches)} of {olen} patches\n")
sys.stderr.write("Exporting {} of {} patches\n".format(len(patches), olen))
try:
os.mkdir(out_dir)
@@ -253,8 +256,7 @@ def export_patches(repo, out_dir,
for patch in patches:
filename = get_file_name(patch)
filepath = posixpath.join(out_dir, filename)
with io.open(filepath, 'rb') as inp:
existing_patch = str(inp.read(), 'utf-8')
existing_patch = str(io.open(filepath, 'rb').read(), 'utf-8')
formatted_patch = join_patch(patch)
if formatted_patch != existing_patch:
bad_patches.append(filename)

View File

@@ -65,7 +65,7 @@ class Platform:
return Platform.WINDOWS
raise AssertionError(
f"unexpected current platform '{platform}'")
"unexpected current platform '{}'".format(platform))
@staticmethod
def get_all():
@@ -101,19 +101,19 @@ class TestsList():
# First check that all names are present in the config.
for binary_name in binaries:
if binary_name not in self.tests:
msg = f"binary {binary_name} not found in config '{self.config_path}'"
raise Exception(msg)
raise Exception("binary {0} not found in config '{1}'".format(
binary_name, self.config_path))
# Respect the "platform" setting.
for binary_name in binaries:
if not self.__platform_supports(binary_name):
host = Platform.get_current()
errmsg = f"binary {binary_name} cannot run on {host}. Check the config"
raise Exception(errmsg)
raise Exception(
"binary {0} cannot be run on {1}, check the config".format(
binary_name, Platform.get_current()))
suite_returncode = sum(
self.__run(binary, output_dir, verbosity, disabled_tests_policy)
for binary in binaries)
[self.__run(binary, output_dir, verbosity, disabled_tests_policy)
for binary in binaries])
return suite_returncode
def run_all(self, output_dir=None, verbosity=Verbosity.CHATTY,
@@ -134,7 +134,7 @@ class TestsList():
@staticmethod
def __get_config_data(config_path):
with open(config_path, 'r', encoding='utf-8') as stream:
with open(config_path, 'r') as stream:
return yaml.load(stream)
@staticmethod
@@ -146,7 +146,7 @@ class TestsList():
if isinstance(value, str):
return {value: None}
raise AssertionError(f"unexpected shorthand type: {type(value)}")
raise AssertionError("unexpected shorthand type: {}".format(type(value)))
@staticmethod
def __make_a_list(value):
@@ -166,7 +166,7 @@ class TestsList():
return [list_item for key in value for list_item in value[key]]
raise AssertionError(
f"unexpected type for list merging: {type(value)}")
"unexpected type for list merging: {}".format(type(value)))
def __platform_supports(self, binary_name):
return Platform.get_current() in self.tests[binary_name]['platforms']
@@ -194,7 +194,8 @@ class TestsList():
for platform in platforms:
assert Platform.is_valid(platform), \
f"Unsupported platform {platform}, check {binary_name} config"
"platform '{0}' is not supported, check {1} config" \
.format(platform, binary_name)
test_data['platforms'] = platforms
@@ -230,7 +231,7 @@ class TestsList():
if output_dir is None:
return None
return os.path.join(output_dir, f"results_{binary_name}.xml")
return os.path.join(output_dir, "results_{}.xml".format(binary_name))
class TestBinary():
@@ -247,40 +248,50 @@ class TestBinary():
gtest_output = TestBinary.__get_gtest_output(output_file_path)
args = [self.binary_path, gtest_filter, gtest_output]
stdout, stderr = TestBinary.__get_stdout_and_stderr(verbosity)
returncode = 0
with open(os.devnull, "w", encoding='utf-8') as devnull:
stdout = stderr = None
if Verbosity.le(verbosity, Verbosity.ERRORS):
stdout = devnull
if verbosity == Verbosity.SILENT:
stderr = devnull
try:
returncode = subprocess.call(args, stdout=stdout, stderr=stderr)
except Exception as exception:
if Verbosity.ge(verbosity, Verbosity.ERRORS):
print(f"An error occurred while running '{self.binary_path}':",
'\n', exception, file=sys.stderr)
returncode = 1
try:
returncode = subprocess.call(args, stdout=stdout, stderr=stderr)
except Exception as exception:
if Verbosity.ge(verbosity, Verbosity.ERRORS):
print("An error occurred while running '{}':".format(self.binary_path),
'\n', exception, file=sys.stderr)
returncode = 1
return returncode
@staticmethod
def __get_gtest_filter(included_tests, excluded_tests):
included_str = TestBinary.__list_tests(included_tests)
excluded_str = TestBinary.__list_tests(excluded_tests)
return f"--gtest_filter={included_str}-{excluded_str}"
included_tests_string = TestBinary.__list_tests(included_tests)
excluded_tests_string = TestBinary.__list_tests(excluded_tests)
gtest_filter = "--gtest_filter={}-{}".format(included_tests_string,
excluded_tests_string)
return gtest_filter
@staticmethod
def __get_gtest_output(output_file_path):
if output_file_path is None:
return ""
return f"--gtest_output={TestBinary.output_format}:{output_file_path}"
gtest_output = ""
if output_file_path is not None:
gtest_output = "--gtest_output={0}:{1}".format(TestBinary.output_format,
output_file_path)
return gtest_output
@staticmethod
def __list_tests(tests):
if tests is None:
return ''
return ':'.join(tests)
@staticmethod
def __get_stdout_and_stderr(verbosity):
stdout = stderr = None
if Verbosity.le(verbosity, Verbosity.ERRORS):
devnull = open(os.devnull, 'w')
stdout = devnull
if verbosity == Verbosity.SILENT:
stderr = devnull
return (stdout, stderr)

View File

@@ -21,8 +21,8 @@ def read_patch(patch_dir, patch_filename):
for l in f.readlines():
line_has_correct_start = l.startswith('diff -') or l.startswith('---')
if not added_patch_location and line_has_correct_start:
ret.append(f'{PATCH_DIR_PREFIX}{patch_dir}\n')
ret.append(f'{PATCH_FILENAME_PREFIX}{patch_filename}\n')
ret.append('{}{}\n'.format(PATCH_DIR_PREFIX, patch_dir))
ret.append('{}{}\n'.format(PATCH_FILENAME_PREFIX, patch_filename))
added_patch_location = True
ret.append(l)
return ''.join(ret)
@@ -31,8 +31,8 @@ def read_patch(patch_dir, patch_filename):
def patch_from_dir(patch_dir):
"""Read a directory of patches into a format suitable for passing to
'git am'"""
with open(os.path.join(patch_dir, ".patches"), encoding='utf-8') as file_in:
patch_list = [line.rstrip('\n') for line in file_in.readlines()]
with open(os.path.join(patch_dir, ".patches")) as f:
patch_list = [l.rstrip('\n') for l in f.readlines()]
return ''.join([
read_patch(patch_dir, patch_filename)

View File

@@ -35,8 +35,9 @@ def scoped_cwd(path):
def download(text, url, path):
safe_mkdir(os.path.dirname(path))
with open(path, 'wb') as local_file, urlopen(url) as web_file:
print(f"Downloading {url} to {path}")
with open(path, 'wb') as local_file:
print("Downloading %s to %s" % (url, path))
web_file = urlopen(url)
info = web_file.info()
if hasattr(info, 'getheader'):
file_size = int(info.getheaders("Content-Length")[0])
@@ -57,11 +58,11 @@ def download(text, url, path):
if not ci:
percent = downloaded_size * 100. / file_size
status = f"\r{text} {downloaded_size:10d} [{percent:3.1f}%]"
status = "\r%s %10d [%3.1f%%]" % (text, downloaded_size, percent)
print(status, end=' ')
if ci:
print(f"{text} done.")
print("%s done." % (text))
else:
print()
return path
@@ -73,16 +74,15 @@ def make_zip(zip_file_path, files, dirs):
allfiles = files + dirs
execute(['zip', '-r', '-y', zip_file_path] + allfiles)
else:
with zipfile.ZipFile(zip_file_path, "w",
zipfile.ZIP_DEFLATED,
allowZip64=True) as zip_file:
for filename in files:
zip_file.write(filename, filename)
for dirname in dirs:
for root, _, filenames in os.walk(dirname):
for f in filenames:
zip_file.write(os.path.join(root, f))
zip_file.close()
zip_file = zipfile.ZipFile(zip_file_path, "w", zipfile.ZIP_DEFLATED,
allowZip64=True)
for filename in files:
zip_file.write(filename, filename)
for dirname in dirs:
for root, _, filenames in os.walk(dirname):
for f in filenames:
zip_file.write(os.path.join(root, f))
zip_file.close()
def rm_rf(path):
@@ -128,8 +128,8 @@ def get_electron_branding():
SOURCE_ROOT = os.path.abspath(os.path.join(__file__, '..', '..', '..'))
branding_file_path = os.path.join(
SOURCE_ROOT, 'shell', 'app', 'BRANDING.json')
with open(branding_file_path, encoding='utf-8') as file_in:
return json.load(file_in)
with open(branding_file_path) as f:
return json.load(f)
cached_electron_version = None
@@ -173,14 +173,14 @@ def get_electron_exec():
out_dir = get_out_dir()
if sys.platform == 'darwin':
return f'{out_dir}/Electron.app/Contents/MacOS/Electron'
return '{0}/Electron.app/Contents/MacOS/Electron'.format(out_dir)
if sys.platform == 'win32':
return f'{out_dir}/electron.exe'
return '{0}/electron.exe'.format(out_dir)
if sys.platform == 'linux':
return f'{out_dir}/electron'
return '{0}/electron'.format(out_dir)
raise Exception(
f"get_electron_exec: unexpected platform '{sys.platform}'")
"get_electron_exec: unexpected platform '{0}'".format(sys.platform))
def get_buildtools_executable(name):
buildtools = os.path.realpath(os.path.join(ELECTRON_DIR, '..', 'buildtools'))

View File

@@ -120,10 +120,10 @@ const LINTERS = [{
roots: ['script'],
test: filename => filename.endsWith('.py'),
run: (opts, filenames) => {
const rcfile = path.join(DEPOT_TOOLS, 'pylintrc-2.17');
const rcfile = path.join(DEPOT_TOOLS, 'pylintrc');
const args = ['--rcfile=' + rcfile, ...filenames];
const env = { PYTHONPATH: path.join(ELECTRON_ROOT, 'script'), ...process.env };
spawnAndCheckExitCode('pylint-2.17', args, { env });
spawnAndCheckExitCode('pylint-2.7', args, { env });
}
}, {
key: 'javascript',

View File

@@ -65,19 +65,19 @@ def parse_args():
# 'config' must exist and be a file.
args.config = os.path.abspath(args.config)
if not os.path.isfile(args.config):
parser.error(f"file '{args.config}' doesn't exist")
parser.error("file '{}' doesn't exist".format(args.config))
# 'tests_dir' must exist and be a directory.
if args.tests_dir is not None:
args.tests_dir = os.path.abspath(args.tests_dir)
if not os.path.isdir(args.tests_dir):
parser.error(f"directory '{args.tests_dir}' doesn't exist")
parser.error("directory '{}' doesn't exist".format(args.tests_dir))
# 'output_dir' must exist and be a directory.
if args.output_dir is not None:
args.output_dir = os.path.abspath(args.output_dir)
if not os.path.isdir(args.output_dir):
parser.error(f"directory '{args.output_dir}' doesn't exist")
parser.error("directory '{}' doesn't exist".format(args.output_dir))
return args
@@ -99,7 +99,7 @@ def main():
return tests_list.run_all(args.output_dir, args.verbosity,
args.disabled_tests_policy)
raise AssertionError(f"unexpected command '{args.command}'")
raise AssertionError("unexpected command '{}'".format(args.command))
if __name__ == '__main__':

View File

@@ -77,8 +77,8 @@ def set_mtimes(patches_config, mtime):
mtime_cache[file_path] = mtime
for file_path, file_mtime in mtime_cache.items():
os.utime(file_path, (file_mtime, file_mtime))
for file_path in mtime_cache:
os.utime(file_path, (mtime_cache[file_path], mtime_cache[file_path]))
def main():
@@ -131,17 +131,17 @@ def main():
if args.operation == "generate":
try:
# Cache file may exist from a previously aborted sync. Reuse it.
with open(args.cache_file, mode='r', encoding='utf-8') as fin:
json.load(fin) # Make sure it's not an empty file
with open(args.cache_file, mode="r") as f:
json.load(f) # Make sure it's not an empty file
print("Using existing mtime cache for patches")
return 0
except Exception:
pass
try:
with open(args.cache_file, mode="w", encoding='utf-8') as fin:
with open(args.cache_file, mode="w") as f:
mtime_cache = generate_cache(json.load(args.patches_config))
json.dump(mtime_cache, fin, indent=2)
json.dump(mtime_cache, f, indent=2)
except Exception:
print(
"ERROR: failed to generate mtime cache for patches",
@@ -155,8 +155,8 @@ def main():
return 0 # Cache file may not exist, fail more gracefully
try:
with open(args.cache_file, mode='r', encoding='utf-8') as file_in:
apply_mtimes(json.load(file_in))
with open(args.cache_file, mode="r") as f:
apply_mtimes(json.load(f))
if not args.preserve_cache:
os.remove(args.cache_file)

View File

@@ -3,18 +3,9 @@ if (!process.env.CI) require('dotenv-safe').load();
const assert = require('node:assert');
const got = require('got');
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({
auth: process.env.ELECTRON_GITHUB_TOKEN
});
const BUILD_APPVEYOR_URL = 'https://ci.appveyor.com/api/builds';
const CIRCLECI_PIPELINE_URL = 'https://circleci.com/api/v2/project/gh/electron/electron/pipeline';
const GH_ACTIONS_PIPELINE_URL = 'https://github.com/electron/electron/actions';
const GH_ACTIONS_API_URL = '/repos/electron/electron/actions';
const CIRCLECI_WAIT_TIME = process.env.CIRCLECI_WAIT_TIME || 30000;
const GH_ACTIONS_WAIT_TIME = process.env.GH_ACTIONS_WAIT_TIME || 30000;
const appVeyorJobs = {
'electron-x64': 'electron-x64-release',
@@ -32,14 +23,6 @@ const circleCIPublishIndividualArches = {
'linux-publish': ['arm', 'arm64', 'x64']
};
const ghActionsPublishWorkflows = [
'macos-publish'
];
const ghActionsPublishIndividualArches = {
'macos-publish': ['osx-x64', 'mas-x64', 'osx-arm64', 'mas-arm64']
};
let jobRequestedCount = 0;
async function makeRequest ({ auth, username, password, url, headers, body, method }) {
@@ -70,65 +53,6 @@ async function makeRequest ({ auth, username, password, url, headers, body, meth
return JSON.parse(response.body);
}
async function githubActionsCall (targetBranch, workflowName, options) {
console.log(`Triggering GitHub Actions to run build job: ${workflowName} on branch: ${targetBranch} with release flag.`);
const buildRequest = {
branch: targetBranch,
parameters: {}
};
if (options.ghRelease) {
buildRequest.parameters['upload-to-storage'] = '0';
} else {
buildRequest.parameters['upload-to-storage'] = '1';
}
buildRequest.parameters[`run-${workflowName}`] = true;
if (options.arch) {
const validArches = ghActionsPublishIndividualArches[workflowName];
assert(validArches.includes(options.arch), `Unknown GitHub Actions architecture "${options.arch}". Valid values are ${JSON.stringify(validArches)}`);
buildRequest.parameters['macos-publish-arch-limit'] = options.arch;
}
jobRequestedCount++;
try {
const commits = await octokit.repos.listCommits({
owner: 'electron',
repo: 'electron',
sha: targetBranch,
per_page: 5
});
if (!commits.data.length) {
console.error('Could not fetch most recent commits for GitHub Actions, returning early');
}
await octokit.request(`POST ${GH_ACTIONS_API_URL}/workflows/${workflowName}.yml/dispatches`, {
ref: buildRequest.branch,
inputs: {
...buildRequest.parameters
},
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
const runNumber = await getGitHubActionsRun(workflowName, commits.data[0].sha);
if (runNumber === -1) {
return;
}
console.log(`GitHub Actions release build pipeline ${runNumber} for ${workflowName} triggered.`);
const runUrl = `${GH_ACTIONS_PIPELINE_URL}/runs/${runNumber}`;
if (options.runningPublishWorkflows) {
console.log(`GitHub Actions release workflow request for ${workflowName} successful. Check ${runUrl} for status.`);
} else {
console.log(`GitHub Actions release build workflow running at ${GH_ACTIONS_PIPELINE_URL}/runs/${runNumber} for ${workflowName}.`);
console.log(`GitHub Actions release build request for ${workflowName} successful. Check ${runUrl} for status.`);
}
} catch (err) {
console.log('Error calling GitHub Actions: ', err);
}
}
async function circleCIcall (targetBranch, workflowName, options) {
console.log(`Triggering CircleCI to run build job: ${workflowName} on branch: ${targetBranch} with release flag.`);
const buildRequest = {
@@ -243,59 +167,6 @@ async function getCircleCIJobNumber (workflowId) {
return jobNumber;
}
async function getGitHubActionsRun (workflowId, headCommit) {
let runNumber = 0;
let actionRun;
while (runNumber === 0) {
const actionsRuns = await octokit.request(`GET ${GH_ACTIONS_API_URL}/workflows/${workflowId}.yml/runs`, {
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
if (!actionsRuns.data.workflow_runs.length) {
console.log(`No current workflow_runs found for ${workflowId}, response was: ${actionsRuns.data.workflow_runs}`);
runNumber = -1;
break;
}
for (const run of actionsRuns.data.workflow_runs) {
if (run.head_sha === headCommit) {
console.log(`GitHub Actions run ${run.html_url} found for ${headCommit}, waiting on status.`);
actionRun = run;
break;
}
}
if (actionRun) {
switch (actionRun.status) {
case 'in_progress':
case 'pending':
case 'queued':
case 'requested':
case 'waiting': {
if (actionRun.id && !isNaN(actionRun.id)) {
console.log(`GitHub Actions run ${actionRun.status} for ${actionRun.html_url}.`);
runNumber = actionRun.id;
}
break;
}
case 'action_required':
case 'cancelled':
case 'failure':
case 'skipped':
case 'timed_out':
case 'failed': {
console.log(`Error workflow run returned a status of ${actionRun.status} for ${actionRun.html_url}`);
runNumber = -1;
break;
}
}
await new Promise(resolve => setTimeout(resolve, GH_ACTIONS_WAIT_TIME));
}
}
return runNumber;
}
async function circleCIRequest (url, method, requestBody) {
const requestOpts = {
username: process.env.CIRCLE_TOKEN,
@@ -323,6 +194,18 @@ async function circleCIRequest (url, method, requestBody) {
});
}
function buildAppVeyor (targetBranch, options) {
const validJobs = Object.keys(appVeyorJobs);
if (options.job) {
assert(validJobs.includes(options.job), `Unknown AppVeyor CI job name: ${options.job}. Valid values are: ${validJobs}.`);
callAppVeyor(targetBranch, options.job, options);
} else {
for (const job of validJobs) {
callAppVeyor(targetBranch, job, options);
}
}
}
async function callAppVeyor (targetBranch, job, options) {
console.log(`Triggering AppVeyor to run build job: ${job} on branch: ${targetBranch} with release flag.`);
const environmentVariables = {
@@ -369,18 +252,6 @@ async function callAppVeyor (targetBranch, job, options) {
}
}
function buildAppVeyor (targetBranch, options) {
const validJobs = Object.keys(appVeyorJobs);
if (options.job) {
assert(validJobs.includes(options.job), `Unknown AppVeyor CI job name: ${options.job}. Valid values are: ${validJobs}.`);
callAppVeyor(targetBranch, options.job, options);
} else {
for (const job of validJobs) {
callAppVeyor(targetBranch, job, options);
}
}
}
function buildCircleCI (targetBranch, options) {
if (options.job) {
assert(circleCIPublishWorkflows.includes(options.job), `Unknown CircleCI workflow name: ${options.job}. Valid values are: ${circleCIPublishWorkflows}.`);
@@ -394,19 +265,6 @@ function buildCircleCI (targetBranch, options) {
}
}
function buildGHActions (targetBranch, options) {
if (options.job) {
assert(ghActionsPublishWorkflows.includes(options.job), `Unknown GitHub Actions workflow name: ${options.job}. Valid values are: ${ghActionsPublishWorkflows}.`);
githubActionsCall(targetBranch, options.job, options);
} else {
assert(!options.arch, 'Cannot provide a single architecture while building all workflows, please specify a single workflow via --workflow');
options.runningPublishWorkflows = true;
for (const job of ghActionsPublishWorkflows) {
githubActionsCall(targetBranch, job, options);
}
}
}
function runRelease (targetBranch, options) {
if (options.ci) {
switch (options.ci) {
@@ -414,10 +272,6 @@ function runRelease (targetBranch, options) {
buildCircleCI(targetBranch, options);
break;
}
case 'GitHubActions': {
buildGHActions(targetBranch, options);
break;
}
case 'AppVeyor': {
buildAppVeyor(targetBranch, options);
break;
@@ -430,8 +284,6 @@ function runRelease (targetBranch, options) {
} else {
buildCircleCI(targetBranch, options);
buildAppVeyor(targetBranch, options);
// TODO(vertedinde): Enable GH Actions in defaults when ready
// buildGHActions(targetBranch, options);
}
console.log(`${jobRequestedCount} jobs were requested.`);
}
@@ -445,7 +297,7 @@ if (require.main === module) {
const targetBranch = args._[0];
if (args._.length < 1) {
console.log(`Trigger CI to build release builds of electron.
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--arch=INDIVIDUAL_ARCH] [--ci=CircleCI|AppVeyor|GitHubActions]
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--arch=INDIVIDUAL_ARCH] [--ci=CircleCI|AppVeyor]
[--ghRelease] [--circleBuildNum=xxx] [--appveyorJobId=xxx] [--commit=sha] TARGET_BRANCH
`);
process.exit(0);

View File

@@ -32,8 +32,9 @@ def get_content(retry_count = 5):
headers={"Authorization" : authToken}
)
with urlopen(request) as resp:
proposed_content = resp.read()
proposed_content = urlopen(
request
).read()
if is_json(proposed_content):
return proposed_content

View File

@@ -29,7 +29,7 @@ def main():
]
if args.target_dir is None:
store_artifact(directory, f'headers/dist/{args.version}',
store_artifact(directory, 'headers/dist/{0}'.format(args.version),
checksums)
else:
copy_files(checksums, args.target_dir)
@@ -51,10 +51,10 @@ def parse_args():
def get_files_list(version):
return [
{ "filename": f'node-{version}.tar.gz', "required": True },
{ "filename": f'node-{version}-headers.tar.gz', "required": True },
{ "filename": f'iojs-{version}.tar.gz', "required": True },
{ "filename": f'iojs-{version}-headers.tar.gz', "required": True },
{ "filename": 'node-{0}.tar.gz'.format(version), "required": True },
{ "filename": 'node-{0}-headers.tar.gz'.format(version), "required": True },
{ "filename": 'iojs-{0}.tar.gz'.format(version), "required": True },
{ "filename": 'iojs-{0}-headers.tar.gz'.format(version), "required": True },
{ "filename": 'node.lib', "required": False },
{ "filename": 'x64/node.lib', "required": False },
{ "filename": 'win-x86/iojs.lib', "required": False },
@@ -91,8 +91,8 @@ def create_checksum(algorithm, directory, filename, files):
lines.append(h.hexdigest() + ' ' + os.path.relpath(path, directory))
checksum_file = os.path.join(directory, filename)
with open(checksum_file, 'w', encoding='utf-8') as fout:
fout.write('\n'.join(lines) + '\n')
with open(checksum_file, 'w') as f:
f.write('\n'.join(lines) + '\n')
return checksum_file
def copy_files(source_files, output_dir):

View File

@@ -45,9 +45,9 @@ def upload_node(version):
versioned_header_tar = header_tar.format(version)
shutil.copy2(generated_tar, os.path.join(GEN_DIR, versioned_header_tar))
store_artifact(GEN_DIR, f'headers/dist/{version}',
store_artifact(GEN_DIR, 'headers/dist/{0}'.format(version),
glob.glob('node-*.tar.gz'))
store_artifact(GEN_DIR, f'headers/dist/{version}',
store_artifact(GEN_DIR, 'headers/dist/{0}'.format(version),
glob.glob('iojs-*.tar.gz'))
if PLATFORM == 'win32':
@@ -73,13 +73,13 @@ def upload_node(version):
shutil.copy2(electron_lib, v4_node_lib)
# Upload the node.lib.
store_artifact(DIST_DIR, f'headers/dist/{version}', [node_lib])
store_artifact(DIST_DIR, 'headers/dist/{0}'.format(version), [node_lib])
# Upload the iojs.lib.
store_artifact(DIST_DIR, f'headers/dist/{version}', [iojs_lib])
store_artifact(DIST_DIR, 'headers/dist/{0}'.format(version), [iojs_lib])
# Upload the v4 node.lib.
store_artifact(DIST_DIR, f'headers/dist/{version}',
store_artifact(DIST_DIR, 'headers/dist/{0}'.format(version),
[v4_node_lib])

View File

@@ -26,7 +26,7 @@ PRODUCT_NAME = get_electron_branding()['product_name']
SYMBOLS_DIR = os.path.join(RELEASE_DIR, 'breakpad_symbols')
PDB_LIST = [
os.path.join(RELEASE_DIR, f'{PROJECT_NAME}.exe.pdb')
os.path.join(RELEASE_DIR, '{0}.exe.pdb'.format(PROJECT_NAME))
]
PDB_LIST += glob.glob(os.path.join(RELEASE_DIR, '*.dll.pdb'))
@@ -80,14 +80,8 @@ def main():
def run_symstore(pdb, dest, product):
for attempt in range(2):
try:
execute(['symstore', 'add', '/r', '/f', pdb, '/s', dest, '/t', product])
break
except Exception as e:
print(f"An error occurred while adding '{pdb}' to SymStore: {str(e)}")
if attempt == 0:
print("Retrying...")
execute(['symstore', 'add', '/r', '/f', pdb, '/s', dest, '/t', product])
def upload_symbols(files):
store_artifact(SYMBOLS_DIR, 'symbols',

View File

@@ -53,8 +53,9 @@ def main():
build_version = get_electron_build_version()
if not ELECTRON_VERSION.startswith(build_version):
errmsg = f"Tag ({ELECTRON_VERSION}) should match build ({build_version})\n"
sys.stderr.write(errmsg)
error = 'Tag name ({0}) should match build version ({1})\n'.format(
ELECTRON_VERSION, build_version)
sys.stderr.write(error)
sys.stderr.flush()
return 1
@@ -343,7 +344,8 @@ def upload_electron(release, file_path, args):
# if upload_to_storage is set, skip github upload.
# todo (vertedinde): migrate this variable to upload_to_storage
if args.upload_to_storage:
key_prefix = f'release-builds/{args.version}_{args.upload_timestamp}'
key_prefix = 'release-builds/{0}_{1}'.format(args.version,
args.upload_timestamp)
store_artifact(os.path.dirname(file_path), key_prefix, [file_path])
upload_sha256_checksum(args.version, file_path, key_prefix)
return
@@ -356,30 +358,30 @@ def upload_electron(release, file_path, args):
def upload_io_to_github(release, filename, filepath, version):
print(f'Uploading {filename} to GitHub')
print('Uploading %s to GitHub' % \
(filename))
script_path = os.path.join(
ELECTRON_DIR, 'script', 'release', 'uploaders', 'upload-to-github.ts')
with subprocess.Popen([TS_NODE, script_path, filepath,
filename, str(release['id']), version],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT) as upload_process:
if is_verbose_mode():
for c in iter(lambda: upload_process.stdout.read(1), b""):
sys.stdout.buffer.write(c)
sys.stdout.flush()
upload_process = subprocess.Popen([TS_NODE, script_path, filepath, filename,
str(release['id']), version], stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
if is_verbose_mode():
for c in iter(lambda: upload_process.stdout.read(1), b""):
sys.stdout.buffer.write(c)
sys.stdout.flush()
def upload_sha256_checksum(version, file_path, key_prefix=None):
checksum_path = f'{file_path}.sha256sum'
checksum_path = '{}.sha256sum'.format(file_path)
if key_prefix is None:
key_prefix = f'checksums-scratchpad/{version}'
key_prefix = 'checksums-scratchpad/{0}'.format(version)
sha256 = hashlib.sha256()
with open(file_path, 'rb') as f:
sha256.update(f.read())
filename = os.path.basename(file_path)
with open(checksum_path, 'w', encoding='utf-8') as checksum:
checksum.write(f'{sha256.hexdigest()} *{filename}')
with open(checksum_path, 'w') as checksum:
checksum.write('{} *{}'.format(sha256.hexdigest(), filename))
store_artifact(os.path.dirname(checksum_path), key_prefix, [checksum_path])
@@ -392,7 +394,7 @@ def get_release(version):
release_env['NODE_NO_WARNINGS'] = '1'
release_info = execute(['node', script_path, version], release_env)
if is_verbose_mode():
print(f'Release info for version: {version}:\n')
print('Release info for version: {}:\n'.format(version))
print(release_info)
release = json.loads(release_info)
return release

View File

@@ -85,8 +85,8 @@ def make_diff(diff_file, original, reformatted):
difflib.unified_diff(
original,
reformatted,
fromfile=f'a/{diff_file}',
tofile=f'b/{diff_file}',
fromfile='a/{}'.format(diff_file),
tofile='b/{}'.format(diff_file),
n=3))
@@ -111,7 +111,8 @@ def run_clang_format_diff_wrapper(args, file_name):
raise
except Exception as e:
# pylint: disable=W0707
raise UnexpectedError(f'{file_name}: {e.__class__.__name__}: {e}', e)
raise UnexpectedError('{}: {}: {}'.format(
file_name, e.__class__.__name__, e), e)
def run_clang_format_diff(args, file_name):
@@ -130,22 +131,25 @@ def run_clang_format_diff(args, file_name):
print(" ".join(invocation))
return [], []
try:
with subprocess.Popen(' '.join(invocation),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
shell=True) as proc:
outs = list(proc.stdout.readlines())
errs = list(proc.stderr.readlines())
proc.wait()
if proc.returncode:
code = proc.returncode
msg = f"clang-format exited with code {code}: '{file_name}'"
raise DiffError(msg, errs)
proc = subprocess.Popen(
' '.join(invocation),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
shell=True)
except OSError as exc:
# pylint: disable=raise-missing-from
cmd = subprocess.list2cmdline(invocation)
raise DiffError(f"Command '{cmd}' failed to start: {exc}")
# pylint: disable=W0707
raise DiffError(
"Command '{}' failed to start: {}".format(
subprocess.list2cmdline(invocation), exc
)
)
outs = list(proc.stdout.readlines())
errs = list(proc.stderr.readlines())
proc.wait()
if proc.returncode:
raise DiffError("clang-format exited with status {}: '{}'".format(
proc.returncode, file_name), errs)
if args.fix:
return None, errs
if sys.platform == 'win32':
@@ -196,7 +200,7 @@ def print_trouble(prog, message, use_colors):
error_text = 'error:'
if use_colors:
error_text = bold_red(error_text)
print(f"{prog}: {error_text} {message}", file=sys.stderr)
print("{}: {} {}".format(prog, error_text, message), file=sys.stderr)
def main():
@@ -208,8 +212,8 @@ def main():
default=get_buildtools_executable('clang-format'))
parser.add_argument(
'--extensions',
help='comma-separated list of file extensions'
f' (default: {DEFAULT_EXTENSIONS})',
help='comma separated list of file extensions (default: {})'.format(
DEFAULT_EXTENSIONS),
default=DEFAULT_EXTENSIONS)
parser.add_argument(
'--fix',
@@ -286,18 +290,18 @@ def main():
parse_files = []
if args.changed:
with subprocess.Popen(
stdout = subprocess.Popen(
"git diff --name-only --cached",
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True,
universal_newlines=True
) as child:
for line in child.communicate()[0].split("\n"):
file_name = line.rstrip()
# don't check deleted files
if os.path.isfile(file_name):
parse_files.append(file_name)
).communicate()[0].split("\n")
for line in stdout:
file_name = line.rstrip()
# don't check deleted files
if os.path.isfile(file_name):
parse_files.append(file_name)
else:
parse_files = args.files
@@ -320,7 +324,6 @@ def main():
njobs = min(len(files), njobs)
if not args.fix:
# pylint: disable=consider-using-with
patch_file = tempfile.NamedTemporaryFile(delete=False,
prefix='electron-format-')
@@ -330,7 +333,6 @@ def main():
it = (run_clang_format_diff_wrapper(args, file) for file in files)
pool = None
else:
# pylint: disable=consider-using-with
pool = multiprocessing.Pool(njobs)
it = pool.imap_unordered(
partial(run_clang_format_diff_wrapper, args), files)
@@ -371,11 +373,8 @@ def main():
patch_file.close()
os.unlink(patch_file.name)
else:
print(
'To patch these files, run:',
f"$ git apply {patch_file.name}", sep='\n')
filename=patch_file.name
print(f"\nTo patch these files, run:\n$ git apply {filename}\n")
print("\nTo patch these files, run:\n$ git apply {}\n"
.format(patch_file.name))
return retcode

View File

@@ -7,6 +7,6 @@ target = sys.argv[2]
os.chdir(os.path.dirname(source))
with tarfile.open(name=os.path.basename(target), mode='w:gz') as tarball:
tarball.add(os.path.relpath(source))
tarball.close()
tarball = tarfile.open(name=os.path.basename(target), mode='w:gz')
tarball.add(os.path.relpath(source))
tarball.close()

View File

@@ -21,15 +21,14 @@ def main():
chromedriver_path = os.path.join(
args.source_root, args.build_dir, chromedriver_name[sys.platform])
with subprocess.Popen([chromedriver_path],
stdout=subprocess.PIPE,
universal_newlines=True) as proc:
try:
output = proc.stdout.readline()
except KeyboardInterrupt:
returncode = 0
finally:
proc.terminate()
proc = subprocess.Popen([chromedriver_path],
stdout=subprocess.PIPE, universal_newlines=True)
try:
output = proc.stdout.readline()
except KeyboardInterrupt:
returncode = 0
finally:
proc.terminate()
returncode = 0
match = re.search(

View File

@@ -24,10 +24,10 @@ def main():
electron = os.path.join(app_path, 'Contents', 'MacOS', PRODUCT_NAME)
ffmpeg_name = 'libffmpeg.dylib'
ffmpeg_app_path = os.path.join(app_path, 'Contents', 'Frameworks',
f'{PRODUCT_NAME} Framework.framework',
'{0} Framework.framework'.format(PRODUCT_NAME),
'Libraries')
elif sys.platform == 'win32':
electron = os.path.join(app_path, f'{PROJECT_NAME}.exe')
electron = os.path.join(app_path, '{0}.exe'.format(PROJECT_NAME))
ffmpeg_app_path = app_path
ffmpeg_name = 'ffmpeg.dll'
else:
@@ -69,7 +69,7 @@ def create_app_copy(initial_app_path):
+ '-no-proprietary-codecs')
if sys.platform == 'darwin':
app_name = f'{PRODUCT_NAME}.app'
app_name = '{0}.app'.format(PRODUCT_NAME)
initial_app_path = os.path.join(initial_app_path, app_name)
app_path = os.path.join(app_path, app_name)

View File

@@ -26,9 +26,8 @@ def main():
try:
with scoped_cwd(app_path):
if args.snapshot_files_dir is None:
snapshot_filename = os.path.join(app_path, 'mksnapshot_args')
with open(snapshot_filename, encoding='utf-8') as file_in:
mkargs = file_in.read().splitlines()
with open(os.path.join(app_path, 'mksnapshot_args')) as f:
mkargs = f.read().splitlines()
print('running: ' + ' '.join(mkargs + [ SNAPSHOT_SOURCE ]))
subprocess.check_call(mkargs + [ SNAPSHOT_SOURCE ], cwd=app_path)
print('ok mksnapshot successfully created snapshot_blob.bin.')
@@ -42,7 +41,7 @@ def main():
gen_binary = get_binary_path('v8_context_snapshot_generator', \
app_path)
genargs = [ gen_binary, \
f'--output_file={context_snapshot_path}' ]
'--output_file={0}'.format(context_snapshot_path) ]
print('running: ' + ' '.join(genargs))
subprocess.check_call(genargs)
print('ok v8_context_snapshot_generator successfully created ' \
@@ -60,15 +59,15 @@ def main():
if sys.platform == 'darwin':
bin_files = glob.glob(os.path.join(app_path, '*.bin'))
app_dir = os.path.join(app_path, f'{PRODUCT_NAME}.app')
app_dir = os.path.join(app_path, '{0}.app'.format(PRODUCT_NAME))
electron = os.path.join(app_dir, 'Contents', 'MacOS', PRODUCT_NAME)
bin_out_path = os.path.join(app_dir, 'Contents', 'Frameworks',
f'{PROJECT_NAME} Framework.framework',
'{0} Framework.framework'.format(PROJECT_NAME),
'Resources')
for bin_file in bin_files:
shutil.copy2(bin_file, bin_out_path)
elif sys.platform == 'win32':
electron = os.path.join(app_path, f'{PROJECT_NAME}.exe')
electron = os.path.join(app_path, '{0}.exe'.format(PROJECT_NAME))
else:
electron = os.path.join(app_path, PROJECT_NAME)
@@ -82,7 +81,7 @@ def main():
except KeyboardInterrupt:
print('Other error')
returncode = 0
print(f'Returning with error code: {returncode}')
print('Returning with error code: {0}'.format(returncode))
return returncode
@@ -99,7 +98,7 @@ def create_app_copy(initial_app_path):
def get_binary_path(binary_name, root_path):
if sys.platform == 'win32':
binary_path = os.path.join(root_path, f'{binary_name}.exe')
binary_path = os.path.join(root_path, '{0}.exe'.format(binary_name))
else:
binary_path = os.path.join(root_path, binary_name)
return binary_path

View File

@@ -4,7 +4,7 @@ import zipfile
import sys
def main(zip_path, manifest_in):
with open(manifest_in, 'r', encoding='utf-8') as manifest, \
with open(manifest_in, 'r') as manifest, \
zipfile.ZipFile(zip_path, 'r', allowZip64=True) as z:
files_in_zip = set(z.namelist())
files_in_manifest = {l.strip() for l in manifest.readlines()}

View File

@@ -89,6 +89,7 @@
#if BUILDFLAG(IS_MAC)
#include <CoreFoundation/CoreFoundation.h>
#include "base/mac/mac_util.h"
#include "shell/browser/ui/cocoa/electron_bundle_mover.h"
#endif
@@ -323,6 +324,80 @@ struct Converter<JumpListResult> {
};
#endif
#if BUILDFLAG(IS_WIN)
template <>
struct Converter<Browser::LaunchItem> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
Browser::LaunchItem* out) {
gin_helper::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("name", &(out->name));
dict.Get("path", &(out->path));
dict.Get("args", &(out->args));
dict.Get("scope", &(out->scope));
dict.Get("enabled", &(out->enabled));
return true;
}
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
Browser::LaunchItem val) {
auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
dict.Set("name", val.name);
dict.Set("path", val.path);
dict.Set("args", val.args);
dict.Set("scope", val.scope);
dict.Set("enabled", val.enabled);
return dict.GetHandle();
}
};
#endif
template <>
struct Converter<Browser::LoginItemSettings> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
Browser::LoginItemSettings* out) {
gin_helper::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("openAtLogin", &(out->open_at_login));
dict.Get("openAsHidden", &(out->open_as_hidden));
dict.Get("path", &(out->path));
dict.Get("args", &(out->args));
#if BUILDFLAG(IS_WIN)
dict.Get("name", &(out->name));
dict.Get("enabled", &(out->enabled));
#elif BUILDFLAG(IS_MAC)
dict.Get("serviceName", &(out->service_name));
dict.Get("type", &(out->type));
#endif
return true;
}
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
Browser::LoginItemSettings val) {
auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
#if BUILDFLAG(IS_WIN)
dict.Set("launchItems", val.launch_items);
dict.Set("executableWillLaunchAtLogin",
val.executable_will_launch_at_login);
#elif BUILDFLAG(IS_MAC)
if (base::mac::MacOSMajorVersion() >= 13)
dict.Set("status", val.status);
#endif
dict.Set("openAtLogin", val.open_at_login);
dict.Set("openAsHidden", val.open_as_hidden);
dict.Set("restoreState", val.restore_state);
dict.Set("wasOpenedAtLogin", val.opened_at_login);
dict.Set("wasOpenedAsHidden", val.opened_as_hidden);
return dict.GetHandle();
}
};
template <>
struct Converter<content::CertificateRequestResultType> {
static bool FromV8(v8::Isolate* isolate,
@@ -1141,8 +1216,8 @@ void App::SetAccessibilitySupportEnabled(gin_helper::ErrorThrower thrower,
Browser::Get()->OnAccessibilitySupportChanged();
}
v8::Local<v8::Value> App::GetLoginItemSettings(gin::Arguments* args) {
LoginItemSettings options;
Browser::LoginItemSettings App::GetLoginItemSettings(gin::Arguments* args) {
Browser::LoginItemSettings options;
args->GetNext(&options);
return Browser::Get()->GetLoginItemSettings(options);
}
@@ -1206,7 +1281,7 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
if (!delete_jump_list &&
!gin::ConvertFromV8(args->isolate(), val, &categories)) {
gin_helper::ErrorThrower(args->isolate())
.ThrowTypeError("Argument must be null or an array of categories");
.ThrowError("Argument must be null or an array of categories");
return JumpListResult::kArgumentError;
}

View File

@@ -206,7 +206,7 @@ class App : public ElectronBrowserClient::Delegate,
bool IsAccessibilitySupportEnabled();
void SetAccessibilitySupportEnabled(gin_helper::ErrorThrower thrower,
bool enabled);
v8::Local<v8::Value> GetLoginItemSettings(gin::Arguments* args);
Browser::LoginItemSettings GetLoginItemSettings(gin::Arguments* args);
#if BUILDFLAG(USE_NSS_CERTS)
void ImportCertificate(gin_helper::ErrorThrower thrower,
base::Value options,

View File

@@ -117,6 +117,11 @@ BaseWindow::BaseWindow(gin_helper::Arguments* args,
BaseWindow::~BaseWindow() {
CloseImmediately();
// Destroy the native window in next tick because the native code might be
// iterating all windows.
base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(
FROM_HERE, window_.release());
// Remove global reference so the JS object can be garbage collected.
self_ref_.Reset();
}

View File

@@ -12,12 +12,10 @@
#include <vector>
#include "base/command_line.h"
#include "base/containers/fixed_flat_map.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/uuid.h"
@@ -34,14 +32,11 @@
#include "content/browser/code_cache/generated_code_cache_context.h" // nogncheck
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
#include "gin/arguments.h"
#include "gin/converter.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/completion_repeating_callback.h"
@@ -82,14 +77,12 @@
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_includes.h"
#include "shell/common/options_switches.h"
#include "shell/common/process_util.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/origin.h"
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
@@ -110,8 +103,6 @@
#endif
using content::BrowserThread;
using content::BrowsingDataFilterBuilder;
using content::BrowsingDataRemover;
using content::StoragePartition;
namespace {
@@ -123,23 +114,25 @@ struct ClearStorageDataOptions {
};
uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
static constexpr auto Lookup =
base::MakeFixedFlatMap<std::string_view, uint32_t>(
{{"cookies", StoragePartition::REMOVE_DATA_MASK_COOKIES},
{"filesystem", StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS},
{"indexdb", StoragePartition::REMOVE_DATA_MASK_INDEXEDDB},
{"localstorage", StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE},
{"shadercache", StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE},
{"websql", StoragePartition::REMOVE_DATA_MASK_WEBSQL},
{"serviceworkers",
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS},
{"cachestorage", StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE}});
uint32_t storage_mask = 0;
for (const auto& it : storage_types) {
auto type = base::ToLowerASCII(it);
if (Lookup.contains(type))
storage_mask |= Lookup.at(type);
if (type == "cookies")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
else if (type == "filesystem")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
else if (type == "indexdb")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
else if (type == "localstorage")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
else if (type == "shadercache")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
else if (type == "websql")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
else if (type == "serviceworkers")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
else if (type == "cachestorage")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
}
return storage_mask;
}
@@ -156,204 +149,6 @@ uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
return quota_mask;
}
constexpr BrowsingDataRemover::DataType kClearDataTypeAll = ~0ULL;
constexpr BrowsingDataRemover::OriginType kClearOriginTypeAll =
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
constexpr auto kDataTypeLookup =
base::MakeFixedFlatMap<std::string_view, BrowsingDataRemover::DataType>({
{"backgroundFetch", BrowsingDataRemover::DATA_TYPE_BACKGROUND_FETCH},
{"cache", BrowsingDataRemover::DATA_TYPE_CACHE |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE},
{"cookies", BrowsingDataRemover::DATA_TYPE_COOKIES},
{"downloads", BrowsingDataRemover::DATA_TYPE_DOWNLOADS},
{"fileSystems", BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS},
{"indexedDB", BrowsingDataRemover::DATA_TYPE_INDEXED_DB},
{"localStorage", BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE},
{"serviceWorkers", BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS},
{"webSQL", BrowsingDataRemover::DATA_TYPE_WEB_SQL},
});
BrowsingDataRemover::DataType GetDataTypeMask(
const std::vector<std::string>& data_types) {
BrowsingDataRemover::DataType mask = 0u;
for (const auto& type : data_types) {
if (kDataTypeLookup.contains(type)) {
mask |= kDataTypeLookup.at(type);
}
}
return mask;
}
std::vector<std::string> GetDataTypesFromMask(
BrowsingDataRemover::DataType mask) {
std::vector<std::string> results;
for (const auto [type, flag] : kDataTypeLookup) {
if (mask & flag) {
results.emplace_back(type);
}
}
return results;
}
// Represents a task to clear browsing data for the `clearData` API method.
//
// This type manages its own lifetime, deleting itself once the task finishes
// completely.
class ClearDataTask {
public:
// Starts running a task. This function will return before the task is
// finished, but will resolve or reject the |promise| when it finishes.
static void Run(
BrowsingDataRemover* remover,
gin_helper::Promise<void> promise,
BrowsingDataRemover::DataType data_type_mask,
std::vector<url::Origin> origins,
BrowsingDataFilterBuilder::Mode filter_mode,
BrowsingDataFilterBuilder::OriginMatchingMode origin_matching_mode) {
std::shared_ptr<ClearDataTask> task(new ClearDataTask(std::move(promise)));
// This method counts as an operation. This is important so we can call
// `OnOperationFinished` at the end of this method as a fallback if all the
// other operations finished while this method was still executing
task->operations_running_ = 1;
// Cookies are scoped more broadly than other types of data, so if we are
// filtering then we need to do it at the registrable domain level
if (!origins.empty() &&
data_type_mask & BrowsingDataRemover::DATA_TYPE_COOKIES) {
data_type_mask &= ~BrowsingDataRemover::DATA_TYPE_COOKIES;
auto cookies_filter_builder =
BrowsingDataFilterBuilder::Create(filter_mode);
for (const url::Origin& origin : origins) {
std::string domain = GetDomainAndRegistry(
origin,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
if (domain.empty()) {
domain = origin.host();
}
cookies_filter_builder->AddRegisterableDomain(domain);
}
StartOperation(task, remover, BrowsingDataRemover::DATA_TYPE_COOKIES,
std::move(cookies_filter_builder));
}
// If cookies aren't the only data type and weren't handled above, then we
// can start an operation that is scoped to origins
if (data_type_mask) {
auto filter_builder =
BrowsingDataFilterBuilder::Create(filter_mode, origin_matching_mode);
for (auto const& origin : origins) {
filter_builder->AddOrigin(origin);
}
StartOperation(task, remover, data_type_mask, std::move(filter_builder));
}
// This static method counts as an operation.
task->OnOperationFinished(std::nullopt);
}
private:
// An individiual |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.
class ClearDataOperation : public BrowsingDataRemover::Observer {
public:
static void Run(std::shared_ptr<ClearDataTask> task,
BrowsingDataRemover* remover,
BrowsingDataRemover::DataType data_type_mask,
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
auto* operation = new ClearDataOperation(task, remover);
remover->RemoveWithFilterAndReply(base::Time::Min(), base::Time::Max(),
data_type_mask, kClearOriginTypeAll,
std::move(filter_builder), operation);
}
// BrowsingDataRemover::Observer:
void OnBrowsingDataRemoverDone(
BrowsingDataRemover::DataType failed_data_types) override {
task_->OnOperationFinished(failed_data_types);
delete this;
}
private:
ClearDataOperation(std::shared_ptr<ClearDataTask> task,
BrowsingDataRemover* remover)
: task_(task) {
observation_.Observe(remover);
}
std::shared_ptr<ClearDataTask> task_;
base::ScopedObservation<BrowsingDataRemover, BrowsingDataRemover::Observer>
observation_{this};
};
explicit ClearDataTask(gin_helper::Promise<void> promise)
: promise_(std::move(promise)) {}
static void StartOperation(
std::shared_ptr<ClearDataTask> task,
BrowsingDataRemover* remover,
BrowsingDataRemover::DataType data_type_mask,
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
// Track this operation
task->operations_running_ += 1;
ClearDataOperation::Run(task, remover, data_type_mask,
std::move(filter_builder));
}
void OnOperationFinished(
std::optional<BrowsingDataRemover::DataType> failed_data_types) {
DCHECK_GT(operations_running_, 0);
operations_running_ -= 1;
if (failed_data_types.has_value()) {
failed_data_types_ |= failed_data_types.value();
}
// If this is the last operation, then the task is finished
if (operations_running_ == 0) {
OnTaskFinished();
}
}
void OnTaskFinished() {
if (failed_data_types_ == 0ULL) {
promise_.Resolve();
} else {
v8::Isolate* isolate = promise_.isolate();
v8::Local<v8::Value> failed_data_types_array =
gin::ConvertToV8(isolate, GetDataTypesFromMask(failed_data_types_));
// Create a rich error object with extra detail about what data types
// failed
auto error = v8::Exception::Error(
gin::StringToV8(isolate, "Failed to clear data"));
error.As<v8::Object>()
->Set(promise_.GetContext(),
gin::StringToV8(isolate, "failedDataTypes"),
failed_data_types_array)
.Check();
promise_.Reject(error);
}
}
int operations_running_ = 0;
BrowsingDataRemover::DataType failed_data_types_ = 0ULL;
gin_helper::Promise<void> promise_;
};
base::Value::Dict createProxyConfig(ProxyPrefs::ProxyMode proxy_mode,
std::string const& pac_url,
std::string const& proxy_server,
@@ -1306,89 +1101,6 @@ v8::Local<v8::Promise> Session::ClearCodeCaches(
return handle;
}
v8::Local<v8::Value> Session::ClearData(gin_helper::ErrorThrower thrower,
gin::Arguments* args) {
auto* isolate = JavascriptEnvironment::GetIsolate();
BrowsingDataRemover::DataType data_type_mask = kClearDataTypeAll;
std::vector<url::Origin> origins;
BrowsingDataFilterBuilder::OriginMatchingMode origin_matching_mode =
BrowsingDataFilterBuilder::OriginMatchingMode::kThirdPartiesIncluded;
BrowsingDataFilterBuilder::Mode filter_mode =
BrowsingDataFilterBuilder::Mode::kPreserve;
if (gin_helper::Dictionary options; args->GetNext(&options)) {
if (std::vector<std::string> data_types;
options.Get("dataTypes", &data_types)) {
data_type_mask = GetDataTypeMask(data_types);
}
if (bool avoid_closing_connections;
options.Get("avoidClosingConnections", &avoid_closing_connections) &&
avoid_closing_connections) {
data_type_mask |=
BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS;
}
std::vector<GURL> origin_urls;
{
bool has_origins_key = options.Get("origins", &origin_urls);
std::vector<GURL> exclude_origin_urls;
bool has_exclude_origins_key =
options.Get("excludeOrigins", &exclude_origin_urls);
if (has_origins_key && has_exclude_origins_key) {
thrower.ThrowError(
"Cannot provide both 'origins' and 'excludeOrigins'");
return v8::Undefined(isolate);
}
if (has_origins_key) {
filter_mode = BrowsingDataFilterBuilder::Mode::kDelete;
} else if (has_exclude_origins_key) {
origin_urls = std::move(exclude_origin_urls);
}
}
if (!origin_urls.empty()) {
origins.reserve(origin_urls.size());
for (const GURL& origin_url : origin_urls) {
auto origin = url::Origin::Create(origin_url);
// Opaque origins cannot be used with this API
if (origin.opaque()) {
thrower.ThrowError(
base::StringPrintf("Invalid origin: '%s'",
origin_url.possibly_invalid_spec().c_str()));
return v8::Undefined(isolate);
}
origins.push_back(std::move(origin));
}
}
if (std::string origin_matching_mode_string;
options.Get("originMatchingMode", &origin_matching_mode_string)) {
if (origin_matching_mode_string == "third-parties-included") {
origin_matching_mode = BrowsingDataFilterBuilder::OriginMatchingMode::
kThirdPartiesIncluded;
} else if (origin_matching_mode_string == "origin-in-all-contexts") {
origin_matching_mode =
BrowsingDataFilterBuilder::OriginMatchingMode::kOriginInAllContexts;
}
}
}
gin_helper::Promise<void> promise(isolate);
v8::Local<v8::Promise> promise_handle = promise.GetHandle();
BrowsingDataRemover* remover = browser_context_->GetBrowsingDataRemover();
ClearDataTask::Run(remover, std::move(promise), data_type_mask,
std::move(origins), filter_mode, origin_matching_mode);
return promise_handle;
}
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
base::Value Session::GetSpellCheckerLanguages() {
return browser_context_->prefs()
@@ -1658,7 +1370,6 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
.SetMethod("getStoragePath", &Session::GetPath)
.SetMethod("setCodeCachePath", &Session::SetCodeCachePath)
.SetMethod("clearCodeCaches", &Session::ClearCodeCaches)
.SetMethod("clearData", &Session::ClearData)
.SetProperty("cookies", &Session::Cookies)
.SetProperty("netLog", &Session::NetLog)
.SetProperty("protocol", &Session::Protocol)

View File

@@ -147,8 +147,6 @@ class Session : public gin::Wrappable<Session>,
v8::Local<v8::Value> GetPath(v8::Isolate* isolate);
void SetCodeCachePath(gin::Arguments* args);
v8::Local<v8::Promise> ClearCodeCaches(const gin_helper::Dictionary& options);
v8::Local<v8::Value> ClearData(gin_helper::ErrorThrower thrower,
gin::Arguments* args);
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
base::Value GetSpellCheckerLanguages();
void SetSpellCheckerLanguages(gin_helper::ErrorThrower thrower,

View File

@@ -352,20 +352,6 @@ struct Converter<scoped_refptr<content::DevToolsAgentHost>> {
}
};
template <>
struct Converter<content::NavigationEntry*> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
content::NavigationEntry* entry) {
if (!entry) {
return v8::Null(isolate);
}
gin_helper::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("url", entry->GetURL().spec());
dict.Set("title", entry->GetTitleForDisplay());
return dict.GetHandle();
}
};
} // namespace gin
namespace electron::api {
@@ -1753,6 +1739,23 @@ void WebContents::RenderFrameHostChanged(content::RenderFrameHost* old_host,
if (new_host)
new_host->GetRenderWidgetHost()->AddInputEventObserver(this);
}
// During cross-origin navigation, a FrameTreeNode will swap out its RFH.
// If an instance of WebFrameMain exists, it will need to have its RFH
// swapped as well.
//
// |old_host| can be a nullptr so we use |new_host| for looking up the
// WebFrameMain instance.
auto* web_frame = WebFrameMain::FromRenderFrameHost(new_host);
if (web_frame) {
web_frame->UpdateRenderFrameHost(new_host);
}
}
void WebContents::FrameDeleted(int frame_tree_node_id) {
auto* web_frame = WebFrameMain::FromFrameTreeNodeId(frame_tree_node_id);
if (web_frame)
web_frame->Destroyed();
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
@@ -2557,11 +2560,6 @@ int WebContents::GetActiveIndex() const {
return web_contents()->GetController().GetCurrentEntryIndex();
}
content::NavigationEntry* WebContents::GetNavigationEntryAtIndex(
int index) const {
return web_contents()->GetController().GetEntryAtIndex(index);
}
void WebContents::ClearHistory() {
// In some rare cases (normally while there is no real history) we are in a
// state where we can't prune navigation entries
@@ -4355,11 +4353,9 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
.SetMethod("goToOffset", &WebContents::GoToOffset)
.SetMethod("canGoToIndex", &WebContents::CanGoToIndex)
.SetMethod("goToIndex", &WebContents::GoToIndex)
.SetMethod("_getActiveIndex", &WebContents::GetActiveIndex)
.SetMethod("_getNavigationEntryAtIndex",
&WebContents::GetNavigationEntryAtIndex)
.SetMethod("_historyLength", &WebContents::GetHistoryLength)
.SetMethod("getActiveIndex", &WebContents::GetActiveIndex)
.SetMethod("clearHistory", &WebContents::ClearHistory)
.SetMethod("length", &WebContents::GetHistoryLength)
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("forcefullyCrashRenderer",
&WebContents::ForcefullyCrashRenderer)

View File

@@ -194,7 +194,6 @@ class WebContents : public ExclusiveAccessContext,
bool CanGoToIndex(int index) const;
void GoToIndex(int index);
int GetActiveIndex() const;
content::NavigationEntry* GetNavigationEntryAtIndex(int index) const;
void ClearHistory();
int GetHistoryLength() const;
const std::string GetWebRTCIPHandlingPolicy() const;
@@ -628,6 +627,7 @@ class WebContents : public ExclusiveAccessContext,
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void RenderFrameHostChanged(content::RenderFrameHost* old_host,
content::RenderFrameHost* new_host) override;
void FrameDeleted(int frame_tree_node_id) override;
void RenderViewDeleted(content::RenderViewHost*) override;
void PrimaryMainFrameRenderProcessGone(
base::TerminationStatus status) override;

View File

@@ -24,14 +24,29 @@
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
#if BUILDFLAG(IS_MAC)
#include "shell/browser/ui/cocoa/delayed_native_view_host.h"
#endif
namespace electron::api {
WebContentsView::WebContentsView(v8::Isolate* isolate,
gin::Handle<WebContents> web_contents)
: View(web_contents->inspectable_web_contents()->GetView()),
#if BUILDFLAG(IS_MAC)
: View(new DelayedNativeViewHost(web_contents->inspectable_web_contents()
->GetView()
->GetNativeView())),
#else
: View(web_contents->inspectable_web_contents()->GetView()->GetView()),
#endif
web_contents_(isolate, web_contents.ToV8()),
api_web_contents_(web_contents.get()) {
#if !BUILDFLAG(IS_MAC)
// On macOS the View is a newly-created |DelayedNativeViewHost| and it is our
// responsibility to delete it. On other platforms the View is created and
// managed by InspectableWebContents.
set_delete_view(false);
#endif
view()->SetProperty(
views::kFlexBehaviorKey,
views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,

View File

@@ -55,32 +55,41 @@ struct Converter<blink::mojom::PageVisibilityState> {
namespace electron::api {
typedef std::unordered_map<blink::LocalFrameToken,
WebFrameMain*,
blink::LocalFrameToken::Hasher>
WebFrameMainIdMap;
typedef std::unordered_map<int, WebFrameMain*> WebFrameMainIdMap;
WebFrameMainIdMap& GetWebFrameMainMap() {
static base::NoDestructor<WebFrameMainIdMap> instance;
return *instance;
}
// static
WebFrameMain* WebFrameMain::FromFrameTreeNodeId(int frame_tree_node_id) {
WebFrameMainIdMap& frame_map = GetWebFrameMainMap();
auto iter = frame_map.find(frame_tree_node_id);
auto* web_frame = iter == frame_map.end() ? nullptr : iter->second;
return web_frame;
}
// static
WebFrameMain* WebFrameMain::FromRenderFrameHost(content::RenderFrameHost* rfh) {
if (!rfh)
return nullptr;
WebFrameMainIdMap& frame_map = GetWebFrameMainMap();
auto iter = frame_map.find(rfh->GetGlobalFrameToken().frame_token);
auto* web_frame = iter == frame_map.end() ? nullptr : iter->second;
return web_frame;
// TODO(codebytere): remove after refactoring away from FrameTreeNodeId as map
// key.
auto* ftn =
static_cast<content::RenderFrameHostImpl*>(rfh)->frame_tree_node();
if (!ftn)
return nullptr;
return FromFrameTreeNodeId(rfh->GetFrameTreeNodeId());
}
gin::WrapperInfo WebFrameMain::kWrapperInfo = {gin::kEmbedderNativeGin};
WebFrameMain::WebFrameMain(content::RenderFrameHost* rfh)
: rfh_token_(rfh->GetGlobalFrameToken()), render_frame_(rfh) {
GetWebFrameMainMap().emplace(rfh_token_.frame_token, this);
: frame_tree_node_id_(rfh->GetFrameTreeNodeId()), render_frame_(rfh) {
GetWebFrameMainMap().emplace(frame_tree_node_id_, this);
}
WebFrameMain::~WebFrameMain() {
@@ -89,7 +98,7 @@ WebFrameMain::~WebFrameMain() {
void WebFrameMain::Destroyed() {
MarkRenderFrameDisposed();
GetWebFrameMainMap().erase(rfh_token_.frame_token);
GetWebFrameMainMap().erase(frame_tree_node_id_);
Unpin();
}
@@ -261,7 +270,7 @@ void WebFrameMain::PostMessage(v8::Isolate* isolate,
}
int WebFrameMain::FrameTreeNodeID() const {
return 0;
return frame_tree_node_id_;
}
std::string WebFrameMain::Name() const {

View File

@@ -12,7 +12,6 @@
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "content/public/browser/global_routing_id.h"
#include "gin/handle.h"
#include "gin/wrappable.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -50,6 +49,7 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
static gin::Handle<WebFrameMain> FromOrNull(
v8::Isolate* isolate,
content::RenderFrameHost* render_frame_host);
static WebFrameMain* FromFrameTreeNodeId(int frame_tree_node_id);
static WebFrameMain* FromRenderFrameHost(
content::RenderFrameHost* render_frame_host);
@@ -125,7 +125,7 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
mojo::Remote<mojom::ElectronRenderer> renderer_api_;
mojo::PendingReceiver<mojom::ElectronRenderer> pending_receiver_;
content::GlobalRenderFrameHostToken rfh_token_;
int frame_tree_node_id_;
raw_ptr<content::RenderFrameHost> render_frame_ = nullptr;

View File

@@ -27,16 +27,6 @@
namespace electron {
LoginItemSettings::LoginItemSettings() = default;
LoginItemSettings::~LoginItemSettings() = default;
LoginItemSettings::LoginItemSettings(const LoginItemSettings& other) = default;
#if BUILDFLAG(IS_WIN)
LaunchItem::LaunchItem() = default;
LaunchItem::~LaunchItem() = default;
LaunchItem::LaunchItem(const LaunchItem& other) = default;
#endif
namespace {
// Call |quit| after Chromium is fully started.
@@ -53,6 +43,17 @@ void RunQuitClosure(base::OnceClosure quit) {
} // namespace
#if BUILDFLAG(IS_WIN)
Browser::LaunchItem::LaunchItem() = default;
Browser::LaunchItem::~LaunchItem() = default;
Browser::LaunchItem::LaunchItem(const LaunchItem& other) = default;
#endif
Browser::LoginItemSettings::LoginItemSettings() = default;
Browser::LoginItemSettings::~LoginItemSettings() = default;
Browser::LoginItemSettings::LoginItemSettings(const LoginItemSettings& other) =
default;
Browser::Browser() {
WindowList::AddObserver(this);
}

View File

@@ -17,7 +17,6 @@
#include "gin/dictionary.h"
#include "shell/browser/browser_observer.h"
#include "shell/browser/window_list_observer.h"
#include "shell/common/gin_converters/login_item_settings_converter.h"
#include "shell/common/gin_helper/promise.h"
#if BUILDFLAG(IS_WIN)
@@ -42,48 +41,6 @@ namespace electron {
class ElectronMenuModel;
#if BUILDFLAG(IS_WIN)
struct LaunchItem {
std::wstring name;
std::wstring path;
std::wstring scope;
std::vector<std::wstring> args;
bool enabled = true;
LaunchItem();
~LaunchItem();
LaunchItem(const LaunchItem&);
};
#endif
struct LoginItemSettings {
bool open_at_login = false;
bool open_as_hidden = false;
bool restore_state = false;
bool opened_at_login = false;
bool opened_as_hidden = false;
std::u16string path;
std::vector<std::u16string> args;
#if BUILDFLAG(IS_MAC)
std::string type = "mainAppService";
std::string service_name;
std::string status;
#elif BUILDFLAG(IS_WIN)
// used in browser::setLoginItemSettings
bool enabled = true;
std::wstring name;
// used in browser::getLoginItemSettings
bool executable_will_launch_at_login = false;
std::vector<LaunchItem> launch_items;
#endif
LoginItemSettings();
~LoginItemSettings();
LoginItemSettings(const LoginItemSettings&);
};
// This class is used for control application-wide operations.
class Browser : public WindowListObserver {
public:
@@ -155,8 +112,50 @@ class Browser : public WindowListObserver {
bool SetBadgeCount(std::optional<int> count);
[[nodiscard]] int badge_count() const { return badge_count_; }
#if BUILDFLAG(IS_WIN)
struct LaunchItem {
std::wstring name;
std::wstring path;
std::wstring scope;
std::vector<std::wstring> args;
bool enabled = true;
LaunchItem();
~LaunchItem();
LaunchItem(const LaunchItem&);
};
#endif
// Set/Get the login item settings of the app
struct LoginItemSettings {
bool open_at_login = false;
bool open_as_hidden = false;
bool restore_state = false;
bool opened_at_login = false;
bool opened_as_hidden = false;
std::u16string path;
std::vector<std::u16string> args;
#if BUILDFLAG(IS_MAC)
std::string type = "mainAppService";
std::string service_name;
std::string status;
#elif BUILDFLAG(IS_WIN)
// used in browser::setLoginItemSettings
bool enabled = true;
std::wstring name;
// used in browser::getLoginItemSettings
bool executable_will_launch_at_login = false;
std::vector<LaunchItem> launch_items;
#endif
LoginItemSettings();
~LoginItemSettings();
LoginItemSettings(const LoginItemSettings&);
};
void SetLoginItemSettings(LoginItemSettings settings);
v8::Local<v8::Value> GetLoginItemSettings(const LoginItemSettings& options);
LoginItemSettings GetLoginItemSettings(const LoginItemSettings& options);
#if BUILDFLAG(IS_MAC)
// Set the handler which decides whether to shutdown.

View File

@@ -11,11 +11,9 @@
#include "base/environment.h"
#include "base/process/launch.h"
#include "electron/electron_version.h"
#include "shell/browser/javascript_environment.h"
#include "shell/browser/native_window.h"
#include "shell/browser/window_list.h"
#include "shell/common/application_info.h"
#include "shell/common/gin_converters/login_item_settings_converter.h"
#include "shell/common/thread_restrictions.h"
#if BUILDFLAG(IS_LINUX)
@@ -140,10 +138,9 @@ bool Browser::SetBadgeCount(std::optional<int> count) {
void Browser::SetLoginItemSettings(LoginItemSettings settings) {}
v8::Local<v8::Value> Browser::GetLoginItemSettings(
Browser::LoginItemSettings Browser::GetLoginItemSettings(
const LoginItemSettings& options) {
LoginItemSettings settings;
return gin::ConvertToV8(JavascriptEnvironment::GetIsolate(), settings);
return LoginItemSettings();
}
std::string Browser::GetExecutableFileVersion() const {

View File

@@ -29,7 +29,6 @@
#include "shell/common/api/electron_api_native_image.h"
#include "shell/common/application_info.h"
#include "shell/common/gin_converters/image_converter.h"
#include "shell/common/gin_converters/login_item_settings_converter.h"
#include "shell/common/gin_helper/arguments.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/error_thrower.h"
@@ -89,8 +88,8 @@ bool CheckLoginItemStatus(bool* is_hidden) {
return true;
}
LoginItemSettings GetLoginItemSettingsDeprecated() {
LoginItemSettings settings;
Browser::LoginItemSettings GetLoginItemSettingsDeprecated() {
Browser::LoginItemSettings settings;
settings.open_at_login = CheckLoginItemStatus(&settings.open_as_hidden);
settings.restore_state = base::mac::WasLaunchedAsLoginItemRestoreState();
settings.opened_at_login = base::mac::WasLaunchedAsLoginOrResumeItem();
@@ -376,15 +375,13 @@ void Browser::ApplyForcedRTL() {
}
}
v8::Local<v8::Value> Browser::GetLoginItemSettings(
Browser::LoginItemSettings Browser::GetLoginItemSettings(
const LoginItemSettings& options) {
LoginItemSettings settings;
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
if (options.type != "mainAppService" && options.service_name.empty()) {
gin_helper::ErrorThrower(isolate).ThrowTypeError(
"'name' is required when type is not mainAppService");
return v8::Local<v8::Value>();
gin_helper::ErrorThrower(JavascriptEnvironment::GetIsolate())
.ThrowTypeError("'name' is required when type is not mainAppService");
return settings;
}
#if IS_MAS_BUILD()
@@ -411,7 +408,7 @@ v8::Local<v8::Value> Browser::GetLoginItemSettings(
settings = settings_deprecated;
}
#endif
return gin::ConvertToV8(isolate, settings);
return settings;
}
void Browser::SetLoginItemSettings(LoginItemSettings settings) {

View File

@@ -30,19 +30,16 @@
#include "shell/browser/api/electron_api_app.h"
#include "shell/browser/badging/badge_manager.h"
#include "shell/browser/electron_browser_main_parts.h"
#include "shell/browser/javascript_environment.h"
#include "shell/browser/ui/message_box.h"
#include "shell/browser/ui/win/jump_list.h"
#include "shell/browser/window_list.h"
#include "shell/common/application_info.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_converters/image_converter.h"
#include "shell/common/gin_converters/login_item_settings_converter.h"
#include "shell/common/gin_helper/arguments.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/skia_util.h"
#include "shell/common/thread_restrictions.h"
#include "skia/ext/font_utils.h"
#include "skia/ext/legacy_display_globals.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkFont.h"
@@ -156,12 +153,12 @@ bool FormatCommandLineString(std::wstring* exe,
// a list of launchItem with matching paths to our application.
// if a launchItem with a matching path also has a matching entry within the
// startup_approved_key_path, set executable_will_launch_at_login to be `true`
std::vector<LaunchItem> GetLoginItemSettingsHelper(
std::vector<Browser::LaunchItem> GetLoginItemSettingsHelper(
base::win::RegistryValueIterator* it,
boolean* executable_will_launch_at_login,
std::wstring scope,
const LoginItemSettings& options) {
std::vector<LaunchItem> launch_items;
const Browser::LoginItemSettings& options) {
std::vector<Browser::LaunchItem> launch_items;
base::FilePath lookup_exe_path;
if (options.path.empty()) {
@@ -185,7 +182,7 @@ std::vector<LaunchItem> GetLoginItemSettingsHelper(
// add launch item to vector if it has a matching path (case-insensitive)
if (exe_match) {
LaunchItem launch_item;
Browser::LaunchItem launch_item;
launch_item.name = it->Name();
launch_item.path = registry_launch_path.value();
launch_item.args = registry_launch_cmd.GetArgs();
@@ -594,7 +591,7 @@ void Browser::UpdateBadgeContents(
paint.reset();
paint.setColor(kForegroundColor);
SkFont font = skia::DefaultFont();
SkFont font;
SkRect bounds;
int text_size = kMaxTextSize;
@@ -658,7 +655,7 @@ void Browser::SetLoginItemSettings(LoginItemSettings settings) {
}
}
v8::Local<v8::Value> Browser::GetLoginItemSettings(
Browser::LoginItemSettings Browser::GetLoginItemSettings(
const LoginItemSettings& options) {
LoginItemSettings settings;
std::wstring keyPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
@@ -677,7 +674,7 @@ v8::Local<v8::Value> Browser::GetLoginItemSettings(
// if there exists a launch entry with property enabled=='true',
// set executable_will_launch_at_login to 'true'.
boolean executable_will_launch_at_login = false;
std::vector<LaunchItem> launch_items;
std::vector<Browser::LaunchItem> launch_items;
base::win::RegistryValueIterator hkcu_iterator(HKEY_CURRENT_USER,
keyPath.c_str());
base::win::RegistryValueIterator hklm_iterator(HKEY_LOCAL_MACHINE,
@@ -685,14 +682,16 @@ v8::Local<v8::Value> Browser::GetLoginItemSettings(
launch_items = GetLoginItemSettingsHelper(
&hkcu_iterator, &executable_will_launch_at_login, L"user", options);
std::vector<LaunchItem> launch_items_hklm = GetLoginItemSettingsHelper(
&hklm_iterator, &executable_will_launch_at_login, L"machine", options);
std::vector<Browser::LaunchItem> launch_items_hklm =
GetLoginItemSettingsHelper(&hklm_iterator,
&executable_will_launch_at_login, L"machine",
options);
launch_items.insert(launch_items.end(), launch_items_hklm.begin(),
launch_items_hklm.end());
settings.executable_will_launch_at_login = executable_will_launch_at_login;
settings.launch_items = launch_items;
return gin::ConvertToV8(JavascriptEnvironment::GetIsolate(), settings);
return settings;
}
PCWSTR Browser::GetAppUserModelID() {

View File

@@ -22,7 +22,6 @@
#include "extensions/browser/api/scripting/scripting_utils.h"
#include "extensions/browser/extension_api_frame_id_map.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_user_script_loader.h"
#include "extensions/browser/extension_util.h"
@@ -1062,17 +1061,6 @@ void ScriptingRegisterContentScriptsFunction::OnContentScriptFilesValidated(
return;
}
// We cannot proceed if the extension is uninstalled or unloaded in the middle
// of validating its script files.
ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
if (!extension() ||
!registry->enabled_extensions().Contains(extension_id())) {
// Note: a Respond() is not needed if the system is shutting down or if the
// extension is no longer enabled.
Release(); // Matches the `AddRef()` in `Run()`.
return;
}
auto error = std::move(result.second);
auto scripts = std::move(result.first);
ExtensionUserScriptLoader* loader =
@@ -1318,17 +1306,6 @@ void ScriptingUpdateContentScriptsFunction::OnContentScriptFilesValidated(
return;
}
// We cannot proceed if the extension is uninstalled or unloaded in the middle
// of validating its script files.
ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
if (!extension() ||
!registry->enabled_extensions().Contains(extension_id())) {
// Note: a Respond() is not needed if the system is shutting down or if the
// extension is no longer enabled.
Release(); // Matches the `AddRef()` in `Run()`.
return;
}
auto error = std::move(result.second);
auto scripts = std::move(result.first);
ExtensionUserScriptLoader* loader =

View File

@@ -6,8 +6,6 @@
#include <string>
#include "base/dcheck_is_on.h"
namespace electron {
std::string EnablePlatformSpecificFeatures() {
@@ -21,12 +19,8 @@ std::string EnablePlatformSpecificFeatures() {
// chrome/browser/media/webrtc/thumbnail_capturer_mac.mm
// kThumbnailCapturerMac,
// chrome/browser/media/webrtc/thumbnail_capturer_mac.mm
#if DCHECK_IS_ON()
return "";
#else
return "ScreenCaptureKitPickerScreen,ScreenCaptureKitStreamPickerSonoma,"
"ThumbnailCapturerMac:capture_mode/sc_screenshot_manager";
#endif
}
return "";
}

View File

@@ -242,7 +242,6 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
params.bounds = bounds;
params.delegate = this;
params.type = views::Widget::InitParams::TYPE_WINDOW;
params.headless_mode = true;
params.native_widget =
new ElectronNativeWidgetMac(this, windowType, styleMask, widget());
widget()->Init(std::move(params));

View File

@@ -28,7 +28,7 @@
#include "content/public/browser/desktop_media_id.h"
#include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/ui/views/inspectable_web_contents_view_views.h"
#include "shell/browser/ui/views/root_view.h"
#include "shell/browser/web_contents_preferences.h"
#include "shell/browser/web_view_manager.h"

View File

@@ -159,21 +159,21 @@ void LibnotifyNotification::Show(const NotificationOptions& options) {
void LibnotifyNotification::Dismiss() {
if (!notification_) {
Destroy();
return;
}
GError* error = nullptr;
on_dismissing_ = true;
libnotify_loader_.notify_notification_close(notification_, &error);
if (error) {
log_and_clear_error(error, "notify_notification_close");
Destroy();
}
on_dismissing_ = false;
}
void LibnotifyNotification::OnNotificationClosed(
NotifyNotification* notification) {
NotificationDismissed(!on_dismissing_);
NotificationDismissed();
}
void LibnotifyNotification::OnNotificationView(NotifyNotification* notification,

View File

@@ -33,7 +33,6 @@ class LibnotifyNotification : public Notification {
RAW_PTR_EXCLUSION NotifyNotification* notification_ = nullptr;
ScopedGSignal signal_;
bool on_dismissing_ = false;
};
} // namespace electron

View File

@@ -35,9 +35,7 @@ std::unique_ptr<content::SerialChooser> ElectronSerialDelegate::RunChooser(
if (controller) {
DeleteControllerForFrame(frame);
}
AddControllerForFrame(frame, std::move(filters),
std::move(allowed_bluetooth_service_class_ids),
std::move(callback));
AddControllerForFrame(frame, std::move(filters), std::move(callback));
// Return a nullptr because the return value isn't used for anything, eg
// there is no mechanism to cancel navigator.serial.requestPort(). The return
@@ -108,14 +106,12 @@ SerialChooserController* ElectronSerialDelegate::ControllerForFrame(
SerialChooserController* ElectronSerialDelegate::AddControllerForFrame(
content::RenderFrameHost* render_frame_host,
std::vector<blink::mojom::SerialPortFilterPtr> filters,
std::vector<device::BluetoothUUID> allowed_bluetooth_service_class_ids,
content::SerialChooser::Callback callback) {
auto* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
auto controller = std::make_unique<SerialChooserController>(
render_frame_host, std::move(filters),
std::move(allowed_bluetooth_service_class_ids), std::move(callback),
web_contents, weak_factory_.GetWeakPtr());
render_frame_host, std::move(filters), std::move(callback), web_contents,
weak_factory_.GetWeakPtr());
controller_map_.insert(
std::make_pair(render_frame_host, std::move(controller)));
return ControllerForFrame(render_frame_host);

View File

@@ -67,7 +67,6 @@ class ElectronSerialDelegate : public content::SerialDelegate,
SerialChooserController* AddControllerForFrame(
content::RenderFrameHost* render_frame_host,
std::vector<blink::mojom::SerialPortFilterPtr> filters,
std::vector<device::BluetoothUUID> allowed_bluetooth_service_class_ids,
content::SerialChooser::Callback callback);
base::ScopedObservation<SerialChooserContext,

View File

@@ -11,9 +11,6 @@
#include "base/functional/bind.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "services/device/public/cpp/bluetooth/bluetooth_utils.h"
#include "services/device/public/mojom/serial.mojom.h"
#include "shell/browser/api/electron_api_session.h"
#include "shell/browser/serial/serial_chooser_context.h"
#include "shell/browser/serial/serial_chooser_context_factory.h"
@@ -61,57 +58,14 @@ struct Converter<device::mojom::SerialPortInfoPtr> {
namespace electron {
namespace {
using ::device::mojom::SerialPortType;
bool FilterMatchesPort(const blink::mojom::SerialPortFilter& filter,
const device::mojom::SerialPortInfo& port) {
if (filter.bluetooth_service_class_id) {
if (!port.bluetooth_service_class_id) {
return false;
}
return device::BluetoothUUID(*port.bluetooth_service_class_id) ==
device::BluetoothUUID(*filter.bluetooth_service_class_id);
}
if (!filter.has_vendor_id) {
return true;
}
if (!port.has_vendor_id || port.vendor_id != filter.vendor_id) {
return false;
}
if (!filter.has_product_id) {
return true;
}
return port.has_product_id && port.product_id == filter.product_id;
}
bool BluetoothPortIsAllowed(
const std::vector<::device::BluetoothUUID>& allowed_ids,
const device::mojom::SerialPortInfo& port) {
if (!port.bluetooth_service_class_id) {
return true;
}
// Serial Port Profile is allowed by default.
if (*port.bluetooth_service_class_id == device::GetSerialPortProfileUUID()) {
return true;
}
return base::Contains(allowed_ids, port.bluetooth_service_class_id.value());
}
} // namespace
SerialChooserController::SerialChooserController(
content::RenderFrameHost* render_frame_host,
std::vector<blink::mojom::SerialPortFilterPtr> filters,
std::vector<::device::BluetoothUUID> allowed_bluetooth_service_class_ids,
content::SerialChooser::Callback callback,
content::WebContents* web_contents,
base::WeakPtr<ElectronSerialDelegate> serial_delegate)
: WebContentsObserver(web_contents),
filters_(std::move(filters)),
allowed_bluetooth_service_class_ids_(
std::move(allowed_bluetooth_service_class_ids)),
callback_(std::move(callback)),
serial_delegate_(serial_delegate),
render_frame_host_id_(render_frame_host->GetGlobalId()) {
@@ -139,11 +93,7 @@ api::Session* SerialChooserController::GetSession() {
void SerialChooserController::OnPortAdded(
const device::mojom::SerialPortInfo& port) {
if (!DisplayDevice(port))
return;
ports_.push_back(port.Clone());
api::Session* session = GetSession();
if (session) {
session->Emit("serial-port-added", port.Clone(), web_contents());
@@ -152,8 +102,9 @@ void SerialChooserController::OnPortAdded(
void SerialChooserController::OnPortRemoved(
const device::mojom::SerialPortInfo& port) {
const auto it = base::ranges::find(ports_, port.token,
&device::mojom::SerialPortInfo::token);
const auto it = std::find_if(
ports_.begin(), ports_.end(),
[&port](const auto& ptr) { return ptr->token == port.token; });
if (it != ports_.end()) {
api::Session* session = GetSession();
if (session) {
@@ -198,7 +149,7 @@ void SerialChooserController::OnGetDevices(
});
for (auto& port : ports) {
if (DisplayDevice(*port))
if (FilterMatchesAny(*port))
ports_.push_back(std::move(port));
}
@@ -215,17 +166,21 @@ void SerialChooserController::OnGetDevices(
}
}
bool SerialChooserController::DisplayDevice(
bool SerialChooserController::FilterMatchesAny(
const device::mojom::SerialPortInfo& port) const {
if (filters_.empty()) {
return BluetoothPortIsAllowed(allowed_bluetooth_service_class_ids_, port);
}
if (filters_.empty())
return true;
for (const auto& filter : filters_) {
if (FilterMatchesPort(*filter, port) &&
BluetoothPortIsAllowed(allowed_bluetooth_service_class_ids_, port)) {
return true;
if (filter->has_vendor_id &&
(!port.has_vendor_id || filter->vendor_id != port.vendor_id)) {
continue;
}
if (filter->has_product_id &&
(!port.has_product_id || filter->product_id != port.product_id)) {
continue;
}
return true;
}
return false;

View File

@@ -34,7 +34,6 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
SerialChooserController(
content::RenderFrameHost* render_frame_host,
std::vector<blink::mojom::SerialPortFilterPtr> filters,
std::vector<::device::BluetoothUUID> allowed_bluetooth_service_class_ids,
content::SerialChooser::Callback callback,
content::WebContents* web_contents,
base::WeakPtr<ElectronSerialDelegate> serial_delegate);
@@ -56,12 +55,11 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
private:
api::Session* GetSession();
void OnGetDevices(std::vector<device::mojom::SerialPortInfoPtr> ports);
bool DisplayDevice(const device::mojom::SerialPortInfo& port) const;
bool FilterMatchesAny(const device::mojom::SerialPortInfo& port) const;
void RunCallback(device::mojom::SerialPortInfoPtr port);
void OnDeviceChosen(const std::string& port_id);
std::vector<blink::mojom::SerialPortFilterPtr> filters_;
std::vector<::device::BluetoothUUID> allowed_bluetooth_service_class_ids_;
content::SerialChooser::Callback callback_;
url::Origin origin_;

View File

@@ -0,0 +1,34 @@
// Copyright (c) 2018 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_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_
#define ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_
#include "ui/views/controls/native/native_view_host.h"
namespace electron {
// Automatically attach the native view after the NativeViewHost is attached to
// a widget. (Attaching it directly would cause crash.)
class DelayedNativeViewHost : public views::NativeViewHost {
public:
explicit DelayedNativeViewHost(gfx::NativeView native_view);
~DelayedNativeViewHost() override;
// disable copy
DelayedNativeViewHost(const DelayedNativeViewHost&) = delete;
DelayedNativeViewHost& operator=(const DelayedNativeViewHost&) = delete;
// views::View:
void ViewHierarchyChanged(
const views::ViewHierarchyChangedDetails& details) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
private:
gfx::NativeView native_view_;
};
} // namespace electron
#endif // ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/ui/cocoa/delayed_native_view_host.h"
#include "base/apple/owned_objc.h"
#include "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h"
namespace electron {
DelayedNativeViewHost::DelayedNativeViewHost(gfx::NativeView native_view)
: native_view_(native_view) {}
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_);
}
}
bool DelayedNativeViewHost::OnMousePressed(const ui::MouseEvent& ui_event) {
// NativeViewHost::OnMousePressed normally isn't called, but
// NativeWidgetMacNSWindow specifically carves out an event here for
// right-mouse-button clicks. We want to forward them to the web content, so
// handle them here.
// See:
// https://source.chromium.org/chromium/chromium/src/+/main:components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm;l=415-421;drc=a5af91924bafb85426e091c6035801990a6dc697
ElectronInspectableWebContentsView* inspectable_web_contents_view =
(ElectronInspectableWebContentsView*)native_view_.GetNativeNSView();
[inspectable_web_contents_view
redispatchContextMenuEvent:base::apple::OwnedNSEvent(
ui_event.native_event())];
return true;
}
} // namespace electron

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#ifndef ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#define ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_
#import <AppKit/AppKit.h>
#include "base/apple/owned_objc.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h"
#include "ui/base/cocoa/base_view.h"
namespace electron {
class InspectableWebContentsViewMac;
}
using electron::InspectableWebContentsViewMac;
@interface NSView (WebContentsView)
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
@end
@interface ElectronInspectableWebContentsView : BaseView <NSWindowDelegate> {
@private
raw_ptr<electron::InspectableWebContentsViewMac> inspectableWebContentsView_;
NSView* __strong fake_view_;
NSWindow* __strong devtools_window_;
BOOL devtools_visible_;
BOOL devtools_docked_;
BOOL devtools_is_first_responder_;
BOOL attached_to_window_;
DevToolsContentsResizingStrategy strategy_;
}
- (instancetype)initWithInspectableWebContentsViewMac:
(InspectableWebContentsViewMac*)view;
- (void)notifyDevToolsFocused;
- (void)setDevToolsVisible:(BOOL)visible activate:(BOOL)activate;
- (BOOL)isDevToolsVisible;
- (BOOL)isDevToolsFocused;
- (void)setIsDocked:(BOOL)docked activate:(BOOL)activate;
- (void)setContentsResizingStrategy:
(const DevToolsContentsResizingStrategy&)strategy;
- (void)setTitle:(NSString*)title;
- (NSString*)getTitle;
- (void)redispatchContextMenuEvent:(base::apple::OwnedNSEvent)theEvent;
@end
#endif // ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_

Some files were not shown because too many files have changed in this diff Show More