Compare commits

..

1 Commits

Author SHA1 Message Date
Keeley Hammond
9dd24d7f57 build: revert DomainIs refactor 2024-10-08 13:54:01 -07:00
48 changed files with 280 additions and 422 deletions

View File

@@ -146,21 +146,17 @@ jobs:
sudo security authorizationdb write com.apple.trust-settings.admin allow
cd src/electron
./script/codesign/generate-identity.sh
- name: Install Datadog CLI
run: |
cd src/electron
node script/yarn global add @datadog/datadog-ci
- name: Run Electron Tests
shell: bash
env:
MOCHA_REPORTER: mocha-multi-reporters
ELECTRON_TEST_RESULTS_DIR: junit
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
DISPLAY: ':99.0'
run: |
cd src/electron
export ELECTRON_TEST_RESULTS_DIR=`pwd`/junit
# Get which tests are on this shard
tests_files=$(node script/split-tests ${{ matrix.shard }} ${{ inputs.target-platform == 'macos' && 2 || 3 }})
@@ -189,18 +185,6 @@ jobs:
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn test --runners=main --trace-uncaught --enable-logging --files $tests_files
fi
fi
- name: Upload Test results to Datadog
env:
DD_ENV: ci
DD_SERVICE: electron
DD_API_KEY: ${{ secrets.DD_API_KEY }}
DD_CIVISIBILITY_LOGS_ENABLED: true
DD_TAGS: "os.architecture:${{ inputs.target-arch }},os.family:${{ inputs.target-platform }},os.platform:${{ inputs.target-platform }},asan:${{ inputs.is-asan }}"
run: |
if ! [ -z $DD_API_KEY ]; then
datadog-ci junit upload src/electron/junit/test-results-main.xml
fi
if: always() && !cancelled()
- name: Upload Test Artifacts
if: always() && !cancelled()
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874

2
DEPS
View File

@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
vars = {
'chromium_version':
'130.0.6723.44',
'130.0.6723.31',
'node_version':
'v20.18.0',
'nan_version':

View File

@@ -36,7 +36,7 @@ environment:
ELECTRON_ENABLE_STACK_DUMPING: 1
ELECTRON_ALSO_LOG_TO_STDERR: 1
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, mocha-junit-reporter, tap"
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
GYP_MSVS_HASH_7393122652: 3ba76c5c20
@@ -45,16 +45,10 @@ environment:
matrix:
- job_name: Build Arm on X64 Windows
- job_name: Test On Windows On Arm Hardware 1
- job_name: Test On Windows On Arm Hardware
job_depends_on: Build Arm on X64 Windows
APPVEYOR_BUILD_WORKER_IMAGE: base-woa
APPVEYOR_BUILD_WORKER_CLOUD: electronhq-woa
shard: 1
- job_name: Test On Windows On Arm Hardware 2
job_depends_on: Build Arm on X64 Windows
APPVEYOR_BUILD_WORKER_IMAGE: base-woa
APPVEYOR_BUILD_WORKER_CLOUD: electronhq-woa
shard: 2
clone_script:
- ps: git clone -q $("--branch=" + $Env:APPVEYOR_REPO_BRANCH) $("https://github.com/" + $Env:APPVEYOR_REPO_NAME + ".git") $Env:APPVEYOR_BUILD_FOLDER
@@ -260,19 +254,14 @@ for:
}
- matrix:
only:
- job_name: Test On Windows On Arm Hardware 1
- job_name: Test On Windows On Arm Hardware 2
- job_name: Test On Windows On Arm Hardware
environment:
IGNORE_YARN_INSTALL_ERROR: 1
ELECTRON_TEST_RESULTS_DIR: C:\projects\src\electron\junit
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, mocha-junit-reporter, tap"
ELECTRON_TEST_RESULTS_DIR: junit
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
MOCHA_REPORTER: mocha-multi-reporters
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
DD_ENV: ci
DD_SERVICE: electron
DD_CIVISIBILITY_LOGS_ENABLED: true
DD_GIT_REPOSITORY_URL: "https://github.com/electron/electron.git"
build_script:
- ps: |
@@ -284,7 +273,6 @@ for:
} else {
$global:LASTEXITCODE = 0
}
- ps: Invoke-WebRequest -Uri "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_win-x64" -OutFile "C:\projects\src\electron\datadog-ci.exe"
- cd ..
- mkdir out\Default
- cd ..
@@ -333,22 +321,10 @@ for:
if ($env:TARGET_ARCH -eq 'ia32') {
$env:npm_config_arch = "ia32"
}
- ps: $env:tests_files=node script\split-tests $env:shard 2
- echo "Running shard %shard% specs %tests_files%"
- echo Running main test suite & node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion --files %tests_files%
- echo Running main test suite & node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
- cd ..
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
on_finish:
# Uncomment these lines to enable RDP
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- if exist electron\junit\test-results-main.xml ( appveyor-retry appveyor PushArtifact electron\junit\test-results-main.xml )
- ps: |
if ($env:DD_API_KEY) {
$env:DD_GIT_COMMIT_SHA = $env:APPVEYOR_REPO_COMMIT
$env:DD_GIT_BRANCH = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH
$env:DD_TAGS = "os.architecture:$env:TARGET_ARCH,os.family:windows,os.platform:win32"
if (Test-Path -Path "C:\projects\src\electron\junit\test-results-main.xml") {
C:\projects\src\electron\datadog-ci.exe junit upload --verbose C:\projects\src\electron\junit\test-results-main.xml
}
}

View File

@@ -36,7 +36,7 @@ environment:
ELECTRON_ENABLE_STACK_DUMPING: 1
ELECTRON_ALSO_LOG_TO_STDERR: 1
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, mocha-junit-reporter, tap"
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
GYP_MSVS_HASH_7393122652: 3ba76c5c20
@@ -45,12 +45,8 @@ environment:
matrix:
- job_name: Build
- job_name: Test 1
- job_name: Test
job_depends_on: Build
shard: 1
- job_name: Test 2
job_depends_on: Build
shard: 2
clone_script:
- ps: git clone -q $("--branch=" + $Env:APPVEYOR_REPO_BRANCH) $("https://github.com/" + $Env:APPVEYOR_REPO_NAME + ".git") $Env:APPVEYOR_BUILD_FOLDER
@@ -250,15 +246,7 @@ for:
}
- matrix:
only:
- job_name: Test 1
- job_name: Test 2
environment:
DD_ENV: ci
DD_SERVICE: electron
DD_CIVISIBILITY_LOGS_ENABLED: true
DD_GIT_REPOSITORY_URL: "https://github.com/electron/electron.git"
ELECTRON_TEST_RESULTS_DIR: C:\projects\src\electron\junit
- job_name: Test
init:
- ps: |
@@ -275,7 +263,6 @@ for:
} else {
$global:LASTEXITCODE = 0
}
- npm install -g @datadog/datadog-ci
- cd ..
- mkdir out\Default
- cd ..
@@ -321,9 +308,7 @@ for:
if ($env:TARGET_ARCH -eq 'ia32') {
$env:npm_config_arch = "ia32"
}
- ps: $env:tests_files=node script\split-tests $env:shard 2
- echo "Running shard %shard% specs %tests_files%"
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging --files %tests_files%
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging
- cd ..
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
- echo "About to verify mksnapshot"
@@ -335,13 +320,3 @@ for:
on_finish:
# Uncomment these lines to enable RDP
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- if exist electron\junit\test-results-main.xml ( appveyor-retry appveyor PushArtifact electron\junit\test-results-main.xml )
- ps: |
if ($env:RUN_TESTS -eq 'true' -And $env:DD_API_KEY) {
$env:DD_GIT_COMMIT_SHA = $env:APPVEYOR_REPO_COMMIT
$env:DD_GIT_BRANCH = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH
$env:DD_TAGS = "os.architecture:$env:TARGET_ARCH,os.family:windows,os.platform:win32"
if (Test-Path -Path "C:\projects\src\electron\junit\test-results-main.xml") {
C:\Users\appveyor\AppData\Roaming\npm\datadog-ci.ps1 junit upload --verbose C:\projects\src\electron\junit\test-results-main.xml
}
}

View File

@@ -127,9 +127,6 @@ Returns:
Emitted when the child process needs to terminate due to non continuable error from V8.
No matter if you listen to the `error` event, the `exit` event will be emitted after the
child process terminates.
#### Event: 'exit'
Returns:

