Compare commits

..

1 Commits

Author SHA1 Message Date
Sudowoodo Release Bot
7e155e50ab Bump v17.0.0-alpha.1 2021-11-17 07:46:10 -08:00
823 changed files with 9459 additions and 12428 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2
.github/CODEOWNERS vendored
View File

@@ -4,7 +4,7 @@
# https://git-scm.com/docs/gitignore
# Upgrades WG
/patches/ @electron/wg-upgrades @electron/wg-security
/patches/ @electron/wg-upgrades
DEPS @electron/wg-upgrades
# Releases WG

View File

@@ -12,7 +12,7 @@ body:
required: true
- 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 bug report that matches the one I want to file, without success.
- label: I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a feature request that matches the one I want to file, without success.
required: true
- type: input
attributes:

View File

@@ -361,7 +361,6 @@ source_set("electron_lib") {
"//components/network_hints/common:mojo_bindings",
"//components/network_hints/renderer",
"//components/network_session_configurator/common",
"//components/omnibox/browser:buildflags",
"//components/os_crypt",
"//components/pref_registry",
"//components/prefs",
@@ -473,8 +472,8 @@ source_set("electron_lib") {
if (is_linux) {
deps += [
"//build/config/linux/gtk:gtkprint",
"//components/crash/content/browser",
"//ui/gtk:gtk_config",
]
}
@@ -539,25 +538,19 @@ source_set("electron_lib") {
"//build/config/linux/gtk",
"//dbus",
"//device/bluetooth",
"//ui/base/ime/linux",
"//ui/events/devices/x11",
"//ui/events/platform/x11",
"//ui/gtk",
"//ui/views/controls/webview",
"//ui/wm",
]
if (ozone_platform_x11) {
if (use_x11) {
sources += filenames.lib_sources_linux_x11
public_deps += [
"//ui/base/x",
"//ui/ozone/platform/x11",
]
}
configs += [ ":gio_unix" ]
defines += [
# Disable warnings for g_settings_list_schemas.
"GLIB_DISABLE_DEPRECATION_WARNINGS",
"USE_X11=1",
]
sources += [
@@ -634,6 +627,12 @@ source_set("electron_lib") {
}
if (enable_desktop_capturer) {
if (is_component_build && !is_linux) {
# On windows the implementation relies on unexported
# DxgiDuplicatorController class. On macOS the implementation
# relies on unexported webrtc::GetWindowOwnerPid method.
deps += [ "//third_party/webrtc/modules/desktop_capture" ]
}
sources += [
"shell/browser/api/electron_api_desktop_capturer.cc",
"shell/browser/api/electron_api_desktop_capturer.h",
@@ -901,12 +900,8 @@ if (is_mac) {
deps += [ "//sandbox/mac:seatbelt" ]
}
defines = [ "HELPER_EXECUTABLE" ]
sources = [
"shell/app/electron_main_mac.cc",
"shell/app/uv_stdio_fix.cc",
"shell/app/uv_stdio_fix.h",
"shell/common/electron_constants.cc",
]
sources = filenames.app_sources
sources += [ "shell/common/electron_constants.cc" ]
include_dirs = [ "." ]
info_plist = "shell/renderer/resources/mac/Info.plist"
extra_substitutions =
@@ -1045,18 +1040,15 @@ if (is_mac) {
mac_app_bundle("electron_app") {
output_name = electron_product_name
sources = [
"shell/app/electron_main_mac.cc",
"shell/app/uv_stdio_fix.cc",
"shell/app/uv_stdio_fix.h",
"shell/common/electron_constants.cc",
]
sources = filenames.app_sources
sources += [ "shell/common/electron_constants.cc" ]
include_dirs = [ "." ]
deps = [
":electron_app_framework_bundle_data",
":electron_app_plist",
":electron_app_resources",
":electron_fuses",
"//base",
"//electron/buildflags",
]
if (is_mas_build) {
@@ -1158,15 +1150,7 @@ if (is_mac) {
executable("electron_app") {
output_name = electron_project_name
if (is_win) {
sources = [ "shell/app/electron_main_win.cc" ]
} else if (is_linux) {
sources = [
"shell/app/electron_main_linux.cc",
"shell/app/uv_stdio_fix.cc",
"shell/app/uv_stdio_fix.h",
]
}
sources = filenames.app_sources
include_dirs = [ "." ]
deps = [
":default_app_asar",
@@ -1187,7 +1171,7 @@ if (is_mac) {
if (enable_hidpi) {
data += [ "$root_out_dir/chrome_200_percent.pak" ]
}
foreach(locale, platform_pak_locales) {
foreach(locale, locales) {
data += [ "$root_out_dir/locales/$locale.pak" ]
}
@@ -1402,13 +1386,11 @@ dist_zip("electron_dist_zip") {
if (is_linux) {
data_deps += [ "//sandbox/linux:chrome_sandbox" ]
}
deps = data_deps
outputs = [ "$root_build_dir/dist.zip" ]
}
dist_zip("electron_ffmpeg_zip") {
data_deps = [ "//third_party/ffmpeg" ]
deps = data_deps
outputs = [ "$root_build_dir/ffmpeg.zip" ]
}
@@ -1426,7 +1408,6 @@ group("electron_chromedriver") {
dist_zip("electron_chromedriver_zip") {
testonly = true
data_deps = electron_chromedriver_deps
deps = data_deps
outputs = [ "$root_build_dir/chromedriver.zip" ]
}
@@ -1445,7 +1426,6 @@ group("electron_mksnapshot") {
dist_zip("electron_mksnapshot_zip") {
data_deps = mksnapshot_deps
deps = data_deps
outputs = [ "$root_build_dir/mksnapshot.zip" ]
}
@@ -1456,7 +1436,6 @@ copy("hunspell_dictionaries") {
dist_zip("hunspell_dictionaries_zip") {
data_deps = [ ":hunspell_dictionaries" ]
deps = data_deps
flatten = true
outputs = [ "$root_build_dir/hunspell_dictionaries.zip" ]
@@ -1470,7 +1449,6 @@ copy("libcxx_headers") {
dist_zip("libcxx_headers_zip") {
data_deps = [ ":libcxx_headers" ]
deps = data_deps
flatten = true
flatten_relative_to = rebase_path(
"$target_gen_dir/electron_libcxx_include/buildtools/third_party/libc++/trunk",
@@ -1486,7 +1464,6 @@ copy("libcxxabi_headers") {
dist_zip("libcxxabi_headers_zip") {
data_deps = [ ":libcxxabi_headers" ]
deps = data_deps
flatten = true
flatten_relative_to = rebase_path(
"$target_gen_dir/electron_libcxxabi_include/buildtools/third_party/libc++abi/trunk",

4
DEPS
View File

@@ -15,9 +15,9 @@ gclient_gn_args = [
vars = {
'chromium_version':
'100.0.4894.0',
'96.0.4664.4',
'node_version':
'v16.13.2',
'v16.13.0',
'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

View File

@@ -1 +1 @@
18.0.0-alpha.6
17.0.0-alpha.1

View File

@@ -2,7 +2,7 @@
[![CircleCI Build Status](https://circleci.com/gh/electron/electron/tree/main.svg?style=shield)](https://circleci.com/gh/electron/electron/tree/main)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/4lggi9dpjc1qob7k/branch/main?svg=true)](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/main)
[![Electron Discord Invite](https://img.shields.io/discord/745037351163527189?color=%237289DA&label=chat&logo=discord&logoColor=white)](https://discord.com/invite/APGC3k5yaH)
[![Electron Discord Invite](https://img.shields.io/discord/745037351163527189?color=%237289DA&label=chat&logo=discord&logoColor=white)](https://discord.com/invite/electron)
:memo: Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪.
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
@@ -80,7 +80,7 @@ const child = proc.spawn(electron)
### Mirrors
- [China](https://npmmirror.com/mirrors/electron)
- [China](https://npm.taobao.org/mirrors/electron)
## Documentation Translations

View File

@@ -34,7 +34,6 @@ environment:
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
ELECTRON_OUT_DIR: Default
ELECTRON_ENABLE_STACK_DUMPING: 1
ELECTRON_ALSO_LOG_TO_STDERR: 1
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
GOMA_FALLBACK_ON_AUTH_FAILURE: true
@@ -210,9 +209,7 @@ test_script:
}
- cd electron
# CalculateNativeWinOcclusion is disabled due to https://bugs.chromium.org/p/chromium/issues/detail?id=1139022
- if "%RUN_TESTS%"=="true" ( echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
- if "%RUN_TESTS%"=="true" ( echo Running remote test suite & node script/yarn test -- --trace-uncaught --runners=remote --runTestFilesSeperately --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
- if "%RUN_TESTS%"=="true" ( echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
- if "%RUN_TESTS%"=="true" ( echo Running test suite & node script/yarn test -- --trace-uncaught --enable-logging --disable-features=CalculateNativeWinOcclusion )
- cd ..
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
- echo "About to verify mksnapshot"
@@ -220,7 +217,6 @@ test_script:
- echo "Done verifying mksnapshot"
- if "%RUN_TESTS%"=="true" ( echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd% )
- echo "Done verifying chromedriver"
- if exist %cd%\electron.log ( appveyor-retry appveyor PushArtifact %cd%\electron.log )
deploy_script:
- cd electron
- ps: >-
@@ -235,5 +231,3 @@ deploy_script:
} elseif (Test-Path Env:\TEST_WOA) {
node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
}
on_finish:
- if exist src\electron\electron.log ( appveyor-retry appveyor PushArtifact src\electron\electron.log )

View File

@@ -1,11 +1,11 @@
workspace:
clean: all
steps:
- checkout: self
path: src\electron
- task: CopyFiles@2
displayName: 'Copy Files to: src\electron'
inputs:
TargetFolder: src\electron
- script: |
cd src\electron
node script/yarn.js install --frozen-lockfile
displayName: 'Yarn install'
@@ -13,13 +13,13 @@ steps:
$localArtifactPath = "$pwd\dist.zip"
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/dist.zip"
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -o$(Pipeline.Workspace)\src\out\Default -y $localArtifactPath
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\Default -y $localArtifactPath
displayName: 'Download and extract dist.zip for test'
env:
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
- powershell: |
$localArtifactPath = "$(Pipeline.Workspace)\src\out\Default\shell_browser_ui_unittests.exe"
$localArtifactPath = "$pwd\src\out\Default\shell_browser_ui_unittests.exe"
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/shell_browser_ui_unittests.exe"
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
displayName: 'Download and extract native test executables for test'
@@ -30,57 +30,56 @@ steps:
$localArtifactPath = "$pwd\ffmpeg.zip"
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/ffmpeg.zip"
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -o$(Pipeline.Workspace)\src\out\ffmpeg $localArtifactPath
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\ffmpeg $localArtifactPath
displayName: 'Download and extract ffmpeg.zip for test'
env:
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
- powershell: |
$localArtifactPath = "$(Pipeline.Workspace)\src\node_headers.zip"
$localArtifactPath = "$pwd\src\node_headers.zip"
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/node_headers.zip"
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
cd $(Pipeline.Workspace)\src
cd src
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y node_headers.zip
displayName: 'Download node headers for test'
env:
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
- powershell: |
$localArtifactPath = "$(Pipeline.Workspace)\src\out\Default\electron.lib"
$localArtifactPath = "$pwd\src\out\Default\electron.lib"
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/electron.lib"
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
displayName: 'Download electron.lib for test'
env:
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
# Uncomment the following block if pdb files are needed to debug issues
# - powershell: |
# try {
# $localArtifactPath = "$(Pipeline.Workspace)\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 $(Pipeline.Workspace)\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)
- powershell: |
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)
- powershell: |
New-Item $(Pipeline.Workspace)\src\out\Default\gen\node_headers\Release -Type directory
Copy-Item -path $(Pipeline.Workspace)\src\out\Default\electron.lib -destination $(Pipeline.Workspace)\src\out\Default\gen\node_headers\Release\node.lib
New-Item src\out\Default\gen\node_headers\Release -Type directory
Copy-Item -path src\out\Default\electron.lib -destination src\out\Default\gen\node_headers\Release\node.lib
displayName: 'Setup node headers'
- script: |
cd $(Pipeline.Workspace)\src
cd src
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
set npm_config_arch=arm64
cd electron
node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
node script/yarn test --runners=main --runTestFilesSeperately --enable-logging --disable-features=CalculateNativeWinOcclusion
displayName: 'Run Electron Main process tests'
env:
ELECTRON_ENABLE_STACK_DUMPING: true
@@ -91,7 +90,7 @@ steps:
MOCHA_REPORTER: mocha-multi-reporters
- script: |
cd $(Pipeline.Workspace)\src
cd src
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
set npm_config_arch=arm64
cd electron
@@ -103,17 +102,17 @@ steps:
ELECTRON_TEST_RESULTS_DIR: junit
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
MOCHA_REPORTER: mocha-multi-reporters
condition: succeededOrFailed()
condition: always()
- task: PublishTestResults@2
displayName: 'Publish Test Results'
inputs:
testResultsFiles: '*.xml'
searchFolder: '$(Pipeline.Workspace)/src/junit/'
searchFolder: '$(System.DefaultWorkingDirectory)/src/junit/'
condition: always()
- script: |
cd $(Pipeline.Workspace)\src
cd src
echo "Verifying non proprietary ffmpeg"
python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
displayName: 'Verify ffmpeg'

View File

@@ -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 = 103
node_module_version = 101
v8_promise_internal_field_count = 1
v8_typed_array_max_size_in_heap = 0
@@ -11,12 +11,6 @@ v8_embedder_string = "-electron.0"
# TODO: this breaks mksnapshot
v8_enable_snapshot_native_code_counters = false
# TODO(codebytere): remove when Node.js handles https://chromium-review.googlesource.com/c/v8/v8/+/3211575
v8_scriptormodule_legacy_lifetime = true
# we use this api
v8_enable_javascript_promise_hooks = true
enable_cdm_host_verification = false
proprietary_codecs = true
ffmpeg_branding = "Chrome"

View File

@@ -53,8 +53,8 @@ static_library("chrome") {
"//chrome/browser/predictors/resolve_host_client_impl.cc",
"//chrome/browser/predictors/resolve_host_client_impl.h",
"//chrome/browser/process_singleton.h",
"//chrome/browser/process_singleton_internal.cc",
"//chrome/browser/process_singleton_internal.h",
"//chrome/browser/ui/browser_dialogs.cc",
"//chrome/browser/ui/browser_dialogs.h",
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc",
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h",
"//chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc",
@@ -69,6 +69,8 @@ static_library("chrome") {
"//chrome/browser/ui/exclusive_access/keyboard_lock_controller.h",
"//chrome/browser/ui/exclusive_access/mouse_lock_controller.cc",
"//chrome/browser/ui/exclusive_access/mouse_lock_controller.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",
"//chrome/browser/ui/views/eye_dropper/eye_dropper.h",
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc",
@@ -140,6 +142,10 @@ static_library("chrome") {
"//components/optimization_guide/proto:optimization_guide_proto",
]
if (enable_basic_printing && is_win) {
deps += [ "//chrome/common:cloud_print_utility_mojom" ]
}
if (is_linux) {
sources += [ "//chrome/browser/icon_loader_auralinux.cc" ]
if (use_ozone) {
@@ -195,16 +201,12 @@ static_library("chrome") {
if (enable_basic_printing) {
sources += [
"//chrome/browser/bad_message.cc",
"//chrome/browser/bad_message.h",
"//chrome/browser/printing/print_job.cc",
"//chrome/browser/printing/print_job.h",
"//chrome/browser/printing/print_job_manager.cc",
"//chrome/browser/printing/print_job_manager.h",
"//chrome/browser/printing/print_job_worker.cc",
"//chrome/browser/printing/print_job_worker.h",
"//chrome/browser/printing/print_job_worker_oop.cc",
"//chrome/browser/printing/print_job_worker_oop.h",
"//chrome/browser/printing/print_view_manager_base.cc",
"//chrome/browser/printing/print_view_manager_base.h",
"//chrome/browser/printing/printer_query.cc",
@@ -239,6 +241,8 @@ static_library("chrome") {
sources += [
"//chrome/browser/printing/pdf_to_emf_converter.cc",
"//chrome/browser/printing/pdf_to_emf_converter.h",
"//chrome/utility/printing_handler.cc",
"//chrome/utility/printing_handler.h",
]
}
}
@@ -253,12 +257,8 @@ static_library("chrome") {
"//chrome/browser/ui/views/overlay/close_image_button.cc",
"//chrome/browser/ui/views/overlay/close_image_button.h",
"//chrome/browser/ui/views/overlay/constants.h",
"//chrome/browser/ui/views/overlay/document_overlay_window_views.cc",
"//chrome/browser/ui/views/overlay/document_overlay_window_views.h",
"//chrome/browser/ui/views/overlay/hang_up_button.cc",
"//chrome/browser/ui/views/overlay/hang_up_button.h",
"//chrome/browser/ui/views/overlay/overlay_window_image_button.cc",
"//chrome/browser/ui/views/overlay/overlay_window_image_button.h",
"//chrome/browser/ui/views/overlay/overlay_window_views.cc",
"//chrome/browser/ui/views/overlay/overlay_window_views.h",
"//chrome/browser/ui/views/overlay/playback_image_button.cc",
@@ -273,14 +273,11 @@ static_library("chrome") {
"//chrome/browser/ui/views/overlay/toggle_microphone_button.h",
"//chrome/browser/ui/views/overlay/track_image_button.cc",
"//chrome/browser/ui/views/overlay/track_image_button.h",
"//chrome/browser/ui/views/overlay/video_overlay_window_views.cc",
"//chrome/browser/ui/views/overlay/video_overlay_window_views.h",
]
deps += [
"//chrome/app/vector_icons",
"//components/vector_icons:vector_icons",
"//ui/views/controls/webview",
]
}
@@ -300,8 +297,6 @@ static_library("chrome") {
sources += [
"//chrome/browser/pdf/pdf_extension_util.cc",
"//chrome/browser/pdf/pdf_extension_util.h",
"//chrome/browser/pdf/pdf_frame_util.cc",
"//chrome/browser/pdf/pdf_frame_util.h",
"//chrome/renderer/pepper/chrome_pdf_print_client.cc",
"//chrome/renderer/pepper/chrome_pdf_print_client.h",
]

View File

@@ -1,5 +1,4 @@
import { shell } from 'electron/common';
import { app, dialog, BrowserWindow, ipcMain } from 'electron/main';
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
import * as path from 'path';
import * as url from 'url';

View File

@@ -1,4 +1,4 @@
import * as electron from 'electron/main';
import * as electron from 'electron';
import * as fs from 'fs';
import * as path from 'path';
@@ -92,7 +92,7 @@ function loadApplicationPackage (packagePath: string) {
try {
packageJson = require(packageJsonPath);
} catch (e) {
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${(e as Error).message}`);
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`);
return;
}
@@ -111,7 +111,7 @@ function loadApplicationPackage (packagePath: string) {
const filePath = Module._resolveFilename(packagePath, module, true);
app.setAppPath(appPath || path.dirname(filePath));
} catch (e) {
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${(e as Error).message}`);
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`);
return;
}
@@ -119,7 +119,7 @@ function loadApplicationPackage (packagePath: string) {
Module._load(packagePath, module, true);
} catch (e) {
console.error('App threw an error during load');
console.error((e as Error).stack || e);
console.error(e.stack || e);
throw e;
}
}

View File

@@ -1,4 +1,4 @@
import { ipcRenderer, contextBridge } from 'electron/renderer';
import { ipcRenderer, contextBridge } from 'electron';
const policy = window.trustedTypes.createPolicy('electron-default-app', {
// we trust the SVG contents

View File

@@ -106,6 +106,7 @@ These individual tutorials expand on topics discussed in the guide above.
* [`File` Object](api/file-object.md)
* [`<webview>` Tag](api/webview-tag.md)
* [`window.open` Function](api/window-open.md)
* [`BrowserWindowProxy` Object](api/browser-window-proxy.md)
### Modules for the Main Process:

View File

@@ -484,7 +484,6 @@ Returns:
* `argv` string[] - An array of the second instance's command line arguments
* `workingDirectory` string - The second instance's working directory
* `additionalData` unknown - A JSON object of additional data passed from the second instance
* `ackCallback` unknown - A function that can be used to send data back to the second instance
This event will be emitted inside the primary instance of your application
when a second instance has been executed and calls `app.requestSingleInstanceLock()`.
@@ -496,35 +495,12 @@ non-minimized.
**Note:** If the second instance is started by a different user than the first, the `argv` array will not include the arguments.
**Note:** `ackCallback` allows the user to send data back to the
second instance during the `app.requestSingleInstanceLock()` flow.
This callback can be used for cases where the second instance
needs to obtain additional information from the first instance
before quitting.
Currently, the limit on the message size is kMaxMessageLength,
or around 32kB. To be safe, keep the amount of data passed to 31kB at most.
In order to call the callback, `event.preventDefault()` must be called, first.
If the callback is not called in either case, `null` will be sent back.
If `event.preventDefault()` is not called, but `ackCallback` is called
by the user in the event, then the behaviour is undefined.
This event is guaranteed to be emitted after the `ready` event of `app`
gets emitted.
**Note:** Extra command line arguments might be added by Chromium,
such as `--original-process-start-time`.
### Event: 'first-instance-ack'
Returns:
* `event` Event
* `additionalData` unknown - A JSON object of additional data passed from the first instance, in response to the first instance's `second-instance` event.
This event will be emitted within the second instance during the call to `app.requestSingleInstanceLock()`, when the first instance calls the `ackCallback` provided by the `second-instance` event handler.
## Methods
The `app` object has the following methods:
@@ -954,9 +930,9 @@ app.setJumpList([
])
```
### `app.requestSingleInstanceLock([additionalData])`
### `app.requestSingleInstanceLock()`
* `additionalData` Record<any, any> (optional) - A JSON object containing additional data to send to the first instance.
* `additionalData` unknown (optional) - A JSON object containing additional data to send to the first instance.
Returns `boolean`
@@ -983,13 +959,6 @@ starts:
const { app } = require('electron')
let myWindow = null
app.on('first-instance-ack', (event, additionalData) => {
// Print out the ack received from the first instance.
// Note this event handler must come before the requestSingleInstanceLock call.
// Expected output: '{"myAckKey":"myAckValue"}'
console.log(JSON.stringify(additionalData))
})
const additionalData = { myKey: 'myValue' }
const gotTheLock = app.requestSingleInstanceLock(additionalData)
@@ -997,19 +966,14 @@ if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory, additionalData) => {
// We must call preventDefault if we're sending back data.
event.preventDefault()
// Print out data received from the second instance.
// Expected output: '{"myKey":"myValue"}'
console.log(JSON.stringify(additionalData))
console.log(additionalData)
// Someone tried to run a second instance, we should focus our window.
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore()
myWindow.focus()
}
const ackData = { myAckKey: 'myAckValue' }
ackCallback(ackData)
})
// Create myWindow, load the rest of the app, etc...

View File

@@ -15,16 +15,14 @@ Process: [Main](../glossary.md#main-process)
```javascript
// In the main process.
const { app, BrowserView, BrowserWindow } = require('electron')
const { BrowserView, BrowserWindow } = require('electron')
app.whenReady().then(() => {
const win = new BrowserWindow({ width: 800, height: 600 })
const win = new BrowserWindow({ width: 800, height: 600 })
const view = new BrowserView()
win.setBrowserView(view)
view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
view.webContents.loadURL('https://electronjs.org')
})
const view = new BrowserView()
win.setBrowserView(view)
view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
view.webContents.loadURL('https://electronjs.org')
```
### `new BrowserView([options])` _Experimental_

View File

@@ -0,0 +1,54 @@
## Class: BrowserWindowProxy
> Manipulate the child browser window
Process: [Renderer](../glossary.md#renderer-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._
The `BrowserWindowProxy` object is returned from `window.open` and provides
limited functionality with the child window.
### Instance Methods
The `BrowserWindowProxy` object has the following instance methods:
#### `win.blur()`
Removes focus from the child window.
#### `win.close()`
Forcefully closes the child window without calling its unload event.
#### `win.eval(code)`
* `code` string
Evaluates the code in the child window.
#### `win.focus()`
Focuses the child window (brings the window to front).
#### `win.print()`
Invokes the print dialog on the child window.
#### `win.postMessage(message, targetOrigin)`
* `message` any
* `targetOrigin` string
Sends a message to the child window with the specified origin or `*` for no
origin preference.
In addition to these methods, the child window implements `window.opener` object
with no properties and a single method.
### Instance Properties
The `BrowserWindowProxy` object has the following instance properties:
#### `win.closed`
A `boolean` that is set to true after the child window gets closed.

View File

@@ -341,6 +341,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
[Chrome Content Scripts][chrome-content-scripts]. You can access this
context in the dev tools by selecting the 'Electron Isolated Context'
entry in the combo box at the top of the Console tab.
* `nativeWindowOpen` boolean (optional) - Whether to use native
`window.open()`. Defaults to `true`. Child windows will always have node
integration disabled unless `nodeIntegrationInSubFrames` is true.
* `webviewTag` boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag.md).
Defaults to `false`. **Note:** The
`preload` script configured for the `<webview>` will have node integration
@@ -388,10 +391,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
contain the layout of the document—without requiring scrolling. Enabling
this will cause the `preferred-size-changed` event to be emitted on the
`WebContents` when the preferred size changes. Default is `false`.
* `titleBarOverlay` Object | Boolean (optional) - When using a frameless window in conjunction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`.
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
* `height` Integer (optional) _macOS_ _Windows_ - The height of the title bar and Window Controls Overlay in pixels. Default is system height.
* `titleBarOverlay` Object | boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`.
* `color` string (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
* `symbolColor` string (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
@@ -557,7 +559,7 @@ Returns:
Emitted before the window is moved. On Windows, calling `event.preventDefault()` will prevent the window from being moved.
Note that this is only emitted when the window is being moved manually. Moving the window with `setPosition`/`setBounds`/`center` will not emit this event.
Note that this is only emitted when the window is being resized manually. Resizing the window with `setBounds`/`setSize` will not emit this event.
#### Event: 'move'
@@ -997,7 +999,7 @@ APIs like `win.setSize`.
is `true`). Default is `#FFF` (white).
Sets the background color of the window. See [Setting
`backgroundColor`](#setting-the-backgroundcolor-property).
`backgroundColor`](#setting-backgroundcolor).
#### `win.previewFile(path[, displayName])` _macOS_
@@ -1042,7 +1044,7 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
#### `win.getBackgroundColor()`
Returns `string` - Gets the background color of the window. See [Setting
`backgroundColor`](#setting-the-backgroundcolor-property).
`backgroundColor`](#setting-backgroundcolor).
#### `win.setContentBounds(bounds[, animate])`

View File

@@ -76,7 +76,7 @@ Writes `markup` to the clipboard.
```js
const { clipboard } = require('electron')
clipboard.writeHTML('<b>Hi</b>')
clipboard.writeHTML('<b>Hi</b')
```
### `clipboard.readImage([type])`

View File

@@ -102,8 +102,8 @@ has been included below for completeness:
| `boolean` | Simple | ✅ | ✅ | N/A |
| `Object` | Complex | ✅ | ✅ | Keys must be supported using only "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
| `Array` | Complex | ✅ | ✅ | Same limitations as the `Object` type |
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context, and any custom properties on the Error object [will be lost](https://github.com/electron/electron/issues/25596) |
| `Promise` | Complex | ✅ | ✅ | N/A
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context |
| `Promise` | Complex | ✅ | ✅ | Promises are only proxied if they are the return value or exact parameter. Promises nested in arrays or objects will be dropped. |
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |

View File

@@ -27,7 +27,6 @@ Or use a 3rd party hosted solution:
* [Backtrace](https://backtrace.io/electron/)
* [Sentry](https://docs.sentry.io/clients/electron)
* [BugSplat](https://www.bugsplat.com/docs/platforms/electron)
* [Bugsnag](https://docs.bugsnag.com/platforms/electron/)
Crash reports are stored temporarily before being uploaded in a directory
underneath the app's user data directory, called 'Crashpad'. You can override

View File

@@ -285,7 +285,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
include a checkbox with the given label.
* `checkboxChecked` boolean (optional) - Initial checked state of the
checkbox. `false` by default.
* `icon` ([NativeImage](native-image.md) | string) (optional)
* `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

View File

@@ -28,7 +28,7 @@ When `informational` is passed, the dock icon will bounce for one second.
However, the request remains active until either the application becomes active
or the request is canceled.
**Note:** This method can only be used while the app is not focused; when the app is focused it will return -1.
**Nota Bene:** This method can only be used while the app is not focused; when the app is focused it will return -1.
#### `dock.cancelBounce(id)` _macOS_

View File

@@ -122,7 +122,7 @@ Prints Chromium's internal logging to the console.
Setting this variable is the same as passing `--enable-logging`
on the command line. For more info, see `--enable-logging` in [command-line
switches](./command-line-switches.md#--enable-loggingfile).
switches](./command-line-switches.md#enable-loggingfile).
### `ELECTRON_LOG_FILE`
@@ -130,7 +130,7 @@ Sets the file destination for Chromium's internal logging.
Setting this variable is the same as passing `--log-file`
on the command line. For more info, see `--log-file` in [command-line
switches](./command-line-switches.md#--log-filepath).
switches](./command-line-switches.md#log-filepath).
### `ELECTRON_DEBUG_DRAG_REGIONS`

View File

@@ -80,25 +80,3 @@ An `Integer` indicating the HTTP protocol major version number.
An `Integer` indicating the HTTP protocol minor version number.
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
#### `response.rawHeaders`
A `string[]` containing the raw HTTP response headers exactly as they were
received. The keys and values are in the same list. It is not a list of
tuples. So, the even-numbered offsets are key values, and the odd-numbered
offsets are the associated values. Header names are not lowercased, and
duplicates are not merged.
```javascript
// Prints something like:
//
// [ 'user-agent',
// 'this is invalid because there can be only one',
// 'User-Agent',
// 'curl/7.22.0',
// 'Host',
// '127.0.0.1:8000',
// 'ACCEPT',
// '*/*' ]
console.log(request.rawHeaders)
```

View File

@@ -14,7 +14,7 @@ See [`Menu`](menu.md) for examples.
* `menuItem` MenuItem
* `browserWindow` [BrowserWindow](browser-window.md) | undefined - This will not be defined if no window is open.
* `event` [KeyboardEvent](structures/keyboard-event.md)
* `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, 'showSubstitutions', 'toggleSmartQuotes', 'toggleSmartDashes', 'toggleTextReplacement', `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
* `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
`click` property will be ignored. See [roles](#roles).
* `type` string (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or
`radio`.
@@ -100,10 +100,6 @@ The following additional roles are available on _macOS_:
* `hide` - Map to the `hide` action.
* `hideOthers` - Map to the `hideOtherApplications` action.
* `unhide` - Map to the `unhideAllApplications` action.
* `showSubstitutions` - Map to the `orderFrontSubstitutionsPanel` action.
* `toggleSmartQuotes` - Map to the `toggleAutomaticQuoteSubstitution` action.
* `toggleSmartDashes` - Map to the `toggleAutomaticDashSubstitution` action.
* `toggleTextReplacement` - Map to the `toggleAutomaticTextReplacement` action.
* `startSpeaking` - Map to the `startSpeaking` action.
* `stopSpeaking` - Map to the `stopSpeaking` action.
* `front` - Map to the `arrangeInFront` action.
@@ -124,7 +120,7 @@ When specifying a `role` on macOS, `label` and `accelerator` are the only
options that will affect the menu item. All other options will be ignored.
Lowercase `role`, e.g. `toggledevtools`, is still supported.
**Note:** The `enabled` and `visibility` properties are not available for top-level menu items in the tray on macOS.
**Nota Bene:** The `enabled` and `visibility` properties are not available for top-level menu items in the tray on macOS.
### Instance Properties

View File

@@ -39,7 +39,7 @@ Returns:
* `messageDetails` Object - Information about the console message
* `message` string - The actual console message
* `versionId` number - The version ID of the service worker that sent the log message
* `source` string - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
* `source` string - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `app-cache`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
* `level` number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `sourceUrl` string - The URL the message came from
* `lineNumber` number - The line number of the source that triggered this console message

View File

@@ -903,10 +903,8 @@ setting with the current OS locale. This setting is persisted across restarts.
By default Electron will download hunspell dictionaries from the Chromium CDN. If you want to override this
behavior you can use this API to point the dictionary downloader at your own hosted version of the hunspell
dictionaries. We publish a `hunspell_dictionaries.zip` file with each release which contains the files you need
to host here.
The file server must be **case insensitive**. If you cannot do this, you must upload each file twice: once with
the case it has in the ZIP file and once with the filename as all lowercase.
to host here, the file server must be **case insensitive** you must upload each file twice, once with the case it
has in the ZIP file and once with the filename as all lower case.
If the files present in `hunspell_dictionaries.zip` are available at `https://example.com/dictionaries/language-code.bdic`
then you should call this api with `ses.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')`. Please

View File

@@ -1,7 +0,0 @@
# PaymentDiscount Object
* `identifier` string - A string used to uniquely identify a discount offer for a product.
* `keyIdentifier` string - A string that identifies the key used to generate the signature.
* `nonce` string - A universally unique ID (UUID) value that you define.
* `signature` string - A UTF-8 string representing the properties of a specific discount offer, cryptographically signed.
* `timestamp` number - The date and time of the signature's creation in milliseconds, formatted in Unix epoch time.

View File

@@ -7,3 +7,17 @@
the `enctype` attribute of the submitted HTML form.
* `boundary` string (optional) - The boundary used to separate multiple parts of
the message. Only valid when `contentType` is `multipart/form-data`.
Note that keys starting with `--` are not currently supported. For example, this will errantly submit as `multipart/form-data` when `nativeWindowOpen` is set to `false` in webPreferences:
```html
<form
target="_blank"
method="POST"
enctype="application/x-www-form-urlencoded"
action="https://postman-echo.com/post"
>
<input type="text" name="--theKey">
<input type="submit">
</form>
```

View File

@@ -1,9 +0,0 @@
# ProductDiscount Object
* `identifier` string - A string used to uniquely identify a discount offer for a product.
* `type` number - The type of discount offer.
* `price` number - The discount price of the product in the local currency.
* `priceLocale` string - The locale used to format the discount price of the product.
* `paymentMode` string - The payment mode for this product discount. Can be `payAsYouGo`, `payUpFront`, or `freeTrial`.
* `numberOfPeriods` number - An integer that indicates the number of periods the product discount is available.
* `subscriptionPeriod` [ProductSubscriptionPeriod](product-subscription-period.md) (optional) - An object that defines the period for the product discount.

View File

@@ -1,4 +0,0 @@
# ProductSubscriptionPeriod Object
* `numberOfUnits` number - The number of units per subscription period.
* `unit` string - The increment of time that a subscription period is specified in. Can be `day`, `week`, `month`, `year`.

View File

@@ -8,11 +8,4 @@
* `price` number - The cost of the product in the local currency.
* `formattedPrice` string - The locale formatted price of the product.
* `currencyCode` string - 3 character code presenting a product's currency based on the ISO 4217 standard.
* `introductoryPrice` [ProductDiscount](product-discount.md) (optional) - The object containing introductory price information for the product.
available for the product.
* `discounts` [ProductDiscount](product-discount.md)[] - An array of discount offers
* `subscriptionGroupIdentifier` string - The identifier of the subscription group to which the subscription belongs.
* `subscriptionPeriod` [ProductSubscriptionPeriod](product-subscription-period.md) (optional) - The period details for products that are subscriptions.
* `isDownloadable` boolean - A boolean value that indicates whether the App Store has downloadable content for this product. `true` if at least one file has been associated with the product.
* `downloadContentVersion` string - A string that identifies the version of the content.
* `downloadContentLengths` number[] - The total size of the content, in bytes.

View File

@@ -9,5 +9,3 @@
* `payment` Object
* `productIdentifier` string - The identifier of the purchased product.
* `quantity` Integer - The quantity purchased.
* `applicationUsername` string - An opaque identifier for the users account on your system.
* `paymentDiscount` [PaymentDiscount](payment-discount.md) (optional) - The details of the discount offer to apply to the payment.

View File

@@ -2,3 +2,4 @@
* `code` string
* `url` string (optional)
* `startLine` Integer (optional) - Default is 1.

View File

@@ -290,7 +290,7 @@ Returns:
* `frameProcessId` Integer
* `frameRoutingId` Integer
Emitted when a server side redirect occurs during navigation. For example a 302
Emitted as a server side redirect occurs during navigation. For example a 302
redirect.
This event will be emitted after `did-start-navigation` and always before the
@@ -508,23 +508,6 @@ Returns:
Emitted when the user is requesting to change the zoom level using the mouse wheel.
#### Event: 'blur'
Emitted when the `WebContents` loses focus.
#### Event: 'focus'
Emitted when the `WebContents` gains focus.
Note that on macOS, having focus means the `WebContents` is the first responder
of window, so switching focus between windows would not trigger the `focus` and
`blur` events of `WebContents`, as the first responder of each window is not
changed.
The `focus` and `blur` events of `WebContents` should only be used to detect
focus change between different `WebContents` and `BrowserView` in the same
window.
#### Event: 'devtools-opened'
Emitted when DevTools is opened.
@@ -753,8 +736,6 @@ first available device will be selected. `callback` should be called with
`deviceId` to be selected, passing empty string to `callback` will
cancel the request.
If no event listener is added for this event, all bluetooth requests will be cancelled.
```javascript
const { app, BrowserWindow } = require('electron')
@@ -1101,7 +1082,7 @@ Returns `string` - The user agent for this web page.
* `css` string
* `options` Object (optional)
* `cssOrigin` string (optional) - Can be either 'user' or 'author'. Sets the [cascade origin](https://www.w3.org/TR/css3-cascade/#cascade-origin) of the inserted stylesheet. Default is 'author'.
* `cssOrigin` string (optional) - Can be either 'user' or 'author'; Specifying 'user' enables you to prevent websites from overriding the CSS you insert. Default is 'author'.
Returns `Promise<string>` - A promise that resolves with a key for the inserted CSS that can later be used to remove the CSS via `contents.removeInsertedCSS(key)`.
@@ -1628,7 +1609,7 @@ app.whenReady().then(() => {
* `options` Object (optional)
* `mode` string - Opens the devtools with specified dock state, can be
`left`, `right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
`right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
In `undocked` mode it's possible to dock back. In `detach` mode it's not.
* `activate` boolean (optional) - Whether to bring the opened devtools window
to the foreground. The default is `true`.
@@ -1856,7 +1837,7 @@ the cursor when dragging.
#### `contents.savePage(fullPath, saveType)`
* `fullPath` string - The absolute file path.
* `fullPath` string - The full file path.
* `saveType` string - Specify the save type.
* `HTMLOnly` - Save only the HTML of the page.
* `HTMLComplete` - Save complete-html page.

View File

@@ -5,8 +5,8 @@
Process: [Renderer](../glossary.md#renderer-process)
`webFrame` export of the Electron module is an instance of the `WebFrame`
class representing the current frame. Sub-frames can be retrieved by
certain properties and methods (e.g. `webFrame.firstChild`).
class representing the top frame of the current `BrowserWindow`. Sub-frames can
be retrieved by certain properties and methods (e.g. `webFrame.firstChild`).
An example of zooming current page to 200%.

View File

@@ -98,7 +98,6 @@ Some examples of valid `urls`:
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
* `referrer` string
* `timestamp` Double
* `uploadData` [UploadData[]](structures/upload-data.md) (optional)
* `requestHeaders` Record<string, string>
* `callback` Function
* `beforeSendResponse` Object

View File

@@ -12,6 +12,10 @@ useful for app sub-windows that act as preference panels, or similar, as the
parent can render to the sub-window directly, as if it were a `div` in the
parent. This is the same behavior as in the browser.
When `nativeWindowOpen` is set to false, `window.open` instead results in the
creation of a [`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper
around `BrowserWindow`.
Electron pairs this native Chrome `Window` with a BrowserWindow under the hood.
You can take advantage of all the customization available when creating a
BrowserWindow in the main process by using `webContents.setWindowOpenHandler()`
@@ -30,7 +34,7 @@ because it is invoked in the main process.
* `frameName` string (optional)
* `features` string (optional)
Returns [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) | null
Returns [`BrowserWindowProxy`](browser-window-proxy.md) | [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window)
`features` is a comma-separated key-value list, following the standard format of
the browser. Electron will parse `BrowserWindowConstructorOptions` out of this
@@ -60,9 +64,6 @@ window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIn
`features` will be passed to any registered `webContents`'s
`did-create-window` event handler in the `options` argument.
* `frameName` follows the specification of `windowName` located in the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters).
* When opening `about:blank`, the child window's `WebPreferences` will be copied
from the parent window, and there is no way to override it because Chromium
skips browser side navigation in this case.
To customize or cancel the creation of the window, you can optionally set an
override handler with `webContents.setWindowOpenHandler()` from the main
@@ -104,3 +105,33 @@ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
const childWindow = window.open('', 'modal')
childWindow.document.write('<h1>Hello</h1>')
```
### `BrowserWindowProxy` example
```javascript
// main.js
const mainWindow = new BrowserWindow({
webPreferences: { nativeWindowOpen: false }
})
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('https://github.com/')) {
return { action: 'allow' }
}
return { action: 'deny' }
})
mainWindow.webContents.on('did-create-window', (childWindow) => {
// For example...
childWindow.webContents.on('will-navigate', (e) => {
e.preventDefault()
})
})
```
```javascript
// renderer.js
const windowProxy = window.open('https://github.com/', null, 'minimizable=false')
windowProxy.postMessage('hi', '*')
```

View File

@@ -12,18 +12,6 @@ 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 (18.0)
### Removed: `nativeWindowOpen`
Prior to Electron 15, `window.open` was by default shimmed to use
`BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work
to open synchronously scriptable child windows, among other incompatibilities.
Since Electron 15, `nativeWindowOpen` has been enabled by default.
See the documentation for [window.open in Electron](api/window-open.md)
for more details.
## Planned Breaking API Changes (17.0)
### Removed: `desktopCapturer.getSources` in the renderer
@@ -57,16 +45,6 @@ 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.
### Deprecated: `nativeWindowOpen`
Prior to Electron 15, `window.open` was by default shimmed to use
`BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work
to open synchronously scriptable child windows, among other incompatibilities.
Since Electron 15, `nativeWindowOpen` has been enabled by default.
See the documentation for [window.open in Electron](api/window-open.md)
for more details.
## Planned Breaking API Changes (16.0)
### Behavior Changed: `crashReporter` implementation switched to Crashpad on Linux

View File

@@ -98,40 +98,45 @@ $ gclient sync -f
## Building
**Set the environment variable for chromium build tools**
On Linux & MacOS
```sh
$ cd src
$ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
```
On Windows:
Or on Windows (without the optional argument):
```sh
$ cd src
$ set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools
```
**To generate Testing build config of Electron:**
```sh
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"
```
**To generate Release build config of Electron:**
This will generate a build directory `out/Testing` under `src/` with
the testing build configuration. You can replace `Testing` with another name,
but it should be a subdirectory of `out`.
Also you shouldn't have to run `gn gen` again—if you want to change the
build arguments, you can run `gn args out/Testing` to bring up an editor.
To see the list of available build configuration options, run `gn args
out/Testing --list`.
**For generating Testing build config of
Electron:**
```sh
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\")"
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
```
**Note:** This will generate a `out/Testing` or `out/Release` build directory under `src/` with the testing or release build depending upon the configuration passed above. You can replace `Testing|Release` with another names, but it should be a subdirectory of `out`.
**For generating Release (aka "non-component" or "static") build config of
Electron:**
Also you shouldn't have to run `gn gen` again—if you want to change the build arguments, you can run `gn args out/Testing` to bring up an editor. To see the list of available build configuration options, run `gn args out/Testing --list`.
```sh
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\") $GN_EXTRA_ARGS"
```
**To build, run `ninja` with the `electron` target:**
Note: This will also take a while and probably heat up your lap.
Nota Bene: This will also take a while and probably heat up your lap.
For the testing configuration:
@@ -164,13 +169,13 @@ $ ./out/Testing/electron
On linux, first strip the debugging and symbol information:
```sh
$ electron/script/strip-binaries.py -d out/Release
electron/script/strip-binaries.py -d out/Release
```
To package the electron build as a distributable zip file:
```sh
$ ninja -C out/Release electron:electron_dist_zip
ninja -C out/Release electron:electron_dist_zip
```
### Cross-compiling

View File

@@ -29,17 +29,7 @@ Follow the guidelines below for building **Electron itself** on Linux, for the p
* [clang](https://clang.llvm.org/get_started.html) 3.4 or later.
* Development headers of GTK 3 and libnotify.
On Ubuntu >= 20.04, install the following libraries:
```sh
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
libnotify-dev libasound2-dev libcap-dev \
libcups2-dev libxtst-dev \
libxss1 libnss3-dev gcc-multilib g++-multilib curl \
gperf bison python3-dbusmock openjdk-8-jre
```
On Ubuntu < 20.04, install the following libraries:
On Ubuntu, install the following libraries:
```sh
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \

View File

@@ -50,8 +50,8 @@ In your `api_name.h` file:
```cpp title='api_name.h'
#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
#ifndef SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
#define SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
#include "gin/handle.h"
#include "gin/wrappable.h"

View File

@@ -43,9 +43,8 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
## Using the symbol server in Visual Studio
![Tools -> Options](../images/vs-tools-options.png)
![Symbols Settings](../images/vs-options-debugging-symbols.png)
![Tools -> Options](https://mdn.mozillademos.org/files/733/symbol-server-vc8express-menu.jpg)
![Symbols Settings](https://mdn.mozillademos.org/files/2497/2005_options.gif)
## Troubleshooting: Symbols will not load

View File

@@ -35,28 +35,6 @@ base::debug::StackTrace().Print();
This will allow you to observe call chains and identify potential issue areas.
## Breakpoint Debugging
> Note that this will increase the size of the build significantly, taking up around 50G of disk space
Write the following file to `electron/.git/info/exclude/debug.gn`
```gn
import("//electron/build/args/testing.gn")
is_debug = true
symbol_level = 2
forbid_non_component_debug_builds = false
```
Then execute:
```sh
$ gn gen out/Debug --args="import(\"//electron/.git/info/exclude/debug.gn\") $GN_EXTRA_ARGS"
$ ninja -C out/Debug electron
```
Now you can use `LLDB` for breakpoint debugging.
## Platform-Specific Debugging
<!-- TODO(@codebytere): add debugging file for Linux-->

View File

@@ -180,7 +180,7 @@ $ git push origin my-branch
### Step 9: Opening the Pull Request
From within GitHub, opening a new pull request will present you with a template
that should be filled out. It can be found [here](https://github.com/electron/electron/blob/main/.github/PULL_REQUEST_TEMPLATE.md).
that should be filled out. It can be found [here](../../.github/PULL_REQUEST_TEMPLATE.md).
If you do not adequately complete this template, your PR may be delayed in being merged as maintainers
seek more information or clarify ambiguities.

View File

@@ -22,7 +22,7 @@ you error would be caught at commit time.
## Unit Tests
If you are not using [build-tools](https://github.com/electron/build-tools),
ensure that the name you have configured for your
ensure that that name you have configured for your
local build of Electron is one of `Testing`, `Release`, `Default`, or
you have set `process.env.ELECTRON_OUT_DIR`. Without these set, Electron will fail
to perform some pre-testing steps.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -56,7 +56,7 @@ will then be your distribution to deliver to users.
### With an app source code archive
Instead of shipping your app by copying all of its source files, you can
Instead of from shipping your app by copying all of its source files, you can
package your app into an [asar] archive to improve the performance of reading
files on platforms like Windows, if you are not already using a bundler such
as Parcel or Webpack.

View File

@@ -58,6 +58,8 @@ To run your tests:
$ npx wdio run wdio.conf.js
```
[chrome-driver]: https://sites.google.com/chromium.org/driver/
### With Selenium
[Selenium](https://www.selenium.dev/) is a web automation framework that
@@ -114,142 +116,6 @@ driver.wait(() => {
driver.quit()
```
## Using Playwright
[Microsoft Playwright](https://playwright.dev) is an end-to-end testing framework built
using browser-specific remote debugging protocols, similar to the [Puppeteer] headless
Node.js API but geared towards end-to-end testing. Playwright has experimental Electron
support via Electron's support for the [Chrome DevTools Protocol] (CDP).
### Install dependencies
You can install Playwright through your preferred Node.js package manager. The Playwright team
recommends using the `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` environment variable to avoid
unnecessary browser downloads when testing an Electron app.
```sh npm2yarn
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --save-dev playwright
```
Playwright also comes with its own test runner, Playwright Test, which is built for end-to-end
testing. You can also install it as a dev dependency in your project:
```sh npm2yarn
npm install --save-dev @playwright/test
```
:::caution Dependencies
This tutorial was written `playwright@1.16.3` and `@playwright/test@1.16.3`. Check out
[Playwright's releases][playwright-releases] page to learn about
changes that might affect the code below.
:::
:::info Using third-party test runners
If you're interested in using an alternative test runner (e.g. Jest or Mocha), check out
Playwright's [Third-Party Test Runner][playwright-test-runners] guide.
:::
### Write your tests
Playwright launches your app in development mode through the `_electron.launch` API.
To point this API to your Electron app, you can pass the path to your main process
entry point (here, it is `main.js`).
```js {5}
const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test')
test('launch app', async () => {
const electronApp = await electron.launch({ args: ['main.js'] })
// close app
await electronApp.close()
})
```
After that, you will access to an instance of Playwright's `ElectronApp` class. This
is a powerful class that has access to main process modules for example:
```js {6-11}
const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test')
test('get isPackaged', async () => {
const electronApp = await electron.launch({ args: ['main.js'] })
const isPackaged = await electronApp.evaluate(async ({ app }) => {
// This runs in Electron's main process, parameter here is always
// the result of the require('electron') in the main app script.
return app.isPackaged
})
console.log(isPackaged) // false (because we're in development mode)
// close app
await electronApp.close()
})
```
It can also create individual [Page][playwright-page] objects from Electron BrowserWindow instances.
For example, to grab the first BrowserWindow and save a screenshot:
```js {6-7}
const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test')
test('save screenshot', async () => {
const electronApp = await electron.launch({ args: ['main.js'] })
const window = await electronApp.firstWindow()
await window.screenshot({ path: 'intro.png' })
// close app
await electronApp.close()
})
```
Putting all this together using the PlayWright Test runner, let's create a `example.spec.js`
test file with a single test and assertion:
```js title='example.spec.js'
const { _electron: electron } = require('playwright')
const { test, expect } = require('@playwright/test')
test('example test', async () => {
const electronApp = await electron.launch({ args: ['.'] })
const isPackaged = await electronApp.evaluate(async ({ app }) => {
// This runs in Electron's main process, parameter here is always
// the result of the require('electron') in the main app script.
return app.isPackaged;
});
expect(isPackaged).toBe(false);
// Wait for the first BrowserWindow to open
// and return its Page object
const window = await electronApp.firstWindow()
await window.screenshot({ path: 'intro.png' })
// close app
await electronApp.close()
});
```
Then, run Playwright Test using `npx playwright test`. You should see the test pass in your
console, and have an `intro.png` screenshot on your filesystem.
```console
☁ $ npx playwright test
Running 1 test using 1 worker
✓ example.spec.js:4:1 example test (1s)
```
:::info
Playwright Test will automatically run any files matching the `.*(test|spec)\.(js|ts|mjs)` regex.
You can customize this match in the [Playwright Test configuration options][playwright-test-config].
:::
:::tip Further reading
Check out Playwright's documentation for the full [Electron][playwright-electron]
and [ElectronApplication][playwright-electronapplication] class APIs.
:::
## Using a custom test driver
It's also possible to write your own custom driver using Node.js' built-in IPC-over-STDIO.
@@ -397,13 +263,3 @@ test.after.always('cleanup', async t => {
await app.stop()
})
```
[chrome-driver]: https://sites.google.com/chromium.org/driver/
[Puppeteer]: https://github.com/puppeteer/puppeteer
[playwright-electron]: https://playwright.dev/docs/api/class-electron/
[playwright-electronapplication]: https://playwright.dev/docs/api/class-electronapplication
[playwright-page]: https://playwright.dev/docs/api/class-page
[playwright-releases]: https://github.com/microsoft/playwright/releases
[playwright-test-config]: https://playwright.dev/docs/api/class-testconfig#test-config-test-match
[playwright-test-runners]: https://playwright.dev/docs/test-runners/
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/

View File

@@ -26,5 +26,4 @@ Special notes:
| 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-Oct-20 | 2021-Nov-16 | M96 | v16.9 |
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | v16.13 |
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | M100 | TBD |
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | TBD |

View File

@@ -73,7 +73,7 @@ url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
For instance, to use the China CDN mirror:
```shell
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
ELECTRON_MIRROR="https://cdn.npm.taobao.org/dist/electron/"
```
By default, `ELECTRON_CUSTOM_DIR` is set to `v$VERSION`. To change the format,
@@ -83,15 +83,15 @@ resolves to `version-5.0.0`, `{{ version }}` resolves to `5.0.0`, and
use the China non-CDN mirror:
```shell
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"
ELECTRON_CUSTOM_DIR="{{ version }}"
```
The above configuration will download from URLs such as
`https://npmmirror.com/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.
`https://npm.taobao.org/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.
If your mirror serves artifacts with different checksums to the official
Electron release you may have to set `electron_use_remote_checksums=1` to
Electron release you may have to set `ELECTRON_USE_REMOTE_CHECKSUMS=1` to
force Electron to use the remote `SHASUMS256.txt` file to verify the checksum
instead of the embedded checksums.

View File

@@ -56,4 +56,4 @@ problem. If not, feel free to fill out our bug report template and submit a new
[comic]: https://www.google.com/googlebooks/chrome/
[fiddle]: https://electronjs.org/fiddle
[issue-tracker]: https://github.com/electron/electron/issues
[discord]: https://discord.gg/electronjs
[discord]: https://discord.gg/electron

View File

@@ -146,7 +146,7 @@ desktop environment that follows [Desktop Notifications
Specification][notification-spec], including Cinnamon, Enlightenment, Unity,
GNOME, KDE.
[notification-spec]: https://developer-old.gnome.org/notification-spec/
[notification-spec]: https://developer.gnome.org/notification-spec/
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
[set-app-user-model-id]: ../api/app.md#appsetappusermodelidid-windows
[squirrel-events]: https://github.com/electron/windows-installer/blob/master/README.md#handling-squirrel-events

View File

@@ -1,11 +1,3 @@
---
title: Performance
description: A set of guidelines for building performant Electron apps
slug: performance
hide_title: true
toc_max_heading_level: 3
---
# Performance
Developers frequently ask about strategies to optimize the performance of
@@ -57,7 +49,7 @@ at once, consider the [Chrome Tracing](https://www.chromium.org/developers/how-t
* [Get Started With Analyzing Runtime Performance][chrome-devtools-tutorial]
* [Talk: "Visual Studio Code - The First Second"][vscode-first-second]
## Checklist: Performance recommendations
## Checklist
Chances are that your app could be a little leaner, faster, and generally less
resource-hungry if you attempt these steps.
@@ -70,7 +62,7 @@ resource-hungry if you attempt these steps.
6. [Unnecessary or blocking network requests](#6-unnecessary-or-blocking-network-requests)
7. [Bundle your code](#7-bundle-your-code)
### 1. Carelessly including modules
## 1) Carelessly including modules
Before adding a Node.js module to your application, examine said module. How
many dependencies does that module include? What kind of resources does
@@ -78,7 +70,7 @@ it need to simply be called in a `require()` statement? You might find
that the module with the most downloads on the NPM package registry or the most stars on GitHub
is not in fact the leanest or smallest one available.
#### Why?
### Why?
The reasoning behind this recommendation is best illustrated with a real-world
example. During the early days of Electron, reliable detection of network
@@ -107,7 +99,7 @@ running Linux might be bad news for your app's performance. In this particular
example, the correct solution was to use no module at all, and to instead use
connectivity checks included in later versions of Chromium.
#### How?
### How?
When considering a module, we recommend that you check:
@@ -136,7 +128,7 @@ 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
and less than 50ms.
### 2. Loading and running code too soon
## 2) Loading and running code too soon
If you have expensive setup operations, consider deferring those. Inspect all
the work being executed right after the application starts. Instead of firing
@@ -149,7 +141,7 @@ using the same strategy _and_ are using sizable modules that you do not
immediately need, apply the same strategy and defer loading to a more
opportune time.
#### Why?
### Why?
Loading modules is a surprisingly expensive operation, especially on Windows.
When your app starts, it should not make users wait for operations that are
@@ -165,14 +157,14 @@ immediately display the file to you without any code highlighting, prioritizing
your ability to interact with the text. Once it has done that work, it will
move on to code highlighting.
#### How?
### How?
Let's consider an example and assume that your application is parsing files
in the fictitious `.foo` format. In order to do that, it relies on the
equally fictitious `foo-parser` module. In traditional Node.js development,
you might write code that eagerly loads dependencies:
```js title='parser.js'
```js
const fs = require('fs')
const fooParser = require('foo-parser')
@@ -195,7 +187,7 @@ In the above example, we're doing a lot of work that's being executed as soon
as the file is loaded. Do we need to get parsed files right away? Could we
do this work a little later, when `getParsedFiles()` is actually called?
```js title='parser.js'
```js
// "fs" is likely already being loaded, so the `require()` call is cheap
const fs = require('fs')
@@ -231,7 +223,7 @@ module.exports = { parser }
In short, allocate resources "just in time" rather than allocating them all
when your app starts.
### 3. Blocking the main process
## 3) Blocking the main process
Electron's main process (sometimes called "browser process") is special: It is
the parent process to all your app's other processes and the primary process
@@ -243,7 +235,7 @@ Under no circumstances should you block this process and the UI thread with
long-running operations. Blocking the UI thread means that your entire app
will freeze until the main process is ready to continue processing.
#### Why?
### Why?
The main process and its UI thread are essentially the control tower for major
operations inside your app. When the operating system tells your app about a
@@ -254,31 +246,31 @@ the GPU process about that once again going through the main process.
Electron and Chromium are careful to put heavy disk I/O and CPU-bound operations
onto new threads to avoid blocking the UI thread. You should do the same.
#### How?
### How?
Electron's powerful multi-process architecture stands ready to assist you with
your long-running tasks, but also includes a small number of performance traps.
1. For long running CPU-heavy tasks, make use of
1) For long running CPU-heavy tasks, make use of
[worker threads][worker-threads], consider moving them to the BrowserWindow, or
(as a last resort) spawn a dedicated process.
2. Avoid using the synchronous IPC and the `@electron/remote` module as much
as possible. While there are legitimate use cases, it is far too easy to
unknowingly block the UI thread.
2) Avoid using the synchronous IPC and the `remote` module as much as possible.
While there are legitimate use cases, it is far too easy to unknowingly block
the UI thread using the `remote` module.
3. Avoid using blocking I/O operations in the main process. In short, whenever
3) Avoid using blocking I/O operations in the main process. In short, whenever
core Node.js modules (like `fs` or `child_process`) offer a synchronous or an
asynchronous version, you should prefer the asynchronous and non-blocking
variant.
### 4. Blocking the renderer process
## 4) Blocking the renderer process
Since Electron ships with a current version of Chrome, you can make use of the
latest and greatest features the Web Platform offers to defer or offload heavy
operations in a way that keeps your app smooth and responsive.
#### Why?
### Why?
Your app probably has a lot of JavaScript to run in the renderer process. The
trick is to execute operations as quickly as possible without taking away
@@ -288,7 +280,7 @@ at 60fps.
Orchestrating the flow of operations in your renderer's code is
particularly useful if users complain about your app sometimes "stuttering".
#### How?
### How?
Generally speaking, all advice for building performant web apps for modern
browsers apply to Electron's renderers, too. The two primary tools at your
@@ -308,14 +300,14 @@ some caveats to consider  consult Electron's
for any operation that requires a lot of CPU power for an extended period of
time.
### 5. Unnecessary polyfills
## 5) Unnecessary polyfills
One of Electron's great benefits is that you know exactly which engine will
parse your JavaScript, HTML, and CSS. If you're re-purposing code that was
written for the web at large, make sure to not polyfill features included in
Electron.
#### Why?
### Why?
When building a web application for today's Internet, the oldest environments
dictate what features you can and cannot use. Even though Electron supports
@@ -331,7 +323,7 @@ It is rare for a JavaScript-based polyfill to be faster than the equivalent
native feature in Electron. Do not slow down your Electron app by shipping your
own version of standard web platform features.
#### How?
### How?
Operate under the assumption that polyfills in current versions of Electron
are unnecessary. If you have doubts, check [caniuse.com](https://caniuse.com/)
@@ -346,12 +338,12 @@ If you're using a transpiler/compiler like TypeScript, examine its configuration
and ensure that you're targeting the latest ECMAScript version supported by
Electron.
### 6. Unnecessary or blocking network requests
## 6) Unnecessary or blocking network requests
Avoid fetching rarely changing resources from the internet if they could easily
be bundled with your application.
#### Why?
### Why?
Many users of Electron start with an entirely web-based app that they're
turning into a desktop application. As web developers, we are used to loading
@@ -368,7 +360,7 @@ will take care of the rest.
When building an Electron app, your users are better served if you download
the fonts and include them in your app's bundle.
#### How?
### How?
In an ideal world, your application wouldn't need the network to operate at
all. To get there, you must understand what resources your app is downloading
@@ -395,21 +387,21 @@ without shipping an application update is a powerful strategy. For advanced
control over how resources are being loaded, consider investing in
[Service Workers][service-workers].
### 7. Bundle your code
## 7) Bundle your code
As already pointed out in
"[Loading and running code too soon](#2-loading-and-running-code-too-soon)",
calling `require()` is an expensive operation. If you are able to do so,
bundle your application's code into a single file.
#### Why?
### Why?
Modern JavaScript development usually involves many files and modules. While
that's perfectly fine for developing with Electron, we heavily recommend that
you bundle all your code into one single file to ensure that the overhead
included in calling `require()` is only paid once when your application loads.
#### How?
### How?
There are numerous JavaScript bundlers out there and we know better than to
anger the community by recommending one tool over another. We do however

View File

@@ -119,7 +119,7 @@ of your project.
Before we can create a window for our application, we need to create the content that
will be loaded into it. In Electron, each window displays web contents that can be loaded
from either a local HTML file or a remote URL.
from either from a local HTML file or a remote URL.
For this tutorial, you will be doing the former. Create an `index.html` file in the root
folder of your project:
@@ -463,46 +463,46 @@ The fastest way to distribute your newly created app is using
1. Add Electron Forge as a development dependency of your app, and use its `import` command to set up
Forge's scaffolding:
```sh npm2yarn
npm install --save-dev @electron-forge/cli
npx electron-forge import
```sh npm2yarn
npm install --save-dev @electron-forge/cli
npx electron-forge import
✔ Checking your system
✔ Initializing Git Repository
✔ Writing modified package.json file
✔ Installing dependencies
✔ Writing modified package.json file
✔ Fixing .gitignore
✔ Checking your system
✔ Initializing Git Repository
✔ Writing modified package.json file
✔ Installing dependencies
✔ Writing modified package.json file
✔ Fixing .gitignore
We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
Thanks for using "electron-forge"!!!
```
Thanks for using "electron-forge"!!!
```
1. Create a distributable using Forge's `make` command:
```sh npm2yarn
npm run make
```sh npm2yarn
npm run make
> my-electron-app@1.0.0 make /my-electron-app
> electron-forge make
> my-electron-app@1.0.0 make /my-electron-app
> electron-forge make
✔ Checking your system
✔ Resolving Forge Config
We need to package your application before we can make it
✔ Preparing to Package Application for arch: x64
✔ Preparing native dependencies
✔ Packaging Application
Making for the following targets: zip
✔ Making for target: zip - On platform: darwin - For arch: x64
```
✔ Checking your system
✔ Resolving Forge Config
We need to package your application before we can make it
✔ Preparing to Package Application for arch: x64
✔ Preparing native dependencies
✔ Packaging Application
Making for the following targets: zip
✔ Making for target: zip - On platform: darwin - For arch: x64
```
Electron Forge creates the `out` folder where your package will be located:
Electron Forge creates the `out` folder where your package will be located:
```plain
// Example for macOS
out/
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
├── ...
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
```
```plain
// Example for macOS
out/
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
├── ...
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
```

View File

@@ -1,24 +1,6 @@
---
title: Security
description: A set of guidelines for building secure Electron apps
slug: security
hide_title: true
toc_max_heading_level: 3
---
# Security
# Security, Native Capabilities, and Your Responsibility
:::info Reporting security issues
For information on how to properly disclose an Electron vulnerability,
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md).
For upstream Chromium vulnerabilities: Electron keeps up to date with alternating
Chromium releases. For more information, see the
[Electron Release Timelines](../tutorial/electron-timelines.md) document.
:::
## Preface
As web developers, we usually enjoy the strong security net of the browser —
As web developers, we usually enjoy the strong security net of the browser -
the risks associated with the code we write are relatively small. Our websites
are granted limited powers in a sandbox, and we trust that our users enjoy a
browser built by a large team of engineers that is able to quickly respond to
@@ -35,12 +17,20 @@ With that in mind, be aware that displaying arbitrary content from untrusted
sources poses a severe security risk that Electron is not intended to handle.
In fact, the most popular Electron apps (Atom, Slack, Visual Studio Code, etc)
display primarily local content (or trusted, secure remote content without Node
integration) if your application executes code from an online source, it is
integration) if your application executes code from an online source, it is
your responsibility to ensure that the code is not malicious.
## General guidelines
## Reporting Security Issues
### Security is everyone's responsibility
For information on how to properly disclose an Electron vulnerability,
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md)
## Chromium Security Issues and Upgrades
Electron keeps up to date with alternating Chromium releases. For more information,
see the [Electron Release Cadence blog post](https://electronjs.org/blog/12-week-cadence).
## Security Is Everyone's Responsibility
It is important to remember that the security of your Electron application is
the result of the overall security of the framework foundation
@@ -66,7 +56,7 @@ is your own code. Common web vulnerabilities, such as Cross-Site Scripting (XSS)
have a higher security impact on Electron applications hence it is highly recommended
to adopt secure software development best practices and perform security testing.
### Isolation for untrusted content
## Isolation For Untrusted Content
A security issue exists whenever you receive code from an untrusted source (e.g.
a remote server) and execute it locally. As an example, consider a remote
@@ -75,74 +65,72 @@ an attacker somehow manages to change said content (either by attacking the
source directly, or by sitting between your app and the actual destination), they
will be able to execute native code on the user's machine.
:::warning
Under no circumstances should you load and execute remote code with
> :warning: Under no circumstances should you load and execute remote code with
Node.js integration enabled. Instead, use only local files (packaged together
with your application) to execute Node.js code. To display remote content, use
the [`<webview>`][webview-tag] tag or [`BrowserView`][browser-view], make sure
to disable the `nodeIntegration` and enable `contextIsolation`.
:::
:::info Electron security warnings
Security warnings and recommendations are printed to the developer console.
They only show up when the binary's name is Electron, indicating that a developer
is currently looking at the console.
## Electron Security Warnings
From Electron 2.0 on, developers will see warnings and recommendations printed
to the developer console. They only show up when the binary's name is Electron,
indicating that a developer is currently looking at the console.
You can force-enable or force-disable these warnings by setting
`ELECTRON_ENABLE_SECURITY_WARNINGS` or `ELECTRON_DISABLE_SECURITY_WARNINGS` on
either `process.env` or the `window` object.
:::
## Checklist: Security recommendations
## Checklist: Security Recommendations
You should at least follow these steps to improve the security of your application:
1. [Only load secure content](#1-only-load-secure-content)
2. [Disable the Node.js integration in all renderers that display remote content](#2-do-not-enable-nodejs-integration-for-remote-content)
3. [Enable context isolation in all renderers that display remote content](#3-enable-context-isolation-for-remote-content)
4. [Enable process sandboxing](#4-enable-process-sandboxing)
4. [Enable sandboxing](#4-enable-sandboxing)
5. [Use `ses.setPermissionRequestHandler()` in all sessions that load remote content](#5-handle-session-permission-requests-from-remote-content)
6. [Do not disable `webSecurity`](#6-do-not-disable-websecurity)
7. [Define a `Content-Security-Policy`](#7-define-a-content-security-policy) and use restrictive rules (i.e. `script-src 'self'`)
8. [Do not enable `allowRunningInsecureContent`](#8-do-not-enable-allowrunninginsecurecontent)
8. [Do not set `allowRunningInsecureContent` to `true`](#8-do-not-set-allowrunninginsecurecontent-to-true)
9. [Do not enable experimental features](#9-do-not-enable-experimental-features)
10. [Do not use `enableBlinkFeatures`](#10-do-not-use-enableblinkfeatures)
11. [`<webview>`: Do not use `allowpopups`](#11-do-not-use-allowpopups-for-webviews)
11. [`<webview>`: Do not use `allowpopups`](#11-do-not-use-allowpopups)
12. [`<webview>`: Verify options and params](#12-verify-webview-options-before-creation)
13. [Disable or limit navigation](#13-disable-or-limit-navigation)
14. [Disable or limit creation of new windows](#14-disable-or-limit-creation-of-new-windows)
15. [Do not use `shell.openExternal` with untrusted content](#15-do-not-use-shellopenexternal-with-untrusted-content)
15. [Do not use `openExternal` with untrusted content](#15-do-not-use-openexternal-with-untrusted-content)
16. [Use a current version of Electron](#16-use-a-current-version-of-electron)
To automate the detection of misconfigurations and insecure patterns, it is
possible to use
[Electronegativity](https://github.com/doyensec/electronegativity). For
[electronegativity](https://github.com/doyensec/electronegativity). For
additional details on potential weaknesses and implementation bugs when
developing applications using Electron, please refer to this [guide for
developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf).
developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf)
### 1. Only load secure content
## 1) Only Load Secure Content
Any resources not included with your application should be loaded using a
secure protocol like `HTTPS`. In other words, do not use insecure protocols
like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over
`FTP`, and so on.
#### Why?
### Why?
`HTTPS` has three main benefits:
1. It authenticates the remote server, ensuring your app connects to the correct
1) It authenticates the remote server, ensuring your app connects to the correct
host instead of an impersonator.
1. It ensures data integrity, asserting that the data was not modified while in
2) It ensures data integrity, asserting that the data was not modified while in
transit between your application and the host.
1. It encrypts the traffic between your user and the destination host, making it
3) It encrypts the traffic between your user and the destination host, making it
more difficult to eavesdrop on the information sent between your app and
the host.
#### How?
### How?
```js title='main.js (Main Process)'
```js
// Bad
browserWindow.loadURL('http://example.com')
@@ -150,7 +138,7 @@ browserWindow.loadURL('http://example.com')
browserWindow.loadURL('https://example.com')
```
```html title='index.html (Renderer Process)'
```html
<!-- Bad -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">
@@ -160,11 +148,9 @@ browserWindow.loadURL('https://example.com')
<link rel="stylesheet" href="https://example.com/style.css">
```
### 2. Do not enable Node.js integration for remote content
## 2) Do not enable Node.js Integration for Remote Content
:::info
This recommendation is the default behavior in Electron since 5.0.0.
:::
_This recommendation is the default behavior in Electron since 5.0.0._
It is paramount that you do not enable Node.js integration in any renderer
([`BrowserWindow`][browser-window], [`BrowserView`][browser-view], or
@@ -177,7 +163,7 @@ After this, you can grant additional permissions for specific hosts. For example
if you are opening a BrowserWindow pointed at `https://example.com/`, you can
give that website exactly the abilities it needs, but no more.
#### Why?
### Why?
A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump
out of the renderer process and execute code on the user's computer.
@@ -186,13 +172,12 @@ power is usually limited to messing with the website that they are executed on.
Disabling Node.js integration helps prevent an XSS from being escalated into a
so-called "Remote Code Execution" (RCE) attack.
#### How?
### How?
```js title='main.js (Main Process)'
```js
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
}
@@ -201,7 +186,7 @@ const mainWindow = new BrowserWindow({
mainWindow.loadURL('https://example.com')
```
```js title='main.js (Main Process)'
```js
// Good
const mainWindow = new BrowserWindow({
webPreferences: {
@@ -212,7 +197,7 @@ const mainWindow = new BrowserWindow({
mainWindow.loadURL('https://example.com')
```
```html title='index.html (Renderer Process)'
```html
<!-- Bad -->
<webview nodeIntegration src="page.html"></webview>
@@ -223,13 +208,21 @@ mainWindow.loadURL('https://example.com')
When disabling Node.js integration, you can still expose APIs to your website that
do consume Node.js modules or features. Preload scripts continue to have access
to `require` and other Node.js features, allowing developers to expose a custom
API to remotely loaded content via the [contextBridge API](../api/context-bridge.md).
API to remotely loaded content.
### 3. Enable Context Isolation for remote content
In the following example preload script, the later loaded website will have
access to a `window.readConfig()` method, but no Node.js features.
:::info
This recommendation is the default behavior in Electron since 12.0.0.
:::
```js
const { readFileSync } = require('fs')
window.readConfig = () => {
const data = readFileSync('./config.json')
return data
}
```
## 3) Enable Context Isolation for Remote Content
Context isolation is an Electron feature that allows developers to run code
in preload scripts and in Electron APIs in a dedicated JavaScript context. In
@@ -242,42 +235,48 @@ to enable this behavior.
Even when `nodeIntegration: false` is used, to truly enforce strong isolation
and prevent the use of Node primitives `contextIsolation` **must** also be used.
:::info
### Why & How?
For more information on what `contextIsolation` is and how to enable it please
see our dedicated [Context Isolation](context-isolation.md) document.
:::info
### 4. Enable process sandboxing
## 4) Enable Sandboxing
[Sandboxing](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md)
is a Chromium feature that uses the operating system to
[Sandboxing](sandbox.md) is a Chromium feature that uses the operating system to
significantly limit what renderer processes have access to. You should enable
the sandbox in all renderers. Loading, reading or processing any untrusted
content in an unsandboxed process, including the main process, is not advised.
:::info
For more information on what `contextIsolation` is and how to enable it please
see our dedicated [Process Sandboxing](sandbox.md) document.
:::info
### How?
### 5. Handle session permission requests from remote content
When creating a window, pass the `sandbox: true` option in `webPreferences`:
You may have seen permission requests while using Chrome: they pop up whenever
```js
const win = new BrowserWindow({
webPreferences: {
sandbox: true
}
})
```
## 5) Handle Session Permission Requests From Remote Content
You may have seen permission requests while using Chrome: They pop up whenever
the website attempts to use a feature that the user has to manually approve (
like notifications).
The API is based on the [Chromium permissions API](https://developer.chrome.com/extensions/permissions)
and implements the same types of permissions.
#### Why?
### Why?
By default, Electron will automatically approve all permission requests unless
the developer has manually configured a custom handler. While a solid default,
security-conscious developers might want to assume the very opposite.
#### How?
### How?
```js title='main.js (Main Process)'
```js
const { session } = require('electron')
session
@@ -298,11 +297,9 @@ session
})
```
### 6. Do not disable `webSecurity`
## 6) Do Not Disable WebSecurity
:::info
This recommendation is Electron's default.
:::
_Recommendation is Electron's default_
You may have already guessed that disabling the `webSecurity` property on a
renderer process ([`BrowserWindow`][browser-window],
@@ -311,15 +308,15 @@ security features.
Do not disable `webSecurity` in production applications.
#### Why?
### Why?
Disabling `webSecurity` will disable the same-origin policy and set
`allowRunningInsecureContent` property to `true`. In other words, it allows
the execution of insecure code from different domains.
#### How?
### How?
```js title='main.js (Main Process)'
```js
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
@@ -328,12 +325,12 @@ const mainWindow = new BrowserWindow({
})
```
```js title='main.js (Main Process)'
```js
// Good
const mainWindow = new BrowserWindow()
```
```html title='index.html (Renderer Process)'
```html
<!-- Bad -->
<webview disablewebsecurity src="page.html"></webview>
@@ -341,13 +338,13 @@ const mainWindow = new BrowserWindow()
<webview src="page.html"></webview>
```
### 7. Define a Content Security Policy
## 7) Define a Content Security Policy
A Content Security Policy (CSP) is an additional layer of protection against
cross-site-scripting attacks and data injection attacks. We recommend that they
be enabled by any website you load inside Electron.
#### Why?
### Why?
CSP allows the server serving content to restrict and control the resources
Electron can load for that given web page. `https://example.com` should
@@ -355,8 +352,6 @@ be allowed to load scripts from the origins you defined while scripts from
`https://evil.attacker.com` should not be allowed to run. Defining a CSP is an
easy way to improve your application's security.
#### How?
The following CSP will allow Electron to execute scripts from the current
website and from `apis.example.com`.
@@ -368,14 +363,14 @@ Content-Security-Policy: '*'
Content-Security-Policy: script-src 'self' https://apis.example.com
```
#### CSP HTTP headers
### CSP HTTP Header
Electron respects the [`Content-Security-Policy` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
which can be set using Electron's
[`webRequest.onHeadersReceived`](../api/web-request.md#webrequestonheadersreceivedfilter-listener)
handler:
```javascript title='main.js (Main Process)'
```javascript
const { session } = require('electron')
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
@@ -388,22 +383,20 @@ session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
})
```
#### CSP meta tag
### CSP Meta Tag
CSP's preferred delivery mechanism is an HTTP header. However, it is not possible
CSP's preferred delivery mechanism is an HTTP header, however it is not possible
to use this method when loading a resource using the `file://` protocol. It can
be useful in some cases to set a policy on a page directly in the markup using a
`<meta>` tag:
be useful in some cases, such as using the `file://` protocol, to set a policy
on a page directly in the markup using a `<meta>` tag:
```html title='index.html (Renderer Process)'
```html
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
```
### 8. Do not enable `allowRunningInsecureContent`
## 8) Do Not Set `allowRunningInsecureContent` to `true`
:::info
This recommendation is Electron's default.
:::
_Recommendation is Electron's default_
By default, Electron will not allow websites loaded over `HTTPS` to load and
execute scripts, CSS, or plugins from insecure sources (`HTTP`). Setting the
@@ -412,15 +405,15 @@ property `allowRunningInsecureContent` to `true` disables that protection.
Loading the initial HTML of a website over `HTTPS` and attempting to load
subsequent resources via `HTTP` is also known as "mixed content".
#### Why?
### Why?
Loading content over `HTTPS` assures the authenticity and integrity
of the loaded resources while encrypting the traffic itself. See the section on
[only displaying secure content](#1-only-load-secure-content) for more details.
#### How?
### How?
```js title='main.js (Main Process)'
```js
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
@@ -429,21 +422,19 @@ const mainWindow = new BrowserWindow({
})
```
```js title='main.js (Main Process)'
```js
// Good
const mainWindow = new BrowserWindow({})
```
### 9. Do not enable experimental features
## 9) Do Not Enable Experimental Features
:::info
This recommendation is Electron's default.
:::
_Recommendation is Electron's default_
Advanced users of Electron can enable experimental Chromium features using the
`experimentalFeatures` property.
#### Why?
### Why?
Experimental features are, as the name suggests, experimental and have not been
enabled for all Chromium users. Furthermore, their impact on Electron as a whole
@@ -452,9 +443,9 @@ has likely not been tested.
Legitimate use cases exist, but unless you know what you are doing, you should
not enable this property.
#### How?
### How?
```js title='main.js (Main Process)'
```js
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
@@ -463,22 +454,20 @@ const mainWindow = new BrowserWindow({
})
```
```js title='main.js (Main Process)'
```js
// Good
const mainWindow = new BrowserWindow({})
```
### 10. Do not use `enableBlinkFeatures`
## 10) Do Not Use `enableBlinkFeatures`
:::info
This recommendation is Electron's default.
:::
_Recommendation is Electron's default_
Blink is the name of the rendering engine behind Chromium. As with
`experimentalFeatures`, the `enableBlinkFeatures` property allows developers to
enable features that have been disabled by default.
#### Why?
### Why?
Generally speaking, there are likely good reasons if a feature was not enabled
by default. Legitimate use cases for enabling specific features exist. As a
@@ -486,9 +475,9 @@ developer, you should know exactly why you need to enable a feature, what the
ramifications are, and how it impacts the security of your application. Under
no circumstances should you enable features speculatively.
#### How?
### How?
```js title='main.js (Main Process)'
```js
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
@@ -497,16 +486,14 @@ const mainWindow = new BrowserWindow({
})
```
```js title='main.js (Main Process)'
```js
// Good
const mainWindow = new BrowserWindow()
```
### 11. Do not use `allowpopups` for WebViews
## 11) Do Not Use `allowpopups`
:::info
This recommendation is Electron's default.
:::
_Recommendation is Electron's default_
If you are using [`<webview>`][webview-tag], you might need the pages and scripts
loaded in your `<webview>` tag to open new windows. The `allowpopups` attribute
@@ -514,16 +501,16 @@ enables them to create new [`BrowserWindows`][browser-window] using the
`window.open()` method. `<webview>` tags are otherwise not allowed to create new
windows.
#### Why?
### Why?
If you do not need popups, you are better off not allowing the creation of
new [`BrowserWindows`][browser-window] by default. This follows the principle
of minimally required access: Don't let a website create new popups unless
you know it needs that feature.
#### How?
### How?
```html title='index.html (Renderer Process)'
```html
<!-- Bad -->
<webview allowpopups src="page.html"></webview>
@@ -531,7 +518,7 @@ you know it needs that feature.
<webview src="page.html"></webview>
```
### 12. Verify WebView options before creation
## 12) Verify WebView Options Before Creation
A WebView created in a renderer process that does not have Node.js integration
enabled will not be able to enable integration itself. However, a WebView will
@@ -541,7 +528,7 @@ It is a good idea to control the creation of new [`<webview>`][webview-tag] tags
from the main process and to verify that their webPreferences do not disable
security features.
#### Why?
### Why?
Since `<webview>` live in the DOM, they can be created by a script running on your
website even if Node.js integration is otherwise disabled.
@@ -551,13 +538,13 @@ a renderer process. In most cases, developers do not need to disable any of
those features - and you should therefore not allow different configurations
for newly created [`<webview>`][webview-tag] tags.
#### How?
### How?
Before a [`<webview>`][webview-tag] tag is attached, Electron will fire the
`will-attach-webview` event on the hosting `webContents`. Use the event to
prevent the creation of `webViews` with possibly insecure options.
```js title='main.js (Main Process)'
```js
app.on('web-contents-created', (event, contents) => {
contents.on('will-attach-webview', (event, webPreferences, params) => {
// Strip away preload scripts if unused or verify their location is legitimate
@@ -575,16 +562,16 @@ app.on('web-contents-created', (event, contents) => {
})
```
Again, this list merely minimizes the risk, but does not remove it. If your goal
Again, this list merely minimizes the risk, it does not remove it. If your goal
is to display a website, a browser will be a more secure option.
### 13. Disable or limit navigation
## 13) Disable or limit navigation
If your app has no need to navigate or only needs to navigate to known pages,
it is a good idea to limit navigation outright to that known scope, disallowing
any other kinds of navigation.
#### Why?
### Why?
Navigation is a common attack vector. If an attacker can convince your app to
navigate away from its current page, they can possibly force your app to open
@@ -597,7 +584,7 @@ A common attack pattern is that the attacker convinces your app's users to
interact with the app in such a way that it navigates to one of the attacker's
pages. This is usually done via links, plugins, or other user-generated content.
#### How?
### How?
If your app has no need for navigation, you can call `event.preventDefault()`
in a [`will-navigate`][will-navigate] handler. If you know which pages your app
@@ -608,7 +595,7 @@ We recommend that you use Node's parser for URLs. Simple string comparisons can
sometimes be fooled - a `startsWith('https://example.com')` test would let
`https://example.com.attacker.com` through.
```js title='main.js (Main Process)'
```js
const URL = require('url').URL
app.on('web-contents-created', (event, contents) => {
@@ -622,12 +609,12 @@ app.on('web-contents-created', (event, contents) => {
})
```
### 14. Disable or limit creation of new windows
## 14) Disable or limit creation of new windows
If you have a known set of windows, it's a good idea to limit the creation of
additional windows in your app.
#### Why?
### Why?
Much like navigation, the creation of new `webContents` is a common attack
vector. Attackers attempt to convince your app to create new windows, frames,
@@ -640,7 +627,7 @@ security at no cost. This is commonly the case for apps that open one
`BrowserWindow` and do not need to open an arbitrary number of additional
windows at runtime.
#### How?
### How?
[`webContents`][web-contents] will delegate to its [window open
handler][window-open-handler] before creating new windows. The handler will
@@ -648,7 +635,7 @@ receive, amongst other parameters, the `url` the window was requested to open
and the options used to create it. We recommend that you register a handler to
monitor the creation of windows, and deny any unexpected window creation.
```js title='main.js (Main Process)'
```js
const { shell } = require('electron')
app.on('web-contents-created', (event, contents) => {
@@ -669,40 +656,40 @@ app.on('web-contents-created', (event, contents) => {
})
```
### 15. Do not use `shell.openExternal` with untrusted content
## 15) Do not use `openExternal` with untrusted content
The shell module's [`openExternal`][open-external] API allows opening a given
protocol URI with the desktop's native utilities. On macOS, for instance, this
function is similar to the `open` terminal command utility and will open the
specific application based on the URI and filetype association.
Shell's [`openExternal`][open-external] allows opening a given protocol URI with
the desktop's native utilities. On macOS, for instance, this function is similar
to the `open` terminal command utility and will open the specific application
based on the URI and filetype association.
#### Why?
### Why?
Improper use of [`openExternal`][open-external] can be leveraged to compromise
the user's host. When openExternal is used with untrusted content, it can be
leveraged to execute arbitrary commands.
#### How?
### How?
```js title='main.js (Main Process)'
```js
// Bad
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
```
```js title='main.js (Main Process)'
```js
// Good
const { shell } = require('electron')
shell.openExternal('https://example.com/index.html')
```
### 16. Use a current version of Electron
## 16) Use a current version of Electron
You should strive for always using the latest available version of Electron.
Whenever a new major version is released, you should attempt to update your
app as quickly as possible.
#### Why?
### Why?
An application built with an older version of Electron, Chromium, and Node.js
is an easier target than an application that is using more recent versions of
@@ -718,13 +705,6 @@ to fix issues before publishing them. Your application will be more secure if
it is running a recent version of Electron (and thus, Chromium and Node.js) for
which potential security issues are not as widely known.
#### How?
Migrate your app one major version at a time, while referring to Electron's
[Breaking Changes][breaking-changes] document to see if any code needs to
be updated.
[breaking-changes]: ../breaking-changes.md
[browser-window]: ../api/browser-window.md
[browser-view]: ../api/browser-view.md
[webview-tag]: ../api/webview-tag.md
@@ -732,4 +712,5 @@ be updated.
[window-open-handler]: ../api/web-contents.md#contentssetwindowopenhandlerhandler
[will-navigate]: ../api/web-contents.md#event-will-navigate
[open-external]: ../api/shell.md#shellopenexternalurl-options
[sandbox]: ../tutorial/sandbox.md
[responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure

View File

@@ -10,7 +10,7 @@ for answers to questions,
or to join in discussion with other developers who use Electron,
you can interact with the community in these locations:
* [Electron's Discord server](https://discord.com/invite/APGC3k5yaH) has channels for:
* [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
* Getting help
* Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
* Sharing ideas with other Electron app developers
@@ -70,10 +70,10 @@ until the maintainers feel the maintenance burden is too high to continue doing
### Currently supported versions
* 18.x.y
* 17.x.y
* 16.x.y
* 15.x.y
* 14.x.y
### End-of-life

View File

@@ -3,7 +3,7 @@
Being based on Chromium, Electron requires a display driver to function.
If Chromium can't find a display driver, Electron will fail to launch -
and therefore not executing any of your tests, regardless of how you are running
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar Systems
them. Testing Electron-based apps on Travis, Circle, Jenkins or similar Systems
requires therefore a little bit of configuration. In essence, we need to use
a virtual display driver.
@@ -49,9 +49,10 @@ install:
For Jenkins, a [Xvfb plugin is available](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin).
### CircleCI
### Circle CI
CircleCI is awesome and has Xvfb and `$DISPLAY` already set up, so no further configuration is required.
Circle CI is awesome and has Xvfb and `$DISPLAY`
[already set up, so no further configuration is required](https://circleci.com/docs/environment#browsers).
### AppVeyor

View File

@@ -179,7 +179,6 @@ template("electron_paks") {
"${root_gen_dir}/device/bluetooth/strings/bluetooth_strings_",
"${root_gen_dir}/services/strings/services_strings_",
"${root_gen_dir}/ui/strings/app_locale_settings_",
"${root_gen_dir}/ui/strings/ax_strings_",
"${root_gen_dir}/ui/strings/ui_strings_",
]
deps = [
@@ -189,17 +188,16 @@ template("electron_paks") {
"//services/strings",
"//third_party/blink/public/strings",
"//ui/strings:app_locale_settings",
"//ui/strings:ax_strings",
"//ui/strings:ui_strings",
]
input_locales = platform_pak_locales
input_locales = locales
output_dir = "${invoker.output_dir}/locales"
if (is_mac) {
output_locales = locales_as_mac_outputs
} else {
output_locales = platform_pak_locales
output_locales = locales
}
}

View File

@@ -33,23 +33,6 @@
{SCREEN_INDEX, plural, =1{Screen #} other{Screen #}}
</message>
<!-- File Select Helper-->
<message name="IDS_IMAGE_FILES" desc="The description of the image file extensions in the select file dialog.">
Image Files
</message>
<message name="IDS_AUDIO_FILES" desc="The description of the audio file extensions in the select file dialog.">
Audio Files
</message>
<message name="IDS_VIDEO_FILES" desc="The description of the video file extensions in the select file dialog.">
Video Files
</message>
<message name="IDS_CUSTOM_FILES" desc="The description of the custom file extensions in the select file dialog.">
Custom Files
</message>
<message name="IDS_DEFAULT_DOWNLOAD_FILENAME" desc="Default name for downloaded files when we have no idea what they could be.">
download
</message>
<!-- Picture-in-Picture -->
<if expr="is_macosx">
<message name="IDS_PICTURE_IN_PICTURE_TITLE_TEXT" desc="Title of the Picture-in-Picture window. This appears in the system tray and window header.">

View File

@@ -5,6 +5,7 @@ auto_filenames = {
"docs/api/app.md",
"docs/api/auto-updater.md",
"docs/api/browser-view.md",
"docs/api/browser-window-proxy.md",
"docs/api/browser-window.md",
"docs/api/client-request.md",
"docs/api/clipboard.md",
@@ -100,14 +101,11 @@ auto_filenames = {
"docs/api/structures/new-window-web-contents-event.md",
"docs/api/structures/notification-action.md",
"docs/api/structures/notification-response.md",
"docs/api/structures/payment-discount.md",
"docs/api/structures/point.md",
"docs/api/structures/post-body.md",
"docs/api/structures/printer-info.md",
"docs/api/structures/process-memory-info.md",
"docs/api/structures/process-metric.md",
"docs/api/structures/product-discount.md",
"docs/api/structures/product-subscription-period.md",
"docs/api/structures/product.md",
"docs/api/structures/protocol-request.md",
"docs/api/structures/protocol-response-upload-data.md",
@@ -228,6 +226,7 @@ auto_filenames = {
"lib/browser/devtools.ts",
"lib/browser/guest-view-manager.ts",
"lib/browser/guest-window-manager.ts",
"lib/browser/guest-window-proxy.ts",
"lib/browser/init.ts",
"lib/browser/ipc-main-impl.ts",
"lib/browser/ipc-main-internal-utils.ts",

View File

@@ -32,13 +32,10 @@ filenames = {
"shell/browser/notifications/linux/notification_presenter_linux.cc",
"shell/browser/notifications/linux/notification_presenter_linux.h",
"shell/browser/relauncher_linux.cc",
"shell/browser/ui/electron_desktop_window_tree_host_linux.cc",
"shell/browser/ui/file_dialog_gtk.cc",
"shell/browser/ui/message_box_gtk.cc",
"shell/browser/ui/tray_icon_gtk.cc",
"shell/browser/ui/tray_icon_gtk.h",
"shell/browser/ui/views/client_frame_view_linux.cc",
"shell/browser/ui/views/client_frame_view_linux.h",
"shell/common/application_info_linux.cc",
"shell/common/language_util_linux.cc",
"shell/common/node_bindings_linux.cc",
@@ -386,6 +383,8 @@ 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",
@@ -414,8 +413,6 @@ filenames = {
"shell/browser/native_browser_view.h",
"shell/browser/native_window.cc",
"shell/browser/native_window.h",
"shell/browser/native_window_features.cc",
"shell/browser/native_window_features.h",
"shell/browser/native_window_observer.h",
"shell/browser/net/asar/asar_file_validator.cc",
"shell/browser/net/asar/asar_file_validator.h",
@@ -679,6 +676,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",
@@ -735,6 +734,11 @@ filenames = {
"shell/renderer/extensions/electron_extensions_renderer_client.h",
]
app_sources = [
"shell/app/electron_main.cc",
"shell/app/electron_main.h",
]
framework_sources = [
"shell/app/electron_library_main.h",
"shell/app/electron_library_main.mm",

View File

@@ -35,7 +35,7 @@ const spawnUpdate = function (args: string[], detached: boolean, callback: Funct
spawnedArgs = args || [];
}
} catch (error1) {
error = error1 as Error;
error = error1;
// Shouldn't happen, but still guard it.
process.nextTick(function () {

View File

@@ -5,8 +5,7 @@ const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
type RoleId = 'about' | 'close' | 'copy' | 'cut' | 'delete' | 'forcereload' | 'front' | 'help' | 'hide' | 'hideothers' | 'minimize' |
'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' |
'showsubstitutions' | 'togglesmartquotes' | 'togglesmartdashes' | 'toggletextreplacement' | 'startspeaking' | 'stopspeaking' |
'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' | 'startspeaking' | 'stopspeaking' |
'toggledevtools' | 'togglefullscreen' | 'undo' | 'unhide' | 'window' | 'zoom' | 'zoomin' | 'zoomout' | 'togglespellchecker' |
'appmenu' | 'filemenu' | 'editmenu' | 'viewmenu' | 'windowmenu' | 'sharemenu'
interface Role {
@@ -134,18 +133,6 @@ export const roleList: Record<RoleId, Role> = {
clearrecentdocuments: {
label: 'Clear Menu'
},
showsubstitutions: {
label: 'Show Substitutions'
},
togglesmartquotes: {
label: 'Smart Quotes'
},
togglesmartdashes: {
label: 'Smart Dashes'
},
toggletextreplacement: {
label: 'Text Replacement'
},
startspeaking: {
label: 'Start Speaking'
},
@@ -250,16 +237,6 @@ export const roleList: Record<RoleId, Role> = {
{ role: 'delete' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Substitutions',
submenu: [
{ role: 'showSubstitutions' },
{ type: 'separator' },
{ role: 'toggleSmartQuotes' },
{ role: 'toggleSmartDashes' },
{ role: 'toggleTextReplacement' }
]
},
{
label: 'Speech',
submenu: [

View File

@@ -61,25 +61,24 @@ class IncomingMessage extends Readable {
const filteredHeaders: Record<string, string | string[]> = {};
const { rawHeaders } = this._responseHead;
rawHeaders.forEach(header => {
const keyLowerCase = header.key.toLowerCase();
if (Object.prototype.hasOwnProperty.call(filteredHeaders, keyLowerCase) &&
discardableDuplicateHeaders.has(keyLowerCase)) {
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key) &&
discardableDuplicateHeaders.has(header.key)) {
// do nothing with discardable duplicate headers
} else {
if (keyLowerCase === 'set-cookie') {
if (header.key === 'set-cookie') {
// keep set-cookie as an array per Node.js rules
// see https://nodejs.org/api/http.html#http_message_headers
if (Object.prototype.hasOwnProperty.call(filteredHeaders, keyLowerCase)) {
(filteredHeaders[keyLowerCase] as string[]).push(header.value);
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
(filteredHeaders[header.key] as string[]).push(header.value);
} else {
filteredHeaders[keyLowerCase] = [header.value];
filteredHeaders[header.key] = [header.value];
}
} else {
// for non-cookie headers, the values are joined together with ', '
if (Object.prototype.hasOwnProperty.call(filteredHeaders, keyLowerCase)) {
filteredHeaders[keyLowerCase] += `, ${header.value}`;
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key] += `, ${header.value}`;
} else {
filteredHeaders[keyLowerCase] = header.value;
filteredHeaders[header.key] = header.value;
}
}
}
@@ -87,15 +86,6 @@ class IncomingMessage extends Readable {
return filteredHeaders;
}
get rawHeaders () {
const rawHeadersArr: string[] = [];
const { rawHeaders } = this._responseHead;
rawHeaders.forEach(header => {
rawHeadersArr.push(header.key, header.value);
});
return rawHeadersArr;
}
get httpVersion () {
return `${this.httpVersionMajor}.${this.httpVersionMinor}`;
}

View File

@@ -680,6 +680,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
@@ -689,23 +699,14 @@ WebContents.prototype._init = function () {
transparent: windowOpenOverriddenOptions.transparent,
...windowOpenOverriddenOptions.webPreferences
} : undefined;
// TODO(zcbenz): The features string is parsed twice: here where it is
// passed to C++, and in |makeBrowserWindowOptions| later where it is
// not actually used since the WebContents is created here.
// We should be able to remove the latter once the |new-window| event
// is removed.
const { webPreferences: parsedWebPreferences } = parseFeatures(rawFeatures);
// Parameters should keep same with |makeBrowserWindowOptions|.
const webPreferences = makeWebPreferences({
embedder: event.sender,
insecureParsedWebPreferences: parsedWebPreferences,
secureOverrideWebPreferences
});
this._setNextChildWebPreferences(webPreferences);
this._setNextChildWebPreferences(
makeWebPreferences({ embedder: event.sender, secureOverrideWebPreferences })
);
}
});
// Create a new browser window for "window.open"
// Create a new browser window for the native implementation of
// "window.open", used in sandbox and nativeWindowOpen mode.
this.on('-add-new-contents' as any, (event: ElectronInternal.Event, webContents: Electron.WebContents, disposition: string,
_userGesture: boolean, _left: number, _top: number, _width: number, _height: number, url: string, frameName: string,
referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => {
@@ -748,14 +749,6 @@ WebContents.prototype._init = function () {
}
});
this.on('select-bluetooth-device', (event, devices, callback) => {
if (this.listenerCount('select-bluetooth-device') === 1) {
// Cancel it if there are no handlers
event.preventDefault();
callback('');
}
});
const event = process._linkedBinding('electron_browser_event').createEmpty();
app.emit('web-contents-created', event, this);

View File

@@ -31,7 +31,7 @@ export const setDefaultApplicationMenu = () => {
{
label: 'Community Discussions',
click: async () => {
await shell.openExternal('https://discord.com/invite/APGC3k5yaH');
await shell.openExternal('https://discord.gg/electron');
}
},
{

View File

@@ -56,6 +56,7 @@ function makeWebPreferences (embedder: Electron.WebContents, params: Record<stri
const inheritedWebPreferences = new Map([
['contextIsolation', true],
['javascript', false],
['nativeWindowOpen', true],
['nodeIntegration', false],
['sandbox', true],
['nodeIntegrationInSubFrames', false],
@@ -73,17 +74,6 @@ function makeWebPreferences (embedder: Electron.WebContents, params: Record<stri
return webPreferences;
}
function makeLoadURLOptions (params: Record<string, any>) {
const opts: Electron.LoadURLOptions = {};
if (params.httpreferrer) {
opts.httpReferrer = params.httpreferrer;
}
if (params.useragent) {
opts.userAgent = params.useragent;
}
return opts;
}
// Create a new guest instance.
const createGuest = function (embedder: Electron.WebContents, embedderFrameId: number, elementInstanceId: number, params: Record<string, any>) {
// eslint-disable-next-line no-undef
@@ -107,7 +97,7 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
// Init guest web view after attached.
guest.once('did-attach' as any, function (this: Electron.WebContents, event: Electron.Event) {
const params = this.attachParams!;
params = this.attachParams!;
delete this.attachParams;
const previouslyAttached = this.viewInstanceId != null;
@@ -119,7 +109,14 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
}
if (params.src) {
this.loadURL(params.src, params.opts);
const opts: Electron.LoadURLOptions = {};
if (params.httpreferrer) {
opts.httpReferrer = params.httpreferrer;
}
if (params.useragent) {
opts.userAgent = params.useragent;
}
this.loadURL(params.src, opts);
}
embedder.emit('did-attach-webview', event, guest);
});
@@ -208,15 +205,13 @@ const attachGuest = function (embedder: Electron.WebContents, embedderFrameId: n
return false;
}
const { instanceId } = params;
// If this guest is already attached to an element then remove it
if (guestInstance.elementInstanceId) {
const oldKey = `${guestInstance.embedder.id}-${guestInstance.elementInstanceId}`;
embedderElementsMap.delete(oldKey);
// Remove guest from embedder if moving across web views
if (guest.viewInstanceId !== instanceId) {
if (guest.viewInstanceId !== params.instanceId) {
webViewManager.removeGuest(guestInstance.embedder, guestInstanceId);
guestInstance.embedder._sendInternal(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${guest.viewInstanceId}`);
}
@@ -227,12 +222,12 @@ const attachGuest = function (embedder: Electron.WebContents, embedderFrameId: n
const event = eventBinding.createWithSender(embedder);
embedder.emit('will-attach-webview', event, webPreferences, params);
if (event.defaultPrevented) {
if (guest.viewInstanceId == null) guest.viewInstanceId = instanceId;
if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId;
guest.destroy();
return false;
}
guest.attachParams = { instanceId, src: params.src, opts: makeLoadURLOptions(params) };
guest.attachParams = params;
embedderElementsMap.set(key, guestInstanceId);
guest.setEmbedder(embedder);

View File

@@ -1,13 +1,14 @@
/**
* Create and minimally track guest windows at the direction of the renderer
* (via window.open). Here, "guest" roughly means "child" — it's not necessarily
* emblematic of its process status; both in-process (same-origin) and
* out-of-process (cross-origin) are created here. "Embedder" roughly means
* "parent."
* emblematic of its process status; both in-process (same-origin
* nativeWindowOpen) and out-of-process (cross-origin nativeWindowOpen and
* BrowserWindowProxy) are created here. "Embedder" roughly means "parent."
*/
import { BrowserWindow } from 'electron/main';
import type { BrowserWindowConstructorOptions, Referrer, WebContents, LoadURLOptions } from 'electron/main';
import { parseFeatures } from '@electron/internal/browser/parse-features-string';
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
type PostData = LoadURLOptions['postData']
export type WindowOpenArgs = {
@@ -22,12 +23,13 @@ const unregisterFrameName = (name: string) => frameNamesToWindow.delete(name);
const getGuestWindowByFrameName = (name: string) => frameNamesToWindow.get(name);
/**
* `openGuestWindow` is called to create and setup event handling for the new
* window.
* `openGuestWindow` is called for both implementations of window.open
* (BrowserWindowProxy and nativeWindowOpen) to create and setup event handling
* for the new window.
*
* Until its removal in 12.0.0, the `new-window` event is fired, allowing the
* user to preventDefault() on the passed event (which ends up calling
* DestroyWebContents).
* DestroyWebContents in the nativeWindowOpen code path).
*/
export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs }: {
event: { sender: WebContents, defaultPrevented: boolean },
@@ -76,6 +78,22 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
webContents: guest,
...browserWindowOptions
});
if (!guest) {
// We should only call `loadURL` if the webContents was constructed by us in
// the case of BrowserWindowProxy (non-sandboxed, nativeWindowOpen: false),
// as navigating to the url when creating the window from an existing
// webContents is not necessary (it will navigate there anyway).
// This can also happen if we enter this function from OpenURLFromTab, in
// which case the browser process is responsible for initiating navigation
// in the new window.
window.loadURL(url, {
httpReferrer: referrer,
...(postData && {
postData,
extraHeaders: formatPostDataHeaders(postData as Electron.UploadRawData[])
})
});
}
handleWindowLifecycleEvents({ embedder, frameName, guest: window });
@@ -100,7 +118,9 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName }: {
guest.destroy();
};
const cachedGuestId = guest.webContents.id;
const closedByUser = function () {
embedder._sendInternal(`${IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_CLOSED}_${cachedGuestId}`);
embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder);
};
embedder.once('current-render-view-deleted' as any, closedByEmbedder);
@@ -175,6 +195,7 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs,
const securityWebPreferences: { [key: string]: boolean } = {
contextIsolation: true,
javascript: false,
nativeWindowOpen: true,
nodeIntegration: false,
sandbox: true,
webviewTag: false,
@@ -196,10 +217,6 @@ function makeBrowserWindowOptions ({ embedder, features, overrideOptions }: {
height: 600,
...parsedOptions,
...overrideOptions,
// Note that for normal code path an existing WebContents created by
// Chromium will be used, with web preferences parsed in the
// |-will-add-new-contents| event.
// The |webPreferences| here is only used by the |new-window| event.
webPreferences: makeWebPreferences({
embedder,
insecureParsedWebPreferences: parsedWebPreferences,
@@ -224,6 +241,7 @@ export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {
}
return map;
}, {} as Electron.WebPreferences));
const openerId = parentWebPreferences.nativeWindowOpen ? null : embedder.id;
return {
...parsedWebPreferences,
@@ -231,10 +249,22 @@ export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {
// ability to change important security options but allow main (via
// setWindowOpenHandler) to change them.
...securityWebPreferencesFromParent,
...secureOverrideWebPreferences
...secureOverrideWebPreferences,
// Sets correct openerId here to give correct options to 'new-window' event handler
// TODO: Figure out another way to pass this?
openerId
};
}
function formatPostDataHeaders (postData: PostData) {
if (!postData) return;
const { contentType, boundary } = parseContentTypeFormat(postData);
if (boundary != null) { return `content-type: ${contentType}; boundary=${boundary}`; }
return `content-type: ${contentType}`;
}
const MULTIPART_CONTENT_TYPE = 'multipart/form-data';
const URL_ENCODED_CONTENT_TYPE = 'application/x-www-form-urlencoded';

View File

@@ -0,0 +1,213 @@
/**
* Manage guest windows when using the default BrowserWindowProxy version of the
* renderer's window.open (i.e. nativeWindowOpen off). This module mostly
* consists of marshaling IPC requests from the BrowserWindowProxy to the
* WebContents.
*/
import { webContents, BrowserWindow } from 'electron/main';
import type { WebContents } from 'electron/main';
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
import { openGuestWindow } from '@electron/internal/browser/guest-window-manager';
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
const { isSameOrigin } = process._linkedBinding('electron_common_v8_util');
const getGuestWindow = function (guestContents: WebContents) {
let guestWindow = BrowserWindow.fromWebContents(guestContents);
if (guestWindow == null) {
const hostContents = guestContents.hostWebContents;
if (hostContents != null) {
guestWindow = BrowserWindow.fromWebContents(hostContents);
}
}
if (!guestWindow) {
throw new Error('getGuestWindow failed');
}
return guestWindow;
};
const isChildWindow = function (sender: WebContents, target: WebContents) {
return target.getLastWebPreferences()!.openerId === sender.id;
};
const isRelatedWindow = function (sender: WebContents, target: WebContents) {
return isChildWindow(sender, target) || isChildWindow(target, sender);
};
const isScriptableWindow = function (sender: WebContents, target: WebContents) {
return (
isRelatedWindow(sender, target) &&
isSameOrigin(sender.getURL(), target.getURL())
);
};
const isNodeIntegrationEnabled = function (sender: WebContents) {
return sender.getLastWebPreferences()!.nodeIntegration === true;
};
// Checks whether |sender| can access the |target|:
const canAccessWindow = function (sender: WebContents, target: WebContents) {
return (
isChildWindow(sender, target) ||
isScriptableWindow(sender, target) ||
isNodeIntegrationEnabled(sender)
);
};
// Routed window.open messages with raw options
ipcMainInternal.on(
IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_OPEN,
(
event,
url: string,
frameName: string,
features: string
) => {
// This should only be allowed for senders that have nativeWindowOpen: false
const lastWebPreferences = event.sender.getLastWebPreferences()!;
if (lastWebPreferences.nativeWindowOpen || lastWebPreferences.sandbox) {
event.returnValue = null;
throw new Error(
'GUEST_WINDOW_MANAGER_WINDOW_OPEN denied: expected native window.open'
);
}
const referrer: Electron.Referrer = { url: '', policy: 'strict-origin-when-cross-origin' };
const browserWindowOptions = event.sender._callWindowOpenHandler(event, { url, frameName, features, disposition: 'new-window', referrer });
if (event.defaultPrevented) {
event.returnValue = null;
return;
}
const guest = openGuestWindow({
event,
embedder: event.sender,
referrer,
disposition: 'new-window',
overrideBrowserWindowOptions: browserWindowOptions!,
windowOpenArgs: {
url: url || 'about:blank',
frameName: frameName || '',
features: features || ''
}
});
event.returnValue = guest ? guest.webContents.id : null;
}
);
type IpcHandler<T, Event> = (event: Event, guestContents: Electron.WebContents, ...args: any[]) => T;
const makeSafeHandler = function<T, Event> (handler: IpcHandler<T, Event>) {
return (event: Event, guestId: number, ...args: any[]) => {
// Access webContents via electron to prevent circular require.
const guestContents = webContents.fromId(guestId);
if (!guestContents) {
throw new Error(`Invalid guestId: ${guestId}`);
}
return handler(event, guestContents as Electron.WebContents, ...args);
};
};
const handleMessage = function (channel: string, handler: IpcHandler<any, Electron.IpcMainInvokeEvent>) {
ipcMainInternal.handle(channel, makeSafeHandler(handler));
};
const handleMessageSync = function (channel: string, handler: IpcHandler<any, ElectronInternal.IpcMainInternalEvent>) {
ipcMainUtils.handleSync(channel, makeSafeHandler(handler));
};
type ContentsCheck = (contents: WebContents, guestContents: WebContents) => boolean;
const securityCheck = function (contents: WebContents, guestContents: WebContents, check: ContentsCheck) {
if (!check(contents, guestContents)) {
console.error(
`Blocked ${contents.getURL()} from accessing guestId: ${guestContents.id}`
);
throw new Error(`Access denied to guestId: ${guestContents.id}`);
}
};
const windowMethods = new Set(['destroy', 'focus', 'blur']);
handleMessage(
IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_METHOD,
(event, guestContents, method, ...args) => {
securityCheck(event.sender, guestContents, canAccessWindow);
if (!windowMethods.has(method)) {
console.error(
`Blocked ${event.senderFrame.url} from calling method: ${method}`
);
throw new Error(`Invalid method: ${method}`);
}
return (getGuestWindow(guestContents) as any)[method](...args);
}
);
handleMessage(
IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE,
(event, guestContents, message, targetOrigin, sourceOrigin) => {
if (targetOrigin == null) {
targetOrigin = '*';
}
// The W3C does not seem to have word on how postMessage should work when the
// origins do not match, so we do not do |canAccessWindow| check here since
// postMessage across origins is useful and not harmful.
securityCheck(event.sender, guestContents, isRelatedWindow);
if (
targetOrigin === '*' ||
isSameOrigin(guestContents.getURL(), targetOrigin)
) {
const sourceId = event.sender.id;
guestContents._sendInternal(
IPC_MESSAGES.GUEST_WINDOW_POSTMESSAGE,
sourceId,
message,
sourceOrigin
);
}
}
);
const webContentsMethodsAsync = new Set([
'loadURL',
'executeJavaScript',
'print'
]);
handleMessage(
IPC_MESSAGES.GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD,
(event, guestContents, method, ...args) => {
securityCheck(event.sender, guestContents, canAccessWindow);
if (!webContentsMethodsAsync.has(method)) {
console.error(
`Blocked ${event.sender.getURL()} from calling method: ${method}`
);
throw new Error(`Invalid method: ${method}`);
}
return (guestContents as any)[method](...args);
}
);
const webContentsMethodsSync = new Set(['getURL']);
handleMessageSync(
IPC_MESSAGES.GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD,
(event, guestContents, method, ...args) => {
securityCheck(event.sender, guestContents, canAccessWindow);
if (!webContentsMethodsSync.has(method)) {
console.error(
`Blocked ${event.sender.getURL()} from calling method: ${method}`
);
throw new Error(`Invalid method: ${method}`);
}
return (guestContents as any)[method](...args);
}
);

View File

@@ -78,6 +78,7 @@ require('@electron/internal/browser/rpc-server');
// Load the guest view manager.
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');

View File

@@ -15,7 +15,7 @@ export class IpcMainImpl extends EventEmitter {
try {
e._reply(await Promise.resolve(fn(e, ...args)));
} catch (err) {
e._throw(err as Error);
e._throw(err);
}
});
}

View File

@@ -18,6 +18,13 @@ export const enum IPC_MESSAGES {
GUEST_VIEW_MANAGER_PROPERTY_GET = 'GUEST_VIEW_MANAGER_PROPERTY_GET',
GUEST_VIEW_MANAGER_PROPERTY_SET = 'GUEST_VIEW_MANAGER_PROPERTY_SET',
GUEST_WINDOW_MANAGER_WINDOW_OPEN = 'GUEST_WINDOW_MANAGER_WINDOW_OPEN',
GUEST_WINDOW_MANAGER_WINDOW_CLOSED = 'GUEST_WINDOW_MANAGER_WINDOW_CLOSED',
GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE = 'GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE',
GUEST_WINDOW_MANAGER_WINDOW_METHOD = 'GUEST_WINDOW_MANAGER_WINDOW_METHOD',
GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD = 'GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD',
GUEST_WINDOW_POSTMESSAGE = 'GUEST_WINDOW_POSTMESSAGE',
RENDERER_WEB_FRAME_METHOD = 'RENDERER_WEB_FRAME_METHOD',
INSPECTOR_CONFIRM = 'INSPECTOR_CONFIRM',

View File

@@ -12,7 +12,9 @@ const v8Util = process._linkedBinding('electron_common_v8_util');
const nodeIntegration = mainFrame.getWebPreference('nodeIntegration');
const webviewTag = mainFrame.getWebPreference('webviewTag');
const isHiddenPage = mainFrame.getWebPreference('hiddenPage');
const nativeWindowOpen = mainFrame.getWebPreference('nativeWindowOpen') || process.sandboxed;
const isWebView = mainFrame.getWebPreference('isWebView');
const openerId = mainFrame.getWebPreference('openerId');
// ElectronApiServiceImpl will look for the "ipcNative" hidden object when
// invoking the 'onMessage' callback.
@@ -42,7 +44,7 @@ switch (window.location.protocol) {
default: {
// Override default web functions.
const { windowSetup } = require('@electron/internal/renderer/window-setup') as typeof windowSetupModule;
windowSetup(isWebView, isHiddenPage);
windowSetup(isWebView, openerId, isHiddenPage, nativeWindowOpen);
}
}

View File

@@ -8,24 +8,40 @@ const { contextIsolationEnabled } = internalContextBridge;
/* Corrects for some Inspector adaptations needed in Electron.
* 1) Use menu API to show context menu.
* 2) Correct for Chromium returning undefined for filesystem.
* 3) Use dialog API to override file chooser dialog.
*/
window.onload = function () {
if (contextIsolationEnabled) {
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
'InspectorFrontendHost', 'showContextMenuAtPoint'
], createMenu);
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
'Persistence', 'FileSystemWorkspaceBinding', 'completeURL'
], completeURL);
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
'UI', 'createFileSelectorElement'
], createFileSelectorElement);
} else {
window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu;
window.Persistence!.FileSystemWorkspaceBinding.completeURL = completeURL;
window.UI!.createFileSelectorElement = createFileSelectorElement;
}
};
// Extra / is needed as a result of MacOS requiring absolute paths
function completeURL (project: string, path: string) {
project = 'file:///';
return `${project}${path}`;
}
// The DOM implementation expects (message?: string) => boolean
window.confirm = function (message?: string, title?: string) {
return ipcRendererUtils.invokeSync(IPC_MESSAGES.INSPECTOR_CONFIRM, message, title) as boolean;
};
const useEditMenuItems = function (x: number, y: number, items: ContextMenuItem[]) {
return items.length === 0 && document.elementsFromPoint(x, y).some(element => {
return items.length === 0 && document.elementsFromPoint(x, y).some(function (element) {
return element.nodeName === 'INPUT' ||
element.nodeName === 'TEXTAREA' ||
(element as HTMLElement).isContentEditable;
@@ -42,3 +58,22 @@ const createMenu = function (x: number, y: number, items: ContextMenuItem[]) {
webFrame.executeJavaScript('window.DevToolsAPI.contextMenuCleared()');
});
};
const showFileChooserDialog = function (callback: (blob: File) => void) {
ipcRendererInternal.invoke<[ string, any ]>(IPC_MESSAGES.INSPECTOR_SELECT_FILE).then(([path, data]) => {
if (path && data) {
callback(dataToHtml5FileObject(path, data));
}
});
};
const dataToHtml5FileObject = function (path: string, data: any) {
return new File([data], path);
};
const createFileSelectorElement = function (this: any, callback: () => void) {
const fileSelectorElement = document.createElement('span');
fileSelectorElement.style.display = 'none';
fileSelectorElement.click = showFileChooserDialog.bind(this, callback);
return fileSelectorElement;
};

View File

@@ -25,6 +25,7 @@ export class WebViewImpl {
public hasFocus = false
public internalInstanceId?: number;
public resizeObserver?: ResizeObserver;
public userAgentOverride?: string;
public viewInstanceId: number
// on* Event handlers.
@@ -179,7 +180,8 @@ export class WebViewImpl {
buildParams () {
const params: Record<string, any> = {
instanceId: this.viewInstanceId
instanceId: this.viewInstanceId,
userAgentOverride: this.userAgentOverride
};
for (const [attributeName, attribute] of this.attributes) {

View File

@@ -1,10 +1,249 @@
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
import { internalContextBridge } from '@electron/internal/renderer/api/context-bridge';
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
const { contextIsolationEnabled } = internalContextBridge;
export const windowSetup = (isWebView: boolean, isHiddenPage: boolean) => {
// This file implements the following APIs over the ctx bridge:
// - window.open()
// - window.opener.blur()
// - window.opener.close()
// - window.opener.eval()
// - window.opener.focus()
// - window.opener.location
// - window.opener.print()
// - window.opener.closed
// - window.opener.postMessage()
// - window.history.back()
// - window.history.forward()
// - window.history.go()
// - window.history.length
// - window.prompt()
// - document.hidden
// - document.visibilityState
// Helper function to resolve relative url.
const resolveURL = (url: string, base: string) => new URL(url, base).href;
// Use this method to ensure values expected as strings in the main process
// are convertible to strings in the renderer process. This ensures exceptions
// converting values to strings are thrown in this process.
const toString = (value: any) => {
return value != null ? `${value}` : value;
};
const windowProxies = new Map<number, BrowserWindowProxy>();
const getOrCreateProxy = (guestId: number): SafelyBoundBrowserWindowProxy => {
let proxy = windowProxies.get(guestId);
if (proxy == null) {
proxy = new BrowserWindowProxy(guestId);
windowProxies.set(guestId, proxy);
}
return proxy.getSafe();
};
const removeProxy = (guestId: number) => {
windowProxies.delete(guestId);
};
type LocationProperties = 'hash' | 'href' | 'host' | 'hostname' | 'origin' | 'pathname' | 'port' | 'protocol' | 'search'
class LocationProxy {
@LocationProxy.ProxyProperty public hash!: string;
@LocationProxy.ProxyProperty public href!: string;
@LocationProxy.ProxyProperty public host!: string;
@LocationProxy.ProxyProperty public hostname!: string;
@LocationProxy.ProxyProperty public origin!: string;
@LocationProxy.ProxyProperty public pathname!: string;
@LocationProxy.ProxyProperty public port!: string;
@LocationProxy.ProxyProperty public protocol!: string;
@LocationProxy.ProxyProperty public search!: URLSearchParams;
private guestId: number;
/**
* Beware: This decorator will have the _prototype_ as the `target`. It defines properties
* commonly found in URL on the LocationProxy.
*/
private static ProxyProperty<T> (target: LocationProxy, propertyKey: LocationProperties) {
Object.defineProperty(target, propertyKey, {
enumerable: true,
configurable: true,
get: function (this: LocationProxy): T | string {
const guestURL = this.getGuestURL();
const value = guestURL ? guestURL[propertyKey] : '';
return value === undefined ? '' : value;
},
set: function (this: LocationProxy, newVal: T) {
const guestURL = this.getGuestURL();
if (guestURL) {
// TypeScript doesn't want us to assign to read-only variables.
// It's right, that's bad, but we're doing it anyway.
(guestURL as any)[propertyKey] = newVal;
return this._invokeWebContentsMethod('loadURL', guestURL.toString());
}
}
});
}
public getSafe = () => {
const that = this;
return {
get href () { return that.href; },
set href (newValue) { that.href = newValue; },
get hash () { return that.hash; },
set hash (newValue) { that.hash = newValue; },
get host () { return that.host; },
set host (newValue) { that.host = newValue; },
get hostname () { return that.hostname; },
set hostname (newValue) { that.hostname = newValue; },
get origin () { return that.origin; },
set origin (newValue) { that.origin = newValue; },
get pathname () { return that.pathname; },
set pathname (newValue) { that.pathname = newValue; },
get port () { return that.port; },
set port (newValue) { that.port = newValue; },
get protocol () { return that.protocol; },
set protocol (newValue) { that.protocol = newValue; },
get search () { return that.search; },
set search (newValue) { that.search = newValue; }
};
}
constructor (guestId: number) {
// eslint will consider the constructor "useless"
// unless we assign them in the body. It's fine, that's what
// TS would do anyway.
this.guestId = guestId;
this.getGuestURL = this.getGuestURL.bind(this);
}
public toString (): string {
return this.href;
}
private getGuestURL (): URL | null {
const maybeURL = this._invokeWebContentsMethodSync('getURL') as string;
// When there's no previous frame the url will be blank, so account for that here
// to prevent url parsing errors on an empty string.
const urlString = maybeURL !== '' ? maybeURL : 'about:blank';
try {
return new URL(urlString);
} catch (e) {
console.error('LocationProxy: failed to parse string', urlString, e);
}
return null;
}
private _invokeWebContentsMethod (method: string, ...args: any[]) {
return ipcRendererInternal.invoke(IPC_MESSAGES.GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD, this.guestId, method, ...args);
}
private _invokeWebContentsMethodSync (method: string, ...args: any[]) {
return ipcRendererUtils.invokeSync(IPC_MESSAGES.GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD, this.guestId, method, ...args);
}
}
interface SafelyBoundBrowserWindowProxy {
location: WindowProxy['location'];
blur: WindowProxy['blur'];
close: WindowProxy['close'];
eval: typeof eval; // eslint-disable-line no-eval
focus: WindowProxy['focus'];
print: WindowProxy['print'];
postMessage: WindowProxy['postMessage'];
closed: boolean;
}
class BrowserWindowProxy {
public closed: boolean = false
private _location: LocationProxy
private guestId: number
// TypeScript doesn't allow getters/accessors with different types,
// so for now, we'll have to make do with an "any" in the mix.
// https://github.com/Microsoft/TypeScript/issues/2521
public get location (): LocationProxy | any {
return this._location.getSafe();
}
public set location (url: string | any) {
url = resolveURL(url, this.location.href);
this._invokeWebContentsMethod('loadURL', url);
}
constructor (guestId: number) {
this.guestId = guestId;
this._location = new LocationProxy(guestId);
ipcRendererInternal.once(`${IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_CLOSED}_${guestId}`, () => {
removeProxy(guestId);
this.closed = true;
});
}
public getSafe = (): SafelyBoundBrowserWindowProxy => {
const that = this;
return {
postMessage: this.postMessage,
blur: this.blur,
close: this.close,
focus: this.focus,
print: this.print,
eval: this.eval,
get location () {
return that.location;
},
set location (url: string | any) {
that.location = url;
},
get closed () {
return that.closed;
}
};
}
public close = () => {
this._invokeWindowMethod('destroy');
}
public focus = () => {
this._invokeWindowMethod('focus');
}
public blur = () => {
this._invokeWindowMethod('blur');
}
public print = () => {
this._invokeWebContentsMethod('print');
}
public postMessage = (message: any, targetOrigin: string) => {
ipcRendererInternal.invoke(IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE, this.guestId, message, toString(targetOrigin), window.location.origin);
}
public eval = (code: string) => {
this._invokeWebContentsMethod('executeJavaScript', code);
}
private _invokeWindowMethod (method: string, ...args: any[]) {
return ipcRendererInternal.invoke(IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_METHOD, this.guestId, method, ...args);
}
private _invokeWebContentsMethod (method: string, ...args: any[]) {
return ipcRendererInternal.invoke(IPC_MESSAGES.GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD, this.guestId, method, ...args);
}
}
export const windowSetup = (
isWebView: boolean, openerId: number, isHiddenPage: boolean, usesNativeWindowOpen: boolean) => {
if (!process.sandboxed && !isWebView) {
// Override default window.close.
window.close = function () {
@@ -13,12 +252,72 @@ export const windowSetup = (isWebView: boolean, isHiddenPage: boolean) => {
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['close'], window.close);
}
if (!usesNativeWindowOpen) {
// TODO(MarshallOfSound): Make compatible with ctx isolation without hole-punch
// Make the browser window or guest view emit "new-window" event.
window.open = function (url?: string, frameName?: string, features?: string) {
if (url != null && url !== '') {
url = resolveURL(url, location.href);
}
const guestId = ipcRendererInternal.sendSync(IPC_MESSAGES.GUEST_WINDOW_MANAGER_WINDOW_OPEN, url, toString(frameName), toString(features));
if (guestId != null) {
return getOrCreateProxy(guestId) as any as WindowProxy;
} else {
return null;
}
};
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['open'], window.open);
}
// If this window uses nativeWindowOpen, but its opener window does not, we
// need to proxy window.opener in order to let the page communicate with its
// opener.
// Additionally, windows opened from a nativeWindowOpen child of a
// non-nativeWindowOpen parent will initially have their WebPreferences
// copied from their opener before having them updated, meaning openerId is
// initially incorrect. We detect this situation by checking for
// window.opener, which will be non-null for a natively-opened child, so we
// can ignore the openerId in that case, since it's incorrectly copied from
// the parent. This is, uh, confusing, so here's a diagram that will maybe
// help?
//
// [ grandparent window ] --> [ parent window ] --> [ child window ]
// n.W.O = false n.W.O = true n.W.O = true
// id = 1 id = 2 id = 3
// openerId = 0 openerId = 1 openerId = 1 <- !!wrong!!
// opener = null opener = null opener = [parent window]
if (openerId && !window.opener) {
window.opener = getOrCreateProxy(openerId);
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['opener'], window.opener);
}
// But we do not support prompt().
window.prompt = function () {
throw new Error('prompt() is and will not be supported.');
};
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['prompt'], window.prompt);
if (!usesNativeWindowOpen || openerId) {
ipcRendererInternal.on(IPC_MESSAGES.GUEST_WINDOW_POSTMESSAGE, function (
_event, sourceId: number, message: any, sourceOrigin: string
) {
// Manually dispatch event instead of using postMessage because we also need to
// set event.source.
//
// Why any? We can't construct a MessageEvent and we can't
// use `as MessageEvent` because you're not supposed to override
// data, origin, and source
const event: any = document.createEvent('Event');
event.initEvent('message', false, false);
event.data = message;
event.origin = sourceOrigin;
event.source = getOrCreateProxy(sourceId);
window.dispatchEvent(event as MessageEvent);
});
}
if (isWebView) {
// Webview `document.visibilityState` tracks window visibility (and ignores
// the actual <webview> element visibility) for backwards compatibility.

View File

@@ -22,8 +22,7 @@ if (isInstalled()) {
const platform = process.env.npm_config_platform || process.platform;
let arch = process.env.npm_config_arch || process.arch;
if (platform === 'darwin' && process.platform === 'darwin' && arch === 'x64' &&
process.env.npm_config_arch === undefined) {
if (platform === 'darwin' && process.platform === 'darwin' && arch === 'x64') {
// When downloading for macOS ON macOS and we think we need x64 we should
// check if we're running under rosetta and download the arm64 version if appropriate
try {

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "18.0.0-alpha.6",
"version": "17.0.0-alpha.1",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
@@ -31,9 +31,9 @@
"@typescript-eslint/eslint-plugin": "^4.4.1",
"@typescript-eslint/parser": "^4.4.1",
"asar": "^3.1.0",
"aws-sdk": "^2.814.0",
"aws-sdk": "^2.727.1",
"check-for-leaks": "^1.2.1",
"colors": "1.4.0",
"colors": "^1.4.0",
"dotenv-safe": "^4.0.4",
"dugite": "^1.103.0",
"eslint": "^7.4.0",
@@ -67,7 +67,7 @@
"timers-browserify": "1.4.2",
"ts-loader": "^8.0.2",
"ts-node": "6.2.0",
"typescript": "^4.5.5",
"typescript": "^4.1.3",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
"wrapper-webpack-plugin": "^2.1.0"

View File

@@ -2,4 +2,4 @@ expose_ripemd160.patch
expose_aes-cfb.patch
expose_des-ede3.patch
fix_sync_evp_get_cipherbynid_and_evp_get_cipherbyname.patch
expose_blowfish_ciphers.patch
enable_x509_v_flag_trusted_first_flag.patch

View File

@@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Juan Cruz Viotti <jv@jviotti.com>
Date: Thu, 30 Sep 2021 13:39:23 -0400
Subject: Enable X509_V_FLAG_TRUSTED_FIRST flag
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c
index 5a881d64c30076404cc800fff9e943bb0b30d2ac..29d5341efc8eb7ae6f90bdde5a8032e99f75c98e 100644
--- a/crypto/x509/x509_vpm.c
+++ b/crypto/x509/x509_vpm.c
@@ -528,7 +528,7 @@ static const X509_VERIFY_PARAM default_table[] = {
(char *)"default", /* X509 default parameters */
0, /* Check time */
0, /* internal flags */
- 0, /* flags */
+ X509_V_FLAG_TRUSTED_FIRST, /* flags */
0, /* purpose */
0, /* trust */
100, /* depth */

View File

@@ -58,10 +58,10 @@ index 852b76bea69988e0b3ac76a17b603128f239dde0..d443f4dc2daea0b7aa86ae75d31d995f
callback(EVP_aes_192_ctr(), "aes-192-ctr", NULL, arg);
callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg);
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
index 2458847e5640fe955a9971aa77c27251e5091db5..a0b3ac5f6b55921a542f27108beca93d6372c6fc 100644
index 09d72ec2c343f23409d35eca804a02e3290c86f1..1bea1a88b265312d700729ad2828f0b5d9f2d84f 100644
--- a/include/openssl/cipher.h
+++ b/include/openssl/cipher.h
@@ -448,6 +448,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
@@ -436,6 +436,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
// EVP_aes_128_cfb128 is only available in decrepit.
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cfb128(void);

View File

@@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeremy Rose <nornagon@nornagon.net>
Date: Wed, 5 Jan 2022 13:08:10 -0800
Subject: expose blowfish ciphers
This exposes the (decrepit) blowfish cipher family, bf-cbc, bf-cfb and
bf-ecb through the EVP interface. This adds references to decrepit code
from non-decrepit code, so upstream is unlikely to take the patch.
diff --git a/crypto/cipher_extra/cipher_extra.c b/crypto/cipher_extra/cipher_extra.c
index cfdb69e3c556fea11aa7c2d28d4b7da524df15c3..95bd172c99874610ec9157c52df4fe0232e78c7f 100644
--- a/crypto/cipher_extra/cipher_extra.c
+++ b/crypto/cipher_extra/cipher_extra.c
@@ -89,6 +89,9 @@ static const struct {
{NID_aes_256_ecb, "aes-256-ecb", EVP_aes_256_ecb},
{NID_aes_256_gcm, "aes-256-gcm", EVP_aes_256_gcm},
{NID_aes_256_ofb128, "aes-256-ofb", EVP_aes_256_ofb},
+ {NID_bf_cbc, "bf-cbc", EVP_bf_cbc},
+ {NID_bf_cfb64, "bf-cfb", EVP_bf_cfb},
+ {NID_bf_ecb, "bf-ecb", EVP_bf_ecb},
{NID_des_cbc, "des-cbc", EVP_des_cbc},
{NID_des_ecb, "des-ecb", EVP_des_ecb},
{NID_des_ede_cbc, "des-ede-cbc", EVP_des_ede_cbc},
diff --git a/decrepit/evp/evp_do_all.c b/decrepit/evp/evp_do_all.c
index 5e71420b765019edea82a33884ace539cd91bda5..43fc792697519325725e9ce87801c5dc176c70a1 100644
--- a/decrepit/evp/evp_do_all.c
+++ b/decrepit/evp/evp_do_all.c
@@ -36,6 +36,9 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
callback(EVP_aes_128_gcm(), "AES-128-GCM", NULL, arg);
callback(EVP_aes_192_gcm(), "AES-192-GCM", NULL, arg);
callback(EVP_aes_256_gcm(), "AES-256-GCM", NULL, arg);
+ callback(EVP_bf_cbc(), "BF-CBC", NULL, arg);
+ callback(EVP_bf_cfb(), "BF-CFB", NULL, arg);
+ callback(EVP_bf_ecb(), "BF-ECB", NULL, arg);
callback(EVP_des_cbc(), "DES-CBC", NULL, arg);
callback(EVP_des_ecb(), "DES-ECB", NULL, arg);
callback(EVP_des_ede(), "DES-EDE", NULL, arg);
@@ -63,6 +66,9 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
callback(EVP_aes_128_gcm(), "aes-128-gcm", NULL, arg);
callback(EVP_aes_192_gcm(), "aes-192-gcm", NULL, arg);
callback(EVP_aes_256_gcm(), "aes-256-gcm", NULL, arg);
+ callback(EVP_bf_cbc(), "bf-cbc", NULL, arg);
+ callback(EVP_bf_cfb(), "bf-cfb", NULL, arg);
+ callback(EVP_bf_ecb(), "bf-ecb", NULL, arg);
callback(EVP_des_cbc(), "des-cbc", NULL, arg);
callback(EVP_des_ecb(), "des-ecb", NULL, arg);
callback(EVP_des_ede(), "des-ede", NULL, arg);

View File

@@ -82,7 +82,7 @@ index a3fb077b9b9e66d1bc524fd7987622e73aa4776a..852b76bea69988e0b3ac76a17b603128
void EVP_MD_do_all(void (*callback)(const EVP_MD *cipher, const char *name,
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
index 6e889993edc1caa7e10670529dd270c337b5ae4c..f61f7e5009a9b4f5630cda2c3a5a21b44e5b88d8 100644
index fa7616896b6cc7422dc0171db29316f20fb25de8..6c19a0f0d454bef1abf16ebfeef380a53fb21e5c 100644
--- a/include/openssl/digest.h
+++ b/include/openssl/digest.h
@@ -90,6 +90,9 @@ OPENSSL_EXPORT const EVP_MD *EVP_blake2b256(void);

View File

@@ -48,6 +48,7 @@ worker_context_will_destroy.patch
frame_host_manager.patch
crashpad_pid_check.patch
network_service_allow_remote_certificate_verification_logic.patch
put_back_deleted_colors_for_autofill.patch
disable_color_correct_rendering.patch
add_contentgpuclient_precreatemessageloop_callback.patch
picture-in-picture.patch
@@ -63,6 +64,7 @@ allow_disabling_blink_scheduler_throttling_per_renderview.patch
hack_plugin_response_interceptor_to_point_to_electron.patch
feat_add_support_for_overriding_the_base_spellchecker_download_url.patch
feat_enable_offscreen_rendering_with_viz_compositor.patch
delay_lock_the_protocol_scheme_registry.patch
gpu_notify_when_dxdiag_request_fails.patch
feat_allow_embedders_to_add_observers_on_created_hunspell.patch
feat_add_onclose_to_messageport.patch
@@ -91,6 +93,8 @@ webview_fullscreen.patch
disable_unload_metrics.patch
fix_add_check_for_sandbox_then_result.patch
extend_apply_webpreferences.patch
add_setter_for_browsermainloop_result_code.patch
make_include_of_stack_trace_h_unconditional.patch
build_libc_as_static_library.patch
build_do_not_depend_on_packed_resource_integrity.patch
refactor_restore_base_adaptcallbackforrepeating.patch
@@ -103,13 +107,7 @@ chore_do_not_use_chrome_windows_in_cryptotoken_webrequestsender.patch
process_singleton.patch
fix_expose_decrementcapturercount_in_web_contents_impl.patch
add_ui_scopedcliboardwriter_writeunsaferawdata.patch
mas_gate_private_enterprise_APIs.patch
feat_add_data_parameter_to_processsingleton.patch
mas_gate_private_enterprise_APIs
load_v8_snapshot_in_browser_process.patch
fix_patch_out_permissions_checks_in_exclusive_access.patch
fix_aspect_ratio_with_max_size.patch
fix_dont_delete_SerialPortManager_on_main_thread.patch
feat_add_data_transfer_to_requestsingleinstancelock.patch
fix_crash_when_saving_edited_pdf_files.patch
port_autofill_colors_to_the_color_pipeline.patch
build_disable_partition_alloc_on_mac.patch
build_disable_thin_lto_on_mac.patch

View File

@@ -10,7 +10,7 @@ This patch makes three changes to Accelerator::GetShortcutText to improve shortc
3. Ctrl-Shift-= and Ctrl-Plus show up as such
diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc
index 2468b2c5881821d6f8e24a0e7c42243427b384ad..7e44c97edabf5ae012ff4f84d1404d8f223a13fe 100644
index d6913b15149f773cad28b5e2278b0f80df3d2896..25342f62acdc28806a0e6ae0bd129c59083ccf06 100644
--- a/ui/base/accelerators/accelerator.cc
+++ b/ui/base/accelerators/accelerator.cc
@@ -11,6 +11,7 @@
@@ -21,7 +21,7 @@ index 2468b2c5881821d6f8e24a0e7c42243427b384ad..7e44c97edabf5ae012ff4f84d1404d8f
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -238,6 +239,11 @@ std::u16string Accelerator::GetShortcutText() const {
@@ -234,6 +235,11 @@ std::u16string Accelerator::GetShortcutText() const {
#endif
if (shortcut.empty()) {
@@ -30,10 +30,10 @@ index 2468b2c5881821d6f8e24a0e7c42243427b384ad..7e44c97edabf5ae012ff4f84d1404d8f
+ if (shifted_char) {
+ shortcut += *shifted_char;
+ } else {
#if BUILDFLAG(IS_WIN)
#if defined(OS_WIN)
// Our fallback is to try translate the key code to a regular character
// unless it is one of digits (VK_0 to VK_9). Some keyboard
@@ -261,6 +267,10 @@ std::u16string Accelerator::GetShortcutText() const {
@@ -257,6 +263,10 @@ std::u16string Accelerator::GetShortcutText() const {
shortcut +=
static_cast<std::u16string::value_type>(base::ToUpperASCII(c));
#endif
@@ -43,8 +43,8 @@ index 2468b2c5881821d6f8e24a0e7c42243427b384ad..7e44c97edabf5ae012ff4f84d1404d8f
+ base::StringPrintf("F%d", key_code_ - VKEY_F1 + 1));
}
#if BUILDFLAG(IS_MAC)
@@ -451,7 +461,7 @@ std::u16string Accelerator::ApplyLongFormModifiers(
#if defined(OS_MAC)
@@ -444,7 +454,7 @@ std::u16string Accelerator::ApplyLongFormModifiers(
const std::u16string& shortcut) const {
std::u16string result = shortcut;
@@ -53,7 +53,7 @@ index 2468b2c5881821d6f8e24a0e7c42243427b384ad..7e44c97edabf5ae012ff4f84d1404d8f
result = ApplyModifierToAcceleratorString(result, IDS_APP_SHIFT_KEY);
// Note that we use 'else-if' in order to avoid using Ctrl+Alt as a shortcut.
@@ -459,7 +469,7 @@ std::u16string Accelerator::ApplyLongFormModifiers(
@@ -452,7 +462,7 @@ std::u16string Accelerator::ApplyLongFormModifiers(
// more information.
if (IsCtrlDown())
result = ApplyModifierToAcceleratorString(result, IDS_APP_CTRL_KEY);
@@ -63,7 +63,7 @@ index 2468b2c5881821d6f8e24a0e7c42243427b384ad..7e44c97edabf5ae012ff4f84d1404d8f
if (IsCmdDown()) {
diff --git a/ui/base/accelerators/accelerator.h b/ui/base/accelerators/accelerator.h
index e0d9df439d120c0a47f55666b3818c7ba6796e70..283c6283f5aeaae1a5436e5fbb17ce2db4a9034e 100644
index 780a45f9ca2dd60e0deac27cc6e8f69e72cd8435..b1b46f18e9c600820fdd2d26631eac38da672811 100644
--- a/ui/base/accelerators/accelerator.h
+++ b/ui/base/accelerators/accelerator.h
@@ -16,6 +16,7 @@
@@ -74,12 +74,12 @@ index e0d9df439d120c0a47f55666b3818c7ba6796e70..283c6283f5aeaae1a5436e5fbb17ce2d
#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/events/event_constants.h"
@@ -130,6 +131,8 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator {
@@ -129,6 +130,8 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator {
return interrupted_by_mouse_event_;
}
+ absl::optional<char16_t> shifted_char;
+
private:
friend class AcceleratorTestMac;
std::u16string ApplyLongFormModifiers(const std::u16string& shortcut) const;
std::u16string ApplyShortFormModifiers(const std::u16string& shortcut) const;

View File

@@ -10,10 +10,10 @@ Allows Electron to restore WER when ELECTRON_DEFAULT_ERROR_MODE is set.
This should be upstreamed.
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 9f840287967b50ec1db3a9d27973429ab231a486..731a279e395a8762a25a115665bff99be428de3d 100644
index 51b004f5e459eb265627c01e9e38acd655a65481..7140d92416709c467ae9b65860ac32947913989d 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -239,6 +239,10 @@ int GpuMain(MainFunctionParams parameters) {
@@ -239,6 +239,10 @@ int GpuMain(const MainFunctionParams& parameters) {
// to the GpuProcessHost once the GpuServiceImpl has started.
viz::GpuServiceImpl::InstallPreInitializeLogHandler();
@@ -24,8 +24,8 @@ index 9f840287967b50ec1db3a9d27973429ab231a486..731a279e395a8762a25a115665bff99b
// We are experiencing what appear to be memory-stomp issues in the GPU
// process. These issues seem to be impacting the task executor and listeners
// registered to it. Create the task executor on the heap to guard against
@@ -345,7 +349,6 @@ int GpuMain(MainFunctionParams parameters) {
GpuProcess gpu_process(io_thread_priority);
@@ -376,7 +380,6 @@ int GpuMain(const MainFunctionParams& parameters) {
}
#endif
- auto* client = GetContentClient()->gpu();
@@ -33,10 +33,10 @@ index 9f840287967b50ec1db3a9d27973429ab231a486..731a279e395a8762a25a115665bff99b
client->PostIOThreadCreated(gpu_process.io_task_runner());
diff --git a/content/public/gpu/content_gpu_client.h b/content/public/gpu/content_gpu_client.h
index 04274b751b498456fc4b269bfbc6399b4f27d3ed..2fb98baf0df4e191e5e18fd7055cc2d92a2156df 100644
index 864ad090cae17f6a93466f9d2ca52b63341f40da..391848e407f6bfcb7ba8f8a652bb062ebd16e697 100644
--- a/content/public/gpu/content_gpu_client.h
+++ b/content/public/gpu/content_gpu_client.h
@@ -29,6 +29,10 @@ class CONTENT_EXPORT ContentGpuClient {
@@ -28,6 +28,10 @@ class CONTENT_EXPORT ContentGpuClient {
public:
virtual ~ContentGpuClient() {}

View File

@@ -10,10 +10,10 @@ DidCreateScriptContext is called, not all JS APIs are available in the
context, which can cause some preload scripts to trip.
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index a92e09dc651a5f1a9bbae2572fad32233afcd46c..f99b652dda817b62615d2b3f00b4ae4b438ec44d 100644
index 94fbf201b82ac000ceac21685f09f68497be1350..70766b01824e63c45e5c035848e5814876956c77 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -129,6 +129,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
@@ -128,6 +128,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
virtual void DidHandleOnloadEvents() {}
virtual void DidCreateScriptContext(v8::Local<v8::Context> context,
int32_t world_id) {}
@@ -23,10 +23,10 @@ index a92e09dc651a5f1a9bbae2572fad32233afcd46c..f99b652dda817b62615d2b3f00b4ae4b
int32_t world_id) {}
virtual void DidClearWindowObject() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 4473c5e812a4a598f3e2f2bb06f78def5791af24..44c0ec9815aafd61182fd18a9d125e185d7196bc 100644
index 78ec20c40e5dbf7f706b57d9b810b4149510defc..900b8125f3fc6dcec4a1637fae6fcb2af40af5ab 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4455,6 +4455,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
@@ -4442,6 +4442,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
observer.DidCreateScriptContext(context, world_id);
}
@@ -40,10 +40,10 @@ index 4473c5e812a4a598f3e2f2bb06f78def5791af24..44c0ec9815aafd61182fd18a9d125e18
int world_id) {
for (auto& observer : observers_)
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 21b90bbb8fe8ddc03eb20538be423a5396d18eb3..f9c735038f733d990783dd66ffe8c74f824c78f2 100644
index 5f89641216bc467ea52619b1732c13174a16c723..061fc0c4a265335faccbf81594504eafabae77f8 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -597,6 +597,8 @@ class CONTENT_EXPORT RenderFrameImpl
@@ -601,6 +601,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 21b90bbb8fe8ddc03eb20538be423a5396d18eb3..f9c735038f733d990783dd66ffe8c74f
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 3d6e0c0395ff7c92d8908c5151b467beec3a7516..2fadd6d9b2e3747eacea08973d8d3c7aa9c15f26 100644
index 994841c02b0472e5239d9b73a07b2592a39df8be..ad19a3cddf200f6600a04c1136fd21218d496ba8 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -599,6 +599,9 @@ class BLINK_EXPORT WebLocalFrameClient {
@@ -596,6 +596,9 @@ class BLINK_EXPORT WebLocalFrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) {}
@@ -67,10 +67,10 @@ index 3d6e0c0395ff7c92d8908c5151b467beec3a7516..2fadd6d9b2e3747eacea08973d8d3c7a
virtual void WillReleaseScriptContext(v8::Local<v8::Context>,
int32_t world_id) {}
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
index aa4b510137d60e6fb924f4f1a6554fe06c19ad75..816b6260020a6cbb6880b0eed197743ccd9002f5 100644
index b0d5db60fbe57275dda835113b0fb21acb9a422f..b6c9c389943088004a419677a2a17be0c6ab6398 100644
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -205,6 +205,7 @@ void LocalWindowProxy::Initialize() {
@@ -201,6 +201,7 @@ void LocalWindowProxy::Initialize() {
}
InstallConditionalFeatures();
@@ -79,10 +79,10 @@ index aa4b510137d60e6fb924f4f1a6554fe06c19ad75..816b6260020a6cbb6880b0eed197743c
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 0dda1f7cd77c47f7e61ba48dd20429c13679b543..2f73aacda1bafe07775213e232eda56c4b33325b 100644
index 19a1ef792848026cb6a125124acd9e798e077e35..bb8220819750a6499568b64b49ca7710035d6092 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -308,6 +308,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
@@ -310,6 +310,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) = 0;
@@ -92,10 +92,10 @@ index 0dda1f7cd77c47f7e61ba48dd20429c13679b543..2f73aacda1bafe07775213e232eda56c
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 5297ad63f1c76240d57a64cc5ea64cbf8c7e1b95..006da6072db12da1632f9d45ecb5710136573641 100644
index 4b1bfb735082513071181f30e8e8af1b699847b1..21f6a54f0255df0d88894860da83b1459c3a378f 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
@@ -274,6 +274,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
@@ -273,6 +273,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
web_frame_->Client()->DidCreateScriptContext(context, world_id);
}
@@ -110,7 +110,7 @@ index 5297ad63f1c76240d57a64cc5ea64cbf8c7e1b95..006da6072db12da1632f9d45ecb57101
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 708414fca139eb8328e425d909a48ca97038e442..48b2a0e129ec166ebd4c9bbd32330b0cc43dbeb2 100644
index 45d493d7a9846c7f4ad567cec6d5fac4aadf9be3..23759d417d81d5bb6c920c94bacd66c303804319 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
@@ -78,6 +78,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
@@ -123,10 +123,10 @@ index 708414fca139eb8328e425d909a48ca97038e442..48b2a0e129ec166ebd4c9bbd32330b0c
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 4b639069d5d9173f0c35fe7656356031ba424a61..3da6699b40bf4f91e6d76a37e5fa8f680f7a7850 100644
index 0a4a0b8a4dc871dc86887774a6c81282ea98cda6..ab6ada68a78aa22e723080925d20cf14e8fe822a 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -357,6 +357,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
@@ -360,6 +360,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) override {}

View File

@@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samuel Attard <samuel.r.attard@gmail.com>
Date: Wed, 14 Apr 2021 17:19:23 -0700
Subject: add setter for BrowserMainLoop::result_code_
After a recent refactor
(https://chromium-review.googlesource.com/c/chromium/src/+/2725153) the
result_code_ pointer is no longer provided to embedders, but their are
valid use cases for setting custom exit codes of the main loop. This
exposes a simple setter that embedders can call.
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 2c13914c1fbf8b81b6b0dc5d059d48525ac9f059..1c6179a00f404cc8d19e47b2e1bb635a6893e751 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -165,6 +165,10 @@ class CONTENT_EXPORT BrowserMainLoop {
int GetResultCode() const { return result_code_; }
+ void SetResultCode(int code) {
+ result_code_ = code;
+ }
+
media::AudioManager* audio_manager() const;
bool AudioServiceOutOfProcess() const;
media::AudioSystem* audio_system() const { return audio_system_.get(); }

View File

@@ -8,12 +8,12 @@ was removed as part of the Raw Clipboard API scrubbing.
https://bugs.chromium.org/p/chromium/issues/detail?id=1217643
diff --git a/ui/base/clipboard/scoped_clipboard_writer.cc b/ui/base/clipboard/scoped_clipboard_writer.cc
index 3009acd40eee36bc3d4dd8642f0ce5e6476da973..1d52ce84184a3ca94e4e0f04d331bf56d75e07d0 100644
index 153f169d2cdef6f8a726c188283a5bc1b7395fa3..3a5d9ab8dafacafb1025e1cb8c157e8a82078424 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.cc
+++ b/ui/base/clipboard/scoped_clipboard_writer.cc
@@ -227,6 +227,16 @@ void ScopedClipboardWriter::WriteEncodedDataTransferEndpointForTesting(
@@ -212,6 +212,16 @@ void ScopedClipboardWriter::WriteData(const std::u16string& format,
}
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+void ScopedClipboardWriter::WriteUnsafeRawData(const std::u16string& format,
+ mojo_base::BigBuffer data) {
@@ -29,10 +29,10 @@ index 3009acd40eee36bc3d4dd8642f0ce5e6476da973..1d52ce84184a3ca94e4e0f04d331bf56
objects_.clear();
platform_representations_.clear();
diff --git a/ui/base/clipboard/scoped_clipboard_writer.h b/ui/base/clipboard/scoped_clipboard_writer.h
index c47909313da0d7cd8a2b3cd670327011af66e3fb..0d259c21507f38124dfa46aceeacfda76cfd4a38 100644
index 879acd4f6f0101a6da3af58d78eeda877ea41a4a..4d4149b6aa34c7073804994cb1c03368830c736d 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.h
+++ b/ui/base/clipboard/scoped_clipboard_writer.h
@@ -84,6 +84,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
@@ -80,6 +80,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
// This is only used to write custom format data.
void WriteData(const std::u16string& format, mojo_base::BigBuffer data);
@@ -42,4 +42,4 @@ index c47909313da0d7cd8a2b3cd670327011af66e3fb..0d259c21507f38124dfa46aceeacfda7
+
void WriteImage(const SkBitmap& bitmap);
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// Mark the data to be written as confidential.

View File

@@ -6,10 +6,10 @@ Subject: allow disabling blink scheduler throttling per RenderView
This allows us to disable throttling for hidden windows.
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 56c08919ab626a8a7b3bcb892ee94cdee2a106fc..b85bdf4ed574a149a6502e8d21e54f2ee80777a5 100644
index 21cbb423d083a985b288c0b040cdd8ae7df56222..ca83e01e82bd55b2c7aaee2361493776b458ebac 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -647,6 +647,11 @@ void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
@@ -630,6 +630,11 @@ void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
GetWidget()->GetAssociatedFrameWidget()->SetBackgroundOpaque(opaque);
}
@@ -22,7 +22,7 @@ index 56c08919ab626a8a7b3bcb892ee94cdee2a106fc..b85bdf4ed574a149a6502e8d21e54f2e
return is_active();
}
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 9e32df9f5fd765895c8470c3922a62f754e7d409..9bac2321d65d9e54ce88fffafd72a74803ed2c87 100644
index 9760b7657584b81558a7dbba03258baaee2471fd..53cf6282bfe5a1f1b98a001e1aa82eb45fcb2252 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -135,6 +135,7 @@ class CONTENT_EXPORT RenderViewHostImpl
@@ -34,10 +34,10 @@ index 9e32df9f5fd765895c8470c3922a62f754e7d409..9bac2321d65d9e54ce88fffafd72a748
void SendRendererPreferencesToRenderer(
const blink::RendererPreferences& preferences);
diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h
index 787077d71c04d571aa825bec0a549c5fad2b8574..4b05b80802ba97a46eed60e509b503fc8375016b 100644
index 8bb06dec16fbf205230a10e0e52daa787338bc23..9ebc42788391e838e78af75e2449dde4f1107f22 100644
--- a/content/public/browser/render_view_host.h
+++ b/content/public/browser/render_view_host.h
@@ -74,6 +74,9 @@ class CONTENT_EXPORT RenderViewHost {
@@ -84,6 +84,9 @@ class CONTENT_EXPORT RenderViewHost {
// Write a representation of this object into a trace.
virtual void WriteIntoTrace(perfetto::TracedValue context) = 0;
@@ -48,10 +48,10 @@ index 787077d71c04d571aa825bec0a549c5fad2b8574..4b05b80802ba97a46eed60e509b503fc
// This interface should only be implemented inside content.
friend class RenderViewHostImpl;
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 4e8d36420d6edc1725a840e1b9f123041d21abe4..dd198cb7bf02e509833c6b4c7d8e5d65d20d46dc 100644
index 604edaea033172123d1e7d9c5512bebf55738db5..93b06e71dae1b9c01463c8b26b74516bad7d5b6d 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -152,6 +152,8 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
@@ -150,6 +150,8 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
static WindowOpenDisposition NavigationPolicyToDisposition(
blink::WebNavigationPolicy policy);
@@ -61,10 +61,10 @@ index 4e8d36420d6edc1725a840e1b9f123041d21abe4..dd198cb7bf02e509833c6b4c7d8e5d65
// ADDING NEW FUNCTIONS? Please keep private functions alphabetized and put
// it in the same order in the .cc file as it was in the header.
diff --git a/third_party/blink/public/mojom/page/page.mojom b/third_party/blink/public/mojom/page/page.mojom
index befd736a9cf362514b9a2ee475dc4a814c85a87b..24b2617f56673a3075697802cf5b574b0c766610 100644
index df834821bd082b92a9b4bd0858d900f554469afe..1e3b281eab8de5d3ab46a01d520737ecc477c3ff 100644
--- a/third_party/blink/public/mojom/page/page.mojom
+++ b/third_party/blink/public/mojom/page/page.mojom
@@ -97,4 +97,7 @@ interface PageBroadcast {
@@ -91,4 +91,7 @@ interface PageBroadcast {
// Sent to whole page, but should only be used by the main frame.
SetPageBaseBackgroundColor(skia.mojom.SkColor? color);
@@ -73,10 +73,10 @@ index befd736a9cf362514b9a2ee475dc4a814c85a87b..24b2617f56673a3075697802cf5b574b
+ SetSchedulerThrottling(bool allowed);
};
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h
index 14d4a00293ab0b11e733676844ce483992d6cd8e..c6c2dbb9dddd1eaa21e8c7b276d871a3898463fa 100644
index f54b993e9fb9fedcedef327290c2e5d706c699a7..73874e124e2810f07b72fc094f57c85c0fcf1dbb 100644
--- a/third_party/blink/public/web/web_view.h
+++ b/third_party/blink/public/web/web_view.h
@@ -368,6 +368,7 @@ class WebView {
@@ -366,6 +366,7 @@ class WebView {
// Scheduling -----------------------------------------------------------
virtual PageScheduler* Scheduler() const = 0;
@@ -85,10 +85,10 @@ index 14d4a00293ab0b11e733676844ce483992d6cd8e..c6c2dbb9dddd1eaa21e8c7b276d871a3
// Visibility -----------------------------------------------------------
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 8cdffac8ecb9ed2c6892f1e975a953846e7e3a5c..7e7927c7258963bd95a2c064ef85e410f4d2571d 100644
index 44474a8e56c5f1751e395f375cedb39656f6d5a8..baf07861d4be89485605f87d344fcffdd220a063 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -3659,6 +3659,13 @@ PageScheduler* WebViewImpl::Scheduler() const {
@@ -3630,6 +3630,13 @@ PageScheduler* WebViewImpl::Scheduler() const {
return GetPage()->GetPageScheduler();
}
@@ -102,7 +102,7 @@ index 8cdffac8ecb9ed2c6892f1e975a953846e7e3a5c..7e7927c7258963bd95a2c064ef85e410
void WebViewImpl::SetVisibilityState(
mojom::blink::PageVisibilityState visibility_state,
bool is_initial_state) {
@@ -3670,7 +3677,8 @@ void WebViewImpl::SetVisibilityState(
@@ -3641,7 +3648,8 @@ void WebViewImpl::SetVisibilityState(
}
GetPage()->SetVisibilityState(visibility_state, is_initial_state);
GetPage()->GetPageScheduler()->SetPageVisible(
@@ -113,10 +113,10 @@ index 8cdffac8ecb9ed2c6892f1e975a953846e7e3a5c..7e7927c7258963bd95a2c064ef85e410
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 5107ef421138e136b20b25b7bbcc1f0bb246bb66..043266205142e59f88c4c2f2ae6b58bb009f2d9c 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
@@ -420,6 +420,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 5107ef421138e136b20b25b7bbcc1f0bb246bb66..043266205142e59f88c4c2f2ae6b58bb
void SetVisibilityState(mojom::blink::PageVisibilityState visibility_state,
bool is_initial_state) override;
mojom::blink::PageVisibilityState GetVisibilityState() override;
@@ -857,6 +858,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;

View File

@@ -8,19 +8,21 @@ WebPreferences of in-process child windows, rather than relying on
process-level command line switches, as before.
diff --git a/third_party/blink/common/web_preferences/web_preferences.cc b/third_party/blink/common/web_preferences/web_preferences.cc
index 30e237f886b41bdf528b2a0e81054d15fb323f1f..43f7920cf6ff12d8a48ddef5440814a42266e8c5 100644
index 8eb1bca3638678041a8ed739cfe3907406455ac2..0d05d32420590a1a589f23aa468086f142cbb45f 100644
--- a/third_party/blink/common/web_preferences/web_preferences.cc
+++ b/third_party/blink/common/web_preferences/web_preferences.cc
@@ -145,6 +145,20 @@ WebPreferences::WebPreferences()
@@ -145,6 +145,22 @@ WebPreferences::WebPreferences()
fake_no_alloc_direct_call_for_testing_enabled(false),
v8_cache_options(blink::mojom::V8CacheOptions::kDefault),
record_whole_document(false),
+ // Begin Electron-specific WebPreferences.
+ opener_id(0),
+ context_isolation(false),
+ is_webview(false),
+ hidden_page(false),
+ offscreen(false),
+ preload(base::FilePath::StringType()),
+ native_window_open(false),
+ node_integration(false),
+ node_integration_in_worker(false),
+ node_integration_in_sub_frames(false),
@@ -33,13 +35,13 @@ index 30e237f886b41bdf528b2a0e81054d15fb323f1f..43f7920cf6ff12d8a48ddef5440814a4
accelerated_video_decode_enabled(false),
animation_policy(
diff --git a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
index d278453a261fe2dd3bacce433e35d50879b555a7..140f8d6273d944bfe36831d27aef757d89240b56 100644
index a264ef99beb81dd6b1f55c1b0f57f6055b4ab771..16b734cb371d22dbe99b4ae397126f240b9f686c 100644
--- a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
+++ b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
@@ -22,6 +22,10 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
!data.ReadSansSerifFontFamilyMap(&out->sans_serif_font_family_map) ||
@@ -23,6 +23,10 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
!data.ReadCursiveFontFamilyMap(&out->cursive_font_family_map) ||
!data.ReadFantasyFontFamilyMap(&out->fantasy_font_family_map) ||
!data.ReadPictographFontFamilyMap(&out->pictograph_font_family_map) ||
+ // Begin Electron-specific WebPreferences.
+ !data.ReadPreloads(&out->preloads) ||
+ !data.ReadPreload(&out->preload) ||
@@ -47,15 +49,17 @@ index d278453a261fe2dd3bacce433e35d50879b555a7..140f8d6273d944bfe36831d27aef757d
!data.ReadLazyFrameLoadingDistanceThresholdsPx(
&out->lazy_frame_loading_distance_thresholds_px) ||
!data.ReadLazyImageLoadingDistanceThresholdsPx(
@@ -151,6 +155,19 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
@@ -156,6 +160,21 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
data.fake_no_alloc_direct_call_for_testing_enabled();
out->v8_cache_options = data.v8_cache_options();
out->record_whole_document = data.record_whole_document();
+ // Begin Electron-specific WebPreferences.
+ out->opener_id = data.opener_id();
+ out->context_isolation = data.context_isolation();
+ out->is_webview = data.is_webview();
+ out->hidden_page = data.hidden_page();
+ out->offscreen = data.offscreen();
+ out->native_window_open = data.native_window_open();
+ out->node_integration = data.node_integration();
+ out->node_integration_in_worker = data.node_integration_in_worker();
+ out->node_integration_in_sub_frames = data.node_integration_in_sub_frames();
@@ -68,7 +72,7 @@ index d278453a261fe2dd3bacce433e35d50879b555a7..140f8d6273d944bfe36831d27aef757d
out->accelerated_video_decode_enabled =
data.accelerated_video_decode_enabled();
diff --git a/third_party/blink/public/common/web_preferences/web_preferences.h b/third_party/blink/public/common/web_preferences/web_preferences.h
index 8509f720c5afb816c6cbb2313dd566a24236a790..b9f0f79d96c58a7769939610bb72f8b2bcd3be94 100644
index 4517bf43c1b80f1aa0f3ba8e67e78b8b91e19f8a..5dc73459f424ad0a01b4ea18e4de196e20d24ae5 100644
--- a/third_party/blink/public/common/web_preferences/web_preferences.h
+++ b/third_party/blink/public/common/web_preferences/web_preferences.h
@@ -10,6 +10,7 @@
@@ -79,17 +83,19 @@ index 8509f720c5afb816c6cbb2313dd566a24236a790..b9f0f79d96c58a7769939610bb72f8b2
#include "net/nqe/effective_connection_type.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-shared.h"
@@ -160,6 +161,22 @@ struct BLINK_COMMON_EXPORT WebPreferences {
@@ -162,6 +163,24 @@ struct BLINK_COMMON_EXPORT WebPreferences {
blink::mojom::V8CacheOptions v8_cache_options;
bool record_whole_document;
+ // Begin Electron-specific WebPreferences.
+ std::vector<base::FilePath> preloads;
+ int opener_id;
+ bool context_isolation;
+ bool is_webview;
+ bool hidden_page;
+ bool offscreen;
+ base::FilePath preload;
+ bool native_window_open;
+ bool node_integration;
+ bool node_integration_in_worker;
+ bool node_integration_in_sub_frames;
@@ -103,7 +109,7 @@ index 8509f720c5afb816c6cbb2313dd566a24236a790..b9f0f79d96c58a7769939610bb72f8b2
// only controls whether or not the "document.cookie" field is properly
// connected to the backing store, for instance if you wanted to be able to
diff --git a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
index a6291be3e953ceaee1d996e4b30a6ae78916bc7a..c3baf95c5d9b6a6ace56bcde9e1dc8179f18eaa0 100644
index 9dbbb581a8876430c3e0a39df1ff655d3ddc6d2d..98c5c4ac5ee3130581c8576e5ef810a78939f50e 100644
--- a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
+++ b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
@@ -6,6 +6,7 @@
@@ -114,7 +120,7 @@ index a6291be3e953ceaee1d996e4b30a6ae78916bc7a..c3baf95c5d9b6a6ace56bcde9e1dc817
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/nqe/effective_connection_type.h"
#include "third_party/blink/public/common/common_export.h"
@@ -441,6 +442,60 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
@@ -451,6 +452,68 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
return r.record_whole_document;
}
@@ -123,6 +129,10 @@ index a6291be3e953ceaee1d996e4b30a6ae78916bc7a..c3baf95c5d9b6a6ace56bcde9e1dc817
+ return r.preloads;
+ }
+
+ static int opener_id(const blink::web_pref::WebPreferences& r) {
+ return r.opener_id;
+ }
+
+ static bool context_isolation(const blink::web_pref::WebPreferences& r) {
+ return r.context_isolation;
+ }
@@ -143,6 +153,10 @@ index a6291be3e953ceaee1d996e4b30a6ae78916bc7a..c3baf95c5d9b6a6ace56bcde9e1dc817
+ return r.preload;
+ }
+
+ static bool native_window_open(const blink::web_pref::WebPreferences& r) {
+ return r.native_window_open;
+ }
+
+ static bool node_integration(const blink::web_pref::WebPreferences& r) {
+ return r.node_integration;
+ }
@@ -176,7 +190,7 @@ index a6291be3e953ceaee1d996e4b30a6ae78916bc7a..c3baf95c5d9b6a6ace56bcde9e1dc817
return r.cookie_enabled;
}
diff --git a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
index 96dd9fd56e44e66c5ea24d9df7c6cbff25409d6c..e0d113b4dee6a72f350b8494448f516be01d0468 100644
index eaecb8c2b7dadaf7650bc8ac85cbad4383035e67..64d83af36d384d2eb7fdd89a3a0d3665a40354a1 100644
--- a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
+++ b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
@@ -10,6 +10,7 @@ import "third_party/blink/public/mojom/v8_cache_options.mojom";
@@ -187,17 +201,19 @@ index 96dd9fd56e44e66c5ea24d9df7c6cbff25409d6c..e0d113b4dee6a72f350b8494448f516b
enum PointerType {
kPointerNone = 1, // 1 << 0
@@ -212,6 +213,22 @@ struct WebPreferences {
@@ -214,6 +215,24 @@ struct WebPreferences {
V8CacheOptions v8_cache_options;
bool record_whole_document;
+ // Begin Electron-specific WebPreferences.
+ array<mojo_base.mojom.FilePath> preloads;
+ int32 opener_id;
+ bool context_isolation;
+ bool is_webview;
+ bool hidden_page;
+ bool offscreen;
+ mojo_base.mojom.FilePath preload;
+ bool native_window_open;
+ bool node_integration;
+ bool node_integration_in_worker;
+ bool node_integration_in_sub_frames;

View File

@@ -6,7 +6,7 @@ Subject: allow new privileges in unsandboxed child processes
This allows unsandboxed renderers to launch setuid processes on Linux.
diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
index f60ad777ab7698a4518d3b1b61ade29e7c618a3a..c7781bdb49f8a92aa9ee1d8dd1af03fa9cf2dfe3 100644
index bbc1d4d057291cc4a3c65287309a22897179a47e..6318b1f2251670d5dd975fde695ee2438c456a0f 100644
--- a/content/browser/child_process_launcher_helper_linux.cc
+++ b/content/browser/child_process_launcher_helper_linux.cc
@@ -53,6 +53,18 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(

View File

@@ -6,7 +6,7 @@ Subject: Allow setting secondary label via SimpleMenuModel
Builds on https://chromium-review.googlesource.com/c/chromium/src/+/2208976
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc
index 746dffb1defec9d776f681d41325a65b02cbdd0f..05a7f20f10e3ff514aa3b3b5386980ddfcc586eb 100644
index 1bfe8fb90673a0d0f9f9228a43eafc3b01b00c5f..1484fc4e477b97b6deb8e23b8a749264990cc1c6 100644
--- a/ui/base/models/simple_menu_model.cc
+++ b/ui/base/models/simple_menu_model.cc
@@ -53,6 +53,11 @@ std::u16string SimpleMenuModel::Delegate::GetLabelForCommandId(
@@ -47,10 +47,10 @@ index 746dffb1defec9d776f681d41325a65b02cbdd0f..05a7f20f10e3ff514aa3b3b5386980dd
return items_[ValidateItemIndex(index)].minor_text;
}
diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h
index bd2ebaf9f84946c708eba13c18869afadd2fdbb0..880d6f12ad188c5f8abf037b3b8d27fcf1fc2cb6 100644
index 60a5e6490d5153772c28551a160ac7c95a744279..e04f0e4d6f9d54cb6b50346ddcbbd16f73135db6 100644
--- a/ui/base/models/simple_menu_model.h
+++ b/ui/base/models/simple_menu_model.h
@@ -49,6 +49,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
@@ -50,6 +50,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
// Some command ids have labels and icons that change over time.
virtual bool IsItemForCommandIdDynamic(int command_id) const;
virtual std::u16string GetLabelForCommandId(int command_id) const;
@@ -58,7 +58,7 @@ index bd2ebaf9f84946c708eba13c18869afadd2fdbb0..880d6f12ad188c5f8abf037b3b8d27fc
// Gets the icon for the item with the specified id.
virtual ImageModel GetIconForCommandId(int command_id) const;
@@ -160,6 +161,9 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
@@ -161,6 +162,9 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
// Sets the label for the item at |index|.
void SetLabel(int index, const std::u16string& label);
@@ -68,7 +68,7 @@ index bd2ebaf9f84946c708eba13c18869afadd2fdbb0..880d6f12ad188c5f8abf037b3b8d27fc
// Sets the minor text for the item at |index|.
void SetMinorText(int index, const std::u16string& minor_text);
@@ -199,6 +203,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
@@ -200,6 +204,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override;
int GetCommandIdAt(int index) const override;
std::u16string GetLabelAt(int index) const override;
@@ -76,7 +76,7 @@ index bd2ebaf9f84946c708eba13c18869afadd2fdbb0..880d6f12ad188c5f8abf037b3b8d27fc
std::u16string GetMinorTextAt(int index) const override;
ImageModel GetMinorIconAt(int index) const override;
bool IsItemDynamicAt(int index) const override;
@@ -238,6 +243,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
@@ -239,6 +244,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
int command_id = 0;
ItemType type = TYPE_COMMAND;
std::u16string label;

View File

@@ -7,10 +7,10 @@ This is used by editors to obtain the filesystem path from a dragged file. See
documentation at https://electronjs.org/docs/api/file-object
diff --git a/third_party/blink/renderer/core/fileapi/file.h b/third_party/blink/renderer/core/fileapi/file.h
index 72d6b7e109779c9785130ebb0e1e23202c5bc68d..e12c4acfd87f1d698d7c8c8459e7231ee03789fd 100644
index d70a95cc9b28674dd4ac925e9f1aca481e60c34b..fa9d21a20e77867a7d596e0df4ec143edb871f27 100644
--- a/third_party/blink/renderer/core/fileapi/file.h
+++ b/third_party/blink/renderer/core/fileapi/file.h
@@ -212,6 +212,9 @@ class CORE_EXPORT File final : public Blob {
@@ -191,6 +191,9 @@ class CORE_EXPORT File final : public Blob {
}
const String& name() const { return name_; }

View File

@@ -15,7 +15,7 @@ Refs changes in:
This patch reverts the changes to fix associated crashes in Electron.
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc
index 2b0c8720866b45c2a83d639533cb4c3e5dbb70e0..97c251cdc310eb22859efb1ba3ca6312a3236fa5 100644
index 58622d645f657dbb08489a5202df3dfe6c7a85ce..af2ad009f9f14fad2d18b39198b100ee0dafa556 100644
--- a/third_party/blink/renderer/core/frame/frame.cc
+++ b/third_party/blink/renderer/core/frame/frame.cc
@@ -122,14 +122,6 @@ bool Frame::Detach(FrameDetachType type) {
@@ -33,7 +33,7 @@ index 2b0c8720866b45c2a83d639533cb4c3e5dbb70e0..97c251cdc310eb22859efb1ba3ca6312
if (type == FrameDetachType::kRemove) {
if (provisional_frame_) {
provisional_frame_->Detach(FrameDetachType::kRemove);
@@ -153,6 +145,14 @@ bool Frame::Detach(FrameDetachType type) {
@@ -152,6 +144,14 @@ bool Frame::Detach(FrameDetachType type) {
GetWindowProxyManager()->ClearForSwap();
}
@@ -49,10 +49,10 @@ index 2b0c8720866b45c2a83d639533cb4c3e5dbb70e0..97c251cdc310eb22859efb1ba3ca6312
// 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 db69148e0756ed36bcf3a04f1ace69cc166261a6..bcf072a6d8bc46e5c71d9ef3f248b6af69693ac9 100644
index cc3b5af94302c43f1eca0bcb3b765befcea7d300..c6507f83c1d11f09967a6186e895bc86c6f01a61 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -538,10 +538,6 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
@@ -578,10 +578,6 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
}
DCHECK(!view_ || !view_->IsAttached());
@@ -63,7 +63,7 @@ index db69148e0756ed36bcf3a04f1ace69cc166261a6..bcf072a6d8bc46e5c71d9ef3f248b6af
if (!Client())
return false;
@@ -587,6 +583,11 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
@@ -628,6 +624,11 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
DCHECK(!view_->IsAttached());
Client()->WillBeDetached();

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