mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
105 Commits
v16.0.0-ni
...
v16.0.0-al
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8b4dc98b9 | ||
|
|
79108c7acd | ||
|
|
b0273b96c1 | ||
|
|
f7dd18466b | ||
|
|
80175c5828 | ||
|
|
2a36199b35 | ||
|
|
f5c2bab02b | ||
|
|
acca212814 | ||
|
|
ebbaa3b352 | ||
|
|
c42ed97535 | ||
|
|
cec707ce67 | ||
|
|
0080a61c1d | ||
|
|
2f543c3fd4 | ||
|
|
f6da3b43c2 | ||
|
|
6029315e1a | ||
|
|
f6748f9795 | ||
|
|
6500bcbb32 | ||
|
|
a75617bff1 | ||
|
|
3ef74abfe4 | ||
|
|
70c534fd14 | ||
|
|
52bacd38a9 | ||
|
|
dbd18d8562 | ||
|
|
4fcc0884f8 | ||
|
|
ee19e5ee48 | ||
|
|
629d8913f6 | ||
|
|
92bff00d43 | ||
|
|
e38a0a67c6 | ||
|
|
82da4b0090 | ||
|
|
6dd33b75b2 | ||
|
|
a96f42ce86 | ||
|
|
efa70131e2 | ||
|
|
6fdf350bea | ||
|
|
8d8fcd88f5 | ||
|
|
ad98f4707f | ||
|
|
4576d9d23e | ||
|
|
64c70c420f | ||
|
|
b491a4c82f | ||
|
|
c5b517d89f | ||
|
|
9c4e3b67fb | ||
|
|
93068cfab5 | ||
|
|
c8e4cc29c0 | ||
|
|
9eaa9de3b4 | ||
|
|
664a452fb6 | ||
|
|
54b44584fa | ||
|
|
1295ba0ffc | ||
|
|
02ac33c4cd | ||
|
|
87050d75b8 | ||
|
|
00d0265782 | ||
|
|
c74b9ff312 | ||
|
|
b6a12a53e3 | ||
|
|
06b3b49214 | ||
|
|
c556ccac08 | ||
|
|
fb539f15d0 | ||
|
|
57d088517c | ||
|
|
fcad531f2e | ||
|
|
eb955af459 | ||
|
|
9dee1183f9 | ||
|
|
9891ff14a7 | ||
|
|
22abbf76fb | ||
|
|
90a3e7f927 | ||
|
|
55c57808fb | ||
|
|
ee33374675 | ||
|
|
6a1726576d | ||
|
|
64e33002f8 | ||
|
|
fb40065c1e | ||
|
|
ce6a71e936 | ||
|
|
57e3c25378 | ||
|
|
1546cb6e6c | ||
|
|
f39ba9281c | ||
|
|
8b7631228f | ||
|
|
4a2f41ee58 | ||
|
|
7379e5eb36 | ||
|
|
26f981fa3e | ||
|
|
99c0a723fd | ||
|
|
94ca57e296 | ||
|
|
1dcb8a370e | ||
|
|
e6f781f403 | ||
|
|
b8372f20a0 | ||
|
|
92222c874f | ||
|
|
c30303207a | ||
|
|
873872a32b | ||
|
|
5554de0237 | ||
|
|
ee0e15a52e | ||
|
|
6d4995ec17 | ||
|
|
8d86d84ff5 | ||
|
|
fd8eb3de1b | ||
|
|
4d89174b41 | ||
|
|
49e62f1261 | ||
|
|
e6802bf935 | ||
|
|
ad776d6113 | ||
|
|
f533c44912 | ||
|
|
63b35403ef | ||
|
|
399032252f | ||
|
|
dd7aeda6fb | ||
|
|
3b2db5f168 | ||
|
|
c1075debf3 | ||
|
|
88ff3a6a9a | ||
|
|
8007d01874 | ||
|
|
c2da4ec2bc | ||
|
|
aa9da78edb | ||
|
|
352ac21413 | ||
|
|
96131af5d3 | ||
|
|
f9c6f9af83 | ||
|
|
00d65eb9ac | ||
|
|
a9983c1d06 |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -16,3 +16,4 @@ DEPS @electron/wg-upgrades
|
||||
/lib/browser/guest-view-manager.ts @electron/wg-security
|
||||
/lib/browser/guest-window-proxy.ts @electron/wg-security
|
||||
/lib/browser/rpc-server.ts @electron/wg-security
|
||||
/lib/renderer/security-warnings.ts @electron/wg-security
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -8,9 +8,9 @@ body:
|
||||
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.
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/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.
|
||||
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/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
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
6
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -8,9 +8,9 @@ body:
|
||||
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.
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/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.
|
||||
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/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
|
||||
@@ -37,4 +37,4 @@ body:
|
||||
label: Additional Information
|
||||
description: Add any other context about the problem here.
|
||||
validations:
|
||||
required: true
|
||||
required: false
|
||||
|
||||
@@ -7,9 +7,9 @@ body:
|
||||
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.
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/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.
|
||||
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
|
||||
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -3,7 +3,7 @@
|
||||
Thank you for your Pull Request. Please provide a description above and review
|
||||
the requirements below.
|
||||
|
||||
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
|
||||
Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
|
||||
-->
|
||||
|
||||
#### Checklist
|
||||
@@ -11,7 +11,7 @@ Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTIN
|
||||
|
||||
- [ ] PR description included and stakeholders cc'd
|
||||
- [ ] `npm test` passes
|
||||
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/master/docs/development/testing.md)
|
||||
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
|
||||
- [ ] relevant documentation is changed or added
|
||||
- [ ] [PR release notes](https://github.com/electron/clerk/blob/master/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/master/README.md#examples).
|
||||
|
||||
|
||||
6
.github/config.yml
vendored
6
.github/config.yml
vendored
@@ -2,7 +2,7 @@
|
||||
newPRWelcomeComment: |
|
||||
💖 Thanks for opening this pull request! 💖
|
||||
|
||||
We use [semantic commit messages](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix.
|
||||
We use [semantic commit messages](https://github.com/electron/electron/blob/main/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix.
|
||||
|
||||
Examples of commit messages with semantic prefixes:
|
||||
|
||||
@@ -12,9 +12,9 @@ newPRWelcomeComment: |
|
||||
|
||||
Things that will help get your PR across the finish line:
|
||||
|
||||
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
|
||||
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/main/docs/development/coding-style.md).
|
||||
- Run `npm run lint` locally to catch formatting errors earlier.
|
||||
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/master/docs/styleguide.md).
|
||||
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/main/docs/styleguide.md).
|
||||
- Include tests when adding/changing behavior.
|
||||
- Include screenshots and animated GIFs whenever possible.
|
||||
|
||||
|
||||
10
BUILD.gn
10
BUILD.gn
@@ -379,6 +379,7 @@ source_set("electron_lib") {
|
||||
"//ppapi/shared_impl",
|
||||
"//printing/buildflags",
|
||||
"//services/device/public/cpp/geolocation",
|
||||
"//services/device/public/cpp/hid",
|
||||
"//services/device/public/mojom",
|
||||
"//services/proxy_resolver:lib",
|
||||
"//services/video_capture/public/mojom:constants",
|
||||
@@ -1024,6 +1025,12 @@ if (is_mac) {
|
||||
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
asar_hashed_info_plist("electron_app_plist") {
|
||||
keys = [ "DEFAULT_APP_ASAR_HEADER_SHA" ]
|
||||
hash_targets = [ ":default_app_asar_header_hash" ]
|
||||
plist_file = "shell/browser/resources/mac/Info.plist"
|
||||
}
|
||||
|
||||
mac_app_bundle("electron_app") {
|
||||
output_name = electron_product_name
|
||||
sources = filenames.app_sources
|
||||
@@ -1031,6 +1038,7 @@ if (is_mac) {
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":electron_app_framework_bundle_data",
|
||||
":electron_app_plist",
|
||||
":electron_app_resources",
|
||||
":electron_fuses",
|
||||
"//base",
|
||||
@@ -1039,7 +1047,7 @@ if (is_mac) {
|
||||
if (is_mas_build) {
|
||||
deps += [ ":electron_login_helper_app" ]
|
||||
}
|
||||
info_plist = "shell/browser/resources/mac/Info.plist"
|
||||
info_plist_target = ":electron_app_plist"
|
||||
extra_substitutions = [
|
||||
"ELECTRON_BUNDLE_ID=$electron_mac_bundle_id",
|
||||
"ELECTRON_VERSION=$electron_version",
|
||||
|
||||
@@ -36,7 +36,7 @@ Having the original text _as well as_ the translation can help mitigate translat
|
||||
|
||||
Responses to posted issues may or may not be in the original language.
|
||||
|
||||
**Please note** that using non-English as an attempt to circumvent our [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) will be an immediate, and possibly indefinite, ban from the project.
|
||||
**Please note** that using non-English as an attempt to circumvent our [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) will be an immediate, and possibly indefinite, ban from the project.
|
||||
|
||||
## [Pull Requests](https://electronjs.org/docs/development/pull-requests)
|
||||
|
||||
|
||||
4
DEPS
4
DEPS
@@ -15,9 +15,9 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'95.0.4612.5',
|
||||
'95.0.4629.0',
|
||||
'node_version':
|
||||
'v16.7.0',
|
||||
'v16.9.1',
|
||||
'nan_version':
|
||||
# The following commit hash of NAN is v2.14.2 with *only* changes to the
|
||||
# test suite. This should be updated to a specific tag when one becomes
|
||||
|
||||
@@ -1 +1 @@
|
||||
16.0.0-nightly.20210825
|
||||
16.0.0-alpha.2
|
||||
@@ -1,7 +1,7 @@
|
||||
[](https://electronjs.org)
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/master)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/master)
|
||||
[](https://circleci.com/gh/electron/electron/tree/main)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/main)
|
||||
[](https://discord.com/invite/electron)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪.
|
||||
@@ -16,7 +16,7 @@ Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
|
||||
This project adheres to the Contributor Covenant
|
||||
[code of conduct](https://github.com/electron/electron/tree/master/CODE_OF_CONDUCT.md).
|
||||
[code of conduct](https://github.com/electron/electron/tree/main/CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to [coc@electronjs.org](mailto:coc@electronjs.org).
|
||||
|
||||
@@ -97,6 +97,6 @@ and more can be found in the [support document](docs/tutorial/support.md#finding
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/electron/electron/blob/master/LICENSE)
|
||||
[MIT](https://github.com/electron/electron/blob/main/LICENSE)
|
||||
|
||||
When using the Electron or other GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos).
|
||||
|
||||
@@ -10,7 +10,7 @@ Report security bugs in third-party modules to the person or team maintaining th
|
||||
|
||||
## The Electron Security Notification Process
|
||||
|
||||
For context on Electron's security notification process, please see the [Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md#notifications) section of the Security WG's [Membership and Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md) Governance document.
|
||||
For context on Electron's security notification process, please see the [Notifications](https://github.com/electron/governance/blob/main/wg-security/membership-and-notifications.md#notifications) section of the Security WG's [Membership and Notifications](https://github.com/electron/governance/blob/main/wg-security/membership-and-notifications.md) Governance document.
|
||||
|
||||
## Learning More About Security
|
||||
|
||||
|
||||
@@ -54,11 +54,17 @@ steps:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\src\pdb.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/pdb.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
cd src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y pdb.zip
|
||||
try {
|
||||
$localArtifactPath = "$pwd\src\pdb.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/pdb.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
cd src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y pdb.zip
|
||||
} catch {
|
||||
Write-Host "There was an exception encountered while downloading pdb files:" $_.Exception.Message
|
||||
} finally {
|
||||
$global:LASTEXITCODE = 0
|
||||
}
|
||||
displayName: 'Download pdb files for detailed stacktraces'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
|
||||
node_module_version = 89
|
||||
node_module_version = 99
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
@@ -33,7 +33,3 @@ is_cfi = false
|
||||
allow_runtime_configurable_key_storage = true
|
||||
|
||||
enable_cet_shadow_stack = false
|
||||
|
||||
# TODO(deepak1556): remove once https://bugs.chromium.org/p/chromium/issues/detail?id=1241610
|
||||
# is fixed.
|
||||
enable_blink_heap_use_v8_oilpan = false
|
||||
|
||||
@@ -57,4 +57,42 @@ template("asar") {
|
||||
rebase_path(outputs[0]),
|
||||
]
|
||||
}
|
||||
|
||||
node_action(target_name + "_header_hash") {
|
||||
invoker_out = invoker.outputs
|
||||
|
||||
deps = [ ":" + invoker.target_name ]
|
||||
sources = invoker.outputs
|
||||
|
||||
script = "//electron/script/gn-asar-hash.js"
|
||||
outputs = [ "$target_gen_dir/asar_hashes/$target_name.hash" ]
|
||||
|
||||
args = [
|
||||
rebase_path(invoker_out[0]),
|
||||
rebase_path(outputs[0]),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
template("asar_hashed_info_plist") {
|
||||
node_action(target_name) {
|
||||
assert(defined(invoker.plist_file),
|
||||
"Need plist_file to add hashed assets to")
|
||||
assert(defined(invoker.keys), "Need keys to replace with asset hash")
|
||||
assert(defined(invoker.hash_targets), "Need hash_targets to read hash from")
|
||||
|
||||
deps = invoker.hash_targets
|
||||
|
||||
script = "//electron/script/gn-plist-but-with-hashes.js"
|
||||
inputs = [ invoker.plist_file ]
|
||||
outputs = [ "$target_gen_dir/hashed_plists/$target_name.plist" ]
|
||||
hash_files = []
|
||||
foreach(hash_target, invoker.hash_targets) {
|
||||
hash_files += get_target_outputs(hash_target)
|
||||
}
|
||||
args = [
|
||||
rebase_path(invoker.plist_file),
|
||||
rebase_path(outputs[0]),
|
||||
] + invoker.keys + rebase_path(hash_files)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,7 @@
|
||||
"run_as_node": "1",
|
||||
"cookie_encryption": "0",
|
||||
"node_options": "1",
|
||||
"node_cli_inspect": "1"
|
||||
"node_cli_inspect": "1",
|
||||
"embedded_asar_integrity_validation": "0",
|
||||
"only_load_app_from_asar": "0"
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ static_library("chrome") {
|
||||
"//chrome/browser/predictors/proxy_lookup_client_impl.h",
|
||||
"//chrome/browser/predictors/resolve_host_client_impl.cc",
|
||||
"//chrome/browser/predictors/resolve_host_client_impl.h",
|
||||
"//chrome/browser/process_singleton.h",
|
||||
"//chrome/browser/ui/browser_dialogs.cc",
|
||||
"//chrome/browser/ui/browser_dialogs.h",
|
||||
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.cc",
|
||||
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper.cc",
|
||||
@@ -57,6 +60,10 @@ static_library("chrome") {
|
||||
"//extensions/browser/app_window/size_constraints.h",
|
||||
]
|
||||
|
||||
if (is_posix) {
|
||||
sources += [ "//chrome/browser/process_singleton_posix.cc" ]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
sources += [
|
||||
"//chrome/browser/extensions/global_shortcut_listener_mac.h",
|
||||
@@ -65,6 +72,7 @@ static_library("chrome") {
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.h",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm",
|
||||
"//chrome/browser/media/webrtc/window_icon_util_mac.mm",
|
||||
"//chrome/browser/process_singleton_mac.mm",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm",
|
||||
]
|
||||
@@ -76,6 +84,7 @@ static_library("chrome") {
|
||||
"//chrome/browser/extensions/global_shortcut_listener_win.h",
|
||||
"//chrome/browser/icon_loader_win.cc",
|
||||
"//chrome/browser/media/webrtc/window_icon_util_win.cc",
|
||||
"//chrome/browser/process_singleton_win.cc",
|
||||
"//chrome/browser/ui/frame/window_frame_util.h",
|
||||
"//chrome/browser/ui/view_ids.h",
|
||||
"//chrome/browser/win/chrome_process_finder.cc",
|
||||
@@ -314,17 +323,13 @@ source_set("plugins") {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [
|
||||
"//components/strings",
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_
|
||||
#define CHROME_BROWSER_PROCESS_SINGLETON_H_
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/process/process.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
|
||||
#if defined(OS_POSIX) && !defined(OS_ANDROID)
|
||||
#include "base/files/scoped_temp_dir.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/win/message_window.h"
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
namespace base {
|
||||
class CommandLine;
|
||||
}
|
||||
|
||||
// ProcessSingleton ----------------------------------------------------------
|
||||
//
|
||||
// This class allows different browser processes to communicate with
|
||||
// each other. It is named according to the user data directory, so
|
||||
// we can be sure that no more than one copy of the application can be
|
||||
// running at once with a given data directory.
|
||||
//
|
||||
// Implementation notes:
|
||||
// - the Windows implementation uses an invisible global message window;
|
||||
// - the Linux implementation uses a Unix domain socket in the user data dir.
|
||||
|
||||
class ProcessSingleton {
|
||||
public:
|
||||
enum NotifyResult {
|
||||
PROCESS_NONE,
|
||||
PROCESS_NOTIFIED,
|
||||
PROFILE_IN_USE,
|
||||
LOCK_ERROR,
|
||||
};
|
||||
|
||||
// Implement this callback to handle notifications from other processes. The
|
||||
// callback will receive the command line and directory with which the other
|
||||
// Chrome process was launched. Return true if the command line will be
|
||||
// handled within the current browser instance or false if the remote process
|
||||
// should handle it (i.e., because the current process is shutting down).
|
||||
using NotificationCallback = base::RepeatingCallback<bool(
|
||||
const base::CommandLine::StringVector& command_line,
|
||||
const base::FilePath& current_directory)>;
|
||||
|
||||
ProcessSingleton(const base::FilePath& user_data_dir,
|
||||
const NotificationCallback& notification_callback);
|
||||
~ProcessSingleton();
|
||||
|
||||
// Notify another process, if available. Otherwise sets ourselves as the
|
||||
// singleton instance. Returns PROCESS_NONE if we became the singleton
|
||||
// instance. Callers are guaranteed to either have notified an existing
|
||||
// process or have grabbed the singleton (unless the profile is locked by an
|
||||
// unreachable process).
|
||||
// TODO(brettw): Make the implementation of this method non-platform-specific
|
||||
// by making Linux re-use the Windows implementation.
|
||||
NotifyResult NotifyOtherProcessOrCreate();
|
||||
void StartListeningOnSocket();
|
||||
void OnBrowserReady();
|
||||
|
||||
// Sets ourself up as the singleton instance. Returns true on success. If
|
||||
// false is returned, we are not the singleton instance and the caller must
|
||||
// exit.
|
||||
// NOTE: Most callers should generally prefer NotifyOtherProcessOrCreate() to
|
||||
// this method, only callers for whom failure is preferred to notifying
|
||||
// another process should call this directly.
|
||||
bool Create();
|
||||
|
||||
// Clear any lock state during shutdown.
|
||||
void Cleanup();
|
||||
|
||||
#if defined(OS_POSIX) && !defined(OS_ANDROID)
|
||||
static void DisablePromptForTesting();
|
||||
#endif
|
||||
#if defined(OS_WIN)
|
||||
// Called to query whether to kill a hung browser process that has visible
|
||||
// windows. Return true to allow killing the hung process.
|
||||
using ShouldKillRemoteProcessCallback = base::RepeatingCallback<bool()>;
|
||||
void OverrideShouldKillRemoteProcessCallbackForTesting(
|
||||
const ShouldKillRemoteProcessCallback& display_dialog_callback);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Notify another process, if available.
|
||||
// Returns true if another process was found and notified, false if we should
|
||||
// continue with the current process.
|
||||
// On Windows, Create() has to be called before this.
|
||||
NotifyResult NotifyOtherProcess();
|
||||
|
||||
#if defined(OS_POSIX) && !defined(OS_ANDROID)
|
||||
// Exposed for testing. We use a timeout on Linux, and in tests we want
|
||||
// this timeout to be short.
|
||||
NotifyResult NotifyOtherProcessWithTimeout(
|
||||
const base::CommandLine& command_line,
|
||||
int retry_attempts,
|
||||
const base::TimeDelta& timeout,
|
||||
bool kill_unresponsive);
|
||||
NotifyResult NotifyOtherProcessWithTimeoutOrCreate(
|
||||
const base::CommandLine& command_line,
|
||||
int retry_attempts,
|
||||
const base::TimeDelta& timeout);
|
||||
void OverrideCurrentPidForTesting(base::ProcessId pid);
|
||||
void OverrideKillCallbackForTesting(
|
||||
const base::RepeatingCallback<void(int)>& callback);
|
||||
#endif
|
||||
|
||||
private:
|
||||
NotificationCallback notification_callback_; // Handler for notifications.
|
||||
|
||||
#if defined(OS_WIN)
|
||||
HWND remote_window_ = nullptr; // The HWND_MESSAGE of another browser.
|
||||
base::win::MessageWindow window_; // The message-only window.
|
||||
bool is_virtualized_ =
|
||||
false; // Stuck inside Microsoft Softricity VM environment.
|
||||
HANDLE lock_file_ = INVALID_HANDLE_VALUE;
|
||||
base::FilePath user_data_dir_;
|
||||
ShouldKillRemoteProcessCallback should_kill_remote_process_callback_;
|
||||
#elif defined(OS_POSIX) && !defined(OS_ANDROID)
|
||||
// Start listening to the socket.
|
||||
void StartListening(int sock);
|
||||
|
||||
// Return true if the given pid is one of our child processes.
|
||||
// Assumes that the current pid is the root of all pids of the current
|
||||
// instance.
|
||||
bool IsSameChromeInstance(pid_t pid);
|
||||
|
||||
// Extract the process's pid from a symbol link path and if it is on
|
||||
// the same host, kill the process, unlink the lock file and return true.
|
||||
// If the process is part of the same chrome instance, unlink the lock file
|
||||
// and return true without killing it.
|
||||
// If the process is on a different host, return false.
|
||||
bool KillProcessByLockPath();
|
||||
|
||||
// Default function to kill a process, overridable by tests.
|
||||
void KillProcess(int pid);
|
||||
|
||||
// Allow overriding for tests.
|
||||
base::ProcessId current_pid_;
|
||||
|
||||
// Function to call when the other process is hung and needs to be killed.
|
||||
// Allows overriding for tests.
|
||||
base::RepeatingCallback<void(int)> kill_callback_;
|
||||
|
||||
// Path in file system to the socket.
|
||||
base::FilePath socket_path_;
|
||||
|
||||
// Path in file system to the lock.
|
||||
base::FilePath lock_path_;
|
||||
|
||||
// Path in file system to the cookie file.
|
||||
base::FilePath cookie_path_;
|
||||
|
||||
// Temporary directory to hold the socket.
|
||||
base::ScopedTempDir socket_dir_;
|
||||
|
||||
// Helper class for linux specific messages. LinuxWatcher is ref counted
|
||||
// because it posts messages between threads.
|
||||
class LinuxWatcher;
|
||||
scoped_refptr<LinuxWatcher> watcher_;
|
||||
int sock_ = -1;
|
||||
bool listen_on_ready_ = false;
|
||||
#endif
|
||||
|
||||
SEQUENCE_CHECKER(sequence_checker_);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ProcessSingleton);
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,315 +0,0 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/browser/process_singleton.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include "base/base_paths.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/process/process.h"
|
||||
#include "base/process/process_info.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/win/registry.h"
|
||||
#include "base/win/scoped_handle.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "chrome/browser/win/chrome_process_finder.h"
|
||||
#include "content/public/common/result_codes.h"
|
||||
#include "net/base/escape.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char kLockfile[] = "lockfile";
|
||||
|
||||
// A helper class that acquires the given |mutex| while the AutoLockMutex is in
|
||||
// scope.
|
||||
class AutoLockMutex {
|
||||
public:
|
||||
explicit AutoLockMutex(HANDLE mutex) : mutex_(mutex) {
|
||||
DWORD result = ::WaitForSingleObject(mutex_, INFINITE);
|
||||
DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result;
|
||||
}
|
||||
|
||||
~AutoLockMutex() {
|
||||
BOOL released = ::ReleaseMutex(mutex_);
|
||||
DPCHECK(released);
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE mutex_;
|
||||
DISALLOW_COPY_AND_ASSIGN(AutoLockMutex);
|
||||
};
|
||||
|
||||
// A helper class that releases the given |mutex| while the AutoUnlockMutex is
|
||||
// in scope and immediately re-acquires it when going out of scope.
|
||||
class AutoUnlockMutex {
|
||||
public:
|
||||
explicit AutoUnlockMutex(HANDLE mutex) : mutex_(mutex) {
|
||||
BOOL released = ::ReleaseMutex(mutex_);
|
||||
DPCHECK(released);
|
||||
}
|
||||
|
||||
~AutoUnlockMutex() {
|
||||
DWORD result = ::WaitForSingleObject(mutex_, INFINITE);
|
||||
DPCHECK(result == WAIT_OBJECT_0) << "Result = " << result;
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE mutex_;
|
||||
DISALLOW_COPY_AND_ASSIGN(AutoUnlockMutex);
|
||||
};
|
||||
|
||||
// Checks the visibility of the enumerated window and signals once a visible
|
||||
// window has been found.
|
||||
BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) {
|
||||
bool* result = reinterpret_cast<bool*>(param);
|
||||
*result = ::IsWindowVisible(window) != 0;
|
||||
// Stops enumeration if a visible window has been found.
|
||||
return !*result;
|
||||
}
|
||||
|
||||
bool ParseCommandLine(const COPYDATASTRUCT* cds,
|
||||
base::CommandLine::StringVector* parsed_command_line,
|
||||
base::FilePath* current_directory) {
|
||||
// We should have enough room for the shortest command (min_message_size)
|
||||
// and also be a multiple of wchar_t bytes. The shortest command
|
||||
// possible is L"START\0\0" (empty current directory and command line).
|
||||
static const int min_message_size = 7;
|
||||
if (cds->cbData < min_message_size * sizeof(wchar_t) ||
|
||||
cds->cbData % sizeof(wchar_t) != 0) {
|
||||
LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We split the string into 4 parts on NULLs.
|
||||
DCHECK(cds->lpData);
|
||||
const std::wstring msg(static_cast<wchar_t*>(cds->lpData),
|
||||
cds->cbData / sizeof(wchar_t));
|
||||
const std::wstring::size_type first_null = msg.find_first_of(L'\0');
|
||||
if (first_null == 0 || first_null == std::wstring::npos) {
|
||||
// no NULL byte, don't know what to do
|
||||
LOG(WARNING) << "Invalid WM_COPYDATA, length = " << msg.length()
|
||||
<< ", first null = " << first_null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the command, which is everything until the first NULL.
|
||||
if (msg.substr(0, first_null) == L"START") {
|
||||
// Another instance is starting parse the command line & do what it would
|
||||
// have done.
|
||||
VLOG(1) << "Handling STARTUP request from another process";
|
||||
const std::wstring::size_type second_null =
|
||||
msg.find_first_of(L'\0', first_null + 1);
|
||||
if (second_null == std::wstring::npos || first_null == msg.length() - 1 ||
|
||||
second_null == msg.length()) {
|
||||
LOG(WARNING) << "Invalid format for start command, we need a string in 4 "
|
||||
"parts separated by NULLs";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get current directory.
|
||||
*current_directory =
|
||||
base::FilePath(msg.substr(first_null + 1, second_null - first_null));
|
||||
|
||||
const std::wstring::size_type third_null =
|
||||
msg.find_first_of(L'\0', second_null + 1);
|
||||
if (third_null == std::wstring::npos || third_null == msg.length()) {
|
||||
LOG(WARNING) << "Invalid format for start command, we need a string in 4 "
|
||||
"parts separated by NULLs";
|
||||
}
|
||||
|
||||
// Get command line.
|
||||
const std::wstring cmd_line =
|
||||
msg.substr(second_null + 1, third_null - second_null);
|
||||
*parsed_command_line = base::CommandLine::FromString(cmd_line).argv();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProcessLaunchNotification(
|
||||
const ProcessSingleton::NotificationCallback& notification_callback,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam,
|
||||
LRESULT* result) {
|
||||
if (message != WM_COPYDATA)
|
||||
return false;
|
||||
|
||||
// Handle the WM_COPYDATA message from another process.
|
||||
const COPYDATASTRUCT* cds = reinterpret_cast<COPYDATASTRUCT*>(lparam);
|
||||
|
||||
base::CommandLine::StringVector parsed_command_line;
|
||||
base::FilePath current_directory;
|
||||
if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) {
|
||||
*result = TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
*result = notification_callback.Run(parsed_command_line, current_directory)
|
||||
? TRUE
|
||||
: FALSE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TerminateAppWithError() {
|
||||
// TODO: This is called when the secondary process can't ping the primary
|
||||
// process. Need to find out what to do here.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ProcessSingleton::ProcessSingleton(
|
||||
const base::FilePath& user_data_dir,
|
||||
const NotificationCallback& notification_callback)
|
||||
: notification_callback_(notification_callback),
|
||||
user_data_dir_(user_data_dir),
|
||||
should_kill_remote_process_callback_(
|
||||
base::BindRepeating(&TerminateAppWithError)) {
|
||||
// The user_data_dir may have not been created yet.
|
||||
base::CreateDirectoryAndGetError(user_data_dir, nullptr);
|
||||
}
|
||||
|
||||
ProcessSingleton::~ProcessSingleton() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
if (lock_file_ != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(lock_file_);
|
||||
}
|
||||
|
||||
// Code roughly based on Mozilla.
|
||||
ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
|
||||
if (is_virtualized_)
|
||||
return PROCESS_NOTIFIED; // We already spawned the process in this case.
|
||||
if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) {
|
||||
return LOCK_ERROR;
|
||||
} else if (!remote_window_) {
|
||||
return PROCESS_NONE;
|
||||
}
|
||||
|
||||
switch (chrome::AttemptToNotifyRunningChrome(remote_window_)) {
|
||||
case chrome::NOTIFY_SUCCESS:
|
||||
return PROCESS_NOTIFIED;
|
||||
case chrome::NOTIFY_FAILED:
|
||||
remote_window_ = NULL;
|
||||
return PROCESS_NONE;
|
||||
case chrome::NOTIFY_WINDOW_HUNG:
|
||||
// Fall through and potentially terminate the hung browser.
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD process_id = 0;
|
||||
DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id);
|
||||
if (!thread_id || !process_id) {
|
||||
remote_window_ = NULL;
|
||||
return PROCESS_NONE;
|
||||
}
|
||||
base::Process process = base::Process::Open(process_id);
|
||||
|
||||
// The window is hung. Scan for every window to find a visible one.
|
||||
bool visible_window = false;
|
||||
::EnumThreadWindows(thread_id, &BrowserWindowEnumeration,
|
||||
reinterpret_cast<LPARAM>(&visible_window));
|
||||
|
||||
// If there is a visible browser window, ask the user before killing it.
|
||||
if (visible_window && !should_kill_remote_process_callback_.Run()) {
|
||||
// The user denied. Quit silently.
|
||||
return PROCESS_NOTIFIED;
|
||||
}
|
||||
|
||||
// Time to take action. Kill the browser process.
|
||||
process.Terminate(content::RESULT_CODE_HUNG, true);
|
||||
remote_window_ = NULL;
|
||||
return PROCESS_NONE;
|
||||
}
|
||||
|
||||
ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() {
|
||||
ProcessSingleton::NotifyResult result = PROCESS_NONE;
|
||||
if (!Create()) {
|
||||
result = NotifyOtherProcess();
|
||||
if (result == PROCESS_NONE)
|
||||
result = PROFILE_IN_USE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ProcessSingleton::StartListeningOnSocket() {}
|
||||
void ProcessSingleton::OnBrowserReady() {}
|
||||
|
||||
// Look for a Chrome instance that uses the same profile directory. If there
|
||||
// isn't one, create a message window with its title set to the profile
|
||||
// directory path.
|
||||
bool ProcessSingleton::Create() {
|
||||
static const wchar_t kMutexName[] = L"Local\\AtomProcessSingletonStartup!";
|
||||
|
||||
remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_);
|
||||
if (!remote_window_) {
|
||||
// Make sure we will be the one and only process creating the window.
|
||||
// We use a named Mutex since we are protecting against multi-process
|
||||
// access. As documented, it's clearer to NOT request ownership on creation
|
||||
// since it isn't guaranteed we will get it. It is better to create it
|
||||
// without ownership and explicitly get the ownership afterward.
|
||||
base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName));
|
||||
if (!only_me.IsValid()) {
|
||||
DPLOG(FATAL) << "CreateMutex failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoLockMutex auto_lock_only_me(only_me.Get());
|
||||
|
||||
// We now own the mutex so we are the only process that can create the
|
||||
// window at this time, but we must still check if someone created it
|
||||
// between the time where we looked for it above and the time the mutex
|
||||
// was given to us.
|
||||
remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_);
|
||||
if (!remote_window_) {
|
||||
// We have to make sure there is no Chrome instance running on another
|
||||
// machine that uses the same profile.
|
||||
base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile);
|
||||
lock_file_ =
|
||||
::CreateFile(lock_file_path.value().c_str(), GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||
DWORD error = ::GetLastError();
|
||||
LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE &&
|
||||
error == ERROR_ALREADY_EXISTS)
|
||||
<< "Lock file exists but is writable.";
|
||||
LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE)
|
||||
<< "Lock file can not be created! Error code: " << error;
|
||||
|
||||
if (lock_file_ != INVALID_HANDLE_VALUE) {
|
||||
// Set the window's title to the path of our user data directory so
|
||||
// other Chrome instances can decide if they should forward to us.
|
||||
bool result =
|
||||
window_.CreateNamed(base::BindRepeating(&ProcessLaunchNotification,
|
||||
notification_callback_),
|
||||
user_data_dir_.value());
|
||||
|
||||
// NB: Ensure that if the primary app gets started as elevated
|
||||
// admin inadvertently, secondary windows running not as elevated
|
||||
// will still be able to send messages
|
||||
::ChangeWindowMessageFilterEx(window_.hwnd(), WM_COPYDATA, MSGFLT_ALLOW,
|
||||
NULL);
|
||||
CHECK(result && window_.hwnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return window_.hwnd() != NULL;
|
||||
}
|
||||
|
||||
void ProcessSingleton::Cleanup() {}
|
||||
|
||||
void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting(
|
||||
const ShouldKillRemoteProcessCallback& display_dialog_callback) {
|
||||
should_kill_remote_process_callback_ = display_dialog_callback;
|
||||
}
|
||||
@@ -277,6 +277,7 @@ Returns:
|
||||
* `certificate` [Certificate](structures/certificate.md)
|
||||
* `callback` Function
|
||||
* `isTrusted` Boolean - Whether to consider the certificate as trusted
|
||||
* `isMainFrame` Boolean
|
||||
|
||||
Emitted when failed to verify the `certificate` for `url`, to trust the
|
||||
certificate you should prevent the default behavior with
|
||||
@@ -1061,6 +1062,61 @@ Imports the certificate in pkcs12 format into the platform certificate store.
|
||||
`callback` is called with the `result` of import operation, a value of `0`
|
||||
indicates success while any other value indicates failure according to Chromium [net_error_list](https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h).
|
||||
|
||||
### `app.configureHostResolver(options)`
|
||||
|
||||
* `options` Object
|
||||
* `enableBuiltInResolver` Boolean (optional) - Whether the built-in host
|
||||
resolver is used in preference to getaddrinfo. When enabled, the built-in
|
||||
resolver will attempt to use the system's DNS settings to do DNS lookups
|
||||
itself. Enabled by default on macOS, disabled by default on Windows and
|
||||
Linux.
|
||||
* `secureDnsMode` String (optional) - Can be "off", "automatic" or "secure".
|
||||
Configures the DNS-over-HTTP mode. When "off", no DoH lookups will be
|
||||
performed. When "automatic", DoH lookups will be peformed first if DoH is
|
||||
available, and insecure DNS lookups will be performed as a fallback. When
|
||||
"secure", only DoH lookups will be performed. Defaults to "automatic".
|
||||
* `secureDnsServers` String[] (optional) - A list of DNS-over-HTTP
|
||||
server templates. See [RFC8484 § 3][] for details on the template format.
|
||||
Most servers support the POST method; the template for such servers is
|
||||
simply a URI. Note that for [some DNS providers][doh-providers], the
|
||||
resolver will automatically upgrade to DoH unless DoH is explicitly
|
||||
disabled, even if there are no DoH servers provided in this list.
|
||||
* `enableAdditionalDnsQueryTypes` Boolean (optional) - Controls whether additional DNS
|
||||
query types, e.g. HTTPS (DNS type 65) will be allowed besides the
|
||||
traditional A and AAAA queries when a request is being made via insecure
|
||||
DNS. Has no effect on Secure DNS which always allows additional types.
|
||||
Defaults to true.
|
||||
|
||||
Configures host resolution (DNS and DNS-over-HTTPS). By default, the following
|
||||
resolvers will be used, in order:
|
||||
|
||||
1. DNS-over-HTTPS, if the [DNS provider supports it][doh-providers], then
|
||||
2. the built-in resolver (enabled on macOS only by default), then
|
||||
3. the system's resolver (e.g. `getaddrinfo`).
|
||||
|
||||
This can be configured to either restrict usage of non-encrypted DNS
|
||||
(`secureDnsMode: "secure"`), or disable DNS-over-HTTPS (`secureDnsMode:
|
||||
"off"`). It is also possible to enable or disable the built-in resolver.
|
||||
|
||||
To disable insecure DNS, you can specify a `secureDnsMode` of `"secure"`. If you do
|
||||
so, you should make sure to provide a list of DNS-over-HTTPS servers to use, in
|
||||
case the user's DNS configuration does not include a provider that supports
|
||||
DoH.
|
||||
|
||||
```js
|
||||
app.configureHostResolver({
|
||||
secureDnsMode: 'secure',
|
||||
secureDnsServers: [
|
||||
'https://cloudflare-dns.com/dns-query'
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
This API must be called after the `ready` event is emitted.
|
||||
|
||||
[doh-providers]: https://source.chromium.org/chromium/chromium/src/+/main:net/dns/public/doh_provider_entry.cc;l=31?q=%22DohProviderEntry::GetList()%22&ss=chromium%2Fchromium%2Fsrc
|
||||
[RFC8484 § 3]: https://datatracker.ietf.org/doc/html/rfc8484#section-3
|
||||
|
||||
### `app.disableHardwareAcceleration()`
|
||||
|
||||
Disables hardware acceleration for current app.
|
||||
|
||||
@@ -43,7 +43,7 @@ The installer generated with Squirrel will create a shortcut icon with an
|
||||
same ID for your app with `app.setAppUserModelId` API, otherwise Windows will
|
||||
not be able to pin your app properly in task bar.
|
||||
|
||||
Unlike Squirrel.Mac, Windows can host updates on S3 or any other static file host.
|
||||
Like Squirrel.Mac, Windows can host updates on S3 or any other static file host.
|
||||
You can read the documents of [Squirrel.Windows][squirrel-windows] to get more details
|
||||
about how Squirrel.Windows works.
|
||||
|
||||
|
||||
@@ -22,12 +22,13 @@ win.loadFile('index.html')
|
||||
To create a window without chrome, or a transparent window in arbitrary shape,
|
||||
you can use the [Frameless Window](frameless-window.md) API.
|
||||
|
||||
## Showing window gracefully
|
||||
## Showing the window gracefully
|
||||
|
||||
When loading a page in the window directly, users may see the page load incrementally, which is not a good experience for a native app. To make the window display
|
||||
without visual flash, there are two solutions for different situations.
|
||||
When loading a page in the window directly, users may see the page load incrementally,
|
||||
which is not a good experience for a native app. To make the window display
|
||||
without a visual flash, there are two solutions for different situations.
|
||||
|
||||
## Using `ready-to-show` event
|
||||
### Using the `ready-to-show` event
|
||||
|
||||
While loading the page, the `ready-to-show` event will be emitted when the renderer
|
||||
process has rendered the page for the first time if the window has not been shown yet. Showing
|
||||
@@ -48,7 +49,7 @@ event.
|
||||
Please note that using this event implies that the renderer will be considered "visible" and
|
||||
paint even though `show` is false. This event will never fire if you use `paintWhenInitiallyHidden: false`
|
||||
|
||||
## Setting `backgroundColor`
|
||||
### Setting the `backgroundColor` property
|
||||
|
||||
For a complex app, the `ready-to-show` event could be emitted too late, making
|
||||
the app feel slow. In this case, it is recommended to show the window
|
||||
@@ -987,7 +988,7 @@ the player itself we would call this function with arguments of 16/9 and
|
||||
are within the content view--only that they exist. Sum any extra width and
|
||||
height areas you have within the overall content view.
|
||||
|
||||
The aspect ratio is not respected when window is resized programmingly with
|
||||
The aspect ratio is not respected when window is resized programmatically with
|
||||
APIs like `win.setSize`.
|
||||
|
||||
#### `win.setBackgroundColor(backgroundColor)`
|
||||
|
||||
@@ -131,15 +131,15 @@ Returns `Object`:
|
||||
|
||||
Returns an Object containing `title` and `url` keys representing the bookmark in
|
||||
the clipboard. The `title` and `url` values will be empty strings when the
|
||||
bookmark is unavailable.
|
||||
bookmark is unavailable. The `title` value will always be empty on Windows.
|
||||
|
||||
### `clipboard.writeBookmark(title, url[, type])` _macOS_ _Windows_
|
||||
|
||||
* `title` String
|
||||
* `title` String - Unused on Windows
|
||||
* `url` String
|
||||
* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.
|
||||
|
||||
Writes the `title` and `url` into the clipboard as a bookmark.
|
||||
Writes the `title` (macOS only) and `url` into the clipboard as a bookmark.
|
||||
|
||||
**Note:** Most apps on Windows don't support pasting bookmarks into them so
|
||||
you can use `clipboard.write` to write both a bookmark and fallback text to the
|
||||
|
||||
@@ -234,6 +234,7 @@ expanding and collapsing the dialog.
|
||||
* `title` String (optional) - Title of the message box, some platforms will not show it.
|
||||
* `detail` String (optional) - Extra information of the message.
|
||||
* `icon` ([NativeImage](native-image.md) | String) (optional)
|
||||
* `textWidth` Integer (optional) _macOS_ - Custom width of the text in the message box.
|
||||
* `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
|
||||
label. If no such labeled buttons exist and this option is not set, `0` will be used as the
|
||||
@@ -285,6 +286,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
* `checkboxChecked` Boolean (optional) - Initial checked state of the
|
||||
checkbox. `false` by default.
|
||||
* `icon` [NativeImage](native-image.md) (optional)
|
||||
* `textWidth` Integer (optional) _macOS_ - Custom width of the text in the message box.
|
||||
* `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
|
||||
label. If no such labeled buttons exist and this option is not set, `0` will be used as the
|
||||
|
||||
@@ -180,6 +180,96 @@ Emitted when a hunspell dictionary file download fails. For details
|
||||
on the failure you should collect a netlog and inspect the download
|
||||
request.
|
||||
|
||||
#### Event: 'select-hid-device'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `deviceList` [HIDDevice[]](structures/hid-device.md)
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
* `callback` Function
|
||||
* `deviceId` String | null (optional)
|
||||
|
||||
Emitted when a HID device needs to be selected when a call to
|
||||
`navigator.hid.requestDevice` is made. `callback` should be called with
|
||||
`deviceId` to be selected; passing no arguments to `callback` will
|
||||
cancel the request. Additionally, permissioning on `navigator.hid` can
|
||||
be further managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler)
|
||||
and [ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow()
|
||||
|
||||
win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
|
||||
if (permission === 'hid') {
|
||||
// Add logic here to determine if permission should be given to allow HID selection
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// Optionally, retrieve previously persisted devices from a persistent store
|
||||
const grantedDevices = fetchGrantedDevices()
|
||||
|
||||
win.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'hid') {
|
||||
if (details.device.vendorId === 123 && details.device.productId === 345) {
|
||||
// Always allow this type of device (this allows skipping the call to `navigator.hid.requestDevice` first)
|
||||
return true
|
||||
}
|
||||
|
||||
// Search through the list of devices that have previously been granted permission
|
||||
return grantedDevices.some((grantedDevice) => {
|
||||
return grantedDevice.vendorId === details.device.vendorId &&
|
||||
grantedDevice.productId === details.device.productId &&
|
||||
grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
|
||||
})
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
win.webContents.session.on('select-hid-device', (event, details, callback) => {
|
||||
event.preventDefault()
|
||||
const selectedDevice = details.deviceList.find((device) => {
|
||||
return device.vendorId === '9025' && device.productId === '67'
|
||||
})
|
||||
callback(selectedPort?.deviceId)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'hid-device-added'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
|
||||
Emitted when a new HID device becomes available. For example, when a new USB device is plugged in.
|
||||
|
||||
This event will only be emitted after `navigator.hid.requestDevice` has been called and `select-hid-device` has fired.
|
||||
|
||||
#### Event: 'hid-device-removed'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
|
||||
Emitted when a HID device has been removed. For example, this event will fire when a USB device is unplugged.
|
||||
|
||||
This event will only be emitted after `navigator.hid.requestDevice` has been called and `select-hid-device` has fired.
|
||||
|
||||
#### Event: 'select-serial-port'
|
||||
|
||||
Returns:
|
||||
@@ -525,7 +615,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
|
||||
|
||||
* `handler` Function\<Boolean> | null
|
||||
* `webContents` ([WebContents](web-contents.md) | null) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. All cross origin sub frames making permission checks will pass a `null` webContents to this handler, while certain other permission checks such as `notifications` checks will always pass `null`. You should use `embeddingOrigin` and `requestingOrigin` to determine what origin the owning frame and the requesting frame are on respectively.
|
||||
* `permission` String - Type of permission check. Valid values are `midiSysex`, `notifications`, `geolocation`, `media`,`mediaKeySystem`,`midi`, `pointerLock`, `fullscreen`, `openExternal`, or `serial`.
|
||||
* `permission` String - Type of permission check. Valid values are `midiSysex`, `notifications`, `geolocation`, `media`,`mediaKeySystem`,`midi`, `pointerLock`, `fullscreen`, `openExternal`, `hid`, or `serial`.
|
||||
* `requestingOrigin` String - The origin URL of the permission check
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
* `embeddingOrigin` String (optional) - The origin of the frame embedding the frame that made the permission check. Only set for cross-origin sub frames making permission checks.
|
||||
@@ -553,6 +643,71 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
|
||||
})
|
||||
```
|
||||
|
||||
#### `ses.setDevicePermissionHandler(handler)`
|
||||
|
||||
* `handler` Function\<Boolean> | null
|
||||
* `details` Object
|
||||
* `deviceType` String - The type of device that permission is being requested on, can be `hid`.
|
||||
* `origin` String - The origin URL of the device permission check.
|
||||
* `device` [HIDDevice](structures/hid-device.md) - the device that permission is being requested for.
|
||||
* `frame` [WebFrameMain](web-frame-main.md) - WebFrameMain checking the device permission.
|
||||
|
||||
Sets the handler which can be used to respond to device permission checks for the `session`.
|
||||
Returning `true` will allow the device to be permitted and `false` will reject it.
|
||||
To clear the handler, call `setDevicePermissionHandler(null)`.
|
||||
This handler can be used to provide default permissioning to devices without first calling for permission
|
||||
to devices (eg via `navigator.hid.requestDevice`). If this handler is not defined, the default device
|
||||
permissions as granted through device selection (eg via `navigator.hid.requestDevice`) will be used.
|
||||
Additionally, the default behavior of Electron is to store granted device permision through the lifetime
|
||||
of the corresponding WebContents. If longer term storage is needed, a developer can store granted device
|
||||
permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow()
|
||||
|
||||
win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
|
||||
if (permission === 'hid') {
|
||||
// Add logic here to determine if permission should be given to allow HID selection
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// Optionally, retrieve previously persisted devices from a persistent store
|
||||
const grantedDevices = fetchGrantedDevices()
|
||||
|
||||
win.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'hid') {
|
||||
if (details.device.vendorId === 123 && details.device.productId === 345) {
|
||||
// Always allow this type of device (this allows skipping the call to `navigator.hid.requestDevice` first)
|
||||
return true
|
||||
}
|
||||
|
||||
// Search through the list of devices that have previously been granted permission
|
||||
return grantedDevices.some((grantedDevice) => {
|
||||
return grantedDevice.vendorId === details.device.vendorId &&
|
||||
grantedDevice.productId === details.device.productId &&
|
||||
grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
|
||||
})
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
win.webContents.session.on('select-hid-device', (event, details, callback) => {
|
||||
event.preventDefault()
|
||||
const selectedDevice = details.deviceList.find((device) => {
|
||||
return device.vendorId === '9025' && device.productId === '67'
|
||||
})
|
||||
callback(selectedPort?.deviceId)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
#### `ses.clearHostResolverCache()`
|
||||
|
||||
Returns `Promise<void>` - Resolves when the operation is complete.
|
||||
|
||||
8
docs/api/structures/hid-device.md
Normal file
8
docs/api/structures/hid-device.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# HIDDevice Object
|
||||
|
||||
* `deviceId` String - Unique identifier for the device.
|
||||
* `name` String - Name of the device.
|
||||
* `vendorId` Integer - The USB vendor ID.
|
||||
* `productId` Integer - The USB product ID.
|
||||
* `serialNumber` String (optional) - The USB device serial number.
|
||||
* `guid` String (optional) - Unique identifier for the HID interface. A device may have multiple HID interfaces.
|
||||
@@ -45,6 +45,26 @@ returns `null`.
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
|
||||
`undefined` if there is no WebContents associated with the given ID.
|
||||
|
||||
### `webContents.fromDevToolsTargetId(targetId)`
|
||||
|
||||
* `targetId` String - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.
|
||||
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or
|
||||
`undefined` if there is no WebContents associated with the given TargetID.
|
||||
|
||||
When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/),
|
||||
it can be useful to lookup a WebContents instance based on its assigned TargetID.
|
||||
|
||||
```js
|
||||
async function lookupTargetId (browserWindow) {
|
||||
const wc = browserWindow.webContents
|
||||
await wc.debugger.attach('1.3')
|
||||
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
|
||||
const { targetId } = targetInfo
|
||||
const targetWebContents = await webContents.fromDevToolsTargetId(targetId)
|
||||
}
|
||||
```
|
||||
|
||||
## Class: WebContents
|
||||
|
||||
> Render and control the contents of a BrowserWindow instance.
|
||||
@@ -114,7 +134,7 @@ Returns:
|
||||
|
||||
* `event` Event
|
||||
|
||||
Emitted when the document in the given frame is loaded.
|
||||
Emitted when the document in the top-level frame is loaded.
|
||||
|
||||
#### Event: 'page-title-updated'
|
||||
|
||||
@@ -510,6 +530,7 @@ Returns:
|
||||
* `certificate` [Certificate](structures/certificate.md)
|
||||
* `callback` Function
|
||||
* `isTrusted` Boolean - Indicates whether the certificate can be considered trusted.
|
||||
* `isMainFrame` Boolean
|
||||
|
||||
Emitted when failed to verify the `certificate` for `url`.
|
||||
|
||||
@@ -630,6 +651,7 @@ Returns:
|
||||
* `params` Object
|
||||
* `x` Integer - x coordinate.
|
||||
* `y` Integer - y coordinate.
|
||||
* `frame` WebFrameMain - Frame from which the context menu was invoked.
|
||||
* `linkURL` String - URL of the link that encloses the node the context menu
|
||||
was invoked on.
|
||||
* `linkText` String - Text associated with the link. May be an empty
|
||||
@@ -856,6 +878,16 @@ Emitted when the `WebContents` preferred size has changed.
|
||||
This event will only be emitted when `enablePreferredSizeMode` is set to `true`
|
||||
in `webPreferences`.
|
||||
|
||||
#### Event: 'frame-created'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `frame` WebFrameMain
|
||||
|
||||
Emitted when the [mainFrame](web-contents.md#contentsmainframe-readonly), an `<iframe>`, or a nested `<iframe>` is loaded within the page.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `contents.loadURL(url[, options])`
|
||||
@@ -1795,7 +1827,8 @@ End subscribing for frame presentation events.
|
||||
#### `contents.startDrag(item)`
|
||||
|
||||
* `item` Object
|
||||
* `file` String[] | String - The path(s) to the file(s) being dragged.
|
||||
* `file` String - The path to the file being dragged.
|
||||
* `files` String[] (optional) - The paths to the files being dragged. (`files` will override `file` field)
|
||||
* `icon` [NativeImage](native-image.md) | String - The image must be
|
||||
non-empty on macOS.
|
||||
|
||||
@@ -1992,11 +2025,6 @@ when the DevTools has been closed.
|
||||
|
||||
A [`Debugger`](debugger.md) instance for this webContents.
|
||||
|
||||
[keyboardevent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`postMessage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
|
||||
|
||||
#### `contents.backgroundThrottling`
|
||||
|
||||
A `Boolean` property that determines whether or not this WebContents will throttle animations and timers
|
||||
@@ -2005,3 +2033,8 @@ when the page becomes backgrounded. This also affects the Page Visibility API.
|
||||
#### `contents.mainFrame` _Readonly_
|
||||
|
||||
A [`WebFrameMain`](web-frame-main.md) property that represents the top frame of the page's frame hierarchy.
|
||||
|
||||
[keyboardevent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`postMessage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
|
||||
|
||||
@@ -71,6 +71,12 @@ or `undefined` if there is no WebFrameMain associated with the given IDs.
|
||||
Process: [Main](../glossary.md#main-process)<br />
|
||||
_This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API._
|
||||
|
||||
### Instance Events
|
||||
|
||||
#### Event: 'dom-ready'
|
||||
|
||||
Emitted when the document is loaded.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `frame.executeJavaScript(code[, userGesture])`
|
||||
|
||||
@@ -143,12 +143,16 @@ browser plugins. Plugins are disabled by default.
|
||||
### `preload`
|
||||
|
||||
```html
|
||||
<!-- from a file -->
|
||||
<webview src="https://www.github.com/" preload="./test.js"></webview>
|
||||
<!-- or if you want to load from an asar archive -->
|
||||
<webview src="https://www.github.com/" preload="./app.asar/test.js"></webview>
|
||||
```
|
||||
|
||||
A `String` that specifies a script that will be loaded before other scripts run in the guest
|
||||
page. The protocol of script's URL must be either `file:` or `asar:`, because it
|
||||
will be loaded by `require` in guest page under the hood.
|
||||
page. The protocol of script's URL must be `file:` (even when using `asar:` archives) because
|
||||
it will be loaded by Node's `require` under the hood, which treats `asar:` archives as virtual
|
||||
directories.
|
||||
|
||||
When the guest page doesn't have node integration this script will still have
|
||||
access to all Node APIs, but global objects injected by Node will be deleted
|
||||
|
||||
@@ -12,6 +12,39 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (17.0)
|
||||
|
||||
### Removed: `desktopCapturer.getSources` in the renderer
|
||||
|
||||
The `desktopCapturer.getSources` API is now only available in the main process.
|
||||
This has been changed in order to improve the default security of Electron
|
||||
apps.
|
||||
|
||||
If you need this functionality, it can be replaced as follows:
|
||||
|
||||
```js
|
||||
// Main process
|
||||
const { ipcMain, desktopCapturer } = require('electron')
|
||||
|
||||
ipcMain.handle(
|
||||
'DESKTOP_CAPTURER_GET_SOURCES',
|
||||
(event, opts) => desktopCapturer.getSources(opts)
|
||||
)
|
||||
```
|
||||
|
||||
```js
|
||||
// Renderer process
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const desktopCapturer = {
|
||||
getSources: (opts) => ipcRenderer.invoke('DESKTOP_CAPTURER_GET_SOURCES', opts)
|
||||
}
|
||||
```
|
||||
|
||||
However, you should consider further restricting the information returned to
|
||||
the renderer; for instance, displaying a source selector to the user and only
|
||||
returning the selected source.
|
||||
|
||||
## Planned Breaking API Changes (16.0)
|
||||
|
||||
### Behavior Changed: `crashReporter` implementation switched to Crashpad on Linux
|
||||
@@ -27,8 +60,36 @@ Linux, including that long values will no longer be split between annotations
|
||||
appended with `__1`, `__2` and so on, and instead will be truncated at the
|
||||
(new, longer) annotation value limit.
|
||||
|
||||
### Deprecated: `desktopCapturer.getSources` in the renderer
|
||||
|
||||
Usage of the `desktopCapturer.getSources` API in the renderer has been
|
||||
deprecated and will be removed. This change improves the default security of
|
||||
Electron apps.
|
||||
|
||||
See [here](#removed-desktopcapturergetsources-in-the-renderer) for details on
|
||||
how to replace this API in your app.
|
||||
|
||||
## Planned Breaking API Changes (14.0)
|
||||
|
||||
### Removed: `remote` module
|
||||
|
||||
The `remote` module was deprecated in Electron 12, and will be removed in
|
||||
Electron 14. It is replaced by the
|
||||
[`@electron/remote`](https://github.com/electron/remote) module.
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 12:
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
```
|
||||
|
||||
```js
|
||||
// Replace with:
|
||||
const { BrowserWindow } = require('@electron/remote')
|
||||
|
||||
// In the main process:
|
||||
require('@electron/remote/main').initialize()
|
||||
```
|
||||
|
||||
### Removed: `app.allowRendererProcessReuse`
|
||||
|
||||
The `app.allowRendererProcessReuse` property will be removed as part of our plan to
|
||||
@@ -571,7 +632,7 @@ error.
|
||||
### API Changed: `shell.openItem` is now `shell.openPath`
|
||||
|
||||
The `shell.openItem` API has been replaced with an asynchronous `shell.openPath` API.
|
||||
You can see the original API proposal and reasoning [here](https://github.com/electron/governance/blob/master/wg-api/spec-documents/shell-openitem.md).
|
||||
You can see the original API proposal and reasoning [here](https://github.com/electron/governance/blob/main/wg-api/spec-documents/shell-openitem.md).
|
||||
|
||||
## Planned Breaking API Changes (8.0)
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ These guides are intended for people working on the Electron project itself.
|
||||
For guides on Electron app development, see
|
||||
[/docs/README.md](../README.md#guides-and-tutorials).
|
||||
|
||||
* [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md)
|
||||
* [Contributing to Electron](https://github.com/electron/electron/blob/master/CONTRIBUTING.md)
|
||||
* [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md)
|
||||
* [Contributing to Electron](https://github.com/electron/electron/blob/main/CONTRIBUTING.md)
|
||||
* [Issues](issues.md)
|
||||
* [Pull Requests](pull-requests.md)
|
||||
* [Documentation Styleguide](coding-style.md#documentation)
|
||||
|
||||
@@ -8,7 +8,7 @@ Example Use Case:
|
||||
* We need `VS15.9` and we have `VS15.7` installed; this would require us to update an Azure image.
|
||||
|
||||
1. Identify the image you wish to modify.
|
||||
* In [appveyor.yml](https://github.com/electron/electron/blob/master/appveyor.yml), the image is identified by the property *image*.
|
||||
* In [appveyor.yml](https://github.com/electron/electron/blob/main/appveyor.yml), the image is identified by the property *image*.
|
||||
* The names used correspond to the *"images"* defined for a build cloud, eg the [libcc-20 cloud](https://windows-ci.electronjs.org/build-clouds/8).
|
||||
* Find the image you wish to modify in the build cloud and make note of the **VHD Blob Path** for that image, which is the value for that corresponding key.
|
||||
* You will need this URI path to copy into a new image.
|
||||
|
||||
@@ -65,8 +65,8 @@ origin URLs.
|
||||
$ cd src/electron
|
||||
$ git remote remove origin
|
||||
$ git remote add origin https://github.com/electron/electron
|
||||
$ git checkout master
|
||||
$ git branch --set-upstream-to=origin/master
|
||||
$ git checkout main
|
||||
$ git branch --set-upstream-to=origin/main
|
||||
$ cd -
|
||||
```
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# Creating an Electron Browser Module API
|
||||
# Creating a New Electron Browser Module
|
||||
|
||||
Welcome to the Electron API guide! If you are unfamiliar with creating electron APIs within the `browser` module, this guide serves as a checklist for some of the necessary steps that you will need to implement.
|
||||
Welcome to the Electron API guide! If you are unfamiliar with creating a new Electron API module within the [`browser`](https://github.com/electron/electron/tree/main/shell/browser) directory, this guide serves as a checklist for some of the necessary steps that you will need to implement.
|
||||
|
||||
This is not a comprehensive end-all guide to creating an Electron Browser API, rather an outline documenting some of the more unintuitive steps.
|
||||
|
||||
## Adding Your Files To Electron's Project Configuration
|
||||
## Add your files to Electron's project configuration
|
||||
|
||||
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](https://github.com/electron/electron/blob/main/filenames.gni).
|
||||
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](https://github.com/electron/electron/blob/main/filenames.gni).
|
||||
|
||||
You will need to append your api file names alphabetically into the appropriate files like so:
|
||||
You will need to append your API file names alphabetically into the appropriate files like so:
|
||||
|
||||
```cpp
|
||||
```cpp title='filenames.gni'
|
||||
lib_sources = [
|
||||
"path/to/api/api_name.cc",
|
||||
"path/to/api/api_name.h",
|
||||
@@ -32,13 +32,13 @@ lib_sources_linux = [
|
||||
]
|
||||
```
|
||||
|
||||
Note that the Windows, MacOS and Linux array additions are optional and should only be added if your API has specific platform implementations.
|
||||
Note that the Windows, macOS and Linux array additions are optional and should only be added if your API has specific platform implementations.
|
||||
|
||||
## Create API Documentation
|
||||
## Create API documentation
|
||||
|
||||
Type definitions are generated by Electron using [`docs-parser`](https://github.com/electron/docs-parser) and [`typescript-definitions`](https://github.com/electron/typescript-definitions). This step is necessary to ensure consistency across Electron's API documentation. This means that for your API type definition to appear in the `electron.d.ts` file, we must create a `.md` file. Examples can be found in [this folder](https://github.com/electron/electron/tree/main/docs/api).
|
||||
Type definitions are generated by Electron using [`@electron/docs-parser`](https://github.com/electron/docs-parser) and [`@electron/typescript-definitions`](https://github.com/electron/typescript-definitions). This step is necessary to ensure consistency across Electron's API documentation. This means that for your API type definition to appear in the `electron.d.ts` file, we must create a `.md` file. Examples can be found in [this folder](https://github.com/electron/electron/tree/main/docs/api).
|
||||
|
||||
## Setting Up `ObjectTemplateBuilder` and `Wrappable`
|
||||
## Set up `ObjectTemplateBuilder` and `Wrappable`
|
||||
|
||||
Electron constructs its modules using [`object_template_builder`](https://www.electronjs.org/blog/from-native-to-js#mateobjecttemplatebuilder).
|
||||
|
||||
@@ -48,7 +48,7 @@ Here is a basic example of code that you may need to add, in order to incorporat
|
||||
|
||||
In your `api_name.h` file:
|
||||
|
||||
```cpp
|
||||
```cpp title='api_name.h'
|
||||
|
||||
#ifndef SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
|
||||
#define SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
|
||||
@@ -75,7 +75,7 @@ class ApiName : public gin::Wrappable<ApiName> {
|
||||
|
||||
In your `api_name.cc` file:
|
||||
|
||||
```cpp
|
||||
```cpp title='api_name.cc'
|
||||
#include "shell/browser/api/electron_api_safe_storage.h"
|
||||
|
||||
#include "shell/browser/browser.h"
|
||||
@@ -125,15 +125,11 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
} // namespace
|
||||
```
|
||||
|
||||
## Link Your Electron API With Node
|
||||
## Link your Electron API with Node
|
||||
|
||||
To learn about how Electron links with Node, [click here.](https://www.electronjs.org/blog/electron-internals-using-node-as-a-library#link-node-with-electron)
|
||||
In the [`typings/internal-ambient.d.ts`](https://github.com/electron/electron/blob/main/typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
|
||||
|
||||
In the [`internal-ambient.d.ts`](https://github.com/electron/electron/blob/main/typings/internal-ambient.d.ts) file:
|
||||
|
||||
We need to append a new property onto the `Process` interface found in this file like so:
|
||||
|
||||
```ts
|
||||
```ts title='typings/internal-ambient.d.ts'
|
||||
interface Process {
|
||||
_linkedBinding(name: 'electron_browser_{api_name}', Electron.ApiName);
|
||||
}
|
||||
@@ -141,22 +137,22 @@ interface Process {
|
||||
|
||||
At the very bottom of your `api_name.cc` file:
|
||||
|
||||
```cpp
|
||||
```cpp title='api_name.cc'
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_{api_name},Initialize)
|
||||
```
|
||||
|
||||
In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file:
|
||||
In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
|
||||
|
||||
Add your node binding name to Electron's built-in modules.
|
||||
|
||||
```cpp
|
||||
```cpp title='shell/common/node_bindings.cc'
|
||||
#define ELECTRON_BUILTIN_MODULES(V) \
|
||||
V(electron_browser_{api_name})
|
||||
```
|
||||
|
||||
## Expose Your API to TypeScript
|
||||
> Note: More technical details on how Node links with Electron can be found on [our blog](https://www.electronjs.org/blog/electron-internals-using-node-as-a-library#link-node-with-electron).
|
||||
|
||||
### Export Your API as a module
|
||||
## Expose your API to TypeScript
|
||||
|
||||
### Export your API as a module
|
||||
|
||||
We will need to create a new TypeScript file in the path that follows:
|
||||
|
||||
@@ -164,11 +160,11 @@ We will need to create a new TypeScript file in the path that follows:
|
||||
|
||||
An example of the contents of this file can be found [here](https://github.com/electron/electron/blob/main/lib/browser/api/native-image.ts).
|
||||
|
||||
### Expose Your module to TypeScript
|
||||
### Expose your module to TypeScript
|
||||
|
||||
Add your module to the module list found at `"lib/browser/api/module-list.ts"` like so:
|
||||
|
||||
```typescript
|
||||
```typescript title='lib/browser/api/module-list.ts'
|
||||
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'apiName', loader: () => require('./api-name') },
|
||||
];
|
||||
@@ -26,7 +26,9 @@ you prefer a graphical interface.
|
||||
* **.lldbinit**: Create or edit `~/.lldbinit` to allow Chromium code to be properly source-mapped.
|
||||
|
||||
```text
|
||||
command script import ~/electron/src/tools/lldb/lldbinit.py
|
||||
# e.g: ['~/electron/src/tools/lldb']
|
||||
script sys.path[:0] = ['<...path/to/electron/src/tools/lldb>']
|
||||
script import lldbinit
|
||||
```
|
||||
|
||||
## Attaching to and Debugging Electron
|
||||
|
||||
@@ -72,4 +72,4 @@ to try NW.js.
|
||||
|
||||
[nwjs]: https://nwjs.io/
|
||||
[electron-modules]: https://www.npmjs.com/search?q=electron
|
||||
[node-bindings]: https://github.com/electron/electron/tree/master/lib/common
|
||||
[node-bindings]: https://github.com/electron/electron/tree/main/lib/common
|
||||
|
||||
@@ -45,10 +45,10 @@ Once you've built the project locally, you're ready to start making changes!
|
||||
### Step 3: Branch
|
||||
|
||||
To keep your development environment organized, create local branches to
|
||||
hold your work. These should be branched directly off of the `master` branch.
|
||||
hold your work. These should be branched directly off of the `main` branch.
|
||||
|
||||
```sh
|
||||
$ git checkout -b my-branch -t upstream/master
|
||||
$ git checkout -b my-branch -t upstream/main
|
||||
```
|
||||
|
||||
## Making Changes
|
||||
@@ -134,11 +134,11 @@ Once you have committed your changes, it is a good idea to use `git rebase`
|
||||
|
||||
```sh
|
||||
$ git fetch upstream
|
||||
$ git rebase upstream/master
|
||||
$ git rebase upstream/main
|
||||
```
|
||||
|
||||
This ensures that your working branch has the latest changes from `electron/electron`
|
||||
master.
|
||||
main.
|
||||
|
||||
### Step 7: Test
|
||||
|
||||
@@ -189,7 +189,7 @@ the requirements below.
|
||||
|
||||
Bug fixes and new features should include tests and possibly benchmarks.
|
||||
|
||||
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
|
||||
Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
|
||||
-->
|
||||
```
|
||||
|
||||
@@ -222,7 +222,7 @@ seem unfamiliar, refer to this
|
||||
#### Approval and Request Changes Workflow
|
||||
|
||||
All pull requests require approval from a
|
||||
[Code Owner](https://github.com/electron/electron/blob/master/.github/CODEOWNERS)
|
||||
[Code Owner](https://github.com/electron/electron/blob/main/.github/CODEOWNERS)
|
||||
of the area you modified in order to land. Whenever a maintainer reviews a pull
|
||||
request they may request changes. These may be small, such as fixing a typo, or
|
||||
may involve substantive changes. Such requests are intended to be helpful, but
|
||||
|
||||
17
docs/fiddles/features/web-bluetooth/index.html
Normal file
17
docs/fiddles/features/web-bluetooth/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Web Bluetooth API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Web Bluetooth API</h1>
|
||||
|
||||
<button id="clickme">Test Bluetooth</button>
|
||||
|
||||
<p>Currently selected bluetooth device: <strong id="device-name""></strong></p>
|
||||
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
30
docs/fiddles/features/web-bluetooth/main.js
Normal file
30
docs/fiddles/features/web-bluetooth/main.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
|
||||
event.preventDefault()
|
||||
if (deviceList && deviceList.length > 0) {
|
||||
callback(deviceList[0].deviceId)
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
8
docs/fiddles/features/web-bluetooth/renderer.js
Normal file
8
docs/fiddles/features/web-bluetooth/renderer.js
Normal file
@@ -0,0 +1,8 @@
|
||||
async function testIt() {
|
||||
const device = await navigator.bluetooth.requestDevice({
|
||||
acceptAllDevices: true
|
||||
})
|
||||
document.getElementById('device-name').innerHTML = device.name || `ID: ${device.id}`
|
||||
}
|
||||
|
||||
document.getElementById('clickme').addEventListener('click',testIt)
|
||||
21
docs/fiddles/features/web-hid/index.html
Normal file
21
docs/fiddles/features/web-hid/index.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>WebHID API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebHID API</h1>
|
||||
|
||||
<button id="clickme">Test WebHID</button>
|
||||
|
||||
<h3>HID devices automatically granted access via <i>setDevicePermissionHandler</i></h3>
|
||||
<div id="granted-devices"></div>
|
||||
|
||||
<h3>HID devices automatically granted access via <i>select-hid-device</i></h3>
|
||||
<div id="granted-devices2"></div>
|
||||
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
50
docs/fiddles/features/web-hid/main.js
Normal file
50
docs/fiddles/features/web-hid/main.js
Normal file
@@ -0,0 +1,50 @@
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('select-hid-device', (event, details, callback) => {
|
||||
event.preventDefault()
|
||||
if (details.deviceList && details.deviceList.length > 0) {
|
||||
callback(details.deviceList[0].deviceId)
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('hid-device-added', (event, device) => {
|
||||
console.log('hid-device-added FIRED WITH', device)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('hid-device-removed', (event, device) => {
|
||||
console.log('hid-device-removed FIRED WITH', device)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
|
||||
if (permission === 'hid' && details.securityOrigin === 'file:///') {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (details.deviceType === 'hid' && details.origin === 'file://') {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
19
docs/fiddles/features/web-hid/renderer.js
Normal file
19
docs/fiddles/features/web-hid/renderer.js
Normal file
@@ -0,0 +1,19 @@
|
||||
async function testIt() {
|
||||
const grantedDevices = await navigator.hid.getDevices()
|
||||
let grantedDeviceList = ''
|
||||
grantedDevices.forEach(device => {
|
||||
grantedDeviceList += `<hr>${device.productName}</hr>`
|
||||
})
|
||||
document.getElementById('granted-devices').innerHTML = grantedDeviceList
|
||||
const grantedDevices2 = await navigator.hid.requestDevice({
|
||||
filters: []
|
||||
})
|
||||
|
||||
grantedDeviceList = ''
|
||||
grantedDevices2.forEach(device => {
|
||||
grantedDeviceList += `<hr>${device.productName}</hr>`
|
||||
})
|
||||
document.getElementById('granted-devices2').innerHTML = grantedDeviceList
|
||||
}
|
||||
|
||||
document.getElementById('clickme').addEventListener('click',testIt)
|
||||
16
docs/fiddles/features/web-serial/index.html
Normal file
16
docs/fiddles/features/web-serial/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Web Serial API</title>
|
||||
<body>
|
||||
<h1>Web Serial API</h1>
|
||||
|
||||
<button id="clickme">Test Web Serial API</button>
|
||||
|
||||
<p>Matching Arduino Uno device: <strong id="device-name""></strong></p>
|
||||
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
54
docs/fiddles/features/web-serial/main.js
Normal file
54
docs/fiddles/features/web-serial/main.js
Normal file
@@ -0,0 +1,54 @@
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
|
||||
event.preventDefault()
|
||||
if (portList && portList.length > 0) {
|
||||
callback(portList[0].portId)
|
||||
} else {
|
||||
callback('') //Could not find any matching devices
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('serial-port-added', (event, port) => {
|
||||
console.log('serial-port-added FIRED WITH', port)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
|
||||
console.log('serial-port-removed FIRED WITH', port)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
|
||||
if (permission === 'serial' && details.securityOrigin === 'file:///') {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (details.deviceType === 'serial' && details.origin === 'file://') {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
mainWindow.webContents.openDevTools()
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
19
docs/fiddles/features/web-serial/renderer.js
Normal file
19
docs/fiddles/features/web-serial/renderer.js
Normal file
@@ -0,0 +1,19 @@
|
||||
async function testIt() {
|
||||
const filters = [
|
||||
{ usbVendorId: 0x2341, usbProductId: 0x0043 },
|
||||
{ usbVendorId: 0x2341, usbProductId: 0x0001 }
|
||||
];
|
||||
try {
|
||||
const port = await navigator.serial.requestPort({filters});
|
||||
const portInfo = port.getInfo();
|
||||
document.getElementById('device-name').innerHTML = `vendorId: ${portInfo.usbVendorId} | productId: ${portInfo.usbProductId} `
|
||||
} catch (ex) {
|
||||
if (ex.name === 'NotFoundError') {
|
||||
document.getElementById('device-name').innerHTML = 'Device NOT found'
|
||||
} else {
|
||||
document.getElementById('device-name').innerHTML = ex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('clickme').addEventListener('click',testIt)
|
||||
118
docs/glossary.md
118
docs/glossary.md
@@ -4,15 +4,39 @@ This page defines some terminology that is commonly used in Electron development
|
||||
|
||||
### ASAR
|
||||
|
||||
ASAR stands for Atom Shell Archive Format. An [asar][asar] archive is a simple
|
||||
ASAR stands for Atom Shell Archive Format. An [asar] archive is a simple
|
||||
`tar`-like format that concatenates files into a single file. Electron can read
|
||||
arbitrary files from it without unpacking the whole file.
|
||||
|
||||
The ASAR format was created primarily to improve performance on Windows... TODO
|
||||
The ASAR format was created primarily to improve performance on Windows when
|
||||
reading large quantities of small files (e.g. when loading your app's JavaScript
|
||||
dependency tree from `node_modules`).
|
||||
|
||||
### code signing
|
||||
|
||||
Code signing is a process where an app developer digitally signs their code to
|
||||
ensure that it hasn't been tampered with after packaging. Both Windows and
|
||||
macOS implement their own version of code signing. As a desktop app developer,
|
||||
it's important that you sign your code if you plan on distributing it to the
|
||||
general public.
|
||||
|
||||
For more information, read the [Code Signing] tutorial.
|
||||
|
||||
### context isolation
|
||||
|
||||
Context isolation is a security measure in Electron that ensures that your
|
||||
preload script cannot leak privileged Electron or Node.js APIs to the web
|
||||
contents in your renderer process. With context isolation enabled, the
|
||||
only way to expose APIs from your preload script is through the
|
||||
`contextBridge` API.
|
||||
|
||||
For more information, read the [Context Isolation] tutorial.
|
||||
|
||||
See also: [preload script](#preload-script), [renderer process](#renderer-process)
|
||||
|
||||
### CRT
|
||||
|
||||
The C Run-time Library (CRT) is the part of the C++ Standard Library that
|
||||
The C Runtime Library (CRT) is the part of the C++ Standard Library that
|
||||
incorporates the ISO C99 standard library. The Visual C++ libraries that
|
||||
implement the CRT support native code development, and both mixed native and
|
||||
managed code, and pure managed code for .NET development.
|
||||
@@ -20,8 +44,7 @@ managed code, and pure managed code for .NET development.
|
||||
### DMG
|
||||
|
||||
An Apple Disk Image is a packaging format used by macOS. DMG files are
|
||||
commonly used for distributing application "installers". [electron-builder]
|
||||
supports `dmg` as a build target.
|
||||
commonly used for distributing application "installers".
|
||||
|
||||
### IME
|
||||
|
||||
@@ -31,19 +54,15 @@ keyboards to input Chinese, Japanese, Korean and Indic characters.
|
||||
|
||||
### IDL
|
||||
|
||||
Interface description language. Write function signatures and data types in a format that can be used to generate interfaces in Java, C++, JavaScript, etc.
|
||||
Interface description language. Write function signatures and data types in a
|
||||
format that can be used to generate interfaces in Java, C++, JavaScript, etc.
|
||||
|
||||
### IPC
|
||||
|
||||
IPC stands for Inter-Process Communication. Electron uses IPC to send
|
||||
serialized JSON messages between the [main] and [renderer] processes.
|
||||
IPC stands for inter-process communication. Electron uses IPC to send
|
||||
serialized JSON messages between the main and renderer processes.
|
||||
|
||||
### libchromiumcontent
|
||||
|
||||
A shared library that includes the [Chromium Content module] and all its
|
||||
dependencies (e.g., Blink, [V8], etc.). Also referred to as "libcc".
|
||||
|
||||
- [github.com/electron/libchromiumcontent](https://github.com/electron/libchromiumcontent)
|
||||
see also: [main process](#main-process), [renderer process](#renderer-process)
|
||||
|
||||
### main process
|
||||
|
||||
@@ -68,10 +87,22 @@ MAS, see the [Mac App Store Submission Guide].
|
||||
|
||||
### Mojo
|
||||
|
||||
An IPC system for communicating intra- or inter-process, and that's important because Chrome is keen on being able to split its work into separate processes or not, depending on memory pressures etc.
|
||||
An IPC system for communicating intra- or inter-process, and that's important
|
||||
because Chrome is keen on being able to split its work into separate processes
|
||||
or not, depending on memory pressures etc.
|
||||
|
||||
See https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md
|
||||
|
||||
See also: [IPC](#ipc)
|
||||
|
||||
### MSI
|
||||
|
||||
On Windows, MSI packages are used by the Windows Installer
|
||||
(also known as Microsoft Installer) service to install and configure
|
||||
applications.
|
||||
|
||||
More information can be found in [Microsoft's documentation][msi].
|
||||
|
||||
### native modules
|
||||
|
||||
Native modules (also called [addons] in
|
||||
@@ -85,22 +116,33 @@ likely to use a different V8 version from the Node binary installed in your
|
||||
system, you have to manually specify the location of Electron’s headers when
|
||||
building native modules.
|
||||
|
||||
See also [Using Native Node Modules].
|
||||
For more information, read the [Native Node Modules] tutorial.
|
||||
|
||||
### NSIS
|
||||
### notarization
|
||||
|
||||
Nullsoft Scriptable Install System is a script-driven Installer
|
||||
authoring tool for Microsoft Windows. It is released under a combination of
|
||||
free software licenses, and is a widely-used alternative to commercial
|
||||
proprietary products like InstallShield. [electron-builder] supports NSIS
|
||||
as a build target.
|
||||
Notarization is a macOS-specific process where a developer can send a
|
||||
code-signed app to Apple servers to get verified for malicious
|
||||
components through an automated service.
|
||||
|
||||
See also: [code signing](#code-signing)
|
||||
|
||||
### OSR
|
||||
|
||||
OSR (Off-screen rendering) can be used for loading heavy page in
|
||||
OSR (offscreen rendering) can be used for loading heavy page in
|
||||
background and then displaying it after (it will be much faster).
|
||||
It allows you to render page without showing it on screen.
|
||||
|
||||
For more information, read the [Offscreen Rendering][osr] tutorial.
|
||||
|
||||
### preload script
|
||||
|
||||
Preload scripts contain code that executes in a renderer process
|
||||
before its web contents begin loading. These scripts run within
|
||||
the renderer context, but are granted more privileges by having
|
||||
access to Node.js APIs.
|
||||
|
||||
See also: [renderer process](#renderer-process), [context isolation](#context-isolation)
|
||||
|
||||
### process
|
||||
|
||||
A process is an instance of a computer program that is being executed. Electron
|
||||
@@ -120,13 +162,17 @@ The renderer process is a browser window in your app. Unlike the main process,
|
||||
there can be multiple of these and each is run in a separate process.
|
||||
They can also be hidden.
|
||||
|
||||
In normal browsers, web pages usually run in a sandboxed environment and are not
|
||||
allowed access to native resources. Electron users, however, have the power to
|
||||
use Node.js APIs in web pages allowing lower level operating system
|
||||
interactions.
|
||||
|
||||
See also: [process](#process), [main process](#main-process)
|
||||
|
||||
### sandbox
|
||||
|
||||
The sandbox is a security feature inherited from Chromium that restricts
|
||||
your renderer processes to a limited set of permissions.
|
||||
|
||||
For more information, read the [Process Sandboxing] tutorial.
|
||||
|
||||
See also: [process](#process)
|
||||
|
||||
### Squirrel
|
||||
|
||||
Squirrel is an open-source framework that enables Electron apps to update
|
||||
@@ -174,13 +220,15 @@ embedded content.
|
||||
|
||||
[addons]: https://nodejs.org/api/addons.html
|
||||
[asar]: https://github.com/electron/asar
|
||||
[autoUpdater]: api/auto-updater.md
|
||||
[Chromium Content module]: https://www.chromium.org/developers/content-module
|
||||
[electron-builder]: https://github.com/electron-userland/electron-builder
|
||||
[libchromiumcontent]: #libchromiumcontent
|
||||
[Mac App Store Submission Guide]: tutorial/mac-app-store-submission-guide.md
|
||||
[autoupdater]: api/auto-updater.md
|
||||
[code signing]: tutorial/code-signing.md
|
||||
[context isolation]: tutorial/context-isolation.md
|
||||
[mac app store submission guide]: tutorial/mac-app-store-submission-guide.md
|
||||
[main]: #main-process
|
||||
[msi]: https://docs.microsoft.com/en-us/windows/win32/msi/windows-installer-portal
|
||||
[offscreen rendering]: tutorial/offscreen-rendering.md
|
||||
[process sandboxing]: tutorial/sandbox.md
|
||||
[renderer]: #renderer-process
|
||||
[userland]: #userland
|
||||
[Using Native Node Modules]: tutorial/using-native-node-modules.md
|
||||
[V8]: #v8
|
||||
[using native node modules]: tutorial/using-native-node-modules.md
|
||||
[v8]: #v8
|
||||
|
||||
@@ -88,14 +88,15 @@ without meaning any harm:
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Note that up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
To see all of this in action, check out Electron Fiddle's source code,
|
||||
[especially its `electron-forge` configuration
|
||||
file](https://github.com/electron/fiddle/blob/master/forge.config.js).
|
||||
@@ -165,14 +166,15 @@ without meaning any harm:
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
## Mac App Store
|
||||
|
||||
See the [Mac App Store Guide].
|
||||
|
||||
@@ -4,39 +4,38 @@
|
||||
|
||||
Context Isolation is a feature that ensures that both your `preload` scripts and Electron's internal logic run in a separate context to the website you load in a [`webContents`](../api/web-contents.md). This is important for security purposes as it helps prevent the website from accessing Electron internals or the powerful APIs your preload script has access to.
|
||||
|
||||
This means that the `window` object that your preload script has access to is actually a **different** object than the website would have access to. For example, if you set `window.hello = 'wave'` in your preload script and context isolation is enabled `window.hello` will be undefined if the website tries to access it.
|
||||
This means that the `window` object that your preload script has access to is actually a **different** object than the website would have access to. For example, if you set `window.hello = 'wave'` in your preload script and context isolation is enabled, `window.hello` will be undefined if the website tries to access it.
|
||||
|
||||
Every single application should have context isolation enabled and from Electron 12 it will be enabled by default.
|
||||
|
||||
## How do I enable it?
|
||||
|
||||
From Electron 12, it will be enabled by default. For lower versions it is an option in the `webPreferences` option when constructing `new BrowserWindow`'s.
|
||||
|
||||
```javascript
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
contextIsolation: true
|
||||
}
|
||||
})
|
||||
```
|
||||
Context isolation has been enabled by default since Electron 12, and it is a recommended security setting for _all applications_.
|
||||
|
||||
## Migration
|
||||
|
||||
> I used to provide APIs from my preload script using `window.X = apiObject` now what?
|
||||
> Without context isolation, I used to provide APIs from my preload script using `window.X = apiObject`. Now what?
|
||||
|
||||
Exposing APIs from your preload script to the loaded website is a common usecase and there is a dedicated module in Electron to help you do this in a painless way.
|
||||
### Before: context isolation disabled
|
||||
|
||||
**Before: With context isolation disabled**
|
||||
Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script:
|
||||
|
||||
```javascript
|
||||
```javascript title='preload.js'
|
||||
// preload with contextIsolation disabled
|
||||
window.myAPI = {
|
||||
doAThing: () => {}
|
||||
}
|
||||
```
|
||||
|
||||
**After: With context isolation enabled**
|
||||
The `doAThing()` function could then be used directly in the renderer process:
|
||||
|
||||
```javascript
|
||||
```javascript title='renderer.js'
|
||||
// use the exposed API in the renderer
|
||||
window.myAPI.doAThing()
|
||||
```
|
||||
|
||||
### After: context isolation enabled
|
||||
|
||||
There is a dedicated module in Electron to help you do this in a painless way. The [`contextBridge`](../api/context-bridge.md) module can be used to **safely** expose APIs from your preload script's isolated context to the context the website is running in. The API will also be accessible from the website on `window.myAPI` just like it was before.
|
||||
|
||||
```javascript title='preload.js'
|
||||
// preload with contextIsolation enabled
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
@@ -44,26 +43,63 @@ contextBridge.exposeInMainWorld('myAPI', {
|
||||
})
|
||||
```
|
||||
|
||||
The [`contextBridge`](../api/context-bridge.md) module can be used to **safely** expose APIs from the isolated context your preload script runs in to the context the website is running in. The API will also be accessible from the website on `window.myAPI` just like it was before.
|
||||
```javascript title='renderer.js'
|
||||
// use the exposed API in the renderer
|
||||
window.myAPI.doAThing()
|
||||
```
|
||||
|
||||
You should read the `contextBridge` documentation linked above to fully understand its limitations. For instance you can't send custom prototypes or symbols over the bridge.
|
||||
Please read the `contextBridge` documentation linked above to fully understand its limitations. For instance, you can't send custom prototypes or symbols over the bridge.
|
||||
|
||||
## Security Considerations
|
||||
## Security considerations
|
||||
|
||||
Just enabling `contextIsolation` and using `contextBridge` does not automatically mean that everything you do is safe. For instance this code is **unsafe**.
|
||||
Just enabling `contextIsolation` and using `contextBridge` does not automatically mean that everything you do is safe. For instance, this code is **unsafe**.
|
||||
|
||||
```javascript
|
||||
```javascript title='preload.js'
|
||||
// ❌ Bad code
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
send: ipcRenderer.send
|
||||
})
|
||||
```
|
||||
|
||||
It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
|
||||
It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages, which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
|
||||
|
||||
```javascript
|
||||
```javascript title='preload.js'
|
||||
// ✅ Good code
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
loadPreferences: () => ipcRenderer.invoke('load-prefs')
|
||||
})
|
||||
```
|
||||
|
||||
## Usage with TypeScript
|
||||
|
||||
If you're building your Electron app with TypeScript, you'll want to add types to your APIs exposed over the context bridge. The renderer's `window` object won't have the correct typings unless you extend the types with a [declaration file].
|
||||
|
||||
For example, given this `preload.ts` script:
|
||||
|
||||
```typescript title='preload.ts'
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
loadPreferences: () => ipcRenderer.invoke('load-prefs')
|
||||
})
|
||||
```
|
||||
|
||||
You can create a `renderer.d.ts` declaration file and globally augment the `Window` interface:
|
||||
|
||||
```typescript title='renderer.d.ts'
|
||||
export interface IElectronAPI {
|
||||
loadPreferences: () => Promise<void>,
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
electronAPI: IElectronAPI
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process:
|
||||
|
||||
```typescript title='renderer.ts'
|
||||
window.electronAPI.loadPreferences()
|
||||
```
|
||||
|
||||
[declaration file]: https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html
|
||||
|
||||
99
docs/tutorial/devices.md
Normal file
99
docs/tutorial/devices.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Device Access
|
||||
|
||||
Like Chromium based browsers, Electron provides access to device hardware
|
||||
through web APIs. For the most part these APIs work like they do in a browser,
|
||||
but there are some differences that need to be taken into account. The primary
|
||||
difference between Electron and browsers is what happens when device access is
|
||||
requested. In a browser, users are presented with a popup where they can grant
|
||||
access to an individual device. In Electron APIs are provided which can be
|
||||
used by a developer to either automatically pick a device or prompt users to
|
||||
pick a device via a developer created interface.
|
||||
|
||||
## Web Bluetooth API
|
||||
|
||||
The [Web Bluetooth API](https://web.dev/bluetooth/) can be used to communicate
|
||||
with bluetooth devices. In order to use this API in Electron, developers will
|
||||
need to handle the [`select-bluetooth-device` event on the webContents](../api/web-contents.md#event-select-bluetooth-device)
|
||||
associated with the device request.
|
||||
|
||||
### Example
|
||||
|
||||
This example demonstrates an Electron application that automatically selects
|
||||
the first available bluetooth device when the `Test Bluetooth` button is
|
||||
clicked.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/web-bluetooth'
|
||||
|
||||
```
|
||||
|
||||
## WebHID API
|
||||
|
||||
The [WebHID API](https://web.dev/hid/) can be used to access HID devices such
|
||||
as keyboards and gamepads. Electron provides several APIs for working with
|
||||
the WebHID API:
|
||||
|
||||
* The [`select-hid-device` event on the Session](../api/session.md#event-select-hid-device)
|
||||
can be used to select a HID device when a call to
|
||||
`navigator.hid.requestDevice` is made. Additionally the [`hid-device-added`](../api/session.md#event-hid-device-added)
|
||||
and [`hid-device-removed`](../api/session.md#event-hid-device-removed) events
|
||||
on the Session can be used to handle devices being plugged in or unplugged during the
|
||||
`navigator.hid.requestDevice` process.
|
||||
* [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
|
||||
can be used to provide default permissioning to devices without first calling
|
||||
for permission to devices via `navigator.hid.requestDevice`. Additionally,
|
||||
the default behavior of Electron is to store granted device permision through
|
||||
the lifetime of the corresponding WebContents. If longer term storage is
|
||||
needed, a developer can store granted device permissions (eg when handling
|
||||
the `select-hid-device` event) and then read from that storage with
|
||||
`setDevicePermissionHandler`.
|
||||
* [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler)
|
||||
can be used to disable HID access for specific origins.
|
||||
|
||||
### Blocklist
|
||||
|
||||
By default Electron employs the same [blocklist](https://github.com/WICG/webhid/blob/main/blocklist.txt)
|
||||
used by Chromium. If you wish to override this behavior, you can do so by
|
||||
setting the `disable-hid-blocklist` flag:
|
||||
|
||||
```javascript
|
||||
app.commandLine.appendSwitch('disable-hid-blocklist')
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
This example demonstrates an Electron application that automatically selects
|
||||
HID devices through [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
|
||||
and through [`select-hid-device` event on the Session](../api/session.md#event-select-hid-device)
|
||||
when the `Test WebHID` button is clicked.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/web-hid'
|
||||
|
||||
```
|
||||
|
||||
## Web Serial API
|
||||
|
||||
The [Web Serial API](https://web.dev/serial/) can be used to access serial
|
||||
devices that are connected via serial port, USB, or Bluetooth. In order to use
|
||||
this API in Electron, developers will need to handle the
|
||||
[`select-serial-port` event on the Session](../api/session.md#event-select-serial-port)
|
||||
associated with the serial port request.
|
||||
|
||||
There are several additional APIs for working with the Web Serial API:
|
||||
|
||||
* The [`serial-port-added`](../api/session.md#event-serial-port-added)
|
||||
and [`serial-port-removed`](../api/session.md#event-serial-port-removed) events
|
||||
on the Session can be used to handle devices being plugged in or unplugged during the
|
||||
`navigator.serial.requestPort` process.
|
||||
* [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler)
|
||||
can be used to disable serial access for specific origins.
|
||||
|
||||
### Example
|
||||
|
||||
This example demonstrates an Electron application that automatically selects
|
||||
the first available Arduino Uno serial device (if connected) through
|
||||
[`select-serial-port` event on the Session](../api/session.md#event-select-serial-port)
|
||||
when the `Test Web Serial` button is clicked.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/web-serial'
|
||||
|
||||
```
|
||||
@@ -23,5 +23,6 @@ Special notes:
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | TBD |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | TBD |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | v14.17 |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | v16.5 |
|
||||
| 16.0.0 | -- | 2021-Sep-23 | 2021-Nov-16 | M96 | TBD |
|
||||
|
||||
@@ -12,7 +12,7 @@ Fuses are the solution to this problem, at a high level they are "magic bits" in
|
||||
|
||||
### The easy way
|
||||
|
||||
We've made a handy module `@electron/fuses` to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.
|
||||
We've made a handy module, [`@electron/fuses`](https://npmjs.com/package/@electron/fuses), to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.
|
||||
|
||||
```js
|
||||
require('@electron/fuses').flipFuses(
|
||||
@@ -51,4 +51,4 @@ Somewhere in the Electron binary there will be a sequence of bytes that look lik
|
||||
|
||||
To flip a fuse you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.
|
||||
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/master/build/fuses/fuses.json5).
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/main/build/fuses/fuses.json5).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Launching Your Electron App From A URL In Another App
|
||||
title: Launching Your Electron App From a URL In Another App
|
||||
description: This guide will take you through the process of setting your electron app as the default handler for a specific protocol.
|
||||
slug: launch-app-from-url-in-another-app
|
||||
hide_title: true
|
||||
@@ -11,7 +11,7 @@ hide_title: true
|
||||
|
||||
<!-- ✍ Update this section if you want to provide more details -->
|
||||
|
||||
This guide will take you through the process of setting your electron app as the default
|
||||
This guide will take you through the process of setting your Electron app as the default
|
||||
handler for a specific [protocol](https://www.electronjs.org/docs/api/protocol).
|
||||
|
||||
By the end of this tutorial, we will have set our app to intercept and handle
|
||||
@@ -22,16 +22,17 @@ we will use will be "`electron-fiddle://`".
|
||||
|
||||
### Main Process (main.js)
|
||||
|
||||
First we will import the required modules from `electron`. These modules help control our application life and create a native browser window.
|
||||
First, we will import the required modules from `electron`. These modules help
|
||||
control our application lifecycle and create a native browser window.
|
||||
|
||||
```js
|
||||
```javascript
|
||||
const { app, BrowserWindow, shell } = require('electron')
|
||||
const path = require('path')
|
||||
```
|
||||
|
||||
Next, we will proceed to register our application to handle all "`electron-fiddle://`" protocols.
|
||||
|
||||
```js
|
||||
```javascript
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
@@ -43,7 +44,7 @@ if (process.defaultApp) {
|
||||
|
||||
We will now define the function in charge of creating our browser window and load our application's `index.html` file.
|
||||
|
||||
```js
|
||||
```javascript
|
||||
const createWindow = () => {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
@@ -60,11 +61,11 @@ const createWindow = () => {
|
||||
|
||||
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
|
||||
|
||||
This code will be different in WindowsOS compared to MacOS and Linux. This is due to Windows requiring additional code in order to open the contents of the protocol link within the same electron instance. Read more about this [here](https://www.electronjs.org/docs/api/app#apprequestsingleinstancelock).
|
||||
This code will be different in Windows compared to MacOS and Linux. This is due to Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](https://www.electronjs.org/docs/api/app#apprequestsingleinstancelock).
|
||||
|
||||
### Windows code:
|
||||
#### Windows code:
|
||||
|
||||
```js
|
||||
```javascript
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
@@ -83,16 +84,16 @@ if (!gotTheLock) {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// handling the protocol. In this case, we choose to show an Error Box.
|
||||
// Handle the protocol. In this case, we choose to show an Error Box.
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### MacOS and Linux code:
|
||||
#### MacOS and Linux code:
|
||||
|
||||
```js
|
||||
```javascript
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
@@ -100,15 +101,15 @@ app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// handling the protocol. In this case, we choose to show an Error Box.
|
||||
// Handle the protocol. In this case, we choose to show an Error Box.
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
```
|
||||
|
||||
Finally, we will add some additional code to handle when someone closes our application
|
||||
Finally, we will add some additional code to handle when someone closes our application.
|
||||
|
||||
```js
|
||||
```javascript
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
@@ -117,40 +118,84 @@ app.on('window-all-closed', () => {
|
||||
})
|
||||
```
|
||||
|
||||
## Important Note:
|
||||
## Important notes
|
||||
|
||||
### Packaging
|
||||
|
||||
This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS `plist` for the app is updated to include the new protocol handler. If you're using [`electron-packager`](https://github.com/electron/electron-packager) then you
|
||||
can add the flag `--extend-info` with a path to the `plist` you've created. The one for this app is below:
|
||||
On macOS and Linux, this feature will only work when your app is packaged. It will not work when
|
||||
you're launching it in development from the command-line. When you package your app you'll need to
|
||||
make sure the macOS `Info.plist` and the Linux `.desktop` files for the app are updated to include
|
||||
the new protocol handler. Some of the Electron tools for bundling and distributing apps handle
|
||||
this for you.
|
||||
|
||||
### Plist
|
||||
#### [Electron Forge](https://electronforge.io)
|
||||
|
||||
```XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
If you're using Electron Forge, adjust `packagerConfig` for macOS support, and the configuration for
|
||||
the appropriate Linux makers for Linux support, in your [Forge
|
||||
configuration](https://www.electronforge.io/configuration) _(please note the following example only
|
||||
shows the bare minimum needed to add the configuration changes)_:
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"forge": {
|
||||
"packagerConfig": {
|
||||
"protocols": [
|
||||
{
|
||||
"name": "Electron Fiddle",
|
||||
"schemes": ["electron-fiddle"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-deb",
|
||||
"config": {
|
||||
"mimeType": ["x-scheme-handler/electron-fiddle"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### [Electron Packager](https://github.com/electron/electron-packager)
|
||||
|
||||
For macOS support:
|
||||
|
||||
If you're using Electron Packager's API, adding support for protocol handlers is similar to how
|
||||
Electron Forge is handled, except
|
||||
`protocols` is part of the Packager options passed to the `packager` function.
|
||||
|
||||
```javascript
|
||||
const packager = require('electron-packager')
|
||||
|
||||
packager({
|
||||
// ...other options...
|
||||
protocols: [
|
||||
{
|
||||
name: 'Electron Fiddle',
|
||||
schemes: ['electron-fiddle']
|
||||
}
|
||||
]
|
||||
|
||||
}).then(paths => console.log(`SUCCESS: Created ${paths.join(', ')}`))
|
||||
.catch(err => console.error(`ERROR: ${err.message}`))
|
||||
```
|
||||
|
||||
If you're using Electron Packager's CLI, use the `--protocol` and `--protocol-name` flags. For
|
||||
example:
|
||||
|
||||
```shell
|
||||
npx electron-packager . --protocol=electron-fiddle --protocol-name="Electron Fiddle"
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
After you start your electron app, you can now enter in a URL in your browser that contains the custom protocol, for example `"electron-fiddle://open"` and observe that the application will respond and show an error dialog box.
|
||||
After you start your Electron app, you can enter in a URL in your browser that contains the custom
|
||||
protocol, for example `"electron-fiddle://open"` and observe that the application will respond and
|
||||
show an error dialog box.
|
||||
|
||||
<!--
|
||||
Because Electron examples usually require multiple files (HTML, CSS, JS
|
||||
|
||||
@@ -120,9 +120,9 @@ file in the directory you executed it in. Both files can be analyzed using
|
||||
the Chrome Developer Tools, using the `Performance` and `Memory` tabs
|
||||
respectively.
|
||||
|
||||
![Performance CPU Profile][performance-cpu-prof]
|
||||

|
||||
|
||||
![Performance Heap Memory Profile][performance-heap-prof]
|
||||

|
||||
|
||||
In this example, on the author's machine, we saw that loading `request` took
|
||||
almost half a second, whereas `node-fetch` took dramatically less memory
|
||||
@@ -412,8 +412,6 @@ As of writing this article, the popular choices include [Webpack][webpack],
|
||||
[Parcel][parcel], and [rollup.js][rollup].
|
||||
|
||||
[security]: ./security.md
|
||||
[performance-cpu-prof]: ../images/performance-cpu-prof.png
|
||||
[performance-heap-prof]: ../images/performance-heap-prof.png
|
||||
[chrome-devtools-tutorial]: https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/
|
||||
[worker-threads]: https://nodejs.org/api/worker_threads.html
|
||||
[web-workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
|
||||
|
||||
@@ -83,7 +83,7 @@ As a practical example, the app shown in the [quick start guide][quick-start-lif
|
||||
uses `app` APIs to create a more native application window experience.
|
||||
|
||||
```js title='main.js'
|
||||
// quitting the app when no windows are open on macOS
|
||||
// quitting the app when no windows are open on non-macOS platforms
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
@@ -148,7 +148,9 @@ A preload script can be attached to the main process in the `BrowserWindow` cons
|
||||
const { BrowserWindow } = require('electron')
|
||||
//...
|
||||
const win = new BrowserWindow({
|
||||
preload: 'path/to/preload.js'
|
||||
webPreferences: {
|
||||
preload: 'path/to/preload.js'
|
||||
}
|
||||
})
|
||||
//...
|
||||
```
|
||||
|
||||
@@ -7,16 +7,16 @@ without the need of switching to the window itself.
|
||||
|
||||
On Windows, you can use a taskbar button to display a progress bar.
|
||||
|
||||
![Windows Progress Bar][windows-progress-bar]
|
||||
![Windows Progress Bar][https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png]
|
||||
|
||||
On macOS, the progress bar will be displayed as a part of the dock icon.
|
||||
|
||||
![macOS Progress Bar][macos-progress-bar]
|
||||

|
||||
|
||||
On Linux, the Unity graphical interface also has a similar feature that allows
|
||||
you to specify the progress bar in the launcher.
|
||||
|
||||
![Linux Progress Bar][linux-progress-bar]
|
||||

|
||||
|
||||
> NOTE: on Windows, each window can have its own progress bar, whereas on macOS
|
||||
and Linux (Unity) there can be only one progress bar for the application.
|
||||
@@ -102,8 +102,4 @@ For macOS, the progress bar will also be indicated for your application
|
||||
when using [Mission Control](https://support.apple.com/en-us/HT204100):
|
||||
|
||||

|
||||
|
||||
[windows-progress-bar]: https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png
|
||||
[macos-progress-bar]: ../images/macos-progress-bar.png
|
||||
[linux-progress-bar]: ../images/linux-progress-bar.png
|
||||
[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress-options
|
||||
|
||||
@@ -23,7 +23,7 @@ your responsibility to ensure that the code is not malicious.
|
||||
## Reporting Security Issues
|
||||
|
||||
For information on how to properly disclose an Electron vulnerability,
|
||||
see [SECURITY.md](https://github.com/electron/electron/tree/master/SECURITY.md)
|
||||
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md)
|
||||
|
||||
## Chromium Security Issues and Upgrades
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Finding Support
|
||||
|
||||
If you have a security concern,
|
||||
please see the [security document](https://github.com/electron/electron/tree/master/SECURITY.md).
|
||||
please see the [security document](https://github.com/electron/electron/tree/main/SECURITY.md).
|
||||
|
||||
If you're looking for programming help,
|
||||
for answers to questions,
|
||||
@@ -26,7 +26,7 @@ you can interact with the community in these locations:
|
||||
* [`electron-pl`](https://electronpl.github.io) *(Poland)*
|
||||
|
||||
If you'd like to contribute to Electron,
|
||||
see the [contributing document](https://github.com/electron/electron/blob/master/CONTRIBUTING.md).
|
||||
see the [contributing document](https://github.com/electron/electron/blob/main/CONTRIBUTING.md).
|
||||
|
||||
If you've found a bug in a [supported version](#supported-versions) of Electron,
|
||||
please report it with the [issue tracker](../development/issues.md).
|
||||
@@ -50,15 +50,15 @@ as the 4.2.x series are supported. We only support the latest minor release
|
||||
for each stable release series. This means that in the case of a security fix
|
||||
6.1.x will receive the fix, but we will not release a new version of 6.0.x.
|
||||
|
||||
The latest stable release unilaterally receives all fixes from `master`,
|
||||
The latest stable release unilaterally receives all fixes from `main`,
|
||||
and the version prior to that receives the vast majority of those fixes
|
||||
as time and bandwidth warrants. The oldest supported release line will receive
|
||||
only security fixes directly.
|
||||
|
||||
All supported release lines will accept external pull requests to backport
|
||||
fixes previously merged to `master`, though this may be on a case-by-case
|
||||
fixes previously merged to `main`, though this may be on a case-by-case
|
||||
basis for some older supported lines. All contested decisions around release
|
||||
line backports will be resolved by the [Releases Working Group](https://github.com/electron/governance/tree/master/wg-releases) as an agenda item at their weekly meeting the week the backport PR is raised.
|
||||
line backports will be resolved by the [Releases Working Group](https://github.com/electron/governance/tree/main/wg-releases) as an agenda item at their weekly meeting the week the backport PR is raised.
|
||||
|
||||
When an API is changed or removed in a way that breaks existing functionality, the
|
||||
previous functionality will be supported for a minimum of two major versions when
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<includes>
|
||||
<include name="IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE" file="${target_gen_dir}/shell_devtools_discovery_page.html" use_base_dir="false" type="BINDATA" />
|
||||
<include name="IDR_PDF_MANIFEST" file="../chrome/browser/resources/pdf/manifest.json" type="BINDATA" />
|
||||
<include name="IDR_CRYPTOTOKEN_MANIFEST" file="../chrome/browser/resources/cryptotoken/manifest.json" type="BINDATA" />
|
||||
</includes>
|
||||
</release>
|
||||
</grit>
|
||||
|
||||
@@ -125,5 +125,7 @@
|
||||
</message>
|
||||
<message name="IDS_BADGE_UNREAD_NOTIFICATIONS" desc="The accessibility text which will be read by a screen reader when there are notifcatications">
|
||||
{UNREAD_NOTIFICATIONS, plural, =1 {1 Unread Notification} other {# Unread Notifications}}
|
||||
</message>
|
||||
</message>
|
||||
<message name="IDS_HID_CHOOSER_ITEM_WITHOUT_NAME" desc="User option displaying the device IDs for a Human Interface Device (HID) without a device name.">
|
||||
Unknown Device (<ph name="DEVICE_ID">$1<ex>1234:abcd</ex></ph>) </message>
|
||||
</grit-part>
|
||||
|
||||
@@ -84,6 +84,7 @@ auto_filenames = {
|
||||
"docs/api/structures/file-filter.md",
|
||||
"docs/api/structures/file-path-with-headers.md",
|
||||
"docs/api/structures/gpu-feature-status.md",
|
||||
"docs/api/structures/hid-device.md",
|
||||
"docs/api/structures/input-event.md",
|
||||
"docs/api/structures/io-counters.md",
|
||||
"docs/api/structures/ipc-main-event.md",
|
||||
@@ -135,15 +136,14 @@ auto_filenames = {
|
||||
|
||||
sandbox_bundle_deps = [
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-methods.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/web-frame.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
@@ -168,7 +168,6 @@ auto_filenames = {
|
||||
]
|
||||
|
||||
isolated_bundle_deps = [
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/isolated_renderer/init.ts",
|
||||
"lib/renderer/web-view/web-view-attributes.ts",
|
||||
@@ -205,7 +204,6 @@ auto_filenames = {
|
||||
"lib/browser/api/menu.ts",
|
||||
"lib/browser/api/message-channel.ts",
|
||||
"lib/browser/api/module-list.ts",
|
||||
"lib/browser/api/native-image.ts",
|
||||
"lib/browser/api/native-theme.ts",
|
||||
"lib/browser/api/net-log.ts",
|
||||
"lib/browser/api/net.ts",
|
||||
@@ -240,13 +238,13 @@ auto_filenames = {
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/parse-features-string.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",
|
||||
@@ -263,12 +261,12 @@ auto_filenames = {
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
@@ -277,7 +275,6 @@ auto_filenames = {
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/init.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
@@ -303,12 +300,12 @@ auto_filenames = {
|
||||
"lib/common/api/clipboard.ts",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/webpack-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
@@ -316,7 +313,6 @@ auto_filenames = {
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
|
||||
@@ -44,8 +44,8 @@ filenames = {
|
||||
]
|
||||
|
||||
lib_sources_linux_x11 = [
|
||||
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc",
|
||||
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h",
|
||||
"shell/browser/ui/views/global_menu_bar_registrar_x11.cc",
|
||||
"shell/browser/ui/views/global_menu_bar_registrar_x11.h",
|
||||
"shell/browser/ui/views/global_menu_bar_x11.cc",
|
||||
"shell/browser/ui/views/global_menu_bar_x11.h",
|
||||
"shell/browser/ui/x/event_disabler.cc",
|
||||
@@ -56,13 +56,9 @@ filenames = {
|
||||
"shell/browser/ui/x/x_window_utils.h",
|
||||
]
|
||||
|
||||
lib_sources_posix = [
|
||||
"chromium_src/chrome/browser/process_singleton_posix.cc",
|
||||
"shell/browser/electron_browser_main_parts_posix.cc",
|
||||
]
|
||||
lib_sources_posix = [ "shell/browser/electron_browser_main_parts_posix.cc" ]
|
||||
|
||||
lib_sources_win = [
|
||||
"chromium_src/chrome/browser/process_singleton_win.cc",
|
||||
"shell/browser/api/electron_api_power_monitor_win.cc",
|
||||
"shell/browser/api/electron_api_system_preferences_win.cc",
|
||||
"shell/browser/browser_win.cc",
|
||||
@@ -195,6 +191,7 @@ filenames = {
|
||||
"shell/browser/ui/tray_icon_cocoa.mm",
|
||||
"shell/common/api/electron_api_clipboard_mac.mm",
|
||||
"shell/common/api/electron_api_native_image_mac.mm",
|
||||
"shell/common/asar/archive_mac.mm",
|
||||
"shell/common/application_info_mac.mm",
|
||||
"shell/common/language_util_mac.mm",
|
||||
"shell/common/mac/main_application_bundle.h",
|
||||
@@ -236,7 +233,6 @@ filenames = {
|
||||
]
|
||||
|
||||
lib_sources = [
|
||||
"chromium_src/chrome/browser/process_singleton.h",
|
||||
"shell/app/command_line_args.cc",
|
||||
"shell/app/command_line_args.h",
|
||||
"shell/app/electron_content_client.cc",
|
||||
@@ -387,8 +383,18 @@ filenames = {
|
||||
"shell/browser/file_select_helper.cc",
|
||||
"shell/browser/file_select_helper.h",
|
||||
"shell/browser/file_select_helper_mac.mm",
|
||||
"shell/browser/font/electron_font_access_delegate.cc",
|
||||
"shell/browser/font/electron_font_access_delegate.h",
|
||||
"shell/browser/font_defaults.cc",
|
||||
"shell/browser/font_defaults.h",
|
||||
"shell/browser/hid/electron_hid_delegate.cc",
|
||||
"shell/browser/hid/electron_hid_delegate.h",
|
||||
"shell/browser/hid/hid_chooser_context.cc",
|
||||
"shell/browser/hid/hid_chooser_context.h",
|
||||
"shell/browser/hid/hid_chooser_context_factory.cc",
|
||||
"shell/browser/hid/hid_chooser_context_factory.h",
|
||||
"shell/browser/hid/hid_chooser_controller.cc",
|
||||
"shell/browser/hid/hid_chooser_controller.h",
|
||||
"shell/browser/javascript_environment.cc",
|
||||
"shell/browser/javascript_environment.h",
|
||||
"shell/browser/lib/bluetooth_chooser.cc",
|
||||
@@ -408,6 +414,8 @@ filenames = {
|
||||
"shell/browser/native_window.cc",
|
||||
"shell/browser/native_window.h",
|
||||
"shell/browser/native_window_observer.h",
|
||||
"shell/browser/net/asar/asar_file_validator.cc",
|
||||
"shell/browser/net/asar/asar_file_validator.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",
|
||||
@@ -496,8 +504,6 @@ filenames = {
|
||||
"shell/browser/web_contents_preferences.h",
|
||||
"shell/browser/web_contents_zoom_controller.cc",
|
||||
"shell/browser/web_contents_zoom_controller.h",
|
||||
"shell/browser/web_dialog_helper.cc",
|
||||
"shell/browser/web_dialog_helper.h",
|
||||
"shell/browser/web_view_guest_delegate.cc",
|
||||
"shell/browser/web_view_guest_delegate.h",
|
||||
"shell/browser/web_view_manager.cc",
|
||||
@@ -677,6 +683,8 @@ filenames = {
|
||||
lib_sources_extensions = [
|
||||
"shell/browser/extensions/api/i18n/i18n_api.cc",
|
||||
"shell/browser/extensions/api/i18n/i18n_api.h",
|
||||
"shell/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc",
|
||||
"shell/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.cc",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.h",
|
||||
"shell/browser/extensions/api/resources_private/resources_private_api.cc",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import type * as Crypto from 'crypto';
|
||||
|
||||
const asar = process._linkedBinding('electron_common_asar');
|
||||
|
||||
@@ -194,6 +195,20 @@ const overrideAPI = function (module: Record<string, any>, name: string, pathArg
|
||||
}
|
||||
};
|
||||
|
||||
let crypto: typeof Crypto;
|
||||
function validateBufferIntegrity (buffer: Buffer, integrity: NodeJS.AsarFileInfo['integrity']) {
|
||||
if (!integrity) return;
|
||||
|
||||
// Delay load crypto to improve app boot performance
|
||||
// when integrity protection is not enabled
|
||||
crypto = crypto || require('crypto');
|
||||
const actual = crypto.createHash(integrity.algorithm).update(buffer).digest('hex');
|
||||
if (actual !== integrity.hash) {
|
||||
console.error(`ASAR Integrity Violation: got a hash mismatch (${actual} vs ${integrity.hash})`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const makePromiseFunction = function (orig: Function, pathArgumentIndex: number) {
|
||||
return function (this: any, ...args: any[]) {
|
||||
const pathArgument = args[pathArgumentIndex];
|
||||
@@ -531,7 +546,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
}
|
||||
|
||||
const buffer = Buffer.alloc(info.size);
|
||||
const fd = archive.getFd();
|
||||
const fd = archive.getFdAndValidateIntegrityLater();
|
||||
if (!(fd >= 0)) {
|
||||
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
nextTick(callback, [error]);
|
||||
@@ -540,6 +555,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
|
||||
logASARAccess(asarPath, filePath, info.offset);
|
||||
fs.read(fd, buffer, 0, info.size, info.offset, (error: Error) => {
|
||||
validateBufferIntegrity(buffer, info.integrity);
|
||||
callback(error, encoding ? buffer.toString(encoding) : buffer);
|
||||
});
|
||||
}
|
||||
@@ -595,11 +611,12 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
|
||||
const { encoding } = options;
|
||||
const buffer = Buffer.alloc(info.size);
|
||||
const fd = archive.getFd();
|
||||
const fd = archive.getFdAndValidateIntegrityLater();
|
||||
if (!(fd >= 0)) throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
|
||||
logASARAccess(asarPath, filePath, info.offset);
|
||||
fs.readSync(fd, buffer, 0, info.size, info.offset);
|
||||
validateBufferIntegrity(buffer, info.integrity);
|
||||
return (encoding) ? buffer.toString(encoding) : buffer;
|
||||
};
|
||||
|
||||
@@ -713,11 +730,12 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
}
|
||||
|
||||
const buffer = Buffer.alloc(info.size);
|
||||
const fd = archive.getFd();
|
||||
const fd = archive.getFdAndValidateIntegrityLater();
|
||||
if (!(fd >= 0)) return [];
|
||||
|
||||
logASARAccess(asarPath, filePath, info.offset);
|
||||
fs.readSync(fd, buffer, 0, info.size, info.offset);
|
||||
validateBufferIntegrity(buffer, info.integrity);
|
||||
const str = buffer.toString('utf8');
|
||||
return [str, str.length > 0];
|
||||
};
|
||||
|
||||
@@ -168,6 +168,7 @@ const messageBox = (sync: boolean, window: BrowserWindow | null, options?: Messa
|
||||
defaultId = -1,
|
||||
detail = '',
|
||||
icon = null,
|
||||
textWidth = 0,
|
||||
noLink = false,
|
||||
message = '',
|
||||
title = '',
|
||||
@@ -225,7 +226,8 @@ const messageBox = (sync: boolean, window: BrowserWindow | null, options?: Messa
|
||||
detail,
|
||||
checkboxLabel,
|
||||
checkboxChecked,
|
||||
icon
|
||||
icon,
|
||||
textWidth
|
||||
};
|
||||
|
||||
if (sync) {
|
||||
|
||||
@@ -16,7 +16,6 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'Menu', loader: () => require('./menu') },
|
||||
{ name: 'MenuItem', loader: () => require('./menu-item') },
|
||||
{ name: 'MessageChannelMain', loader: () => require('./message-channel') },
|
||||
{ name: 'nativeImage', loader: () => require('./native-image') },
|
||||
{ name: 'nativeTheme', loader: () => require('./native-theme') },
|
||||
{ name: 'net', loader: () => require('./net') },
|
||||
{ name: 'netLog', loader: () => require('./net-log') },
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/m
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import { openGuestWindow, makeWebPreferences, parseContentTypeFormat } from '@electron/internal/browser/guest-window-manager';
|
||||
import { parseFeatures } from '@electron/internal/common/parse-features-string';
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
@@ -665,6 +666,16 @@ WebContents.prototype._init = function () {
|
||||
postBody
|
||||
};
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
|
||||
// if attempting to use this API with the deprecated new-window event,
|
||||
// windowOpenOverriddenOptions will always return null. This ensures
|
||||
// short-term backwards compatibility until new-window is removed.
|
||||
const parsedFeatures = parseFeatures(rawFeatures);
|
||||
const overriddenFeatures: BrowserWindowConstructorOptions = {
|
||||
...parsedFeatures.options,
|
||||
webPreferences: parsedFeatures.webPreferences
|
||||
};
|
||||
windowOpenOverriddenOptions = windowOpenOverriddenOptions || overriddenFeatures;
|
||||
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
@@ -769,6 +780,10 @@ export function fromId (id: string) {
|
||||
return binding.fromId(id);
|
||||
}
|
||||
|
||||
export function fromDevToolsTargetId (targetId: string) {
|
||||
return binding.fromDevToolsTargetId(targetId);
|
||||
}
|
||||
|
||||
export function getFocusedWebContents () {
|
||||
let focused = null;
|
||||
for (const contents of binding.getAllWebContents()) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-util
|
||||
import { parseWebViewWebPreferences } from '@electron/internal/common/parse-features-string';
|
||||
import { syncMethods, asyncMethods, properties } from '@electron/internal/common/web-view-methods';
|
||||
import { webViewEvents } from '@electron/internal/common/web-view-events';
|
||||
import { serialize } from '@electron/internal/common/type-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
interface GuestInstance {
|
||||
@@ -330,12 +329,6 @@ handleMessageSync(IPC_MESSAGES.GUEST_VIEW_MANAGER_PROPERTY_SET, function (event,
|
||||
(guest as any)[property] = val;
|
||||
});
|
||||
|
||||
handleMessage(IPC_MESSAGES.GUEST_VIEW_MANAGER_CAPTURE_PAGE, async function (event, guestInstanceId: number, args: any[]) {
|
||||
const guest = getGuestForWebContents(guestInstanceId, event.sender);
|
||||
|
||||
return serialize(await guest.capturePage(...args));
|
||||
});
|
||||
|
||||
// Returns WebContents from its guest id hosted in given webContents.
|
||||
const getGuestForWebContents = function (guestInstanceId: number, contents: Electron.WebContents) {
|
||||
const guestInstance = guestInstances.get(guestInstanceId);
|
||||
|
||||
@@ -81,9 +81,10 @@ require('@electron/internal/browser/guest-view-manager');
|
||||
require('@electron/internal/browser/guest-window-proxy');
|
||||
|
||||
// Now we try to load app's package.json.
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
let packagePath = null;
|
||||
let packageJson = null;
|
||||
const searchPaths = ['app', 'app.asar', 'default_app.asar'];
|
||||
const searchPaths: string[] = v8Util.getHiddenValue(global, 'appSearchPaths');
|
||||
|
||||
if (process.resourcesPath) {
|
||||
for (packagePath of searchPaths) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { app } from 'electron/main';
|
||||
import type { WebContents } from 'electron/main';
|
||||
import { clipboard, nativeImage } from 'electron/common';
|
||||
import { clipboard } from 'electron/common';
|
||||
import * as fs from 'fs';
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
|
||||
import * as typeUtils from '@electron/internal/common/type-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
import type * as desktopCapturerModule from '@electron/internal/browser/desktop-capturer';
|
||||
@@ -56,7 +55,7 @@ ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, function (event, me
|
||||
throw new Error(`Invalid method: ${method}`);
|
||||
}
|
||||
|
||||
return typeUtils.serialize((clipboard as any)[method](...typeUtils.deserialize(args)));
|
||||
return (clipboard as any)[method](...args);
|
||||
});
|
||||
|
||||
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
@@ -71,7 +70,7 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return typeUtils.serialize(await desktopCapturer.getSourcesImpl(event.sender, options));
|
||||
return await desktopCapturer.getSourcesImpl(event.sender, options);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -105,7 +104,3 @@ ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event
|
||||
ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadPath: string, error: Error) {
|
||||
event.sender.emit('preload-error', event, preloadPath, error);
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, async (_, path: string, size: Electron.Size) => {
|
||||
return typeUtils.serialize(await nativeImage.createThumbnailFromPath(path, size));
|
||||
});
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import type * as typeUtilsModule from '@electron/internal/common/type-utils';
|
||||
|
||||
const clipboard = process._linkedBinding('electron_common_clipboard');
|
||||
|
||||
if (process.type === 'renderer') {
|
||||
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') as typeof ipcRendererUtilsModule;
|
||||
const typeUtils = require('@electron/internal/common/type-utils') as typeof typeUtilsModule;
|
||||
|
||||
const makeRemoteMethod = function (method: keyof Electron.Clipboard) {
|
||||
return (...args: any[]) => {
|
||||
args = typeUtils.serialize(args);
|
||||
const result = ipcRendererUtils.invokeSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, method, ...args);
|
||||
return typeUtils.deserialize(result);
|
||||
};
|
||||
const makeRemoteMethod = function (method: keyof Electron.Clipboard): any {
|
||||
return (...args: any[]) => ipcRendererUtils.invokeSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, method, ...args);
|
||||
};
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Common modules, please sort alphabetically
|
||||
export const commonModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'clipboard', loader: () => require('./clipboard') },
|
||||
{ name: 'nativeImage', loader: () => require('./native-image') },
|
||||
{ name: 'shell', loader: () => require('./shell') },
|
||||
// The internal modules, invisible unless you know their names.
|
||||
{ name: 'deprecate', loader: () => require('./deprecate'), private: true }
|
||||
|
||||
@@ -13,7 +13,6 @@ export const enum IPC_MESSAGES {
|
||||
GUEST_VIEW_MANAGER_DETACH_GUEST = 'GUEST_VIEW_MANAGER_DETACH_GUEST',
|
||||
GUEST_VIEW_MANAGER_FOCUS_CHANGE = 'GUEST_VIEW_MANAGER_FOCUS_CHANGE',
|
||||
GUEST_VIEW_MANAGER_CALL = 'GUEST_VIEW_MANAGER_CALL',
|
||||
GUEST_VIEW_MANAGER_CAPTURE_PAGE = 'GUEST_VIEW_MANAGER_CAPTURE_PAGE',
|
||||
GUEST_VIEW_MANAGER_PROPERTY_GET = 'GUEST_VIEW_MANAGER_PROPERTY_GET',
|
||||
GUEST_VIEW_MANAGER_PROPERTY_SET = 'GUEST_VIEW_MANAGER_PROPERTY_SET',
|
||||
|
||||
@@ -31,5 +30,4 @@ export const enum IPC_MESSAGES {
|
||||
INSPECTOR_SELECT_FILE = 'INSPECTOR_SELECT_FILE',
|
||||
|
||||
DESKTOP_CAPTURER_GET_SOURCES = 'DESKTOP_CAPTURER_GET_SOURCES',
|
||||
NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH = 'NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH',
|
||||
}
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
function getCreateNativeImage () {
|
||||
return process._linkedBinding('electron_common_native_image').nativeImage.createEmpty;
|
||||
}
|
||||
|
||||
export function isPromise (val: any) {
|
||||
return (
|
||||
val &&
|
||||
val.then &&
|
||||
val.then instanceof Function &&
|
||||
val.constructor &&
|
||||
val.constructor.reject &&
|
||||
val.constructor.reject instanceof Function &&
|
||||
val.constructor.resolve &&
|
||||
val.constructor.resolve instanceof Function
|
||||
);
|
||||
}
|
||||
|
||||
const serializableTypes = [
|
||||
Boolean,
|
||||
Number,
|
||||
String,
|
||||
Date,
|
||||
Error,
|
||||
RegExp,
|
||||
ArrayBuffer
|
||||
];
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#Supported_types
|
||||
export function isSerializableObject (value: any) {
|
||||
return value === null || ArrayBuffer.isView(value) || serializableTypes.some(type => value instanceof type);
|
||||
}
|
||||
|
||||
const objectMap = function (source: Object, mapper: (value: any) => any) {
|
||||
const sourceEntries = Object.entries(source);
|
||||
const targetEntries = sourceEntries.map(([key, val]) => [key, mapper(val)]);
|
||||
return Object.fromEntries(targetEntries);
|
||||
};
|
||||
|
||||
function serializeNativeImage (image: Electron.NativeImage) {
|
||||
const representations = [];
|
||||
const scaleFactors = image.getScaleFactors();
|
||||
|
||||
// Use Buffer when there's only one representation for better perf.
|
||||
// This avoids compressing to/from PNG where it's not necessary to
|
||||
// ensure uniqueness of dataURLs (since there's only one).
|
||||
if (scaleFactors.length === 1) {
|
||||
const scaleFactor = scaleFactors[0];
|
||||
const size = image.getSize(scaleFactor);
|
||||
const buffer = image.toBitmap({ scaleFactor });
|
||||
representations.push({ scaleFactor, size, buffer });
|
||||
} else {
|
||||
// Construct from dataURLs to ensure that they are not lost in creation.
|
||||
for (const scaleFactor of scaleFactors) {
|
||||
const size = image.getSize(scaleFactor);
|
||||
const dataURL = image.toDataURL({ scaleFactor });
|
||||
representations.push({ scaleFactor, size, dataURL });
|
||||
}
|
||||
}
|
||||
return { __ELECTRON_SERIALIZED_NativeImage__: true, representations };
|
||||
}
|
||||
|
||||
function deserializeNativeImage (value: any, createNativeImage: typeof Electron.nativeImage['createEmpty']) {
|
||||
const image = createNativeImage();
|
||||
|
||||
// Use Buffer when there's only one representation for better perf.
|
||||
// This avoids compressing to/from PNG where it's not necessary to
|
||||
// ensure uniqueness of dataURLs (since there's only one).
|
||||
if (value.representations.length === 1) {
|
||||
const { buffer, size, scaleFactor } = value.representations[0];
|
||||
const { width, height } = size;
|
||||
image.addRepresentation({ buffer, scaleFactor, width, height });
|
||||
} else {
|
||||
// Construct from dataURLs to ensure that they are not lost in creation.
|
||||
for (const rep of value.representations) {
|
||||
const { dataURL, size, scaleFactor } = rep;
|
||||
const { width, height } = size;
|
||||
image.addRepresentation({ dataURL, scaleFactor, width, height });
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
export function serialize (value: any): any {
|
||||
if (value && value.constructor && value.constructor.name === 'NativeImage') {
|
||||
return serializeNativeImage(value);
|
||||
} if (Array.isArray(value)) {
|
||||
return value.map(serialize);
|
||||
} else if (isSerializableObject(value)) {
|
||||
return value;
|
||||
} else if (value instanceof Object) {
|
||||
return objectMap(value, serialize);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
export function deserialize (value: any, createNativeImage: typeof Electron.nativeImage['createEmpty'] = getCreateNativeImage()): any {
|
||||
if (value && value.__ELECTRON_SERIALIZED_NativeImage__) {
|
||||
return deserializeNativeImage(value, createNativeImage);
|
||||
} else if (Array.isArray(value)) {
|
||||
return value.map(value => deserialize(value, createNativeImage));
|
||||
} else if (isSerializableObject(value)) {
|
||||
return value;
|
||||
} else if (value instanceof Object) {
|
||||
return objectMap(value, value => deserialize(value, createNativeImage));
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,7 @@ export const properties = new Set([
|
||||
]);
|
||||
|
||||
export const asyncMethods = new Set([
|
||||
'capturePage',
|
||||
'loadURL',
|
||||
'executeJavaScript',
|
||||
'insertCSS',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import { deserialize } from '@electron/internal/common/type-utils';
|
||||
import deprecate from '@electron/internal/common/api/deprecate';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
@@ -14,6 +14,11 @@ function getCurrentStack () {
|
||||
return (target as any).stack;
|
||||
}
|
||||
|
||||
let warned = process.noDeprecation;
|
||||
export async function getSources (options: Electron.SourcesOptions) {
|
||||
return deserialize(await ipcRendererInternal.invoke(IPC_MESSAGES.DESKTOP_CAPTURER_GET_SOURCES, options, getCurrentStack()));
|
||||
if (!warned) {
|
||||
deprecate.log('The use of \'desktopCapturer.getSources\' in the renderer process is deprecated and will be removed. See https://www.electronjs.org/docs/breaking-changes#removed-desktopcapturergetsources-in-the-renderer for more details.');
|
||||
warned = true;
|
||||
}
|
||||
return await ipcRendererInternal.invoke(IPC_MESSAGES.DESKTOP_CAPTURER_GET_SOURCES, options, getCurrentStack());
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ export const rendererModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'contextBridge', loader: () => require('./context-bridge') },
|
||||
{ name: 'crashReporter', loader: () => require('./crash-reporter') },
|
||||
{ name: 'ipcRenderer', loader: () => require('./ipc-renderer') },
|
||||
{ name: 'nativeImage', loader: () => require('./native-image') },
|
||||
{ name: 'webFrame', loader: () => require('./web-frame') }
|
||||
];
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import { deserialize } from '@electron/internal/common/type-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
const { nativeImage } = process._linkedBinding('electron_common_native_image');
|
||||
|
||||
nativeImage.createThumbnailFromPath = async (path: string, size: Electron.Size) => {
|
||||
return deserialize(await ipcRendererInternal.invoke(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, path, size));
|
||||
};
|
||||
|
||||
export default nativeImage;
|
||||
@@ -103,10 +103,14 @@ const warnAboutInsecureResources = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
const isLocal = (url: URL): boolean =>
|
||||
['localhost', '127.0.0.1', '[::1]', ''].includes(url.hostname);
|
||||
const isInsecure = (url: URL): boolean =>
|
||||
['http:', 'ftp:'].includes(url.protocol) && !isLocal(url);
|
||||
|
||||
const resources = window.performance
|
||||
.getEntriesByType('resource')
|
||||
.filter(({ name }) => /^(http|ftp):/gi.test(name || ''))
|
||||
.filter(({ name }) => new URL(name).hostname !== 'localhost')
|
||||
.filter(({ name }) => isInsecure(new URL(name)))
|
||||
.map(({ name }) => `- ${name}`)
|
||||
.join('\n');
|
||||
|
||||
|
||||
@@ -43,10 +43,6 @@ export function detachGuest (guestInstanceId: number) {
|
||||
return ipcRendererUtils.invokeSync(IPC_MESSAGES.GUEST_VIEW_MANAGER_DETACH_GUEST, guestInstanceId);
|
||||
}
|
||||
|
||||
export function capturePage (guestInstanceId: number, args: any[]) {
|
||||
return ipcRendererInternal.invoke(IPC_MESSAGES.GUEST_VIEW_MANAGER_CAPTURE_PAGE, guestInstanceId, args);
|
||||
}
|
||||
|
||||
export function invoke (guestInstanceId: number, method: string, args: any[]) {
|
||||
return ipcRendererInternal.invoke(IPC_MESSAGES.GUEST_VIEW_MANAGER_CALL, guestInstanceId, method, args);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-vie
|
||||
import { syncMethods, asyncMethods, properties } from '@electron/internal/common/web-view-methods';
|
||||
import type { WebViewAttribute, PartitionAttribute } from '@electron/internal/renderer/web-view/web-view-attributes';
|
||||
import { setupWebViewAttributes } from '@electron/internal/renderer/web-view/web-view-attributes';
|
||||
import { deserialize } from '@electron/internal/common/type-utils';
|
||||
|
||||
// ID generator.
|
||||
let nextId = 0;
|
||||
@@ -16,7 +15,6 @@ export interface WebViewImplHooks {
|
||||
readonly guestViewInternal: typeof guestViewInternalModule;
|
||||
readonly allowGuestViewElementDefinition: NodeJS.InternalWebFrame['allowGuestViewElementDefinition'];
|
||||
readonly setIsWebView: (iframe: HTMLIFrameElement) => void;
|
||||
readonly createNativeImage?: typeof Electron.nativeImage['createEmpty'];
|
||||
}
|
||||
|
||||
// Represents the internal state of the WebView node.
|
||||
@@ -235,10 +233,6 @@ export const setupMethods = (WebViewElement: typeof ElectronInternal.WebViewElem
|
||||
};
|
||||
}
|
||||
|
||||
WebViewElement.prototype.capturePage = async function (...args) {
|
||||
return deserialize(await hooks.guestViewInternal.capturePage(this.getWebContentsId(), args), hooks.createNativeImage);
|
||||
};
|
||||
|
||||
const createPropertyGetter = function (property: string) {
|
||||
return function (this: ElectronInternal.WebViewElement) {
|
||||
return hooks.guestViewInternal.propertyGet(this.getWebContentsId(), property);
|
||||
|
||||
@@ -13,7 +13,7 @@ export const moduleList: ElectronInternal.ModuleEntry[] = [
|
||||
},
|
||||
{
|
||||
name: 'nativeImage',
|
||||
loader: () => require('@electron/internal/renderer/api/native-image')
|
||||
loader: () => require('@electron/internal/common/api/native-image')
|
||||
},
|
||||
{
|
||||
name: 'webFrame',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "16.0.0-nightly.20210825",
|
||||
"version": "16.0.0-alpha.2",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@electron/docs-parser": "^0.12.1",
|
||||
"@electron/docs-parser": "^0.12.2",
|
||||
"@electron/typescript-definitions": "^8.9.5",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
"@octokit/rest": "^18.0.3",
|
||||
@@ -30,7 +30,7 @@
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||
"@typescript-eslint/parser": "^4.4.1",
|
||||
"asar": "^3.0.3",
|
||||
"asar": "^3.1.0",
|
||||
"aws-sdk": "^2.727.1",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.4.0",
|
||||
|
||||
@@ -2,3 +2,4 @@ expose_ripemd160.patch
|
||||
expose_aes-cfb.patch
|
||||
expose_des-ede3.patch
|
||||
fix_sync_evp_get_cipherbynid_and_evp_get_cipherbyname.patch
|
||||
add_maskhash_to_rsa_pss_params_st_for_compat.patch
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Wed, 8 Sep 2021 10:59:51 +0200
|
||||
Subject: Add maskHash to rsa_pss_params_st for compat
|
||||
|
||||
This CL adds a maskHash member to the rsa_pss_params_st struct for
|
||||
increased compatibility with OpenSSL.
|
||||
|
||||
Node.js recently began to make use of this member in
|
||||
https://github.com/nodejs/node/pull/39851
|
||||
and without this member Electron sees compilation errors.
|
||||
|
||||
Upstreamed at https://boringssl-review.googlesource.com/c/boringssl/+/49365
|
||||
|
||||
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
|
||||
index fa333ca057dd8e90a3e38c51db6269815de7b85f..0f4a6d79514739fb4c719f9e5b41db364e775417 100644
|
||||
--- a/include/openssl/x509.h
|
||||
+++ b/include/openssl/x509.h
|
||||
@@ -1949,6 +1949,7 @@ typedef struct rsa_pss_params_st {
|
||||
X509_ALGOR *maskGenAlgorithm;
|
||||
ASN1_INTEGER *saltLength;
|
||||
ASN1_INTEGER *trailerField;
|
||||
+ X509_ALGOR *maskHash;
|
||||
} RSA_PSS_PARAMS;
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
|
||||
2
patches/breakpad/.patches
Normal file
2
patches/breakpad/.patches
Normal file
@@ -0,0 +1,2 @@
|
||||
revert_remove_warning_about_unknown_abstract_origin.patch
|
||||
revert_add_inline_and_inline_origin_records_to_symbol_file.patch
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Thu, 2 Sep 2021 22:55:25 +0000
|
||||
Subject: Revert "Remove warning about unknown abstract origin"
|
||||
|
||||
This reverts commit 7933ec0a69bac134b7cee4b60a5dc80743b2b1a9.
|
||||
|
||||
diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc
|
||||
index dacc9cbe4b0e13d19b5969fe91ba7a867e64a36c..c51514b7575c2e961aaae3ff883be00d80e3ec15 100644
|
||||
--- a/src/common/dwarf_cu_to_module.cc
|
||||
+++ b/src/common/dwarf_cu_to_module.cc
|
||||
@@ -504,6 +504,8 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
|
||||
abstract_origin_ = &(origin->second);
|
||||
} else if (data > offset_) {
|
||||
forward_ref_die_offset_ = data;
|
||||
+ } else {
|
||||
+ cu_context_->reporter->UnknownAbstractOrigin(offset_, data);
|
||||
}
|
||||
specification_offset_ = data;
|
||||
break;
|
||||
@@ -748,6 +750,14 @@ void DwarfCUToModule::InlineHandler::Finish() {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Malformed DWARF may omit the name, but all Module::Functions must
|
||||
+ // have names.
|
||||
+ // If we have a forward reference to a DW_AT_specification or
|
||||
+ // DW_AT_abstract_origin, then don't warn, the name will be fixed up
|
||||
+ // later
|
||||
+ if (name_.empty() && forward_ref_die_offset_ == 0)
|
||||
+ cu_context_->reporter->UnnamedFunction(offset_);
|
||||
+
|
||||
// Every DW_TAG_inlined_subroutine should have a DW_AT_abstract_origin.
|
||||
assert(specification_offset_ != 0);
|
||||
|
||||
@@ -919,6 +929,11 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
||||
if (!name_.empty()) {
|
||||
name = name_;
|
||||
} else {
|
||||
+ // If we have a forward reference to a DW_AT_specification or
|
||||
+ // DW_AT_abstract_origin, then don't warn, the name will be fixed up
|
||||
+ // later
|
||||
+ if (forward_ref_die_offset_ == 0)
|
||||
+ cu_context_->reporter->UnnamedFunction(offset_);
|
||||
name = "<name omitted>";
|
||||
}
|
||||
|
||||
@@ -93,7 +93,6 @@ webview_fullscreen.patch
|
||||
disable_unload_metrics.patch
|
||||
fix_add_check_for_sandbox_then_result.patch
|
||||
extend_apply_webpreferences.patch
|
||||
fix_expose_decrementcapturercount_in_web_contents_impl.patch
|
||||
add_setter_for_browsermainloop_result_code.patch
|
||||
make_include_of_stack_trace_h_unconditional.patch
|
||||
build_libc_as_static_library.patch
|
||||
@@ -101,9 +100,10 @@ build_do_not_depend_on_packed_resource_integrity.patch
|
||||
refactor_restore_base_adaptcallbackforrepeating.patch
|
||||
hack_to_allow_gclient_sync_with_host_os_mac_on_linux_in_ci.patch
|
||||
don_t_run_pcscan_notifythreadcreated_if_pcscan_is_disabled.patch
|
||||
add_gin_wrappable_crash_key.patch
|
||||
logging_win32_only_create_a_console_if_logging_to_stderr.patch
|
||||
disable_use_lld_for_macos.patch
|
||||
fix_media_key_usage_with_globalshortcuts.patch
|
||||
feat_expose_raw_response_headers_from_urlloader.patch
|
||||
revert_roll_clang_llvmorg-14-init-1002-gb5e470aa-1.patch
|
||||
chore_do_not_use_chrome_windows_in_cryptotoken_webrequestsender.patch
|
||||
fix_chrome_root_store_codegen_for_cross-compile_builds.patch
|
||||
process_singleton.patch
|
||||
fix_expose_decrementcapturercount_in_web_contents_impl.patch
|
||||
|
||||
@@ -10,7 +10,7 @@ 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 e24c169444c699f295de2c1f1f42683eeca73436..4675cdccb1876a318a9a0253cdf552bb65516310 100644
|
||||
index 794a89ded73c415403d0d590780869c8d8b4ae38..5eb76debe9804a5195747cb6b90707fd0a242ec6 100644
|
||||
--- a/content/public/renderer/render_frame_observer.h
|
||||
+++ b/content/public/renderer/render_frame_observer.h
|
||||
@@ -127,6 +127,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
|
||||
@@ -23,10 +23,10 @@ index e24c169444c699f295de2c1f1f42683eeca73436..4675cdccb1876a318a9a0253cdf552bb
|
||||
int32_t world_id) {}
|
||||
virtual void DidClearWindowObject() {}
|
||||
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
||||
index da75e85c94b1dba16c423066940cf27c90c1081c..7884866e2358f78a994dd784f187fdb8bd592bad 100644
|
||||
index 173952d4545d59ecb1b99aa07b6c8f8bcd1b2e86..395bb615c0a2d5a49cfbc6d8a9e9f3d9a809b595 100644
|
||||
--- a/content/renderer/render_frame_impl.cc
|
||||
+++ b/content/renderer/render_frame_impl.cc
|
||||
@@ -4446,6 +4446,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
@@ -4461,6 +4461,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
observer.DidCreateScriptContext(context, world_id);
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ index da75e85c94b1dba16c423066940cf27c90c1081c..7884866e2358f78a994dd784f187fdb8
|
||||
int world_id) {
|
||||
for (auto& observer : observers_)
|
||||
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
|
||||
index a2577aefe0f7121daa46765014fd94cc9c5264b9..302aeb4257105b04cb8ca4ce484354021757ee8d 100644
|
||||
index 4cd3901203e5399fb5a2855fca98e083fe0973d1..b11cb66d157023d36113f28399d57ff2b2f10abb 100644
|
||||
--- a/content/renderer/render_frame_impl.h
|
||||
+++ b/content/renderer/render_frame_impl.h
|
||||
@@ -588,6 +588,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
@@ -593,6 +593,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 a2577aefe0f7121daa46765014fd94cc9c5264b9..302aeb4257105b04cb8ca4ce48435402
|
||||
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 99ddb8f449481647a499a5bb3fd7f5d5272ae414..00d7f0bbb8dc3afdc2303668481cf17fbdfbdcba 100644
|
||||
index 0ccf54bd50144bc890c96651978f54b0d33713b6..de26aa9f319bd0c762b96f729ccf25a72dd90eb3 100644
|
||||
--- a/third_party/blink/public/web/web_local_frame_client.h
|
||||
+++ b/third_party/blink/public/web/web_local_frame_client.h
|
||||
@@ -587,6 +587,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
@@ -589,6 +589,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {}
|
||||
|
||||
@@ -79,10 +79,10 @@ index b0d5db60fbe57275dda835113b0fb21acb9a422f..b6c9c389943088004a419677a2a17be0
|
||||
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 8d7a0e9445d7817441f02b4def1777020d35618f..6f0f79b2766ee8f42815c15744ccfc2a75976b0b 100644
|
||||
index 727b770b33f209288904cc10f486ab25f82b4cd6..b25c945378a01ac918ff6dc6caf69effde3685e6 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
@@ -300,6 +300,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
@@ -303,6 +303,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) = 0;
|
||||
@@ -92,7 +92,7 @@ index 8d7a0e9445d7817441f02b4def1777020d35618f..6f0f79b2766ee8f42815c15744ccfc2a
|
||||
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 94e332a2da9522e83ce55d8b7ce303a383e37d05..a3fa8d72ffb450f502de161a8875a81d72c075e8 100644
|
||||
index ba855e42e395f1ba1838400f08827a5bdc19d90f..c74031e118ffb7ff6312c33f99a6ff9d67b5bf19 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(
|
||||
@@ -110,7 +110,7 @@ index 94e332a2da9522e83ce55d8b7ce303a383e37d05..a3fa8d72ffb450f502de161a8875a81d
|
||||
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 0d7ecf011c802f8c4d874815e345b16ac3a0b5dc..572968b7f6495ee544cdf265aa9b7f6728c74cc9 100644
|
||||
index 57c9b6b733ebf5b9483d31959fbdccad8b72031c..13c7e6924a19717473379045ae1c1f0e6f6d52cf 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
|
||||
@@ -77,6 +77,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
|
||||
@@ -123,10 +123,10 @@ index 0d7ecf011c802f8c4d874815e345b16ac3a0b5dc..572968b7f6495ee544cdf265aa9b7f67
|
||||
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 ec4dfeb2d6fd5206c1d6d697a36d5d78899023cb..7b978f119d3321416dffcc2dea266403dd86f2b6 100644
|
||||
index 65356d0acdc5868cce8401ed88b90d75c6306f28..338ebba74360e09bfc93c5be943ab828d22b500b 100644
|
||||
--- a/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
@@ -356,6 +356,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
@@ -359,6 +359,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
|
||||
void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) override {}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: VerteDinde <khammond@slack-corp.com>
|
||||
Date: Thu, 15 Jul 2021 12:16:50 -0700
|
||||
Subject: chore: add gin::wrappable wrapperinfo crash key
|
||||
|
||||
This patch adds an additional crash key for gin::Wrappable, to help
|
||||
debug a crash that is occurring during garbage collection in SecondWeakCallback.
|
||||
|
||||
The crash seems to be due to a class that is holding a reference to
|
||||
gin::Wrappable even after being deleted. This added crash key compares
|
||||
the soon-to-be-deleted WrapperInfo with known WrapperInfo components to
|
||||
help determine where the crash originated from.
|
||||
|
||||
This patch should not be upstreamed, and can be removed in Electron 15 and
|
||||
beyond once we identify the cause of the crash.
|
||||
|
||||
diff --git a/gin/BUILD.gn b/gin/BUILD.gn
|
||||
index c6059fdb0e0f74ee3ef78c5517634ed5a36f1b10..e16b2ec43b98c3b8724fd85085a33fe52a1e1979 100644
|
||||
--- a/gin/BUILD.gn
|
||||
+++ b/gin/BUILD.gn
|
||||
@@ -88,6 +88,10 @@ component("gin") {
|
||||
frameworks = [ "CoreFoundation.framework" ]
|
||||
}
|
||||
|
||||
+ if (!is_mas_build) {
|
||||
+ public_deps += [ "//components/crash/core/common:crash_key" ]
|
||||
+ }
|
||||
+
|
||||
configs += [
|
||||
"//tools/v8_context_snapshot:use_v8_context_snapshot",
|
||||
"//v8:external_startup_data",
|
||||
diff --git a/gin/wrappable.cc b/gin/wrappable.cc
|
||||
index fe07eb94a8e679859bba6d76ff0d6ee86bd0c67e..ecb0aa2c4ec57e1814f4c94194e775440f4e35ee 100644
|
||||
--- a/gin/wrappable.cc
|
||||
+++ b/gin/wrappable.cc
|
||||
@@ -8,6 +8,11 @@
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "gin/per_isolate_data.h"
|
||||
|
||||
+#if !defined(MAS_BUILD)
|
||||
+#include "components/crash/core/common/crash_key.h"
|
||||
+#include "electron/shell/common/crash_keys.h"
|
||||
+#endif
|
||||
+
|
||||
namespace gin {
|
||||
|
||||
WrappableBase::WrappableBase() = default;
|
||||
@@ -36,6 +41,15 @@ void WrappableBase::FirstWeakCallback(
|
||||
void WrappableBase::SecondWeakCallback(
|
||||
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
||||
WrappableBase* wrappable = data.GetParameter();
|
||||
+
|
||||
+#if !defined(MAS_BUILD)
|
||||
+ WrapperInfo* wrapperInfo = static_cast<WrapperInfo*>(data.GetInternalField(0));
|
||||
+ std::string location = electron::crash_keys::GetCrashValueForGinWrappable(wrapperInfo);
|
||||
+
|
||||
+ static crash_reporter::CrashKeyString<32> crash_key("gin-wrappable-fatal.location");
|
||||
+ crash_reporter::ScopedCrashKeyString auto_clear(&crash_key, location);
|
||||
+#endif
|
||||
+
|
||||
delete wrappable;
|
||||
}
|
||||
|
||||
@@ -113,10 +113,10 @@ index 7995eb16a7cf6a824653736ca067baa5e688834f..c26e087f2f4d7a1446ce439e5a08a34a
|
||||
|
||||
mojom::blink::PageVisibilityState WebViewImpl::GetVisibilityState() {
|
||||
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
|
||||
index e7b0409bd60df8c1476f0c9ce14380bfade9773d..3a955aa7fcf08a7d7222eca37222870c6ec8fe36 100644
|
||||
index 293e146acb0257a80d41eecf0794b7f08aa0ffc4..c1c88c9349d3882f3896fa1ed715433d9cf19429 100644
|
||||
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
|
||||
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
|
||||
@@ -416,6 +416,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
@@ -417,6 +417,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
LocalDOMWindow* PagePopupWindow() const;
|
||||
|
||||
PageScheduler* Scheduler() const override;
|
||||
@@ -124,7 +124,7 @@ index e7b0409bd60df8c1476f0c9ce14380bfade9773d..3a955aa7fcf08a7d7222eca37222870c
|
||||
void SetVisibilityState(mojom::blink::PageVisibilityState visibility_state,
|
||||
bool is_initial_state) override;
|
||||
mojom::blink::PageVisibilityState GetVisibilityState() override;
|
||||
@@ -847,6 +848,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
@@ -848,6 +849,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
// If true, we send IPC messages when |preferred_size_| changes.
|
||||
bool send_preferred_size_changes_ = false;
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ index 8bf6b4bc077cc41da5e0e6b13302bc343537c68f..01bddc0bcb7476408023c4cfc042a088
|
||||
// its owning reference back to our owning LocalFrame.
|
||||
client_->Detached(type);
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
index a9c4d4efe4d66a152c02c7d6029d8c7e3740ebfb..cce1fc3bc9d7779215cd3536553e09078c8d9680 100644
|
||||
index cf505929c9f6eac724a22e5abcd362ed70aed710..b49500d62fb29f179ae802366108c84e2f891836 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
@@ -553,10 +553,6 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
|
||||
|
||||
@@ -8,7 +8,7 @@ categories in use are known / declared. This patch is required for us
|
||||
to introduce a new Electron category for Electron-specific tracing.
|
||||
|
||||
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h
|
||||
index 81dea0e4a02ae26b2b55e6839202d6864a120d45..5174db10126c9cb81dc422bdac9ba18e498debe8 100644
|
||||
index efa8e6578dbdda31a9cfafe680d03c809617f84c..46affd2c438a5108440848943fb20efe070e6ed0 100644
|
||||
--- a/base/trace_event/builtin_categories.h
|
||||
+++ b/base/trace_event/builtin_categories.h
|
||||
@@ -77,6 +77,7 @@
|
||||
|
||||
@@ -11,7 +11,7 @@ if we ever align our .pak file generation with Chrome we can remove this
|
||||
patch.
|
||||
|
||||
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
|
||||
index d4436b93723cac8b33a6ffab1437b221446a1fb0..3aef47b5f85c11845962e48efd75a1d5064b7412 100644
|
||||
index 897e473cbb4c3e8b244210706e4e1549b1e71a0c..cde17f7fee3851e96afc181c92121867c97a0f95 100644
|
||||
--- a/chrome/BUILD.gn
|
||||
+++ b/chrome/BUILD.gn
|
||||
@@ -165,11 +165,16 @@ if (!is_android && !is_mac) {
|
||||
@@ -33,10 +33,10 @@ index d4436b93723cac8b33a6ffab1437b221446a1fb0..3aef47b5f85c11845962e48efd75a1d5
|
||||
"//base",
|
||||
"//build:branding_buildflags",
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index 74f816aef514eef1263d9b2c25cf3a52359860a6..a9cb81f06f1a4ef57e90190b9dde01df5dc67124 100644
|
||||
index 3acfeb5e5bf721fabe2339e389193cd9e154e293..9cdea4ca822f74cf7398d3f474bcc5ccfd43f829 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -4367,7 +4367,7 @@ static_library("browser") {
|
||||
@@ -4398,7 +4398,7 @@ static_library("browser") {
|
||||
|
||||
# On Windows, the hashes are embedded in //chrome:chrome_initial rather
|
||||
# than here in :chrome_dll.
|
||||
@@ -46,10 +46,10 @@ index 74f816aef514eef1263d9b2c25cf3a52359860a6..a9cb81f06f1a4ef57e90190b9dde01df
|
||||
}
|
||||
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index c506774eef1725c67f6b56abe36f5541ef940cd0..4585132bb6b2d35560d851940ef0d71441fda6a9 100644
|
||||
index f8eeccc044eebd0c7f1a845ff29c7e46acf83252..d81d15061a88a7e38d7ee46ca7b0f6fcbe994961 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -5328,7 +5328,6 @@ test("unit_tests") {
|
||||
@@ -5353,7 +5353,6 @@ test("unit_tests") {
|
||||
assert(toolkit_views)
|
||||
sources += [ "../browser/ui/startup/credential_provider_signin_info_fetcher_win_unittest.cc" ]
|
||||
deps += [
|
||||
@@ -57,7 +57,7 @@ index c506774eef1725c67f6b56abe36f5541ef940cd0..4585132bb6b2d35560d851940ef0d714
|
||||
"//chrome/browser:chrome_process_finder",
|
||||
"//chrome/browser/safe_browsing/chrome_cleaner",
|
||||
"//chrome/browser/safe_browsing/chrome_cleaner:public",
|
||||
@@ -5341,6 +5340,12 @@ test("unit_tests") {
|
||||
@@ -5366,6 +5365,12 @@ test("unit_tests") {
|
||||
"//components/chrome_cleaner/public/proto",
|
||||
"//ui/events/devices:test_support",
|
||||
]
|
||||
@@ -70,17 +70,17 @@ index c506774eef1725c67f6b56abe36f5541ef940cd0..4585132bb6b2d35560d851940ef0d714
|
||||
}
|
||||
|
||||
# TODO(crbug.com/931218): Ninja cannot handle certain characters appearing
|
||||
@@ -5933,7 +5938,6 @@ test("unit_tests") {
|
||||
@@ -5953,7 +5958,6 @@ test("unit_tests") {
|
||||
}
|
||||
|
||||
deps += [
|
||||
- "//chrome:packed_resources_integrity_hash",
|
||||
"//chrome/browser:cart_db_content_proto",
|
||||
"//chrome/browser/media/router:test_support",
|
||||
"//chrome/browser/promo_browser_command:mojo_bindings",
|
||||
@@ -5969,6 +5973,9 @@ test("unit_tests") {
|
||||
"//ui/color:test_support",
|
||||
"//chrome/browser/resource_coordinator:intervention_policy_database_proto",
|
||||
@@ -5989,6 +5993,9 @@ test("unit_tests") {
|
||||
"//ui/native_theme:test_support",
|
||||
"//ui/webui/resources/js/browser_command:mojo_bindings",
|
||||
]
|
||||
+ if (!is_electron_build) {
|
||||
+ deps += [ "//chrome:packed_resources_integrity_hash" ]
|
||||
|
||||
@@ -9,10 +9,10 @@ potentially prevent a window from being created.
|
||||
TODO(loc): this patch is currently broken.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index ac98459fd07c4daee384c50e2ac4b19da14ccaf6..b5f7104ffde611652c55ebe85e3969394dbf76fc 100644
|
||||
index befd11fbac2068e6ac303989528ee609263ae9b2..ea22c655ae4e5c1e023d68fbedb2a684edabe1fe 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -6348,6 +6348,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -6406,6 +6406,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
last_committed_origin_, params->window_container_type,
|
||||
params->target_url, params->referrer.To<Referrer>(),
|
||||
params->frame_name, params->disposition, *params->features,
|
||||
@@ -21,10 +21,10 @@ index ac98459fd07c4daee384c50e2ac4b19da14ccaf6..b5f7104ffde611652c55ebe85e396939
|
||||
&no_javascript_access);
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 6f0d2cee13b39ef0fb60ceec0bbf25f17f8b1152..183fa12d38d28f3de40bdd9f26155388658e8ffe 100644
|
||||
index afee3ed1f21aa9b95e2dc48191445d0f18049bbb..0ba0990cf02624cc7cf1b304a0d9b63692cd464d 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3727,6 +3727,14 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -3739,6 +3739,14 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
}
|
||||
auto* new_contents_impl = new_contents.get();
|
||||
|
||||
@@ -39,7 +39,7 @@ index 6f0d2cee13b39ef0fb60ceec0bbf25f17f8b1152..183fa12d38d28f3de40bdd9f26155388
|
||||
new_contents_impl->GetController().SetSessionStorageNamespace(
|
||||
partition_id, session_storage_namespace);
|
||||
|
||||
@@ -3769,12 +3777,6 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -3781,12 +3789,6 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
AddWebContentsDestructionObserver(new_contents_impl);
|
||||
}
|
||||
|
||||
@@ -53,13 +53,13 @@ index 6f0d2cee13b39ef0fb60ceec0bbf25f17f8b1152..183fa12d38d28f3de40bdd9f26155388
|
||||
new_contents_impl, opener, params.target_url,
|
||||
params.referrer.To<Referrer>(), params.disposition,
|
||||
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
|
||||
index 72fd11b1733aa5433c1905933c357aa58c02578d..d6cdf5cfe1287cddf29279e28ce878cf11616cca 100644
|
||||
index 74ed9ae0eae10e77dace6905b5108a834b07f8b4..924d6b43d444ccb919d6985c975eb8862ca35b20 100644
|
||||
--- a/content/common/frame.mojom
|
||||
+++ b/content/common/frame.mojom
|
||||
@@ -523,6 +523,10 @@ struct CreateNewWindowParams {
|
||||
// The impression associated with the navigation in the new window, if
|
||||
// one is specified.
|
||||
blink.mojom.Impression? impression;
|
||||
@@ -533,6 +533,10 @@ struct CreateNewWindowParams {
|
||||
|
||||
// Governs how downloads are handled if `target_url` results in a download.
|
||||
blink.mojom.NavigationDownloadPolicy download_policy;
|
||||
+
|
||||
+ // Extra fields added by Electron.
|
||||
+ string raw_features;
|
||||
@@ -68,10 +68,10 @@ index 72fd11b1733aa5433c1905933c357aa58c02578d..d6cdf5cfe1287cddf29279e28ce878cf
|
||||
|
||||
// Operation result when the renderer asks the browser to create a new window.
|
||||
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
|
||||
index 757313d3543d3777b0fb751197a6c16cb262514a..8bcdbc88d1445df9c833f7d6cd5f768c7a1b9c62 100644
|
||||
index 9f8dbbc7a63cf8a1a8166dd67efd452eab791426..8a45f8c39fe160829de316c513e73327dabfc391 100644
|
||||
--- a/content/public/browser/content_browser_client.cc
|
||||
+++ b/content/public/browser/content_browser_client.cc
|
||||
@@ -556,6 +556,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
@@ -557,6 +557,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -81,10 +81,10 @@ index 757313d3543d3777b0fb751197a6c16cb262514a..8bcdbc88d1445df9c833f7d6cd5f768c
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access) {
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index f97d7367f0e46eb7c59d6654138a6aec607beeea..75227e160dda6724e59271e702c956ea1470a40e 100644
|
||||
index 4db050cb8e5e328f84d4a5fc92aee7d743ee16c4..bb30bb3604a793cbe37d20a3a18b21d5abfd6530 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -164,6 +164,7 @@ class NetworkService;
|
||||
@@ -166,6 +166,7 @@ class NetworkService;
|
||||
class TrustedURLLoaderHeaderClient;
|
||||
} // namespace mojom
|
||||
struct ResourceRequest;
|
||||
@@ -92,7 +92,7 @@ index f97d7367f0e46eb7c59d6654138a6aec607beeea..75227e160dda6724e59271e702c956ea
|
||||
} // namespace network
|
||||
|
||||
namespace sandbox {
|
||||
@@ -921,6 +922,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
@@ -924,6 +925,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -150,7 +150,7 @@ index a0da74d5cbe4ab8be84d6f1a92f444e858320745..5936fa4bce09895595ccb294504f5b89
|
||||
// typically happens when popups are created.
|
||||
virtual void WebContentsCreated(WebContents* source_contents,
|
||||
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
|
||||
index 092352d96858b45a46ac1eddd162a63b1e468031..aa1cf3dfca39c4443311895a3d7abfc89aad8951 100644
|
||||
index ea22a86dc1a6e5cdb3e3dfa31a929a3dd14b9e61..215b059bb2dfcead6c709c99b39578f8e2216d93 100644
|
||||
--- a/content/renderer/render_view_impl.cc
|
||||
+++ b/content/renderer/render_view_impl.cc
|
||||
@@ -31,6 +31,7 @@
|
||||
@@ -169,9 +169,9 @@ index 092352d96858b45a46ac1eddd162a63b1e468031..aa1cf3dfca39c4443311895a3d7abfc8
|
||||
+ WTF::UTF8ConversionMode::kStrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD);
|
||||
+ params->body = GetRequestBodyForWebURLRequest(request);
|
||||
+
|
||||
// We preserve this information before sending the message since |params| is
|
||||
// moved on send.
|
||||
bool is_background_tab =
|
||||
params->download_policy.ApplyDownloadFramePolicy(
|
||||
/*is_opener_navigation=*/false, request.HasUserGesture(),
|
||||
// `openee_can_access_opener_origin` only matters for opener navigations,
|
||||
diff --git a/content/web_test/browser/web_test_content_browser_client.cc b/content/web_test/browser/web_test_content_browser_client.cc
|
||||
index c6872573086e628a894f482877db2d417552c6a1..5e67b6a59c3e3d6881f738985ab947a2d7902f0a 100644
|
||||
--- a/content/web_test/browser/web_test_content_browser_client.cc
|
||||
@@ -220,10 +220,10 @@ index 84d32491a56528a84b4395fba1d54cdbb38d522b..09998a83c449ef8cd9f360fbcdcf7edc
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
index 1a46a0589b5891ca0513ba9854fca034c56b25b8..d1040bc168dfd20405a09436e089a29696e31d41 100644
|
||||
index 10e40d408bb0b1526534918add49906e65d17368..b6a0473ad93f8ef1adc53536411e8fd62c106b5d 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
@@ -2008,6 +2008,7 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
@@ -2022,6 +2022,7 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
|
||||
WebWindowFeatures window_features =
|
||||
GetWindowFeaturesFromString(features, incumbent_window);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Fri, 6 Aug 2021 03:36:57 -0700
|
||||
Subject: chore: do not use chrome.windows in cryptotoken webrequestsender
|
||||
|
||||
Electron does not support chrome.windows which this method depends on. It also does not need to, the method's goal is to determine if the webContents that triggered the cryptotoken request is still "active". In Chrome this means active tab in the tab strip === this tab + the window owning that tab strip is focused.
|
||||
|
||||
In Electron that can be simplified to webContents.isFocused() which maps to "is the webContents view focused and is the owning window the key window". We map tab.active to that IsFocused() value and we can remove the chrome.windows logic here.
|
||||
|
||||
This can't be upstreamed but the patch is minimal.
|
||||
|
||||
diff --git a/chrome/browser/resources/cryptotoken/webrequestsender.js b/chrome/browser/resources/cryptotoken/webrequestsender.js
|
||||
index 734abbbf3132d245c2c39bbe9b7780acbea196b0..adff416286eaa10a099be83aaf07e56ec323fe3d 100644
|
||||
--- a/chrome/browser/resources/cryptotoken/webrequestsender.js
|
||||
+++ b/chrome/browser/resources/cryptotoken/webrequestsender.js
|
||||
@@ -134,10 +134,11 @@ function tabInForeground(tabId) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
- if (!chrome.windows || !chrome.windows.get) {
|
||||
- reject();
|
||||
- return;
|
||||
- }
|
||||
+ // Electron does not support chrome.windows
|
||||
+ // if (!chrome.windows || !chrome.windows.get) {
|
||||
+ // reject();
|
||||
+ // return;
|
||||
+ // }
|
||||
chrome.tabs.get(tabId, function(tab) {
|
||||
if (chrome.runtime.lastError) {
|
||||
resolve(false);
|
||||
@@ -147,9 +148,13 @@ function tabInForeground(tabId) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
- chrome.windows.get(tab.windowId, function(aWindow) {
|
||||
- resolve(aWindow && aWindow.focused);
|
||||
- });
|
||||
+ // tab.active in Electron maps to the "focused" state of the view
|
||||
+ // which is only true when both the webContents and the window are
|
||||
+ // focused.
|
||||
+ resolve(true);
|
||||
+ // chrome.windows.get(tab.windowId, function(aWindow) {
|
||||
+ // resolve(aWindow && aWindow.focused);
|
||||
+ // });
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -108,10 +108,10 @@ index ef84e04d628fb5cdbaf8fbbf84af3bf23e00c522..f1ee0bee5bfd08227a29498f8410d5d3
|
||||
}
|
||||
|
||||
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
|
||||
index c522e51369fbcdf482a467475abce309bd8195c5..f7c95b019f4a19c94ec95234e7bdda84d8bfcf51 100644
|
||||
index 61724ab53609f80cf5a0139c8bdb2ad1fb0413b2..b8647710bf9a16e8ffc3ca3b25aa4f6c584fa9be 100644
|
||||
--- a/chrome/browser/ui/browser.cc
|
||||
+++ b/chrome/browser/ui/browser.cc
|
||||
@@ -1788,12 +1788,11 @@ bool Browser::IsWebContentsCreationOverridden(
|
||||
@@ -1789,12 +1789,11 @@ bool Browser::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
@@ -127,10 +127,10 @@ index c522e51369fbcdf482a467475abce309bd8195c5..f7c95b019f4a19c94ec95234e7bdda84
|
||||
|
||||
WebContents* Browser::CreateCustomWebContents(
|
||||
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
|
||||
index 17c3233034d0e40970887253c2518486cc32825e..795a8390c23ac016d05ea8898f2a082cd5a80fbc 100644
|
||||
index 7649c59dde3f58b5ec153eb6146b159cfc190975..c1cc53b89d805f63fe4dcda12e02cd0a2687f926 100644
|
||||
--- a/chrome/browser/ui/browser.h
|
||||
+++ b/chrome/browser/ui/browser.h
|
||||
@@ -798,8 +798,7 @@ class Browser : public TabStripModelObserver,
|
||||
@@ -807,8 +807,7 @@ class Browser : public TabStripModelObserver,
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
@@ -232,10 +232,10 @@ index c5c5a7b63b5b3b62a9517cbef3ae23ce57a3c89c..4f1b7e88d6d2ae89a60311c8aeb1fcee
|
||||
void AddNewContents(content::WebContents* source,
|
||||
std::unique_ptr<content::WebContents> new_contents,
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 1e38a16e950a4ee5ed63405576b57185fe7b9e3c..8b9e76ad6eee5e03bfa97a2f5c6c7d8898f0dfe5 100644
|
||||
index bc84aa5826d4ca8aef8f496acd3569152007b7a8..b6524566b96a141ba710441ab70d17f46e5b1b9a 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3675,8 +3675,7 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -3687,8 +3687,7 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
|
||||
if (delegate_ && delegate_->IsWebContentsCreationOverridden(
|
||||
source_site_instance, params.window_container_type,
|
||||
@@ -302,10 +302,10 @@ index 9b293d0df6c634bf44a69d607c4eee839a74b4a1..7e5b9cbdcc232c5e20eae0130d800f50
|
||||
content::RenderFrameHost* opener,
|
||||
content::SiteInstance* source_site_instance,
|
||||
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
|
||||
index 2dc016e4be765413b4cef0f5471dcf9240f73ff5..224cd2be71670ac565d02ecb2838123154255dc6 100644
|
||||
index b794ee4204fb8eaf90084e762f80988af13609b4..ac4e00f2ef1d2a722851d88531c28e65dea0341e 100644
|
||||
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
|
||||
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
|
||||
@@ -386,8 +386,7 @@ bool MimeHandlerViewGuest::IsWebContentsCreationOverridden(
|
||||
@@ -385,8 +385,7 @@ bool MimeHandlerViewGuest::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
@@ -344,10 +344,10 @@ index 2863abb239a77b96e638c83f47ae7219cf0ccec8..5675ad386efa99383067eb404b385cf2
|
||||
// can catch bad client behavior while not interfering with normal operation.
|
||||
constexpr size_t kMaxPendingWebContentsCount = 10;
|
||||
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h
|
||||
index e2736c5329d9516fdd417df4dff8039f991e800e..11081373e0d70e7ec366c6917c21db61c4e18cca 100644
|
||||
index 3e65c4e8faf63ab1d42e3f57457a071e322383dc..5f4d859f8f3ebb58336485a0a39837eec2c46294 100644
|
||||
--- a/fuchsia/engine/browser/frame_impl.h
|
||||
+++ b/fuchsia/engine/browser/frame_impl.h
|
||||
@@ -245,8 +245,7 @@ class FrameImpl : public fuchsia::web::Frame,
|
||||
@@ -246,8 +246,7 @@ class FrameImpl : public fuchsia::web::Frame,
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
@@ -358,7 +358,7 @@ index e2736c5329d9516fdd417df4dff8039f991e800e..11081373e0d70e7ec366c6917c21db61
|
||||
int opener_render_process_id,
|
||||
int opener_render_frame_id,
|
||||
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
|
||||
index dd1f6129173a0e19023f4ec9b66c44486b080456..d10468c06f84b59387af0a8fd5bc1c06108865eb 100644
|
||||
index 09bb4b3ef68aeb6dc2fa83ab574c46bebc68dcd1..e104fcba8c5c2e5530ae9a231c21fb1cd69ee303 100644
|
||||
--- a/headless/lib/browser/headless_web_contents_impl.cc
|
||||
+++ b/headless/lib/browser/headless_web_contents_impl.cc
|
||||
@@ -192,8 +192,7 @@ class HeadlessWebContentsImpl::Delegate : public content::WebContentsDelegate {
|
||||
|
||||
@@ -7,10 +7,10 @@ spellchecker uses a few IDS_ resources. We need to load these from
|
||||
Electrons grit header instead of Chromes
|
||||
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index 708f198ecb05fe37ea979cd7d79c6613a3fd3ff5..74f816aef514eef1263d9b2c25cf3a52359860a6 100644
|
||||
index 8847ed67e305d746c671afb49b445afaf24b85b3..3acfeb5e5bf721fabe2339e389193cd9e154e293 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -6635,6 +6635,7 @@ static_library("browser") {
|
||||
@@ -6689,6 +6689,7 @@ static_library("browser") {
|
||||
deps += [
|
||||
"//components/spellcheck/browser",
|
||||
"//components/spellcheck/common",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user