mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
106 Commits
feat/frame
...
v35.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a0abfd667 | ||
|
|
255e4e22e4 | ||
|
|
c32fcdfede | ||
|
|
a9c535d900 | ||
|
|
aa584714cd | ||
|
|
24bc99cc2f | ||
|
|
248104ece6 | ||
|
|
0a543f389d | ||
|
|
768daef27b | ||
|
|
8e32d80512 | ||
|
|
4c81971213 | ||
|
|
2da02ec9bc | ||
|
|
05b57a2f07 | ||
|
|
4cb9c44d97 | ||
|
|
51babe4592 | ||
|
|
4015b8c48e | ||
|
|
671178cfdb | ||
|
|
3a65cfe339 | ||
|
|
8934eb1af5 | ||
|
|
02b85f1e6d | ||
|
|
5a641e02ee | ||
|
|
d291fa6ced | ||
|
|
f29559e46c | ||
|
|
3ad2989862 | ||
|
|
8ea1f5b604 | ||
|
|
b63be7b5c7 | ||
|
|
11d1f063bd | ||
|
|
eb456ec5cd | ||
|
|
c92a02ea17 | ||
|
|
74c71dbb2d | ||
|
|
497849bf66 | ||
|
|
277a80da98 | ||
|
|
fc6a602929 | ||
|
|
bdab736f08 | ||
|
|
3c6e75e22d | ||
|
|
9a7f27d845 | ||
|
|
b2b59a6c0b | ||
|
|
b6884b5c50 | ||
|
|
fa0da6f19f | ||
|
|
cf85d2d7c1 | ||
|
|
bc163a5ea8 | ||
|
|
b52917c380 | ||
|
|
cd1186a116 | ||
|
|
f1176be749 | ||
|
|
aacbdaf4ec | ||
|
|
5b90ce2290 | ||
|
|
8fb9fd97df | ||
|
|
107c0c6c6e | ||
|
|
bca80f19e0 | ||
|
|
66eb15d093 | ||
|
|
a1b846c9e5 | ||
|
|
71d3a86d32 | ||
|
|
452d891be5 | ||
|
|
fc697735c4 | ||
|
|
acfe4766d2 | ||
|
|
763d978765 | ||
|
|
2bce515091 | ||
|
|
e15ba780c4 | ||
|
|
713d32fccc | ||
|
|
3b421ef77f | ||
|
|
9d9d1afb2e | ||
|
|
984b8f9b1b | ||
|
|
cb7eb6fe3d | ||
|
|
f1d8e03ef8 | ||
|
|
637313c2f3 | ||
|
|
20941efeb5 | ||
|
|
7373bde546 | ||
|
|
acfc32f534 | ||
|
|
eaa28375d9 | ||
|
|
f40fc49461 | ||
|
|
a07de0099c | ||
|
|
46c9ed61da | ||
|
|
51170c3652 | ||
|
|
5be655585d | ||
|
|
04e37266c4 | ||
|
|
b0b7c8f540 | ||
|
|
49078100f4 | ||
|
|
599030ea08 | ||
|
|
07bdef0370 | ||
|
|
cc6164fe27 | ||
|
|
59e4794ff5 | ||
|
|
fa03b92f7e | ||
|
|
9d696ceffe | ||
|
|
e9b3e4cc91 | ||
|
|
895bc51272 | ||
|
|
ef1ad85082 | ||
|
|
e99328a45e | ||
|
|
04f5fe6a1c | ||
|
|
08b6bb1712 | ||
|
|
813efbcdf7 | ||
|
|
d34fa2e301 | ||
|
|
724744af16 | ||
|
|
91bb748eaa | ||
|
|
d77c2d75ed | ||
|
|
f4c3eb4391 | ||
|
|
9aca9e9fb6 | ||
|
|
e0fa647601 | ||
|
|
6b0fd02c0a | ||
|
|
1017ac821f | ||
|
|
91b53b633a | ||
|
|
8da9572592 | ||
|
|
291bbff5d8 | ||
|
|
d704a3fc5b | ||
|
|
fb70b81ee6 | ||
|
|
97fa059e1f | ||
|
|
8a64cdc0b1 |
23
.github/actions/build-electron/action.yml
vendored
23
.github/actions/build-electron/action.yml
vendored
@@ -108,7 +108,9 @@ runs:
|
||||
if [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
cd out/Default
|
||||
powershell Compress-Archive -update mksnapshot_args mksnapshot.zip
|
||||
powershell Compress-Archive -update gen/v8/embedded.S mksnapshot.zip
|
||||
powershell mkdir mktmp\\gen\\v8
|
||||
powershell Copy-Item gen\\v8\\embedded.S mktmp\\gen\\v8
|
||||
powershell Compress-Archive -update -Path mktmp\\gen mksnapshot.zip
|
||||
else
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
|
||||
fi
|
||||
@@ -143,6 +145,25 @@ runs:
|
||||
run: |
|
||||
cd src
|
||||
e build --target electron:node_headers
|
||||
- name: Create installed_software.json ${{ inputs.step-suffix }}
|
||||
shell: powershell
|
||||
if: ${{ inputs.is-release == 'true' && inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
cd src
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- name: Profile Windows Toolchain ${{ inputs.step-suffix }}
|
||||
shell: bash
|
||||
if: ${{ inputs.is-release == 'true' && inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
cd src
|
||||
python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- name: Add msdia140.dll to Path ${{ inputs.step-suffix }}
|
||||
shell: bash
|
||||
if: ${{ inputs.is-release == 'true' && inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
cd src
|
||||
export PATH="$PATH:$(pwd)/third_party/llvm-build/Release+Asserts/bin"
|
||||
- name: Generate & Zip Symbols ${{ inputs.step-suffix }}
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
6
.github/actions/checkout/action.yml
vendored
6
.github/actions/checkout/action.yml
vendored
@@ -20,6 +20,8 @@ runs:
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Install Build Tools
|
||||
uses: ./src/electron/.github/actions/install-build-tools
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Get Depot Tools
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -73,10 +75,10 @@ runs:
|
||||
if: steps.check-cache.outputs.cache_exists == 'false' && inputs.use-cache == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
# if there is less than 20 GB free space then creating the cache might fail so exit early
|
||||
# if there is less than 35 GB free space then creating the cache might fail so exit early
|
||||
freespace=`df -m /mnt/cross-instance-cache | grep -w /mnt/cross-instance-cache | awk '{print $4}'`
|
||||
freespace_human=`df -h /mnt/cross-instance-cache | grep -w /mnt/cross-instance-cache | awk '{print $4}'`
|
||||
if [ $freespace -le 20000 ]; then
|
||||
if [ $freespace -le 35000 ]; then
|
||||
echo "The cross mount cache has $freespace_human free space which is not enough - exiting"
|
||||
exit 1
|
||||
else
|
||||
|
||||
@@ -16,5 +16,5 @@ runs:
|
||||
e auto-update disable
|
||||
if [ "$(expr substr $(uname -s) 1 10)" == "MSYS_NT-10" ]; then
|
||||
e d cipd.bat --version
|
||||
cp "C:\Python37\python.exe" "C:\Python37\python3.exe"
|
||||
cp "C:\Python311\python.exe" "C:\Python311\python3.exe"
|
||||
fi
|
||||
|
||||
26
.github/actions/set-chromium-cookie/action.yml
vendored
Normal file
26
.github/actions/set-chromium-cookie/action.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: 'Set Chromium Git Cookie'
|
||||
description: 'Sets an authenticated cookie from Chromium to allow for a higher request limit'
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set the git cookie from chromium.googlesource.com (Unix)
|
||||
if: ${{ runner.os != 'Windows' && env.CHROMIUM_GIT_COOKIE }}
|
||||
shell: bash
|
||||
run: |
|
||||
eval 'set +o history' 2>/dev/null || setopt HIST_IGNORE_SPACE 2>/dev/null
|
||||
touch ~/.gitcookies
|
||||
chmod 0600 ~/.gitcookies
|
||||
|
||||
git config --global http.cookiefile ~/.gitcookies
|
||||
|
||||
tr , \\t <<\__END__ >>~/.gitcookies
|
||||
${{ env.CHROMIUM_GIT_COOKIE }}
|
||||
__END__
|
||||
eval 'set -o history' 2>/dev/null || unsetopt HIST_IGNORE_SPACE 2>/dev/null
|
||||
- name: Set the git cookie from chromium.googlesource.com (Windows)
|
||||
if: ${{ runner.os == 'Windows' && env.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
|
||||
shell: cmd
|
||||
run: |
|
||||
git config --global http.cookiefile "%USERPROFILE%\.gitcookies"
|
||||
powershell -noprofile -nologo -command Write-Output "${{ env.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}" >>"%USERPROFILE%\.gitcookies"
|
||||
|
||||
6
.github/workflows/branch-created.yml
vendored
6
.github/workflows/branch-created.yml
vendored
@@ -94,7 +94,7 @@ jobs:
|
||||
}))
|
||||
- name: Create Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/copy-project@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/copy-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
id: create-release-board
|
||||
with:
|
||||
drafts: true
|
||||
@@ -114,14 +114,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Find Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/find-project@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/find-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
id: find-prev-release-board
|
||||
with:
|
||||
title: ${{ steps.generate-project-metadata.outputs.prev-prev-major }}-x-y
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Close Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/close-project@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/close-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
project-number: ${{ steps.find-prev-release-board.outputs.number }}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -100,6 +100,7 @@ jobs:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
- /var/run/sas:/var/run/sas
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
|
||||
outputs:
|
||||
build-image-sha: ${{ needs.setup.outputs.build-image-sha }}
|
||||
@@ -126,6 +127,7 @@ jobs:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
- /var/run/sas:/var/run/sas
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
PATCH_UP_APP_CREDS: ${{ secrets.PATCH_UP_APP_CREDS }}
|
||||
outputs:
|
||||
@@ -150,6 +152,8 @@ jobs:
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_win=True'
|
||||
TARGET_OS: 'win'
|
||||
ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN: '1'
|
||||
|
||||
8
.github/workflows/clean-src-cache.yml
vendored
8
.github/workflows/clean-src-cache.yml
vendored
@@ -1,8 +1,12 @@
|
||||
name: Clean Source Cache
|
||||
|
||||
description: |
|
||||
This workflow cleans up the source cache on the cross-instance cache volume
|
||||
to free up space. It runs daily at midnight and clears files older than 15 days.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * SUN" # Run at midnight every Sunday
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
clean-src-cache:
|
||||
@@ -17,5 +21,5 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
df -h /mnt/cross-instance-cache
|
||||
find /mnt/cross-instance-cache -type f -mtime +30 -delete
|
||||
find /mnt/cross-instance-cache -type f -mtime +15 -delete
|
||||
df -h /mnt/cross-instance-cache
|
||||
|
||||
6
.github/workflows/issue-labeled.yml
vendored
6
.github/workflows/issue-labeled.yml
vendored
@@ -20,13 +20,12 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: ✅ Triaged
|
||||
fail-if-item-not-found: false
|
||||
issue-labeled-blocked:
|
||||
name: blocked/* label added
|
||||
if: startsWith(github.event.label.name, 'blocked/')
|
||||
@@ -39,13 +38,12 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: 🛑 Blocked
|
||||
fail-if-item-not-found: false
|
||||
issue-labeled-blocked-need-repro:
|
||||
name: blocked/need-repro label added
|
||||
if: github.event.label.name == 'blocked/need-repro'
|
||||
|
||||
2
.github/workflows/issue-opened.yml
vendored
2
.github/workflows/issue-opened.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Add to Issue Triage
|
||||
uses: dsanders11/project-actions/add-item@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/add-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
field: Reporter
|
||||
field-value: ${{ github.event.issue.user.login }}
|
||||
|
||||
3
.github/workflows/issue-transferred.yml
vendored
3
.github/workflows/issue-transferred.yml
vendored
@@ -18,8 +18,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Remove from issue triage
|
||||
uses: dsanders11/project-actions/delete-item@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/delete-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
fail-if-item-not-found: false
|
||||
|
||||
3
.github/workflows/issue-unlabeled.yml
vendored
3
.github/workflows/issue-unlabeled.yml
vendored
@@ -30,10 +30,9 @@ jobs:
|
||||
org: electron
|
||||
- name: Set status
|
||||
if: ${{ steps.check-for-blocked-labels.outputs.NOT_BLOCKED }}
|
||||
uses: dsanders11/project-actions/edit-item@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: 📥 Was Blocked
|
||||
fail-if-item-not-found: false
|
||||
|
||||
@@ -56,8 +56,8 @@ on:
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: electron-build-and-test-and-nan-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-build-and-test-and-nan-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -56,8 +56,8 @@ on:
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: electron-build-and-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-build-and-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
9
.github/workflows/pipeline-electron-lint.yml
vendored
9
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -9,8 +9,11 @@ on:
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: electron-lint-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-lint-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
@@ -27,6 +30,8 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Setup third_party Depot Tools
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -13,7 +13,7 @@ on:
|
||||
required: true
|
||||
target-arch:
|
||||
type: string
|
||||
description: 'Arch to build for, can be x64, arm64 or arm'
|
||||
description: 'Arch to build for, can be x64, arm64, ia32 or arm'
|
||||
required: true
|
||||
target-variant:
|
||||
type: string
|
||||
@@ -61,10 +61,12 @@ on:
|
||||
|
||||
|
||||
concurrency:
|
||||
group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.target-variant }}-${{ inputs.is-asan }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.target-variant }}-${{ inputs.is-asan }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
|
||||
ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }}
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
SUDOWOODO_EXCHANGE_URL: ${{ secrets.SUDOWOODO_EXCHANGE_URL }}
|
||||
@@ -125,6 +127,8 @@ jobs:
|
||||
GN_EXTRA_ARGS='is_asan=true'
|
||||
fi
|
||||
echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Get Depot Tools
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
|
||||
@@ -27,8 +27,8 @@ on:
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -36,6 +36,8 @@ permissions:
|
||||
pull-requests: read
|
||||
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
|
||||
@@ -74,6 +76,7 @@ jobs:
|
||||
echo "C:\Program Files\Git\cmd" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
echo "C:\Program Files\Git\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
echo "C:\Python311" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
cp "C:\Python311\python.exe" "C:\Python311\python3.exe"
|
||||
- name: Setup Node.js/npm
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
|
||||
@@ -112,6 +115,9 @@ jobs:
|
||||
configure_sys_tccdb "$values"
|
||||
fi
|
||||
done
|
||||
- name: Turn off the unexpectedly quit dialog on macOS
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: defaults write com.apple.CrashReporter DialogType server
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
@@ -120,6 +126,8 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Get Depot Tools
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
|
||||
@@ -27,10 +27,11 @@ on:
|
||||
default: testing
|
||||
|
||||
concurrency:
|
||||
group: electron-node-nan-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-node-nan-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
|
||||
@@ -38,7 +39,7 @@ jobs:
|
||||
node-tests:
|
||||
name: Run Node.js Tests
|
||||
runs-on: electron-arc-linux-amd64-8core
|
||||
timeout-minutes: 20
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
BUILD_TYPE: linux
|
||||
@@ -57,6 +58,8 @@ jobs:
|
||||
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu ${{ inputs.target-arch }}
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Get Depot Tools
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
@@ -99,7 +102,7 @@ jobs:
|
||||
nan-tests:
|
||||
name: Run Nan Tests
|
||||
runs-on: electron-arc-linux-amd64-4core
|
||||
timeout-minutes: 20
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
BUILD_TYPE: linux
|
||||
@@ -118,6 +121,8 @@ jobs:
|
||||
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }}
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Get Depot Tools
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
|
||||
6
.github/workflows/pull-request-labeled.yml
vendored
6
.github/workflows/pull-request-labeled.yml
vendored
@@ -15,12 +15,12 @@ jobs:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@485a9d42d3a73031f12ec201c457e2162c45d02d # v2.0.0
|
||||
with:
|
||||
webhook: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
|
||||
webhook-type: webhook-trigger
|
||||
payload: |
|
||||
{
|
||||
"url": "${{ github.event.pull_request.html_url }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
|
||||
pull-request-labeled-deprecation-review-complete:
|
||||
name: deprecation-review/complete label added
|
||||
if: github.event.label.name == 'deprecation-review/complete ✅'
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
creds: ${{ secrets.RELEASE_BOARD_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 94
|
||||
|
||||
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@@ -50,6 +50,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
|
||||
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
2
.github/workflows/stable-prep-items.yml
vendored
2
.github/workflows/stable-prep-items.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
PROJECT_NUMBER=$(gh project list --owner electron --format json | jq -r '.projects | map(select(.title | test("^[0-9]+-x-y$"))) | max_by(.number) | .number')
|
||||
echo "PROJECT_NUMBER=$PROJECT_NUMBER" >> "$GITHUB_OUTPUT"
|
||||
- name: Update Completed Stable Prep Items
|
||||
uses: dsanders11/project-actions/completed-by@8bc0bd421be3a2f9e96e160c4cb703f97cd3be55 # v1.5.0
|
||||
uses: dsanders11/project-actions/completed-by@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
field: Prep Status
|
||||
field-value: ✅ Complete
|
||||
|
||||
78
.github/workflows/update_appveyor_image.yml
vendored
78
.github/workflows/update_appveyor_image.yml
vendored
@@ -1,78 +0,0 @@
|
||||
name: Update AppVeyor Image
|
||||
|
||||
# Run chron daily Mon-Fri
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 8 * * 1-5' # runs 8:00 every business day (see https://crontab.guru)
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
bake-appveyor-image:
|
||||
name: Bake AppVeyor Image
|
||||
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: 20.11.x
|
||||
- name: Yarn install
|
||||
run: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
- name: Set Repo for Commit
|
||||
run: git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||
- name: Check AppVeyor Image
|
||||
env:
|
||||
APPVEYOR_TOKEN: ${{ secrets.APPVEYOR_TOKEN }}
|
||||
run: |
|
||||
node ./script/prepare-appveyor
|
||||
if [ -f ./image_version.txt ]; then
|
||||
echo "APPVEYOR_IMAGE_VERSION="$(cat image_version.txt)"" >> $GITHUB_ENV
|
||||
rm image_version.txt
|
||||
fi
|
||||
- name: (Optionally) Update Appveyor Image
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
uses: mikefarah/yq@8bf425b4d1344db7cd469a8d10a390876e0c77fd # v4.45.1
|
||||
with:
|
||||
cmd: |
|
||||
yq '.image = "${{ env.APPVEYOR_IMAGE_VERSION }}"' "appveyor.yml" > "appveyor2.yml"
|
||||
yq '.image = "${{ env.APPVEYOR_IMAGE_VERSION }}"' "appveyor-woa.yml" > "appveyor-woa2.yml"
|
||||
- name: (Optionally) Generate Commit Diff
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
run: |
|
||||
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
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
uses: dsanders11/github-app-commit-action@43de6da2f4d927e997c0784c7a0b61bd19ad6aac # v1.5.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 }}
|
||||
84
.github/workflows/windows-publish.yml
vendored
Normal file
84
.github/workflows/windows-publish.yml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
name: Publish Windows
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: 'bc2f48b2415a670de18d13605b1cf0eb5fdbaae1'
|
||||
required: true
|
||||
upload-to-storage:
|
||||
description: 'Uploads to Azure storage'
|
||||
required: false
|
||||
default: '1'
|
||||
type: string
|
||||
run-windows-publish:
|
||||
description: 'Run the publish jobs vs just the build jobs'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
checkout-windows:
|
||||
runs-on: electron-arc-linux-amd64-32core
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ inputs.build-image-sha }}
|
||||
options: --user root --device /dev/fuse --cap-add SYS_ADMIN
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
env:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_win=True'
|
||||
TARGET_OS: 'win'
|
||||
ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN: '1'
|
||||
outputs:
|
||||
build-image-sha: ${{ inputs.build-image-sha }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
- name: Checkout & Sync & Save
|
||||
uses: ./src/electron/.github/actions/checkout
|
||||
|
||||
publish-x64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
build-runs-on: electron-arc-windows-amd64-16core
|
||||
target-platform: win
|
||||
target-arch: x64
|
||||
is-release: true
|
||||
gn-build-type: release
|
||||
generate-symbols: true
|
||||
upload-to-storage: ${{ inputs.upload-to-storage }}
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
build-runs-on: electron-arc-windows-amd64-16core
|
||||
target-platform: win
|
||||
target-arch: arm64
|
||||
is-release: true
|
||||
gn-build-type: release
|
||||
generate-symbols: true
|
||||
upload-to-storage: ${{ inputs.upload-to-storage }}
|
||||
secrets: inherit
|
||||
|
||||
publish-x86-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
build-runs-on: electron-arc-windows-amd64-16core
|
||||
target-platform: win
|
||||
target-arch: x86
|
||||
is-release: true
|
||||
gn-build-type: release
|
||||
generate-symbols: true
|
||||
upload-to-storage: ${{ inputs.upload-to-storage }}
|
||||
secrets: inherit
|
||||
12
BUILD.gn
12
BUILD.gn
@@ -224,11 +224,21 @@ webpack_build("electron_utility_bundle") {
|
||||
out_file = "$target_gen_dir/js2c/utility_init.js"
|
||||
}
|
||||
|
||||
webpack_build("electron_preload_realm_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
inputs = auto_filenames.preload_realm_bundle_deps
|
||||
|
||||
config_file = "//electron/build/webpack/webpack.config.preload_realm.js"
|
||||
out_file = "$target_gen_dir/js2c/preload_realm_bundle.js"
|
||||
}
|
||||
|
||||
action("electron_js2c") {
|
||||
deps = [
|
||||
":electron_browser_bundle",
|
||||
":electron_isolated_renderer_bundle",
|
||||
":electron_node_bundle",
|
||||
":electron_preload_realm_bundle",
|
||||
":electron_renderer_bundle",
|
||||
":electron_sandboxed_renderer_bundle",
|
||||
":electron_utility_bundle",
|
||||
@@ -240,6 +250,7 @@ action("electron_js2c") {
|
||||
"$target_gen_dir/js2c/browser_init.js",
|
||||
"$target_gen_dir/js2c/isolated_bundle.js",
|
||||
"$target_gen_dir/js2c/node_init.js",
|
||||
"$target_gen_dir/js2c/preload_realm_bundle.js",
|
||||
"$target_gen_dir/js2c/renderer_init.js",
|
||||
"$target_gen_dir/js2c/sandbox_bundle.js",
|
||||
"$target_gen_dir/js2c/utility_init.js",
|
||||
@@ -430,6 +441,7 @@ source_set("electron_lib") {
|
||||
"chromium_src:chrome_spellchecker",
|
||||
"shell/common:mojo",
|
||||
"shell/common:plugin",
|
||||
"shell/common:web_contents_utility",
|
||||
"shell/services/node/public/mojom",
|
||||
"//base:base_static",
|
||||
"//base/allocator:buildflags",
|
||||
|
||||
4
DEPS
4
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'133.0.6920.0',
|
||||
'134.0.6998.23',
|
||||
'node_version':
|
||||
'v22.9.0',
|
||||
'v22.14.0',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
# The config is used to bake appveyor images, not for running CI jobs.
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "APPVEYOR_BAKE_IMAGE" e.g. 'electron-99.0.4767.0'. Name of the image to be baked.
|
||||
# Typically named after the Chromium version on which the image is built.
|
||||
# This can be set dynamically in the prepare-appveyor script.
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: base-bake-image
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# init:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# - appveyor version
|
||||
# - ps: $ErrorActionPreference = 'Stop'
|
||||
# - ps: 'Write-Host "OS Build: $((Get-CimInstance Win32_OperatingSystem).BuildNumber)"'
|
||||
|
||||
# clone_folder: '%USERPROFILE%\image-bake-scripts'
|
||||
|
||||
# clone_script:
|
||||
# - ps: Invoke-WebRequest "https://github.com/appveyor/build-images/archive/1f90d94e74c8243c909a09b994e527584dfcb838.zip" -OutFile "$env:temp\scripts.zip"
|
||||
# - ps: Expand-Archive -Path "$env:temp\scripts.zip" -DestinationPath "$env:temp\scripts" -Force
|
||||
# - ps: Copy-Item -Path "$env:temp\scripts\build-images-1f90d94e74c8243c909a09b994e527584dfcb838\scripts\Windows\*" -Destination $env:APPVEYOR_BUILD_FOLDER -Recurse
|
||||
|
||||
build_script:
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# - ps: .\init_server.ps1
|
||||
# - ps: .\extend_system_volume.ps1
|
||||
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
|
||||
# - appveyor version
|
||||
# - ps: .\install_path_utils.ps1
|
||||
# - ps: .\install_powershell_core.ps1
|
||||
# - ps: .\install_powershell_get.ps1
|
||||
# - ps: .\install_7zip.ps1
|
||||
# - ps: .\install_chocolatey.ps1
|
||||
# - ps: .\install_webpi.ps1
|
||||
# - ps: .\install_nuget.ps1
|
||||
# - ps: .\install_pstools.ps1
|
||||
|
||||
# - ps: .\install_git.ps1
|
||||
# - ps: .\install_git_lfs.ps1
|
||||
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
# END LINES FOR COMPLETELY NEW IMAGE
|
||||
|
||||
- git config --global core.longpaths true
|
||||
- ps: >-
|
||||
if (-not (Test-Path -Path C:\projects\src)) {
|
||||
New-Item -Path C:\projects\src -ItemType Directory
|
||||
}
|
||||
- cd C:\projects\
|
||||
- git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/electron/electron.git C:\projects\src\electron
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- update_depot_tools.bat
|
||||
# Uncomment the following line if windows deps change
|
||||
- src\electron\script\setup-win-for-dev.bat
|
||||
- >-
|
||||
gclient config
|
||||
--name "src\electron"
|
||||
--unmanaged
|
||||
%GCLIENT_EXTRA_ARGS%
|
||||
"https://github.com/electron/electron"
|
||||
- ps: cd src\electron
|
||||
- ps: node script\generate-deps-hash.js
|
||||
- ps: $depshash = Get-Content .\.depshash -Raw
|
||||
- ps: Copy-Item -path .\.depshash -destination ..\.depshash
|
||||
- ps: cd ..\..
|
||||
- gclient sync --with_branch_heads --with_tags --nohooks
|
||||
- ps: regsvr32 /s "C:\Program Files\Microsoft Visual Studio\2022\Community\DIA SDK\bin\amd64\msdia140.dll"
|
||||
- ps: set vs2022_install="C:\Program Files\Microsoft Visual Studio\2022\Community"
|
||||
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
|
||||
# - cd %USERPROFILE%\image-bake-scripts
|
||||
# - appveyor version
|
||||
# - ps: .\optimize_dotnet_runtime.ps1
|
||||
# - ps: .\disable_windows_background_services.ps1
|
||||
# - ps: .\enforce_windows_firewall.ps1
|
||||
# - ps: .\cleanup_windows.ps1
|
||||
# END LINES FOR COMPLETELY NEW IMAGE
|
||||
on_image_bake:
|
||||
- ps: >-
|
||||
echo "Baking image: $env:APPVEYOR_BAKE_IMAGE at dir $PWD"
|
||||
- ps: Remove-Item -Recurse -Force C:\projects\depot_tools
|
||||
- ps: Remove-Item -Recurse -Force C:\projects\src\electron
|
||||
# Uncomment these lines and set APPVEYOR_RDP_PASSWORD in project settings to enable RDP after bake is done
|
||||
# # on_finish:
|
||||
# - ps: >-
|
||||
# $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
352
appveyor-woa.yml
352
appveyor-woa.yml
@@ -1,352 +0,0 @@
|
||||
# NOTE IF CHANGING THIS FILE, ALSO APPLY THE CHANGE TO appveyor.yml
|
||||
# IF APPLICABLE!!!!
|
||||
#
|
||||
#
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/main/docs/reference.md#var_target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
|
||||
# Otherwise the release will be uploaded to the GitHub Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# AppVeyor docs on variables:
|
||||
# https://www.appveyor.com/docs/environment-variables/
|
||||
# https://www.appveyor.com/docs/build-configuration/#secure-variables
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-133.0.6878.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, mocha-junit-reporter, tap"
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_7393122652: 3ba76c5c20
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
matrix:
|
||||
|
||||
- job_name: Build Arm on X64 Windows
|
||||
- job_name: Test On Windows On Arm Hardware 1
|
||||
job_depends_on: Build Arm on X64 Windows
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: base-woa
|
||||
APPVEYOR_BUILD_WORKER_CLOUD: electronhq-woa
|
||||
shard: 1
|
||||
- job_name: Test On Windows On Arm Hardware 2
|
||||
job_depends_on: Build Arm on X64 Windows
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: base-woa
|
||||
APPVEYOR_BUILD_WORKER_CLOUD: electronhq-woa
|
||||
shard: 2
|
||||
|
||||
clone_script:
|
||||
- ps: git clone -q $("--branch=" + $Env:APPVEYOR_REPO_BRANCH) $("https://github.com/" + $Env:APPVEYOR_REPO_NAME + ".git") $Env:APPVEYOR_BUILD_FOLDER
|
||||
- ps: if (!$Env:APPVEYOR_PULL_REQUEST_NUMBER) {$("git checkout -qf " + $Env:APPVEYOR_REPO_COMMIT)}
|
||||
- ps: if ($Env:APPVEYOR_PULL_REQUEST_NUMBER) {git fetch -q origin +refs/pull/$($Env:APPVEYOR_PULL_REQUEST_NUMBER)/head; git checkout -qf FETCH_HEAD}
|
||||
|
||||
clone_folder: C:\projects\src\electron
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
# the first failed job cancels other jobs and fails entire build
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
for:
|
||||
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Build Arm on X64 Windows
|
||||
|
||||
build_script:
|
||||
# TODO: Remove --ignore-engines once WOA image is up to node 20
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile --ignore-engines
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
|
||||
$env:SHOULD_SKIP_ARTIFACT_VALIDATION = "false"
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc-only change"
|
||||
$env:SHOULD_SKIP_ARTIFACT_VALIDATION = "true"
|
||||
Exit-AppveyorBuild
|
||||
} else {
|
||||
$global:LASTEXITCODE = 0
|
||||
}
|
||||
- cd ..
|
||||
- ps: Write-Host "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\depot_tools") {
|
||||
Remove-Item -Recurse -Force $pwd\depot_tools
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: |
|
||||
Set-Content -Path $pwd\depot_tools\build_telemetry.cfg -Value '{"user": "info@electronjs.org", "status": "opt-out", "countdown": 10, "version": 1}'
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npx yarn --ignore-engines
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
- ps: $env:RECLIENT_HELPER = node -p "require('./src/utils/reclient.js').helperPath({})"
|
||||
- ps: >-
|
||||
& $env:RECLIENT_HELPER login
|
||||
- ps: >-
|
||||
$env:RBE_service = node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"
|
||||
- ps: >-
|
||||
$env:RBE_credentials_helper = $env:RECLIENT_HELPER
|
||||
- ps: >-
|
||||
$env:RBE_credentials_helper_args = "print"
|
||||
- ps: >-
|
||||
if ($env:ELECTRON_RBE_JWT -eq '') {
|
||||
$env:RBE_fail_early_min_action_count = "0"
|
||||
$env:RBE_fail_early_min_fallback_ratio = "0"
|
||||
}
|
||||
- cd ..\..
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- gclient config --name "src\electron" --unmanaged %GCLIENT_EXTRA_ARGS% "https://github.com/electron/electron"
|
||||
# Patches are applied in the image bake. Check depshash to see if patches have changed.
|
||||
- ps: $env:RUN_GCLIENT_SYNC="false"
|
||||
- ps: $depshash_baked = Get-Content .\src\.depshash -Raw
|
||||
- ps: cd src\electron
|
||||
- ps: node script\generate-deps-hash.js
|
||||
- ps: $depshash = Get-Content .\.depshash -Raw
|
||||
- ps: cd ..\..
|
||||
- ps: >-
|
||||
if ($depshash_baked -ne $depshash) {
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
}
|
||||
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync --with_branch_heads --with_tags ) else ( gclient runhooks )
|
||||
- cd src
|
||||
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") use_remoteexec=true %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common:mojo
|
||||
- gn check out/Default //electron/shell/common:plugin
|
||||
- autoninja -j 300 -C out/Default electron:electron_app
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true %GN_EXTRA_ARGS%"
|
||||
- autoninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- autoninja -C out/Default electron:electron_dist_zip
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') } | Set-Content out/Default/mksnapshot_args
|
||||
- autoninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- autoninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- autoninja -C out/Default electron:electron_chromedriver_zip
|
||||
- autoninja -C out/Default electron:node_headers
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- 7z a nan.zip third_party\nan
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
}
|
||||
- if "%GN_CONFIG%"=="release" ( autoninja -C out/Default electron:electron_symbols )
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python3 electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- ps: |
|
||||
$manifest_file = "electron/script/zip_manifests/dist_zip.win.$env:TARGET_ARCH.manifest"
|
||||
python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip $manifest_file
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Zip contains files not listed in the manifest $manifest_file"
|
||||
}
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only $env:APPVEYOR_PROJECT_NAME"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip','nan.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif (
|
||||
$artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} elseif (
|
||||
$artifact_name -eq 'nan.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (-not(Test-Path $artifact_file)) {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python3 script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
}
|
||||
on_finish:
|
||||
# Uncomment this lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist nan.zip (appveyor-retry appveyor PushArtifact nan.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Test On Windows On Arm Hardware 1
|
||||
- job_name: Test On Windows On Arm Hardware 2
|
||||
|
||||
environment:
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: C:\projects\src\electron\junit
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, mocha-junit-reporter, tap"
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
DD_ENV: ci
|
||||
DD_SERVICE: electron
|
||||
DD_CIVISIBILITY_LOGS_ENABLED: true
|
||||
DD_GIT_REPOSITORY_URL: "https://github.com/electron/electron.git"
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile --ignore-engines
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"
|
||||
Exit-AppveyorBuild
|
||||
} else {
|
||||
$global:LASTEXITCODE = 0
|
||||
}
|
||||
- ps: Invoke-WebRequest -Uri "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_win-x64" -OutFile "C:\projects\src\electron\datadog-ci.exe"
|
||||
- cd ..
|
||||
- mkdir out\Default
|
||||
- cd ..
|
||||
- ps: |
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','electron.lib', 'nan.zip')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build Arm on X64 Windows") {
|
||||
$jobId = $job.jobId
|
||||
foreach($artifact_name in $artifacts_to_download) {
|
||||
if ($artifact_name -eq 'electron.lib') {
|
||||
$outfile = "src\out\Default\$artifact_name"
|
||||
} else {
|
||||
$outfile = $artifact_name
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
# Uncomment the following lines to download the pdb.zip to show real stacktraces when crashes happen during testing
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/pdb.zip" -OutFile pdb.zip
|
||||
7z x -y -osrc pdb.zip
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
$out_default_zips = @('dist.zip')
|
||||
foreach($zip_name in $out_default_zips) {
|
||||
7z x -y -osrc\out\Default $zip_name
|
||||
}
|
||||
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
|
||||
- ps: 7z x -y -osrc node_headers.zip
|
||||
- ps: 7z x -y -osrc nan.zip
|
||||
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: |
|
||||
cd src
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
- set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
- set npm_config_arch=arm64
|
||||
- cd electron
|
||||
# Explicitly set npm_config_arch because the .env doesn't persist
|
||||
- ps: >-
|
||||
if ($env:TARGET_ARCH -eq 'ia32') {
|
||||
$env:npm_config_arch = "ia32"
|
||||
}
|
||||
- ps: $env:tests_files=node script\split-tests $env:shard 2
|
||||
- echo "Running shard %shard% specs %tests_files%"
|
||||
- echo Running main test suite & node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion --files %tests_files%
|
||||
- cd ..
|
||||
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
|
||||
on_finish:
|
||||
# Uncomment these lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- if exist electron\junit\test-results-main.xml ( appveyor-retry appveyor PushArtifact electron\junit\test-results-main.xml )
|
||||
- ps: |
|
||||
if ($env:DD_API_KEY) {
|
||||
$env:DD_GIT_COMMIT_SHA = $env:APPVEYOR_REPO_COMMIT
|
||||
$env:DD_GIT_BRANCH = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH
|
||||
$env:DD_TAGS = "os.architecture:$env:TARGET_ARCH,os.family:windows,os.platform:win32"
|
||||
if (Test-Path -Path "C:\projects\src\electron\junit\test-results-main.xml") {
|
||||
C:\projects\src\electron\datadog-ci.exe junit upload --verbose C:\projects\src\electron\junit\test-results-main.xml
|
||||
}
|
||||
}
|
||||
350
appveyor.yml
350
appveyor.yml
@@ -1,350 +0,0 @@
|
||||
# NOTE IF CHANGING THIS FILE, ALSO APPLY THE CHANGE TO appveyor-woa.yml
|
||||
# IF APPLICABLE!!!!
|
||||
#
|
||||
#
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/main/docs/reference.md#var_target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
|
||||
# Otherwise the release will be uploaded to the GitHub Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# AppVeyor docs on variables:
|
||||
# https://www.appveyor.com/docs/environment-variables/
|
||||
# https://www.appveyor.com/docs/build-configuration/#secure-variables
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-133.0.6878.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, mocha-junit-reporter, tap"
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_7393122652: 3ba76c5c20
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
matrix:
|
||||
|
||||
- job_name: Build
|
||||
- job_name: Test 1
|
||||
job_depends_on: Build
|
||||
shard: 1
|
||||
- job_name: Test 2
|
||||
job_depends_on: Build
|
||||
shard: 2
|
||||
|
||||
clone_script:
|
||||
- ps: git clone -q $("--branch=" + $Env:APPVEYOR_REPO_BRANCH) $("https://github.com/" + $Env:APPVEYOR_REPO_NAME + ".git") $Env:APPVEYOR_BUILD_FOLDER
|
||||
- ps: if (!$Env:APPVEYOR_PULL_REQUEST_NUMBER) {$("git checkout -qf " + $Env:APPVEYOR_REPO_COMMIT)}
|
||||
- ps: if ($Env:APPVEYOR_PULL_REQUEST_NUMBER) {git fetch -q origin +refs/pull/$($Env:APPVEYOR_PULL_REQUEST_NUMBER)/head; git checkout -qf FETCH_HEAD}
|
||||
|
||||
clone_folder: C:\projects\src\electron
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
# the first failed job cancels other jobs and fails entire build
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
for:
|
||||
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Build
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
|
||||
$env:SHOULD_SKIP_ARTIFACT_VALIDATION = "false"
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc-only change"
|
||||
$env:SHOULD_SKIP_ARTIFACT_VALIDATION = "true"
|
||||
Exit-AppveyorBuild
|
||||
} else {
|
||||
$global:LASTEXITCODE = 0
|
||||
}
|
||||
- cd ..
|
||||
- ps: Write-Host "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\depot_tools") {
|
||||
Remove-Item -Recurse -Force $pwd\depot_tools
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: |
|
||||
Set-Content -Path $pwd\depot_tools\build_telemetry.cfg -Value '{"user": "info@electronjs.org", "status": "opt-out", "countdown": 10, "version": 1}'
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npx yarn --ignore-engines
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
- ps: $env:RECLIENT_HELPER = node -p "require('./src/utils/reclient.js').helperPath({})"
|
||||
- ps: >-
|
||||
& $env:RECLIENT_HELPER login
|
||||
- ps: >-
|
||||
$env:RBE_service = node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"
|
||||
- ps: >-
|
||||
$env:RBE_credentials_helper = $env:RECLIENT_HELPER
|
||||
- ps: >-
|
||||
$env:RBE_credentials_helper_args = "print"
|
||||
- ps: >-
|
||||
if ($env:ELECTRON_RBE_JWT -eq '') {
|
||||
$env:RBE_fail_early_min_action_count = "0"
|
||||
$env:RBE_fail_early_min_fallback_ratio = "0"
|
||||
}
|
||||
- cd ..\..
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- gclient config --name "src\electron" --unmanaged %GCLIENT_EXTRA_ARGS% "https://github.com/electron/electron"
|
||||
# Patches are applied in the image bake. Check depshash to see if patches have changed.
|
||||
- ps: $env:RUN_GCLIENT_SYNC="false"
|
||||
- ps: $depshash_baked = Get-Content .\src\.depshash -Raw
|
||||
- ps: cd src\electron
|
||||
- ps: node script\generate-deps-hash.js
|
||||
- ps: $depshash = Get-Content .\.depshash -Raw
|
||||
- ps: cd ..\..
|
||||
- ps: >-
|
||||
if ($depshash_baked -ne $depshash) {
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
}
|
||||
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync --with_branch_heads --with_tags ) else ( gclient runhooks )
|
||||
- cd src
|
||||
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") use_remoteexec=true %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common:mojo
|
||||
- gn check out/Default //electron/shell/common:plugin
|
||||
- autoninja -j 300 -C out/Default electron:electron_app
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true %GN_EXTRA_ARGS%"
|
||||
- autoninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- autoninja -C out/Default electron:electron_dist_zip
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') } | Set-Content out/Default/mksnapshot_args
|
||||
- autoninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- autoninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- autoninja -C out/Default electron:electron_chromedriver_zip
|
||||
- autoninja -C out/Default electron:node_headers
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
}
|
||||
- if "%GN_CONFIG%"=="release" ( autoninja -C out/Default electron:electron_symbols )
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python3 electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- ps: |
|
||||
if ($env:TARGET_ARCH -eq 'ia32') {
|
||||
$env:MANIFEST_ARCH = "x86"
|
||||
} else {
|
||||
$env:MANIFEST_ARCH = $env:TARGET_ARCH
|
||||
}
|
||||
$manifest_file = "electron/script/zip_manifests/dist_zip.win.$env:MANIFEST_ARCH.manifest"
|
||||
python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip $manifest_file
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Zip contains files not listed in the manifest $manifest_file"
|
||||
}
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only $env:APPVEYOR_PROJECT_NAME"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif (
|
||||
$artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (-not(Test-Path $artifact_file)) {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python3 script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
}
|
||||
on_finish:
|
||||
# Uncomment this lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Test 1
|
||||
- job_name: Test 2
|
||||
|
||||
environment:
|
||||
DD_ENV: ci
|
||||
DD_SERVICE: electron
|
||||
DD_CIVISIBILITY_LOGS_ENABLED: true
|
||||
DD_GIT_REPOSITORY_URL: "https://github.com/electron/electron.git"
|
||||
ELECTRON_TEST_RESULTS_DIR: C:\projects\src\electron\junit
|
||||
|
||||
init:
|
||||
- ps: |
|
||||
if ($env:RUN_TESTS -ne 'true') {
|
||||
Write-warning "Skipping tests for $env:APPVEYOR_PROJECT_NAME"; Exit-AppveyorBuild
|
||||
}
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"
|
||||
Exit-AppveyorBuild
|
||||
} else {
|
||||
$global:LASTEXITCODE = 0
|
||||
}
|
||||
- npm install -g @datadog/datadog-ci
|
||||
- cd ..
|
||||
- mkdir out\Default
|
||||
- cd ..
|
||||
- ps: |
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build") {
|
||||
$jobId = $job.jobId
|
||||
foreach($artifact_name in $artifacts_to_download) {
|
||||
if ($artifact_name -eq 'electron.lib') {
|
||||
$outfile = "src\out\Default\$artifact_name"
|
||||
} else {
|
||||
$outfile = $artifact_name
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
# Uncomment the following lines to download the pdb.zip to show real stacktraces when crashes happen during testing
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/pdb.zip" -OutFile pdb.zip
|
||||
7z x -y -osrc pdb.zip
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
$out_default_zips = @('dist.zip','chromedriver.zip','mksnapshot.zip')
|
||||
foreach($zip_name in $out_default_zips) {
|
||||
7z x -y -osrc\out\Default $zip_name
|
||||
}
|
||||
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
|
||||
- ps: 7z x -y -osrc node_headers.zip
|
||||
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: |
|
||||
cd src
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
- cd electron
|
||||
# Explicitly set npm_config_arch because the .env doesn't persist
|
||||
- ps: >-
|
||||
if ($env:TARGET_ARCH -eq 'ia32') {
|
||||
$env:npm_config_arch = "ia32"
|
||||
}
|
||||
- ps: $env:tests_files=node script\split-tests $env:shard 2
|
||||
- echo "Running shard %shard% specs %tests_files%"
|
||||
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging --files %tests_files%
|
||||
- cd ..
|
||||
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
- echo "About to verify mksnapshot"
|
||||
- echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd%
|
||||
- echo "Done verifying mksnapshot"
|
||||
- echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd%
|
||||
- echo "Done verifying chromedriver"
|
||||
|
||||
on_finish:
|
||||
# Uncomment these lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- if exist electron\junit\test-results-main.xml ( appveyor-retry appveyor PushArtifact electron\junit\test-results-main.xml )
|
||||
- ps: |
|
||||
if ($env:RUN_TESTS -eq 'true' -And $env:DD_API_KEY) {
|
||||
$env:DD_GIT_COMMIT_SHA = $env:APPVEYOR_REPO_COMMIT
|
||||
$env:DD_GIT_BRANCH = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH
|
||||
$env:DD_TAGS = "os.architecture:$env:TARGET_ARCH,os.family:windows,os.platform:win32"
|
||||
if (Test-Path -Path "C:\projects\src\electron\junit\test-results-main.xml") {
|
||||
C:\Users\appveyor\AppData\Roaming\npm\datadog-ci.ps1 junit upload --verbose C:\projects\src\electron\junit\test-results-main.xml
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,8 @@ v8_enable_snapshot_native_code_counters = false
|
||||
v8_enable_javascript_promise_hooks = true
|
||||
|
||||
enable_cdm_host_verification = false
|
||||
proprietary_codecs = true
|
||||
ffmpeg_branding = "Chrome"
|
||||
proprietary_codecs = true
|
||||
|
||||
enable_printing = true
|
||||
|
||||
@@ -48,7 +48,8 @@ enable_cet_shadow_stack = false
|
||||
is_cfi = false
|
||||
|
||||
# TODO: fix this once sysroots have been updated.
|
||||
use_qt = false
|
||||
use_qt5 = false
|
||||
use_qt6 = false
|
||||
|
||||
# Disables the builtins PGO for V8
|
||||
v8_builtins_profiling_log_file = ""
|
||||
@@ -65,11 +66,6 @@ v8_enable_private_mapping_fork_optimization = true
|
||||
# Expose public V8 symbols for native modules.
|
||||
v8_expose_public_symbols = true
|
||||
|
||||
# Disables unsafe-buffers-usage plugin due to incompatibilities with our reclient implementation
|
||||
# Ref: https://chromium-review.googlesource.com/c/chromium/src/+/5426599
|
||||
# Ref: https://github.com/electron/electron/commit/8e20f16ea35eeaeb149ae63bad3703d782665f6a
|
||||
clang_unsafe_buffers_paths = ""
|
||||
|
||||
# Disable snapshotting a page when printing for its content to be analyzed for
|
||||
# sensitive content by enterprise users.
|
||||
enterprise_cloud_content_analysis = false
|
||||
@@ -78,5 +74,4 @@ enterprise_cloud_content_analysis = false
|
||||
# https://issues.chromium.org/issues/40943039
|
||||
content_enable_legacy_ipc = true
|
||||
|
||||
# Electron has its own unsafe-buffers enforcement directories.
|
||||
clang_unsafe_buffers_paths = "//electron/electron_unsafe_buffers_paths.txt"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import("all.gn")
|
||||
import("//electron/build/args/all.gn")
|
||||
is_component_build = false
|
||||
is_component_ffmpeg = true
|
||||
is_official_build = true
|
||||
proprietary_codecs = false
|
||||
ffmpeg_branding = "Chromium"
|
||||
enable_dsyms = false
|
||||
proprietary_codecs = false
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import("all.gn")
|
||||
import("//electron/build/args/all.gn")
|
||||
is_component_build = false
|
||||
is_official_build = true
|
||||
|
||||
# This may be guarded behind is_chrome_branded alongside
|
||||
# proprietary_codecs https://webrtc-review.googlesource.com/c/src/+/36321,
|
||||
# explicitly override here to build OpenH264 encoder/FFmpeg decoder.
|
||||
# The initialization of the decoder depends on whether ffmpeg has
|
||||
# been built with H.264 support.
|
||||
rtc_use_h264 = proprietary_codecs
|
||||
|
||||
# By default, Electron builds ffmpeg with proprietary codecs enabled. In order
|
||||
# to facilitate users who don't want to ship proprietary codecs in ffmpeg, or
|
||||
# who have an LGPL requirement to ship ffmpeg as a dynamically linked library,
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import("all.gn")
|
||||
import("//electron/build/args/all.gn")
|
||||
is_debug = false
|
||||
is_component_build = false
|
||||
is_component_ffmpeg = true
|
||||
is_official_build = false
|
||||
dcheck_always_on = true
|
||||
symbol_level = 1
|
||||
|
||||
# This may be guarded behind is_chrome_branded alongside
|
||||
# proprietary_codecs https://webrtc-review.googlesource.com/c/src/+/36321,
|
||||
# explicitly override here to build OpenH264 encoder/FFmpeg decoder.
|
||||
# The initialization of the decoder depends on whether ffmpeg has
|
||||
# been built with H.264 support.
|
||||
rtc_use_h264 = proprietary_codecs
|
||||
|
||||
6
build/webpack/webpack.config.preload_realm.js
Normal file
6
build/webpack/webpack.config.preload_realm.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'preload_realm',
|
||||
alwaysHasNode: false,
|
||||
wrapInitWithProfilingTimeout: true,
|
||||
wrapInitWithTryCatch: true
|
||||
});
|
||||
@@ -34,8 +34,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/devtools/features.h",
|
||||
"//chrome/browser/devtools/visual_logging.cc",
|
||||
"//chrome/browser/devtools/visual_logging.h",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.h",
|
||||
"//chrome/browser/file_system_access/file_system_access_features.cc",
|
||||
"//chrome/browser/file_system_access/file_system_access_features.h",
|
||||
"//chrome/browser/icon_loader.cc",
|
||||
@@ -70,6 +68,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker_observer.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager_uma_helper.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager_uma_helper.h",
|
||||
"//chrome/browser/picture_in_picture/scoped_picture_in_picture_occlusion_observation.cc",
|
||||
"//chrome/browser/picture_in_picture/scoped_picture_in_picture_occlusion_observation.h",
|
||||
"//chrome/browser/platform_util.cc",
|
||||
@@ -146,6 +146,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/webui/accessibility/accessibility_ui.h",
|
||||
"//extensions/browser/app_window/size_constraints.cc",
|
||||
"//extensions/browser/app_window/size_constraints.h",
|
||||
"//ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.cc",
|
||||
"//ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.h",
|
||||
"//ui/views/native_window_tracker.h",
|
||||
]
|
||||
|
||||
@@ -176,7 +178,6 @@ static_library("chrome") {
|
||||
}
|
||||
|
||||
public_deps = [
|
||||
"//chrome/browser:dev_ui_browser_resources",
|
||||
"//chrome/browser/resources/accessibility:resources",
|
||||
"//chrome/browser/ui/color:color_headers",
|
||||
"//chrome/browser/ui/color:mixers",
|
||||
@@ -198,6 +199,7 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/webui/tab_search:mojo_bindings",
|
||||
"//chrome/browser/web_applications/mojom:mojom_web_apps_enum",
|
||||
"//components/enterprise/buildflags",
|
||||
"//components/enterprise/common/proto:browser_events_proto",
|
||||
"//components/enterprise/common/proto:connectors_proto",
|
||||
"//components/enterprise/obfuscation/core:enterprise_obfuscation",
|
||||
"//components/safe_browsing/core/browser/db:safebrowsing_proto",
|
||||
@@ -219,9 +221,9 @@ static_library("chrome") {
|
||||
|
||||
if (is_linux) {
|
||||
sources += [
|
||||
"//chrome/browser/extensions/global_shortcut_listener_linux.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_linux.h",
|
||||
"//chrome/browser/icon_loader_auralinux.cc",
|
||||
"//ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc",
|
||||
"//ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h",
|
||||
]
|
||||
sources += [
|
||||
"//chrome/browser/ui/views/status_icons/concat_menu_model.cc",
|
||||
|
||||
@@ -127,6 +127,7 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* [pushNotifications](api/push-notifications.md)
|
||||
* [safeStorage](api/safe-storage.md)
|
||||
* [screen](api/screen.md)
|
||||
* [ServiceWorkerMain](api/service-worker-main.md)
|
||||
* [session](api/session.md)
|
||||
* [ShareMenu](api/share-menu.md)
|
||||
* [systemPreferences](api/system-preferences.md)
|
||||
|
||||
@@ -313,6 +313,12 @@ Set the default value of the `verbatim` parameter in the Node.js [`dns.lookup()`
|
||||
|
||||
The default is `verbatim` and `dns.setDefaultResultOrder()` have higher priority than `--dns-result-order`.
|
||||
|
||||
### `--diagnostic-dir=directory`
|
||||
|
||||
Set the directory to which all Node.js diagnostic output files are written. Defaults to current working directory.
|
||||
|
||||
Affects the default output directory of [v8.setHeapSnapshotNearHeapLimit](https://nodejs.org/docs/latest/api/v8.html#v8setheapsnapshotnearheaplimitlimit).
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: command-line.md#commandlineappendswitchswitch-value
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
|
||||
@@ -61,6 +61,20 @@ The `contextBridge` module has the following methods:
|
||||
* `apiKey` string - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
|
||||
* `api` any - Your API, more information on what this API can be and how it works is available below.
|
||||
|
||||
### `contextBridge.executeInMainWorld(executionScript)` _Experimental_
|
||||
|
||||
<!-- TODO(samuelmaddock): add generics to map the `args` types to the `func` params -->
|
||||
|
||||
* `executionScript` Object
|
||||
* `func` (...args: any[]) => any - A JavaScript function to execute. This function will be serialized which means
|
||||
that any bound parameters and execution context will be lost.
|
||||
* `args` any[] (optional) - An array of arguments to pass to the provided function. These
|
||||
arguments will be copied between worlds in accordance with
|
||||
[the table of supported types.](#parameter--error--return-type-support)
|
||||
|
||||
Returns `any` - A copy of the resulting value from executing the function in the main world.
|
||||
[Refer to the table](#parameter--error--return-type-support) on how values are copied between worlds.
|
||||
|
||||
## Usage
|
||||
|
||||
### API
|
||||
|
||||
@@ -10,13 +10,13 @@ The `inAppPurchase` module emits the following events:
|
||||
|
||||
### Event: 'transactions-updated'
|
||||
|
||||
Emitted when one or more transactions have been updated.
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `transactions` Transaction[] - Array of [`Transaction`](structures/transaction.md) objects.
|
||||
|
||||
Emitted when one or more transactions have been updated.
|
||||
|
||||
## Methods
|
||||
|
||||
The `inAppPurchase` module has the following methods:
|
||||
|
||||
75
docs/api/ipc-main-service-worker.md
Normal file
75
docs/api/ipc-main-service-worker.md
Normal file
@@ -0,0 +1,75 @@
|
||||
## Class: IpcMainServiceWorker
|
||||
|
||||
> Communicate asynchronously from the main process to service workers.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
> [!NOTE]
|
||||
> This API is a subtle variation of [`IpcMain`](ipc-main.md)—targeted for
|
||||
> communicating with service workers. For communicating with web frames,
|
||||
> consult the `IpcMain` documentation.
|
||||
|
||||
<!-- TODO(samuelmaddock): refactor doc gen to allow generics to reduce duplication -->
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `ipcMainServiceWorker.on(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainServiceWorkerEvent][ipc-main-service-worker-event]
|
||||
* `...args` any[]
|
||||
|
||||
Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
`listener(event, args...)`.
|
||||
|
||||
#### `ipcMainServiceWorker.once(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainServiceWorkerEvent][ipc-main-service-worker-event]
|
||||
* `...args` any[]
|
||||
|
||||
Adds a one time `listener` function for the event. This `listener` is invoked
|
||||
only the next time a message is sent to `channel`, after which it is removed.
|
||||
|
||||
#### `ipcMainServiceWorker.removeListener(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `...args` any[]
|
||||
|
||||
Removes the specified `listener` from the listener array for the specified
|
||||
`channel`.
|
||||
|
||||
#### `ipcMainServiceWorker.removeAllListeners([channel])`
|
||||
|
||||
* `channel` string (optional)
|
||||
|
||||
Removes listeners of the specified `channel`.
|
||||
|
||||
#### `ipcMainServiceWorker.handle(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainServiceWorkerInvokeEvent][ipc-main-service-worker-invoke-event]
|
||||
* `...args` any[]
|
||||
|
||||
#### `ipcMainServiceWorker.handleOnce(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainServiceWorkerInvokeEvent][ipc-main-service-worker-invoke-event]
|
||||
* `...args` any[]
|
||||
|
||||
Handles a single `invoke`able IPC message, then removes the listener. See
|
||||
`ipcMainServiceWorker.handle(channel, listener)`.
|
||||
|
||||
#### `ipcMainServiceWorker.removeHandler(channel)`
|
||||
|
||||
* `channel` string
|
||||
|
||||
Removes any handler for `channel`, if present.
|
||||
|
||||
[ipc-main-service-worker-event]:../api/structures/ipc-main-service-worker-event.md
|
||||
[ipc-main-service-worker-invoke-event]:../api/structures/ipc-main-service-worker-invoke-event.md
|
||||
@@ -41,6 +41,16 @@ The `ipcRenderer` module has the following method to listen for events and send
|
||||
Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
`listener(event, args...)`.
|
||||
|
||||
:::warning
|
||||
Do not expose the `event` argument to the renderer for security reasons! Wrap any
|
||||
callback that you receive from the renderer in another function like this:
|
||||
`ipcRenderer.on('my-channel', (event, ...args) => callback(...args))`.
|
||||
Not wrapping the callback in such a function would expose dangerous Electron APIs
|
||||
to the renderer process. See the
|
||||
[security guide](../tutorial/security.md#20-do-not-expose-electron-apis-to-untrusted-web-content)
|
||||
for more info.
|
||||
:::
|
||||
|
||||
### `ipcRenderer.off(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
|
||||
@@ -5,7 +5,16 @@
|
||||
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.
|
||||
Each [NavigationEntry](./structures/navigation-entry.md) corresponds to a specific visited page.
|
||||
The indexing system follows a sequential order, where the entry for the earliest visited
|
||||
page is at index 0 and the entry for the most recent visited page is at index N.
|
||||
|
||||
Some APIs in this class also accept an _offset_, which is an integer representing the relative
|
||||
position of an index from the current entry according to the above indexing system (i.e. an offset
|
||||
value of `1` would represent going forward in history by one page).
|
||||
|
||||
Maintaining this ordered list of navigation entries enables seamless navigation both backward and
|
||||
forward through the user's browsing history.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
@@ -21,7 +30,7 @@ Returns `boolean` - Whether the browser can go forward to next web page.
|
||||
|
||||
* `offset` Integer
|
||||
|
||||
Returns `boolean` - Whether the web page can go to the specified `offset` from the current entry.
|
||||
Returns `boolean` - Whether the web page can go to the specified relative `offset` from the current entry.
|
||||
|
||||
#### `navigationHistory.clear()`
|
||||
|
||||
@@ -57,7 +66,7 @@ Navigates browser to the specified absolute web page index.
|
||||
|
||||
* `offset` Integer
|
||||
|
||||
Navigates to the specified offset from the current entry.
|
||||
Navigates to the specified relative offset from the current entry.
|
||||
|
||||
#### `navigationHistory.length()`
|
||||
|
||||
@@ -74,3 +83,22 @@ Returns `boolean` - Whether the navigation entry was removed from the webContent
|
||||
#### `navigationHistory.getAllEntries()`
|
||||
|
||||
Returns [`NavigationEntry[]`](structures/navigation-entry.md) - WebContents complete history.
|
||||
|
||||
#### `navigationHistory.restore(options)`
|
||||
|
||||
Restores navigation history and loads the given entry in the in stack. Will make a best effort
|
||||
to restore not just the navigation stack but also the state of the individual pages - for instance
|
||||
including HTML form values or the scroll position. It's recommended to call this API before any
|
||||
navigation entries are created, so ideally before you call `loadURL()` or `loadFile()` on the
|
||||
`webContents` object.
|
||||
|
||||
This API allows you to create common flows that aim to restore, recreate, or clone other webContents.
|
||||
|
||||
* `options` Object
|
||||
* `entries` [NavigationEntry[]](structures/navigation-entry.md) - Result of a prior `getAllEntries()` call
|
||||
* `index` Integer (optional) - Index of the stack that should be loaded. If you set it to `0`, the webContents will load the first (oldest) entry. If you leave it undefined, Electron will automatically load the last (newest) entry.
|
||||
|
||||
Returns `Promise<void>` - the promise will resolve when the page has finished loading the selected navigation entry
|
||||
(see [`did-finish-load`](web-contents.md#event-did-finish-load)), and rejects
|
||||
if the page fails to load (see
|
||||
[`did-fail-load`](web-contents.md#event-did-fail-load)). A noop rejection handler is already attached, which avoids unhandled rejection errors.
|
||||
|
||||
@@ -26,7 +26,10 @@ Emitted when system changes to battery power.
|
||||
|
||||
### Event: 'thermal-state-change' _macOS_
|
||||
|
||||
* `state` string - The system's new thermal state. Can be `unknown`, `nominal`, `fair`, `serious`, `critical`.
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `state` string - The system's new thermal state. Can be `unknown`, `nominal`, `fair`, `serious`, `critical`.
|
||||
|
||||
Emitted when the thermal state of the system changes. Notification of a change
|
||||
in the thermal status of the system, such as entering a critical temperature
|
||||
@@ -44,7 +47,8 @@ See https://developer.apple.com/library/archive/documentation/Performance/Concep
|
||||
|
||||
Returns:
|
||||
|
||||
* `limit` number - The operating system's advertised speed limit for CPUs, in percent.
|
||||
* `details` Event\<\>
|
||||
* `limit` number - The operating system's advertised speed limit for CPUs, in percent.
|
||||
|
||||
Notification of a change in the operating system's advertised speed limit for
|
||||
CPUs, in percent. Values below 100 indicate that the system is impairing
|
||||
|
||||
@@ -114,6 +114,7 @@ A `string` representing the current process's type, can be:
|
||||
|
||||
* `browser` - The main process
|
||||
* `renderer` - A renderer process
|
||||
* `service-worker` - In a service worker
|
||||
* `worker` - In a web worker
|
||||
* `utility` - In a node process launched as a service
|
||||
|
||||
|
||||
54
docs/api/service-worker-main.md
Normal file
54
docs/api/service-worker-main.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# ServiceWorkerMain
|
||||
|
||||
> An instance of a Service Worker representing a version of a script for a given scope.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
## Class: ServiceWorkerMain
|
||||
|
||||
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._
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `serviceWorker.isDestroyed()` _Experimental_
|
||||
|
||||
Returns `boolean` - Whether the service worker has been destroyed.
|
||||
|
||||
#### `serviceWorker.send(channel, ...args)` _Experimental_
|
||||
|
||||
- `channel` string
|
||||
- `...args` any[]
|
||||
|
||||
Send an asynchronous message to the service worker process via `channel`, along with
|
||||
arguments. Arguments will be serialized with the [Structured Clone Algorithm][SCA],
|
||||
just like [`postMessage`][], so prototype chains will not be included.
|
||||
Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.
|
||||
|
||||
The service worker process can handle the message by listening to `channel` with the
|
||||
[`ipcRenderer`](ipc-renderer.md) module.
|
||||
|
||||
#### `serviceWorker.startTask()` _Experimental_
|
||||
|
||||
Returns `Object`:
|
||||
|
||||
- `end` Function - Method to call when the task has ended. If never called, the service won't terminate while otherwise idle.
|
||||
|
||||
Initiate a task to keep the service worker alive until ended.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `serviceWorker.ipc` _Readonly_ _Experimental_
|
||||
|
||||
An [`IpcMainServiceWorker`](ipc-main-service-worker.md) instance scoped to the service worker.
|
||||
|
||||
#### `serviceWorker.scope` _Readonly_ _Experimental_
|
||||
|
||||
A `string` representing the scope URL of the service worker.
|
||||
|
||||
#### `serviceWorker.versionId` _Readonly_ _Experimental_
|
||||
|
||||
A `number` representing the ID of the specific version of the service worker script in its scope.
|
||||
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`postMessage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
|
||||
@@ -56,6 +56,17 @@ Returns:
|
||||
|
||||
Emitted when a service worker has been registered. Can occur after a call to [`navigator.serviceWorker.register('/sw.js')`](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register) successfully resolves or when a Chrome extension is loaded.
|
||||
|
||||
#### Event: 'running-status-changed' _Experimental_
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `versionId` number - ID of the updated service worker version
|
||||
* `runningStatus` string - Running status.
|
||||
Possible values include `starting`, `running`, `stopping`, or `stopped`.
|
||||
|
||||
Emitted when a service worker's running status has changed.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
The following methods are available on instances of `ServiceWorkers`:
|
||||
@@ -64,10 +75,55 @@ The following methods are available on instances of `ServiceWorkers`:
|
||||
|
||||
Returns `Record<number, ServiceWorkerInfo>` - A [ServiceWorkerInfo](structures/service-worker-info.md) object where the keys are the service worker version ID and the values are the information about that service worker.
|
||||
|
||||
#### `serviceWorkers.getFromVersionID(versionId)`
|
||||
#### `serviceWorkers.getInfoFromVersionID(versionId)`
|
||||
|
||||
* `versionId` number
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
|
||||
|
||||
If the service worker does not exist or is not running this method will throw an exception.
|
||||
|
||||
#### `serviceWorkers.getFromVersionID(versionId)` _Deprecated_
|
||||
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
|
||||
|
||||
If the service worker does not exist or is not running this method will throw an exception.
|
||||
|
||||
**Deprecated:** Use the new `serviceWorkers.getInfoFromVersionID` API.
|
||||
|
||||
#### `serviceWorkers.getWorkerFromVersionID(versionId)` _Experimental_
|
||||
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
Returns [`ServiceWorkerMain | undefined`](service-worker-main.md) - Instance of the service worker associated with the given version ID. If there's no associated version, or its running status has changed to 'stopped', this will return `undefined`.
|
||||
|
||||
#### `serviceWorkers.startWorkerForScope(scope)` _Experimental_
|
||||
|
||||
* `scope` string - The scope of the service worker to start.
|
||||
|
||||
Returns `Promise<ServiceWorkerMain>` - Resolves with the service worker when it's started.
|
||||
|
||||
Starts the service worker or does nothing if already running.
|
||||
|
||||
```js
|
||||
const { app, session } = require('electron')
|
||||
const { serviceWorkers } = session.defaultSession
|
||||
|
||||
// Collect service workers scopes
|
||||
const workerScopes = Object.values(serviceWorkers.getAllRunning()).map((info) => info.scope)
|
||||
|
||||
app.on('browser-window-created', async (event, window) => {
|
||||
for (const scope of workerScopes) {
|
||||
try {
|
||||
// Ensure worker is started
|
||||
const serviceWorker = await serviceWorkers.startWorkerForScope(scope)
|
||||
serviceWorker.send('window-created', { windowId: window.id })
|
||||
} catch (error) {
|
||||
console.error(`Failed to start service worker for ${scope}`)
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
@@ -933,6 +933,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
|
||||
* `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).
|
||||
* `deprecated-sync-clipboard-read` _Deprecated_ - Request access to run `document.execCommand("paste")`
|
||||
* `requestingOrigin` string - The origin URL of the permission check
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
* `embeddingOrigin` string (optional) - The origin of the frame embedding the frame that made the permission check. Only set for cross-origin sub frames making permission checks.
|
||||
@@ -1330,18 +1331,43 @@ the initial state will be `interrupted`. The download will start only when the
|
||||
|
||||
Returns `Promise<void>` - resolves when the session’s HTTP authentication cache has been cleared.
|
||||
|
||||
#### `ses.setPreloads(preloads)`
|
||||
#### `ses.setPreloads(preloads)` _Deprecated_
|
||||
|
||||
* `preloads` string[] - An array of absolute path to preload scripts
|
||||
|
||||
Adds scripts that will be executed on ALL web contents that are associated with
|
||||
this session just before normal `preload` scripts run.
|
||||
|
||||
#### `ses.getPreloads()`
|
||||
**Deprecated:** Use the new `ses.registerPreloadScript` API.
|
||||
|
||||
#### `ses.getPreloads()` _Deprecated_
|
||||
|
||||
Returns `string[]` an array of paths to preload scripts that have been
|
||||
registered.
|
||||
|
||||
**Deprecated:** Use the new `ses.getPreloadScripts` API. This will only return preload script paths
|
||||
for `frame` context types.
|
||||
|
||||
#### `ses.registerPreloadScript(script)`
|
||||
|
||||
* `script` [PreloadScriptRegistration](structures/preload-script-registration.md) - Preload script
|
||||
|
||||
Registers preload script that will be executed in its associated context type in this session. For
|
||||
`frame` contexts, this will run prior to any preload defined in the web preferences of a
|
||||
WebContents.
|
||||
|
||||
Returns `string` - The ID of the registered preload script.
|
||||
|
||||
#### `ses.unregisterPreloadScript(id)`
|
||||
|
||||
* `id` string - Preload script ID
|
||||
|
||||
Unregisters script.
|
||||
|
||||
#### `ses.getPreloadScripts()`
|
||||
|
||||
Returns [`PreloadScript[]`](structures/preload-script.md): An array of paths to preload scripts that have been registered.
|
||||
|
||||
#### `ses.setCodeCachePath(path)`
|
||||
|
||||
* `path` String - Absolute path to store the v8 generated JS code cache from the renderer.
|
||||
|
||||
@@ -97,9 +97,10 @@
|
||||
* `height` Integer (optional) - The height of the title bar and Window Controls Overlay in pixels. Default is system height.
|
||||
* `trafficLightPosition` [Point](point.md) (optional) _macOS_ -
|
||||
Set a custom position for the traffic light buttons in frameless windows.
|
||||
* `roundedCorners` boolean (optional) _macOS_ - Whether frameless window
|
||||
should have rounded corners on macOS. Default is `true`. Setting this property
|
||||
to `false` will prevent the window from being fullscreenable.
|
||||
* `roundedCorners` boolean (optional) _macOS_ _Windows_ - Whether frameless window
|
||||
should have rounded corners. Default is `true`. Setting this property
|
||||
to `false` will prevent the window from being fullscreenable on macOS.
|
||||
On Windows versions older than Windows 11 Build 22000 this property has no effect, and frameless windows will not have rounded corners.
|
||||
* `thickFrame` boolean (optional) - Use `WS_THICKFRAME` style for frameless windows on
|
||||
Windows, which adds standard window frame. Setting it to `false` will remove
|
||||
window shadow and window animations. Default is `true`.
|
||||
@@ -149,7 +150,7 @@ Possible values are:
|
||||
focus, keyboard or mouse events, but you can use `globalShortcut` to receive
|
||||
input sparingly.
|
||||
* The `panel` type enables the window to float on top of full-screened apps
|
||||
by adding the `NSWindowStyleMaskNonactivatingPanel` style mask,normally
|
||||
by adding the `NSWindowStyleMaskNonactivatingPanel` style mask, normally
|
||||
reserved for NSPanel, at runtime. Also, the window will appear on all
|
||||
spaces (desktops).
|
||||
* On Windows, possible type is `toolbar`.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* `colorDepth` number - The number of bits per pixel.
|
||||
* `colorSpace` string - represent a color space (three-dimensional object which contains all realizable color combinations) for the purpose of color conversions.
|
||||
* `depthPerComponent` number - The number of bits per color component.
|
||||
* `detected` boolean - `true`` if the display is detected by the system.
|
||||
* `detected` boolean - `true` if the display is detected by the system.
|
||||
* `displayFrequency` number - The display refresh rate.
|
||||
* `id` number - Unique identifier associated with the display. A value of of -1 means the display is invalid or the correct `id` is not yet known, and a value of -10 means the display is a virtual display assigned to a unified desktop.
|
||||
* `internal` boolean - `true` for an internal display and `false` for an external display.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# IpcMainEvent Object extends `Event`
|
||||
|
||||
* `type` String - Possible values include `frame`
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `returnValue` any - Set this to the value to be returned in a synchronous message
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# IpcMainInvokeEvent Object extends `Event`
|
||||
|
||||
* `type` String - Possible values include `frame`
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `sender` [WebContents](../web-contents.md) - Returns the `webContents` that sent the message
|
||||
|
||||
11
docs/api/structures/ipc-main-service-worker-event.md
Normal file
11
docs/api/structures/ipc-main-service-worker-event.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# IpcMainServiceWorkerEvent Object extends `Event`
|
||||
|
||||
* `type` String - Possible values include `service-worker`.
|
||||
* `serviceWorker` [ServiceWorkerMain](../service-worker-main.md) _Readonly_ - The service worker that sent this message
|
||||
* `versionId` Number - The service worker version ID.
|
||||
* `session` Session - The [`Session`](../session.md) instance with which the event is associated.
|
||||
* `returnValue` any - Set this to the value to be returned in a synchronous message
|
||||
* `ports` [MessagePortMain](../message-port-main.md)[] - A list of MessagePorts that were transferred with this message
|
||||
* `reply` Function - A function that will send an IPC message to the renderer frame that sent the original message that you are currently handling. You should use this method to "reply" to the sent message in order to guarantee the reply will go to the correct process and frame.
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
@@ -0,0 +1,6 @@
|
||||
# IpcMainServiceWorkerInvokeEvent Object extends `Event`
|
||||
|
||||
* `type` String - Possible values include `service-worker`.
|
||||
* `serviceWorker` [ServiceWorkerMain](../service-worker-main.md) _Readonly_ - The service worker that sent this message
|
||||
* `versionId` Number - The service worker version ID.
|
||||
* `session` Session - The [`Session`](../session.md) instance with which the event is associated.
|
||||
@@ -2,3 +2,6 @@
|
||||
|
||||
* `url` string
|
||||
* `title` string
|
||||
* `pageState` string (optional) - A base64 encoded data string containing Chromium page state
|
||||
including information like the current scroll position or form values. It is committed by
|
||||
Chromium before a navigation event and on a regular interval.
|
||||
|
||||
6
docs/api/structures/preload-script-registration.md
Normal file
6
docs/api/structures/preload-script-registration.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# PreloadScriptRegistration Object
|
||||
|
||||
* `type` string - Context type where the preload script will be executed.
|
||||
Possible values include `frame` or `service-worker`.
|
||||
* `id` string (optional) - Unique ID of preload script. Defaults to a random UUID.
|
||||
* `filePath` string - Path of the script file. Must be an absolute path.
|
||||
6
docs/api/structures/preload-script.md
Normal file
6
docs/api/structures/preload-script.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# PreloadScript Object
|
||||
|
||||
* `type` string - Context type where the preload script will be executed.
|
||||
Possible values include `frame` or `service-worker`.
|
||||
* `id` string - Unique ID of preload script.
|
||||
* `filePath` string - Path of the script file. Must be an absolute path.
|
||||
@@ -3,3 +3,4 @@
|
||||
* `scriptUrl` string - The full URL to the script that this service worker runs
|
||||
* `scope` string - The base URL that this service worker is active for.
|
||||
* `renderProcessId` number - The virtual ID of the process that this service worker is running in. This is not an OS level PID. This aligns with the ID set used for `webContents.getProcessId()`.
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
this will cause the `preferred-size-changed` event to be emitted on the
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `transparent` boolean (optional) - Whether to enable background transparency for the guest page. Default is `true`. **Note:** The guest page's text and background colors are derived from the [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) of its root element. When transparency is enabled, the text color will still change accordingly but the background will remain transparent.
|
||||
* `enableDeprecatedPaste` boolean (optional) _Deprecated_ - Whether to enable the `paste` [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). Default is `false`.
|
||||
|
||||
[chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment
|
||||
[runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# WebRequestFilter Object
|
||||
|
||||
* `urls` string[] - Array of [URL patterns](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns) that will be used to filter out the requests that do not match the URL patterns.
|
||||
* `types` String[] (optional) - Array of types that will be used to filter out the requests that do not match the types. When not specified, all types will be matched. Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media` or `webSocket`.
|
||||
* `urls` string[] - Array of [URL patterns](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns) used to include requests that match these patterns. Use the pattern `<all_urls>` to match all URLs.
|
||||
* `excludeUrls` string[] (optional) - Array of [URL patterns](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns) used to exclude requests that match these patterns.
|
||||
* `types` string[] (optional) - Array of types that will be used to filter out the requests that do not match the types. When not specified, all types will be matched. Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media` or `webSocket`.
|
||||
|
||||
@@ -6,7 +6,7 @@ Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-p
|
||||
|
||||
```js
|
||||
const { systemPreferences } = require('electron')
|
||||
console.log(systemPreferences.isAeroGlassEnabled())
|
||||
console.log(systemPreferences.getEffectiveAppearance())
|
||||
```
|
||||
|
||||
## Events
|
||||
@@ -181,35 +181,13 @@ Some popular `key` and `type`s are:
|
||||
Removes the `key` in `NSUserDefaults`. This can be used to restore the default
|
||||
or global value of a `key` previously set with `setUserDefault`.
|
||||
|
||||
### `systemPreferences.isAeroGlassEnabled()` _Windows_
|
||||
### `systemPreferences.isAeroGlassEnabled()` _Windows_ _Deprecated_
|
||||
|
||||
Returns `boolean` - `true` if [DWM composition][dwm-composition] (Aero Glass) is
|
||||
enabled, and `false` otherwise.
|
||||
|
||||
An example of using it to determine if you should create a transparent window or
|
||||
not (transparent windows won't work correctly when DWM composition is disabled):
|
||||
|
||||
```js
|
||||
const { BrowserWindow, systemPreferences } = require('electron')
|
||||
const browserOptions = { width: 1000, height: 800 }
|
||||
|
||||
// Make the window transparent only if the platform supports it.
|
||||
if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
|
||||
browserOptions.transparent = true
|
||||
browserOptions.frame = false
|
||||
}
|
||||
|
||||
// Create the window.
|
||||
const win = new BrowserWindow(browserOptions)
|
||||
|
||||
// Navigate.
|
||||
if (browserOptions.transparent) {
|
||||
win.loadFile('index.html')
|
||||
} else {
|
||||
// No transparency, so we load a fallback that uses basic styles.
|
||||
win.loadFile('fallback.html')
|
||||
}
|
||||
```
|
||||
**Deprecated:**
|
||||
This function has been always returning `true` since Electron 23, which only supports Windows 10+.
|
||||
|
||||
[dwm-composition]: https://learn.microsoft.com/en-us/windows/win32/dwm/composition-ovw
|
||||
|
||||
|
||||
@@ -106,6 +106,12 @@ Examples of valid `color` values:
|
||||
|
||||
* `visible` boolean - If false, the view will be hidden from display.
|
||||
|
||||
#### `view.getVisible()`
|
||||
|
||||
Returns `boolean` - Whether the view should be drawn. Note that this is
|
||||
different from whether the view is visible on screen—it may still be obscured
|
||||
or out of view.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
Objects created with `new View` have the following properties:
|
||||
|
||||
@@ -165,13 +165,6 @@ app.on('web-contents-created', (_, webContents) => {
|
||||
})
|
||||
```
|
||||
|
||||
#### `frame.copyImageAt(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
Copy the image at the given position to the clipboard.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `frame.ipc` _Readonly_
|
||||
|
||||
@@ -73,6 +73,7 @@ The `callback` has to be called with an `response` object.
|
||||
Some examples of valid `urls`:
|
||||
|
||||
```js
|
||||
'<all_urls>'
|
||||
'http://foo:1234/'
|
||||
'http://foo.com/'
|
||||
'http://foo:1234/bar'
|
||||
|
||||
@@ -14,6 +14,40 @@ This document uses the following convention to categorize breaking changes:
|
||||
|
||||
## Planned Breaking API Changes (35.0)
|
||||
|
||||
### Deprecated: `setPreloads`, `getPreloads` on `Session`
|
||||
|
||||
`registerPreloadScript`, `unregisterPreloadScript`, and `getPreloadScripts` are introduced as a
|
||||
replacement for the deprecated methods. These new APIs allow third-party libraries to register
|
||||
preload scripts without replacing existing scripts. Also, the new `type` option allows for
|
||||
additional preload targets beyond `frame`.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
session.setPreloads([path.join(__dirname, 'preload.js')])
|
||||
|
||||
// Replace with:
|
||||
session.registerPreloadScript({
|
||||
type: 'frame',
|
||||
id: 'app-preload',
|
||||
filePath: path.join(__dirname, 'preload.js')
|
||||
})
|
||||
```
|
||||
|
||||
### Deprecated: `getFromVersionID` on `session.serviceWorkers`
|
||||
|
||||
The `session.serviceWorkers.fromVersionID(versionId)` API has been deprecated
|
||||
in favor of `session.serviceWorkers.getInfoFromVersionID(versionId)`. This was
|
||||
changed to make it more clear which object is returned with the introduction
|
||||
of the `session.serviceWorkers.getWorkerFromVersionID(versionId)` API.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
session.serviceWorkers.fromVersionID(versionId)
|
||||
|
||||
// Replace with
|
||||
session.serviceWorkers.getInfoFromVersionID(versionId)
|
||||
```
|
||||
|
||||
### Deprecated: `level`, `message`, `line`, and `sourceId` arguments in `console-message` event on `WebContents`
|
||||
|
||||
The `console-message` event on `WebContents` has been updated to provide details on the `Event`
|
||||
@@ -29,6 +63,29 @@ webContents.on('console-message', ({ level, message, lineNumber, sourceId, frame
|
||||
|
||||
Additionally, `level` is now a string with possible values of `info`, `warning`, `error`, and `debug`.
|
||||
|
||||
### Behavior Changed: `urls` property of `WebRequestFilter`.
|
||||
|
||||
Previously, an empty urls array was interpreted as including all URLs. To explicitly include all URLs, developers should now use the `<all_urls>` pattern, which is a [designated URL pattern](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#all_urls) that matches every possible URL. This change clarifies the intent and ensures more predictable behavior.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
const deprecatedFilter = {
|
||||
urls: []
|
||||
}
|
||||
|
||||
// Replace with
|
||||
const newFilter = {
|
||||
urls: ['<all_urls>']
|
||||
}
|
||||
```
|
||||
|
||||
### Deprecated: `systemPreferences.isAeroGlassEnabled()`
|
||||
|
||||
The `systemPreferences.isAeroGlassEnabled()` function has been deprecated without replacement.
|
||||
It has been always returning `true` since Electron 23, which only supports Windows 10+, where DWM composition can no longer be disabled.
|
||||
|
||||
https://learn.microsoft.com/en-us/windows/win32/dwm/composition-ovw#disabling-dwm-composition-windows7-and-earlier
|
||||
|
||||
## Planned Breaking API Changes (34.0)
|
||||
|
||||
### Behavior Changed: menu bar will be hidden during fullscreen on Windows
|
||||
@@ -39,6 +96,15 @@ This brings the behavior to parity with Linux. Prior behavior: Menu bar is still
|
||||
|
||||
## Planned Breaking API Changes (33.0)
|
||||
|
||||
### Deprecated: `document.execCommand("paste")`
|
||||
|
||||
The synchronous clipboard read API [document.execCommand("paste")](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard) has been
|
||||
deprecated in favor of [async clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API). This is to align with the browser defaults.
|
||||
|
||||
The `enableDeprecatedPaste` option on `WebPreferences` that triggers the permission
|
||||
checks for this API and the associated permission type `deprecated-sync-clipboard-read`
|
||||
are also deprecated.
|
||||
|
||||
### Behavior Changed: frame properties may retrieve detached WebFrameMain instances or none at all
|
||||
|
||||
APIs which provide access to a `WebFrameMain` instance may return an instance
|
||||
@@ -56,15 +122,15 @@ immediately upon being received. Otherwise, it's not guaranteed to point to the
|
||||
same webpage as when received. To avoid misaligned expectations, Electron will
|
||||
return `null` in the case of late access where the webpage has changed.
|
||||
|
||||
```ts
|
||||
```js
|
||||
ipcMain.on('unload-event', (event) => {
|
||||
event.senderFrame; // ✅ accessed immediately
|
||||
});
|
||||
event.senderFrame // ✅ accessed immediately
|
||||
})
|
||||
|
||||
ipcMain.on('unload-event', async (event) => {
|
||||
await crossOriginNavigationPromise;
|
||||
event.senderFrame; // ❌ returns `null` due to late access
|
||||
});
|
||||
await crossOriginNavigationPromise
|
||||
event.senderFrame // ❌ returns `null` due to late access
|
||||
})
|
||||
```
|
||||
|
||||
### Behavior Changed: custom protocol URL handling on Windows
|
||||
@@ -111,6 +177,16 @@ macOS 10.15 (Catalina) is no longer supported by [Chromium](https://chromium-rev
|
||||
Older versions of Electron will continue to run on Catalina, but macOS 11 (Big Sur)
|
||||
or later will be required to run Electron v33.0.0 and higher.
|
||||
|
||||
### Behavior Changed: Native modules now require C++20
|
||||
|
||||
Due to changes made upstream, both
|
||||
[V8](https://chromium-review.googlesource.com/c/v8/v8/+/5587859) and
|
||||
[Node.js](https://github.com/nodejs/node/pull/45427) now require C++20 as a
|
||||
minimum version. Developers using native node modules should build their
|
||||
modules with `--std=c++20` rather than `--std=c++17`. Images using gcc9 or
|
||||
lower may need to update to gcc10 in order to compile. See
|
||||
[#43555](https://github.com/electron/electron/pull/43555) for more details.
|
||||
|
||||
### Deprecated: `systemPreferences.accessibilityDisplayShouldReduceTransparency`
|
||||
|
||||
The `systemPreferences.accessibilityDisplayShouldReduceTransparency` property is now deprecated in favor of the new `nativeTheme.prefersReducedTransparency`, which provides identical information and works cross-platform.
|
||||
@@ -182,6 +258,14 @@ win.webContents.navigationHistory.canGoToOffset()
|
||||
win.webContents.navigationHistory.goToOffset(index)
|
||||
```
|
||||
|
||||
### Behavior changed: Directory `databases` in `userData` will be deleted
|
||||
|
||||
If you have a directory called `databases` in the directory returned by
|
||||
`app.getPath('userData')`, it will be deleted when Electron 32 is first run.
|
||||
The `databases` directory was used by WebSQL, which was removed in Electron 31.
|
||||
Chromium now performs a cleanup that deletes this directory. See
|
||||
[issue #45396](https://github.com/electron/electron/issues/45396).
|
||||
|
||||
## Planned Breaking API Changes (31.0)
|
||||
|
||||
### Removed: `WebSQL` support
|
||||
|
||||
@@ -22,12 +22,9 @@ In `preload.js` use the [`contextBridge`][] to inject a method `window.electron.
|
||||
|
||||
```js
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
ipcRenderer.send('ondragstart', path.join(process.cwd(), fileName))
|
||||
}
|
||||
startDrag: (fileName) => ipcRenderer.send('ondragstart', fileName)
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -69,8 +69,25 @@ if (navigationHistory.canGoToOffset(2)) {
|
||||
}
|
||||
```
|
||||
|
||||
## Restoring history
|
||||
|
||||
A common flow is that you want to restore the history of a webContents - for instance to implement an "undo close tab" feature. To do so, you can call `navigationHistory.restore({ index, entries })`. This will restore the webContent's navigation history and the webContents location in said history, meaning that `goBack()` and `goForward()` navigate you through the stack as expected.
|
||||
|
||||
```js @ts-type={navigationHistory:Electron.NavigationHistory}
|
||||
|
||||
const firstWindow = new BrowserWindow()
|
||||
|
||||
// Later, you want a second window to have the same history and navigation position
|
||||
async function restore () {
|
||||
const entries = firstWindow.webContents.navigationHistory.getAllEntries()
|
||||
const index = firstWindow.webContents.navigationHistory.getActiveIndex()
|
||||
|
||||
const secondWindow = new BrowserWindow()
|
||||
await secondWindow.webContents.navigationHistory.restore({ index, entries })
|
||||
}
|
||||
```
|
||||
|
||||
Here's a full example that you can open with Electron Fiddle:
|
||||
|
||||
```fiddle docs/fiddles/features/navigation-history
|
||||
|
||||
```
|
||||
|
||||
@@ -14,7 +14,7 @@ _Notes_:
|
||||
* There are two rendering modes that can be used (see the section below) and only
|
||||
the dirty area is passed to the `paint` event to be more efficient.
|
||||
* You can stop/continue the rendering as well as set the frame rate.
|
||||
* The maximum frame rate is 240 because greater values bring only performance
|
||||
* When `webPreferences.offscreen.useSharedTexture` is not `true`, the maximum frame rate is 240 because greater values bring only performance
|
||||
losses with no benefits.
|
||||
* When nothing is happening on a webpage, no frames are generated.
|
||||
* An offscreen window is always created as a
|
||||
|
||||
@@ -116,6 +116,7 @@ You should at least follow these steps to improve the security of your applicati
|
||||
17. [Validate the `sender` of all IPC messages](#17-validate-the-sender-of-all-ipc-messages)
|
||||
18. [Avoid usage of the `file://` protocol and prefer usage of custom protocols](#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols)
|
||||
19. [Check which fuses you can change](#19-check-which-fuses-you-can-change)
|
||||
20. [Do not expose Electron APIs to untrusted web content](#20-do-not-expose-electron-apis-to-untrusted-web-content)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
@@ -229,7 +230,7 @@ API to remotely loaded content via the [contextBridge API](../api/context-bridge
|
||||
### 3. Enable Context Isolation
|
||||
|
||||
:::info
|
||||
This recommendation is the default behavior in Electron since 12.0.0.
|
||||
Context Isolation is the default behavior in Electron since 12.0.0.
|
||||
:::
|
||||
|
||||
Context isolation is an Electron feature that allows developers to run code
|
||||
@@ -804,6 +805,48 @@ flipping these fuses easy. Check out the README of that module for more details
|
||||
potential error cases, and refer to
|
||||
[How do I flip the fuses?](./fuses.md#how-do-i-flip-the-fuses) in our documentation.
|
||||
|
||||
### 20. Do not expose Electron APIs to untrusted web content
|
||||
|
||||
You should not directly expose Electron's APIs, especially IPC, to untrusted web content in your
|
||||
preload scripts.
|
||||
|
||||
### Why?
|
||||
|
||||
Exposing raw APIs like `ipcRenderer.on` is dangerous because it gives renderer processes direct
|
||||
access to the entire IPC event system, allowing them to listen for any IPC events, not just the ones
|
||||
intended for them.
|
||||
|
||||
To avoid that exposure, we also cannot pass callbacks directly through: The first
|
||||
argument to IPC event callbacks is an `IpcRendererEvent` object, which includes properties like `sender`
|
||||
that provide access to the underlying `ipcRenderer` instance. Even if you only listen for specific
|
||||
events, passing the callback directly means the renderer gets access to this event object.
|
||||
|
||||
In short, we want the untrusted web content to only have access to necessary information and APIs.
|
||||
|
||||
### How?
|
||||
|
||||
```js title='preload'.js'
|
||||
// Bad
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
on: ipcRenderer.on
|
||||
})
|
||||
|
||||
// Also bad
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
|
||||
})
|
||||
|
||||
// Good
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value))
|
||||
})
|
||||
```
|
||||
|
||||
:::info
|
||||
For more information on what `contextIsolation` is and how to use it to secure your app,
|
||||
please see the [Context Isolation](context-isolation.md) document.
|
||||
:::
|
||||
|
||||
[breaking-changes]: ../breaking-changes.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[webview-tag]: ../api/webview-tag.md
|
||||
|
||||
@@ -252,7 +252,7 @@ apps often use the preload script to set up inter-process communication (IPC) in
|
||||
to pass arbitrary messages between the two kinds of processes.
|
||||
|
||||
In the next part of the tutorial, we will be showing you resources on adding more
|
||||
functionality to your app, then teaching you distributing your app to users.
|
||||
functionality to your app, then teaching you how to distribute your app to users.
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Window Customization
|
||||
|
||||
The [`BrowserWindow`][] module is the foundation of your Electron application, and
|
||||
@@ -5,13 +7,15 @@ it exposes many APIs that let you customize the look and behavior of your app’
|
||||
This section covers how to implement various use cases for window customization on macOS,
|
||||
Windows, and Linux.
|
||||
|
||||
:::info
|
||||
`BrowserWindow` is a subclass of the [`BaseWindow`][] module. Both modules allow
|
||||
you to create and manage application windows in Electron, with the main difference
|
||||
being that `BrowserWindow` supports a single, full size web view while `BaseWindow`
|
||||
supports composing many web views. `BaseWindow` can be used interchangeably with `BrowserWindow`
|
||||
in the examples of the documents in this section.
|
||||
:::
|
||||
> [!NOTE]
|
||||
> `BrowserWindow` is a subclass of the [`BaseWindow`][] module. Both modules allow
|
||||
> you to create and manage application windows in Electron, with the main difference
|
||||
> being that `BrowserWindow` supports a single, full size web view while `BaseWindow`
|
||||
> supports composing many web views. `BaseWindow` can be used interchangeably with `BrowserWindow`
|
||||
> in the examples of the documents in this section.
|
||||
|
||||
<!-- markdownlint-disable-next-line MD033 -->
|
||||
<DocCardList />
|
||||
|
||||
[`BaseWindow`]: ../api/base-window.md
|
||||
[`BrowserWindow`]: ../api/browser-window.md
|
||||
|
||||
@@ -55,7 +55,6 @@ template("electron_extra_paks") {
|
||||
"$root_gen_dir/chrome/accessibility_resources.pak",
|
||||
"$root_gen_dir/chrome/browser_resources.pak",
|
||||
"$root_gen_dir/chrome/common_resources.pak",
|
||||
"$root_gen_dir/chrome/dev_ui_browser_resources.pak",
|
||||
"$root_gen_dir/components/components_resources.pak",
|
||||
"$root_gen_dir/content/browser/resources/media/media_internals_resources.pak",
|
||||
"$root_gen_dir/content/browser/tracing/tracing_resources.pak",
|
||||
@@ -69,7 +68,6 @@ template("electron_extra_paks") {
|
||||
"$target_gen_dir/electron_resources.pak",
|
||||
]
|
||||
deps = [
|
||||
"//chrome/browser:dev_ui_browser_resources",
|
||||
"//chrome/browser:resources",
|
||||
"//chrome/browser/resources/accessibility:resources",
|
||||
"//chrome/common:resources",
|
||||
@@ -178,7 +176,7 @@ template("electron_paks") {
|
||||
}
|
||||
|
||||
source_patterns = [
|
||||
"${root_gen_dir}/chrome/chromium_strings_",
|
||||
"${root_gen_dir}/chrome/branded_strings_",
|
||||
"${root_gen_dir}/chrome/locale_settings_",
|
||||
"${root_gen_dir}/chrome/platform_locale_settings_",
|
||||
"${root_gen_dir}/chrome/generated_resources_",
|
||||
|
||||
@@ -25,6 +25,7 @@ auto_filenames = {
|
||||
"docs/api/global-shortcut.md",
|
||||
"docs/api/in-app-purchase.md",
|
||||
"docs/api/incoming-message.md",
|
||||
"docs/api/ipc-main-service-worker.md",
|
||||
"docs/api/ipc-main.md",
|
||||
"docs/api/ipc-renderer.md",
|
||||
"docs/api/menu-item.md",
|
||||
@@ -45,6 +46,7 @@ auto_filenames = {
|
||||
"docs/api/push-notifications.md",
|
||||
"docs/api/safe-storage.md",
|
||||
"docs/api/screen.md",
|
||||
"docs/api/service-worker-main.md",
|
||||
"docs/api/service-workers.md",
|
||||
"docs/api/session.md",
|
||||
"docs/api/share-menu.md",
|
||||
@@ -94,6 +96,8 @@ auto_filenames = {
|
||||
"docs/api/structures/input-event.md",
|
||||
"docs/api/structures/ipc-main-event.md",
|
||||
"docs/api/structures/ipc-main-invoke-event.md",
|
||||
"docs/api/structures/ipc-main-service-worker-event.md",
|
||||
"docs/api/structures/ipc-main-service-worker-invoke-event.md",
|
||||
"docs/api/structures/ipc-renderer-event.md",
|
||||
"docs/api/structures/jump-list-category.md",
|
||||
"docs/api/structures/jump-list-item.md",
|
||||
@@ -114,6 +118,8 @@ auto_filenames = {
|
||||
"docs/api/structures/permission-request.md",
|
||||
"docs/api/structures/point.md",
|
||||
"docs/api/structures/post-body.md",
|
||||
"docs/api/structures/preload-script-registration.md",
|
||||
"docs/api/structures/preload-script.md",
|
||||
"docs/api/structures/printer-info.md",
|
||||
"docs/api/structures/process-memory-info.md",
|
||||
"docs/api/structures/process-metric.md",
|
||||
@@ -169,6 +175,8 @@ auto_filenames = {
|
||||
"lib/renderer/api/web-utils.ts",
|
||||
"lib/renderer/common-init.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-native-setup.ts",
|
||||
"lib/renderer/ipc-renderer-bindings.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/security-warnings.ts",
|
||||
@@ -183,6 +191,8 @@ auto_filenames = {
|
||||
"lib/sandboxed_renderer/api/exports/electron.ts",
|
||||
"lib/sandboxed_renderer/api/module-list.ts",
|
||||
"lib/sandboxed_renderer/init.ts",
|
||||
"lib/sandboxed_renderer/pre-init.ts",
|
||||
"lib/sandboxed_renderer/preload.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
@@ -239,6 +249,7 @@ auto_filenames = {
|
||||
"lib/browser/api/push-notifications.ts",
|
||||
"lib/browser/api/safe-storage.ts",
|
||||
"lib/browser/api/screen.ts",
|
||||
"lib/browser/api/service-worker-main.ts",
|
||||
"lib/browser/api/session.ts",
|
||||
"lib/browser/api/share-menu.ts",
|
||||
"lib/browser/api/system-preferences.ts",
|
||||
@@ -255,6 +266,7 @@ auto_filenames = {
|
||||
"lib/browser/guest-view-manager.ts",
|
||||
"lib/browser/guest-window-manager.ts",
|
||||
"lib/browser/init.ts",
|
||||
"lib/browser/ipc-dispatch.ts",
|
||||
"lib/browser/ipc-main-impl.ts",
|
||||
"lib/browser/ipc-main-internal-utils.ts",
|
||||
"lib/browser/ipc-main-internal.ts",
|
||||
@@ -299,6 +311,8 @@ auto_filenames = {
|
||||
"lib/renderer/common-init.ts",
|
||||
"lib/renderer/init.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-native-setup.ts",
|
||||
"lib/renderer/ipc-renderer-bindings.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/security-warnings.ts",
|
||||
@@ -333,6 +347,7 @@ auto_filenames = {
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/api/web-utils.ts",
|
||||
"lib/renderer/ipc-renderer-bindings.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/worker/init.ts",
|
||||
@@ -373,4 +388,27 @@ auto_filenames = {
|
||||
"typings/internal-ambient.d.ts",
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
|
||||
preload_realm_bundle_deps = [
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/preload_realm/api/exports/electron.ts",
|
||||
"lib/preload_realm/api/module-list.ts",
|
||||
"lib/preload_realm/init.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/ipc-native-setup.ts",
|
||||
"lib/renderer/ipc-renderer-bindings.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/sandboxed_renderer/pre-init.ts",
|
||||
"lib/sandboxed_renderer/preload.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
"typings/internal-ambient.d.ts",
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -296,6 +296,8 @@ filenames = {
|
||||
"shell/browser/api/electron_api_screen.h",
|
||||
"shell/browser/api/electron_api_service_worker_context.cc",
|
||||
"shell/browser/api/electron_api_service_worker_context.h",
|
||||
"shell/browser/api/electron_api_service_worker_main.cc",
|
||||
"shell/browser/api/electron_api_service_worker_main.h",
|
||||
"shell/browser/api/electron_api_session.cc",
|
||||
"shell/browser/api/electron_api_session.h",
|
||||
"shell/browser/api/electron_api_system_preferences.cc",
|
||||
@@ -322,6 +324,7 @@ filenames = {
|
||||
"shell/browser/api/gpu_info_enumerator.h",
|
||||
"shell/browser/api/gpuinfo_manager.cc",
|
||||
"shell/browser/api/gpuinfo_manager.h",
|
||||
"shell/browser/api/ipc_dispatcher.h",
|
||||
"shell/browser/api/message_port.cc",
|
||||
"shell/browser/api/message_port.h",
|
||||
"shell/browser/api/process_metric.cc",
|
||||
@@ -353,6 +356,8 @@ filenames = {
|
||||
"shell/browser/draggable_region_provider.h",
|
||||
"shell/browser/electron_api_ipc_handler_impl.cc",
|
||||
"shell/browser/electron_api_ipc_handler_impl.h",
|
||||
"shell/browser/electron_api_sw_ipc_handler_impl.cc",
|
||||
"shell/browser/electron_api_sw_ipc_handler_impl.h",
|
||||
"shell/browser/electron_autofill_driver.cc",
|
||||
"shell/browser/electron_autofill_driver.h",
|
||||
"shell/browser/electron_autofill_driver_factory.cc",
|
||||
@@ -474,6 +479,7 @@ filenames = {
|
||||
"shell/browser/osr/osr_web_contents_view.h",
|
||||
"shell/browser/plugins/plugin_utils.cc",
|
||||
"shell/browser/plugins/plugin_utils.h",
|
||||
"shell/browser/preload_script.h",
|
||||
"shell/browser/protocol_registry.cc",
|
||||
"shell/browser/protocol_registry.h",
|
||||
"shell/browser/relauncher.cc",
|
||||
@@ -613,6 +619,8 @@ filenames = {
|
||||
"shell/common/gin_converters/osr_converter.cc",
|
||||
"shell/common/gin_converters/osr_converter.h",
|
||||
"shell/common/gin_converters/serial_port_info_converter.h",
|
||||
"shell/common/gin_converters/service_worker_converter.cc",
|
||||
"shell/common/gin_converters/service_worker_converter.h",
|
||||
"shell/common/gin_converters/std_converter.h",
|
||||
"shell/common/gin_converters/time_converter.cc",
|
||||
"shell/common/gin_converters/time_converter.h",
|
||||
@@ -653,6 +661,8 @@ filenames = {
|
||||
"shell/common/gin_helper/pinnable.h",
|
||||
"shell/common/gin_helper/promise.cc",
|
||||
"shell/common/gin_helper/promise.h",
|
||||
"shell/common/gin_helper/reply_channel.cc",
|
||||
"shell/common/gin_helper/reply_channel.h",
|
||||
"shell/common/gin_helper/trackable_object.cc",
|
||||
"shell/common/gin_helper/trackable_object.h",
|
||||
"shell/common/gin_helper/wrappable.cc",
|
||||
@@ -702,14 +712,22 @@ filenames = {
|
||||
"shell/renderer/electron_api_service_impl.h",
|
||||
"shell/renderer/electron_autofill_agent.cc",
|
||||
"shell/renderer/electron_autofill_agent.h",
|
||||
"shell/renderer/electron_ipc_native.cc",
|
||||
"shell/renderer/electron_ipc_native.h",
|
||||
"shell/renderer/electron_render_frame_observer.cc",
|
||||
"shell/renderer/electron_render_frame_observer.h",
|
||||
"shell/renderer/electron_renderer_client.cc",
|
||||
"shell/renderer/electron_renderer_client.h",
|
||||
"shell/renderer/electron_sandboxed_renderer_client.cc",
|
||||
"shell/renderer/electron_sandboxed_renderer_client.h",
|
||||
"shell/renderer/preload_realm_context.cc",
|
||||
"shell/renderer/preload_realm_context.h",
|
||||
"shell/renderer/preload_utils.cc",
|
||||
"shell/renderer/preload_utils.h",
|
||||
"shell/renderer/renderer_client_base.cc",
|
||||
"shell/renderer/renderer_client_base.h",
|
||||
"shell/renderer/service_worker_data.cc",
|
||||
"shell/renderer/service_worker_data.h",
|
||||
"shell/renderer/web_worker_observer.cc",
|
||||
"shell/renderer/web_worker_observer.h",
|
||||
"shell/services/node/node_service.cc",
|
||||
|
||||
@@ -74,6 +74,7 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__algorithm/prev_permutation.h",
|
||||
"//third_party/libc++/src/include/__algorithm/pstl.h",
|
||||
"//third_party/libc++/src/include/__algorithm/push_heap.h",
|
||||
"//third_party/libc++/src/include/__algorithm/radix_sort.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_adjacent_find.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_all_of.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_any_of.h",
|
||||
@@ -1517,7 +1518,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__iterator/wrap_iter.h",
|
||||
"//third_party/libc++/src/include/__locale",
|
||||
"//third_party/libc++/src/include/__locale_dir/locale_base_api/android.h",
|
||||
"//third_party/libc++/src/include/__locale_dir/locale_base_api/bsd_locale_defaults.h",
|
||||
"//third_party/libc++/src/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h",
|
||||
"//third_party/libc++/src/include/__locale_dir/locale_base_api/fuchsia.h",
|
||||
"//third_party/libc++/src/include/__locale_dir/locale_base_api/ibm.h",
|
||||
|
||||
@@ -29,6 +29,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'protocol', loader: () => require('./protocol') },
|
||||
{ name: 'safeStorage', loader: () => require('./safe-storage') },
|
||||
{ name: 'screen', loader: () => require('./screen') },
|
||||
{ name: 'ServiceWorkerMain', loader: () => require('./service-worker-main') },
|
||||
{ name: 'session', loader: () => require('./session') },
|
||||
{ name: 'ShareMenu', loader: () => require('./share-menu') },
|
||||
{ name: 'systemPreferences', loader: () => require('./system-preferences') },
|
||||
|
||||
39
lib/browser/api/service-worker-main.ts
Normal file
39
lib/browser/api/service-worker-main.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl';
|
||||
|
||||
const { ServiceWorkerMain } = process._linkedBinding('electron_browser_service_worker_main');
|
||||
|
||||
Object.defineProperty(ServiceWorkerMain.prototype, 'ipc', {
|
||||
get () {
|
||||
const ipc = new IpcMainImpl();
|
||||
Object.defineProperty(this, 'ipc', { value: ipc });
|
||||
return ipc;
|
||||
}
|
||||
});
|
||||
|
||||
ServiceWorkerMain.prototype.send = function (channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new TypeError('Missing required channel argument');
|
||||
}
|
||||
|
||||
try {
|
||||
return this._send(false /* internal */, channel, args);
|
||||
} catch (e) {
|
||||
console.error('Error sending from ServiceWorkerMain: ', e);
|
||||
}
|
||||
};
|
||||
|
||||
ServiceWorkerMain.prototype.startTask = function () {
|
||||
// TODO(samuelmaddock): maybe make timeout configurable in the future
|
||||
const hasTimeout = false;
|
||||
const { id, ok } = this._startExternalRequest(hasTimeout);
|
||||
|
||||
if (!ok) {
|
||||
throw new Error('Unable to start service worker task.');
|
||||
}
|
||||
|
||||
return {
|
||||
end: () => this._finishExternalRequest(id)
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = ServiceWorkerMain;
|
||||
@@ -1,4 +1,6 @@
|
||||
import { fetchWithSession } from '@electron/internal/browser/api/net-fetch';
|
||||
import { addIpcDispatchListeners } from '@electron/internal/browser/ipc-dispatch';
|
||||
import * as deprecate from '@electron/internal/common/deprecate';
|
||||
|
||||
import { net } from 'electron/main';
|
||||
|
||||
@@ -20,6 +22,10 @@ Object.defineProperty(systemPickerVideoSource, 'id', {
|
||||
systemPickerVideoSource.name = '';
|
||||
Object.freeze(systemPickerVideoSource);
|
||||
|
||||
Session.prototype._init = function () {
|
||||
addIpcDispatchListeners(this, this.serviceWorkers);
|
||||
};
|
||||
|
||||
Session.prototype.fetch = function (input: RequestInfo, init?: RequestInit) {
|
||||
return fetchWithSession(input, init, this, net.request);
|
||||
};
|
||||
@@ -36,6 +42,31 @@ Session.prototype.setDisplayMediaRequestHandler = function (handler, opts) {
|
||||
}, opts);
|
||||
};
|
||||
|
||||
const getPreloadsDeprecated = deprecate.warnOnce('session.getPreloads', 'session.getPreloadScripts');
|
||||
Session.prototype.getPreloads = function () {
|
||||
getPreloadsDeprecated();
|
||||
return this.getPreloadScripts()
|
||||
.filter((script) => script.type === 'frame')
|
||||
.map((script) => script.filePath);
|
||||
};
|
||||
|
||||
const setPreloadsDeprecated = deprecate.warnOnce('session.setPreloads', 'session.registerPreloadScript');
|
||||
Session.prototype.setPreloads = function (preloads) {
|
||||
setPreloadsDeprecated();
|
||||
this.getPreloadScripts()
|
||||
.filter((script) => script.type === 'frame')
|
||||
.forEach((script) => {
|
||||
this.unregisterPreloadScript(script.id);
|
||||
});
|
||||
preloads.map(filePath => ({
|
||||
type: 'frame',
|
||||
filePath,
|
||||
_deprecated: true
|
||||
}) as Electron.PreloadScriptRegistration).forEach(script => {
|
||||
this.registerPreloadScript(script);
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
fromPartition,
|
||||
fromPath,
|
||||
|
||||
@@ -20,4 +20,12 @@ if ('accessibilityDisplayShouldReduceTransparency' in systemPreferences) {
|
||||
});
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
const isAeroGlassEnabledDeprecated = deprecate.warnOnce('systemPreferences.isAeroGlassEnabled');
|
||||
systemPreferences.isAeroGlassEnabled = () => {
|
||||
isAeroGlassEnabledDeprecated();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
export default systemPreferences;
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as deprecate from '@electron/internal/common/deprecate';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
import { app, ipcMain, session, webFrameMain, dialog } from 'electron/main';
|
||||
import type { BrowserWindowConstructorOptions, MessageBoxOptions } from 'electron/main';
|
||||
import type { BrowserWindowConstructorOptions, MessageBoxOptions, NavigationEntry } from 'electron/main';
|
||||
|
||||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
@@ -343,8 +343,8 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
|
||||
|
||||
type LoadError = { errorCode: number, errorDescription: string, url: string };
|
||||
|
||||
WebContents.prototype.loadURL = function (url, options) {
|
||||
const p = new Promise<void>((resolve, reject) => {
|
||||
function _awaitNextLoad (this: Electron.WebContents, navigationUrl: string) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const resolveAndCleanup = () => {
|
||||
removeListeners();
|
||||
resolve();
|
||||
@@ -402,7 +402,7 @@ WebContents.prototype.loadURL = function (url, options) {
|
||||
// the only one is with a bad scheme, perhaps ERR_INVALID_ARGUMENT
|
||||
// would be more appropriate.
|
||||
if (!error) {
|
||||
error = { errorCode: -2, errorDescription: 'ERR_FAILED', url };
|
||||
error = { errorCode: -2, errorDescription: 'ERR_FAILED', url: navigationUrl };
|
||||
}
|
||||
finishListener();
|
||||
};
|
||||
@@ -426,6 +426,10 @@ WebContents.prototype.loadURL = function (url, options) {
|
||||
this.on('did-stop-loading', stopLoadingListener);
|
||||
this.on('destroyed', stopLoadingListener);
|
||||
});
|
||||
};
|
||||
|
||||
WebContents.prototype.loadURL = function (url, options) {
|
||||
const p = _awaitNextLoad.call(this, url);
|
||||
// Add a no-op rejection handler to silence the unhandled rejection error.
|
||||
p.catch(() => {});
|
||||
this._loadURL(url, options ?? {});
|
||||
@@ -476,10 +480,6 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event,
|
||||
}
|
||||
};
|
||||
|
||||
WebContents.prototype.copyImageAt = function (x: number, y: number) {
|
||||
this.mainFrame.copyImageAt(x, y);
|
||||
};
|
||||
|
||||
const addReplyToEvent = (event: Electron.IpcMainEvent) => {
|
||||
const { processId, frameId } = event;
|
||||
event.reply = (channel: string, ...args: any[]) => {
|
||||
@@ -615,7 +615,27 @@ WebContents.prototype._init = function () {
|
||||
length: this._historyLength.bind(this),
|
||||
getEntryAtIndex: this._getNavigationEntryAtIndex.bind(this),
|
||||
removeEntryAtIndex: this._removeNavigationEntryAtIndex.bind(this),
|
||||
getAllEntries: this._getHistory.bind(this)
|
||||
getAllEntries: this._getHistory.bind(this),
|
||||
restore: ({ index, entries }: { index?: number, entries: NavigationEntry[] }) => {
|
||||
if (index === undefined) {
|
||||
index = entries.length - 1;
|
||||
}
|
||||
|
||||
if (index < 0 || !entries[index]) {
|
||||
throw new Error('Invalid index. Index must be a positive integer and within the bounds of the entries length.');
|
||||
}
|
||||
|
||||
const p = _awaitNextLoad.call(this, entries[index].url);
|
||||
p.catch(() => {});
|
||||
|
||||
try {
|
||||
this._restoreHistory(index, entries);
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
},
|
||||
writable: false,
|
||||
enumerable: true
|
||||
|
||||
@@ -69,6 +69,7 @@ const assertChromeDevTools = function (contents: Electron.WebContents, api: stri
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.INSPECTOR_CONTEXT_MENU, function (event, items: ContextMenuItem[], isEditMenu: boolean) {
|
||||
return new Promise<number | void>(resolve => {
|
||||
if (event.type !== 'frame') return;
|
||||
assertChromeDevTools(event.sender, 'window.InspectorFrontendHost.showContextMenuAtPoint()');
|
||||
|
||||
const template = isEditMenu ? getEditMenuItems() : convertToMenuTemplate(items, resolve);
|
||||
@@ -80,6 +81,7 @@ ipcMainInternal.handle(IPC_MESSAGES.INSPECTOR_CONTEXT_MENU, function (event, ite
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.INSPECTOR_SELECT_FILE, async function (event) {
|
||||
if (event.type !== 'frame') return [];
|
||||
assertChromeDevTools(event.sender, 'window.UI.createFileSelectorElement()');
|
||||
|
||||
const result = await dialog.showOpenDialog({});
|
||||
@@ -92,6 +94,7 @@ ipcMainInternal.handle(IPC_MESSAGES.INSPECTOR_SELECT_FILE, async function (event
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.INSPECTOR_CONFIRM, async function (event, message: string = '', title: string = '') {
|
||||
if (event.type !== 'frame') return;
|
||||
assertChromeDevTools(event.sender, 'window.confirm()');
|
||||
|
||||
const options = {
|
||||
|
||||
@@ -267,9 +267,10 @@ const isWebViewTagEnabled = function (contents: Electron.WebContents) {
|
||||
};
|
||||
|
||||
const makeSafeHandler = function<Event extends { sender: Electron.WebContents }> (channel: string, handler: (event: Event, ...args: any[]) => any) {
|
||||
return (event: Event, ...args: any[]) => {
|
||||
return (event: Electron.IpcMainInvokeEvent | Electron.IpcMainServiceWorkerInvokeEvent, ...args: any[]) => {
|
||||
if (event.type !== 'frame') return;
|
||||
if (isWebViewTagEnabled(event.sender)) {
|
||||
return handler(event, ...args);
|
||||
return handler(event as unknown as Event, ...args);
|
||||
} else {
|
||||
console.error(`<webview> IPC message ${channel} sent by WebContents with <webview> disabled (${event.sender.id})`);
|
||||
throw new Error('<webview> disabled');
|
||||
@@ -281,7 +282,7 @@ const handleMessage = function (channel: string, handler: (event: Electron.IpcMa
|
||||
ipcMainInternal.handle(channel, makeSafeHandler(channel, handler));
|
||||
};
|
||||
|
||||
const handleMessageSync = function (channel: string, handler: (event: ElectronInternal.IpcMainInternalEvent, ...args: any[]) => any) {
|
||||
const handleMessageSync = function (channel: string, handler: (event: { sender: Electron.WebContents }, ...args: any[]) => any) {
|
||||
ipcMainUtils.handleSync(channel, makeSafeHandler(channel, handler));
|
||||
};
|
||||
|
||||
@@ -294,8 +295,10 @@ handleMessageSync(IPC_MESSAGES.GUEST_VIEW_MANAGER_DETACH_GUEST, function (event,
|
||||
});
|
||||
|
||||
// this message is sent by the actual <webview>
|
||||
ipcMainInternal.on(IPC_MESSAGES.GUEST_VIEW_MANAGER_FOCUS_CHANGE, function (event: ElectronInternal.IpcMainInternalEvent, focus: boolean) {
|
||||
event.sender.emit('-focus-change', {}, focus);
|
||||
ipcMainInternal.on(IPC_MESSAGES.GUEST_VIEW_MANAGER_FOCUS_CHANGE, function (event, focus: boolean) {
|
||||
if (event.type === 'frame') {
|
||||
event.sender.emit('-focus-change', {}, focus);
|
||||
}
|
||||
});
|
||||
|
||||
handleMessage(IPC_MESSAGES.GUEST_VIEW_MANAGER_CALL, function (event, guestInstanceId: number, method: string, args: any[]) {
|
||||
|
||||
@@ -146,6 +146,9 @@ require('@electron/internal/browser/devtools');
|
||||
// Load protocol module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/protocol');
|
||||
|
||||
// Load service-worker-main module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/service-worker-main');
|
||||
|
||||
// Load web-contents module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/web-contents');
|
||||
|
||||
|
||||
91
lib/browser/ipc-dispatch.ts
Normal file
91
lib/browser/ipc-dispatch.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
|
||||
import type { ServiceWorkerMain } from 'electron/main';
|
||||
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const addReturnValueToEvent = (event: Electron.IpcMainEvent | Electron.IpcMainServiceWorkerEvent) => {
|
||||
Object.defineProperty(event, 'returnValue', {
|
||||
set: (value) => event._replyChannel.sendReply(value),
|
||||
get: () => {}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens for IPC dispatch events on `api`.
|
||||
*
|
||||
* NOTE: Currently this only supports dispatching IPCs for ServiceWorkerMain.
|
||||
*/
|
||||
export function addIpcDispatchListeners (api: NodeJS.EventEmitter, serviceWorkers: Electron.ServiceWorkers) {
|
||||
const getServiceWorkerFromEvent = (event: Electron.IpcMainServiceWorkerEvent | Electron.IpcMainServiceWorkerInvokeEvent): ServiceWorkerMain | undefined => {
|
||||
return serviceWorkers._getWorkerFromVersionIDIfExists(event.versionId);
|
||||
};
|
||||
const addServiceWorkerPropertyToEvent = (event: Electron.IpcMainServiceWorkerEvent | Electron.IpcMainServiceWorkerInvokeEvent) => {
|
||||
Object.defineProperty(event, 'serviceWorker', {
|
||||
get: () => serviceWorkers.getWorkerFromVersionID(event.versionId)
|
||||
});
|
||||
};
|
||||
|
||||
api.on('-ipc-message' as any, function (event: Electron.IpcMainEvent | Electron.IpcMainServiceWorkerEvent, channel: string, args: any[]) {
|
||||
const internal = v8Util.getHiddenValue<boolean>(event, 'internal');
|
||||
|
||||
if (internal) {
|
||||
ipcMainInternal.emit(channel, event, ...args);
|
||||
} else if (event.type === 'service-worker') {
|
||||
addServiceWorkerPropertyToEvent(event);
|
||||
getServiceWorkerFromEvent(event)?.ipc.emit(channel, event, ...args);
|
||||
}
|
||||
} as any);
|
||||
|
||||
api.on('-ipc-invoke' as any, async function (event: Electron.IpcMainInvokeEvent | Electron.IpcMainServiceWorkerInvokeEvent, channel: string, args: any[]) {
|
||||
const internal = v8Util.getHiddenValue<boolean>(event, 'internal');
|
||||
|
||||
const replyWithResult = (result: any) => event._replyChannel.sendReply({ result });
|
||||
const replyWithError = (error: Error) => {
|
||||
console.error(`Error occurred in handler for '${channel}':`, error);
|
||||
event._replyChannel.sendReply({ error: error.toString() });
|
||||
};
|
||||
|
||||
const targets: (Electron.IpcMainServiceWorker | ElectronInternal.IpcMainInternal | undefined)[] = [];
|
||||
|
||||
if (internal) {
|
||||
targets.push(ipcMainInternal);
|
||||
} else if (event.type === 'service-worker') {
|
||||
addServiceWorkerPropertyToEvent(event);
|
||||
const workerIpc = getServiceWorkerFromEvent(event)?.ipc;
|
||||
targets.push(workerIpc);
|
||||
}
|
||||
|
||||
const target = targets.find(target => (target as any)?._invokeHandlers.has(channel));
|
||||
if (target) {
|
||||
const handler = (target as any)._invokeHandlers.get(channel);
|
||||
try {
|
||||
replyWithResult(await Promise.resolve(handler(event, ...args)));
|
||||
} catch (err) {
|
||||
replyWithError(err as Error);
|
||||
}
|
||||
} else {
|
||||
replyWithError(new Error(`No handler registered for '${channel}'`));
|
||||
}
|
||||
} as any);
|
||||
|
||||
api.on('-ipc-message-sync' as any, function (event: Electron.IpcMainEvent | Electron.IpcMainServiceWorkerEvent, channel: string, args: any[]) {
|
||||
const internal = v8Util.getHiddenValue<boolean>(event, 'internal');
|
||||
addReturnValueToEvent(event);
|
||||
if (internal) {
|
||||
ipcMainInternal.emit(channel, event, ...args);
|
||||
} else if (event.type === 'service-worker') {
|
||||
addServiceWorkerPropertyToEvent(event);
|
||||
getServiceWorkerFromEvent(event)?.ipc.emit(channel, event, ...args);
|
||||
}
|
||||
} as any);
|
||||
|
||||
api.on('-ipc-ports' as any, function (event: Electron.IpcMainEvent | Electron.IpcMainServiceWorkerEvent, channel: string, message: any, ports: any[]) {
|
||||
event.ports = ports.map(p => new MessagePortMain(p));
|
||||
if (event.type === 'service-worker') {
|
||||
addServiceWorkerPropertyToEvent(event);
|
||||
getServiceWorkerFromEvent(event)?.ipc.emit(channel, event, message);
|
||||
}
|
||||
} as any);
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export function invokeInWebContents<T> (sender: Electron.WebContents, command: s
|
||||
const requestId = ++nextId;
|
||||
const channel = `${command}_RESPONSE_${requestId}`;
|
||||
ipcMainInternal.on(channel, function handler (event, error: Error, result: any) {
|
||||
if (event.sender !== sender) {
|
||||
if (event.type === 'frame' && event.sender !== sender) {
|
||||
console.error(`Reply to ${command} sent by unexpected WebContents (${event.sender.id})`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,12 @@ import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import { clipboard } from 'electron/common';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
// Implements window.close()
|
||||
ipcMainInternal.on(IPC_MESSAGES.BROWSER_WINDOW_CLOSE, function (event) {
|
||||
if (event.type !== 'frame') return;
|
||||
|
||||
const window = event.sender.getOwnerBrowserWindow();
|
||||
if (window) {
|
||||
window.close();
|
||||
@@ -16,10 +19,12 @@ ipcMainInternal.on(IPC_MESSAGES.BROWSER_WINDOW_CLOSE, function (event) {
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_LAST_WEB_PREFERENCES, function (event) {
|
||||
if (event.type !== 'frame') return;
|
||||
return event.sender.getLastWebPreferences();
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO, function (event) {
|
||||
if (event.type !== 'frame') return;
|
||||
return event.sender._getProcessMemoryInfo();
|
||||
});
|
||||
|
||||
@@ -43,22 +48,47 @@ ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, function (event, me
|
||||
return (clipboard as any)[method](...args);
|
||||
});
|
||||
|
||||
const getPreloadScript = async function (preloadPath: string) {
|
||||
let preloadSrc = null;
|
||||
let preloadError = null;
|
||||
try {
|
||||
preloadSrc = await fs.promises.readFile(preloadPath, 'utf8');
|
||||
} catch (error) {
|
||||
preloadError = error;
|
||||
const getPreloadScriptsFromEvent = (event: ElectronInternal.IpcMainInternalEvent) => {
|
||||
const session: Electron.Session = event.type === 'service-worker' ? event.session : event.sender.session;
|
||||
let preloadScripts = session.getPreloadScripts();
|
||||
|
||||
if (event.type === 'frame') {
|
||||
preloadScripts = preloadScripts.filter(script => script.type === 'frame');
|
||||
|
||||
const webPrefPreload = event.sender._getPreloadScript();
|
||||
if (webPrefPreload) preloadScripts.push(webPrefPreload);
|
||||
} else if (event.type === 'service-worker') {
|
||||
preloadScripts = preloadScripts.filter(script => script.type === 'service-worker');
|
||||
} else {
|
||||
throw new Error(`getPreloadScriptsFromEvent: event.type is invalid (${(event as any).type})`);
|
||||
}
|
||||
return { preloadPath, preloadSrc, preloadError };
|
||||
|
||||
// TODO(samuelmaddock): Remove filter after Session.setPreloads is fully
|
||||
// deprecated. The new API will prevent relative paths from being registered.
|
||||
return preloadScripts.filter(script => path.isAbsolute(script.filePath));
|
||||
};
|
||||
|
||||
const readPreloadScript = async function (script: Electron.PreloadScript): Promise<ElectronInternal.PreloadScript> {
|
||||
let contents;
|
||||
let error;
|
||||
try {
|
||||
contents = await fs.promises.readFile(script.filePath, 'utf8');
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
return {
|
||||
...script,
|
||||
contents,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event) {
|
||||
const preloadPaths = event.sender._getPreloadPaths();
|
||||
|
||||
const preloadScripts = getPreloadScriptsFromEvent(event);
|
||||
return {
|
||||
preloadScripts: await Promise.all(preloadPaths.map(path => getPreloadScript(path))),
|
||||
preloadScripts: await Promise.all(preloadScripts.map(readPreloadScript)),
|
||||
process: {
|
||||
arch: process.arch,
|
||||
platform: process.platform,
|
||||
@@ -71,9 +101,11 @@ ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_NONSANDBOX_LOAD, function (event) {
|
||||
return { preloadPaths: event.sender._getPreloadPaths() };
|
||||
const preloadScripts = getPreloadScriptsFromEvent(event);
|
||||
return { preloadPaths: preloadScripts.map(script => script.filePath) };
|
||||
});
|
||||
|
||||
ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadPath: string, error: Error) {
|
||||
event.sender.emit('preload-error', event, preloadPath, error);
|
||||
if (event.type !== 'frame') return;
|
||||
event.sender?.emit('preload-error', event, preloadPath, error);
|
||||
});
|
||||
|
||||
@@ -24,6 +24,8 @@ const nextTick = (functionToCall: Function, args: any[] = []) => {
|
||||
process.nextTick(() => functionToCall(...args));
|
||||
};
|
||||
|
||||
const binding = internalBinding('fs');
|
||||
|
||||
// Cache asar archive objects.
|
||||
const cachedArchives = new Map<string, NodeJS.AsarArchive>();
|
||||
|
||||
@@ -705,7 +707,137 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
};
|
||||
|
||||
type ReaddirOptions = { encoding: BufferEncoding | null; withFileTypes?: false, recursive?: false } | undefined | null;
|
||||
type ReaddirCallback = (err: NodeJS.ErrnoException | null, files: string[]) => void;
|
||||
type ReaddirCallback = (err: NodeJS.ErrnoException | null, files?: string[]) => void;
|
||||
|
||||
const processReaddirResult = (args: any) => (args.context.withFileTypes ? handleDirents(args) : handleFilePaths(args));
|
||||
|
||||
function handleDirents ({ result, currentPath, context }: { result: any[], currentPath: string, context: any }) {
|
||||
const length = result[0].length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const resultPath = path.join(currentPath, result[0][i]);
|
||||
const info = splitPath(resultPath);
|
||||
|
||||
let type = result[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(currentPath, result[0][i], type);
|
||||
const stat = internalBinding('fs').internalModuleStat(binding, resultPath);
|
||||
|
||||
context.readdirResults.push(dirent);
|
||||
if (dirent.isDirectory() || stat === 1) {
|
||||
context.pathsQueue.push(path.join(dirent.path, dirent.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleFilePaths ({ result, currentPath, context }: { result: string[], currentPath: string, context: any }) {
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const resultPath = path.join(currentPath, result[i]);
|
||||
const relativeResultPath = path.relative(context.basePath, resultPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(binding, resultPath);
|
||||
context.readdirResults.push(relativeResultPath);
|
||||
|
||||
if (stat === 1) {
|
||||
context.pathsQueue.push(resultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readdirRecursive (basePath: string, options: ReaddirOptions, callback: ReaddirCallback) {
|
||||
const context = {
|
||||
withFileTypes: Boolean(options!.withFileTypes),
|
||||
encoding: options!.encoding,
|
||||
basePath,
|
||||
readdirResults: [],
|
||||
pathsQueue: [basePath]
|
||||
};
|
||||
|
||||
let i = 0;
|
||||
|
||||
function read (pathArg: string) {
|
||||
const req = new binding.FSReqCallback();
|
||||
req.oncomplete = (err: any, result: string) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result === undefined) {
|
||||
callback(null, context.readdirResults);
|
||||
return;
|
||||
}
|
||||
|
||||
processReaddirResult({
|
||||
result,
|
||||
currentPath: pathArg,
|
||||
context
|
||||
});
|
||||
|
||||
if (i < context.pathsQueue.length) {
|
||||
read(context.pathsQueue[i++]);
|
||||
} else {
|
||||
callback(null, context.readdirResults);
|
||||
}
|
||||
};
|
||||
|
||||
const pathInfo = splitPath(pathArg);
|
||||
if (pathInfo.isAsar) {
|
||||
let readdirResult;
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
|
||||
const archive = getOrCreateArchive(asarPath);
|
||||
if (!archive) {
|
||||
const error = createError(AsarError.INVALID_ARCHIVE, { asarPath });
|
||||
nextTick(callback, [error]);
|
||||
return;
|
||||
}
|
||||
|
||||
readdirResult = archive.readdir(filePath);
|
||||
if (!readdirResult) {
|
||||
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
nextTick(callback, [error]);
|
||||
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 (context.withFileTypes) {
|
||||
readdirResult = [
|
||||
[...readdirResult], readdirResult.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(binding, path.join(pathArg, p));
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
processReaddirResult({
|
||||
result: readdirResult,
|
||||
currentPath: pathArg,
|
||||
context
|
||||
});
|
||||
|
||||
if (i < context.pathsQueue.length) {
|
||||
read(context.pathsQueue[i++]);
|
||||
} else {
|
||||
callback(null, context.readdirResults);
|
||||
}
|
||||
} else {
|
||||
binding.readdir(
|
||||
pathArg,
|
||||
context.encoding,
|
||||
context.withFileTypes,
|
||||
req
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
read(context.pathsQueue[i++]);
|
||||
}
|
||||
|
||||
const { readdir } = fs;
|
||||
fs.readdir = function (pathArgument: string, options: ReaddirOptions, callback: ReaddirCallback) {
|
||||
@@ -720,7 +852,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
}
|
||||
|
||||
if (options?.recursive) {
|
||||
nextTick(callback!, [null, readdirSyncRecursive(pathArgument, options)]);
|
||||
readdirRecursive(pathArgument, options, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -771,7 +903,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
}
|
||||
|
||||
if (options?.recursive) {
|
||||
return readdirRecursive(pathArgument, options);
|
||||
return readdirRecursivePromises(pathArgument, options);
|
||||
}
|
||||
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
@@ -868,12 +1000,10 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
return readPackageJSON(realPath, isESM, base, specifier);
|
||||
};
|
||||
|
||||
const binding = internalBinding('fs');
|
||||
|
||||
const { internalModuleStat } = binding;
|
||||
internalBinding('fs').internalModuleStat = (pathArgument: string) => {
|
||||
internalBinding('fs').internalModuleStat = (receiver: unknown, pathArgument: string) => {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return internalModuleStat(pathArgument);
|
||||
if (!pathInfo.isAsar) return internalModuleStat(receiver, pathArgument);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
|
||||
// -ENOENT
|
||||
@@ -888,7 +1018,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
};
|
||||
|
||||
const { kUsePromises } = binding;
|
||||
async function readdirRecursive (originalPath: string, options: ReaddirOptions) {
|
||||
async function readdirRecursivePromises (originalPath: string, options: ReaddirOptions) {
|
||||
const result: any[] = [];
|
||||
|
||||
const pathInfo = splitPath(originalPath);
|
||||
@@ -908,7 +1038,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
if (withFileTypes) {
|
||||
initialItem = [
|
||||
[...initialItem], initialItem.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(originalPath, p));
|
||||
return internalBinding('fs').internalModuleStat(binding, path.join(originalPath, p));
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -941,7 +1071,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
|
||||
readdirResult = [
|
||||
[...files], files.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(direntPath, p));
|
||||
return internalBinding('fs').internalModuleStat(binding, path.join(direntPath, p));
|
||||
})
|
||||
];
|
||||
} else {
|
||||
@@ -962,7 +1092,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
const { 0: pathArg, 1: readDir } = queue.pop();
|
||||
for (const ent of readDir) {
|
||||
const direntPath = path.join(pathArg, ent);
|
||||
const stat = internalBinding('fs').internalModuleStat(direntPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(binding, direntPath);
|
||||
result.push(path.relative(originalPath, direntPath));
|
||||
|
||||
if (stat === 1) {
|
||||
@@ -992,11 +1122,13 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
}
|
||||
|
||||
function readdirSyncRecursive (basePath: string, options: ReaddirOptions) {
|
||||
const withFileTypes = Boolean(options!.withFileTypes);
|
||||
const encoding = options!.encoding;
|
||||
|
||||
const readdirResults: string[] = [];
|
||||
const pathsQueue = [basePath];
|
||||
const context = {
|
||||
withFileTypes: Boolean(options!.withFileTypes),
|
||||
encoding: options!.encoding,
|
||||
basePath,
|
||||
readdirResults: [] as any,
|
||||
pathsQueue: [basePath]
|
||||
};
|
||||
|
||||
function read (pathArg: string) {
|
||||
let readdirResult;
|
||||
@@ -1011,62 +1143,37 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
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) {
|
||||
if (context.withFileTypes) {
|
||||
readdirResult = [
|
||||
[...readdirResult], readdirResult.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(pathArg, p));
|
||||
return internalBinding('fs').internalModuleStat(binding, path.join(pathArg, p));
|
||||
})
|
||||
];
|
||||
}
|
||||
} else {
|
||||
readdirResult = binding.readdir(
|
||||
path.toNamespacedPath(pathArg),
|
||||
encoding,
|
||||
withFileTypes
|
||||
context.encoding,
|
||||
context.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);
|
||||
}
|
||||
if (readdirResult === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
processReaddirResult({
|
||||
result: readdirResult,
|
||||
currentPath: pathArg,
|
||||
context
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < pathsQueue.length; i++) {
|
||||
read(pathsQueue[i]);
|
||||
for (let i = 0; i < context.pathsQueue.length; i++) {
|
||||
read(context.pathsQueue[i]);
|
||||
}
|
||||
|
||||
return readdirResults;
|
||||
return context.readdirResults;
|
||||
}
|
||||
|
||||
// Calling mkdir for directory inside asar archive should throw ENOTDIR
|
||||
|
||||
18
lib/preload_realm/.eslintrc.json
Normal file
18
lib/preload_realm/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
6
lib/preload_realm/api/exports/electron.ts
Normal file
6
lib/preload_realm/api/exports/electron.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { defineProperties } from '@electron/internal/common/define-properties';
|
||||
import { moduleList } from '@electron/internal/preload_realm/api/module-list';
|
||||
|
||||
module.exports = {};
|
||||
|
||||
defineProperties(module.exports, moduleList);
|
||||
14
lib/preload_realm/api/module-list.ts
Normal file
14
lib/preload_realm/api/module-list.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export const moduleList: ElectronInternal.ModuleEntry[] = [
|
||||
{
|
||||
name: 'contextBridge',
|
||||
loader: () => require('@electron/internal/renderer/api/context-bridge')
|
||||
},
|
||||
{
|
||||
name: 'ipcRenderer',
|
||||
loader: () => require('@electron/internal/renderer/api/ipc-renderer')
|
||||
},
|
||||
{
|
||||
name: 'nativeImage',
|
||||
loader: () => require('@electron/internal/common/api/native-image')
|
||||
}
|
||||
];
|
||||
58
lib/preload_realm/init.ts
Normal file
58
lib/preload_realm/init.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import '@electron/internal/sandboxed_renderer/pre-init';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { createPreloadProcessObject, executeSandboxedPreloadScripts } from '@electron/internal/sandboxed_renderer/preload';
|
||||
|
||||
import * as events from 'events';
|
||||
|
||||
declare const binding: {
|
||||
get: (name: string) => any;
|
||||
process: NodeJS.Process;
|
||||
createPreloadScript: (src: string) => Function
|
||||
};
|
||||
|
||||
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') as typeof ipcRendererUtilsModule;
|
||||
|
||||
const {
|
||||
preloadScripts,
|
||||
process: processProps
|
||||
} = ipcRendererUtils.invokeSync<{
|
||||
preloadScripts: ElectronInternal.PreloadScript[];
|
||||
process: NodeJS.Process;
|
||||
}>(IPC_MESSAGES.BROWSER_SANDBOX_LOAD);
|
||||
|
||||
const electron = require('electron');
|
||||
|
||||
const loadedModules = new Map<string, any>([
|
||||
['electron', electron],
|
||||
['electron/common', electron],
|
||||
['events', events],
|
||||
['node:events', events]
|
||||
]);
|
||||
|
||||
const loadableModules = new Map<string, Function>([
|
||||
['url', () => require('url')],
|
||||
['node:url', () => require('url')]
|
||||
]);
|
||||
|
||||
const preloadProcess = createPreloadProcessObject();
|
||||
|
||||
Object.assign(preloadProcess, binding.process);
|
||||
Object.assign(preloadProcess, processProps);
|
||||
|
||||
Object.assign(process, processProps);
|
||||
|
||||
require('@electron/internal/renderer/ipc-native-setup');
|
||||
|
||||
executeSandboxedPreloadScripts({
|
||||
loadedModules,
|
||||
loadableModules,
|
||||
process: preloadProcess,
|
||||
createPreloadScript: binding.createPreloadScript,
|
||||
exposeGlobals: {
|
||||
Buffer,
|
||||
// FIXME(samuelmaddock): workaround webpack bug replacing this with just
|
||||
// `__webpack_require__.g,` which causes script error
|
||||
global: globalThis
|
||||
}
|
||||
}, preloadScripts);
|
||||
@@ -5,13 +5,17 @@ const checkContextIsolationEnabled = () => {
|
||||
};
|
||||
|
||||
const contextBridge: Electron.ContextBridge = {
|
||||
exposeInMainWorld: (key: string, api: any) => {
|
||||
exposeInMainWorld: (key, api) => {
|
||||
checkContextIsolationEnabled();
|
||||
return binding.exposeAPIInWorld(0, key, api);
|
||||
},
|
||||
exposeInIsolatedWorld: (worldId: number, key: string, api: any) => {
|
||||
exposeInIsolatedWorld: (worldId, key, api) => {
|
||||
checkContextIsolationEnabled();
|
||||
return binding.exposeAPIInWorld(worldId, key, api);
|
||||
},
|
||||
executeInMainWorld: (script) => {
|
||||
checkContextIsolationEnabled();
|
||||
return binding.executeInWorld(0, script);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,8 +31,7 @@ export const internalContextBridge = {
|
||||
},
|
||||
overrideGlobalPropertyFromIsolatedWorld: (keys: string[], getter: Function, setter?: Function) => {
|
||||
return binding._overrideGlobalPropertyFromIsolatedWorld(keys, getter, setter || null);
|
||||
},
|
||||
isInMainWorld: () => binding._isCalledFromMainWorld() as boolean
|
||||
}
|
||||
};
|
||||
|
||||
if (binding._isDebug) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { getIPCRenderer } from '@electron/internal/renderer/ipc-renderer-bindings';
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { ipc } = process._linkedBinding('electron_renderer_ipc');
|
||||
|
||||
const ipc = getIPCRenderer();
|
||||
const internal = false;
|
||||
|
||||
class IpcRenderer extends EventEmitter implements Electron.IpcRenderer {
|
||||
send (channel: string, ...args: any[]) {
|
||||
return ipc.send(internal, channel, args);
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import type * as securityWarningsModule from '@electron/internal/renderer/security-warnings';
|
||||
import type * as webFrameInitModule from '@electron/internal/renderer/web-frame-init';
|
||||
import type * as webViewInitModule from '@electron/internal/renderer/web-view/web-view-init';
|
||||
import type * as windowSetupModule from '@electron/internal/renderer/window-setup';
|
||||
|
||||
import { ipcRenderer } from 'electron/renderer';
|
||||
|
||||
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const nodeIntegration = mainFrame.getWebPreference('nodeIntegration');
|
||||
const webviewTag = mainFrame.getWebPreference('webviewTag');
|
||||
const isHiddenPage = mainFrame.getWebPreference('hiddenPage');
|
||||
const isWebView = mainFrame.getWebPreference('isWebView');
|
||||
|
||||
// ElectronApiServiceImpl will look for the "ipcNative" hidden object when
|
||||
// invoking the 'onMessage' callback.
|
||||
v8Util.setHiddenValue(global, 'ipcNative', {
|
||||
onMessage (internal: boolean, channel: string, ports: MessagePort[], args: any[]) {
|
||||
const sender = internal ? ipcRendererInternal : ipcRenderer;
|
||||
sender.emit(channel, { sender, ports }, ...args);
|
||||
}
|
||||
});
|
||||
require('@electron/internal/renderer/ipc-native-setup');
|
||||
|
||||
switch (window.location.protocol) {
|
||||
case 'devtools:': {
|
||||
|
||||
14
lib/renderer/ipc-native-setup.ts
Normal file
14
lib/renderer/ipc-native-setup.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
import { ipcRenderer } from 'electron/renderer';
|
||||
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
// ElectronApiServiceImpl will look for the "ipcNative" hidden object when
|
||||
// invoking the 'onMessage' callback.
|
||||
v8Util.setHiddenValue(globalThis, 'ipcNative', {
|
||||
onMessage (internal: boolean, channel: string, ports: MessagePort[], args: any[]) {
|
||||
const sender = internal ? ipcRendererInternal : ipcRenderer;
|
||||
sender.emit(channel, { sender, ports }, ...args);
|
||||
}
|
||||
});
|
||||
17
lib/renderer/ipc-renderer-bindings.ts
Normal file
17
lib/renderer/ipc-renderer-bindings.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
let ipc: NodeJS.IpcRendererImpl | undefined;
|
||||
|
||||
/**
|
||||
* Get IPCRenderer implementation for the current process.
|
||||
*/
|
||||
export function getIPCRenderer () {
|
||||
if (ipc) return ipc;
|
||||
const ipcBinding = process._linkedBinding('electron_renderer_ipc');
|
||||
switch (process.type) {
|
||||
case 'renderer':
|
||||
return (ipc = ipcBinding.createForRenderFrame());
|
||||
case 'service-worker':
|
||||
return (ipc = ipcBinding.createForServiceWorker());
|
||||
default:
|
||||
throw new Error(`Cannot create IPCRenderer for '${process.type}' process`);
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,8 @@
|
||||
import { getIPCRenderer } from '@electron/internal/renderer/ipc-renderer-bindings';
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { ipc } = process._linkedBinding('electron_renderer_ipc');
|
||||
|
||||
const ipc = getIPCRenderer();
|
||||
const internal = true;
|
||||
|
||||
class IpcRendererInternal extends EventEmitter implements ElectronInternal.IpcRendererInternal {
|
||||
|
||||
@@ -1,45 +1,23 @@
|
||||
import '@electron/internal/sandboxed_renderer/pre-init';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import type * as ipcRendererInternalModule from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { createPreloadProcessObject, executeSandboxedPreloadScripts } from '@electron/internal/sandboxed_renderer/preload';
|
||||
|
||||
import * as events from 'events';
|
||||
import { setImmediate, clearImmediate } from 'timers';
|
||||
|
||||
declare const binding: {
|
||||
get: (name: string) => any;
|
||||
process: NodeJS.Process;
|
||||
createPreloadScript: (src: string) => Function
|
||||
};
|
||||
|
||||
const { EventEmitter } = events;
|
||||
|
||||
process._linkedBinding = binding.get;
|
||||
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
// Expose Buffer shim as a hidden value. This is used by C++ code to
|
||||
// deserialize Buffer instances sent from browser process.
|
||||
v8Util.setHiddenValue(global, 'Buffer', Buffer);
|
||||
// The process object created by webpack is not an event emitter, fix it so
|
||||
// the API is more compatible with non-sandboxed renderers.
|
||||
for (const prop of Object.keys(EventEmitter.prototype) as (keyof typeof process)[]) {
|
||||
if (Object.hasOwn(process, prop)) {
|
||||
delete process[prop];
|
||||
}
|
||||
}
|
||||
Object.setPrototypeOf(process, EventEmitter.prototype);
|
||||
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal') as typeof ipcRendererInternalModule;
|
||||
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') as typeof ipcRendererUtilsModule;
|
||||
|
||||
const {
|
||||
preloadScripts,
|
||||
process: processProps
|
||||
} = ipcRendererUtils.invokeSync<{
|
||||
preloadScripts: {
|
||||
preloadPath: string;
|
||||
preloadSrc: string | null;
|
||||
preloadError: null | Error;
|
||||
}[];
|
||||
preloadScripts: ElectronInternal.PreloadScript[];
|
||||
process: NodeJS.Process;
|
||||
}>(IPC_MESSAGES.BROWSER_SANDBOX_LOAD);
|
||||
|
||||
@@ -60,10 +38,10 @@ const loadableModules = new Map<string, Function>([
|
||||
['node:url', () => require('url')]
|
||||
]);
|
||||
|
||||
// Pass different process object to the preload script.
|
||||
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
|
||||
const preloadProcess = createPreloadProcessObject();
|
||||
|
||||
// InvokeEmitProcessEvent in ElectronSandboxedRendererClient will look for this
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
v8Util.setHiddenValue(global, 'emit-process-event', (event: string) => {
|
||||
(process as events.EventEmitter).emit(event);
|
||||
(preloadProcess as events.EventEmitter).emit(event);
|
||||
@@ -72,77 +50,22 @@ v8Util.setHiddenValue(global, 'emit-process-event', (event: string) => {
|
||||
Object.assign(preloadProcess, binding.process);
|
||||
Object.assign(preloadProcess, processProps);
|
||||
|
||||
Object.assign(process, binding.process);
|
||||
Object.assign(process, processProps);
|
||||
|
||||
process.getProcessMemoryInfo = preloadProcess.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||
get () {
|
||||
return process.noDeprecation;
|
||||
},
|
||||
set (value) {
|
||||
process.noDeprecation = value;
|
||||
}
|
||||
});
|
||||
|
||||
// This is the `require` function that will be visible to the preload script
|
||||
function preloadRequire (module: string) {
|
||||
if (loadedModules.has(module)) {
|
||||
return loadedModules.get(module);
|
||||
}
|
||||
if (loadableModules.has(module)) {
|
||||
const loadedModule = loadableModules.get(module)!();
|
||||
loadedModules.set(module, loadedModule);
|
||||
return loadedModule;
|
||||
}
|
||||
throw new Error(`module not found: ${module}`);
|
||||
}
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
||||
// that tests can call it to get access to some test only bindings
|
||||
if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
preloadProcess._linkedBinding = process._linkedBinding;
|
||||
}
|
||||
|
||||
// Common renderer initialization
|
||||
require('@electron/internal/renderer/common-init');
|
||||
|
||||
// Wrap the script into a function executed in global scope. It won't have
|
||||
// access to the current scope, so we'll expose a few objects as arguments:
|
||||
//
|
||||
// - `require`: The `preloadRequire` function
|
||||
// - `process`: The `preloadProcess` object
|
||||
// - `Buffer`: Shim of `Buffer` implementation
|
||||
// - `global`: The window object, which is aliased to `global` by webpack.
|
||||
function runPreloadScript (preloadSrc: string) {
|
||||
const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate, clearImmediate, exports, module) {
|
||||
${preloadSrc}
|
||||
})`;
|
||||
|
||||
// eval in window scope
|
||||
const preloadFn = binding.createPreloadScript(preloadWrapperSrc);
|
||||
const exports = {};
|
||||
|
||||
preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate, clearImmediate, exports, { exports });
|
||||
}
|
||||
|
||||
for (const { preloadPath, preloadSrc, preloadError } of preloadScripts) {
|
||||
try {
|
||||
if (preloadSrc) {
|
||||
runPreloadScript(preloadSrc);
|
||||
} else if (preloadError) {
|
||||
throw preloadError;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Unable to load preload script: ${preloadPath}`);
|
||||
console.error(error);
|
||||
|
||||
ipcRendererInternal.send(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, preloadPath, error);
|
||||
executeSandboxedPreloadScripts({
|
||||
loadedModules,
|
||||
loadableModules,
|
||||
process: preloadProcess,
|
||||
createPreloadScript: binding.createPreloadScript,
|
||||
exposeGlobals: {
|
||||
Buffer,
|
||||
// FIXME(samuelmaddock): workaround webpack bug replacing this with just
|
||||
// `__webpack_require__.g,` which causes script error
|
||||
global: globalThis,
|
||||
setImmediate,
|
||||
clearImmediate
|
||||
}
|
||||
}
|
||||
}, preloadScripts);
|
||||
|
||||
30
lib/sandboxed_renderer/pre-init.ts
Normal file
30
lib/sandboxed_renderer/pre-init.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// Pre-initialization code for sandboxed renderers.
|
||||
|
||||
import * as events from 'events';
|
||||
|
||||
declare const binding: {
|
||||
get: (name: string) => any;
|
||||
process: NodeJS.Process;
|
||||
};
|
||||
|
||||
// Expose internal binding getter.
|
||||
process._linkedBinding = binding.get;
|
||||
|
||||
const { EventEmitter } = events;
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
// Include properties from script 'binding' parameter.
|
||||
Object.assign(process, binding.process);
|
||||
|
||||
// Expose Buffer shim as a hidden value. This is used by C++ code to
|
||||
// deserialize Buffer instances sent from browser process.
|
||||
v8Util.setHiddenValue(global, 'Buffer', Buffer);
|
||||
|
||||
// The process object created by webpack is not an event emitter, fix it so
|
||||
// the API is more compatible with non-sandboxed renderers.
|
||||
for (const prop of Object.keys(EventEmitter.prototype) as (keyof typeof process)[]) {
|
||||
if (Object.hasOwn(process, prop)) {
|
||||
delete process[prop];
|
||||
}
|
||||
}
|
||||
Object.setPrototypeOf(process, EventEmitter.prototype);
|
||||
101
lib/sandboxed_renderer/preload.ts
Normal file
101
lib/sandboxed_renderer/preload.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
interface PreloadContext {
|
||||
loadedModules: Map<string, any>;
|
||||
loadableModules: Map<string, any>;
|
||||
|
||||
/** Process object to pass into preloads. */
|
||||
process: NodeJS.Process;
|
||||
|
||||
createPreloadScript: (src: string) => Function
|
||||
|
||||
/** Globals to be exposed to preload context. */
|
||||
exposeGlobals: any;
|
||||
}
|
||||
|
||||
export function createPreloadProcessObject (): NodeJS.Process {
|
||||
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
|
||||
|
||||
preloadProcess.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||
get () {
|
||||
return process.noDeprecation;
|
||||
},
|
||||
set (value) {
|
||||
process.noDeprecation = value;
|
||||
}
|
||||
});
|
||||
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
||||
// that tests can call it to get access to some test only bindings
|
||||
if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
preloadProcess._linkedBinding = process._linkedBinding;
|
||||
}
|
||||
|
||||
return preloadProcess;
|
||||
}
|
||||
|
||||
// This is the `require` function that will be visible to the preload script
|
||||
function preloadRequire (context: PreloadContext, module: string) {
|
||||
if (context.loadedModules.has(module)) {
|
||||
return context.loadedModules.get(module);
|
||||
}
|
||||
if (context.loadableModules.has(module)) {
|
||||
const loadedModule = context.loadableModules.get(module)!();
|
||||
context.loadedModules.set(module, loadedModule);
|
||||
return loadedModule;
|
||||
}
|
||||
throw new Error(`module not found: ${module}`);
|
||||
}
|
||||
|
||||
// Wrap the script into a function executed in global scope. It won't have
|
||||
// access to the current scope, so we'll expose a few objects as arguments:
|
||||
//
|
||||
// - `require`: The `preloadRequire` function
|
||||
// - `process`: The `preloadProcess` object
|
||||
// - `Buffer`: Shim of `Buffer` implementation
|
||||
// - `global`: The window object, which is aliased to `global` by webpack.
|
||||
function runPreloadScript (context: PreloadContext, preloadSrc: string) {
|
||||
const globalVariables = [];
|
||||
const fnParameters = [];
|
||||
for (const [key, value] of Object.entries(context.exposeGlobals)) {
|
||||
globalVariables.push(key);
|
||||
fnParameters.push(value);
|
||||
}
|
||||
const preloadWrapperSrc = `(function(require, process, exports, module, ${globalVariables.join(', ')}) {
|
||||
${preloadSrc}
|
||||
})`;
|
||||
|
||||
// eval in window scope
|
||||
const preloadFn = context.createPreloadScript(preloadWrapperSrc);
|
||||
const exports = {};
|
||||
|
||||
preloadFn(preloadRequire.bind(null, context), context.process, exports, { exports }, ...fnParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute preload scripts within a sandboxed process.
|
||||
*/
|
||||
export function executeSandboxedPreloadScripts (context: PreloadContext, preloadScripts: ElectronInternal.PreloadScript[]) {
|
||||
for (const { filePath, contents, error } of preloadScripts) {
|
||||
try {
|
||||
if (contents) {
|
||||
runPreloadScript(context, contents);
|
||||
} else if (error) {
|
||||
throw error;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Unable to load preload script: ${filePath}`);
|
||||
console.error(error);
|
||||
ipcRendererInternal.send(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, filePath, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,11 @@ with node.js that allows exposing additional digests without patching,
|
||||
this patch is required to provide ripemd160 support in the nodejs crypto
|
||||
module.
|
||||
|
||||
diff --git a/crypto/digest_extra/digest_extra.cc b/crypto/digest_extra/digest_extra.cc
|
||||
index 0b30897db59bdfc9ada43cf44af21bc54b6d8442..d6ecbc05d7beb6efea79166004137f7cab4ce425 100644
|
||||
--- a/crypto/digest_extra/digest_extra.cc
|
||||
+++ b/crypto/digest_extra/digest_extra.cc
|
||||
@@ -87,6 +87,7 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
|
||||
diff --git a/crypto/digest/digest_extra.cc b/crypto/digest/digest_extra.cc
|
||||
index f68ede9156ee57526f4578953c350798a1299f00..1de18075e1cfa7f9660fa3b065cd20bafcbe7ee8 100644
|
||||
--- a/crypto/digest/digest_extra.cc
|
||||
+++ b/crypto/digest/digest_extra.cc
|
||||
@@ -45,6 +45,7 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
|
||||
{NID_sha512, EVP_sha512, SN_sha512, LN_sha512},
|
||||
{NID_sha512_256, EVP_sha512_256, SN_sha512_256, LN_sha512_256},
|
||||
{NID_md5_sha1, EVP_md5_sha1, SN_md5_sha1, LN_md5_sha1},
|
||||
@@ -22,10 +22,10 @@ index 0b30897db59bdfc9ada43cf44af21bc54b6d8442..d6ecbc05d7beb6efea79166004137f7c
|
||||
// hash function when given a signature OID. To avoid unintended lax parsing
|
||||
// of hash OIDs, this is no longer supported for lookup by OID or NID.
|
||||
diff --git a/crypto/fipsmodule/digest/digests.cc.inc b/crypto/fipsmodule/digest/digests.cc.inc
|
||||
index e1b08fa2f2e2e3afca95b1f8b719220c5436903b..90a5d1895b9d5dff2748ef638c06c127ef84797b 100644
|
||||
index 3c1bfac504c8f41788e429f23606a02e87ad03ae..c3a371029cd9e871ebffae5396cc2f8ae773409f 100644
|
||||
--- a/crypto/fipsmodule/digest/digests.cc.inc
|
||||
+++ b/crypto/fipsmodule/digest/digests.cc.inc
|
||||
@@ -60,6 +60,7 @@
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/nid.h>
|
||||
@@ -33,7 +33,7 @@ index e1b08fa2f2e2e3afca95b1f8b719220c5436903b..90a5d1895b9d5dff2748ef638c06c127
|
||||
|
||||
#include "../../internal.h"
|
||||
#include "../bcm_interface.h"
|
||||
@@ -217,4 +218,27 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) {
|
||||
@@ -175,4 +176,27 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) {
|
||||
out->ctx_size = sizeof(SHA512_CTX);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ index e1b08fa2f2e2e3afca95b1f8b719220c5436903b..90a5d1895b9d5dff2748ef638c06c127
|
||||
+
|
||||
#undef CHECK
|
||||
diff --git a/decrepit/evp/evp_do_all.cc b/decrepit/evp/evp_do_all.cc
|
||||
index e199e10ca6602f231df4d83e1efe5254ee20e98f..9fd0e0225fa48b0afb90b525236e54cff17c1c84 100644
|
||||
index e04b80cd6a1a215fc87f8fd8d750c3d258c3974f..8fdf1c624794f568bfc77b7b6b0c510b23905a4d 100644
|
||||
--- a/decrepit/evp/evp_do_all.cc
|
||||
+++ b/decrepit/evp/evp_do_all.cc
|
||||
@@ -79,6 +79,7 @@ void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher,
|
||||
@@ -82,10 +82,10 @@ index e199e10ca6602f231df4d83e1efe5254ee20e98f..9fd0e0225fa48b0afb90b525236e54cf
|
||||
|
||||
void EVP_MD_do_all(void (*callback)(const EVP_MD *cipher, const char *name,
|
||||
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
|
||||
index c3130dc9baf4e28b9eef383a22707a561129ec16..2d046ece0705e8bec17aa1f164e1f9702b2f325b 100644
|
||||
index 5ddc2d3b4cfb8a87eb22fb707230f56dcb7ccb3e..dea3c5b3adf49e1b4aab197e822744c80964afac 100644
|
||||
--- a/include/openssl/digest.h
|
||||
+++ b/include/openssl/digest.h
|
||||
@@ -90,6 +90,9 @@ OPENSSL_EXPORT const EVP_MD *EVP_blake2b256(void);
|
||||
@@ -48,6 +48,9 @@ OPENSSL_EXPORT const EVP_MD *EVP_blake2b256(void);
|
||||
// MD5 and SHA-1, as used in TLS 1.1 and below.
|
||||
OPENSSL_EXPORT const EVP_MD *EVP_md5_sha1(void);
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@ RC2 Ciphers: rc2-40-cbc
|
||||
|
||||
It's unclear whether this would be accepted upstream. We should try regardless.
|
||||
|
||||
diff --git a/crypto/cipher_extra/cipher_extra.cc b/crypto/cipher_extra/cipher_extra.cc
|
||||
index 62850ab6a216d401d023f81007fb59a33b4585f3..95bd172c99874610ec9157c52df4fe0232e78c7f 100644
|
||||
--- a/crypto/cipher_extra/cipher_extra.cc
|
||||
+++ b/crypto/cipher_extra/cipher_extra.cc
|
||||
@@ -73,6 +73,7 @@ static const struct {
|
||||
diff --git a/crypto/cipher/get_cipher.cc b/crypto/cipher/get_cipher.cc
|
||||
index 2622dc78d1da236862312f55bc0a40f26116486e..ac7aff6518ad5c2a0e48bd91d60a1f825851b634 100644
|
||||
--- a/crypto/cipher/get_cipher.cc
|
||||
+++ b/crypto/cipher/get_cipher.cc
|
||||
@@ -31,6 +31,7 @@ static const struct {
|
||||
const EVP_CIPHER *(*func)(void);
|
||||
} kCiphers[] = {
|
||||
{NID_aes_128_cbc, "aes-128-cbc", EVP_aes_128_cbc},
|
||||
@@ -39,7 +39,7 @@ index 62850ab6a216d401d023f81007fb59a33b4585f3..95bd172c99874610ec9157c52df4fe02
|
||||
{NID_aes_128_ctr, "aes-128-ctr", EVP_aes_128_ctr},
|
||||
{NID_aes_128_ecb, "aes-128-ecb", EVP_aes_128_ecb},
|
||||
{NID_aes_128_gcm, "aes-128-gcm", EVP_aes_128_gcm},
|
||||
@@ -83,17 +84,23 @@ static const struct {
|
||||
@@ -41,17 +42,23 @@ static const struct {
|
||||
{NID_aes_192_gcm, "aes-192-gcm", EVP_aes_192_gcm},
|
||||
{NID_aes_192_ofb128, "aes-192-ofb", EVP_aes_192_ofb},
|
||||
{NID_aes_256_cbc, "aes-256-cbc", EVP_aes_256_cbc},
|
||||
@@ -64,7 +64,7 @@ index 62850ab6a216d401d023f81007fb59a33b4585f3..95bd172c99874610ec9157c52df4fe02
|
||||
|
||||
const EVP_CIPHER *EVP_get_cipherbynid(int nid) {
|
||||
diff --git a/decrepit/evp/evp_do_all.cc b/decrepit/evp/evp_do_all.cc
|
||||
index 9fd0e0225fa48b0afb90b525236e54cff17c1c84..dded715011ac8c1dd9e4525f0bdd64088f8007cf 100644
|
||||
index 8fdf1c624794f568bfc77b7b6b0c510b23905a4d..2e40c031e8c681fe921331b26dbf63f4df2fcf71 100644
|
||||
--- a/decrepit/evp/evp_do_all.cc
|
||||
+++ b/decrepit/evp/evp_do_all.cc
|
||||
@@ -20,8 +20,10 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
|
||||
@@ -118,10 +118,10 @@ index 9fd0e0225fa48b0afb90b525236e54cff17c1c84..dded715011ac8c1dd9e4525f0bdd6408
|
||||
callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg);
|
||||
callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg);
|
||||
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
|
||||
index 18c1e708a42d7802b7d52564bceb93a53b7ab9c5..08b830a40e4587435b4e026dee4b205b4813c357 100644
|
||||
index 6bb135801326bc1cbe2b93f02e561e38c90abeca..06bcba4451456c72b168266859482343af76a931 100644
|
||||
--- a/include/openssl/cipher.h
|
||||
+++ b/include/openssl/cipher.h
|
||||
@@ -476,6 +476,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
|
||||
@@ -448,6 +448,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
|
||||
|
||||
// EVP_aes_128_cfb128 is only available in decrepit.
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cfb128(void);
|
||||
|
||||
@@ -8,7 +8,7 @@ This reverts commit ebd8b8965c74ab06bb91f7a00b23822e1f1f26ca.
|
||||
It is causing significant TLS failures in Node.js.
|
||||
|
||||
diff --git a/ssl/ssl_buffer.cc b/ssl/ssl_buffer.cc
|
||||
index 76c74e2941d9912ca93a69254f540a6a6ddd9e74..3baf5043800c8cbca73efa4d8a65a68e9ec0ecc4 100644
|
||||
index 2cdcbc346175eeee69402ecee7f169e61c655199..f7226fe711e4214b216ea2c5173a02124b80f9ef 100644
|
||||
--- a/ssl/ssl_buffer.cc
|
||||
+++ b/ssl/ssl_buffer.cc
|
||||
@@ -230,7 +230,6 @@ int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret,
|
||||
@@ -20,10 +20,10 @@ index 76c74e2941d9912ca93a69254f540a6a6ddd9e74..3baf5043800c8cbca73efa4d8a65a68e
|
||||
|
||||
case ssl_open_record_error:
|
||||
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
|
||||
index 4ede3ad282b30b84df70a24ed9b89c516cddae4e..4d8fe9eb9a2138da994e54da6fa00ffa6a62a71d 100644
|
||||
index 98bd21eed9b71d2339c1fbc19a294cc0f00fe43b..87b6a657b4a5a5423299febb703ea5122be0bf9c 100644
|
||||
--- a/ssl/ssl_lib.cc
|
||||
+++ b/ssl/ssl_lib.cc
|
||||
@@ -1323,7 +1323,7 @@ int SSL_get_error(const SSL *ssl, int ret_code) {
|
||||
@@ -1198,7 +1198,7 @@ int SSL_get_error(const SSL *ssl, int ret_code) {
|
||||
}
|
||||
|
||||
if (ret_code == 0) {
|
||||
@@ -32,7 +32,7 @@ index 4ede3ad282b30b84df70a24ed9b89c516cddae4e..4d8fe9eb9a2138da994e54da6fa00ffa
|
||||
return SSL_ERROR_ZERO_RETURN;
|
||||
}
|
||||
// An EOF was observed which violates the protocol, and the underlying
|
||||
@@ -2690,13 +2690,7 @@ void *SSL_CTX_get_ex_data(const SSL_CTX *ctx, int idx) {
|
||||
@@ -2565,13 +2565,7 @@ void *SSL_CTX_get_ex_data(const SSL_CTX *ctx, int idx) {
|
||||
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user