View File

@@ -9,11 +9,10 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
| 34.0.0 | 2024-Oct-17 | 2024-Nov-13 | 2024-Jan-07 | 2025-Jun-24 | M132 | TBD | ✅ |
| 33.0.0 | 2024-Aug-22 | 2024-Sep-18 | 2024-Oct-15 | 2025-Apr-29 | M130 | v20.18 | ✅ |
| 33.0.0 | 2024-Aug-22 | 2024-Sep-18 | 2024-Oct-15 | 2025-Apr-29 | M130 | TBD | ✅ |
| 32.0.0 | 2024-Jun-14 | 2024-Jul-24 | 2024-Aug-20 | 2025-Mar-04 | M128 | v20.16 | ✅ |
| 31.0.0 | 2024-Apr-18 | 2024-May-15 | 2024-Jun-11 | 2025-Jan-07 | M126 | v20.14 | ✅ |
| 30.0.0 | 2024-Feb-22 | 2024-Mar-20 | 2024-Apr-16 | 2024-Oct-15 | M124 | v20.11 | 🚫 |
| 30.0.0 | 2024-Feb-22 | 2024-Mar-20 | 2024-Apr-16 | 2024-Oct-15 | M124 | v20.11 | |
| 29.0.0 | 2023-Dec-07 | 2024-Jan-24 | 2024-Feb-20 | 2024-Aug-20 | M122 | v20.9 | 🚫 |
| 28.0.0 | 2023-Oct-11 | 2023-Nov-06 | 2023-Dec-05 | 2024-Jun-11 | M120 | v18.18 | 🚫 |
| 27.0.0 | 2023-Aug-17 | 2023-Sep-13 | 2023-Oct-10 | 2024-Apr-16 | M118 | v18.17 | 🚫 |

View File

@@ -680,8 +680,8 @@ filenames = {
"shell/common/skia_util.cc",
"shell/common/skia_util.h",
"shell/common/thread_restrictions.h",
"shell/common/v8_util.cc",
"shell/common/v8_util.h",
"shell/common/v8_value_serializer.cc",
"shell/common/v8_value_serializer.h",
"shell/common/world_ids.h",
"shell/renderer/api/context_bridge/object_cache.cc",
"shell/renderer/api/context_bridge/object_cache.h",

View File

@@ -130,3 +130,4 @@ chore_remove_reference_to_chrome_browser_themes.patch
feat_enable_customizing_symbol_color_in_framecaptionbutton.patch
build_expose_webplugininfo_interface_to_electron.patch
feat_allow_usage_of_sccontentsharingpicker_on_supported_platforms.patch
feat_allow_-4_as_a_macos_screen_share_id.patch

View File

@@ -23,10 +23,10 @@ index ad0092ef2e13853e4bb8b923481559a043b00ab7..1c2dfd23f18733e21312992877ae1499
int32_t world_id) {}
virtual void DidClearWindowObject() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 24904d0b6436353601aa43c603f9d12fb8eff960..a673c3c00bc59e3bd8b0ed2ecb086856f57134ac 100644
index 724818204a4fa1578102c2fe1a8877735323595a..954fdbbdd4d07c32d6fe78632ca95efc29fadc3c 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4794,6 +4794,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
@@ -4791,6 +4791,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
observer.DidCreateScriptContext(context, world_id);
}

View File

