mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
289 Commits
v13.0.0-be
...
v14.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c398062dd | ||
|
|
7584ca16c1 | ||
|
|
2ceae36766 | ||
|
|
7cf1f8d11c | ||
|
|
9afae17380 | ||
|
|
7884f52976 | ||
|
|
79f67417f0 | ||
|
|
82b0d67d70 | ||
|
|
5d15cec0fd | ||
|
|
a76b53348c | ||
|
|
cce73c3b8d | ||
|
|
08c4b0ab61 | ||
|
|
a1386dc19b | ||
|
|
ae0de8ef9f | ||
|
|
7c32deb70f | ||
|
|
dc7fa1d9f1 | ||
|
|
1c57e078aa | ||
|
|
33bbdcf1de | ||
|
|
be3c2fd0af | ||
|
|
d2654c652a | ||
|
|
583660a85a | ||
|
|
28904714ae | ||
|
|
43d27cc4d1 | ||
|
|
93311c8686 | ||
|
|
362e8421d6 | ||
|
|
13f36d54cf | ||
|
|
79077f6df9 | ||
|
|
4ca518468d | ||
|
|
c4931ff70e | ||
|
|
503d24a473 | ||
|
|
7063b5ef2c | ||
|
|
11199d8824 | ||
|
|
69f3e330e7 | ||
|
|
6ee819aa65 | ||
|
|
4f3664e6d9 | ||
|
|
e12a3cb59c | ||
|
|
8164322195 | ||
|
|
400d7c4bce | ||
|
|
ac9ec1a6ea | ||
|
|
6327a5a4a2 | ||
|
|
99fc054ce9 | ||
|
|
0d7fd7a74f | ||
|
|
b8c2481edb | ||
|
|
484931bba2 | ||
|
|
a354c95d4c | ||
|
|
e12128b65b | ||
|
|
22a70eb803 | ||
|
|
9236e56ddc | ||
|
|
5ee906fd04 | ||
|
|
20801573aa | ||
|
|
e37533b73a | ||
|
|
f8bdef5349 | ||
|
|
dba4df9326 | ||
|
|
b6315612dd | ||
|
|
f78f8d15a9 | ||
|
|
6df2680cb6 | ||
|
|
e775467e9c | ||
|
|
2e9ed50bb0 | ||
|
|
6bd13cc98f | ||
|
|
ef4954fa1f | ||
|
|
f755c521eb | ||
|
|
95e26e2fd4 | ||
|
|
6772e7773e | ||
|
|
17f527f757 | ||
|
|
f73d09374e | ||
|
|
da8c35e3b2 | ||
|
|
c428ec5cd5 | ||
|
|
16b0d1fbdd | ||
|
|
3a569c176a | ||
|
|
14834f35df | ||
|
|
968b30c9b4 | ||
|
|
17a44895dd | ||
|
|
00fa60ef76 | ||
|
|
2865d161b7 | ||
|
|
7d04f729d8 | ||
|
|
e454bded3c | ||
|
|
fe0da255b6 | ||
|
|
63317627b5 | ||
|
|
77dcf1020a | ||
|
|
641e9337f3 | ||
|
|
0c2150a6fa | ||
|
|
62b38812b6 | ||
|
|
3ed8da0931 | ||
|
|
e2f49edf83 | ||
|
|
1fcd6e2740 | ||
|
|
19d7a6b761 | ||
|
|
82ea8ea68c | ||
|
|
c280d770dc | ||
|
|
29603bcc27 | ||
|
|
55c66e3e92 | ||
|
|
9904438118 | ||
|
|
e6aefed0ee | ||
|
|
fa65faa4b0 | ||
|
|
e323bfe661 | ||
|
|
976222b509 | ||
|
|
2a55ae4b85 | ||
|
|
05d164e660 | ||
|
|
ba3b2189ad | ||
|
|
bdeeabdc3c | ||
|
|
f55aa78883 | ||
|
|
52262a9db0 | ||
|
|
5fe07e1e23 | ||
|
|
b9ea4a6ba4 | ||
|
|
a006cf681b | ||
|
|
9684d85101 | ||
|
|
1594c54933 | ||
|
|
9127cff58b | ||
|
|
0f3620099a | ||
|
|
6016e244fa | ||
|
|
54e72fa8e3 | ||
|
|
5d13820441 | ||
|
|
c9217f07e6 | ||
|
|
9fecf8369f | ||
|
|
9a7cfc42aa | ||
|
|
1f575ca3af | ||
|
|
b6254bfd36 | ||
|
|
ae2059eaa1 | ||
|
|
ff96fabe5e | ||
|
|
3122820e58 | ||
|
|
01ca00ec82 | ||
|
|
606fd87d1e | ||
|
|
5be2183dd7 | ||
|
|
2632564ccf | ||
|
|
521146f71e | ||
|
|
dd975328a0 | ||
|
|
fb4e99e729 | ||
|
|
77365e701f | ||
|
|
1453a8e743 | ||
|
|
b9b734c9c4 | ||
|
|
6fbd84fc80 | ||
|
|
7918ddb026 | ||
|
|
89df6b98da | ||
|
|
640a145112 | ||
|
|
aaf03765ed | ||
|
|
7f7b1f6c8a | ||
|
|
d874a59056 | ||
|
|
4f97b9303c | ||
|
|
83d93bcbdc | ||
|
|
d93690ccdc | ||
|
|
3d2b740d9e | ||
|
|
39e3576c48 | ||
|
|
61cf1abd4d | ||
|
|
1e9e2f8cf6 | ||
|
|
7c36463085 | ||
|
|
6a0b03ba6a | ||
|
|
94af0e8bb0 | ||
|
|
5b598037bb | ||
|
|
ea62ecd188 | ||
|
|
665ac6f9c8 | ||
|
|
74318705c2 | ||
|
|
205f572181 | ||
|
|
451e0931bf | ||
|
|
deeb2de14b | ||
|
|
d10398610b | ||
|
|
e99893df22 | ||
|
|
fa320eeb90 | ||
|
|
96ce59609d | ||
|
|
703f8707db | ||
|
|
8c3165434a | ||
|
|
c8d18a0a1c | ||
|
|
db7059eb0a | ||
|
|
a79ef2d525 | ||
|
|
79bcb882ac | ||
|
|
a68d43ce8b | ||
|
|
502d4c19ce | ||
|
|
f35fc93080 | ||
|
|
4057e6b56e | ||
|
|
b52ccc9726 | ||
|
|
8476bed36e | ||
|
|
2d3c65beca | ||
|
|
3b183854ff | ||
|
|
baadcd48df | ||
|
|
14acf00ba9 | ||
|
|
fc7f2042ec | ||
|
|
485fa5bea9 | ||
|
|
08330cb079 | ||
|
|
54bc21929a | ||
|
|
bccafa0289 | ||
|
|
b6ff12ef7f | ||
|
|
80f89a3472 | ||
|
|
c49bc282d5 | ||
|
|
7e961d8a37 | ||
|
|
b6d2ae0455 | ||
|
|
97b6868e9c | ||
|
|
29dfabadfd | ||
|
|
d0989802bd | ||
|
|
ec893f8322 | ||
|
|
22d8f22cfb | ||
|
|
86d23cee40 | ||
|
|
29dc5a2f83 | ||
|
|
3160e608e2 | ||
|
|
f1bb6be4b9 | ||
|
|
2cd53eb46a | ||
|
|
5fc298ee5f | ||
|
|
d54bee03d0 | ||
|
|
4a6bc7a42f | ||
|
|
3010dd93e3 | ||
|
|
88bbe2a352 | ||
|
|
185c343b22 | ||
|
|
b15b820bca | ||
|
|
9f5e3f6685 | ||
|
|
003dd6c16c | ||
|
|
fdc2e2bc57 | ||
|
|
b045d42b0e | ||
|
|
76538d2d38 | ||
|
|
676f74f3dc | ||
|
|
08036802cb | ||
|
|
9e336f5d0c | ||
|
|
d4bec23bde | ||
|
|
d0e88c2476 | ||
|
|
fae4d87a5a | ||
|
|
57a8781c01 | ||
|
|
8f4e362d8f | ||
|
|
d27ad0d182 | ||
|
|
1e16606524 | ||
|
|
b023b33c05 | ||
|
|
45c4dd529f | ||
|
|
41fdf450b2 | ||
|
|
8dfe4abd14 | ||
|
|
f933c249fe | ||
|
|
5e7ae59d29 | ||
|
|
f73256651b | ||
|
|
a442f11574 | ||
|
|
b8926cb4e8 | ||
|
|
b7eb521cec | ||
|
|
ab74cf4e1a | ||
|
|
8d38e9dd54 | ||
|
|
4d1d6c8a3a | ||
|
|
40d779a7f3 | ||
|
|
6bce814736 | ||
|
|
5b710519cf | ||
|
|
6c90411e21 | ||
|
|
74e7f98572 | ||
|
|
8badc6583f | ||
|
|
35cafdd1d8 | ||
|
|
089ac8180f | ||
|
|
102a3740ea | ||
|
|
32ec7e1e21 | ||
|
|
73d0a16ae2 | ||
|
|
5df13e7c8a | ||
|
|
8c6027c519 | ||
|
|
5b205731f6 | ||
|
|
d274df7e3a | ||
|
|
aadf2f4a7c | ||
|
|
d9997c303f | ||
|
|
ab943d78b2 | ||
|
|
f6949dd197 | ||
|
|
e27b7ed248 | ||
|
|
41b5cd1a84 | ||
|
|
7e22523ed2 | ||
|
|
3270613bf7 | ||
|
|
0505beb43d | ||
|
|
8949b8a462 | ||
|
|
5b50c88508 | ||
|
|
9ccb8f5910 | ||
|
|
46cfb347d7 | ||
|
|
ee0ab6f392 | ||
|
|
f4e1a343b9 | ||
|
|
b3a0743121 | ||
|
|
b36292780f | ||
|
|
e99e6a5a8a | ||
|
|
54cc68dd7a | ||
|
|
59432fe30a | ||
|
|
f51f427646 | ||
|
|
4e02d9407a | ||
|
|
77ad17b383 | ||
|
|
be627568b2 | ||
|
|
59669e99cb | ||
|
|
dc36e8e6fc | ||
|
|
1a296e59c2 | ||
|
|
0d94e0d1d9 | ||
|
|
2fed02556d | ||
|
|
eccfa516c5 | ||
|
|
f114dcfd6e | ||
|
|
54bc71da34 | ||
|
|
afb7d9f550 | ||
|
|
d92bab0e29 | ||
|
|
e900271bea | ||
|
|
87df2766ba | ||
|
|
c8148febfa | ||
|
|
e715b9c921 | ||
|
|
55e50a0879 | ||
|
|
b820b4078d | ||
|
|
5defd96ecd | ||
|
|
ca75bca667 | ||
|
|
0b042d3b1c | ||
|
|
9b93750e5e | ||
|
|
6e121d2250 | ||
|
|
2e091d401e |
@@ -85,17 +85,12 @@ machine-linux-2xlarge: &machine-linux-2xlarge
|
||||
|
||||
machine-mac: &machine-mac
|
||||
macos:
|
||||
xcode: "12.2.0"
|
||||
xcode: "12.4.0"
|
||||
|
||||
machine-mac-large: &machine-mac-large
|
||||
resource_class: large
|
||||
macos:
|
||||
xcode: "12.2.0"
|
||||
|
||||
machine-mac-large-arm: &machine-mac-large-arm
|
||||
resource_class: large
|
||||
macos:
|
||||
xcode: "12.2.0"
|
||||
xcode: "12.4.0"
|
||||
|
||||
machine-mac-arm64: &machine-mac-arm64
|
||||
resource_class: electronjs/macos-arm64
|
||||
@@ -230,6 +225,18 @@ step-maybe-notify-slack-success: &step-maybe-notify-slack-success
|
||||
fi
|
||||
when: on_success
|
||||
|
||||
step-maybe-cleanup-arm64-mac: &step-maybe-cleanup-arm64-mac
|
||||
run:
|
||||
name: Cleanup after testing
|
||||
command: |
|
||||
if [ "$TARGET_ARCH" == "arm64" ] &&[ "`uname`" == "Darwin" ]; then
|
||||
killall Electron || echo "No Electron processes left running"
|
||||
killall Safari || echo "No Safari processes left running"
|
||||
rm -rf ~/Library/Application\ Support/Electron*
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
fi
|
||||
when: always
|
||||
|
||||
step-checkout-electron: &step-checkout-electron
|
||||
checkout:
|
||||
path: src/electron
|
||||
@@ -316,6 +323,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
cd ..
|
||||
|
||||
step-restore-brew-cache: &step-restore-brew-cache
|
||||
@@ -517,7 +525,9 @@ step-electron-build: &step-electron-build
|
||||
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default tools/v8_context_snapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
rm -rf out/Default/clang_x64_v8_arm64/gen
|
||||
rm -rf out/Default/clang_x64_v8_arm64/obj
|
||||
rm -rf out/Default/clang_x64/obj
|
||||
|
||||
# Regenerate because we just deleted some ninja files
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
@@ -840,7 +850,7 @@ step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-symbols-store: &step-symbols-store
|
||||
store_artifacts:
|
||||
@@ -920,7 +930,7 @@ step-ninja-summary: &step-ninja-summary
|
||||
command: |
|
||||
set +e
|
||||
set +o pipefail
|
||||
python depot_tools/post_build_ninja_summary.py -C src/out/Default
|
||||
python depot_tools/post_build_ninja_summary.py -C src/out/Default || echo Ninja Summary Failed
|
||||
|
||||
step-ninja-report: &step-ninja-report
|
||||
store_artifacts:
|
||||
@@ -1340,6 +1350,8 @@ steps-tests: &steps-tests
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
- *step-maybe-cleanup-arm64-mac
|
||||
|
||||
steps-test-nan: &steps-test-nan
|
||||
steps:
|
||||
- attach_workspace:
|
||||
@@ -2104,7 +2116,7 @@ jobs:
|
||||
checkout: true
|
||||
|
||||
osx-publish-arm64:
|
||||
<<: *machine-mac-large-arm
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
@@ -2129,7 +2141,7 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
osx-publish-arm64-skip-checkout:
|
||||
<<: *machine-mac-large-arm
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
@@ -2142,7 +2154,7 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
osx-testing-arm64:
|
||||
<<: *machine-mac-large-arm
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-testing-build
|
||||
@@ -2211,7 +2223,7 @@ jobs:
|
||||
checkout: true
|
||||
|
||||
mas-publish-arm64:
|
||||
<<: *machine-mac-large-arm
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas-apple-silicon
|
||||
@@ -2236,7 +2248,7 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
mas-publish-arm64-skip-checkout:
|
||||
<<: *machine-mac-large-arm
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas-apple-silicon
|
||||
@@ -2249,7 +2261,7 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
mas-testing-arm64:
|
||||
<<: *machine-mac-large-arm
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-testing-build
|
||||
@@ -2311,7 +2323,7 @@ jobs:
|
||||
<<: *steps-tests
|
||||
|
||||
linux-x64-testing-asan-tests:
|
||||
<<: *machine-linux-medium
|
||||
<<: *machine-linux-xlarge
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-headless-testing
|
||||
|
||||
@@ -4,4 +4,3 @@
|
||||
APPVEYOR_CLOUD_TOKEN=
|
||||
CIRCLE_TOKEN=
|
||||
ELECTRON_GITHUB_TOKEN=
|
||||
VSTS_TOKEN=
|
||||
6
.github/CODEOWNERS
vendored
6
.github/CODEOWNERS
vendored
@@ -13,9 +13,3 @@ DEPS @electron/wg-upgrades
|
||||
|
||||
# Security WG
|
||||
/lib/browser/rpc-server.ts @electron/wg-security
|
||||
|
||||
# Remote Change Disliker
|
||||
/lib/browser/remote/ @nornagon
|
||||
/lib/renderer/remote/ @nornagon
|
||||
/lib/renderer/api/remote.ts @nornagon
|
||||
/docs/api/remote.md @nornagon
|
||||
|
||||
58
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
58
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -1,58 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve Electron
|
||||
|
||||
---
|
||||
|
||||
<!-- As an open source project with a dedicated but small maintainer team, it can sometimes take a long time for issues to be addressed so please be patient and we will get back to you as soon as we can.
|
||||
-->
|
||||
|
||||
### Preflight Checklist
|
||||
<!-- Please ensure you've completed the following steps by replacing [ ] with [x]-->
|
||||
|
||||
* [ ] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
* [ ] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
* [ ] I have searched the issue tracker for an issue that matches the one I want to file, without success.
|
||||
|
||||
### Issue Details
|
||||
|
||||
* **Electron Version:**
|
||||
* <!-- (output of `node_modules/.bin/electron --version`) e.g. 4.0.3 -->
|
||||
* **Operating System:**
|
||||
* <!-- (Platform and Version) e.g. macOS 10.13.6 / Windows 10 (1803) / Ubuntu 18.04 x64 -->
|
||||
* **Last Known Working Electron version:**
|
||||
* <!-- (if applicable) e.g. 3.1.0 -->
|
||||
|
||||
### Expected Behavior
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
### Actual Behavior
|
||||
<!-- A clear and concise description of what actually happened. -->
|
||||
|
||||
### To Reproduce
|
||||
<!--
|
||||
Your best chance of getting this bug looked at quickly is to provide an example.
|
||||
-->
|
||||
|
||||
<!--
|
||||
For bugs that can be encapsulated in a small experiment, you can use Electron Fiddle (https://github.com/electron/fiddle) to publish your example to a GitHub Gist and link it your bug report.
|
||||
-->
|
||||
|
||||
<!--
|
||||
If Fiddle is insufficient to produce an example, please provide an example REPOSITORY that can be cloned and run. You can fork electron-quick-start (https://github.com/electron/electron-quick-start) and include a link to the branch with your changes.
|
||||
-->
|
||||
|
||||
<!--
|
||||
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
|
||||
```sh
|
||||
$ git clone $YOUR_URL -b $BRANCH
|
||||
$ npm install
|
||||
$ npm start || electron .
|
||||
```
|
||||
-->
|
||||
|
||||
### Screenshots
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
### Additional Information
|
||||
<!-- Add any other context about the problem here. -->
|
||||
77
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
77
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
name: Bug Report
|
||||
description: Report an Electron bug
|
||||
title: "[Bug]: "
|
||||
labels: "bug :beetle:"
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Preflight Checklist
|
||||
description: Please ensure you've completed all of the following.
|
||||
options:
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
required: true
|
||||
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
required: true
|
||||
- label: I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a feature request that matches the one I want to file, without success.
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Electron Version
|
||||
description: What version of Electron are you using?
|
||||
placeholder: 12.0.0
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: What operating system are you using?
|
||||
options:
|
||||
- Windows
|
||||
- macOS
|
||||
- Ubuntu
|
||||
- Other Linux
|
||||
- Other (specify below)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Operating System Version
|
||||
description: What operating system version are you using? On Windows, click Start button > Settings > System > About. On macOS, click the Apple Menu > About This Mac. On Linux, use lsb_release or uname -a.
|
||||
placeholder: "e.g. Windows 10 version 1909, macOS Catalina 10.15.7, or Ubuntu 20.04"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: What arch are you using?
|
||||
options:
|
||||
- x64
|
||||
- ia32
|
||||
- arm64 (including Apple Silicon)
|
||||
- Other (specify below)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Last Known Working Electron version
|
||||
description: What is the last version of Electron this worked in, if applicable?
|
||||
placeholder: 11.0.0
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: A clear description of what actually happens.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Testcase Gist URL
|
||||
description: If you can reproduce the issue in a standalone test case, please use [Electron Fiddle](https://github.com/electron/fiddle) to create one and to publish it as a [GitHub gist](https://gist.github.com) and put the gist URL here. This is **the best way** to ensure this issue is triaged quickly.
|
||||
placeholder: https://gist.github.com/...
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: If your problem needs further explanation, or if the issue you're seeing cannot be reproduced in a gist, please add more information here.
|
||||
21
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
21
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,18 +1,19 @@
|
||||
name: Feature Request
|
||||
about: Suggest an idea for Electron
|
||||
description: Suggest an idea for Electron
|
||||
title: "[Feature Request]: "
|
||||
labels: "enhancement ✨"
|
||||
labels: "enhancement :sparkles:"
|
||||
body:
|
||||
- type: textarea
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Preflight Checklist
|
||||
description: Please ensure you've completed the following steps by replacing [ ] with [x]
|
||||
value: |
|
||||
* [ ] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
* [ ] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
* [ ] I have searched the issue tracker for a feature request that matches the one I want to file, without success.
|
||||
validations:
|
||||
required: true
|
||||
description: Please ensure you've completed all of the following.
|
||||
options:
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
required: true
|
||||
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
required: true
|
||||
- label: I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a feature request that matches the one I want to file, without success.
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Problem Description
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
name: Mac App Store Private API Rejection
|
||||
about: Your app was rejected from the Mac App Store for using private API's
|
||||
|
||||
---
|
||||
|
||||
<!-- As an open source project with a dedicated but small maintainer team, it can sometimes take a long time for issues to be addressed so please be patient and we will get back to you as soon as we can.
|
||||
-->
|
||||
|
||||
### Preflight Checklist
|
||||
<!-- Please ensure you've completed the following steps by replacing [ ] with [x]-->
|
||||
|
||||
* [ ] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
* [ ] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
|
||||
### Issue Details
|
||||
|
||||
* **Electron Version:**
|
||||
* <!-- (output of `node_modules/.bin/electron --version`) e.g. 4.0.3 -->
|
||||
|
||||
### Rejection Email
|
||||
<!-- Paste the contents of your rejection email here, censoring any private information such as app names.-->
|
||||
|
||||
### Additional Information
|
||||
<!-- Add any other context about the problem here. -->
|
||||
30
.github/ISSUE_TEMPLATE/mac_app_store_private_api_rejection.yml
vendored
Normal file
30
.github/ISSUE_TEMPLATE/mac_app_store_private_api_rejection.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Report Mac App Store Private API Rejection
|
||||
description: Your app was rejected from the Mac App Store for using private API's
|
||||
title: "[MAS Rejection]: "
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Preflight Checklist
|
||||
description: Please ensure you've completed all of the following.
|
||||
options:
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
required: true
|
||||
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Electron Version
|
||||
description: What version of Electron are you using?
|
||||
placeholder: 12.0.0
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Rejection Email
|
||||
description: Paste the contents of your rejection email here, censoring any private information such as app names.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: Add any other context about the problem here.
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -68,4 +68,6 @@ ts-gen
|
||||
.depshash-target
|
||||
|
||||
# Used to accelerate builds after sync
|
||||
patches/mtime-cache.json
|
||||
patches/mtime-cache.json
|
||||
|
||||
spec/fixtures/logo.png
|
||||
8
BUILD.gn
8
BUILD.gn
@@ -32,6 +32,10 @@ if (is_mac) {
|
||||
import("//ui/gl/features.gni")
|
||||
import("//v8/gni/v8.gni")
|
||||
import("build/rules.gni")
|
||||
|
||||
assert(
|
||||
mac_deployment_target == "10.11.0",
|
||||
"Chromium has updated the mac_deployment_target, please update this assert, update the supported versions documentation (docs/tutorial/support.md) and flag this as a breaking change")
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
@@ -443,6 +447,7 @@ source_set("electron_lib") {
|
||||
if (is_mac) {
|
||||
deps += [
|
||||
"//components/remote_cocoa/app_shim",
|
||||
"//components/remote_cocoa/browser",
|
||||
"//content/common:mac_helpers",
|
||||
"//ui/accelerated_widget_mac",
|
||||
]
|
||||
@@ -622,6 +627,9 @@ source_set("electron_lib") {
|
||||
"//chrome/services/printing/public/mojom",
|
||||
"//components/printing/common:mojo_interfaces",
|
||||
]
|
||||
if (is_mac) {
|
||||
deps += [ "//chrome/services/mac_notifications/public/mojom" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_electron_extensions) {
|
||||
|
||||
8
DEPS
8
DEPS
@@ -14,11 +14,11 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'90.0.4415.0',
|
||||
'92.0.4475.0',
|
||||
'node_version':
|
||||
'v14.16.0',
|
||||
'v14.16.1',
|
||||
'nan_version':
|
||||
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
|
||||
'v2.14.2',
|
||||
'squirrel.mac_version':
|
||||
'cdc0729c8bf8576bfef18629186e1e9ecf1b0d9f',
|
||||
|
||||
@@ -48,6 +48,8 @@ vars = {
|
||||
# It's only needed to parse the native tests configurations.
|
||||
'checkout_pyyaml': False,
|
||||
|
||||
'use_rts': False,
|
||||
|
||||
'mac_xcode_version': 'default',
|
||||
|
||||
# To allow running hooks without parsing the DEPS tree
|
||||
|
||||
@@ -1 +1 @@
|
||||
13.0.0-beta.6
|
||||
14.0.0-nightly.20210426
|
||||
@@ -36,6 +36,7 @@ environment:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://electron-mission-control.herokuapp.com/rest/appveyor-hook
|
||||
|
||||
@@ -19,4 +19,12 @@ enable_basic_printing = true
|
||||
angle_enable_vulkan_validation_layers = false
|
||||
dawn_enable_vulkan_validation_layers = false
|
||||
|
||||
# This breaks native node modules
|
||||
libcxx_abi_unstable = false
|
||||
|
||||
# These are disabled because they cause the zip manifest to differ between
|
||||
# testing and release builds.
|
||||
# See https://chromium-review.googlesource.com/c/chromium/src/+/2774898.
|
||||
enable_pseudolocales = false
|
||||
|
||||
is_cfi = false
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# require any direct Cocoa locale support.
|
||||
|
||||
import os
|
||||
import errno
|
||||
import sys
|
||||
|
||||
|
||||
@@ -16,7 +17,7 @@ def main(args):
|
||||
try:
|
||||
os.makedirs(dirname)
|
||||
except OSError as e:
|
||||
if e.errno == os.errno.EEXIST:
|
||||
if e.errno == errno.EEXIST:
|
||||
# It's OK if it already exists
|
||||
pass
|
||||
else:
|
||||
|
||||
@@ -61,13 +61,6 @@ module.exports = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (defines.ENABLE_REMOTE_MODULE === 'false') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/remote/server',
|
||||
'@electron/internal/renderer/api/remote'
|
||||
);
|
||||
}
|
||||
|
||||
if (defines.ENABLE_VIEWS_API === 'false') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/api/views/image-view.js'
|
||||
@@ -163,7 +156,7 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
|
||||
setImmediate: false
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimize: env.mode === 'production',
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
|
||||
@@ -22,6 +22,11 @@ template("webpack_build") {
|
||||
"//electron/typings/internal-electron.d.ts",
|
||||
] + invoker.inputs
|
||||
|
||||
mode = "development"
|
||||
if (is_official_build) {
|
||||
mode = "production"
|
||||
}
|
||||
|
||||
args = [
|
||||
"--config",
|
||||
rebase_path(invoker.config_file),
|
||||
@@ -29,6 +34,7 @@ template("webpack_build") {
|
||||
"--output-path=" + rebase_path(get_path_info(invoker.out_file, "dir")),
|
||||
"--env.buildflags=" +
|
||||
rebase_path("$target_gen_dir/buildflags/buildflags.h"),
|
||||
"--env.mode=" + mode,
|
||||
]
|
||||
deps += [ "buildflags" ]
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_DESKTOP_CAPTURER=$enable_desktop_capturer",
|
||||
"ENABLE_RUN_AS_NODE=$enable_run_as_node",
|
||||
"ENABLE_OSR=$enable_osr",
|
||||
"ENABLE_REMOTE_MODULE=$enable_remote_module",
|
||||
"ENABLE_VIEWS_API=$enable_views_api",
|
||||
"ENABLE_PDF_VIEWER=$enable_pdf_viewer",
|
||||
"ENABLE_TTS=$enable_tts",
|
||||
|
||||
@@ -10,8 +10,6 @@ declare_args() {
|
||||
|
||||
enable_osr = true
|
||||
|
||||
enable_remote_module = true
|
||||
|
||||
enable_views_api = true
|
||||
|
||||
enable_pdf_viewer = true
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Use of this source code is governed by the MIT license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/config/ozone.gni")
|
||||
import("//build/config/ui.gni")
|
||||
import("//components/spellcheck/spellcheck_build_features.gni")
|
||||
import("//electron/buildflags/buildflags.gni")
|
||||
@@ -44,7 +45,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/predictors/resolve_host_client_impl.h",
|
||||
"//chrome/browser/ssl/security_state_tab_helper.cc",
|
||||
"//chrome/browser/ssl/security_state_tab_helper.h",
|
||||
"//chrome/browser/ssl/tls_deprecation_config.cc",
|
||||
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.cc",
|
||||
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.h",
|
||||
"//extensions/browser/app_window/size_constraints.cc",
|
||||
@@ -93,12 +93,18 @@ static_library("chrome") {
|
||||
|
||||
if (is_linux) {
|
||||
sources += [ "//chrome/browser/icon_loader_auralinux.cc" ]
|
||||
if (use_x11 || use_ozone) {
|
||||
sources +=
|
||||
[ "//chrome/browser/extensions/global_shortcut_listener_linux.cc" ]
|
||||
}
|
||||
if (use_x11) {
|
||||
sources += [
|
||||
"//chrome/browser/extensions/global_shortcut_listener_x11.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_x11.h",
|
||||
]
|
||||
} else if (use_ozone) {
|
||||
}
|
||||
if (use_ozone) {
|
||||
deps += [ "//ui/ozone" ]
|
||||
sources += [
|
||||
"//chrome/browser/extensions/global_shortcut_listener_ozone.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_ozone.h",
|
||||
@@ -189,7 +195,7 @@ static_library("chrome") {
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
sources += [ "//chrome/browser/media/webrtc/window_icon_util_x11.cc" ]
|
||||
sources += [ "//chrome/browser/media/webrtc/window_icon_util_linux.cc" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,8 +257,12 @@ static_library("chrome") {
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.h",
|
||||
"//chrome/browser/ui/views/overlay/back_to_tab_image_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/back_to_tab_image_button.h",
|
||||
"//chrome/browser/ui/views/overlay/back_to_tab_label_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/close_image_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/close_image_button.h",
|
||||
"//chrome/browser/ui/views/overlay/constants.h",
|
||||
"//chrome/browser/ui/views/overlay/hang_up_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/hang_up_button.h",
|
||||
"//chrome/browser/ui/views/overlay/overlay_window_views.cc",
|
||||
"//chrome/browser/ui/views/overlay/overlay_window_views.h",
|
||||
"//chrome/browser/ui/views/overlay/playback_image_button.cc",
|
||||
@@ -261,6 +271,10 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/views/overlay/resize_handle_button.h",
|
||||
"//chrome/browser/ui/views/overlay/skip_ad_label_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/skip_ad_label_button.h",
|
||||
"//chrome/browser/ui/views/overlay/toggle_camera_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/toggle_camera_button.h",
|
||||
"//chrome/browser/ui/views/overlay/toggle_microphone_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/toggle_microphone_button.h",
|
||||
"//chrome/browser/ui/views/overlay/track_image_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/track_image_button.h",
|
||||
]
|
||||
|
||||
@@ -90,7 +90,7 @@ CertificateManagerModel::~CertificateManagerModel() = default;
|
||||
int CertificateManagerModel::ImportFromPKCS12(
|
||||
PK11SlotInfo* slot_info,
|
||||
const std::string& data,
|
||||
const base::string16& password,
|
||||
const std::u16string& password,
|
||||
bool is_extractable,
|
||||
net::ScopedCERTCertificateList* imported_certs) {
|
||||
return cert_db_->ImportFromPKCS12(slot_info, data, password, is_extractable,
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "base/callback.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "net/cert/nss_cert_database.h"
|
||||
|
||||
namespace content {
|
||||
@@ -46,7 +45,7 @@ class CertificateManagerModel {
|
||||
// Returns a net error code on failure.
|
||||
int ImportFromPKCS12(PK11SlotInfo* slot_info,
|
||||
const std::string& data,
|
||||
const base::string16& password,
|
||||
const std::u16string& password,
|
||||
bool is_extractable,
|
||||
net::ScopedCERTCertificateList* imported_certs);
|
||||
|
||||
|
||||
@@ -41,19 +41,18 @@ ipcMain.handle('bootstrap', (event) => {
|
||||
return isTrustedSender(event.sender) ? electronPath : null;
|
||||
});
|
||||
|
||||
async function createWindow () {
|
||||
async function createWindow (backgroundColor?: string) {
|
||||
await app.whenReady();
|
||||
|
||||
const options: Electron.BrowserWindowConstructorOptions = {
|
||||
width: 960,
|
||||
height: 620,
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#2f3241',
|
||||
backgroundColor,
|
||||
webPreferences: {
|
||||
preload: path.resolve(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
sandbox: true,
|
||||
enableRemoteModule: false
|
||||
sandbox: true
|
||||
},
|
||||
useContentSize: true,
|
||||
show: false
|
||||
@@ -96,7 +95,7 @@ export const loadURL = async (appUrl: string) => {
|
||||
};
|
||||
|
||||
export const loadFile = async (appPath: string) => {
|
||||
mainWindow = await createWindow();
|
||||
mainWindow = await createWindow(appPath === 'index.html' ? '#2f3241' : undefined);
|
||||
mainWindow.loadFile(appPath);
|
||||
mainWindow.focus();
|
||||
};
|
||||
|
||||
@@ -144,15 +144,14 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
### Modules for the Renderer Process (Web Page):
|
||||
|
||||
* [contextBridge](api/context-bridge.md)
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [ipcRenderer](api/ipc-renderer.md)
|
||||
* [remote](api/remote.md)
|
||||
* [webFrame](api/web-frame.md)
|
||||
|
||||
### Modules for Both Processes:
|
||||
|
||||
* [clipboard](api/clipboard.md)
|
||||
* [crashReporter](api/crash-reporter.md)
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [nativeImage](api/native-image.md)
|
||||
* [shell](api/shell.md)
|
||||
|
||||
|
||||
@@ -507,64 +507,6 @@ Returns:
|
||||
Emitted when `desktopCapturer.getSources()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will make it return empty sources.
|
||||
|
||||
### Event: 'remote-require' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.require()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Event: 'remote-get-global' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `globalName` String
|
||||
|
||||
Emitted when `remote.getGlobal()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the global from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Event: 'remote-get-builtin' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.getBuiltin()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Event: 'remote-get-current-window' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
Emitted when `remote.getCurrentWindow()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the object from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Event: 'remote-get-current-web-contents' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
Emitted when `remote.getCurrentWebContents()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the object from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
## Methods
|
||||
|
||||
The `app` object has the following methods:
|
||||
@@ -929,6 +871,10 @@ re-add a removed item to a custom category earlier than that will result in the
|
||||
entire custom category being omitted from the Jump List. The list of removed
|
||||
items can be obtained using `app.getJumpListSettings()`.
|
||||
|
||||
**Note:** The maximum length of a Jump List item's `description` property is
|
||||
260 characters. Beyond this limit, the item will not be added to the Jump
|
||||
List, nor will it be displayed.
|
||||
|
||||
Here's a very simple example of creating a custom Jump List:
|
||||
|
||||
```javascript
|
||||
@@ -1480,19 +1426,6 @@ This is the user agent that will be used when no user agent is set at the
|
||||
app has the same user agent. Set to a custom value as early as possible
|
||||
in your app's initialization to ensure that your overridden value is used.
|
||||
|
||||
### `app.allowRendererProcessReuse`
|
||||
|
||||
A `Boolean` which when `true` disables the overrides that Electron has in place
|
||||
to ensure renderer processes are restarted on every navigation. The current
|
||||
default value for this property is `true`.
|
||||
|
||||
The intention is for these overrides to become disabled by default and then at
|
||||
some point in the future this property will be removed. This property impacts
|
||||
which native modules you can use in the renderer process. For more information
|
||||
on the direction Electron is going with renderer process restarts and usage of
|
||||
native modules in the renderer process please check out this
|
||||
[Tracking Issue](https://github.com/electron/electron/issues/18397).
|
||||
|
||||
### `app.runningUnderRosettaTranslation` _macOS_ _Readonly_
|
||||
|
||||
A `Boolean` which when `true` indicates that the app is currently running
|
||||
|
||||
@@ -118,6 +118,9 @@ Returns `String` - The current update feed URL.
|
||||
Asks the server whether there is an update. You must call `setFeedURL` before
|
||||
using this API.
|
||||
|
||||
**Note:** If an update is available it will be downloaded automatically.
|
||||
Calling `autoUpdater.checkForUpdates()` twice will download the update two times.
|
||||
|
||||
### `autoUpdater.quitAndInstall()`
|
||||
|
||||
Restarts the app and installs the update after it has been downloaded. It
|
||||
|
||||
@@ -267,14 +267,12 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
be the absolute file path to the script.
|
||||
When node integration is turned off, the preload script can reintroduce
|
||||
Node global symbols back to the global scope. See example
|
||||
[here](process.md#event-loaded).
|
||||
[here](context-bridge.md#exposing-node-global-symbols).
|
||||
* `sandbox` Boolean (optional) - If set, this will sandbox the renderer
|
||||
associated with the window, making it compatible with the Chromium
|
||||
OS-level sandbox and disabling the Node.js engine. This is not the same as
|
||||
the `nodeIntegration` option and the APIs available to the preload script
|
||||
are more limited. Read more about the option [here](sandbox-option.md).
|
||||
* `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
|
||||
Default is `false`.
|
||||
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
|
||||
page. Instead of passing the Session object directly, you can also choose to
|
||||
use the `partition` option instead, which accepts a partition string. When
|
||||
@@ -286,13 +284,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
same `partition`. If there is no `persist:` prefix, the page will use an
|
||||
in-memory session. By assigning the same `partition`, multiple pages can share
|
||||
the same session. Default is the default session.
|
||||
* `affinity` String (optional) - When specified, web pages with the same
|
||||
`affinity` will run in the same renderer process. Note that due to reusing
|
||||
the renderer process, certain `webPreferences` options will also be shared
|
||||
between the web pages even when you specified different values for them,
|
||||
including but not limited to `preload`, `sandbox` and `nodeIntegration`.
|
||||
So it is suggested to use exact same `webPreferences` for web pages with
|
||||
the same `affinity`. _Deprecated_
|
||||
* `zoomFactor` Number (optional) - The default zoom factor of the page, `3.0` represents
|
||||
`300%`. Default is `1.0`.
|
||||
* `javascript` Boolean (optional) - Enables JavaScript support. Default is `true`.
|
||||
@@ -339,7 +330,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
more details.
|
||||
* `contextIsolation` Boolean (optional) - Whether to run Electron APIs and
|
||||
the specified `preload` script in a separate JavaScript context. Defaults
|
||||
to `false`. The context that the `preload` script runs in will only have
|
||||
to `true`. The context that the `preload` script runs in will only have
|
||||
access to its own dedicated `document` and `window` globals, as well as
|
||||
its own set of JavaScript builtins (`Array`, `Object`, `JSON`, etc.),
|
||||
which are all invisible to the loaded content. The Electron API will only
|
||||
@@ -350,13 +341,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
[Chrome Content Scripts][chrome-content-scripts]. You can access this
|
||||
context in the dev tools by selecting the 'Electron Isolated Context'
|
||||
entry in the combo box at the top of the Console tab.
|
||||
* `worldSafeExecuteJavaScript` Boolean (optional) - If true, values returned from `webFrame.executeJavaScript` will be sanitized to ensure JS values
|
||||
can't unsafely cross between worlds when using `contextIsolation`. The default
|
||||
is `false`. In Electron 12, the default will be changed to `true`. _Deprecated_
|
||||
* `nativeWindowOpen` Boolean (optional) - Whether to use native
|
||||
`window.open()`. Defaults to `false`. Child windows will always have node
|
||||
integration disabled unless `nodeIntegrationInSubFrames` is true. **Note:** This option is currently
|
||||
experimental.
|
||||
`window.open()`. Defaults to `true`. Child windows will always have node
|
||||
integration disabled unless `nodeIntegrationInSubFrames` is true.
|
||||
* `webviewTag` Boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag.md).
|
||||
Defaults to `false`. **Note:** The
|
||||
`preload` script configured for the `<webview>` will have node integration
|
||||
@@ -763,6 +750,10 @@ A `Boolean` property that determines whether the window is in simple (pre-Lion)
|
||||
|
||||
A `Boolean` property that determines whether the window is in fullscreen mode.
|
||||
|
||||
#### `win.focusable` _Windows_ _macOS_
|
||||
|
||||
A `Boolean` property that determines whether the window is focusable.
|
||||
|
||||
#### `win.visibleOnAllWorkspaces`
|
||||
|
||||
A `Boolean` property that determines whether the window is visible on all workspaces.
|
||||
@@ -1301,7 +1292,7 @@ can be be used to listen to changes to tablet mode.
|
||||
|
||||
#### `win.getMediaSourceId()`
|
||||
|
||||
Returns `String` - Window id in the format of DesktopCapturerSource's id. For example "window:1234:0".
|
||||
Returns `String` - Window id in the format of DesktopCapturerSource's id. For example "window:1324:0".
|
||||
|
||||
More precisely the format is `window:id:other_id` where `id` is `HWND` on
|
||||
Windows, `CGWindowID` (`uint64_t`) on macOS and `Window` (`unsigned long`) on
|
||||
@@ -1382,7 +1373,7 @@ Captures a snapshot of the page within `rect`. Omitting `rect` will capture the
|
||||
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer URL.
|
||||
* `userAgent` String (optional) - A user agent originating the request.
|
||||
* `extraHeaders` String (optional) - Extra headers separated by "\n"
|
||||
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
|
||||
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
|
||||
* `baseURLForDataURL` String (optional) - Base URL (with trailing path separator) for files to be loaded by the data URL. This is needed only if the specified `url` is a data URL and needs to load other files.
|
||||
|
||||
Returns `Promise<void>` - the promise will resolve when the page has finished loading
|
||||
@@ -1681,6 +1672,10 @@ Changes whether the window can be focused.
|
||||
|
||||
On macOS it does not remove the focus from the window.
|
||||
|
||||
#### `win.isFocusable()` _macOS_ _Windows_
|
||||
|
||||
Returns whether the window can be focused.
|
||||
|
||||
#### `win.setParentWindow(parent)`
|
||||
|
||||
* `parent` BrowserWindow | null
|
||||
|
||||
@@ -66,11 +66,6 @@ Forces the maximum disk space to be used by the disk cache, in bytes.
|
||||
Enables caller stack logging for the following APIs (filtering events):
|
||||
|
||||
* `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
|
||||
* `remote.require()` / `remote-require`
|
||||
* `remote.getGlobal()` / `remote-get-builtin`
|
||||
* `remote.getBuiltin()` / `remote-get-global`
|
||||
* `remote.getCurrentWindow()` / `remote-get-current-window`
|
||||
* `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
|
||||
|
||||
### --enable-logging
|
||||
|
||||
@@ -80,6 +75,12 @@ This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
|
||||
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
|
||||
environment variable to achieve the same effect.
|
||||
|
||||
## --force-fieldtrials=`trials`
|
||||
|
||||
Field trials to be forcefully enabled or disabled.
|
||||
|
||||
For example: `WebRTC-Audio-Red-For-Opus/Enabled/`
|
||||
|
||||
### --host-rules=`rules`
|
||||
|
||||
A comma-separated list of `rules` that control how hostnames are mapped.
|
||||
|
||||
@@ -33,7 +33,7 @@ page you load in your renderer executes code in this world.
|
||||
|
||||
### Isolated World
|
||||
|
||||
When `contextIsolation` is enabled in your `webPreferences`, your `preload` scripts run in an
|
||||
When `contextIsolation` is enabled in your `webPreferences` (this is the default behavior since Electron 12.0.0), your `preload` scripts run in an
|
||||
"Isolated World". You can read more about context isolation and what it affects in the
|
||||
[security](../tutorial/security.md#3-enable-context-isolation-for-remote-content) docs.
|
||||
|
||||
@@ -110,3 +110,22 @@ has been included below for completeness:
|
||||
| `Symbol` | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |
|
||||
|
||||
If the type you care about is not in the above table, it is probably not supported.
|
||||
|
||||
### Exposing Node Global Symbols
|
||||
|
||||
The `contextBridge` can be used by the preload script to give your renderer access to Node APIs.
|
||||
The table of supported types described above also applies to Node APIs that you expose through `contextBridge`.
|
||||
Please note that many Node APIs grant access to local system resources.
|
||||
Be very cautious about which globals and APIs you expose to untrusted remote content.
|
||||
|
||||
```javascript
|
||||
const { contextBridge } = require('electron')
|
||||
const crypto = require('crypto')
|
||||
contextBridge.exposeInMainWorld('nodeCrypto', {
|
||||
sha256sum (data) {
|
||||
const hash = crypto.createHash('sha256')
|
||||
hash.update(data)
|
||||
return hash.digest('hex')
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
@@ -77,7 +77,8 @@ The `crashReporter` module has the following methods:
|
||||
### `crashReporter.start(options)`
|
||||
|
||||
* `options` Object
|
||||
* `submitURL` String - URL that crash reports will be sent to as POST.
|
||||
* `submitURL` String (optional) - URL that crash reports will be sent to as
|
||||
POST. Required unless `uploadToServer` is `false`.
|
||||
* `productName` String (optional) - Defaults to `app.name`.
|
||||
* `companyName` String (optional) _Deprecated_ - Deprecated alias for
|
||||
`{ globalExtra: { _companyName: ... } }`.
|
||||
|
||||
@@ -233,10 +233,6 @@ expanding and collapsing the dialog.
|
||||
be selected by default when the message box opens.
|
||||
* `title` String (optional) - Title of the message box, some platforms will not show it.
|
||||
* `detail` String (optional) - Extra information of the message.
|
||||
* `checkboxLabel` String (optional) - If provided, the message box will
|
||||
include a checkbox with the given label.
|
||||
* `checkboxChecked` Boolean (optional) - Initial checked state of the
|
||||
checkbox. `false` by default.
|
||||
* `icon` ([NativeImage](native-image.md) | String) (optional)
|
||||
* `cancelId` Integer (optional) - The index of the button to be used to cancel the dialog, via
|
||||
the `Esc` key. By default this is assigned to the first button with "cancel" or "no" as the
|
||||
|
||||
@@ -83,8 +83,10 @@ win.show()
|
||||
blur effect to the content below the window (i.e. other applications open on
|
||||
the user's system).
|
||||
* The window will not be transparent when DevTools is opened.
|
||||
* On Windows operating systems, transparent windows will not work when DWM is
|
||||
* On Windows operating systems,
|
||||
* transparent windows will not work when DWM is
|
||||
disabled.
|
||||
* transparent windows can not be maximized using the Windows system menu or by double clicking the title bar. The reasoning behind this can be seen on [this pull request](https://github.com/electron/electron/pull/28207).
|
||||
* On Linux, users have to put `--enable-transparent-visuals --disable-gpu` in
|
||||
the command line to disable GPU and allow ARGB to make transparent window,
|
||||
this is caused by an upstream bug that [alpha channel doesn't work on some
|
||||
|
||||
@@ -8,11 +8,11 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
The `powerMonitor` module emits the following events:
|
||||
|
||||
### Event: 'suspend' _macOS_ _Windows_
|
||||
### Event: 'suspend'
|
||||
|
||||
Emitted when the system is suspending.
|
||||
|
||||
### Event: 'resume' _macOS_ _Windows_
|
||||
### Event: 'resume'
|
||||
|
||||
Emitted when system is resuming.
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ In sandboxed renderers the `process` object contains only a subset of the APIs:
|
||||
* `arch`
|
||||
* `platform`
|
||||
* `sandboxed`
|
||||
* `contextIsolated`
|
||||
* `type`
|
||||
* `version`
|
||||
* `versions`
|
||||
@@ -44,19 +45,6 @@ In sandboxed renderers the `process` object contains only a subset of the APIs:
|
||||
Emitted when Electron has loaded its internal initialization script and is
|
||||
beginning to load the web page or the main script.
|
||||
|
||||
It can be used by the preload script to add removed Node global symbols back to
|
||||
the global scope when node integration is turned off:
|
||||
|
||||
```javascript
|
||||
// preload.js
|
||||
const _setImmediate = setImmediate
|
||||
const _clearImmediate = clearImmediate
|
||||
process.once('loaded', () => {
|
||||
global.setImmediate = _setImmediate
|
||||
global.clearImmediate = _clearImmediate
|
||||
})
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### `process.defaultApp` _Readonly_
|
||||
@@ -94,6 +82,11 @@ A `String` representing the path to the resources directory.
|
||||
A `Boolean`. When the renderer process is sandboxed, this property is `true`,
|
||||
otherwise it is `undefined`.
|
||||
|
||||
### `process.contextIsolated` _Readonly_
|
||||
|
||||
A `Boolean` that indicates whether the current renderer context has `contextIsolation` enabled.
|
||||
It is `undefined` in the main process.
|
||||
|
||||
### `process.throwDeprecation`
|
||||
|
||||
A `Boolean` that controls whether or not deprecation warnings will be thrown as
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
# remote
|
||||
|
||||
> Use main process modules from the renderer process.
|
||||
|
||||
Process: [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
> ⚠️ WARNING ⚠️
|
||||
> The `remote` module is [deprecated](https://github.com/electron/electron/issues/21408).
|
||||
> Instead of `remote`, use [`ipcRenderer`](ipc-renderer.md) and
|
||||
> [`ipcMain`](ipc-main.md).
|
||||
>
|
||||
> Read more about why the `remote` module is deprecated [here](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
|
||||
>
|
||||
> If you still want to use `remote` despite the performance and security
|
||||
> concerns, see [@electron/remote](https://github.com/electron/remote).
|
||||
|
||||
The `remote` module provides a simple way to do inter-process communication
|
||||
(IPC) between the renderer process (web page) and the main process.
|
||||
|
||||
In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only
|
||||
available in the main process, not in the renderer process. In order to use them
|
||||
from the renderer process, the `ipc` module is necessary to send inter-process
|
||||
messages to the main process. With the `remote` module, you can invoke methods
|
||||
of the main process object without explicitly sending inter-process messages,
|
||||
similar to Java's [RMI][rmi]. An example of creating a browser window from a
|
||||
renderer process:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
**Note:** For the reverse (access the renderer process from the main process),
|
||||
you can use [webContents.executeJavaScript](web-contents.md#contentsexecutejavascriptcode-usergesture).
|
||||
|
||||
**Note:** The remote module can be disabled for security reasons in the following contexts:
|
||||
|
||||
* [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
|
||||
* [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
|
||||
|
||||
## Remote Objects
|
||||
|
||||
Each object (including functions) returned by the `remote` module represents an
|
||||
object in the main process (we call it a remote object or remote function).
|
||||
When you invoke methods of a remote object, call a remote function, or create
|
||||
a new object with the remote constructor (function), you are actually sending
|
||||
synchronous inter-process messages.
|
||||
|
||||
In the example above, both [`BrowserWindow`](browser-window.md) and `win` were remote objects and
|
||||
`new BrowserWindow` didn't create a `BrowserWindow` object in the renderer
|
||||
process. Instead, it created a `BrowserWindow` object in the main process and
|
||||
returned the corresponding remote object in the renderer process, namely the
|
||||
`win` object.
|
||||
|
||||
**Note:** Only [enumerable properties][enumerable-properties] which are present
|
||||
when the remote object is first referenced are accessible via remote.
|
||||
|
||||
**Note:** Arrays and Buffers are copied over IPC when accessed via the `remote`
|
||||
module. Modifying them in the renderer process does not modify them in the main
|
||||
process and vice versa.
|
||||
|
||||
## Lifetime of Remote Objects
|
||||
|
||||
Electron makes sure that as long as the remote object in the renderer process
|
||||
lives (in other words, has not been garbage collected), the corresponding object
|
||||
in the main process will not be released. When the remote object has been
|
||||
garbage collected, the corresponding object in the main process will be
|
||||
dereferenced.
|
||||
|
||||
If the remote object is leaked in the renderer process (e.g. stored in a map but
|
||||
never freed), the corresponding object in the main process will also be leaked,
|
||||
so you should be very careful not to leak remote objects.
|
||||
|
||||
Primary value types like strings and numbers, however, are sent by copy.
|
||||
|
||||
## Passing callbacks to the main process
|
||||
|
||||
Code in the main process can accept callbacks from the renderer - for instance
|
||||
the `remote` module - but you should be extremely careful when using this
|
||||
feature.
|
||||
|
||||
First, in order to avoid deadlocks, the callbacks passed to the main process
|
||||
are called asynchronously. You should not expect the main process to
|
||||
get the return value of the passed callbacks.
|
||||
|
||||
For instance you can't use a function from the renderer process in an
|
||||
`Array.map` called in the main process:
|
||||
|
||||
```javascript
|
||||
// main process mapNumbers.js
|
||||
exports.withRendererCallback = (mapper) => {
|
||||
return [1, 2, 3].map(mapper)
|
||||
}
|
||||
|
||||
exports.withLocalCallback = () => {
|
||||
return [1, 2, 3].map(x => x + 1)
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
// renderer process
|
||||
const mapNumbers = require('electron').remote.require('./mapNumbers')
|
||||
const withRendererCb = mapNumbers.withRendererCallback(x => x + 1)
|
||||
const withLocalCb = mapNumbers.withLocalCallback()
|
||||
|
||||
console.log(withRendererCb, withLocalCb)
|
||||
// [undefined, undefined, undefined], [2, 3, 4]
|
||||
```
|
||||
|
||||
As you can see, the renderer callback's synchronous return value was not as
|
||||
expected, and didn't match the return value of an identical callback that lives
|
||||
in the main process.
|
||||
|
||||
Second, the callbacks passed to the main process will persist until the
|
||||
main process garbage-collects them.
|
||||
|
||||
For example, the following code seems innocent at first glance. It installs a
|
||||
callback for the `close` event on a remote object:
|
||||
|
||||
```javascript
|
||||
require('electron').remote.getCurrentWindow().on('close', () => {
|
||||
// window was closed...
|
||||
})
|
||||
```
|
||||
|
||||
But remember the callback is referenced by the main process until you
|
||||
explicitly uninstall it. If you do not, each time you reload your window the
|
||||
callback will be installed again, leaking one callback for each restart.
|
||||
|
||||
To make things worse, since the context of previously installed callbacks has
|
||||
been released, exceptions will be raised in the main process when the `close`
|
||||
event is emitted.
|
||||
|
||||
To avoid this problem, ensure you clean up any references to renderer callbacks
|
||||
passed to the main process. This involves cleaning up event handlers, or
|
||||
ensuring the main process is explicitly told to dereference callbacks that came
|
||||
from a renderer process that is exiting.
|
||||
|
||||
## Accessing built-in modules in the main process
|
||||
|
||||
The built-in modules in the main process are added as getters in the `remote`
|
||||
module, so you can use them directly like the `electron` module.
|
||||
|
||||
```javascript
|
||||
const app = require('electron').remote.app
|
||||
console.log(app)
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `remote` module has the following methods:
|
||||
|
||||
### `remote.getCurrentWindow()`
|
||||
|
||||
Returns [`BrowserWindow`](browser-window.md) - The window to which this web page
|
||||
belongs.
|
||||
|
||||
**Note:** Do not use `removeAllListeners` on [`BrowserWindow`](browser-window.md).
|
||||
Use of this can remove all [`blur`](https://developer.mozilla.org/en-US/docs/Web/Events/blur)
|
||||
listeners, disable click events on touch bar buttons, and other unintended
|
||||
consequences.
|
||||
|
||||
### `remote.getCurrentWebContents()`
|
||||
|
||||
Returns [`WebContents`](web-contents.md) - The web contents of this web page.
|
||||
|
||||
### `remote.getGlobal(name)`
|
||||
|
||||
* `name` String
|
||||
|
||||
Returns `any` - The global variable of `name` (e.g. `global[name]`) in the main
|
||||
process.
|
||||
|
||||
## Properties
|
||||
|
||||
### `remote.require`
|
||||
|
||||
A `NodeJS.Require` function equivalent to `require(module)` in the main process.
|
||||
Modules specified by their relative path will resolve relative to the entrypoint
|
||||
of the main process.
|
||||
|
||||
e.g.
|
||||
|
||||
```sh
|
||||
project/
|
||||
├── main
|
||||
│ ├── foo.js
|
||||
│ └── index.js
|
||||
├── package.json
|
||||
└── renderer
|
||||
└── index.js
|
||||
```
|
||||
|
||||
```js
|
||||
// main process: main/index.js
|
||||
const { app } = require('electron')
|
||||
app.whenReady().then(() => { /* ... */ })
|
||||
```
|
||||
|
||||
```js
|
||||
// some relative module: main/foo.js
|
||||
module.exports = 'bar'
|
||||
```
|
||||
|
||||
```js
|
||||
// renderer process: renderer/index.js
|
||||
const foo = require('electron').remote.require('./foo') // bar
|
||||
```
|
||||
|
||||
### `remote.process` _Readonly_
|
||||
|
||||
A `NodeJS.Process` object. The `process` object in the main process. This is the same as
|
||||
`remote.getGlobal('process')` but is cached.
|
||||
|
||||
[rmi]: https://en.wikipedia.org/wiki/Java_remote_method_invocation
|
||||
[enumerable-properties]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
|
||||
@@ -197,9 +197,7 @@ be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissionch
|
||||
with the `serial` permission.
|
||||
|
||||
Because this is an experimental feature it is disabled by default. To enable this feature, you
|
||||
will need to use the `--enable-features=ElectronSerialChooser` command line switch. Additionally
|
||||
because this is an experimental Chromium feature you will need to set `enableBlinkFeatures: 'Serial'`
|
||||
on the `webPreferences` property when opening a BrowserWindow.
|
||||
will need to use the `--enable-features=ElectronSerialChooser` command line switch.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
@@ -210,10 +208,7 @@ app.commandLine.appendSwitch('enable-features', 'ElectronSerialChooser')
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
enableBlinkFeatures: 'Serial'
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
win.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
|
||||
event.preventDefault()
|
||||
|
||||
@@ -19,3 +19,7 @@
|
||||
property set then its `type` is assumed to be `tasks`. If the `name` property
|
||||
is set but the `type` property is omitted then the `type` is assumed to be
|
||||
`custom`.
|
||||
|
||||
**Note:** The maximum length of a Jump List item's `description` property is
|
||||
260 characters. Beyond this limit, the item will not be added to the Jump
|
||||
List, nor will it be displayed.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* `title` String (optional) - The text to be displayed for the item in the Jump List.
|
||||
Should only be set if `type` is `task`.
|
||||
* `description` String (optional) - Description of the task (displayed in a tooltip).
|
||||
Should only be set if `type` is `task`.
|
||||
Should only be set if `type` is `task`. Maximum length 260 characters.
|
||||
* `iconPath` String (optional) - The absolute path to an icon to be displayed in a
|
||||
Jump List, which can be an arbitrary resource file that contains an icon
|
||||
(e.g. `.ico`, `.exe`, `.dll`). You can usually specify `process.execPath` to
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# PostBody Object
|
||||
|
||||
* `data` Array<[PostData](./post-data.md)> - The post data to be sent to the
|
||||
* `data` ([UploadRawData](upload-raw-data.md) | [UploadFile](upload-file.md))[] - The post data to be sent to the
|
||||
new window.
|
||||
* `contentType` String - The `content-type` header used for the data. One of
|
||||
`application/x-www-form-urlencoded` or `multipart/form-data`. Corresponds to
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# PostData Object
|
||||
|
||||
* `type` String - One of the following:
|
||||
* `rawData` - The data is available as a `Buffer`, in the `rawData` field.
|
||||
* `file` - The object represents a file. The `filePath`, `offset`, `length`
|
||||
and `modificationTime` fields will be used to describe the file.
|
||||
* `blob` - The object represents a `Blob`. The `blobUUID` field will be used
|
||||
to describe the `Blob`.
|
||||
* `bytes` String (optional) - The raw bytes of the post data in a `Buffer`.
|
||||
Required for the `rawData` type.
|
||||
* `filePath` String (optional) - The path of the file being uploaded. Required
|
||||
for the `file` type.
|
||||
* `blobUUID` String (optional) - The `UUID` of the `Blob` being uploaded.
|
||||
Required for the `blob` type.
|
||||
* `offset` Integer (optional) - The offset from the beginning of the file being
|
||||
uploaded, in bytes. Only valid for `file` types.
|
||||
* `length` Integer (optional) - The length of the file being uploaded, in bytes.
|
||||
If set to `-1`, the whole file will be uploaded. Only valid for `file` types.
|
||||
* `modificationTime` Double (optional) - The modification time of the file
|
||||
represented by a double, which is the number of seconds since the `UNIX Epoch`
|
||||
(Jan 1, 1970). Only valid for `file` types.
|
||||
@@ -1,6 +1,6 @@
|
||||
# UploadFile Object
|
||||
|
||||
* `type` String - `file`.
|
||||
* `type` 'file' - `file`.
|
||||
* `filePath` String - Path of file to be uploaded.
|
||||
* `offset` Integer - Defaults to `0`.
|
||||
* `length` Integer - Number of bytes to read from `offset`.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# UploadRawData Object
|
||||
|
||||
* `type` String - `rawData`.
|
||||
* `type` 'rawData' - `rawData`.
|
||||
* `bytes` Buffer - Data to be uploaded.
|
||||
|
||||
12
docs/api/structures/user-default-types.md
Normal file
12
docs/api/structures/user-default-types.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# UserDefaultTypes Object
|
||||
|
||||
* `string` String
|
||||
* `boolean` Boolean
|
||||
* `integer` Number
|
||||
* `float` Number
|
||||
* `double` Number
|
||||
* `url` String
|
||||
* `array` Array\<unknown>
|
||||
* `dictionary` Record\<string, unknown>
|
||||
|
||||
This type is a helper alias, no object will never exist of this type.
|
||||
@@ -130,6 +130,8 @@ This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
* `userInfo` Record<String, unknown>
|
||||
* `object` String
|
||||
|
||||
Returns `Number` - The ID of this subscription
|
||||
|
||||
Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`.
|
||||
This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`.
|
||||
|
||||
@@ -157,13 +159,13 @@ Same as `unsubscribeNotification`, but removes the subscriber from `NSWorkspace.
|
||||
|
||||
Add the specified defaults to your application's `NSUserDefaults`.
|
||||
|
||||
### `systemPreferences.getUserDefault(key, type)` _macOS_
|
||||
### `systemPreferences.getUserDefault<Type extends keyof UserDefaultTypes>(key, type)` _macOS_
|
||||
|
||||
* `key` String
|
||||
* `type` String - Can be `string`, `boolean`, `integer`, `float`, `double`,
|
||||
* `type` Type - Can be `string`, `boolean`, `integer`, `float`, `double`,
|
||||
`url`, `array` or `dictionary`.
|
||||
|
||||
Returns `any` - The value of `key` in `NSUserDefaults`.
|
||||
Returns [`UserDefaultTypes[Type]`](structures/user-default-types.md) - The value of `key` in `NSUserDefaults`.
|
||||
|
||||
Some popular `key` and `type`s are:
|
||||
|
||||
|
||||
@@ -147,7 +147,8 @@ Returns:
|
||||
* `options` BrowserWindowConstructorOptions - The options which will be used for creating the new
|
||||
[`BrowserWindow`](browser-window.md).
|
||||
* `additionalFeatures` String[] - The non-standard features (features not handled
|
||||
by Chromium or Electron) given to `window.open()`.
|
||||
by Chromium or Electron) given to `window.open()`. Deprecated, and will now
|
||||
always be the empty array `[]`.
|
||||
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
|
||||
passed to the new window. May or may not result in the `Referer` header being
|
||||
sent, depending on the referrer policy.
|
||||
@@ -202,13 +203,11 @@ Returns:
|
||||
* `frameName` String - Name given to the created window in the
|
||||
`window.open()` call.
|
||||
* `options` BrowserWindowConstructorOptions - The options used to create the
|
||||
BrowserWindow. They are merged in increasing precedence: options inherited
|
||||
from the parent, parsed options from the `features` string from
|
||||
`window.open()`, and options given by
|
||||
BrowserWindow. They are merged in increasing precedence: parsed options
|
||||
from the `features` string from `window.open()`, security-related
|
||||
webPreferences inherited from the parent, and options given by
|
||||
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
|
||||
Unrecognized options are not filtered out.
|
||||
* `additionalFeatures` String[] - The non-standard features (features not
|
||||
handled Chromium or Electron) _Deprecated_
|
||||
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
|
||||
passed to the new window. May or may not result in the `Referer` header
|
||||
being sent, depending on the referrer policy.
|
||||
@@ -375,6 +374,8 @@ win.webContents.on('will-prevent-unload', (event) => {
|
||||
})
|
||||
```
|
||||
|
||||
**Note:** This will be emitted for `BrowserViews` but will _not_ be respected - this is because we have chosen not to tie the `BrowserView` lifecycle to its owning BrowserWindow should one exist per the [specification](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event).
|
||||
|
||||
#### Event: 'crashed' _Deprecated_
|
||||
|
||||
Returns:
|
||||
@@ -839,59 +840,6 @@ Returns:
|
||||
Emitted when `desktopCapturer.getSources()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will make it return empty sources.
|
||||
|
||||
#### Event: 'remote-require' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` IpcMainEvent
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.require()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'remote-get-global' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` IpcMainEvent
|
||||
* `globalName` String
|
||||
|
||||
Emitted when `remote.getGlobal()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the global from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'remote-get-builtin' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` IpcMainEvent
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.getBuiltin()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'remote-get-current-window' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` IpcMainEvent
|
||||
|
||||
Emitted when `remote.getCurrentWindow()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the object from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'remote-get-current-web-contents' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` IpcMainEvent
|
||||
|
||||
Emitted when `remote.getCurrentWebContents()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the object from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'preferred-size-changed'
|
||||
|
||||
Returns:
|
||||
@@ -914,7 +862,7 @@ in `webPreferences`.
|
||||
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer url.
|
||||
* `userAgent` String (optional) - A user agent originating the request.
|
||||
* `extraHeaders` String (optional) - Extra headers separated by "\n".
|
||||
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
|
||||
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
|
||||
* `baseURLForDataURL` String (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.
|
||||
|
||||
Returns `Promise<void>` - the promise will resolve when the page has finished loading
|
||||
@@ -1184,14 +1132,27 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
* `url` String - The _resolved_ version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
|
||||
* `frameName` String - Name of the window provided in `window.open()`
|
||||
* `features` String - Comma separated list of window features provided to `window.open()`.
|
||||
* `disposition` String - Can be `default`, `foreground-tab`, `background-tab`,
|
||||
`new-window`, `save-to-disk` or `other`.
|
||||
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
|
||||
passed to the new window. May or may not result in the `Referer` header being
|
||||
sent, depending on the referrer policy.
|
||||
* `postBody` [PostBody](structures/post-body.md) (optional) - The post data that
|
||||
will be sent to the new window, along with the appropriate headers that will
|
||||
be set. If no post data is to be sent, the value will be `null`. Only defined
|
||||
when the window is being created by a form that set `target=_blank`.
|
||||
|
||||
Returns `{action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new
|
||||
window. `allow` will allow the new window to be created. Specifying `overrideBrowserWindowOptions` allows customization of the created window.
|
||||
Returning an unrecognized value such as a null, undefined, or an object
|
||||
without a recognized 'action' value will result in a console error and have
|
||||
the same effect as returning `{action: 'deny'}`.
|
||||
|
||||
Called before creating a window when `window.open()` is called from the
|
||||
renderer. See [`window.open()`](window-open.md) for more details and how to use this in conjunction with `did-create-window`.
|
||||
Called before creating a window a new window is requested by the renderer, e.g.
|
||||
by `window.open()`, a link with `target="_blank"`, shift+clicking on a link, or
|
||||
submitting a form with `<form target="_blank">`. See
|
||||
[`window.open()`](window-open.md) for more details and how to use this in
|
||||
conjunction with `did-create-window`.
|
||||
|
||||
#### `contents.setAudioMuted(muted)`
|
||||
|
||||
@@ -1363,19 +1324,21 @@ Captures a snapshot of the page within `rect`. Omitting `rect` will capture the
|
||||
Returns `Boolean` - Whether this page is being captured. It returns true when the capturer count
|
||||
is large then 0.
|
||||
|
||||
#### `contents.incrementCapturerCount([size, stayHidden])`
|
||||
#### `contents.incrementCapturerCount([size, stayHidden, stayAwake])`
|
||||
|
||||
* `size` [Size](structures/size.md) (optional) - The preferred size for the capturer.
|
||||
* `stayHidden` Boolean (optional) - Keep the page hidden instead of visible.
|
||||
* `stayAwake` Boolean (optional) - Keep the system awake instead of allowing it to sleep.
|
||||
|
||||
Increase the capturer count by one. The page is considered visible when its browser window is
|
||||
hidden and the capturer count is non-zero. If you would like the page to stay hidden, you should ensure that `stayHidden` is set to true.
|
||||
|
||||
This also affects the Page Visibility API.
|
||||
|
||||
#### `contents.decrementCapturerCount([stayHidden])`
|
||||
#### `contents.decrementCapturerCount([stayHidden, stayAwake])`
|
||||
|
||||
* `stayHidden` Boolean (optional) - Keep the page in hidden state instead of visible.
|
||||
* `stayAwake` Boolean (optional) - Keep the system awake instead of allowing it to sleep.
|
||||
|
||||
Decrease the capturer count by one. The page will be set to hidden or occluded state when its
|
||||
browser window is hidden or occluded and the capturer count reaches zero. If you want to
|
||||
|
||||
@@ -182,3 +182,9 @@ This is not the same as the OS process ID; to read that use `frame.osProcessId`.
|
||||
An `Integer` representing the unique frame id in the current renderer process.
|
||||
Distinct `WebFrameMain` instances that refer to the same underlying frame will
|
||||
have the same `routingId`.
|
||||
|
||||
#### `frame.visibilityState` _Readonly_
|
||||
|
||||
A `string` representing the [visibility state](https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState) of the frame.
|
||||
|
||||
See also how the [Page Visibility API](browser-window.md#page-visibility) is affected by other Electron APIs.
|
||||
|
||||
@@ -130,15 +130,6 @@ inside the `webview`. All your preloads will load for every iframe, you can
|
||||
use `process.isMainFrame` to determine if you are in the main frame or not.
|
||||
This option is disabled by default in the guest page.
|
||||
|
||||
### `enableremotemodule`
|
||||
|
||||
```html
|
||||
<webview src="http://www.google.com/" enableremotemodule="false"></webview>
|
||||
```
|
||||
|
||||
A `Boolean`. When this attribute is `false` the guest page in `webview` will not have access
|
||||
to the [`remote`](remote.md) module. The remote module is unavailable by default.
|
||||
|
||||
### `plugins`
|
||||
|
||||
```html
|
||||
@@ -274,7 +265,7 @@ webview.addEventListener('dom-ready', () => {
|
||||
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer url.
|
||||
* `userAgent` String (optional) - A user agent originating the request.
|
||||
* `extraHeaders` String (optional) - Extra headers separated by "\n"
|
||||
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
|
||||
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
|
||||
* `baseURLForDataURL` String (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.
|
||||
|
||||
Returns `Promise<void>` - The promise will resolve when the page has finished loading
|
||||
|
||||
@@ -6,16 +6,15 @@ untrusted content within a renderer. Windows can be created from the renderer in
|
||||
* clicking on links or submitting forms adorned with `target=_blank`
|
||||
* JavaScript calling `window.open()`
|
||||
|
||||
In non-sandboxed renderers, or when `nativeWindowOpen` is false (the default), this results in the creation of a
|
||||
[`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper around
|
||||
`BrowserWindow`.
|
||||
For same-origin content, the new window is created within the same process,
|
||||
enabling the parent to access the child window directly. This can be very
|
||||
useful for app sub-windows that act as preference panels, or similar, as the
|
||||
parent can render to the sub-window directly, as if it were a `div` in the
|
||||
parent. This is the same behavior as in the browser.
|
||||
|
||||
However, when the `sandbox` (or directly, `nativeWindowOpen`) option is set, a
|
||||
`Window` instance is created, as you'd expect in the browser. For same-origin
|
||||
content, the new window is created within the same process, enabling the parent
|
||||
to access the child window directly. This can be very useful for app sub-windows that act
|
||||
as preference panels, or similar, as the parent can render to the sub-window
|
||||
directly, as if it were a `div` in the parent.
|
||||
When `nativeWindowOpen` is set to false, `window.open` instead results in the
|
||||
creation of a [`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper
|
||||
around `BrowserWindow`.
|
||||
|
||||
Electron pairs this native Chrome `Window` with a BrowserWindow under the hood.
|
||||
You can take advantage of all the customization available when creating a
|
||||
@@ -23,9 +22,8 @@ BrowserWindow in the main process by using `webContents.setWindowOpenHandler()`
|
||||
for renderer-created windows.
|
||||
|
||||
BrowserWindow constructor options are set by, in increasing precedence
|
||||
order: options inherited from the parent, parsed options
|
||||
from the `features` string from `window.open()`, security-related webPreferences
|
||||
inherited from the parent, and options given by
|
||||
order: parsed options from the `features` string from `window.open()`,
|
||||
security-related webPreferences inherited from the parent, and options given by
|
||||
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
|
||||
Note that `webContents.setWindowOpenHandler` has final say and full privilege
|
||||
because it is invoked in the main process.
|
||||
@@ -64,53 +62,23 @@ window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIn
|
||||
the parent window.
|
||||
* Non-standard features (that are not handled by Chromium or Electron) given in
|
||||
`features` will be passed to any registered `webContents`'s
|
||||
`did-create-window` event handler in the `additionalFeatures` argument.
|
||||
`did-create-window` event handler in the `options` argument.
|
||||
* `frameName` follows the specification of `windowName` located in the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters).
|
||||
|
||||
To customize or cancel the creation of the window, you can optionally set an
|
||||
override handler with `webContents.setWindowOpenHandler()` from the main
|
||||
process. Returning `false` cancels the window, while returning an object sets
|
||||
the `BrowserWindowConstructorOptions` used when creating the window. Note that
|
||||
this is more powerful than passing options through the feature string, as the
|
||||
renderer has more limited privileges in deciding security preferences than the
|
||||
main process.
|
||||
|
||||
### `BrowserWindowProxy` example
|
||||
|
||||
```javascript
|
||||
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow()
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url.startsWith('https://github.com/')) {
|
||||
return { action: 'allow' }
|
||||
}
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('did-create-window', (childWindow) => {
|
||||
// For example...
|
||||
childWindow.webContents('will-navigate', (e) => {
|
||||
e.preventDefault()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
// renderer.js
|
||||
const windowProxy = window.open('https://github.com/', null, 'minimizable=false')
|
||||
windowProxy.postMessage('hi', '*')
|
||||
```
|
||||
process. Returning `{ action: 'deny' }` cancels the window. Returning `{
|
||||
action: 'allow', overrideBrowserWindowOptions: { ... } }` will allow opening
|
||||
the window and setting the `BrowserWindowConstructorOptions` to be used when
|
||||
creating the window. Note that this is more powerful than passing options
|
||||
through the feature string, as the renderer has more limited privileges in
|
||||
deciding security preferences than the main process.
|
||||
|
||||
### Native `Window` example
|
||||
|
||||
```javascript
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nativeWindowOpen: true
|
||||
}
|
||||
})
|
||||
const mainWindow = new BrowserWindow()
|
||||
|
||||
// In this example, only windows with the `about:blank` url will be created.
|
||||
// All other urls will be blocked.
|
||||
@@ -134,3 +102,33 @@ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
const childWindow = window.open('', 'modal')
|
||||
childWindow.document.write('<h1>Hello</h1>')
|
||||
```
|
||||
|
||||
### `BrowserWindowProxy` example
|
||||
|
||||
```javascript
|
||||
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: { nativeWindowOpen: false }
|
||||
})
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url.startsWith('https://github.com/')) {
|
||||
return { action: 'allow' }
|
||||
}
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('did-create-window', (childWindow) => {
|
||||
// For example...
|
||||
childWindow.webContents.on('will-navigate', (e) => {
|
||||
e.preventDefault()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
// renderer.js
|
||||
const windowProxy = window.open('https://github.com/', null, 'minimizable=false')
|
||||
windowProxy.postMessage('hi', '*')
|
||||
```
|
||||
|
||||
@@ -14,7 +14,22 @@ This document uses the following convention to categorize breaking changes:
|
||||
|
||||
## Planned Breaking API Changes (14.0)
|
||||
|
||||
### API Changed: `window.(open)`
|
||||
### Removed: `app.allowRendererProcessReuse`
|
||||
|
||||
The `app.allowRendererProcessReuse` property will be removed as part of our plan to
|
||||
more closely align with Chromium's process model for security, performance and maintainability.
|
||||
|
||||
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||
|
||||
### Removed: Browser Window Affinity
|
||||
|
||||
The `affinity` option when constructing a new `BrowserWindow` will be removed
|
||||
as part of our plan to more closely align with Chromium's process model for security,
|
||||
performance and maintainability.
|
||||
|
||||
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||
|
||||
### API Changed: `window.open()`
|
||||
|
||||
The optional parameter `frameName` will no longer set the title of the window. This now follows the specification described by the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters) under the corresponding parameter `windowName`.
|
||||
|
||||
@@ -28,6 +43,63 @@ ensure your code works with this property enabled. It has been enabled by defau
|
||||
|
||||
You will be affected by this change if you use either `webFrame.executeJavaScript` or `webFrame.executeJavaScriptInIsolatedWorld`. You will need to ensure that values returned by either of those methods are supported by the [Context Bridge API](api/context-bridge.md#parameter--error--return-type-support) as these methods use the same value passing semantics.
|
||||
|
||||
### Default Changed: `nativeWindowOpen` defaults to `true`
|
||||
|
||||
Prior to Electron 14, `window.open` was by default shimmed to use
|
||||
`BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work
|
||||
to open synchronously scriptable child windows, among other incompatibilities.
|
||||
`nativeWindowOpen` is no longer experimental, and is now the default.
|
||||
|
||||
See the documentation for [window.open in Electron](api/window-open.md)
|
||||
for more details.
|
||||
|
||||
### Removed: BrowserWindowConstructorOptions inheriting from parent windows
|
||||
|
||||
Prior to Electron 14, windows opened with `window.open` would inherit
|
||||
BrowserWindow constructor options such as `transparent` and `resizable` from
|
||||
their parent window. Beginning with Electron 14, this behavior is removed, and
|
||||
windows will not inherit any BrowserWindow constructor options from their
|
||||
parents.
|
||||
|
||||
Instead, explicitly set options for the new window with `setWindowOpenHandler`:
|
||||
|
||||
```js
|
||||
webContents.setWindowOpenHandler((details) => {
|
||||
return {
|
||||
action: 'allow',
|
||||
overrideBrowserWindowOptions: {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Removed: `additionalFeatures`
|
||||
|
||||
The deprecated `additionalFeatures` property in the `new-window` and
|
||||
`did-create-window` events of WebContents has been removed. Since `new-window`
|
||||
uses positional arguments, the argument is still present, but will always be
|
||||
the empty array `[]`. (Though note, the `new-window` event itself is
|
||||
deprecated, and is replaced by `setWindowOpenHandler`.) Bare keys in window
|
||||
features will now present as keys with the value `true` in the options object.
|
||||
|
||||
```js
|
||||
// Removed in Electron 14
|
||||
// Triggered by window.open('...', '', 'my-key')
|
||||
webContents.on('did-create-window', (window, details) => {
|
||||
if (details.additionalFeatures.includes('my-key')) {
|
||||
// ...
|
||||
}
|
||||
})
|
||||
|
||||
// Replace with
|
||||
webContents.on('did-create-window', (window, details) => {
|
||||
if (details.options['my-key']) {
|
||||
// ...
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (13.0)
|
||||
|
||||
### API Changed: `session.setPermissionCheckHandler(handler)`
|
||||
@@ -136,6 +208,22 @@ systemPreferences.isHighContrastColorScheme()
|
||||
nativeTheme.shouldUseHighContrastColors
|
||||
```
|
||||
|
||||
### Deprecated: WebContents `new-window` event
|
||||
|
||||
The `new-window` event of WebContents has been deprecated. It is replaced by [`webContents.setWindowOpenHandler()`](api/web-contents.md#contentssetwindowopenhandlerhandler).
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 13
|
||||
webContents.on('new-window', (event) => {
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
// Replace with
|
||||
webContents.setWindowOpenHandler((details) => {
|
||||
return { action: 'deny' }
|
||||
})
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (12.0)
|
||||
|
||||
### Removed: Pepper Flash support
|
||||
@@ -160,6 +248,9 @@ the previous behavior, `contextIsolation: false` must be specified in WebPrefere
|
||||
|
||||
We [recommend having contextIsolation enabled](https://github.com/electron/electron/blob/master/docs/tutorial/security.md#3-enable-context-isolation-for-remote-content) for the security of your application.
|
||||
|
||||
Another implication is that `require()` cannot be used in the renderer process unless
|
||||
`nodeIntegration` is `true` and `contextIsolation` is `false`.
|
||||
|
||||
For more details see: https://github.com/electron/electron/issues/23506
|
||||
|
||||
### Removed: `crashReporter.getCrashesDirectory()`
|
||||
@@ -295,14 +386,6 @@ Setting `{ compress: false }` in `crashReporter.start` is deprecated. Nearly
|
||||
all crash ingestion servers support gzip compression. This option will be
|
||||
removed in a future version of Electron.
|
||||
|
||||
### Removed: Browser Window Affinity
|
||||
|
||||
The `affinity` option when constructing a new `BrowserWindow` will be removed
|
||||
as part of our plan to more closely align with Chromium's process model for security,
|
||||
performance and maintainability.
|
||||
|
||||
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||
|
||||
### Default Changed: `enableRemoteModule` defaults to `false`
|
||||
|
||||
In Electron 9, using the remote module without explicitly enabling it via the
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Build Instructions
|
||||
|
||||
Follow the guidelines below for building Electron.
|
||||
Follow the guidelines below for building **Electron itself**, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
|
||||
## Platform prerequisites
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Build Instructions (Linux)
|
||||
|
||||
Follow the guidelines below for building Electron on Linux.
|
||||
Follow the guidelines below for building **Electron itself** on Linux, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Build Instructions (macOS)
|
||||
|
||||
Follow the guidelines below for building Electron on macOS.
|
||||
Follow the guidelines below for building **Electron itself** on macOS, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Build Instructions (Windows)
|
||||
|
||||
Follow the guidelines below for building Electron on Windows.
|
||||
Follow the guidelines below for building **Electron itself** on Windows, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@ contributing, and more. Please use the issue tracker for bugs only!
|
||||
To submit a bug report:
|
||||
|
||||
When opening a new issue in the [`electron/electron` issue tracker](https://github.com/electron/electron/issues/new/choose), users
|
||||
will be presented with [a template](https://github.com/electron/electron/blob/master/.github/ISSUE_TEMPLATE/Bug_report.md)
|
||||
that should be filled in.
|
||||
will be presented with a template that should be filled in.
|
||||
|
||||
If you believe that you have found a bug in Electron, please fill out the template
|
||||
to the best of your ability.
|
||||
|
||||
@@ -190,7 +190,6 @@ it may be worth your time to shop around. Popular resellers include:
|
||||
|
||||
* [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
|
||||
* [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
* [GoDaddy](https://au.godaddy.com/web-security/code-signing-certificate)
|
||||
* Amongst others, please shop around to find one that suits your needs, Google
|
||||
is your friend 😄
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ The `index.html` page looks as follows:
|
||||
|
||||
#### Define a preload script
|
||||
|
||||
Your preload script acts as a bridge between Node.js and your web page. It allows you to expose specific APIs and behaviors to your web page rather than insecurely exposing the entire Node.js API. In this example we will use the preload script to read version information from the `process` object and update the web page with that info.
|
||||
Your preload script (in our case, the `preload.js` file) acts as a bridge between Node.js and your web page. It allows you to expose specific APIs and behaviors to your web page rather than insecurely exposing the entire Node.js API. In this example we will use the preload script to read version information from the `process` object and update the web page with that info.
|
||||
|
||||
```javascript fiddle='docs/fiddles/quick-start'
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
@@ -196,7 +196,8 @@ The simplest and the fastest way to distribute your newly created app is using
|
||||
1. Import Electron Forge to your app folder:
|
||||
|
||||
```sh
|
||||
npx @electron-forge/cli import
|
||||
npm install --save-dev @electron-forge/cli
|
||||
npx electron-forge import
|
||||
|
||||
✔ Checking your system
|
||||
✔ Initializing Git Repository
|
||||
|
||||
@@ -44,7 +44,7 @@ Chromium shared library and Node.js. Vulnerabilities affecting these components
|
||||
may impact the security of your application. By updating Electron to the latest
|
||||
version, you ensure that critical vulnerabilities (such as *nodeIntegration bypasses*)
|
||||
are already patched and cannot be exploited in your application. For more information,
|
||||
see "[Use a current version of Electron](#17-use-a-current-version-of-electron)".
|
||||
see "[Use a current version of Electron](#15-use-a-current-version-of-electron)".
|
||||
|
||||
* **Evaluate your dependencies.** While NPM provides half a million reusable packages,
|
||||
it is your responsibility to choose trusted 3rd-party libraries. If you use outdated
|
||||
@@ -99,9 +99,7 @@ You should at least follow these steps to improve the security of your applicati
|
||||
12. [Disable or limit navigation](#12-disable-or-limit-navigation)
|
||||
13. [Disable or limit creation of new windows](#13-disable-or-limit-creation-of-new-windows)
|
||||
14. [Do not use `openExternal` with untrusted content](#14-do-not-use-openexternal-with-untrusted-content)
|
||||
15. [Disable the `remote` module](#15-disable-the-remote-module)
|
||||
16. [Filter the `remote` module](#16-filter-the-remote-module)
|
||||
17. [Use a current version of Electron](#17-use-a-current-version-of-electron)
|
||||
15. [Use a current version of Electron](#15-use-a-current-version-of-electron)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
@@ -665,134 +663,7 @@ const { shell } = require('electron')
|
||||
shell.openExternal('https://example.com/index.html')
|
||||
```
|
||||
|
||||
## 15) Disable the `remote` module
|
||||
|
||||
The `remote` module provides a way for the renderer processes to
|
||||
access APIs normally only available in the main process. Using it, a
|
||||
renderer can invoke methods of a main process object without explicitly sending
|
||||
inter-process messages. If your desktop application does not run untrusted
|
||||
content, this can be a useful way to have your renderer processes access and
|
||||
work with modules that are only available to the main process, such as
|
||||
GUI-related modules (dialogs, menus, etc.).
|
||||
|
||||
However, if your app can run untrusted content and even if you
|
||||
[sandbox][sandbox] your renderer processes accordingly, the `remote` module
|
||||
makes it easy for malicious code to escape the sandbox and have access to
|
||||
system resources via the higher privileges of the main process. Therefore,
|
||||
it should be disabled in such circumstances.
|
||||
|
||||
### Why?
|
||||
|
||||
`remote` uses an internal IPC channel to communicate with the main process.
|
||||
"Prototype pollution" attacks can grant malicious code access to the internal
|
||||
IPC channel, which can then be used to escape the sandbox by mimicking `remote`
|
||||
IPC messages and getting access to main process modules running with higher
|
||||
privileges.
|
||||
|
||||
Additionally, it's possible for preload scripts to accidentally leak modules to a
|
||||
sandboxed renderer. Leaking `remote` arms malicious code with a multitude
|
||||
of main process modules with which to perform an attack.
|
||||
|
||||
Disabling the `remote` module eliminates these attack vectors. Enabling
|
||||
context isolation also prevents the "prototype pollution" attacks from
|
||||
succeeding.
|
||||
|
||||
### How?
|
||||
|
||||
```js
|
||||
// Bad if the renderer can run untrusted content
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
enableRemoteModule: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
enableRemoteModule: false
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- Bad if the renderer can run untrusted content -->
|
||||
<webview enableremotemodule="true" src="page.html"></webview>
|
||||
|
||||
<!-- Good -->
|
||||
<webview enableremotemodule="false" src="page.html"></webview>
|
||||
```
|
||||
|
||||
> **Note:** The default value of `enableRemoteModule` is `false` starting
|
||||
> from Electron 10. For prior versions, you need to explicitly disable
|
||||
> the `remote` module by the means above.
|
||||
|
||||
## 16) Filter the `remote` module
|
||||
|
||||
If you cannot disable the `remote` module, you should filter the globals,
|
||||
Node, and Electron modules (so-called built-ins) accessible via `remote`
|
||||
that your application does not require. This can be done by blocking
|
||||
certain modules entirely and by replacing others with proxies that
|
||||
expose only the functionality that your app needs.
|
||||
|
||||
### Why?
|
||||
|
||||
Due to the system access privileges of the main process, functionality
|
||||
provided by the main process modules may be dangerous in the hands of
|
||||
malicious code running in a compromised renderer process. By limiting
|
||||
the set of accessible modules to the minimum that your app needs and
|
||||
filtering out the others, you reduce the toolset that malicious code
|
||||
can use to attack the system.
|
||||
|
||||
Note that the safest option is to
|
||||
[fully disable the remote module](#15-disable-the-remote-module). If
|
||||
you choose to filter access rather than completely disable the module,
|
||||
you must be very careful to ensure that no escalation of privilege is
|
||||
possible through the modules you allow past the filter.
|
||||
|
||||
### How?
|
||||
|
||||
```js
|
||||
const readOnlyFsProxy = require(/* ... */) // exposes only file read functionality
|
||||
|
||||
const allowedModules = new Set(['crypto'])
|
||||
const proxiedModules = new Map([['fs', readOnlyFsProxy]])
|
||||
const allowedElectronModules = new Set(['shell'])
|
||||
const allowedGlobals = new Set()
|
||||
|
||||
app.on('remote-require', (event, webContents, moduleName) => {
|
||||
if (proxiedModules.has(moduleName)) {
|
||||
event.returnValue = proxiedModules.get(moduleName)
|
||||
}
|
||||
if (!allowedModules.has(moduleName)) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('remote-get-builtin', (event, webContents, moduleName) => {
|
||||
if (!allowedElectronModules.has(moduleName)) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('remote-get-global', (event, webContents, globalName) => {
|
||||
if (!allowedGlobals.has(globalName)) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('remote-get-current-window', (event, webContents) => {
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
app.on('remote-get-current-web-contents', (event, webContents) => {
|
||||
event.preventDefault()
|
||||
})
|
||||
```
|
||||
|
||||
## 17) Use a current version of Electron
|
||||
## 15) Use a current version of Electron
|
||||
|
||||
You should strive for always using the latest available version of Electron.
|
||||
Whenever a new major version is released, you should attempt to update your
|
||||
|
||||
@@ -94,7 +94,7 @@ Following platforms are supported by Electron:
|
||||
### macOS
|
||||
|
||||
Only 64bit binaries are provided for macOS, and the minimum macOS version
|
||||
supported is macOS 10.10 (Yosemite).
|
||||
supported is macOS 10.11 (El Capitan).
|
||||
|
||||
Native support for Apple Silicon (`arm64`) devices was added in Electron 11.0.0.
|
||||
|
||||
|
||||
@@ -86,12 +86,12 @@ const driver = new webdriver.Builder()
|
||||
// The "9515" is the port opened by chrome driver.
|
||||
.usingServer('http://localhost:9515')
|
||||
.withCapabilities({
|
||||
chromeOptions: {
|
||||
'goog:chromeOptions': {
|
||||
// Here is the path to your Electron binary.
|
||||
binary: '/Path-to-Your-App.app/Contents/MacOS/Electron'
|
||||
}
|
||||
})
|
||||
.forBrowser('electron')
|
||||
.forBrowser('chrome') // note: use .forBrowser('electron') for selenium-webdriver <= 3.6.0
|
||||
.build()
|
||||
|
||||
driver.get('http://www.google.com')
|
||||
|
||||
@@ -73,7 +73,7 @@ template("electron_extra_paks") {
|
||||
"//components/resources",
|
||||
"//content:content_resources",
|
||||
"//content:dev_ui_content_resources",
|
||||
"//content/browser/resources/media:media_internals_resources",
|
||||
"//content/browser/resources/media:resources",
|
||||
"//content/browser/tracing:resources",
|
||||
"//content/browser/webrtc/resources",
|
||||
"//electron:resources",
|
||||
|
||||
@@ -51,6 +51,21 @@
|
||||
<message name="IDS_PICTURE_IN_PICTURE_SKIP_AD_CONTROL_TEXT" desc="Text label of the skip ad control button. The button appears when the user hovers over the Picture-in-Picture window.">
|
||||
Skip Ad
|
||||
</message>
|
||||
<message name="IDS_PICTURE_IN_PICTURE_MUTE_MICROPHONE_TEXT" desc="Text label of the mute microphone control button. The button appears when the user hovers over the Picture-in-Picture window.">
|
||||
Mute microphone
|
||||
</message>
|
||||
<message name="IDS_PICTURE_IN_PICTURE_UNMUTE_MICROPHONE_TEXT" desc="Text label of the unmute microphone control button. The button appears when the user hovers over the Picture-in-Picture window.">
|
||||
Unmute microphone
|
||||
</message>
|
||||
<message name="IDS_PICTURE_IN_PICTURE_TURN_ON_CAMERA_TEXT" desc="Text label of the turn on camera control button. The button appears when the user hovers over the Picture-in-Picture window.">
|
||||
Turn on camera
|
||||
</message>
|
||||
<message name="IDS_PICTURE_IN_PICTURE_TURN_OFF_CAMERA_TEXT" desc="Text label of the turn off camera control button. The button appears when the user hovers over the Picture-in-Picture window.">
|
||||
Turn off camera
|
||||
</message>
|
||||
<message name="IDS_PICTURE_IN_PICTURE_HANG_UP_TEXT" desc="Text label of the hang up control button. The button appears when the user hovers over the Picture-in-Picture window.">
|
||||
Hang up
|
||||
</message>
|
||||
<message name="IDS_PICTURE_IN_PICTURE_CLOSE_CONTROL_TEXT" desc="Text label of the close control button. The button appears when the user hovers over the Picture-in-Picture window.">
|
||||
Close
|
||||
</message>
|
||||
|
||||
@@ -43,7 +43,6 @@ auto_filenames = {
|
||||
"docs/api/power-save-blocker.md",
|
||||
"docs/api/process.md",
|
||||
"docs/api/protocol.md",
|
||||
"docs/api/remote.md",
|
||||
"docs/api/sandbox-option.md",
|
||||
"docs/api/screen.md",
|
||||
"docs/api/service-workers.md",
|
||||
@@ -105,7 +104,6 @@ auto_filenames = {
|
||||
"docs/api/structures/notification-response.md",
|
||||
"docs/api/structures/point.md",
|
||||
"docs/api/structures/post-body.md",
|
||||
"docs/api/structures/post-data.md",
|
||||
"docs/api/structures/printer-info.md",
|
||||
"docs/api/structures/process-memory-info.md",
|
||||
"docs/api/structures/process-metric.md",
|
||||
@@ -131,33 +129,26 @@ auto_filenames = {
|
||||
"docs/api/structures/upload-data.md",
|
||||
"docs/api/structures/upload-file.md",
|
||||
"docs/api/structures/upload-raw-data.md",
|
||||
"docs/api/structures/user-default-types.md",
|
||||
"docs/api/structures/web-source.md",
|
||||
]
|
||||
|
||||
sandbox_bundle_deps = [
|
||||
"lib/browser/api/module-names.ts",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/remote/ipc-messages.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-events.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
"lib/renderer/api/desktop-capturer.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/remote.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/remote/callbacks-registry.ts",
|
||||
"lib/renderer/security-warnings.ts",
|
||||
"lib/renderer/web-frame-init.ts",
|
||||
"lib/renderer/web-view/guest-view-internal.ts",
|
||||
@@ -242,8 +233,6 @@ auto_filenames = {
|
||||
"lib/browser/ipc-main-internal.ts",
|
||||
"lib/browser/message-port-main.ts",
|
||||
"lib/browser/navigation-controller.ts",
|
||||
"lib/browser/remote/objects-registry.ts",
|
||||
"lib/browser/remote/server.ts",
|
||||
"lib/browser/rpc-server.ts",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
@@ -253,7 +242,6 @@ auto_filenames = {
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/parse-features-string.ts",
|
||||
"lib/common/remote/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-events.ts",
|
||||
@@ -269,7 +257,6 @@ auto_filenames = {
|
||||
]
|
||||
|
||||
renderer_bundle_deps = [
|
||||
"lib/browser/api/module-names.ts",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
@@ -277,12 +264,10 @@ auto_filenames = {
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/remote/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-events.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/common/webpack-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
@@ -291,13 +276,11 @@ auto_filenames = {
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/remote.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/init.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/remote/callbacks-registry.ts",
|
||||
"lib/renderer/security-warnings.ts",
|
||||
"lib/renderer/web-frame-init.ts",
|
||||
"lib/renderer/web-view/guest-view-internal.ts",
|
||||
@@ -315,7 +298,6 @@ auto_filenames = {
|
||||
]
|
||||
|
||||
worker_bundle_deps = [
|
||||
"lib/browser/api/module-names.ts",
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
@@ -323,10 +305,8 @@ auto_filenames = {
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/remote/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/common/webpack-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
@@ -335,11 +315,9 @@ auto_filenames = {
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/remote.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/remote/callbacks-registry.ts",
|
||||
"lib/worker/init.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
|
||||
@@ -404,6 +404,8 @@ filenames = {
|
||||
"shell/browser/native_window_observer.h",
|
||||
"shell/browser/net/asar/asar_url_loader.cc",
|
||||
"shell/browser/net/asar/asar_url_loader.h",
|
||||
"shell/browser/net/asar/asar_url_loader_factory.cc",
|
||||
"shell/browser/net/asar/asar_url_loader_factory.h",
|
||||
"shell/browser/net/cert_verifier_client.cc",
|
||||
"shell/browser/net/cert_verifier_client.h",
|
||||
"shell/browser/net/electron_url_loader_factory.cc",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import { deprecate, Menu } from 'electron/main';
|
||||
import { Menu } from 'electron/main';
|
||||
|
||||
const bindings = process._linkedBinding('electron_browser_app');
|
||||
const commandLine = process._linkedBinding('electron_common_command_line');
|
||||
@@ -129,7 +129,3 @@ for (const name of events) {
|
||||
webContents.emit(name, event, ...args);
|
||||
});
|
||||
}
|
||||
|
||||
// Deprecate allowRendererProcessReuse but only if they set it to false, no need to log if
|
||||
// they are setting it to true
|
||||
deprecate.removeProperty({ __proto__: app } as any, 'allowRendererProcessReuse', [false]);
|
||||
|
||||
@@ -37,6 +37,11 @@ Object.defineProperty(BaseWindow.prototype, 'simpleFullScreen', {
|
||||
set: function (simple) { this.setSimpleFullScreen(simple); }
|
||||
});
|
||||
|
||||
Object.defineProperty(BaseWindow.prototype, 'focusable', {
|
||||
get: function () { return this.isFocusable(); },
|
||||
set: function (focusable) { this.setFocusable(focusable); }
|
||||
});
|
||||
|
||||
Object.defineProperty(BaseWindow.prototype, 'kiosk', {
|
||||
get: function () { return this.isKiosk(); },
|
||||
set: function (kiosk) { this.setKiosk(kiosk); }
|
||||
|
||||
@@ -10,15 +10,15 @@ class CrashReporter {
|
||||
extra = {},
|
||||
globalExtra = {},
|
||||
ignoreSystemCrashHandler = false,
|
||||
submitURL,
|
||||
submitURL = '',
|
||||
uploadToServer = true,
|
||||
rateLimit = false,
|
||||
compress = true
|
||||
} = options || {};
|
||||
|
||||
if (submitURL == null) throw new Error('submitURL is a required option to crashReporter.start');
|
||||
if (uploadToServer && !submitURL) throw new Error('submitURL must be specified when uploadToServer is true');
|
||||
|
||||
if (!compress) {
|
||||
if (!compress && uploadToServer) {
|
||||
deprecate.log('Sending uncompressed crash reports is deprecated and will be removed in a future version of Electron. Set { compress: true } to opt-in to the new behavior. Crash reports will be uploaded gzipped, which most crash reporting servers support.');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
// TODO: Figure out a way to not duplicate this information between here and module-list
|
||||
// It is currently duplicated as module-list "require"s all the browser API file and the
|
||||
// remote module in the renderer process depends on that file. As a result webpack
|
||||
// includes all the browser API files in the renderer process as well and we want to avoid that
|
||||
|
||||
// Browser side modules, please sort alphabetically.
|
||||
export const browserModuleNames = [
|
||||
'app',
|
||||
'autoUpdater',
|
||||
'BaseWindow',
|
||||
'BrowserView',
|
||||
'BrowserWindow',
|
||||
'contentTracing',
|
||||
'crashReporter',
|
||||
'dialog',
|
||||
'globalShortcut',
|
||||
'ipcMain',
|
||||
'inAppPurchase',
|
||||
'Menu',
|
||||
'MenuItem',
|
||||
'nativeImage',
|
||||
'nativeTheme',
|
||||
'net',
|
||||
'netLog',
|
||||
'MessageChannelMain',
|
||||
'Notification',
|
||||
'powerMonitor',
|
||||
'powerSaveBlocker',
|
||||
'protocol',
|
||||
'screen',
|
||||
'session',
|
||||
'ShareMenu',
|
||||
'systemPreferences',
|
||||
'TouchBar',
|
||||
'Tray',
|
||||
'View',
|
||||
'webContents',
|
||||
'WebContentsView',
|
||||
'webFrameMain'
|
||||
];
|
||||
|
||||
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
browserModuleNames.push('desktopCapturer');
|
||||
}
|
||||
|
||||
if (BUILDFLAG(ENABLE_VIEWS_API)) {
|
||||
browserModuleNames.push(
|
||||
'ImageView'
|
||||
);
|
||||
}
|
||||
@@ -188,6 +188,11 @@ class ChunkedBodyStream extends Writable {
|
||||
this._downstream = pipe;
|
||||
if (this._pendingChunk) {
|
||||
const doneWriting = (maybeError: Error | void) => {
|
||||
// If the underlying request has been aborted, we honeslty don't care about the error
|
||||
// all work should cease as soon as we abort anyway, this error is probably a
|
||||
// "mojo pipe disconnected" error (code=9)
|
||||
if (this._clientRequest._aborted) return;
|
||||
|
||||
const cb = this._pendingCallback!;
|
||||
delete this._pendingCallback;
|
||||
delete this._pendingChunk;
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/m
|
||||
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import { openGuestWindow, makeWebPreferences } from '@electron/internal/browser/guest-window-manager';
|
||||
import { openGuestWindow, makeWebPreferences, parseContentTypeFormat } from '@electron/internal/browser/guest-window-manager';
|
||||
import { NavigationController } from '@electron/internal/browser/navigation-controller';
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
|
||||
@@ -94,6 +94,7 @@ const defaultPrintingSetting = {
|
||||
pagesPerSheet: 1,
|
||||
isFirstRequest: false,
|
||||
previewUIID: 0,
|
||||
// True, if the document source is modifiable. e.g. HTML and not PDF.
|
||||
previewModifiable: true,
|
||||
printToPDF: true,
|
||||
deviceName: 'Save as PDF',
|
||||
@@ -410,11 +411,11 @@ WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electr
|
||||
this._windowOpenHandler = handler;
|
||||
};
|
||||
|
||||
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, url: string, frameName: string, rawFeatures: string): BrowserWindowConstructorOptions | null {
|
||||
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): BrowserWindowConstructorOptions | null {
|
||||
if (!this._windowOpenHandler) {
|
||||
return null;
|
||||
}
|
||||
const response = this._windowOpenHandler({ url, frameName, features: rawFeatures });
|
||||
const response = this._windowOpenHandler(details);
|
||||
|
||||
if (typeof response !== 'object') {
|
||||
event.preventDefault();
|
||||
@@ -432,7 +433,11 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event,
|
||||
event.preventDefault();
|
||||
return null;
|
||||
} else if (response.action === 'allow') {
|
||||
if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) { return response.overrideBrowserWindowOptions; } else { return {}; }
|
||||
if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) {
|
||||
return response.overrideBrowserWindowOptions;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
event.preventDefault();
|
||||
console.error('The window open handler response must be an object with an \'action\' property of \'allow\' or \'deny\'.');
|
||||
@@ -498,10 +503,6 @@ WebContents.prototype._init = function () {
|
||||
|
||||
this._windowOpenHandler = null;
|
||||
|
||||
// Every remote callback from renderer process would add a listener to the
|
||||
// render-view-deleted event, so ignore the listeners warning.
|
||||
this.setMaxListeners(0);
|
||||
|
||||
// Dispatch IPC messages to the ipc module.
|
||||
this.on('-ipc-message' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
|
||||
addSenderFrameToEvent(event);
|
||||
@@ -566,26 +567,49 @@ WebContents.prototype._init = function () {
|
||||
|
||||
if (this.getType() !== 'remote') {
|
||||
// Make new windows requested by links behave like "window.open".
|
||||
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: string,
|
||||
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: Electron.HandlerDetails['disposition'],
|
||||
rawFeatures: string, referrer: Electron.Referrer, postData: PostData) => {
|
||||
openGuestWindow({
|
||||
event,
|
||||
embedder: event.sender,
|
||||
disposition,
|
||||
const postBody = postData ? {
|
||||
data: postData,
|
||||
...parseContentTypeFormat(postData)
|
||||
} : undefined;
|
||||
const details: Electron.HandlerDetails = {
|
||||
url,
|
||||
frameName,
|
||||
features: rawFeatures,
|
||||
referrer,
|
||||
postData,
|
||||
overrideBrowserWindowOptions: {},
|
||||
windowOpenArgs: {
|
||||
url,
|
||||
frameName,
|
||||
features: rawFeatures
|
||||
}
|
||||
});
|
||||
postBody,
|
||||
disposition
|
||||
};
|
||||
const options = this._callWindowOpenHandler(event, details);
|
||||
if (!event.defaultPrevented) {
|
||||
openGuestWindow({
|
||||
event,
|
||||
embedder: event.sender,
|
||||
disposition,
|
||||
referrer,
|
||||
postData,
|
||||
overrideBrowserWindowOptions: options || {},
|
||||
windowOpenArgs: details
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
|
||||
this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string) => {
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, url, frameName, rawFeatures);
|
||||
this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => {
|
||||
const postBody = postData ? {
|
||||
data: postData,
|
||||
...parseContentTypeFormat(postData)
|
||||
} : undefined;
|
||||
const details: Electron.HandlerDetails = {
|
||||
url,
|
||||
frameName,
|
||||
features: rawFeatures,
|
||||
disposition,
|
||||
referrer,
|
||||
postBody
|
||||
};
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
|
||||
@@ -27,7 +27,7 @@ export const setDefaultApplicationMenu = () => {
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: async () => {
|
||||
await shell.openExternal('https://discuss.atom.io/c/electron');
|
||||
await shell.openExternal('https://discord.gg/electron');
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -168,7 +168,6 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
guestInstanceId: guestInstanceId,
|
||||
nodeIntegration: params.nodeintegration != null ? params.nodeintegration : false,
|
||||
nodeIntegrationInSubFrames: params.nodeintegrationinsubframes != null ? params.nodeintegrationinsubframes : false,
|
||||
enableRemoteModule: params.enableremotemodule,
|
||||
plugins: params.plugins,
|
||||
zoomFactor: embedder.zoomFactor,
|
||||
disablePopups: !params.allowpopups,
|
||||
@@ -188,7 +187,6 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
['javascript', false],
|
||||
['nativeWindowOpen', true],
|
||||
['nodeIntegration', false],
|
||||
['enableRemoteModule', false],
|
||||
['sandbox', true],
|
||||
['nodeIntegrationInSubFrames', false],
|
||||
['enableWebSQL', false]
|
||||
|
||||
@@ -42,8 +42,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
windowOpenArgs: WindowOpenArgs,
|
||||
}): BrowserWindow | undefined {
|
||||
const { url, frameName, features } = windowOpenArgs;
|
||||
const isNativeWindowOpen = !!guest;
|
||||
const { options: browserWindowOptions, additionalFeatures } = makeBrowserWindowOptions({
|
||||
const { options: browserWindowOptions } = makeBrowserWindowOptions({
|
||||
embedder,
|
||||
features,
|
||||
overrideOptions: overrideBrowserWindowOptions
|
||||
@@ -55,8 +54,8 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
guest,
|
||||
browserWindowOptions,
|
||||
windowOpenArgs,
|
||||
additionalFeatures,
|
||||
disposition,
|
||||
postData,
|
||||
referrer
|
||||
});
|
||||
if (didCancelEvent) return;
|
||||
@@ -74,11 +73,14 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
webContents: guest,
|
||||
...browserWindowOptions
|
||||
});
|
||||
if (!isNativeWindowOpen) {
|
||||
if (!guest) {
|
||||
// We should only call `loadURL` if the webContents was constructed by us in
|
||||
// the case of BrowserWindowProxy (non-sandboxed, nativeWindowOpen: false),
|
||||
// as navigating to the url when creating the window from an existing
|
||||
// webContents is not necessary (it will navigate there anyway).
|
||||
// This can also happen if we enter this function from OpenURLFromTab, in
|
||||
// which case the browser process is responsible for initiating navigation
|
||||
// in the new window.
|
||||
window.loadURL(url, {
|
||||
httpReferrer: referrer,
|
||||
...(postData && {
|
||||
@@ -90,7 +92,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
|
||||
handleWindowLifecycleEvents({ embedder, frameName, guest: window });
|
||||
|
||||
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, additionalFeatures, referrer, postData });
|
||||
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData });
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -131,13 +133,12 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName }: {
|
||||
* Deprecated in favor of `webContents.setWindowOpenHandler` and
|
||||
* `did-create-window` in 11.0.0. Will be removed in 12.0.0.
|
||||
*/
|
||||
function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs, browserWindowOptions, additionalFeatures, disposition, referrer, postData }: {
|
||||
function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs, browserWindowOptions, disposition, referrer, postData }: {
|
||||
event: { sender: WebContents, defaultPrevented: boolean, newGuest?: BrowserWindow },
|
||||
embedder: WebContents,
|
||||
guest?: WebContents,
|
||||
windowOpenArgs: WindowOpenArgs,
|
||||
browserWindowOptions: BrowserWindowConstructorOptions,
|
||||
additionalFeatures: string[]
|
||||
disposition: string,
|
||||
referrer: Referrer,
|
||||
postData?: PostData,
|
||||
@@ -146,7 +147,7 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs,
|
||||
const isWebViewWithPopupsDisabled = embedder.getType() === 'webview' && embedder.getLastWebPreferences().disablePopups;
|
||||
const postBody = postData ? {
|
||||
data: postData,
|
||||
headers: formatPostDataHeaders(postData as Electron.UploadRawData[])
|
||||
...parseContentTypeFormat(postData)
|
||||
} : null;
|
||||
|
||||
embedder.emit(
|
||||
@@ -159,7 +160,7 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs,
|
||||
...browserWindowOptions,
|
||||
webContents: guest
|
||||
},
|
||||
additionalFeatures,
|
||||
[], // additionalFeatures
|
||||
referrer,
|
||||
postBody
|
||||
);
|
||||
@@ -191,49 +192,43 @@ const securityWebPreferences: { [key: string]: boolean } = {
|
||||
javascript: false,
|
||||
nativeWindowOpen: true,
|
||||
nodeIntegration: false,
|
||||
enableRemoteModule: false,
|
||||
sandbox: true,
|
||||
webviewTag: false,
|
||||
nodeIntegrationInSubFrames: false,
|
||||
enableWebSQL: false
|
||||
};
|
||||
|
||||
function makeBrowserWindowOptions ({ embedder, features, overrideOptions, useDeprecatedBehaviorForBareValues = true, useDeprecatedBehaviorForOptionInheritance = true }: {
|
||||
function makeBrowserWindowOptions ({ embedder, features, overrideOptions }: {
|
||||
embedder: WebContents,
|
||||
features: string,
|
||||
overrideOptions?: BrowserWindowConstructorOptions,
|
||||
useDeprecatedBehaviorForBareValues?: boolean
|
||||
useDeprecatedBehaviorForOptionInheritance?: boolean
|
||||
}) {
|
||||
const { options: parsedOptions, webPreferences: parsedWebPreferences, additionalFeatures } = parseFeatures(features, useDeprecatedBehaviorForBareValues);
|
||||
|
||||
const deprecatedInheritedOptions = getDeprecatedInheritedOptions(embedder);
|
||||
const { options: parsedOptions, webPreferences: parsedWebPreferences } = parseFeatures(features);
|
||||
|
||||
return {
|
||||
additionalFeatures,
|
||||
options: {
|
||||
...(useDeprecatedBehaviorForOptionInheritance && deprecatedInheritedOptions),
|
||||
show: true,
|
||||
width: 800,
|
||||
height: 600,
|
||||
...parsedOptions,
|
||||
...overrideOptions,
|
||||
webPreferences: makeWebPreferences({ embedder, insecureParsedWebPreferences: parsedWebPreferences, secureOverrideWebPreferences: overrideOptions && overrideOptions.webPreferences, useDeprecatedBehaviorForOptionInheritance: true })
|
||||
webPreferences: makeWebPreferences({
|
||||
embedder,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
secureOverrideWebPreferences: overrideOptions && overrideOptions.webPreferences
|
||||
})
|
||||
} as Electron.BrowserViewConstructorOptions
|
||||
};
|
||||
}
|
||||
|
||||
export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {}, insecureParsedWebPreferences: parsedWebPreferences = {}, useDeprecatedBehaviorForOptionInheritance = true }: {
|
||||
export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {}, insecureParsedWebPreferences: parsedWebPreferences = {} }: {
|
||||
embedder: WebContents,
|
||||
insecureParsedWebPreferences?: ReturnType<typeof parseFeatures>['webPreferences'],
|
||||
// Note that override preferences are considered elevated, and should only be
|
||||
// sourced from the main process, as they override security defaults. If you
|
||||
// have unvetted prefs, use parsedWebPreferences.
|
||||
secureOverrideWebPreferences?: BrowserWindowConstructorOptions['webPreferences'],
|
||||
useDeprecatedBehaviorForBareValues?: boolean
|
||||
useDeprecatedBehaviorForOptionInheritance?: boolean
|
||||
}) {
|
||||
const deprecatedInheritedOptions = getDeprecatedInheritedOptions(embedder);
|
||||
const parentWebPreferences = embedder.getLastWebPreferences();
|
||||
const securityWebPreferencesFromParent = (Object.keys(securityWebPreferences).reduce((map, key) => {
|
||||
if (securityWebPreferences[key] === parentWebPreferences[key as keyof Electron.WebPreferences]) {
|
||||
@@ -244,7 +239,6 @@ export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {
|
||||
const openerId = parentWebPreferences.nativeWindowOpen ? null : embedder.id;
|
||||
|
||||
return {
|
||||
...(useDeprecatedBehaviorForOptionInheritance && deprecatedInheritedOptions ? deprecatedInheritedOptions.webPreferences : null),
|
||||
...parsedWebPreferences,
|
||||
// Note that order is key here, we want to disallow the renderer's
|
||||
// ability to change important security options but allow main (via
|
||||
@@ -257,41 +251,40 @@ export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Current Electron behavior is to inherit all options from the parent window.
|
||||
* In practical use, this is kind of annoying because consumers have to know
|
||||
* about the parent window's preferences in order to unset them and makes child
|
||||
* windows even more of an anomaly. In 11.0.0 we will remove this behavior and
|
||||
* only critical security preferences will be inherited by default.
|
||||
*/
|
||||
function getDeprecatedInheritedOptions (embedder: WebContents) {
|
||||
if (!embedder.browserWindowOptions) {
|
||||
// If it's a webview, return just the webPreferences.
|
||||
return {
|
||||
webPreferences: embedder.getLastWebPreferences()
|
||||
};
|
||||
}
|
||||
|
||||
const { type, show, ...inheritableOptions } = embedder.browserWindowOptions;
|
||||
return inheritableOptions;
|
||||
}
|
||||
|
||||
function formatPostDataHeaders (postData: Electron.UploadRawData[]) {
|
||||
function formatPostDataHeaders (postData: PostData) {
|
||||
if (!postData) return;
|
||||
|
||||
let extraHeaders = 'content-type: application/x-www-form-urlencoded';
|
||||
const { contentType, boundary } = parseContentTypeFormat(postData);
|
||||
if (boundary != null) { return `content-type: ${contentType}; boundary=${boundary}`; }
|
||||
|
||||
if (postData.length > 0) {
|
||||
const postDataFront = postData[0].bytes.toString();
|
||||
const boundary = /^--.*[^-\r\n]/.exec(
|
||||
postDataFront
|
||||
);
|
||||
if (boundary != null) {
|
||||
extraHeaders = `content-type: multipart/form-data; boundary=${boundary[0].substr(
|
||||
2
|
||||
)}`;
|
||||
return `content-type: ${contentType}`;
|
||||
}
|
||||
|
||||
const MULTIPART_CONTENT_TYPE = 'multipart/form-data';
|
||||
const URL_ENCODED_CONTENT_TYPE = 'application/x-www-form-urlencoded';
|
||||
|
||||
// Figure out appropriate headers for post data.
|
||||
export const parseContentTypeFormat = function (postData: Exclude<PostData, undefined>) {
|
||||
if (postData.length) {
|
||||
if (postData[0].type === 'rawData') {
|
||||
// For multipart forms, the first element will start with the boundary
|
||||
// notice, which looks something like `------WebKitFormBoundary12345678`
|
||||
// Note, this regex would fail when submitting a urlencoded form with an
|
||||
// input attribute of name="--theKey", but, uhh, don't do that?
|
||||
const postDataFront = postData[0].bytes.toString();
|
||||
const boundary = /^--.*[^-\r\n]/.exec(postDataFront);
|
||||
if (boundary) {
|
||||
return {
|
||||
boundary: boundary[0].substr(2),
|
||||
contentType: MULTIPART_CONTENT_TYPE
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return extraHeaders;
|
||||
}
|
||||
// Either the form submission didn't contain any inputs (the postData array
|
||||
// was empty), or we couldn't find the boundary and thus we can assume this is
|
||||
// a key=value style form.
|
||||
return {
|
||||
contentType: URL_ENCODED_CONTENT_TYPE
|
||||
};
|
||||
};
|
||||
|
||||
@@ -73,14 +73,15 @@ ipcMainInternal.on(
|
||||
);
|
||||
}
|
||||
|
||||
const browserWindowOptions = event.sender._callWindowOpenHandler(event, url, frameName, features);
|
||||
const referrer: Electron.Referrer = { url: '', policy: 'strict-origin-when-cross-origin' };
|
||||
const browserWindowOptions = event.sender._callWindowOpenHandler(event, { url, frameName, features, disposition: 'new-window', referrer });
|
||||
if (event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
const guest = openGuestWindow({
|
||||
event,
|
||||
embedder: event.sender,
|
||||
referrer: { url: '', policy: 'default' },
|
||||
referrer,
|
||||
disposition: 'new-window',
|
||||
overrideBrowserWindowOptions: browserWindowOptions!,
|
||||
windowOpenArgs: {
|
||||
@@ -134,7 +135,7 @@ handleMessage(
|
||||
|
||||
if (!windowMethods.has(method)) {
|
||||
console.error(
|
||||
`Blocked ${event.sender.getURL()} from calling method: ${method}`
|
||||
`Blocked ${event.senderFrame.url} from calling method: ${method}`
|
||||
);
|
||||
throw new Error(`Invalid method: ${method}`);
|
||||
}
|
||||
|
||||
@@ -132,10 +132,6 @@ app._setDefaultAppPaths(packagePath);
|
||||
// Load the chrome devtools support.
|
||||
require('@electron/internal/browser/devtools');
|
||||
|
||||
if (BUILDFLAG(ENABLE_REMOTE_MODULE)) {
|
||||
require('@electron/internal/browser/remote/server');
|
||||
}
|
||||
|
||||
// Load protocol module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/protocol');
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
import { WebContents } from 'electron/main';
|
||||
|
||||
const getOwnerKey = (webContents: WebContents, contextId: string) => {
|
||||
return `${webContents.id}-${contextId}`;
|
||||
};
|
||||
|
||||
class ObjectsRegistry {
|
||||
private nextId: number = 0
|
||||
|
||||
// Stores all objects by ref-counting.
|
||||
// (id) => {object, count}
|
||||
private storage: Record<number, { count: number, object: any }> = {}
|
||||
|
||||
// Stores the IDs + refCounts of objects referenced by WebContents.
|
||||
// (ownerKey) => { id: refCount }
|
||||
private owners: Record<string, Map<number, number>> = {}
|
||||
|
||||
private electronIds = new WeakMap<Object, number>();
|
||||
|
||||
// Register a new object and return its assigned ID. If the object is already
|
||||
// registered then the already assigned ID would be returned.
|
||||
add (webContents: WebContents, contextId: string, obj: any) {
|
||||
// Get or assign an ID to the object.
|
||||
const id = this.saveToStorage(obj);
|
||||
|
||||
// Add object to the set of referenced objects.
|
||||
const ownerKey = getOwnerKey(webContents, contextId);
|
||||
let owner = this.owners[ownerKey];
|
||||
if (!owner) {
|
||||
owner = this.owners[ownerKey] = new Map();
|
||||
this.registerDeleteListener(webContents, contextId);
|
||||
}
|
||||
if (!owner.has(id)) {
|
||||
owner.set(id, 0);
|
||||
// Increase reference count if not referenced before.
|
||||
this.storage[id].count++;
|
||||
}
|
||||
|
||||
owner.set(id, owner.get(id)! + 1);
|
||||
return id;
|
||||
}
|
||||
|
||||
// Get an object according to its ID.
|
||||
get (id: number) {
|
||||
const pointer = this.storage[id];
|
||||
if (pointer != null) return pointer.object;
|
||||
}
|
||||
|
||||
// Dereference an object according to its ID.
|
||||
// Note that an object may be double-freed (cleared when page is reloaded, and
|
||||
// then garbage collected in old page).
|
||||
remove (webContents: WebContents, contextId: string, id: number) {
|
||||
const ownerKey = getOwnerKey(webContents, contextId);
|
||||
const owner = this.owners[ownerKey];
|
||||
if (owner && owner.has(id)) {
|
||||
const newRefCount = owner.get(id)! - 1;
|
||||
|
||||
// Only completely remove if the number of references GCed in the
|
||||
// renderer is the same as the number of references we sent them
|
||||
if (newRefCount <= 0) {
|
||||
// Remove the reference in owner.
|
||||
owner.delete(id);
|
||||
// Dereference from the storage.
|
||||
this.dereference(id);
|
||||
} else {
|
||||
owner.set(id, newRefCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all references to objects refrenced by the WebContents.
|
||||
clear (webContents: WebContents, contextId: string) {
|
||||
const ownerKey = getOwnerKey(webContents, contextId);
|
||||
const owner = this.owners[ownerKey];
|
||||
if (!owner) return;
|
||||
|
||||
for (const id of owner.keys()) this.dereference(id);
|
||||
|
||||
delete this.owners[ownerKey];
|
||||
}
|
||||
|
||||
// Private: Saves the object into storage and assigns an ID for it.
|
||||
saveToStorage (object: any) {
|
||||
let id = this.electronIds.get(object);
|
||||
if (!id) {
|
||||
id = ++this.nextId;
|
||||
this.storage[id] = {
|
||||
count: 0,
|
||||
object: object
|
||||
};
|
||||
this.electronIds.set(object, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
// Private: Dereference the object from store.
|
||||
dereference (id: number) {
|
||||
const pointer = this.storage[id];
|
||||
if (pointer == null) {
|
||||
return;
|
||||
}
|
||||
pointer.count -= 1;
|
||||
if (pointer.count === 0) {
|
||||
this.electronIds.delete(pointer.object);
|
||||
delete this.storage[id];
|
||||
}
|
||||
}
|
||||
|
||||
// Private: Clear the storage when renderer process is destroyed.
|
||||
registerDeleteListener (webContents: WebContents, contextId: string) {
|
||||
// contextId => ${processHostId}-${contextCount}
|
||||
const processHostId = contextId.split('-')[0];
|
||||
const listener = (_: any, deletedProcessHostId: string) => {
|
||||
if (deletedProcessHostId &&
|
||||
deletedProcessHostId.toString() === processHostId) {
|
||||
webContents.removeListener('render-view-deleted' as any, listener);
|
||||
this.clear(webContents, contextId);
|
||||
}
|
||||
};
|
||||
// Note that the "render-view-deleted" event may not be emitted on time when
|
||||
// the renderer process get destroyed because of navigation, we rely on the
|
||||
// renderer process to send "ELECTRON_BROWSER_CONTEXT_RELEASE" message to
|
||||
// guard this situation.
|
||||
webContents.on('render-view-deleted' as any, listener);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ObjectsRegistry();
|
||||
@@ -1,519 +0,0 @@
|
||||
import * as electron from 'electron/main';
|
||||
import { EventEmitter } from 'events';
|
||||
import objectsRegistry from '@electron/internal/browser/remote/objects-registry';
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
|
||||
import type { MetaTypeFromRenderer, ObjectMember, MetaType, ObjProtoDescriptor } from '@electron/internal/common/remote/types';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/remote/ipc-messages';
|
||||
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
const eventBinding = process._linkedBinding('electron_browser_event');
|
||||
const features = process._linkedBinding('electron_common_features');
|
||||
|
||||
if (!features.isRemoteModuleEnabled()) {
|
||||
throw new Error('remote module is disabled');
|
||||
}
|
||||
|
||||
// The internal properties of Function.
|
||||
const FUNCTION_PROPERTIES = [
|
||||
'length', 'name', 'arguments', 'caller', 'prototype'
|
||||
];
|
||||
|
||||
type RendererFunctionId = [string, number] // [contextId, funcId]
|
||||
type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: [number, number] };
|
||||
type CallIntoRenderer = (...args: any[]) => void
|
||||
|
||||
// The remote functions in renderer processes.
|
||||
const rendererFunctionCache = new Map<string, WeakRef<CallIntoRenderer>>();
|
||||
// eslint-disable-next-line no-undef
|
||||
const finalizationRegistry = new FinalizationRegistry((fi: FinalizerInfo) => {
|
||||
const mapKey = fi.id[0] + '~' + fi.id[1];
|
||||
const ref = rendererFunctionCache.get(mapKey);
|
||||
if (ref !== undefined && ref.deref() === undefined) {
|
||||
rendererFunctionCache.delete(mapKey);
|
||||
if (!fi.webContents.isDestroyed()) {
|
||||
try {
|
||||
fi.webContents._sendToFrameInternal(fi.frameId, IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, fi.id[0], fi.id[1]);
|
||||
} catch (error) {
|
||||
console.warn(`_sendToFrameInternal() failed: ${error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function getCachedRendererFunction (id: RendererFunctionId): CallIntoRenderer | undefined {
|
||||
const mapKey = id[0] + '~' + id[1];
|
||||
const ref = rendererFunctionCache.get(mapKey);
|
||||
if (ref !== undefined) {
|
||||
const deref = ref.deref();
|
||||
if (deref !== undefined) return deref;
|
||||
}
|
||||
}
|
||||
function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebContents, frameId: [number, number], value: CallIntoRenderer) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const wr = new WeakRef<CallIntoRenderer>(value);
|
||||
const mapKey = id[0] + '~' + id[1];
|
||||
rendererFunctionCache.set(mapKey, wr);
|
||||
finalizationRegistry.register(value, {
|
||||
id,
|
||||
webContents: wc,
|
||||
frameId
|
||||
} as FinalizerInfo);
|
||||
return value;
|
||||
}
|
||||
|
||||
const locationInfo = new WeakMap<Object, string>();
|
||||
|
||||
// Return the description of object's members:
|
||||
const getObjectMembers = function (object: any): ObjectMember[] {
|
||||
let names = Object.getOwnPropertyNames(object);
|
||||
// For Function, we should not override following properties even though they
|
||||
// are "own" properties.
|
||||
if (typeof object === 'function') {
|
||||
names = names.filter((name) => {
|
||||
return !FUNCTION_PROPERTIES.includes(name);
|
||||
});
|
||||
}
|
||||
// Map properties to descriptors.
|
||||
return names.map((name) => {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(object, name)!;
|
||||
let type: ObjectMember['type'];
|
||||
let writable = false;
|
||||
if (descriptor.get === undefined && typeof object[name] === 'function') {
|
||||
type = 'method';
|
||||
} else {
|
||||
if (descriptor.set || descriptor.writable) writable = true;
|
||||
type = 'get';
|
||||
}
|
||||
return { name, enumerable: descriptor.enumerable, writable, type };
|
||||
});
|
||||
};
|
||||
|
||||
// Return the description of object's prototype.
|
||||
const getObjectPrototype = function (object: any): ObjProtoDescriptor {
|
||||
const proto = Object.getPrototypeOf(object);
|
||||
if (proto === null || proto === Object.prototype) return null;
|
||||
return {
|
||||
members: getObjectMembers(proto),
|
||||
proto: getObjectPrototype(proto)
|
||||
};
|
||||
};
|
||||
|
||||
// Convert a real value into meta data.
|
||||
const valueToMeta = function (sender: electron.WebContents, contextId: string, value: any, optimizeSimpleObject = false): MetaType {
|
||||
// Determine the type of value.
|
||||
let type: MetaType['type'];
|
||||
|
||||
switch (typeof value) {
|
||||
case 'object':
|
||||
// Recognize certain types of objects.
|
||||
if (value instanceof Buffer) {
|
||||
type = 'buffer';
|
||||
} else if (value && value.constructor && value.constructor.name === 'NativeImage') {
|
||||
type = 'nativeimage';
|
||||
} else if (Array.isArray(value)) {
|
||||
type = 'array';
|
||||
} else if (value instanceof Error) {
|
||||
type = 'error';
|
||||
} else if (isSerializableObject(value)) {
|
||||
type = 'value';
|
||||
} else if (isPromise(value)) {
|
||||
type = 'promise';
|
||||
} else if (Object.prototype.hasOwnProperty.call(value, 'callee') && value.length != null) {
|
||||
// Treat the arguments object as array.
|
||||
type = 'array';
|
||||
} else if (optimizeSimpleObject && v8Util.getHiddenValue(value, 'simple')) {
|
||||
// Treat simple objects as value.
|
||||
type = 'value';
|
||||
} else {
|
||||
type = 'object';
|
||||
}
|
||||
break;
|
||||
case 'function':
|
||||
type = 'function';
|
||||
break;
|
||||
default:
|
||||
type = 'value';
|
||||
break;
|
||||
}
|
||||
|
||||
// Fill the meta object according to value's type.
|
||||
if (type === 'array') {
|
||||
return {
|
||||
type,
|
||||
members: value.map((el: any) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
|
||||
};
|
||||
} else if (type === 'nativeimage') {
|
||||
return { type, value: serialize(value) };
|
||||
} else if (type === 'object' || type === 'function') {
|
||||
return {
|
||||
type,
|
||||
name: value.constructor ? value.constructor.name : '',
|
||||
// Reference the original value if it's an object, because when it's
|
||||
// passed to renderer we would assume the renderer keeps a reference of
|
||||
// it.
|
||||
id: objectsRegistry.add(sender, contextId, value),
|
||||
members: getObjectMembers(value),
|
||||
proto: getObjectPrototype(value)
|
||||
};
|
||||
} else if (type === 'buffer') {
|
||||
return { type, value };
|
||||
} else if (type === 'promise') {
|
||||
// Add default handler to prevent unhandled rejections in main process
|
||||
// Instead they should appear in the renderer process
|
||||
value.then(function () {}, function () {});
|
||||
|
||||
return {
|
||||
type,
|
||||
then: valueToMeta(sender, contextId, function (onFulfilled: Function, onRejected: Function) {
|
||||
value.then(onFulfilled, onRejected);
|
||||
})
|
||||
};
|
||||
} else if (type === 'error') {
|
||||
return {
|
||||
type,
|
||||
value,
|
||||
members: Object.keys(value).map(name => ({
|
||||
name,
|
||||
value: valueToMeta(sender, contextId, value[name])
|
||||
}))
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'value',
|
||||
value
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const throwRPCError = function (message: string) {
|
||||
const error = new Error(message) as Error & {code: string, errno: number};
|
||||
error.code = 'EBADRPC';
|
||||
error.errno = -72;
|
||||
throw error;
|
||||
};
|
||||
|
||||
const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...args: any[]) => void) => {
|
||||
const location = locationInfo.get(callIntoRenderer);
|
||||
let message = 'Attempting to call a function in a renderer window that has been closed or released.' +
|
||||
`\nFunction provided here: ${location}`;
|
||||
|
||||
if (sender instanceof EventEmitter) {
|
||||
const remoteEvents = sender.eventNames().filter((eventName) => {
|
||||
return sender.listeners(eventName).includes(callIntoRenderer);
|
||||
});
|
||||
|
||||
if (remoteEvents.length > 0) {
|
||||
message += `\nRemote event names: ${remoteEvents.join(', ')}`;
|
||||
remoteEvents.forEach((eventName) => {
|
||||
sender.removeListener(eventName, callIntoRenderer);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.warn(message);
|
||||
};
|
||||
|
||||
const fakeConstructor = (constructor: Function, name: string) =>
|
||||
new Proxy(Object, {
|
||||
get (target, prop, receiver) {
|
||||
if (prop === 'name') {
|
||||
return name;
|
||||
} else {
|
||||
return Reflect.get(target, prop, receiver);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Convert array of meta data from renderer into array of real values.
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: [number, number], contextId: string, args: any[]) {
|
||||
const metaToValue = function (meta: MetaTypeFromRenderer): any {
|
||||
switch (meta.type) {
|
||||
case 'nativeimage':
|
||||
return deserialize(meta.value);
|
||||
case 'value':
|
||||
return meta.value;
|
||||
case 'remote-object':
|
||||
return objectsRegistry.get(meta.id);
|
||||
case 'array':
|
||||
return unwrapArgs(sender, frameId, contextId, meta.value);
|
||||
case 'buffer':
|
||||
return Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength);
|
||||
case 'promise':
|
||||
return Promise.resolve({
|
||||
then: metaToValue(meta.then)
|
||||
});
|
||||
case 'object': {
|
||||
const ret: any = meta.name !== 'Object' ? Object.create({
|
||||
constructor: fakeConstructor(Object, meta.name)
|
||||
}) : {};
|
||||
|
||||
for (const { name, value } of meta.members) {
|
||||
ret[name] = metaToValue(value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case 'function-with-return-value': {
|
||||
const returnValue = metaToValue(meta.value);
|
||||
return function () {
|
||||
return returnValue;
|
||||
};
|
||||
}
|
||||
case 'function': {
|
||||
// Merge contextId and meta.id, since meta.id can be the same in
|
||||
// different webContents.
|
||||
const objectId: [string, number] = [contextId, meta.id];
|
||||
|
||||
// Cache the callbacks in renderer.
|
||||
const cachedFunction = getCachedRendererFunction(objectId);
|
||||
if (cachedFunction !== undefined) { return cachedFunction; }
|
||||
|
||||
const callIntoRenderer = function (this: any, ...args: any[]) {
|
||||
let succeed = false;
|
||||
if (!sender.isDestroyed()) {
|
||||
try {
|
||||
succeed = sender._sendToFrameInternal(frameId, IPC_MESSAGES.RENDERER_CALLBACK, contextId, meta.id, valueToMeta(sender, contextId, args));
|
||||
} catch (error) {
|
||||
console.warn(`_sendToFrameInternal() failed: ${error}`);
|
||||
}
|
||||
}
|
||||
if (!succeed) {
|
||||
removeRemoteListenersAndLogWarning(this, callIntoRenderer);
|
||||
}
|
||||
};
|
||||
locationInfo.set(callIntoRenderer, meta.location);
|
||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
|
||||
|
||||
setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);
|
||||
return callIntoRenderer;
|
||||
}
|
||||
default:
|
||||
throw new TypeError(`Unknown type: ${(meta as any).type}`);
|
||||
}
|
||||
};
|
||||
return args.map(metaToValue);
|
||||
};
|
||||
|
||||
const isRemoteModuleEnabledImpl = function (contents: electron.WebContents) {
|
||||
const webPreferences = contents.getLastWebPreferences() || {};
|
||||
return webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : false;
|
||||
};
|
||||
|
||||
const isRemoteModuleEnabledCache = new WeakMap();
|
||||
|
||||
export const isRemoteModuleEnabled = function (contents: electron.WebContents) {
|
||||
if (!isRemoteModuleEnabledCache.has(contents)) {
|
||||
isRemoteModuleEnabledCache.set(contents, isRemoteModuleEnabledImpl(contents));
|
||||
}
|
||||
|
||||
return isRemoteModuleEnabledCache.get(contents);
|
||||
};
|
||||
|
||||
const handleRemoteCommand = function (channel: string, handler: (event: ElectronInternal.IpcMainInternalEvent, contextId: string, ...args: any[]) => void) {
|
||||
ipcMainInternal.on(channel, (event, contextId: string, ...args: any[]) => {
|
||||
let returnValue;
|
||||
if (!isRemoteModuleEnabled(event.sender)) {
|
||||
event.returnValue = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
returnValue = handler(event, contextId, ...args);
|
||||
} catch (error) {
|
||||
returnValue = {
|
||||
type: 'exception',
|
||||
value: valueToMeta(event.sender, contextId, error)
|
||||
};
|
||||
}
|
||||
|
||||
if (returnValue !== undefined) {
|
||||
event.returnValue = returnValue;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const emitCustomEvent = function (contents: electron.WebContents, eventName: string, ...args: any[]) {
|
||||
const event = eventBinding.createWithSender(contents);
|
||||
|
||||
electron.app.emit(eventName, event, contents, ...args);
|
||||
contents.emit(eventName, event, ...args);
|
||||
|
||||
return event;
|
||||
};
|
||||
|
||||
const logStack = function (contents: electron.WebContents, code: string, stack: string | undefined) {
|
||||
if (stack) {
|
||||
console.warn(`WebContents (${contents.id}): ${code}`, stack);
|
||||
}
|
||||
};
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_WRONG_CONTEXT_ERROR, function (event, contextId, passedContextId, id) {
|
||||
const objectId: [string, number] = [passedContextId, id];
|
||||
const cachedFunction = getCachedRendererFunction(objectId);
|
||||
if (cachedFunction === undefined) {
|
||||
// Do nothing if the error has already been reported before.
|
||||
return;
|
||||
}
|
||||
removeRemoteListenersAndLogWarning(event.sender, cachedFunction);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_REQUIRE, function (event, contextId, moduleName, stack) {
|
||||
logStack(event.sender, `remote.require('${moduleName}')`, stack);
|
||||
const customEvent = emitCustomEvent(event.sender, 'remote-require', moduleName);
|
||||
|
||||
if (customEvent.returnValue === undefined) {
|
||||
if (customEvent.defaultPrevented) {
|
||||
throw new Error(`Blocked remote.require('${moduleName}')`);
|
||||
} else {
|
||||
customEvent.returnValue = process.mainModule.require(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, customEvent.returnValue);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_BUILTIN, function (event, contextId, moduleName, stack) {
|
||||
logStack(event.sender, `remote.getBuiltin('${moduleName}')`, stack);
|
||||
const customEvent = emitCustomEvent(event.sender, 'remote-get-builtin', moduleName);
|
||||
|
||||
if (customEvent.returnValue === undefined) {
|
||||
if (customEvent.defaultPrevented) {
|
||||
throw new Error(`Blocked remote.getBuiltin('${moduleName}')`);
|
||||
} else {
|
||||
customEvent.returnValue = (electron as any)[moduleName];
|
||||
}
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, customEvent.returnValue);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_GLOBAL, function (event, contextId, globalName, stack) {
|
||||
logStack(event.sender, `remote.getGlobal('${globalName}')`, stack);
|
||||
const customEvent = emitCustomEvent(event.sender, 'remote-get-global', globalName);
|
||||
|
||||
if (customEvent.returnValue === undefined) {
|
||||
if (customEvent.defaultPrevented) {
|
||||
throw new Error(`Blocked remote.getGlobal('${globalName}')`);
|
||||
} else {
|
||||
customEvent.returnValue = (global as any)[globalName];
|
||||
}
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, customEvent.returnValue);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_CURRENT_WINDOW, function (event, contextId, stack) {
|
||||
logStack(event.sender, 'remote.getCurrentWindow()', stack);
|
||||
const customEvent = emitCustomEvent(event.sender, 'remote-get-current-window');
|
||||
|
||||
if (customEvent.returnValue === undefined) {
|
||||
if (customEvent.defaultPrevented) {
|
||||
throw new Error('Blocked remote.getCurrentWindow()');
|
||||
} else {
|
||||
customEvent.returnValue = event.sender.getOwnerBrowserWindow();
|
||||
}
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, customEvent.returnValue);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_GET_CURRENT_WEB_CONTENTS, function (event, contextId, stack) {
|
||||
logStack(event.sender, 'remote.getCurrentWebContents()', stack);
|
||||
const customEvent = emitCustomEvent(event.sender, 'remote-get-current-web-contents');
|
||||
|
||||
if (customEvent.returnValue === undefined) {
|
||||
if (customEvent.defaultPrevented) {
|
||||
throw new Error('Blocked remote.getCurrentWebContents()');
|
||||
} else {
|
||||
customEvent.returnValue = event.sender;
|
||||
}
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, customEvent.returnValue);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_CONSTRUCTOR, function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const constructor = objectsRegistry.get(id);
|
||||
|
||||
if (constructor == null) {
|
||||
throwRPCError(`Cannot call constructor on missing remote object ${id}`);
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, new constructor(...args));
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_FUNCTION_CALL, function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const func = objectsRegistry.get(id);
|
||||
|
||||
if (func == null) {
|
||||
throwRPCError(`Cannot call function on missing remote object ${id}`);
|
||||
}
|
||||
|
||||
try {
|
||||
return valueToMeta(event.sender, contextId, func(...args), true);
|
||||
} catch (error) {
|
||||
const err = new Error(`Could not call remote function '${func.name || 'anonymous'}'. Check that the function signature is correct. Underlying error: ${error.message}\nUnderlying stack: ${error.stack}\n`);
|
||||
(err as any).cause = error;
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CONSTRUCTOR, function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
throwRPCError(`Cannot call constructor '${method}' on missing remote object ${id}`);
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, new object[method](...args));
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_CALL, function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
throwRPCError(`Cannot call method '${method}' on missing remote object ${id}`);
|
||||
}
|
||||
|
||||
try {
|
||||
return valueToMeta(event.sender, contextId, object[method](...args), true);
|
||||
} catch (error) {
|
||||
const err = new Error(`Could not call remote method '${method}'. Check that the method signature is correct. Underlying error: ${error.message}\nUnderlying stack: ${error.stack}\n`);
|
||||
(err as any).cause = error;
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_SET, function (event, contextId, id, name, args) {
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const obj = objectsRegistry.get(id);
|
||||
|
||||
if (obj == null) {
|
||||
throwRPCError(`Cannot set property '${name}' on missing remote object ${id}`);
|
||||
}
|
||||
|
||||
obj[name] = args[0];
|
||||
return null;
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_MEMBER_GET, function (event, contextId, id, name) {
|
||||
const obj = objectsRegistry.get(id);
|
||||
|
||||
if (obj == null) {
|
||||
throwRPCError(`Cannot get property '${name}' on missing remote object ${id}`);
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, obj[name]);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_DEREFERENCE, function (event, contextId, id) {
|
||||
objectsRegistry.remove(event.sender, contextId, id);
|
||||
});
|
||||
|
||||
handleRemoteCommand(IPC_MESSAGES.BROWSER_CONTEXT_RELEASE, (event, contextId) => {
|
||||
objectsRegistry.clear(event.sender, contextId);
|
||||
});
|
||||
@@ -56,41 +56,28 @@ function coerce (key: string, value: string): CoercedValue {
|
||||
}
|
||||
}
|
||||
|
||||
export function parseCommaSeparatedKeyValue (source: string, useSoonToBeDeprecatedBehaviorForBareKeys: boolean) {
|
||||
const bareKeys = [] as string[];
|
||||
export function parseCommaSeparatedKeyValue (source: string) {
|
||||
const parsed = {} as { [key: string]: any };
|
||||
for (const keyValuePair of source.split(',')) {
|
||||
const [key, value] = keyValuePair.split('=').map(str => str.trim());
|
||||
if (useSoonToBeDeprecatedBehaviorForBareKeys && value === undefined) {
|
||||
bareKeys.push(key);
|
||||
continue;
|
||||
}
|
||||
parsed[key] = coerce(key, value);
|
||||
if (key) { parsed[key] = coerce(key, value); }
|
||||
}
|
||||
|
||||
return { parsed, bareKeys };
|
||||
return parsed;
|
||||
}
|
||||
|
||||
export function parseWebViewWebPreferences (preferences: string) {
|
||||
return parseCommaSeparatedKeyValue(preferences, false).parsed;
|
||||
return parseCommaSeparatedKeyValue(preferences);
|
||||
}
|
||||
|
||||
const allowedWebPreferences = ['zoomFactor', 'nodeIntegration', 'enableRemoteModule', 'javascript', 'contextIsolation', 'webviewTag'] as const;
|
||||
const allowedWebPreferences = ['zoomFactor', 'nodeIntegration', 'javascript', 'contextIsolation', 'webviewTag'] as const;
|
||||
type AllowedWebPreference = (typeof allowedWebPreferences)[number];
|
||||
|
||||
/**
|
||||
* Parses a feature string that has the format used in window.open().
|
||||
*
|
||||
* `useSoonToBeDeprecatedBehaviorForBareKeys` - In the html spec, windowFeatures keys
|
||||
* without values are interpreted as `true`. Previous versions of Electron did
|
||||
* not respect this. In order to not break any applications, this will be
|
||||
* flipped in the next major version.
|
||||
*/
|
||||
export function parseFeatures (
|
||||
features: string,
|
||||
useSoonToBeDeprecatedBehaviorForBareKeys: boolean = true
|
||||
) {
|
||||
const { parsed, bareKeys } = parseCommaSeparatedKeyValue(features, useSoonToBeDeprecatedBehaviorForBareKeys);
|
||||
export function parseFeatures (features: string) {
|
||||
const parsed = parseCommaSeparatedKeyValue(features);
|
||||
|
||||
const webPreferences: { [K in AllowedWebPreference]?: any } = {};
|
||||
allowedWebPreferences.forEach((key) => {
|
||||
@@ -104,7 +91,6 @@ export function parseFeatures (
|
||||
|
||||
return {
|
||||
options: parsed as Omit<BrowserWindowConstructorOptions, 'webPreferences'>,
|
||||
webPreferences,
|
||||
additionalFeatures: bareKeys
|
||||
webPreferences
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import type { Size } from 'electron/main';
|
||||
import type { NativeImage } from 'electron/common';
|
||||
|
||||
export type ObjectMember = {
|
||||
name: string,
|
||||
value?: any,
|
||||
enumerable?: boolean,
|
||||
writable?: boolean,
|
||||
type?: 'method' | 'get'
|
||||
}
|
||||
|
||||
export type ObjProtoDescriptor = {
|
||||
members: ObjectMember[],
|
||||
proto: ObjProtoDescriptor
|
||||
} | null
|
||||
|
||||
export type MetaType = {
|
||||
type: 'object' | 'function',
|
||||
name: string,
|
||||
members: ObjectMember[],
|
||||
proto: ObjProtoDescriptor,
|
||||
id: number,
|
||||
} | {
|
||||
type: 'value',
|
||||
value: any,
|
||||
} | {
|
||||
type: 'buffer',
|
||||
value: Uint8Array,
|
||||
} | {
|
||||
type: 'array',
|
||||
members: MetaType[]
|
||||
} | {
|
||||
type: 'error',
|
||||
value: Error,
|
||||
members: ObjectMember[]
|
||||
} | {
|
||||
type: 'exception',
|
||||
value: MetaType,
|
||||
} | {
|
||||
type: 'promise',
|
||||
then: MetaType
|
||||
} | {
|
||||
type: 'nativeimage'
|
||||
value: NativeImage
|
||||
}
|
||||
|
||||
export type MetaTypeFromRenderer = {
|
||||
type: 'value',
|
||||
value: any
|
||||
} | {
|
||||
type: 'remote-object',
|
||||
id: number
|
||||
} | {
|
||||
type: 'array',
|
||||
value: MetaTypeFromRenderer[]
|
||||
} | {
|
||||
type: 'buffer',
|
||||
value: Uint8Array
|
||||
} | {
|
||||
type: 'promise',
|
||||
then: MetaTypeFromRenderer
|
||||
} | {
|
||||
type: 'object',
|
||||
name: string,
|
||||
members: {
|
||||
name: string,
|
||||
value: MetaTypeFromRenderer
|
||||
}[]
|
||||
} | {
|
||||
type: 'function-with-return-value',
|
||||
value: MetaTypeFromRenderer
|
||||
} | {
|
||||
type: 'function',
|
||||
id: number,
|
||||
location: string,
|
||||
length: number
|
||||
} | {
|
||||
type: 'nativeimage',
|
||||
value: {
|
||||
size: Size,
|
||||
buffer: Buffer,
|
||||
scaleFactor: number,
|
||||
dataURL: string
|
||||
}[]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||
const binding = process._linkedBinding('electron_renderer_context_bridge');
|
||||
|
||||
const contextIsolationEnabled = getWebPreference(window, 'contextIsolation');
|
||||
const contextIsolationEnabled = mainFrame.getWebPreference('contextIsolation');
|
||||
|
||||
const checkContextIsolationEnabled = () => {
|
||||
if (!contextIsolationEnabled) throw new Error('contextBridge API can only be used when contextIsolation is enabled');
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
const enableRemoteModule = getWebPreference(window, 'enableRemoteModule');
|
||||
|
||||
// Renderer side modules, please sort alphabetically.
|
||||
export const rendererModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'contextBridge', loader: () => require('./context-bridge') },
|
||||
@@ -17,10 +13,3 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
loader: () => require('@electron/internal/renderer/api/desktop-capturer')
|
||||
});
|
||||
}
|
||||
|
||||
if (BUILDFLAG(ENABLE_REMOTE_MODULE) && enableRemoteModule) {
|
||||
rendererModuleList.push({
|
||||
name: 'remote',
|
||||
loader: () => require('@electron/internal/renderer/api/remote')
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,395 +0,0 @@
|
||||
import { CallbacksRegistry } from '../remote/callbacks-registry';
|
||||
import { isPromise, isSerializableObject, serialize, deserialize } from '../../common/type-utils';
|
||||
import { MetaTypeFromRenderer, ObjectMember, ObjProtoDescriptor, MetaType } from '../../common/remote/types';
|
||||
import { ipcRendererInternal } from '../ipc-renderer-internal';
|
||||
import type { BrowserWindow, WebContents } from 'electron/main';
|
||||
import deprecate from '@electron/internal/common/api/deprecate';
|
||||
import { browserModuleNames } from '@electron/internal/browser/api/module-names';
|
||||
import { commonModuleList } from '@electron/internal/common/api/module-list';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/remote/ipc-messages';
|
||||
|
||||
deprecate.log('The remote module is deprecated. Use https://github.com/electron/remote instead.');
|
||||
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
const callbacksRegistry = new CallbacksRegistry();
|
||||
const remoteObjectCache = new Map();
|
||||
const finalizationRegistry = new FinalizationRegistry((id: number) => {
|
||||
const ref = remoteObjectCache.get(id);
|
||||
if (ref !== undefined && ref.deref() === undefined) {
|
||||
remoteObjectCache.delete(id);
|
||||
ipcRendererInternal.send(IPC_MESSAGES.BROWSER_DEREFERENCE, contextId, id, 0);
|
||||
}
|
||||
});
|
||||
|
||||
const electronIds = new WeakMap<Object, number>();
|
||||
const isReturnValue = new WeakSet<Object>();
|
||||
|
||||
function getCachedRemoteObject (id: number) {
|
||||
const ref = remoteObjectCache.get(id);
|
||||
if (ref !== undefined) {
|
||||
const deref = ref.deref();
|
||||
if (deref !== undefined) return deref;
|
||||
}
|
||||
}
|
||||
function setCachedRemoteObject (id: number, value: any) {
|
||||
const wr = new WeakRef(value);
|
||||
remoteObjectCache.set(id, wr);
|
||||
finalizationRegistry.register(value, id);
|
||||
return value;
|
||||
}
|
||||
|
||||
// An unique ID that can represent current context.
|
||||
const contextId = v8Util.getHiddenValue<string>(global, 'contextId');
|
||||
|
||||
// Notify the main process when current context is going to be released.
|
||||
// Note that when the renderer process is destroyed, the message may not be
|
||||
// sent, we also listen to the "render-view-deleted" event in the main process
|
||||
// to guard that situation.
|
||||
process.on('exit', () => {
|
||||
const command = IPC_MESSAGES.BROWSER_CONTEXT_RELEASE;
|
||||
ipcRendererInternal.send(command, contextId);
|
||||
});
|
||||
|
||||
const IS_REMOTE_PROXY = Symbol('is-remote-proxy');
|
||||
|
||||
// Convert the arguments object into an array of meta data.
|
||||
function wrapArgs (args: any[], visited = new Set()): any {
|
||||
const valueToMeta = (value: any): any => {
|
||||
// Check for circular reference.
|
||||
if (visited.has(value)) {
|
||||
return {
|
||||
type: 'value',
|
||||
value: null
|
||||
};
|
||||
}
|
||||
|
||||
if (value && value.constructor && value.constructor.name === 'NativeImage') {
|
||||
return { type: 'nativeimage', value: serialize(value) };
|
||||
} else if (Array.isArray(value)) {
|
||||
visited.add(value);
|
||||
const meta = {
|
||||
type: 'array',
|
||||
value: wrapArgs(value, visited)
|
||||
};
|
||||
visited.delete(value);
|
||||
return meta;
|
||||
} else if (value instanceof Buffer) {
|
||||
return {
|
||||
type: 'buffer',
|
||||
value
|
||||
};
|
||||
} else if (isSerializableObject(value)) {
|
||||
return {
|
||||
type: 'value',
|
||||
value
|
||||
};
|
||||
} else if (typeof value === 'object') {
|
||||
if (isPromise(value)) {
|
||||
return {
|
||||
type: 'promise',
|
||||
then: valueToMeta(function (onFulfilled: Function, onRejected: Function) {
|
||||
value.then(onFulfilled, onRejected);
|
||||
})
|
||||
};
|
||||
} else if (electronIds.has(value)) {
|
||||
return {
|
||||
type: 'remote-object',
|
||||
id: electronIds.get(value)
|
||||
};
|
||||
}
|
||||
|
||||
const meta: MetaTypeFromRenderer = {
|
||||
type: 'object',
|
||||
name: value.constructor ? value.constructor.name : '',
|
||||
members: []
|
||||
};
|
||||
visited.add(value);
|
||||
for (const prop in value) { // eslint-disable-line guard-for-in
|
||||
meta.members.push({
|
||||
name: prop,
|
||||
value: valueToMeta(value[prop])
|
||||
});
|
||||
}
|
||||
visited.delete(value);
|
||||
return meta;
|
||||
} else if (typeof value === 'function' && isReturnValue.has(value)) {
|
||||
return {
|
||||
type: 'function-with-return-value',
|
||||
value: valueToMeta(value())
|
||||
};
|
||||
} else if (typeof value === 'function') {
|
||||
return {
|
||||
type: 'function',
|
||||
id: callbacksRegistry.add(value),
|
||||
location: callbacksRegistry.getLocation(value),
|
||||
length: value.length
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'value',
|
||||
value
|
||||
};
|
||||
}
|
||||
};
|
||||
return args.map(valueToMeta);
|
||||
}
|
||||
|
||||
// Populate object's members from descriptors.
|
||||
// The |ref| will be kept referenced by |members|.
|
||||
// This matches |getObjectMembers| in rpc-server.
|
||||
function setObjectMembers (ref: any, object: any, metaId: number, members: ObjectMember[]) {
|
||||
if (!Array.isArray(members)) return;
|
||||
|
||||
for (const member of members) {
|
||||
if (Object.prototype.hasOwnProperty.call(object, member.name)) continue;
|
||||
|
||||
const descriptor: PropertyDescriptor = { enumerable: member.enumerable };
|
||||
if (member.type === 'method') {
|
||||
const remoteMemberFunction = function (this: any, ...args: any[]) {
|
||||
let command;
|
||||
if (this && this.constructor === remoteMemberFunction) {
|
||||
command = IPC_MESSAGES.BROWSER_MEMBER_CONSTRUCTOR;
|
||||
} else {
|
||||
command = IPC_MESSAGES.BROWSER_MEMBER_CALL;
|
||||
}
|
||||
const ret = ipcRendererInternal.sendSync(command, contextId, metaId, member.name, wrapArgs(args));
|
||||
return metaToValue(ret);
|
||||
};
|
||||
|
||||
let descriptorFunction = proxyFunctionProperties(remoteMemberFunction, metaId, member.name);
|
||||
|
||||
descriptor.get = () => {
|
||||
descriptorFunction.ref = ref; // The member should reference its object.
|
||||
return descriptorFunction;
|
||||
};
|
||||
// Enable monkey-patch the method
|
||||
descriptor.set = (value) => {
|
||||
descriptorFunction = value;
|
||||
return value;
|
||||
};
|
||||
descriptor.configurable = true;
|
||||
} else if (member.type === 'get') {
|
||||
descriptor.get = () => {
|
||||
const command = IPC_MESSAGES.BROWSER_MEMBER_GET;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, metaId, member.name);
|
||||
return metaToValue(meta);
|
||||
};
|
||||
|
||||
if (member.writable) {
|
||||
descriptor.set = (value) => {
|
||||
const args = wrapArgs([value]);
|
||||
const command = IPC_MESSAGES.BROWSER_MEMBER_SET;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, metaId, member.name, args);
|
||||
if (meta != null) metaToValue(meta);
|
||||
return value;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(object, member.name, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Populate object's prototype from descriptor.
|
||||
// This matches |getObjectPrototype| in rpc-server.
|
||||
function setObjectPrototype (ref: any, object: any, metaId: number, descriptor: ObjProtoDescriptor) {
|
||||
if (descriptor === null) return;
|
||||
const proto = {};
|
||||
setObjectMembers(ref, proto, metaId, descriptor.members);
|
||||
setObjectPrototype(ref, proto, metaId, descriptor.proto);
|
||||
Object.setPrototypeOf(object, proto);
|
||||
}
|
||||
|
||||
// Wrap function in Proxy for accessing remote properties
|
||||
function proxyFunctionProperties (remoteMemberFunction: Function, metaId: number, name: string) {
|
||||
let loaded = false;
|
||||
|
||||
// Lazily load function properties
|
||||
const loadRemoteProperties = () => {
|
||||
if (loaded) return;
|
||||
loaded = true;
|
||||
const command = IPC_MESSAGES.BROWSER_MEMBER_GET;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, metaId, name);
|
||||
setObjectMembers(remoteMemberFunction, remoteMemberFunction, meta.id, meta.members);
|
||||
};
|
||||
|
||||
return new Proxy(remoteMemberFunction as any, {
|
||||
set: (target, property, value) => {
|
||||
if (property !== 'ref') loadRemoteProperties();
|
||||
target[property] = value;
|
||||
return true;
|
||||
},
|
||||
get: (target, property) => {
|
||||
if (property === IS_REMOTE_PROXY) return true;
|
||||
if (!Object.prototype.hasOwnProperty.call(target, property)) loadRemoteProperties();
|
||||
const value = target[property];
|
||||
if (property === 'toString' && typeof value === 'function') {
|
||||
return value.bind(target);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
ownKeys: (target) => {
|
||||
loadRemoteProperties();
|
||||
return Object.getOwnPropertyNames(target);
|
||||
},
|
||||
getOwnPropertyDescriptor: (target, property) => {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(target, property);
|
||||
if (descriptor) return descriptor;
|
||||
loadRemoteProperties();
|
||||
return Object.getOwnPropertyDescriptor(target, property);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Convert meta data from browser into real value.
|
||||
function metaToValue (meta: MetaType): any {
|
||||
if (meta.type === 'value') {
|
||||
return meta.value;
|
||||
} else if (meta.type === 'array') {
|
||||
return meta.members.map((member) => metaToValue(member));
|
||||
} else if (meta.type === 'nativeimage') {
|
||||
return deserialize(meta.value);
|
||||
} else if (meta.type === 'buffer') {
|
||||
return Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength);
|
||||
} else if (meta.type === 'promise') {
|
||||
return Promise.resolve({ then: metaToValue(meta.then) });
|
||||
} else if (meta.type === 'error') {
|
||||
return metaToError(meta);
|
||||
} else if (meta.type === 'exception') {
|
||||
if (meta.value.type === 'error') { throw metaToError(meta.value); } else { throw new Error(`Unexpected value type in exception: ${meta.value.type}`); }
|
||||
} else {
|
||||
let ret;
|
||||
if ('id' in meta) {
|
||||
const cached = getCachedRemoteObject(meta.id);
|
||||
if (cached !== undefined) { return cached; }
|
||||
}
|
||||
|
||||
// A shadow class to represent the remote function object.
|
||||
if (meta.type === 'function') {
|
||||
const remoteFunction = function (this: any, ...args: any[]) {
|
||||
let command;
|
||||
if (this && this.constructor === remoteFunction) {
|
||||
command = IPC_MESSAGES.BROWSER_CONSTRUCTOR;
|
||||
} else {
|
||||
command = IPC_MESSAGES.BROWSER_FUNCTION_CALL;
|
||||
}
|
||||
const obj = ipcRendererInternal.sendSync(command, contextId, meta.id, wrapArgs(args));
|
||||
return metaToValue(obj);
|
||||
};
|
||||
ret = remoteFunction;
|
||||
} else {
|
||||
ret = {};
|
||||
}
|
||||
|
||||
setObjectMembers(ret, ret, meta.id, meta.members);
|
||||
setObjectPrototype(ret, ret, meta.id, meta.proto);
|
||||
if (ret.constructor && (ret.constructor as any)[IS_REMOTE_PROXY]) {
|
||||
Object.defineProperty(ret.constructor, 'name', { value: meta.name });
|
||||
}
|
||||
|
||||
// Track delegate obj's lifetime & tell browser to clean up when object is GCed.
|
||||
electronIds.set(ret, meta.id);
|
||||
setCachedRemoteObject(meta.id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
function metaToError (meta: { type: 'error', value: any, members: ObjectMember[] }) {
|
||||
const obj = meta.value;
|
||||
for (const { name, value } of meta.members) {
|
||||
obj[name] = metaToValue(value);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function handleMessage (channel: string, handler: Function) {
|
||||
ipcRendererInternal.on(channel, (event, passedContextId, id, ...args) => {
|
||||
if (passedContextId === contextId) {
|
||||
handler(id, ...args);
|
||||
} else {
|
||||
// Message sent to an un-exist context, notify the error to main process.
|
||||
ipcRendererInternal.send(IPC_MESSAGES.BROWSER_WRONG_CONTEXT_ERROR, contextId, passedContextId, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const enableStacks = hasSwitch('enable-api-filtering-logging');
|
||||
|
||||
function getCurrentStack (): string | undefined {
|
||||
const target = { stack: undefined as string | undefined };
|
||||
if (enableStacks) {
|
||||
Error.captureStackTrace(target, getCurrentStack);
|
||||
}
|
||||
return target.stack;
|
||||
}
|
||||
|
||||
// Browser calls a callback in renderer.
|
||||
handleMessage(IPC_MESSAGES.RENDERER_CALLBACK, (id: number, args: any) => {
|
||||
callbacksRegistry.apply(id, metaToValue(args));
|
||||
});
|
||||
|
||||
// A callback in browser is released.
|
||||
handleMessage(IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, (id: number) => {
|
||||
callbacksRegistry.remove(id);
|
||||
});
|
||||
|
||||
exports.require = (module: string) => {
|
||||
const command = IPC_MESSAGES.BROWSER_REQUIRE;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, module, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
};
|
||||
|
||||
// Alias to remote.require('electron').xxx.
|
||||
export function getBuiltin (module: string) {
|
||||
const command = IPC_MESSAGES.BROWSER_GET_BUILTIN;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, module, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
}
|
||||
|
||||
export function getCurrentWindow (): BrowserWindow {
|
||||
const command = IPC_MESSAGES.BROWSER_GET_CURRENT_WINDOW;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
}
|
||||
|
||||
// Get current WebContents object.
|
||||
export function getCurrentWebContents (): WebContents {
|
||||
const command = IPC_MESSAGES.BROWSER_GET_CURRENT_WEB_CONTENTS;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
}
|
||||
|
||||
// Get a global object in browser.
|
||||
export function getGlobal<T = any> (name: string): T {
|
||||
const command = IPC_MESSAGES.BROWSER_GET_GLOBAL;
|
||||
const meta = ipcRendererInternal.sendSync(command, contextId, name, getCurrentStack());
|
||||
return metaToValue(meta);
|
||||
}
|
||||
|
||||
// Get the process object in browser.
|
||||
Object.defineProperty(exports, 'process', {
|
||||
get: () => exports.getGlobal('process')
|
||||
});
|
||||
|
||||
// Create a function that will return the specified value when called in browser.
|
||||
export function createFunctionWithReturnValue<T> (returnValue: T): () => T {
|
||||
const func = () => returnValue;
|
||||
isReturnValue.add(func);
|
||||
return func;
|
||||
}
|
||||
|
||||
const addBuiltinProperty = (name: string) => {
|
||||
Object.defineProperty(exports, name, {
|
||||
get: () => exports.getBuiltin(name)
|
||||
});
|
||||
};
|
||||
|
||||
const browserModules = commonModuleList.concat(browserModuleNames.map(name => ({ name, loader: () => {} })));
|
||||
|
||||
// And add a helper receiver for each one.
|
||||
browserModules
|
||||
.filter((m) => !m.private)
|
||||
.map((m) => m.name)
|
||||
.forEach(addBuiltinProperty);
|
||||
@@ -1,84 +1,3 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import deprecate from '@electron/internal/common/api/deprecate';
|
||||
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
const binding = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
class WebFrame extends EventEmitter {
|
||||
constructor (public context: Window) {
|
||||
super();
|
||||
|
||||
// Lots of webview would subscribe to webFrame's events.
|
||||
this.setMaxListeners(0);
|
||||
}
|
||||
|
||||
findFrameByRoutingId (...args: Array<any>) {
|
||||
return getWebFrame(binding._findFrameByRoutingId(this.context, ...args));
|
||||
}
|
||||
|
||||
getFrameForSelector (...args: Array<any>) {
|
||||
return getWebFrame(binding._getFrameForSelector(this.context, ...args));
|
||||
}
|
||||
|
||||
findFrameByName (...args: Array<any>) {
|
||||
return getWebFrame(binding._findFrameByName(this.context, ...args));
|
||||
}
|
||||
|
||||
get opener () {
|
||||
return getWebFrame(binding._getOpener(this.context));
|
||||
}
|
||||
|
||||
get parent () {
|
||||
return getWebFrame(binding._getParent(this.context));
|
||||
}
|
||||
|
||||
get top () {
|
||||
return getWebFrame(binding._getTop(this.context));
|
||||
}
|
||||
|
||||
get firstChild () {
|
||||
return getWebFrame(binding._getFirstChild(this.context));
|
||||
}
|
||||
|
||||
get nextSibling () {
|
||||
return getWebFrame(binding._getNextSibling(this.context));
|
||||
}
|
||||
|
||||
get routingId () {
|
||||
return binding._getRoutingId(this.context);
|
||||
}
|
||||
}
|
||||
|
||||
const contextIsolation = binding.getWebPreference(window, 'contextIsolation');
|
||||
const worldSafeExecuteJavaScript = binding.getWebPreference(window, 'worldSafeExecuteJavaScript');
|
||||
|
||||
const worldSafeJS = worldSafeExecuteJavaScript || !contextIsolation;
|
||||
|
||||
// Populate the methods.
|
||||
for (const name in binding) {
|
||||
if (!name.startsWith('_')) { // some methods are manually populated above
|
||||
// TODO(felixrieseberg): Once we can type web_frame natives, we could
|
||||
// use a neat `keyof` here
|
||||
(WebFrame as any).prototype[name] = function (...args: Array<any>) {
|
||||
if (!worldSafeJS && name.startsWith('executeJavaScript')) {
|
||||
deprecate.log(`Security Warning: webFrame.${name} was called without worldSafeExecuteJavaScript enabled. This is considered unsafe. worldSafeExecuteJavaScript will be enabled by default in Electron 12.`);
|
||||
}
|
||||
return binding[name](this.context, ...args);
|
||||
};
|
||||
// TODO(MarshallOfSound): Remove once the above deprecation is removed
|
||||
if (name.startsWith('executeJavaScript')) {
|
||||
(WebFrame as any).prototype[`_${name}`] = function (...args: Array<any>) {
|
||||
return binding[name](this.context, ...args);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to return WebFrame or null depending on context.
|
||||
// TODO(zcbenz): Consider returning same WebFrame for the same frame.
|
||||
function getWebFrame (context: Window) {
|
||||
return context ? new WebFrame(context) : null;
|
||||
}
|
||||
|
||||
const _webFrame = new WebFrame(window);
|
||||
|
||||
export default _webFrame;
|
||||
export default mainFrame;
|
||||
|
||||
@@ -63,18 +63,18 @@ webFrameInit();
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
const contextIsolation = getWebPreference(window, 'contextIsolation');
|
||||
const nodeIntegration = getWebPreference(window, 'nodeIntegration');
|
||||
const webviewTag = getWebPreference(window, 'webviewTag');
|
||||
const isHiddenPage = getWebPreference(window, 'hiddenPage');
|
||||
const usesNativeWindowOpen = getWebPreference(window, 'nativeWindowOpen');
|
||||
const rendererProcessReuseEnabled = getWebPreference(window, 'disableElectronSiteInstanceOverrides');
|
||||
const preloadScript = getWebPreference(window, 'preload');
|
||||
const preloadScripts = getWebPreference(window, 'preloadScripts');
|
||||
const guestInstanceId = getWebPreference(window, 'guestInstanceId') || null;
|
||||
const openerId = getWebPreference(window, 'openerId') || null;
|
||||
const contextIsolation = mainFrame.getWebPreference('contextIsolation');
|
||||
const nodeIntegration = mainFrame.getWebPreference('nodeIntegration');
|
||||
const webviewTag = mainFrame.getWebPreference('webviewTag');
|
||||
const isHiddenPage = mainFrame.getWebPreference('hiddenPage');
|
||||
const usesNativeWindowOpen = mainFrame.getWebPreference('nativeWindowOpen');
|
||||
const rendererProcessReuseEnabled = mainFrame.getWebPreference('disableElectronSiteInstanceOverrides');
|
||||
const preloadScript = mainFrame.getWebPreference('preload');
|
||||
const preloadScripts = mainFrame.getWebPreference('preloadScripts');
|
||||
const guestInstanceId = mainFrame.getWebPreference('guestInstanceId') || null;
|
||||
const openerId = mainFrame.getWebPreference('openerId') || null;
|
||||
const appPath = hasSwitch('app-path') ? getSwitchValue('app-path') : null;
|
||||
|
||||
// The webContents preload script is loaded after the session preload scripts.
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
export class CallbacksRegistry {
|
||||
private nextId: number = 0
|
||||
private callbacks = new Map<number, Function>()
|
||||
private callbackIds = new WeakMap<Function, number>();
|
||||
private locationInfo = new WeakMap<Function, string>();
|
||||
|
||||
add (callback: Function) {
|
||||
// The callback is already added.
|
||||
let id = this.callbackIds.get(callback);
|
||||
if (id != null) return id;
|
||||
|
||||
id = this.nextId += 1;
|
||||
|
||||
// Capture the location of the function and put it in the ID string,
|
||||
// so that release errors can be tracked down easily.
|
||||
const regexp = /at (.*)/gi;
|
||||
const stackString = (new Error()).stack;
|
||||
if (!stackString) return;
|
||||
|
||||
let filenameAndLine: string;
|
||||
let match;
|
||||
|
||||
while ((match = regexp.exec(stackString)) !== null) {
|
||||
const location = match[1];
|
||||
if (location.includes('(native)')) continue;
|
||||
if (location.includes('(<anonymous>)')) continue;
|
||||
if (location.includes('electron/js2c')) continue;
|
||||
|
||||
const ref = /([^/^)]*)\)?$/gi.exec(location);
|
||||
if (ref) filenameAndLine = ref![1];
|
||||
break;
|
||||
}
|
||||
|
||||
this.callbacks.set(id, callback);
|
||||
this.callbackIds.set(callback, id);
|
||||
this.locationInfo.set(callback, filenameAndLine!);
|
||||
return id;
|
||||
}
|
||||
|
||||
get (id: number) {
|
||||
return this.callbacks.get(id) || function () {};
|
||||
}
|
||||
|
||||
getLocation (callback: Function) {
|
||||
return this.locationInfo.get(callback);
|
||||
}
|
||||
|
||||
apply (id: number, ...args: any[]) {
|
||||
return this.get(id).apply(global, ...args);
|
||||
}
|
||||
|
||||
remove (id: number) {
|
||||
const callback = this.callbacks.get(id);
|
||||
if (callback) {
|
||||
this.callbackIds.delete(callback);
|
||||
this.callbacks.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,8 +78,7 @@ const isLocalhost = function () {
|
||||
* @returns {boolean} Is a CSP with `unsafe-eval` set?
|
||||
*/
|
||||
const isUnsafeEvalEnabled: () => Promise<boolean> = function () {
|
||||
// Call _executeJavaScript to bypass the world-safe deprecation warning
|
||||
return webFrame._executeJavaScript(`(${(() => {
|
||||
return webFrame.executeJavaScript(`(${(() => {
|
||||
try {
|
||||
eval(window.trustedTypes.emptyScript); // eslint-disable-line no-eval
|
||||
} catch {
|
||||
@@ -266,27 +265,6 @@ const warnAboutAllowedPopups = function () {
|
||||
// #13 Disable or limit creation of new windows
|
||||
// #14 Do not use `openExternal` with untrusted content
|
||||
|
||||
// #15 on the checklist: Disable the `remote` module
|
||||
// Logs a warning message about the remote module
|
||||
|
||||
const warnAboutRemoteModuleWithRemoteContent = function (webPreferences?: Electron.WebPreferences) {
|
||||
if (!webPreferences || isLocalhost()) return;
|
||||
const remoteModuleEnabled = webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : true;
|
||||
if (!remoteModuleEnabled) return;
|
||||
|
||||
if (getIsRemoteProtocol()) {
|
||||
const warning = `This renderer process has "enableRemoteModule" enabled
|
||||
and attempted to load remote content from '${window.location}'. This
|
||||
exposes users of this app to unnecessary security risks.\n${moreInformation}`;
|
||||
|
||||
console.warn('%cElectron Security Warning (enableRemoteModule)',
|
||||
'font-weight: bold;', warning);
|
||||
}
|
||||
};
|
||||
|
||||
// Currently missing since we can't easily programmatically check for it:
|
||||
// #16 Filter the `remote` module
|
||||
|
||||
const logSecurityWarnings = function (
|
||||
webPreferences: Electron.WebPreferences | undefined, nodeIntegration: boolean
|
||||
) {
|
||||
@@ -298,7 +276,6 @@ const logSecurityWarnings = function (
|
||||
warnAboutEnableBlinkFeatures(webPreferences);
|
||||
warnAboutInsecureCSP();
|
||||
warnAboutAllowedPopups();
|
||||
warnAboutRemoteModuleWithRemoteContent(webPreferences);
|
||||
};
|
||||
|
||||
const getWebPreferences = async function () {
|
||||
|
||||
@@ -13,11 +13,6 @@ export const webFrameInit = () => {
|
||||
ipcRendererUtils.handle(IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, (
|
||||
event, method: keyof WebFrameMethod, ...args: any[]
|
||||
) => {
|
||||
// TODO(MarshallOfSound): Remove once the world-safe-execute-javascript deprecation warning is removed
|
||||
if (method.startsWith('executeJavaScript')) {
|
||||
return (webFrame as any)[`_${method}`](...args);
|
||||
}
|
||||
|
||||
// The TypeScript compiler cannot handle the sheer number of
|
||||
// call signatures here and simply gives up. Incorrect invocations
|
||||
// will be caught by "keyof WebFrameMethod" though.
|
||||
|
||||
@@ -3,13 +3,8 @@ import { WebViewImpl } from '@electron/internal/renderer/web-view/web-view-impl'
|
||||
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
// Helper function to resolve url set in attribute.
|
||||
const a = document.createElement('a');
|
||||
|
||||
const resolveURL = function (url?: string | null) {
|
||||
if (!url) return '';
|
||||
a.href = url;
|
||||
return a.href;
|
||||
return url ? new URL(url, location.href).href : '';
|
||||
};
|
||||
|
||||
interface MutationHandler {
|
||||
@@ -259,20 +254,6 @@ class WebPreferencesAttribute extends WebViewAttribute {
|
||||
}
|
||||
}
|
||||
|
||||
class EnableRemoteModuleAttribute extends WebViewAttribute {
|
||||
constructor (webViewImpl: WebViewImpl) {
|
||||
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, webViewImpl);
|
||||
}
|
||||
|
||||
public getValue () {
|
||||
return this.webViewImpl.webviewNode.getAttribute(this.name) !== 'false';
|
||||
}
|
||||
|
||||
public setValue (value: any) {
|
||||
this.webViewImpl.webviewNode.setAttribute(this.name, value ? 'true' : 'false');
|
||||
}
|
||||
}
|
||||
|
||||
// Sets up all of the webview attributes.
|
||||
WebViewImpl.prototype.setupWebViewAttributes = function () {
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION, new PartitionAttribute(this));
|
||||
@@ -284,7 +265,6 @@ WebViewImpl.prototype.setupWebViewAttributes = function () {
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, new EnableRemoteModuleAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD, new PreloadAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES, new BlinkFeaturesAttribute(this));
|
||||
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES, new DisableBlinkFeaturesAttribute(this));
|
||||
|
||||
@@ -6,7 +6,6 @@ export const enum WEB_VIEW_CONSTANTS {
|
||||
ATTRIBUTE_HTTPREFERRER = 'httpreferrer',
|
||||
ATTRIBUTE_NODEINTEGRATION = 'nodeintegration',
|
||||
ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES = 'nodeintegrationinsubframes',
|
||||
ATTRIBUTE_ENABLEREMOTEMODULE = 'enableremotemodule',
|
||||
ATTRIBUTE_PLUGINS = 'plugins',
|
||||
ATTRIBUTE_DISABLEWEBSECURITY = 'disablewebsecurity',
|
||||
ATTRIBUTE_ALLOWPOPUPS = 'allowpopups',
|
||||
|
||||
@@ -29,7 +29,6 @@ const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof
|
||||
WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS,
|
||||
WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY,
|
||||
WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS,
|
||||
WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE,
|
||||
WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD,
|
||||
WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES,
|
||||
WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES,
|
||||
|
||||
@@ -270,7 +270,24 @@ export const windowSetup = (
|
||||
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['open'], window.open);
|
||||
}
|
||||
|
||||
if (openerId != null) {
|
||||
// If this window uses nativeWindowOpen, but its opener window does not, we
|
||||
// need to proxy window.opener in order to let the page communicate with its
|
||||
// opener.
|
||||
// Additionally, windows opened from a nativeWindowOpen child of a
|
||||
// non-nativeWindowOpen parent will initially have their WebPreferences
|
||||
// copied from their opener before having them updated, meaning openerId is
|
||||
// initially incorrect. We detect this situation by checking for
|
||||
// window.opener, which will be non-null for a natively-opened child, so we
|
||||
// can ignore the openerId in that case, since it's incorrectly copied from
|
||||
// the parent. This is, uh, confusing, so here's a diagram that will maybe
|
||||
// help?
|
||||
//
|
||||
// [ grandparent window ] --> [ parent window ] --> [ child window ]
|
||||
// n.W.O = false n.W.O = true n.W.O = true
|
||||
// id = 1 id = 2 id = 3
|
||||
// openerId = null openerId = 1 openerId = 1 <- !!wrong!!
|
||||
// opener = null opener = null opener = [parent window]
|
||||
if (openerId != null && !window.opener) {
|
||||
window.opener = getOrCreateProxy(openerId);
|
||||
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['opener'], window.opener);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
const enableRemoteModule = getWebPreference(window, 'enableRemoteModule');
|
||||
|
||||
export const moduleList: ElectronInternal.ModuleEntry[] = [
|
||||
{
|
||||
name: 'contextBridge',
|
||||
@@ -37,10 +33,3 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
loader: () => require('@electron/internal/renderer/api/desktop-capturer')
|
||||
});
|
||||
}
|
||||
|
||||
if (BUILDFLAG(ENABLE_REMOTE_MODULE) && enableRemoteModule) {
|
||||
moduleList.push({
|
||||
name: 'remote',
|
||||
loader: () => require('@electron/internal/renderer/api/remote')
|
||||
});
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ function preloadRequire (module: string) {
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
||||
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||
|
||||
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
||||
// that tests can call it to get access to some test only bindings
|
||||
@@ -121,13 +121,13 @@ if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
preloadProcess._linkedBinding = process._linkedBinding;
|
||||
}
|
||||
|
||||
const contextIsolation = getWebPreference(window, 'contextIsolation');
|
||||
const webviewTag = getWebPreference(window, 'webviewTag');
|
||||
const isHiddenPage = getWebPreference(window, 'hiddenPage');
|
||||
const rendererProcessReuseEnabled = getWebPreference(window, 'disableElectronSiteInstanceOverrides');
|
||||
const contextIsolation = mainFrame.getWebPreference('contextIsolation');
|
||||
const webviewTag = mainFrame.getWebPreference('webviewTag');
|
||||
const isHiddenPage = mainFrame.getWebPreference('hiddenPage');
|
||||
const rendererProcessReuseEnabled = mainFrame.getWebPreference('disableElectronSiteInstanceOverrides');
|
||||
const usesNativeWindowOpen = true;
|
||||
const guestInstanceId = getWebPreference(window, 'guestInstanceId') || null;
|
||||
const openerId = getWebPreference(window, 'openerId') || null;
|
||||
const guestInstanceId = mainFrame.getWebPreference('guestInstanceId') || null;
|
||||
const openerId = mainFrame.getWebPreference('openerId') || null;
|
||||
|
||||
switch (window.location.protocol) {
|
||||
case 'devtools:': {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "13.0.0-beta.6",
|
||||
"version": "14.0.0-nightly.20210426",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@electron/docs-parser": "^0.10.1",
|
||||
"@electron/typescript-definitions": "^8.8.0",
|
||||
"@electron/docs-parser": "^0.11.0",
|
||||
"@electron/typescript-definitions": "^8.9.0",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
"@octokit/rest": "^18.0.3",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
expose_ripemd160.patch
|
||||
expose_aes-cfb.patch
|
||||
expose_des-ede3.patch
|
||||
|
||||
@@ -57,7 +57,7 @@ index 53cb9d2dc8f1962a70dc12b648d27c32be8aca4b..84af06fc56e4aa72d4d48801d7c037ad
|
||||
callback(EVP_aes_192_ctr(), "aes-192-ctr", NULL, arg);
|
||||
callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg);
|
||||
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
|
||||
index c6bec489b51ca2e71b7f81e64a8e59b534e2e91a..512a9003164e65bd4ab896ef75b173dab3a8d1db 100644
|
||||
index badd496293fb9748adacff10478ea702d1155c5f..8565934bac9a810281b04946cb9f38d7623320f7 100644
|
||||
--- a/include/openssl/cipher.h
|
||||
+++ b/include/openssl/cipher.h
|
||||
@@ -430,6 +430,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
|
||||
|
||||
40
patches/boringssl/expose_des-ede3.patch
Normal file
40
patches/boringssl/expose_des-ede3.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Rose <nornagon@nornagon.net>
|
||||
Date: Wed, 24 Feb 2021 11:08:34 -0800
|
||||
Subject: expose des-ede3
|
||||
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/crypto/cipher_extra/cipher_extra.c b/crypto/cipher_extra/cipher_extra.c
|
||||
index 588a4773437c311877f275bf3679f9688cda3c46..e771ed6589b4579cc35300d5b2a1b68d92e444f5 100644
|
||||
--- a/crypto/cipher_extra/cipher_extra.c
|
||||
+++ b/crypto/cipher_extra/cipher_extra.c
|
||||
@@ -93,6 +93,8 @@ const EVP_CIPHER *EVP_get_cipherbyname(const char *name) {
|
||||
return EVP_rc4();
|
||||
} else if (OPENSSL_strcasecmp(name, "des-cbc") == 0) {
|
||||
return EVP_des_cbc();
|
||||
+ } else if (OPENSSL_strcasecmp(name, "des-ede3") == 0) {
|
||||
+ return EVP_des_ede3();
|
||||
} else if (OPENSSL_strcasecmp(name, "des-ede3-cbc") == 0 ||
|
||||
// This is not a name used by OpenSSL, but tcpdump registers it
|
||||
// with |EVP_add_cipher_alias|. Our |EVP_add_cipher_alias| is a
|
||||
diff --git a/decrepit/evp/evp_do_all.c b/decrepit/evp/evp_do_all.c
|
||||
index 84af06fc56e4aa72d4d48801d7c037add0221747..fe412e350f43ad20758025da6b9754952d164938 100644
|
||||
--- a/decrepit/evp/evp_do_all.c
|
||||
+++ b/decrepit/evp/evp_do_all.c
|
||||
@@ -39,6 +39,7 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
|
||||
callback(EVP_des_cbc(), "DES-CBC", NULL, arg);
|
||||
callback(EVP_des_ecb(), "DES-ECB", NULL, arg);
|
||||
callback(EVP_des_ede(), "DES-EDE", NULL, arg);
|
||||
+ callback(EVP_des_ede3(), "DES-EDE3", NULL, arg);
|
||||
callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg);
|
||||
callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg);
|
||||
callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg);
|
||||
@@ -65,6 +66,7 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
|
||||
callback(EVP_des_cbc(), "des-cbc", NULL, arg);
|
||||
callback(EVP_des_ecb(), "des-ecb", NULL, arg);
|
||||
callback(EVP_des_ede(), "des-ede", NULL, arg);
|
||||
+ callback(EVP_des_ede3(), "des-ede3", NULL, arg);
|
||||
callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg);
|
||||
callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg);
|
||||
callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg);
|
||||
@@ -41,7 +41,6 @@ proxy_config_monitor.patch
|
||||
gritsettings_resource_ids.patch
|
||||
isolate_holder.patch
|
||||
notification_provenance.patch
|
||||
content_browser_main_loop.patch
|
||||
dump_syms.patch
|
||||
command-ismediakey.patch
|
||||
printing.patch
|
||||
@@ -50,7 +49,6 @@ fix_disable_usage_of_abort_report_np_in_mas_builds.patch
|
||||
fix_disable_usage_of_pthread_fchdir_np_and_pthread_chdir_np_in_mas.patch
|
||||
fix_disable_usage_of_setapplicationisdaemon_and.patch
|
||||
unsandboxed_ppapi_processes_skip_zygote.patch
|
||||
patch_the_ensure_gn_version_py_script_to_work_on_mac_ci.patch
|
||||
build_add_electron_tracing_category.patch
|
||||
worker_context_will_destroy.patch
|
||||
frame_host_manager.patch
|
||||
@@ -100,12 +98,12 @@ fix_use_electron_generated_resources.patch
|
||||
chore_expose_v8_initialization_isolate_callbacks.patch
|
||||
export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch
|
||||
use_public_apis_to_determine_if_a_font_is_a_system_font_in_mas_build.patch
|
||||
fix_setparentacessibile_crash_win.patch
|
||||
fix_export_zlib_symbols.patch
|
||||
don_t_use_potentially_null_getwebframe_-_view_when_get_blink.patch
|
||||
web_contents.patch
|
||||
add_trustedauthclient_to_urlloaderfactory.patch
|
||||
fix_route_mouse_event_navigations_through_the_web_contents_delegate.patch
|
||||
disable_unload_metrics.patch
|
||||
fix_add_check_for_sandbox_then_result.patch
|
||||
moves_background_color_setter_of_webview_to_blinks_webprefs_logic.patch
|
||||
fix_expose_decrementcapturercount_in_web_contents_impl.patch
|
||||
add_setter_for_browsermainloop_result_code.patch
|
||||
|
||||
@@ -10,28 +10,28 @@ This patch makes three changes to Accelerator::GetShortcutText to improve shortc
|
||||
3. Ctrl-Shift-= should show as Ctrl-+
|
||||
|
||||
diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc
|
||||
index 17e1739c12ee38864e735130792321adadb43f08..7b0bfec6f18e883eb7ad7e3bfe564163592f584e 100644
|
||||
index d6913b15149f773cad28b5e2278b0f80df3d2896..15f944c4bb2fde7241b643f6a979a81ebce844b1 100644
|
||||
--- a/ui/base/accelerators/accelerator.cc
|
||||
+++ b/ui/base/accelerators/accelerator.cc
|
||||
@@ -12,6 +12,7 @@
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "base/i18n/rtl.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/strings/string_util.h"
|
||||
+#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
#include "build/chromeos_buildflags.h"
|
||||
@@ -24,9 +25,7 @@
|
||||
@@ -27,9 +28,7 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
-#if !defined(OS_WIN) && (defined(USE_AURA) || defined(OS_APPLE))
|
||||
-#if !defined(OS_WIN) && (defined(USE_AURA) || defined(OS_MAC))
|
||||
#include "ui/events/keycodes/keyboard_code_conversion.h"
|
||||
-#endif
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
#if defined(OS_CHROMEOS)
|
||||
#include "ui/base/ui_base_features.h"
|
||||
@@ -205,7 +204,15 @@ base::string16 Accelerator::GetShortcutText() const {
|
||||
@@ -233,7 +232,15 @@ std::u16string Accelerator::GetShortcutText() const {
|
||||
shortcut = KeyCodeToName();
|
||||
#endif
|
||||
|
||||
@@ -41,13 +41,13 @@ index 17e1739c12ee38864e735130792321adadb43f08..7b0bfec6f18e883eb7ad7e3bfe564163
|
||||
+ UsLayoutKeyboardCodeToDomCode(key_code_), flags);
|
||||
+ if (c != 0) {
|
||||
+ shortcut =
|
||||
+ static_cast<base::string16::value_type>(
|
||||
+ base::ToUpperASCII(static_cast<base::char16>(c)));
|
||||
+ static_cast<std::u16string::value_type>(
|
||||
+ base::ToUpperASCII(static_cast<char16_t>(c)));
|
||||
+ }
|
||||
#if defined(OS_WIN)
|
||||
// Our fallback is to try translate the key code to a regular character
|
||||
// unless it is one of digits (VK_0 to VK_9). Some keyboard
|
||||
@@ -214,21 +221,14 @@ base::string16 Accelerator::GetShortcutText() const {
|
||||
@@ -242,21 +249,14 @@ std::u16string Accelerator::GetShortcutText() const {
|
||||
// accent' for '0'). For display in the menu (e.g. Ctrl-0 for the
|
||||
// default zoom level), we leave VK_[0-9] alone without translation.
|
||||
wchar_t key;
|
||||
@@ -60,12 +60,12 @@ index 17e1739c12ee38864e735130792321adadb43f08..7b0bfec6f18e883eb7ad7e3bfe564163
|
||||
- // VKEY_UNKNOWN), |::MapVirtualKeyW| returns 0.
|
||||
- if (key != 0)
|
||||
- shortcut += key;
|
||||
-#elif defined(USE_AURA) || defined(OS_APPLE) || defined(OS_ANDROID)
|
||||
-#elif defined(USE_AURA) || defined(OS_MAC) || defined(OS_ANDROID)
|
||||
- const uint16_t c = DomCodeToUsLayoutCharacter(
|
||||
- UsLayoutKeyboardCodeToDomCode(key_code_), false);
|
||||
- if (c != 0)
|
||||
- shortcut +=
|
||||
- static_cast<base::string16::value_type>(base::ToUpperASCII(c));
|
||||
- static_cast<std::u16string::value_type>(base::ToUpperASCII(c));
|
||||
+ shortcut = key;
|
||||
+ }
|
||||
#endif
|
||||
@@ -74,13 +74,13 @@ index 17e1739c12ee38864e735130792321adadb43f08..7b0bfec6f18e883eb7ad7e3bfe564163
|
||||
+ base::StringPrintf("F%d", key_code_ - VKEY_F1 + 1));
|
||||
}
|
||||
|
||||
#if defined(OS_APPLE)
|
||||
@@ -411,7 +411,7 @@ base::string16 Accelerator::ApplyLongFormModifiers(
|
||||
#if defined(OS_MAC)
|
||||
@@ -452,7 +452,7 @@ std::u16string Accelerator::ApplyLongFormModifiers(
|
||||
// more information.
|
||||
if (IsCtrlDown())
|
||||
shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_CTRL_KEY);
|
||||
result = ApplyModifierToAcceleratorString(result, IDS_APP_CTRL_KEY);
|
||||
- else if (IsAltDown())
|
||||
+ if (IsAltDown())
|
||||
shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_ALT_KEY);
|
||||
result = ApplyModifierToAcceleratorString(result, IDS_APP_ALT_KEY);
|
||||
|
||||
if (IsCmdDown()) {
|
||||
|
||||
@@ -10,10 +10,10 @@ Allows Electron to restore WER when ELECTRON_DEFAULT_ERROR_MODE is set.
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
|
||||
index 5bcbb68864ed193a519b34a37f1e50c29422235a..c33f108158538c49f9d4d27b8fa89852e829c787 100644
|
||||
index b3afa0e60f45a10cfe97b129996e1d9489b09a7d..24984b2be369908d72a9493ebb0fa0f9c3e5fc7e 100644
|
||||
--- a/content/gpu/gpu_main.cc
|
||||
+++ b/content/gpu/gpu_main.cc
|
||||
@@ -261,6 +261,10 @@ int GpuMain(const MainFunctionParams& parameters) {
|
||||
@@ -265,6 +265,10 @@ int GpuMain(const MainFunctionParams& parameters) {
|
||||
// to the GpuProcessHost once the GpuServiceImpl has started.
|
||||
viz::GpuServiceImpl::InstallPreInitializeLogHandler();
|
||||
|
||||
@@ -24,7 +24,7 @@ index 5bcbb68864ed193a519b34a37f1e50c29422235a..c33f108158538c49f9d4d27b8fa89852
|
||||
// We are experiencing what appear to be memory-stomp issues in the GPU
|
||||
// process. These issues seem to be impacting the task executor and listeners
|
||||
// registered to it. Create the task executor on the heap to guard against
|
||||
@@ -398,7 +402,6 @@ int GpuMain(const MainFunctionParams& parameters) {
|
||||
@@ -402,7 +406,6 @@ int GpuMain(const MainFunctionParams& parameters) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ DidCreateScriptContext is called, not all JS APIs are available in the
|
||||
context, which can cause some preload scripts to trip.
|
||||
|
||||
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
|
||||
index 7d2ebf0d8a14fd89e32e35631428f43aed259c16..8efabb6b7825f6fab019d7f83e185a953bb589f1 100644
|
||||
index 5a733f2086ec10d3010da52a2758e1748d1178e1..d8c7ef2e3c03f5275c1ed58849ec892f811165ef 100644
|
||||
--- a/content/public/renderer/render_frame_observer.h
|
||||
+++ b/content/public/renderer/render_frame_observer.h
|
||||
@@ -126,6 +126,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
|
||||
@@ -128,6 +128,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
|
||||
virtual void DidHandleOnloadEvents() {}
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
int32_t world_id) {}
|
||||
@@ -23,10 +23,10 @@ index 7d2ebf0d8a14fd89e32e35631428f43aed259c16..8efabb6b7825f6fab019d7f83e185a95
|
||||
int32_t world_id) {}
|
||||
virtual void DidClearWindowObject() {}
|
||||
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
||||
index f1d33694d94b7a0c8f839b512b7680fc9493e5f2..49b0d9012c43661a4fb4b9b8b8a68c156c7a76b6 100644
|
||||
index dc954f7ddb115da018064437c485f91303ca9502..b04ffbc51f260e63c4217c060e87062eb301ead5 100644
|
||||
--- a/content/renderer/render_frame_impl.cc
|
||||
+++ b/content/renderer/render_frame_impl.cc
|
||||
@@ -4543,6 +4543,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
@@ -4536,6 +4536,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
observer.DidCreateScriptContext(context, world_id);
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ index f1d33694d94b7a0c8f839b512b7680fc9493e5f2..49b0d9012c43661a4fb4b9b8b8a68c15
|
||||
int world_id) {
|
||||
for (auto& observer : observers_)
|
||||
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
|
||||
index 64d7f76d2b1570ba8a4ad51362ad6932eb50c7cd..0fcd2204f09c512da27632dcbfd366ac330b1f0a 100644
|
||||
index 4b9ab61b17e0fa277b00daebc71cd1cbc24ce5ce..77a5f522ba70780dedfc324abc98db6775b9eca5 100644
|
||||
--- a/content/renderer/render_frame_impl.h
|
||||
+++ b/content/renderer/render_frame_impl.h
|
||||
@@ -589,6 +589,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
@@ -579,6 +579,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
|
||||
void DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
int world_id) override;
|
||||
@@ -53,10 +53,10 @@ index 64d7f76d2b1570ba8a4ad51362ad6932eb50c7cd..0fcd2204f09c512da27632dcbfd366ac
|
||||
int world_id) override;
|
||||
void DidChangeScrollOffset() override;
|
||||
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
|
||||
index 609eb34fcde080491f9f6a1b10a71daf7c46e11e..e22da080595a7474e1277d5c7526a92461417357 100644
|
||||
index 883f83327a5b04ad56d82b91e1c7d8fa674324b1..2b7d8e13dcde8cd916c1d0a804883415b2b23a16 100644
|
||||
--- a/third_party/blink/public/web/web_local_frame_client.h
|
||||
+++ b/third_party/blink/public/web/web_local_frame_client.h
|
||||
@@ -567,6 +567,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
@@ -570,6 +570,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {}
|
||||
|
||||
@@ -67,7 +67,7 @@ index 609eb34fcde080491f9f6a1b10a71daf7c46e11e..e22da080595a7474e1277d5c7526a924
|
||||
virtual void WillReleaseScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {}
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
index be5cf4457cd379d5abc119d209d2df6520ad1022..8a0baac5bb8cb403324fb8156be62b924d6d3d1a 100644
|
||||
index 50aa1b94ac6aab922f570d78f06096226d428c33..7af7ad0b7ed50dfc1ac061a915d3a99291afaec4 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
@@ -188,6 +188,7 @@ void LocalWindowProxy::Initialize() {
|
||||
@@ -79,10 +79,10 @@ index be5cf4457cd379d5abc119d209d2df6520ad1022..8a0baac5bb8cb403324fb8156be62b92
|
||||
if (World().IsMainWorld()) {
|
||||
GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
index 9a526ac4808171693146870909e058f41fe56a50..a15e379ee951504fd77b27af61b318d266274b3d 100644
|
||||
index 6a581fd26b67097cf82d9cca9c11516db8c7ec04..8cdbacf5ce72faf0aaa034b36b824ce9c9235e31 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
@@ -294,6 +294,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
@@ -296,6 +296,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) = 0;
|
||||
@@ -92,10 +92,10 @@ index 9a526ac4808171693146870909e058f41fe56a50..a15e379ee951504fd77b27af61b318d2
|
||||
int32_t world_id) = 0;
|
||||
virtual bool AllowScriptExtensions() = 0;
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
index e7e9fa3faf605bea1bf90d31d699c5b2c5510502..03fdd09c6dc23f21f7f52ccf30ee8202e304f355 100644
|
||||
index 37698d003248e800d4312a2fa043b8124fc7848d..8d98d11a0f8da14a243e4eb0e0f1ac2a4eb56506 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
@@ -273,6 +273,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
|
||||
@@ -272,6 +272,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
|
||||
web_frame_->Client()->DidCreateScriptContext(context, world_id);
|
||||
}
|
||||
|
||||
@@ -110,10 +110,10 @@ index e7e9fa3faf605bea1bf90d31d699c5b2c5510502..03fdd09c6dc23f21f7f52ccf30ee8202
|
||||
v8::Local<v8::Context> context,
|
||||
int32_t world_id) {
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
index 28d83f87c1582c8df6209f5d0a9aef130f0a4bea..3822c88091dfc803c4c57256e04bbc3946f8a869 100644
|
||||
index 92f875eafc84a46aff388a1164d45c6acee707c0..11845b9e14ccff6ef565f4bdc3af8924d6cb05a3 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
@@ -76,6 +76,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
|
||||
@@ -77,6 +77,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
|
||||
|
||||
void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) override;
|
||||
@@ -123,10 +123,10 @@ index 28d83f87c1582c8df6209f5d0a9aef130f0a4bea..3822c88091dfc803c4c57256e04bbc39
|
||||
int32_t world_id) override;
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
index 3e442a5ddf1dd775febd433e2adb4795a3e5edec..22b5d7fbc3f09ea677444adbd8cae2ecd205b037 100644
|
||||
index 9f9e6c6188d1f108f584b1117a91fc3e9a5e38ab..05330ea84dc1555bcc9dd6fbbd63e97348b5664d 100644
|
||||
--- a/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
@@ -337,6 +337,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
@@ -343,6 +343,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
|
||||
void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) override {}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user