@@ -15,10 +15,10 @@ 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 2f33ec660a975522c473ecd50e633b5edaca707f..65221a51927d9f44bd6adbad88fa1144f2db3add 100644
index 6210eae2b7c25dae24ad7087d3e0ac494dada375..934ee55c89c526ca8fa390a13c4dd79b1c85882f 100644
--- a/third_party/blink/renderer/core/frame/frame.cc
+++ b/third_party/blink/renderer/core/frame/frame.cc
@@ -135,14 +135,6 @@ bool Frame::Detach(FrameDetachType type) {
@@ -131,14 +131,6 @@ bool Frame::Detach(FrameDetachType type) {
DCHECK(!IsDetached());
@@ -33,7 +33,7 @@ index 2f33ec660a975522c473ecd50e633b5edaca707f..65221a51927d9f44bd6adbad88fa1144
if (type == FrameDetachType::kRemove) {
if (provisional_frame_) {
provisional_frame_->Detach(FrameDetachType::kRemove);
@@ -166,6 +158,14 @@ bool Frame::Detach(FrameDetachType type) {
@@ -162,6 +154,14 @@ bool Frame::Detach(FrameDetachType type) {
GetWindowProxyManager()->ClearForSwap();
}

View File

@@ -33,7 +33,7 @@ index ad7aef003b233245201937c58be12fa3acb6b1a4..275eb74983e684310753dabcd453e5a2
"//base",
"//build:branding_buildflags",
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7f1c26990d8d43e92615bd3a5f4046d121d6ac6b..89d03b68cab5cec6095c2df2159a2f1cd15df0be 100644
index 2b66b11333f732ea1ec65474d709b55638696cf3..d2d5eb596db1fc166c0498c2f7a6c15080e5d775 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4486,7 +4486,7 @@ static_library("browser") {
@@ -46,7 +46,7 @@ index 7f1c26990d8d43e92615bd3a5f4046d121d6ac6b..89d03b68cab5cec6095c2df2159a2f1c
# than here in :chrome_dll.
deps += [ "//chrome:packed_resources_integrity_header" ]
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c53d7af88b3570e6c320b408afa449e51e355b6b..61aecb395632212911d57545cb068ca67bbac7d5 100644
index 2a55a6189c6a5c399a08edf4659f33f541726093..f8e8fb75e71a265a0cc2b7c57c4f0fd9035c6def 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -7173,9 +7173,12 @@ test("unit_tests") {
@@ -63,7 +63,7 @@ index c53d7af88b3570e6c320b408afa449e51e355b6b..61aecb395632212911d57545cb068ca6
"//chrome//services/util_win:unit_tests",
"//chrome/app:chrome_dll_resources",
"//chrome/app:win_unit_tests",
@@ -8181,6 +8184,10 @@ test("unit_tests") {
@@ -8180,6 +8183,10 @@ test("unit_tests") {
"../browser/performance_manager/policies/background_tab_loading_policy_unittest.cc",
]
@@ -74,7 +74,7 @@ index c53d7af88b3570e6c320b408afa449e51e355b6b..61aecb395632212911d57545cb068ca6
sources += [
# The importer code is not used on Android.
"../common/importer/firefox_importer_utils_unittest.cc",
@@ -8237,7 +8244,6 @@ test("unit_tests") {
@@ -8236,7 +8243,6 @@ test("unit_tests") {
# Non-android deps for "unit_tests" target.
deps += [
"../browser/screen_ai:screen_ai_install_state",

View File

@@ -9,10 +9,10 @@ potentially prevent a window from being created.
TODO(loc): this patch is currently broken.
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index a0d5a983bb46a50dcf31afadc10f597a0e3ed15d..b6bda9691f0ae96ee4ba5d0d96d4e57e4fa592c2 100644
index c2e377d5b1603a2d3c67a61911545ce361d418c2..20fe5301a0120e926d118f8b27ef57621833a5bf 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -9060,6 +9060,7 @@ void RenderFrameHostImpl::CreateNewWindow(
@@ -9040,6 +9040,7 @@ void RenderFrameHostImpl::CreateNewWindow(
last_committed_origin_, params->window_container_type,
params->target_url, params->referrer.To<Referrer>(),
params->frame_name, params->disposition, *params->features,
@@ -148,10 +148,10 @@ index a080fb57f00c712eb8a3a9be669413e1082ce3b3..4826eea9747c4860d7f5b4b8d478e62c
// typically happens when popups are created.
virtual void WebContentsCreated(WebContents* source_contents,
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 7b7e727c44a1477640f8702ad818f4a8607e3fb7..24904d0b6436353601aa43c603f9d12fb8eff960 100644
index d5e16b9e780efac46e088b3ef226e4418a90aeaf..724818204a4fa1578102c2fe1a8877735323595a 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -6837,6 +6837,10 @@ WebView* RenderFrameImpl::CreateNewWindow(
@@ -6834,6 +6834,10 @@ WebView* RenderFrameImpl::CreateNewWindow(
request.HasUserGesture(), GetWebFrame()->IsAdFrame(),
GetWebFrame()->IsAdScriptInStack());
@@ -210,10 +210,10 @@ index c576ace24e81cc877aa2595d40e0a13a7af9f6a2..210fb97d44c19c29af424cc7b9cb3169
} // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index fe3c23e1dd1c818b5cb07a609dbbf17763c6d583..77bcaaf388fe1fb4577e25880b10154db0b46ce4 100644
index 7b8158aff39c247e1729edb032833cdebf949acf..7d77f26106950deb1bae43ca7dcd7e0cde0ac6b5 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -2251,6 +2251,8 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
@@ -2248,6 +2248,8 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
WebWindowFeatures window_features =
GetWindowFeaturesFromString(features, entered_window);

View File

@@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fedor Indutny <indutny@signal.org>
Date: Tue, 17 Sep 2024 17:51:46 -0700
Subject: feat: allow -4 as a macos screen share id
We use fake video source ids for native macOS screen share window picker
of the following form:
window:-4:-1
Where the last digit represents the window id and decrements with each
requested screen share.
diff --git a/content/browser/media/capture/screen_capture_kit_device_mac.mm b/content/browser/media/capture/screen_capture_kit_device_mac.mm
index 1c2d0c6dd4101fe0bac69e3018bbbedadce224cc..e407382a3463374fd57a83d70c5f96dca5825faf 100644
--- a/content/browser/media/capture/screen_capture_kit_device_mac.mm
+++ b/content/browser/media/capture/screen_capture_kit_device_mac.mm
@@ -510,7 +510,9 @@ void OnStart(std::optional<bool> use_native_picker) override {
if (@available(macOS 15.0, *)) {
constexpr bool DefaultUseNativePicker = true;
- if (use_native_picker.value_or(DefaultUseNativePicker) && source_.id < 0 && source_.window_id == 0) {
+ if (use_native_picker.value_or(DefaultUseNativePicker) &&
+ source_.id == DesktopMediaID::kMacOsNativePickerId &&
+ source_.window_id < 0) {
auto* picker = [SCContentSharingPicker sharedPicker];
ScreenCaptureKitDeviceMac::active_streams_++;
picker.maximumStreamCount = @(ScreenCaptureKitDeviceMac::active_streams_);
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
index d162612dc70a2b57190aaf558aca8f46cbdedcad..bab2f0282b191a4263fc964125e199e52c62554b 100644
--- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
+++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -332,8 +332,16 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
break;
}
+#if defined(USE_AURA)
+ bool allow_window_id = false;
+#elif BUILDFLAG(IS_MAC)
+ bool allow_window_id =
+ desktop_id.id == DesktopMediaID::kMacOsNativePickerId;
+#endif
+
#if defined(USE_AURA) || BUILDFLAG(IS_MAC)
- if (desktop_id.window_id != DesktopMediaID::kNullId) {
+ if (!allow_window_id &&
+ desktop_id.window_id != DesktopMediaID::kNullId) {
// For the other capturers, when a bug reports the type of capture it's
// easy enough to determine which capturer was used, but it's a little
// fuzzier with window capture.
diff --git a/content/public/browser/desktop_media_id.h b/content/public/browser/desktop_media_id.h
index 415156d403a59bf426cf4561a9d58ecdb27524b4..78aa7b2359c684d5305bf6352751dfbb7ca00d29 100644
--- a/content/public/browser/desktop_media_id.h
+++ b/content/public/browser/desktop_media_id.h
@@ -27,6 +27,8 @@ struct CONTENT_EXPORT DesktopMediaID {
static constexpr Id kNullId = 0;
// Represents a fake id to create a dummy capturer for autotests.
static constexpr Id kFakeId = -3;
+ // Represents an id to use native macOS picker for screenshare
+ static constexpr Id kMacOsNativePickerId = -4;
#if defined(USE_AURA) || BUILDFLAG(IS_MAC)
// Assigns integer identifier to the |window| and returns its DesktopMediaID.

View File

@@ -46,7 +46,7 @@ index 8ac12480f663a74dfbdcf7128a582a81b4474d25..db6802a2603e1d3c3039e49737438124
// OnStop is called by StopAndDeAllocate.
virtual void OnStop() = 0;
diff --git a/content/browser/media/capture/screen_capture_kit_device_mac.mm b/content/browser/media/capture/screen_capture_kit_device_mac.mm
index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e172e9c76 100644
index b6129282c6807702cf88e0a3e2ba233e41a20960..1c2d0c6dd4101fe0bac69e3018bbbedadce224cc 100644
--- a/content/browser/media/capture/screen_capture_kit_device_mac.mm
+++ b/content/browser/media/capture/screen_capture_kit_device_mac.mm
@@ -24,24 +24,83 @@
@@ -143,7 +143,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
public:
explicit ScreenCaptureKitDeviceMac(const DesktopMediaID& source,
SCContentFilter* filter)
@@ -152,18 +212,42 @@ explicit ScreenCaptureKitDeviceMac(const DesktopMediaID& source,
@@ -152,18 +212,41 @@ explicit ScreenCaptureKitDeviceMac(const DesktopMediaID& source,
device_task_runner_,
base::BindRepeating(&ScreenCaptureKitDeviceMac::OnStreamSample,
weak_factory_.GetWeakPtr()));
@@ -165,8 +165,8 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
+ device_task_runner_,
+ base::BindRepeating(&ScreenCaptureKitDeviceMac::OnContentFilterReady, weak_factory_.GetWeakPtr())
+ );
+ picker_helper_ = [[ScreenCaptureKitPickerHelper alloc] initWithStreamPickCallback:picker_callback cancelCallback:cancel_callback errorCallback:error_callback];
+ [[SCContentSharingPicker sharedPicker] addObserver:picker_helper_];
+ auto* picker_observer = [[ScreenCaptureKitPickerHelper alloc] initWithStreamPickCallback:picker_callback cancelCallback:cancel_callback errorCallback:error_callback];
+ [[SCContentSharingPicker sharedPicker] addObserver:picker_observer];
+ }
}
ScreenCaptureKitDeviceMac(const ScreenCaptureKitDeviceMac&) = delete;
@@ -180,14 +180,13 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
+ picker.maximumStreamCount = @(ScreenCaptureKitDeviceMac::active_streams_);
+ if (ScreenCaptureKitDeviceMac::active_streams_ == 0 && picker.active) {
+ picker.active = false;
+ [[SCContentSharingPicker sharedPicker] removeObserver:picker_helper_];
+ }
+ }
+ }
void OnShareableContentCreated(SCShareableContent* content) {
DCHECK(device_task_runner_->RunsTasksInCurrentSequence());
@@ -232,7 +316,7 @@ void CreateStream(SCContentFilter* filter) {
@@ -232,7 +315,7 @@ void CreateStream(SCContentFilter* filter) {
return;
}
@@ -196,7 +195,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
// Update the content size. This step is neccessary when used together
// with SCContentSharingPicker. If the Chrome picker is used, it will
// change to retina resolution if applicable.
@@ -241,6 +325,9 @@ void CreateStream(SCContentFilter* filter) {
@@ -241,6 +324,9 @@ void CreateStream(SCContentFilter* filter) {
filter.contentRect.size.height * filter.pointPixelScale);
}
@@ -206,7 +205,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
gfx::RectF dest_rect_in_frame;
actual_capture_format_ = capture_params().requested_format;
actual_capture_format_.pixel_format = media::PIXEL_FORMAT_NV12;
@@ -254,6 +341,7 @@ void CreateStream(SCContentFilter* filter) {
@@ -254,6 +340,7 @@ void CreateStream(SCContentFilter* filter) {
stream_ = [[SCStream alloc] initWithFilter:filter
configuration:config
delegate:helper_];
@@ -214,7 +213,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
{
NSError* error = nil;
bool add_stream_output_result =
@@ -395,7 +483,7 @@ void OnStreamError() {
@@ -395,7 +482,7 @@ void OnStreamError() {
if (fullscreen_module_) {
fullscreen_module_->Reset();
}
@@ -223,7 +222,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
} else {
client()->OnError(media::VideoCaptureError::kScreenCaptureKitStreamError,
FROM_HERE, "Stream delegate called didStopWithError");
@@ -418,23 +506,41 @@ void OnUpdateConfigurationError() {
@@ -418,23 +505,39 @@ void OnUpdateConfigurationError() {
}
// IOSurfaceCaptureDeviceBase:
@@ -247,9 +246,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
+
+ if (@available(macOS 15.0, *)) {
+ constexpr bool DefaultUseNativePicker = true;
+ if (use_native_picker.value_or(DefaultUseNativePicker) &&
+ source_.id == DesktopMediaID::kMacOsNativePickerId &&
+ source_.window_id < 0) {
+ if (use_native_picker.value_or(DefaultUseNativePicker) && source_.id < 0 && source_.window_id == 0) {
+ auto* picker = [SCContentSharingPicker sharedPicker];
+ ScreenCaptureKitDeviceMac::active_streams_++;
+ picker.maximumStreamCount = @(ScreenCaptureKitDeviceMac::active_streams_);
@@ -280,7 +277,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
}
void OnStop() override {
DCHECK(device_task_runner_->RunsTasksInCurrentSequence());
@@ -492,6 +598,8 @@ void ResetStreamTo(SCWindow* window) override {
@@ -492,6 +595,8 @@ void ResetStreamTo(SCWindow* window) override {
}
private:
@@ -289,18 +286,7 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
const DesktopMediaID source_;
SCContentFilter* const filter_;
const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
@@ -509,6 +617,10 @@ void ResetStreamTo(SCWindow* window) override {
// Helper class that acts as output and delegate for `stream_`.
ScreenCaptureKitDeviceHelper* __strong helper_;
+ // Helper class that acts as an observer for SCContentSharingPicker
+ API_AVAILABLE(macos(15.0))
+ ScreenCaptureKitPickerHelper* __strong picker_helper_;
+
// This is used to detect when a captured presentation enters fullscreen mode.
// If this happens, the module will call the ResetStreamTo function.
std::unique_ptr<ScreenCaptureKitFullscreenModule> fullscreen_module_;
@@ -521,6 +633,8 @@ void ResetStreamTo(SCWindow* window) override {
@@ -521,6 +626,8 @@ void ResetStreamTo(SCWindow* window) override {
base::WeakPtrFactory<ScreenCaptureKitDeviceMac> weak_factory_{this};
};
@@ -310,28 +296,10 @@ index b6129282c6807702cf88e0a3e2ba233e41a20960..87a00302de8db47299b185471e303b9e
// Although ScreenCaptureKit is available in 12.3 there were some bugs that
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
index 7adf8264cfa9980c4a8414bf0f8bfa9ad70ec0b3..bab2f0282b191a4263fc964125e199e52c62554b 100644
index 7adf8264cfa9980c4a8414bf0f8bfa9ad70ec0b3..d162612dc70a2b57190aaf558aca8f46cbdedcad 100644
--- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
+++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -332,8 +332,16 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
break;
}
+#if defined(USE_AURA)
+ bool allow_window_id = false;
+#elif BUILDFLAG(IS_MAC)
+ bool allow_window_id =
+ desktop_id.id == DesktopMediaID::kMacOsNativePickerId;
+#endif
+
#if defined(USE_AURA) || BUILDFLAG(IS_MAC)
- if (desktop_id.window_id != DesktopMediaID::kNullId) {
+ if (!allow_window_id &&
+ desktop_id.window_id != DesktopMediaID::kNullId) {
// For the other capturers, when a bug reports the type of capture it's
// easy enough to determine which capturer was used, but it's a little
// fuzzier with window capture.
@@ -360,13 +368,15 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
@@ -360,13 +360,15 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
std::move(after_start_capture_callback));
break;
#else
@@ -348,19 +316,6 @@ index 7adf8264cfa9980c4a8414bf0f8bfa9ad70ec0b3..bab2f0282b191a4263fc964125e199e5
CreateDeviceClient(media::VideoCaptureBufferType::kSharedMemory,
kMaxNumberOfBuffers, std::move(receiver),
std::move(receiver_on_io_thread)),
diff --git a/content/public/browser/desktop_media_id.h b/content/public/browser/desktop_media_id.h
index 415156d403a59bf426cf4561a9d58ecdb27524b4..78aa7b2359c684d5305bf6352751dfbb7ca00d29 100644
--- a/content/public/browser/desktop_media_id.h
+++ b/content/public/browser/desktop_media_id.h
@@ -27,6 +27,8 @@ struct CONTENT_EXPORT DesktopMediaID {
static constexpr Id kNullId = 0;
// Represents a fake id to create a dummy capturer for autotests.
static constexpr Id kFakeId = -3;
+ // Represents an id to use native macOS picker for screenshare
+ static constexpr Id kMacOsNativePickerId = -4;
#if defined(USE_AURA) || BUILDFLAG(IS_MAC)
// Assigns integer identifier to the |window| and returns its DesktopMediaID.
diff --git a/media/capture/video_capture_types.h b/media/capture/video_capture_types.h
index f2b75f5b2f547ad135c1288bf3639b26dedc8053..ef18724d9f2ea68a47b66fc3981f58a73ac1b51d 100644
--- a/media/capture/video_capture_types.h

View File

@@ -40,10 +40,10 @@ index 22bb23e6a84d3b6686461f87e846125ad7484742..198403ec544e71f50c8555d131015b80
// origin of |common_params.url| and/or |common_params.initiator_origin|.
url::Origin resolved_origin = url::Origin::Resolve(
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index f8098c86def00cac76932551bf413266facdc935..98a4c1ad9f561e1bec1e6113db46d4bcf3d3f694 100644
index 0fb02ada85ed3d4cc113ac7ce18d6efdb7065627..9e78c486fdc9b931dfcbcf40145076a22f221e35 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2264,6 +2264,10 @@ Frame* DocumentLoader::CalculateOwnerFrame() {
@@ -2261,6 +2261,10 @@ Frame* DocumentLoader::CalculateOwnerFrame() {
scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
Document* owner_document) {
scoped_refptr<SecurityOrigin> origin;
@@ -54,7 +54,7 @@ index f8098c86def00cac76932551bf413266facdc935..98a4c1ad9f561e1bec1e6113db46d4bc
StringBuilder debug_info_builder;
// Whether the origin is newly created within this call, instead of copied
// from an existing document's origin or from `origin_to_commit_`. If this is
@@ -2316,6 +2320,10 @@ scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
@@ -2313,6 +2317,10 @@ scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
debug_info_builder.Append(", url=");
debug_info_builder.Append(owner_document->Url().BaseAsString());
debug_info_builder.Append(")");

View File

@@ -10,7 +10,7 @@ an about:blank check to this area.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/5403876
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 67e53ad616687ea17719e3f4f1d00192c5b69d61..1642d61585c7aee3ec7a0907f5cdcd016e29ca6e 100644
index 2605701ace806adef40b748f93aebae45144e1be..888e1386d7ed0003bbaabddeefa98d2c25e9adbb 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -782,8 +782,8 @@ void VerifyThatBrowserAndRendererCalculatedOriginsToCommitMatch(

View File

@@ -15,10 +15,10 @@ Note that we also need to manually update embedder's
`api::WebContents::IsFullscreenForTabOrPending` value.
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index b6bda9691f0ae96ee4ba5d0d96d4e57e4fa592c2..67e53ad616687ea17719e3f4f1d00192c5b69d61 100644
index 20fe5301a0120e926d118f8b27ef57621833a5bf..2605701ace806adef40b748f93aebae45144e1be 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -8175,6 +8175,17 @@ void RenderFrameHostImpl::EnterFullscreen(
@@ -8155,6 +8155,17 @@ void RenderFrameHostImpl::EnterFullscreen(
}
}

View File

@@ -52,4 +52,3 @@ build_don_t_redefine_win32_lean_and_mean.patch
src_use_supported_api_to_get_stalled_tla_messages.patch
build_compile_with_c_20_support.patch
add_v8_taskpirority_to_foreground_task_runner_signature.patch
build_restore_clang_as_default_compiler_on_macos.patch

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: deepak1556 <hop2deep@gmail.com>
Date: Fri, 11 Oct 2024 15:01:25 +0900
Subject: build: restore clang as default compiler on macOS
Refs https://github.com/nodejs/node/commit/6e0a2bb54c5bbeff0e9e33e1a0c683ed980a8a0f
configures the value at build time which doesn't work in Electron
as it depends on the environment in which the headers got generated from which
cannot reflect the value per platform. It works for Node.js since
node-gyp will use the result of `process.config` that reflects the environment
in which the binary got built.
diff --git a/common.gypi b/common.gypi
index 2eb62610db2f0ebf68fa9a55ffba98291ecfe451..3ec08ee144b586d05c4e49c2251416734cbc02c5 100644
--- a/common.gypi
+++ b/common.gypi
@@ -125,6 +125,7 @@
'v8_base': '<(PRODUCT_DIR)/obj.target/tools/v8_gypfiles/libv8_snapshot.a',
}],
['OS=="mac"', {
+ 'clang%': 1,
'obj_dir%': '<(PRODUCT_DIR)/obj.target',
'v8_base': '<(PRODUCT_DIR)/libv8_snapshot.a',
}],

View File

@@ -61,10 +61,6 @@ def main(target_file, target_cpu):
v['node_module_version'] = int(args['node_module_version'])
# Used by certain versions of node-gyp.
v['build_v8_with_gn'] = 'false'
# Enable clang conditionally based on target platform
# in common.gypi
if 'clang' in v:
del v['clang']
with open(target_file, 'w+', encoding='utf-8') as file_out:
file_out.write(pprint.pformat(config, indent=2))

View File

@@ -1,7 +1,6 @@
const glob = require('glob');
const fs = require('node:fs');
const path = require('node:path');
const currentShard = parseInt(process.argv[2], 10);
const shardCount = parseInt(process.argv[3], 10);
@@ -26,7 +25,7 @@ specFiles.sort((a, b) => {
let shard = 0;
for (const specFile of specFiles) {
buckets[shard].push(path.normalize(specFile));
buckets[shard].push(specFile);
shard++;
if (shard === shardCount) shard = 0;
}

View File

@@ -79,7 +79,7 @@
#include "shell/common/node_includes.h"
#include "shell/common/options_switches.h"
#include "shell/common/thread_restrictions.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "ui/gfx/image/image.h"
#if BUILDFLAG(IS_WIN)

View File

@@ -28,7 +28,7 @@
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
#include "third_party/blink/public/common/messaging/transferable_message_mojom_traits.h"

View File

@@ -133,7 +133,7 @@
#include "shell/common/node_util.h"
#include "shell/common/options_switches.h"
#include "shell/common/thread_restrictions.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "storage/browser/file_system/isolated_context.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/input/web_input_event.h"

View File

@@ -31,7 +31,7 @@
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
namespace gin {

View File

@@ -21,7 +21,7 @@
#include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/event_emitter_caller.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "third_party/blink/public/common/messaging/transferable_message.h"
#include "third_party/blink/public/common/messaging/transferable_message_mojom_traits.h"
#include "third_party/blink/public/mojom/messaging/transferable_message.mojom.h"

View File

@@ -25,18 +25,6 @@ namespace electron {
namespace {
// write |ref|'s raw bytes to |fd|.
template <typename T>
void WriteValToFd(int fd, const T& ref) {
base::span<const uint8_t> bytes = base::byte_span_from_ref(ref);
while (!bytes.empty()) {
const ssize_t rv = HANDLE_EINTR(write(fd, bytes.data(), bytes.size()));
RAW_CHECK(rv >= 0);
const size_t n_bytes_written = rv >= 0 ? static_cast<size_t>(rv) : 0U;
bytes = bytes.subspan(n_bytes_written);
}
}
// See comment in |PreEarlyInitialization()|, where sigaction is called.
void SIGCHLDHandler(int signal) {}
@@ -61,7 +49,15 @@ void GracefulShutdownHandler(int signal) {
RAW_CHECK(g_pipe_pid == getpid());
RAW_CHECK(g_shutdown_pipe_write_fd != -1);
RAW_CHECK(g_shutdown_pipe_read_fd != -1);
WriteValToFd(g_shutdown_pipe_write_fd, signal);
size_t bytes_written = 0;
do {
int rv = HANDLE_EINTR(
write(g_shutdown_pipe_write_fd,
reinterpret_cast<const char*>(&signal) + bytes_written,
sizeof(signal) - bytes_written));
RAW_CHECK(rv >= 0);
bytes_written += rv;
} while (bytes_written < sizeof(signal));
}
// See comment in |PostCreateMainMessageLoop()|, where sigaction is called.
@@ -134,33 +130,26 @@ NOINLINE void ExitPosted() {
sleep(UINT_MAX);
}
// read |sizeof(T)| raw bytes from |fd| and return the result
template <typename T>
[[nodiscard]] std::optional<T> ReadValFromFd(int fd) {
auto val = T{};
base::span<uint8_t> bytes = base::byte_span_from_ref(val);
while (!bytes.empty()) {
const ssize_t rv = HANDLE_EINTR(read(fd, bytes.data(), bytes.size()));
if (rv < 0) {
NOTREACHED_IN_MIGRATION() << "Unexpected error: " << strerror(errno);
ShutdownFDReadError();
return {};
}
if (rv == 0) {
NOTREACHED_IN_MIGRATION() << "Unexpected closure of shutdown pipe.";
ShutdownFDClosedError();
return {};
}
const size_t n_bytes_read = static_cast<size_t>(rv);
bytes = bytes.subspan(n_bytes_read);
}
return val;
}
void ShutdownDetector::ThreadMain() {
base::PlatformThread::SetName("CrShutdownDetector");
const int signal = ReadValFromFd<int>(shutdown_fd_).value_or(0);
int signal;
size_t bytes_read = 0;
do {
const ssize_t ret = HANDLE_EINTR(
read(shutdown_fd_, reinterpret_cast<char*>(&signal) + bytes_read,
sizeof(signal) - bytes_read));
if (ret < 0) {
NOTREACHED_IN_MIGRATION() << "Unexpected error: " << strerror(errno);
ShutdownFDReadError();
break;
} else if (ret == 0) {
NOTREACHED_IN_MIGRATION() << "Unexpected closure of shutdown pipe.";
ShutdownFDClosedError();
break;
}
bytes_read += ret;
} while (bytes_read < sizeof(signal));
VLOG(1) << "Handling shutdown for signal " << signal << ".";
if (!task_runner_->PostTask(FROM_HERE,

View File

@@ -11,7 +11,7 @@
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_helper/callback.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
ElectronNSSCryptoModuleDelegate::ElectronNSSCryptoModuleDelegate(
const net::HostPortPair& server)

View File

@@ -120,20 +120,20 @@ void SetZoomLevelForWebContents(content::WebContents* web_contents,
content::HostZoomMap::SetZoomLevel(web_contents, level);
}
double GetNextZoomLevel(double level, bool out) {
double GetNextZoomLevel(const double level, const bool out) {
static constexpr std::array<double, 16U> kPresetFactors{
0.25, 0.333, 0.5, 0.666, 0.75, 0.9, 1.0, 1.1,
1.25, 1.5, 1.75, 2.0, 2.5, 3.0, 4.0, 5.0};
static constexpr size_t size = std::size(kPresetFactors);
static constexpr auto kBegin = kPresetFactors.begin();
static constexpr auto kEnd = kPresetFactors.end();
const double factor = blink::ZoomLevelToZoomFactor(level);
for (size_t i = 0U; i < size; ++i) {
if (!blink::ZoomValuesEqual(kPresetFactors[i], factor))
continue;
if (out && i > 0U)
return blink::ZoomFactorToZoomLevel(kPresetFactors[i - 1U]);
if (!out && i + 1U < size)
return blink::ZoomFactorToZoomLevel(kPresetFactors[i + 1U]);
auto matches = [=](auto val) { return blink::ZoomValuesEqual(factor, val); };
if (auto iter = std::find_if(kBegin, kEnd, matches); iter != kEnd) {
if (out && iter != kBegin)
return blink::ZoomFactorToZoomLevel(*--iter);
if (!out && ++iter != kEnd)
return blink::ZoomFactorToZoomLevel(*iter);
}
return level;
}

View File

@@ -30,7 +30,6 @@
#include "shell/common/gin_helper/function_template_extensions.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/node_util.h"
#include "shell/common/process_util.h"
#include "shell/common/skia_util.h"
#include "shell/common/thread_restrictions.h"
@@ -398,18 +397,20 @@ void NativeImage::AddRepresentation(const gin_helper::Dictionary& options) {
v8::Local<v8::Value> buffer;
GURL url;
if (options.Get("buffer", &buffer) && node::Buffer::HasInstance(buffer)) {
auto* data = reinterpret_cast<unsigned char*>(node::Buffer::Data(buffer));
auto size = node::Buffer::Length(buffer);
skia_rep_added = electron::util::AddImageSkiaRepFromBuffer(
&image_skia, electron::util::as_byte_span(buffer), width, height,
scale_factor);
&image_skia, data, size, width, height, scale_factor);
} else if (options.Get("dataURL", &url)) {
std::string mime_type, charset, data;
if (net::DataURL::Parse(url, &mime_type, &charset, &data)) {
auto* data_ptr = reinterpret_cast<const unsigned char*>(data.c_str());
if (mime_type == "image/png") {
skia_rep_added = electron::util::AddImageSkiaRepFromPNG(
&image_skia, base::as_byte_span(data), scale_factor);
&image_skia, data_ptr, data.size(), scale_factor);
} else if (mime_type == "image/jpeg") {
skia_rep_added = electron::util::AddImageSkiaRepFromJPEG(
&image_skia, base::as_byte_span(data), scale_factor);
&image_skia, data_ptr, data.size(), scale_factor);
}
}
}
@@ -441,20 +442,22 @@ gin::Handle<NativeImage> NativeImage::Create(v8::Isolate* isolate,
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromPNG(
v8::Isolate* isolate,
const base::span<const uint8_t> data) {
gin::Handle<NativeImage> NativeImage::CreateFromPNG(v8::Isolate* isolate,
const char* buffer,
size_t length) {
gfx::ImageSkia image_skia;
electron::util::AddImageSkiaRepFromPNG(&image_skia, data, 1.0);
electron::util::AddImageSkiaRepFromPNG(
&image_skia, reinterpret_cast<const unsigned char*>(buffer), length, 1.0);
return Create(isolate, gfx::Image(image_skia));
}
// static
gin::Handle<NativeImage> NativeImage::CreateFromJPEG(
v8::Isolate* isolate,
const base::span<const uint8_t> buffer) {
gin::Handle<NativeImage> NativeImage::CreateFromJPEG(v8::Isolate* isolate,
const char* buffer,
size_t length) {
gfx::ImageSkia image_skia;
electron::util::AddImageSkiaRepFromJPEG(&image_skia, buffer, 1.0);
electron::util::AddImageSkiaRepFromJPEG(
&image_skia, reinterpret_cast<const unsigned char*>(buffer), length, 1.0);
return Create(isolate, gfx::Image(image_skia));
}
@@ -506,8 +509,7 @@ gin::Handle<NativeImage> NativeImage::CreateFromBitmap(
auto info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType);
auto size_bytes = info.computeMinByteSize();
const auto buffer_data = electron::util::as_byte_span(buffer);
if (size_bytes != buffer_data.size()) {
if (size_bytes != node::Buffer::Length(buffer)) {
thrower.ThrowError("invalid buffer size");
return gin::Handle<NativeImage>();
}
@@ -520,7 +522,7 @@ gin::Handle<NativeImage> NativeImage::CreateFromBitmap(
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height, false);
bitmap.writePixels({info, buffer_data.data(), bitmap.rowBytes()});
bitmap.writePixels({info, node::Buffer::Data(buffer), bitmap.rowBytes()});
gfx::ImageSkia image_skia =
gfx::ImageSkia::CreateFromBitmap(bitmap, scale_factor);
@@ -551,8 +553,8 @@ gin::Handle<NativeImage> NativeImage::CreateFromBuffer(
gfx::ImageSkia image_skia;
electron::util::AddImageSkiaRepFromBuffer(
&image_skia, electron::util::as_byte_span(buffer), width, height,
scale_factor);
&image_skia, reinterpret_cast<unsigned char*>(node::Buffer::Data(buffer)),
node::Buffer::Length(buffer), width, height, scale_factor);
return Create(args->isolate(), gfx::Image(image_skia));
}
@@ -562,9 +564,9 @@ gin::Handle<NativeImage> NativeImage::CreateFromDataURL(v8::Isolate* isolate,
std::string mime_type, charset, data;
if (net::DataURL::Parse(url, &mime_type, &charset, &data)) {
if (mime_type == "image/png")
return CreateFromPNG(isolate, base::as_byte_span(data));
if (mime_type == "image/jpeg")
return CreateFromJPEG(isolate, base::as_byte_span(data));
return CreateFromPNG(isolate, data.c_str(), data.size());
else if (mime_type == "image/jpeg")
return CreateFromJPEG(isolate, data.c_str(), data.size());
}
return CreateEmpty(isolate);

View File

@@ -9,7 +9,6 @@
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "gin/wrappable.h"
@@ -62,10 +61,11 @@ class NativeImage final : public gin::Wrappable<NativeImage> {
static gin::Handle<NativeImage> Create(v8::Isolate* isolate,
const gfx::Image& image);
static gin::Handle<NativeImage> CreateFromPNG(v8::Isolate* isolate,
base::span<const uint8_t> data);
static gin::Handle<NativeImage> CreateFromJPEG(
v8::Isolate* isolate,
base::span<const uint8_t> data);
const char* buffer,
size_t length);
static gin::Handle<NativeImage> CreateFromJPEG(v8::Isolate* isolate,
const char* buffer,
size_t length);
static gin::Handle<NativeImage> CreateFromPath(v8::Isolate* isolate,
const base::FilePath& path);
static gin::Handle<NativeImage> CreateFromBitmap(

View File

@@ -26,19 +26,6 @@
namespace electron::api {
namespace {
base::span<const uint8_t> as_byte_span(NSData* data) {
// SAFETY: There is no NSData API that passes the UNSAFE_BUFFER_USAGE
// test, so let's isolate the unsafe API use into this function. Instead of
// calling '[data bytes]' and '[data length]' directly, the rest of our
// code should prefer to use spans returned by this function.
return UNSAFE_BUFFERS(base::span{
reinterpret_cast<const uint8_t*>([data bytes]), [data length]});
}
} // namespace
NSData* bufferFromNSImage(NSImage* image) {
CGImageRef ref = [image CGImageForProposedRect:nil context:nil hints:nil];
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithCGImage:ref];
@@ -140,7 +127,9 @@ gin::Handle<NativeImage> NativeImage::CreateFromNamedImage(gin::Arguments* args,
NSData* png_data = bufferFromNSImage(image);
if (args->GetNext(&hsl_shift) && hsl_shift.size() == 3) {
auto gfx_image = gfx::Image::CreateFrom1xPNGBytes(as_byte_span(png_data));
gfx::Image gfx_image = gfx::Image::CreateFrom1xPNGBytes(
{reinterpret_cast<const uint8_t*>((char*)[png_data bytes]),
[png_data length]});
color_utils::HSL shift = {safeShift(hsl_shift[0], -1),
safeShift(hsl_shift[1], 0.5),
safeShift(hsl_shift[2], 0.5)};
@@ -150,7 +139,8 @@ gin::Handle<NativeImage> NativeImage::CreateFromNamedImage(gin::Arguments* args,
.AsNSImage());
}
return CreateFromPNG(args->isolate(), as_byte_span(png_data));
return CreateFromPNG(args->isolate(), (char*)[png_data bytes],
[png_data length]);
}
}

View File

@@ -21,7 +21,7 @@
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/keyboard_util.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "third_party/blink/public/common/context_menu_data/edit_flags.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"

View File

@@ -35,7 +35,6 @@
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
namespace gin {
@@ -370,7 +369,10 @@ class ChunkedDataPipeReadableStream final
num_bytes = *size_ - bytes_read_;
MojoResult rv = data_pipe_->ReadData(
MOJO_READ_DATA_FLAG_NONE,
electron::util::as_byte_span(buf).first(num_bytes), num_bytes);
base::span(static_cast<uint8_t*>(buf->Buffer()->Data()),
buf->ByteLength())
.subspan(buf->ByteOffset(), num_bytes),
num_bytes);
if (rv == MOJO_RESULT_OK) {
bytes_read_ += num_bytes;
// Not needed for correctness, but this allows the consumer to send the

View File

@@ -4,7 +4,6 @@
#include "shell/common/heap_snapshot.h"
#include "base/containers/span.h"
#include "base/files/file.h"
#include "base/memory/raw_ptr.h"
#include "v8/include/v8-profiler.h"
@@ -25,13 +24,8 @@ class HeapSnapshotOutputStream : public v8::OutputStream {
void EndOfStream() override { is_complete_ = true; }
v8::OutputStream::WriteResult WriteAsciiChunk(char* data, int size) override {
const uint8_t* udata = reinterpret_cast<const uint8_t*>(data);
const size_t usize = static_cast<size_t>(std::max(0, size));
// SAFETY: since WriteAsciiChunk() only gives us data + size, our
// UNSAFE_BUFFERS macro call is unavoidable here. It can be removed
// if/when v8 changes WriteAsciiChunk() to pass a v8::MemorySpan.
const auto data_span = UNSAFE_BUFFERS(base::span(udata, usize));
return file_->WriteAtCurrentPosAndCheck(data_span) ? kContinue : kAbort;
auto bytes_written = file_->WriteAtCurrentPos(data, size);
return bytes_written == size ? kContinue : kAbort;
}
private:

View File

@@ -4,7 +4,6 @@
#include "shell/common/node_util.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "gin/converter.h"
#include "gin/dictionary.h"
@@ -66,14 +65,4 @@ void EmitWarning(v8::Isolate* isolate,
emit_warning.Run(warning_msg, warning_type, "");
}
// SAFETY: There is no node::Buffer API that passes the UNSAFE_BUFFER_USAGE
// test, so let's isolate the unsafe API use into this function. Instead of
// calling `Buffer::Data()` and `Buffer::Length()` directly, the rest of our
// code should prefer to use spans returned by this function.
base::span<uint8_t> as_byte_span(v8::Local<v8::Value> node_buffer) {
auto* data = reinterpret_cast<uint8_t*>(node::Buffer::Data(node_buffer));
const auto size = node::Buffer::Length(node_buffer);
return UNSAFE_BUFFERS(base::span{data, size});
}
} // namespace electron::util

View File

@@ -8,7 +8,6 @@
#include <string_view>
#include <vector>
#include "base/containers/span.h"
#include "v8/include/v8-forward.h"
namespace node {
@@ -37,11 +36,6 @@ v8::MaybeLocal<v8::Value> CompileAndCall(
std::vector<v8::Local<v8::String>>* parameters,
std::vector<v8::Local<v8::Value>>* arguments);
// Convenience function to view a Node buffer's data as a base::span().
// Analogous to base::as_byte_span()
[[nodiscard]] base::span<uint8_t> as_byte_span(
v8::Local<v8::Value> node_buffer);
} // namespace electron::util
#endif // ELECTRON_SHELL_COMMON_NODE_UTIL_H_

View File

@@ -56,10 +56,11 @@ float GetScaleFactorFromPath(const base::FilePath& path) {
}
bool AddImageSkiaRepFromPNG(gfx::ImageSkia* image,
const base::span<const uint8_t> data,
const unsigned char* data,
size_t size,
double scale_factor) {
SkBitmap bitmap;
if (!gfx::PNGCodec::Decode(data.data(), data.size(), &bitmap))
if (!gfx::PNGCodec::Decode(data, size, &bitmap))
return false;
image->AddRepresentation(gfx::ImageSkiaRep(bitmap, scale_factor));
@@ -67,9 +68,10 @@ bool AddImageSkiaRepFromPNG(gfx::ImageSkia* image,
}
bool AddImageSkiaRepFromJPEG(gfx::ImageSkia* image,
const base::span<const uint8_t> data,
const unsigned char* data,
size_t size,
double scale_factor) {
auto bitmap = gfx::JPEGCodec::Decode(data.data(), data.size());
auto bitmap = gfx::JPEGCodec::Decode(data, size);
if (!bitmap)
return false;
@@ -87,28 +89,29 @@ bool AddImageSkiaRepFromJPEG(gfx::ImageSkia* image,
}
bool AddImageSkiaRepFromBuffer(gfx::ImageSkia* image,
const base::span<const uint8_t> data,
const unsigned char* data,
size_t size,
int width,
int height,
double scale_factor) {
// Try PNG first.
if (AddImageSkiaRepFromPNG(image, data, scale_factor))
if (AddImageSkiaRepFromPNG(image, data, size, scale_factor))
return true;
// Try JPEG second.
if (AddImageSkiaRepFromJPEG(image, data, scale_factor))
if (AddImageSkiaRepFromJPEG(image, data, size, scale_factor))
return true;
if (width == 0 || height == 0)
return false;
auto info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType);
if (data.size() < info.computeMinByteSize())
if (size < info.computeMinByteSize())
return false;
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height, false);
bitmap.writePixels({info, data.data(), bitmap.rowBytes()});
bitmap.writePixels({info, data, bitmap.rowBytes()});
image->AddRepresentation(gfx::ImageSkiaRep(bitmap, scale_factor));
return true;
@@ -124,8 +127,11 @@ bool AddImageSkiaRepFromPath(gfx::ImageSkia* image,
return false;
}
return AddImageSkiaRepFromBuffer(image, base::as_byte_span(file_contents), 0,
0, scale_factor);
const auto* data =
reinterpret_cast<const unsigned char*>(file_contents.data());
size_t size = file_contents.size();
return AddImageSkiaRepFromBuffer(image, data, size, 0, 0, scale_factor);
}
bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image,

View File

@@ -5,13 +5,9 @@
#ifndef ELECTRON_SHELL_COMMON_SKIA_UTIL_H_
#define ELECTRON_SHELL_COMMON_SKIA_UTIL_H_
#include <cstdint>
#include "base/containers/span.h"
namespace base {
class FilePath;
} // namespace base
}
namespace gfx {
class ImageSkia;
@@ -23,17 +19,20 @@ bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image,
const base::FilePath& path);
bool AddImageSkiaRepFromBuffer(gfx::ImageSkia* image,
base::span<const uint8_t> data,
const unsigned char* data,
size_t size,
int width,
int height,
double scale_factor);
bool AddImageSkiaRepFromJPEG(gfx::ImageSkia* image,
base::span<const uint8_t> data,
const unsigned char* data,
size_t size,
double scale_factor);
bool AddImageSkiaRepFromPNG(gfx::ImageSkia* image,
base::span<const uint8_t> data,
const unsigned char* data,
size_t size,
double scale_factor);
#if BUILDFLAG(IS_WIN)

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include <utility>
#include <vector>
@@ -240,23 +240,4 @@ v8::Local<v8::Value> DeserializeV8Value(v8::Isolate* isolate,
return V8Deserializer(isolate, data).Deserialize();
}
namespace util {
/**
* SAFETY: There is not yet any v8::ArrayBufferView API that passes the
* UNSAFE_BUFFER_USAGE test, so let's isolate the unsafe API here.
*
* Where possible, Electron should use spans returned here instead of
* |v8::ArrayBufferView::Buffer()->Data()|,
* |v8::ArrayBufferView::ByteOffset()|,
* |v8::ArrayBufferView::ByteLength()|.
*/
base::span<uint8_t> as_byte_span(v8::Local<v8::ArrayBufferView> val) {
uint8_t* data =
static_cast<uint8_t*>(val->Buffer()->Data()) + val->ByteOffset();
const size_t size = val->ByteLength();
return UNSAFE_BUFFERS(base::span{data, size});
}
} // namespace util
} // namespace electron

View File

@@ -9,7 +9,6 @@
#include "ui/gfx/image/image_skia_rep.h"
namespace v8 {
class ArrayBufferView;
class Isolate;
template <class T>
class Local;
@@ -30,12 +29,6 @@ v8::Local<v8::Value> DeserializeV8Value(v8::Isolate* isolate,
v8::Local<v8::Value> DeserializeV8Value(v8::Isolate* isolate,
base::span<const uint8_t> data);
namespace util {
[[nodiscard]] base::span<uint8_t> as_byte_span(
v8::Local<v8::ArrayBufferView> abv);
} // namespace util
} // namespace electron
#endif // ELECTRON_SHELL_COMMON_V8_VALUE_SERIALIZER_H_

View File

@@ -19,7 +19,7 @@
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_bindings.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_message_port_converter.h"

View File

@@ -15,7 +15,6 @@
#include "base/containers/contains.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "base/task/single_thread_task_runner.h"
#include "components/spellcheck/renderer/spellcheck_worditerator.h"
#include "shell/common/gin_helper/dictionary.h"
@@ -30,9 +29,12 @@ namespace electron::api {
namespace {
bool HasWordCharacters(const std::u16string& text, size_t index) {
base_icu::UChar32 code;
while (base::ReadUnicodeCharacter(text.c_str(), text.size(), &index, &code)) {
bool HasWordCharacters(const std::u16string& text, int index) {
const char16_t* data = text.data();
int length = text.length();
while (index < length) {
uint32_t code = 0;
U16_NEXT(data, index, length, code);
UErrorCode error = U_ZERO_ERROR;
if (uscript_getScript(code, &error) != USCRIPT_COMMON)
return true;

View File

@@ -19,7 +19,7 @@
#include "shell/common/node_includes.h"
#include "shell/common/options_switches.h"
#include "shell/common/thread_restrictions.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "shell/renderer/electron_render_frame_observer.h"
#include "shell/renderer/renderer_client_base.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-shared.h"

View File

@@ -15,7 +15,7 @@
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/event_emitter_caller.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "shell/common/v8_value_serializer.h"
#include "third_party/blink/public/common/messaging/transferable_message_mojom_traits.h"
namespace electron {

View File

@@ -7,6 +7,12 @@
<title>Document</title>
</head>
<body>
<h1>Visibility Test</h1>
<script>
const { ipcRenderer } = require('electron')
ipcRenderer.send('initial-visibility-state', document.visibilityState)
document.addEventListener('visibilitychange', () => {
ipcRenderer.send(`visibility-change-${document.visibilityState}`)
})
</script>
</body>
</html>

View File

@@ -149,17 +149,7 @@ app.whenReady().then(async () => {
const { getFiles } = require('./get-files');
const testFiles = await getFiles(__dirname, filter);
const VISIBILITY_SPEC = ('visibility-state-spec.ts');
const sortedFiles = testFiles.sort((a, b) => {
// If visibility-state-spec is in the list, move it to the first position
// so that it gets executed first to avoid other specs interferring with it.
if (a.indexOf(VISIBILITY_SPEC) > -1) {
return -1;
} else {
return a.localeCompare(b);
}
});
for (const file of sortedFiles) {
for (const file of testFiles.sort()) {
mocha.addFile(file);
}

View File

@@ -1,37 +1,26 @@
import { BaseWindow, BrowserWindow, BrowserWindowConstructorOptions, WebContents, WebContentsView } from 'electron/main';
import { BaseWindow, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, WebContents, WebContentsView } from 'electron/main';
import { expect } from 'chai';
import * as cp from 'node:child_process';
import { once } from 'node:events';
import * as path from 'node:path';
import { setTimeout } from 'node:timers/promises';
import { ifdescribe, waitUntil } from './lib/spec-helpers';
import { closeAllWindows } from './lib/window-helpers';
import { ifdescribe } from './lib/spec-helpers';
import { closeWindow } from './lib/window-helpers';
// visibilityState specs pass on linux with a real window manager but on CI
// the environment does not let these specs pass
ifdescribe(process.platform !== 'linux')('document.visibilityState', () => {
let w: BaseWindow & {webContents: WebContents};
before(() => {
for (const checkWin of BaseWindow.getAllWindows()) {
console.log('WINDOW EXISTS BEFORE TEST STARTED:', checkWin.title, checkWin.id);
}
});
afterEach(async () => {
await closeAllWindows();
w = null as unknown as BrowserWindow;
afterEach(() => {
return closeWindow(w);
});
const load = () => w.webContents.loadFile(path.resolve(__dirname, 'fixtures', 'chromium', 'visibilitystate.html'));
async function haveVisibilityState (state: string) {
const docVisState = await w.webContents.executeJavaScript('document.visibilityState');
return docVisState === state;
}
const itWithOptions = (name: string, options: BrowserWindowConstructorOptions, fn: Mocha.Func) => {
it(name, async function (...args) {
w = new BrowserWindow({
@@ -43,9 +32,6 @@ ifdescribe(process.platform !== 'linux')('document.visibilityState', () => {
contextIsolation: false
}
});
if (options.show && process.platform === 'darwin') {
await once(w, 'show');
}
await Promise.resolve(fn.apply(this, args));
});
@@ -56,30 +42,30 @@ ifdescribe(process.platform !== 'linux')('document.visibilityState', () => {
const wcv = new WebContentsView({ webPreferences: { ...(options.webPreferences ?? {}), nodeIntegration: true, contextIsolation: false } });
baseWindow.contentView = wcv;
w = Object.assign(baseWindow, { webContents: wcv.webContents });
if (options.show && process.platform === 'darwin') {
await once(w, 'show');
}
await Promise.resolve(fn.apply(this, args));
});
};
itWithOptions('should be visible when the window is initially shown by default', {}, async () => {
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('visible');
});
itWithOptions('should be visible when the window is initially shown', {
show: true
}, async () => {
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('visible');
});
itWithOptions('should be hidden when the window is initially hidden', {
show: false
}, async () => {
load();
await expect(waitUntil(async () => await haveVisibilityState('hidden'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('hidden');
});
itWithOptions('should be visible when the window is initially hidden but shown before the page is loaded', {
@@ -87,40 +73,52 @@ ifdescribe(process.platform !== 'linux')('document.visibilityState', () => {
}, async () => {
w.show();
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('visible');
});
itWithOptions('should be hidden when the window is initially shown but hidden before the page is loaded', {
show: true
}, async () => {
// TODO(MarshallOfSound): Figure out if we can work around this 1 tick issue for users
if (process.platform === 'darwin') {
// Wait for a tick, the window being "shown" takes 1 tick on macOS
await setTimeout(10000);
}
w.hide();
load();
await expect(waitUntil(async () => await haveVisibilityState('hidden'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('hidden');
});
itWithOptions('should be toggle between visible and hidden as the window is hidden and shown', {}, async () => {
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, initialState] = await once(ipcMain, 'initial-visibility-state');
expect(initialState).to.equal('visible');
w.hide();
await expect(waitUntil(async () => await haveVisibilityState('hidden'))).to.eventually.be.fulfilled();
await once(ipcMain, 'visibility-change-hidden');
w.show();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
await once(ipcMain, 'visibility-change-visible');
});
itWithOptions('should become hidden when a window is minimized', {}, async () => {
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, initialState] = await once(ipcMain, 'initial-visibility-state');
expect(initialState).to.equal('visible');
w.minimize();
await expect(waitUntil(async () => await haveVisibilityState('hidden'))).to.eventually.be.fulfilled();
const p = once(ipcMain, 'visibility-change-hidden');
w.minimize();
await p;
});
itWithOptions('should become visible when a window is restored', {}, async () => {
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, initialState] = await once(ipcMain, 'initial-visibility-state');
expect(initialState).to.equal('visible');
w.minimize();
await expect(waitUntil(async () => await haveVisibilityState('hidden'))).to.eventually.be.fulfilled();
await once(ipcMain, 'visibility-change-hidden');
w.restore();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
await once(ipcMain, 'visibility-change-visible');
});
ifdescribe(process.platform === 'darwin')('on platforms that support occlusion detection', () => {
@@ -154,7 +152,8 @@ ifdescribe(process.platform !== 'linux')('document.visibilityState', () => {
height: 200
});
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('visible');
});
itWithOptions('should be visible when two windows are on screen that overlap partially', {
@@ -170,7 +169,8 @@ ifdescribe(process.platform !== 'linux')('document.visibilityState', () => {
height: 200
});
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('visible');
});
itWithOptions('should be hidden when a second window completely occludes the current window', {
@@ -181,14 +181,15 @@ ifdescribe(process.platform !== 'linux')('document.visibilityState', () => {
}, async function () {
this.timeout(240000);
load();
await expect(waitUntil(async () => await haveVisibilityState('visible'))).to.eventually.be.fulfilled();
const [, state] = await once(ipcMain, 'initial-visibility-state');
expect(state).to.equal('visible');
makeOtherWindow({
x: 0,
y: 0,
width: 300,
height: 300
});
await expect(waitUntil(async () => await haveVisibilityState('hidden'))).to.eventually.be.fulfilled();
await once(ipcMain, 'visibility-change-hidden');
});
});
});