mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc9b5af26e | ||
|
|
952b9c0b46 | ||
|
|
5705ce1d6e | ||
|
|
c8ac7b0efd | ||
|
|
dbeed26c0d | ||
|
|
99e589c2cf | ||
|
|
3782fe51ff | ||
|
|
be7b06108e | ||
|
|
6b956d036d | ||
|
|
370ffe0df5 | ||
|
|
14456ecfbc | ||
|
|
974c8f5150 | ||
|
|
ac5b5995e8 | ||
|
|
5ccd41cf5c | ||
|
|
060cfb94e9 | ||
|
|
587e115527 | ||
|
|
a56b2acadd | ||
|
|
58479848b2 | ||
|
|
ba2cad1670 | ||
|
|
f98501308a | ||
|
|
1d9f1a4cd4 | ||
|
|
7d01169091 |
4
.github/actions/checkout/action.yml
vendored
4
.github/actions/checkout/action.yml
vendored
@@ -99,7 +99,7 @@ runs:
|
||||
fi
|
||||
|
||||
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 e d gclient sync --with_branch_heads --with_tags -vv
|
||||
if [ "${{ inputs.is-release }}" != "true" && -n "${{ env.PATCH_UP_APP_CREDS }}" ]; then
|
||||
if [[ "${{ inputs.is-release }}" != "true" && -n "${{ env.PATCH_UP_APP_CREDS }}" ]]; then
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python3 src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
cd src/electron
|
||||
@@ -128,6 +128,8 @@ runs:
|
||||
cat ../../patches/update-patches.patch
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "No changes to patches detected"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -144,3 +144,10 @@ cherry-pick-dd8e2822e507.patch
|
||||
fix_osr_stutter_in_both_cpu_and_gpu_capture_when_page_has_animation.patch
|
||||
reland_lzma_sdk_update_to_24_09.patch
|
||||
fix_drag_and_drop_icons_on_windows.patch
|
||||
cherry-pick-521faebc8a7c.patch
|
||||
cherry-pick-9dacf5694dfd.patch
|
||||
revert_blink_fix_over_invalidation_with_view_transitions.patch
|
||||
add_a_flag_to_enable_strict_js_compliance_in_audioworklet.patch
|
||||
remove_denormalenabler_from_scriptprocessornode.patch
|
||||
allow_denormal_flushing_to_outlive_scoped_object.patch
|
||||
fix_take_snapped_status_into_account_when_showing_a_window.patch
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Wilson <mjwilson@chromium.org>
|
||||
Date: Thu, 12 Dec 2024 08:45:53 -0800
|
||||
Subject: Add a flag to enable strict JS compliance in AudioWorklet
|
||||
|
||||
AudioWorklet and ScriptProcessorNode are not strictly JavaScript spec
|
||||
compliant because we disable denormal numbers for performance reasons.
|
||||
|
||||
This CL adds a flag to allow experimenting with enabling denormal
|
||||
numbers in AudioWorklet and ScriptProcessorNode, so that we can
|
||||
quantify the actual performance impact.
|
||||
|
||||
The flag can also be used as a server-side switch.
|
||||
|
||||
Bug: 382005099
|
||||
Change-Id: Ib41253cc42dd2f16c262036817cf3db4697f986f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6077677
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Commit-Queue: Michael Wilson <mjwilson@chromium.org>
|
||||
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1395444}
|
||||
|
||||
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
|
||||
index e7224e03e80f8351556b3d2d43650dad7e29edef..1b2b6128e69953be7f9f96853d76c5c0e16552fe 100644
|
||||
--- a/third_party/blink/common/features.cc
|
||||
+++ b/third_party/blink/common/features.cc
|
||||
@@ -2754,6 +2754,12 @@ BASE_FEATURE(kWebAppManifestLockScreen,
|
||||
"WebAppManifestLockScreen",
|
||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
|
||||
+// Allow denormals in AudioWorklet and ScriptProcessorNode, to enable strict
|
||||
+// JavaScript denormal compliance. See https://crbug.com/382005099.
|
||||
+BASE_FEATURE(kWebAudioAllowDenormalInProcessing,
|
||||
+ "WebAudioAllowDenormalInProcessing",
|
||||
+ base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
+
|
||||
// Parameters can be used to control to which latency hints the feature is
|
||||
// applied.
|
||||
BASE_FEATURE_PARAM(bool,
|
||||
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
|
||||
index e8f79c39e03f5777c1accd4446c97f18fb3e34de..0bc9302cd8f3f291949be328aba5df88e2ab0d03 100644
|
||||
--- a/third_party/blink/public/common/features.h
|
||||
+++ b/third_party/blink/public/common/features.h
|
||||
@@ -1791,6 +1791,7 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebAppEnableScopeExtensions);
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebAppEnableUrlHandlers);
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebAppManifestLockScreen);
|
||||
|
||||
+BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebAudioAllowDenormalInProcessing);
|
||||
// Parameters are used to control to which latency hints the feature is applied
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM(
|
||||
bool,
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc
|
||||
index 0382f578a4f98cbac422d5f927c73a6b922c01b8..9a662e7730d3e01dcf8e69f66c4eafa9dd7dd031 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
|
||||
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
|
||||
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
|
||||
+#include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
|
||||
#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
|
||||
@@ -52,7 +53,9 @@ AudioWorkletHandler::AudioWorkletHandler(
|
||||
const AudioWorkletNodeOptions* options)
|
||||
: AudioHandler(kNodeTypeAudioWorklet, node, sample_rate),
|
||||
name_(name),
|
||||
- param_handler_map_(param_handler_map) {
|
||||
+ param_handler_map_(param_handler_map),
|
||||
+ allow_denormal_in_processing_(base::FeatureList::IsEnabled(
|
||||
+ features::kWebAudioAllowDenormalInProcessing)) {
|
||||
DCHECK(IsMainThread());
|
||||
|
||||
for (const auto& param_name : param_handler_map_.Keys()) {
|
||||
@@ -112,7 +115,7 @@ scoped_refptr<AudioWorkletHandler> AudioWorkletHandler::Create(
|
||||
param_handler_map, options));
|
||||
}
|
||||
|
||||
-void AudioWorkletHandler::Process(uint32_t frames_to_process) {
|
||||
+void AudioWorkletHandler::ProcessInternal(uint32_t frames_to_process) {
|
||||
DCHECK(Context()->IsAudioThread());
|
||||
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("webaudio.audionode"),
|
||||
@@ -175,6 +178,15 @@ void AudioWorkletHandler::Process(uint32_t frames_to_process) {
|
||||
}
|
||||
}
|
||||
|
||||
+void AudioWorkletHandler::Process(uint32_t frames_to_process) {
|
||||
+ if (allow_denormal_in_processing_) {
|
||||
+ DenormalEnabler denormal_enabler;
|
||||
+ ProcessInternal(frames_to_process);
|
||||
+ } else {
|
||||
+ ProcessInternal(frames_to_process);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void AudioWorkletHandler::CheckNumberOfChannelsForInput(AudioNodeInput* input) {
|
||||
DCHECK(Context()->IsAudioThread());
|
||||
Context()->AssertGraphOwner();
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.h
|
||||
index e6291f5e9e25433281646965f048a7f2abfc8c01..3ec80cd49a87a76ac03df105b37f1ae17437a328 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.h
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.h
|
||||
@@ -68,6 +68,10 @@ class AudioWorkletHandler final : public AudioHandler {
|
||||
HashMap<String, scoped_refptr<AudioParamHandler>> param_handler_map,
|
||||
const AudioWorkletNodeOptions*);
|
||||
|
||||
+ // Used to avoid code duplication when using scoped objects that affect
|
||||
+ // `Process`.
|
||||
+ void ProcessInternal(uint32_t frames_to_process);
|
||||
+
|
||||
String name_;
|
||||
|
||||
double tail_time_ = std::numeric_limits<double>::infinity();
|
||||
@@ -102,6 +106,9 @@ class AudioWorkletHandler final : public AudioHandler {
|
||||
// when a processor stops invoking the user-defined `process()` callback.
|
||||
bool is_processor_active_ = true;
|
||||
|
||||
+ // Cached feature flag value
|
||||
+ const bool allow_denormal_in_processing_;
|
||||
+
|
||||
base::WeakPtrFactory<AudioWorkletHandler> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc b/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc
|
||||
index d3d44d2a4c87bf5d4191807ec31d87c7e597fef9..ea04e2cd2bfb553a58ba6fb9c63c70c5a2690442 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/script_processor_node.h"
|
||||
+#include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
|
||||
@@ -48,7 +49,9 @@ ScriptProcessorHandler::ScriptProcessorHandler(
|
||||
internal_input_bus_(AudioBus::Create(
|
||||
number_of_input_channels,
|
||||
node.context()->GetDeferredTaskHandler().RenderQuantumFrames(),
|
||||
- false)) {
|
||||
+ false)),
|
||||
+ allow_denormal_in_processing_(base::FeatureList::IsEnabled(
|
||||
+ features::kWebAudioAllowDenormalInProcessing)) {
|
||||
DCHECK_GE(buffer_size_,
|
||||
node.context()->GetDeferredTaskHandler().RenderQuantumFrames());
|
||||
DCHECK_LE(number_of_input_channels, BaseAudioContext::MaxNumberOfChannels());
|
||||
@@ -109,7 +112,7 @@ void ScriptProcessorHandler::Initialize() {
|
||||
AudioHandler::Initialize();
|
||||
}
|
||||
|
||||
-void ScriptProcessorHandler::Process(uint32_t frames_to_process) {
|
||||
+void ScriptProcessorHandler::ProcessInternal(uint32_t frames_to_process) {
|
||||
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("webaudio.audionode"),
|
||||
"ScriptProcessorHandler::Process");
|
||||
|
||||
@@ -238,6 +241,15 @@ void ScriptProcessorHandler::Process(uint32_t frames_to_process) {
|
||||
"ScriptProcessorHandler::Process");
|
||||
}
|
||||
|
||||
+void ScriptProcessorHandler::Process(uint32_t frames_to_process) {
|
||||
+ if (allow_denormal_in_processing_) {
|
||||
+ DenormalEnabler denormal_enabler;
|
||||
+ ProcessInternal(frames_to_process);
|
||||
+ } else {
|
||||
+ ProcessInternal(frames_to_process);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void ScriptProcessorHandler::FireProcessEvent(uint32_t double_buffer_index) {
|
||||
DCHECK(IsMainThread());
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_handler.h b/third_party/blink/renderer/modules/webaudio/script_processor_handler.h
|
||||
index 82ac7cebaefb515a04442e7a24896177d66fcb01..99103e947ade50f07a16a61bc8702d6097266296 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/script_processor_handler.h
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/script_processor_handler.h
|
||||
@@ -65,6 +65,11 @@ class ScriptProcessorHandler final : public AudioHandler {
|
||||
uint32_t number_of_output_channels,
|
||||
const HeapVector<Member<AudioBuffer>>& input_buffers,
|
||||
const HeapVector<Member<AudioBuffer>>& output_buffers);
|
||||
+
|
||||
+ // Used to avoid code duplication when using scoped objects that affect
|
||||
+ // `Process`.
|
||||
+ void ProcessInternal(uint32_t frames_to_process);
|
||||
+
|
||||
double TailTime() const override;
|
||||
double LatencyTime() const override;
|
||||
bool RequiresTailProcessing() const final;
|
||||
@@ -92,6 +97,9 @@ class ScriptProcessorHandler final : public AudioHandler {
|
||||
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
+ // Cached feature flag value
|
||||
+ const bool allow_denormal_in_processing_;
|
||||
+
|
||||
base::WeakPtrFactory<ScriptProcessorHandler> weak_ptr_factory_{this};
|
||||
|
||||
FRIEND_TEST_ALL_PREFIXES(ScriptProcessorNodeTest, BufferLifetime);
|
||||
diff --git a/third_party/blink/renderer/platform/audio/denormal_disabler.h b/third_party/blink/renderer/platform/audio/denormal_disabler.h
|
||||
index e8fadf60eea81b017dc29b39c2d1cfe8c102999b..ac1cdfa026aa1f845a892e96200fd9de46a45c92 100644
|
||||
--- a/third_party/blink/renderer/platform/audio/denormal_disabler.h
|
||||
+++ b/third_party/blink/renderer/platform/audio/denormal_disabler.h
|
||||
@@ -52,28 +52,28 @@ namespace blink {
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_DENORMAL)
|
||||
-class DenormalDisabler {
|
||||
- DISALLOW_NEW();
|
||||
-
|
||||
+class DenormalModifier {
|
||||
public:
|
||||
- DenormalDisabler() { DisableDenormals(); }
|
||||
-
|
||||
- ~DenormalDisabler() { RestoreState(); }
|
||||
-
|
||||
- // This is a nop if we can flush denormals to zero in hardware.
|
||||
- static inline float FlushDenormalFloatToZero(float f) { return f; }
|
||||
+ virtual ~DenormalModifier() = default;
|
||||
|
||||
private:
|
||||
unsigned saved_csr_ = 0;
|
||||
|
||||
#if defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
|
||||
+ protected:
|
||||
inline void DisableDenormals() {
|
||||
saved_csr_ = GetCSR();
|
||||
SetCSR(saved_csr_ | 0x8040);
|
||||
}
|
||||
|
||||
+ inline void EnableDenormals() {
|
||||
+ saved_csr_ = GetCSR();
|
||||
+ SetCSR(saved_csr_ & (~0x8040));
|
||||
+ }
|
||||
+
|
||||
inline void RestoreState() { SetCSR(saved_csr_); }
|
||||
|
||||
+ private:
|
||||
inline int GetCSR() {
|
||||
int result;
|
||||
asm volatile("stmxcsr %0" : "=m"(result));
|
||||
@@ -86,6 +86,7 @@ class DenormalDisabler {
|
||||
}
|
||||
|
||||
#elif BUILDFLAG(IS_WIN) && defined(COMPILER_MSVC)
|
||||
+ protected:
|
||||
inline void DisableDenormals() {
|
||||
// Save the current state, and set mode to flush denormals.
|
||||
//
|
||||
@@ -95,11 +96,18 @@ class DenormalDisabler {
|
||||
_controlfp_s(&unused, _DN_FLUSH, _MCW_DN);
|
||||
}
|
||||
|
||||
+ inline void EnableDenormals() {
|
||||
+ _controlfp_s(&saved_csr_, 0, 0);
|
||||
+ unsigned unused;
|
||||
+ _controlfp_s(&unused, _DN_SAVE, _MCW_DN);
|
||||
+ }
|
||||
+
|
||||
inline void RestoreState() {
|
||||
unsigned unused;
|
||||
_controlfp_s(&unused, saved_csr_, _MCW_DN);
|
||||
}
|
||||
#elif defined(ARCH_CPU_ARM_FAMILY)
|
||||
+ protected:
|
||||
inline void DisableDenormals() {
|
||||
saved_csr_ = GetStatusWord();
|
||||
// Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes
|
||||
@@ -107,8 +115,14 @@ class DenormalDisabler {
|
||||
SetStatusWord(saved_csr_ | (1 << 24));
|
||||
}
|
||||
|
||||
+ inline void EnableDenormals() {
|
||||
+ saved_csr_ = GetStatusWord();
|
||||
+ SetStatusWord(saved_csr_ & (~(1 << 24)));
|
||||
+ }
|
||||
+
|
||||
inline void RestoreState() { SetStatusWord(saved_csr_); }
|
||||
|
||||
+ private:
|
||||
inline int GetStatusWord() {
|
||||
int result;
|
||||
#if defined(ARCH_CPU_ARM64)
|
||||
@@ -130,13 +144,33 @@ class DenormalDisabler {
|
||||
#endif
|
||||
};
|
||||
|
||||
+class DenormalDisabler final : public DenormalModifier {
|
||||
+ DISALLOW_NEW();
|
||||
+
|
||||
+ public:
|
||||
+ DenormalDisabler() { DisableDenormals(); }
|
||||
+ ~DenormalDisabler() final { RestoreState(); }
|
||||
+
|
||||
+ // This is a nop if we can flush denormals to zero in hardware.
|
||||
+ static inline float FlushDenormalFloatToZero(float f) { return f; }
|
||||
+};
|
||||
+
|
||||
+class DenormalEnabler final : public DenormalModifier {
|
||||
+ DISALLOW_NEW();
|
||||
+
|
||||
+ public:
|
||||
+ DenormalEnabler() { EnableDenormals(); }
|
||||
+ ~DenormalEnabler() final { RestoreState(); }
|
||||
+};
|
||||
+
|
||||
#else
|
||||
// FIXME: add implementations for other architectures and compilers
|
||||
class DenormalDisabler {
|
||||
STACK_ALLOCATED();
|
||||
|
||||
public:
|
||||
- DenormalDisabler() {}
|
||||
+ DenormalDisabler() = default;
|
||||
+ ~DenormalDisabler() = default;
|
||||
|
||||
// Assume the worst case that other architectures and compilers
|
||||
// need to flush denormals to zero manually.
|
||||
@@ -145,6 +179,14 @@ class DenormalDisabler {
|
||||
}
|
||||
};
|
||||
|
||||
+class DenormalEnabler {
|
||||
+ STACK_ALLOCATED();
|
||||
+
|
||||
+ public:
|
||||
+ DenormalEnabler() = default;
|
||||
+ ~DenormalEnabler() = default;
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
|
||||
} // namespace blink
|
||||
@@ -0,0 +1,293 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Wilson <mjwilson@chromium.org>
|
||||
Date: Fri, 7 Feb 2025 13:33:40 -0800
|
||||
Subject: Allow denormal flushing to outlive scoped object
|
||||
|
||||
After this refactor we can disable or enable denormals for longer than
|
||||
a scoped object.
|
||||
|
||||
Use this new functionality in audio_worklet_global_scope.cc.
|
||||
|
||||
(cherry picked from commit 93c4f6fb0a0f10562ef9a637449605caae9200e6)
|
||||
|
||||
Bug: 382005099
|
||||
Change-Id: I54f4810a4ec035f639d50275e14dae03b726b876
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6226252
|
||||
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Commit-Queue: Michael Wilson <mjwilson@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1415886}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6242822
|
||||
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6998@{#221}
|
||||
Cr-Branched-From: de9c6fafd8ae5c6ea0438764076ca7d04a0b165d-refs/heads/main@{#1415337}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
|
||||
index c9bd1e8934d7058cb4c8044aa5618033ec975cec..09de112b96b6062f702d57e6181dd39e681e99a1 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
|
||||
+#include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/callback_method_retriever.h"
|
||||
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
|
||||
|
||||
@@ -34,6 +35,9 @@ AudioWorkletGlobalScope::AudioWorkletGlobalScope(
|
||||
: WorkletGlobalScope(std::move(creation_params),
|
||||
thread->GetWorkerReportingProxy(),
|
||||
thread) {
|
||||
+ // Disable denormals for performance.
|
||||
+ DenormalModifier::DisableDenormals();
|
||||
+
|
||||
// Audio is prone to jank introduced by e.g. the garbage collector. Workers
|
||||
// are generally put in a background mode (as they are non-visible). Audio is
|
||||
// an exception here, requiring low-latency behavior similar to any visible
|
||||
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
|
||||
index ffb2cc23eb74da99ca5875293879659b4f171303..01366aa7b5b4438f9d62de4065623a1ede71cc41 100644
|
||||
--- a/third_party/blink/renderer/platform/BUILD.gn
|
||||
+++ b/third_party/blink/renderer/platform/BUILD.gn
|
||||
@@ -2142,6 +2142,7 @@ source_set("blink_platform_unittests_sources") {
|
||||
"animation/timing_function_test.cc",
|
||||
"audio/audio_destination_test.cc",
|
||||
"audio/audio_frame_stats_accumulator_test.cc",
|
||||
+ "audio/denormal_disabler_test.cc",
|
||||
"audio/push_pull_fifo_multithread_test.cc",
|
||||
"audio/push_pull_fifo_test.cc",
|
||||
"audio/vector_math_test.cc",
|
||||
diff --git a/third_party/blink/renderer/platform/audio/denormal_disabler.h b/third_party/blink/renderer/platform/audio/denormal_disabler.h
|
||||
index ac1cdfa026aa1f845a892e96200fd9de46a45c92..a50d7b884e8fdc65f4c1fbe6b5cab7a7801a3b62 100644
|
||||
--- a/third_party/blink/renderer/platform/audio/denormal_disabler.h
|
||||
+++ b/third_party/blink/renderer/platform/audio/denormal_disabler.h
|
||||
@@ -56,74 +56,65 @@ class DenormalModifier {
|
||||
public:
|
||||
virtual ~DenormalModifier() = default;
|
||||
|
||||
- private:
|
||||
- unsigned saved_csr_ = 0;
|
||||
-
|
||||
#if defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
|
||||
- protected:
|
||||
- inline void DisableDenormals() {
|
||||
- saved_csr_ = GetCSR();
|
||||
- SetCSR(saved_csr_ | 0x8040);
|
||||
+ public:
|
||||
+ static void DisableDenormals() {
|
||||
+ unsigned old_csr = GetCsr();
|
||||
+ SetCsr(old_csr | 0x8040);
|
||||
}
|
||||
|
||||
- inline void EnableDenormals() {
|
||||
- saved_csr_ = GetCSR();
|
||||
- SetCSR(saved_csr_ & (~0x8040));
|
||||
+ static void EnableDenormals() {
|
||||
+ unsigned old_csr = GetCsr();
|
||||
+ SetCsr(old_csr & (~0x8040));
|
||||
}
|
||||
|
||||
- inline void RestoreState() { SetCSR(saved_csr_); }
|
||||
-
|
||||
- private:
|
||||
- inline int GetCSR() {
|
||||
+ protected:
|
||||
+ static inline unsigned GetCsr() {
|
||||
int result;
|
||||
asm volatile("stmxcsr %0" : "=m"(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
- inline void SetCSR(int a) {
|
||||
+ static inline void SetCsr(int a) {
|
||||
int temp = a;
|
||||
asm volatile("ldmxcsr %0" : : "m"(temp));
|
||||
}
|
||||
|
||||
#elif BUILDFLAG(IS_WIN) && defined(COMPILER_MSVC)
|
||||
+ public:
|
||||
+ static void DisableDenormals() { SetCsr(_DN_FLUSH); }
|
||||
+
|
||||
+ static void EnableDenormals() { SetCsr(_DN_SAVE); }
|
||||
+
|
||||
protected:
|
||||
- inline void DisableDenormals() {
|
||||
- // Save the current state, and set mode to flush denormals.
|
||||
- //
|
||||
- // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s-may-not-restore-control-word-correctly
|
||||
- _controlfp_s(&saved_csr_, 0, 0);
|
||||
- unsigned unused;
|
||||
- _controlfp_s(&unused, _DN_FLUSH, _MCW_DN);
|
||||
+ static inline unsigned GetCsr() {
|
||||
+ unsigned result;
|
||||
+ _controlfp_s(&result, 0, 0);
|
||||
+ return result;
|
||||
}
|
||||
|
||||
- inline void EnableDenormals() {
|
||||
- _controlfp_s(&saved_csr_, 0, 0);
|
||||
+ static inline void SetCsr(unsigned a) {
|
||||
+ // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s-may-not-restore-control-word-correctly
|
||||
unsigned unused;
|
||||
- _controlfp_s(&unused, _DN_SAVE, _MCW_DN);
|
||||
+ _controlfp_s(&unused, a, _MCW_DN);
|
||||
}
|
||||
|
||||
- inline void RestoreState() {
|
||||
- unsigned unused;
|
||||
- _controlfp_s(&unused, saved_csr_, _MCW_DN);
|
||||
- }
|
||||
#elif defined(ARCH_CPU_ARM_FAMILY)
|
||||
- protected:
|
||||
- inline void DisableDenormals() {
|
||||
- saved_csr_ = GetStatusWord();
|
||||
+ public:
|
||||
+ static void DisableDenormals() {
|
||||
+ unsigned old_csr = GetCsr();
|
||||
// Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes
|
||||
// denormals to 0.
|
||||
- SetStatusWord(saved_csr_ | (1 << 24));
|
||||
+ SetCsr(old_csr | (1 << 24));
|
||||
}
|
||||
|
||||
- inline void EnableDenormals() {
|
||||
- saved_csr_ = GetStatusWord();
|
||||
- SetStatusWord(saved_csr_ & (~(1 << 24)));
|
||||
+ static void EnableDenormals() {
|
||||
+ unsigned old_csr = GetCsr();
|
||||
+ SetCsr(old_csr & (~(1 << 24)));
|
||||
}
|
||||
|
||||
- inline void RestoreState() { SetStatusWord(saved_csr_); }
|
||||
-
|
||||
- private:
|
||||
- inline int GetStatusWord() {
|
||||
+ protected:
|
||||
+ static inline unsigned GetCsr() {
|
||||
int result;
|
||||
#if defined(ARCH_CPU_ARM64)
|
||||
asm volatile("mrs %x[result], FPCR" : [result] "=r"(result));
|
||||
@@ -133,7 +124,7 @@ class DenormalModifier {
|
||||
return result;
|
||||
}
|
||||
|
||||
- inline void SetStatusWord(int a) {
|
||||
+ static inline void SetCsr(int a) {
|
||||
#if defined(ARCH_CPU_ARM64)
|
||||
asm volatile("msr FPCR, %x[src]" : : [src] "r"(a));
|
||||
#else
|
||||
@@ -148,24 +139,44 @@ class DenormalDisabler final : public DenormalModifier {
|
||||
DISALLOW_NEW();
|
||||
|
||||
public:
|
||||
- DenormalDisabler() { DisableDenormals(); }
|
||||
- ~DenormalDisabler() final { RestoreState(); }
|
||||
+ DenormalDisabler() {
|
||||
+ // Save the current state, and set mode to flush denormals.
|
||||
+ saved_csr_ = GetCsr();
|
||||
+ DisableDenormals();
|
||||
+ }
|
||||
+ ~DenormalDisabler() final { SetCsr(saved_csr_); }
|
||||
|
||||
// This is a nop if we can flush denormals to zero in hardware.
|
||||
static inline float FlushDenormalFloatToZero(float f) { return f; }
|
||||
+
|
||||
+ private:
|
||||
+ unsigned saved_csr_ = 0;
|
||||
};
|
||||
|
||||
class DenormalEnabler final : public DenormalModifier {
|
||||
DISALLOW_NEW();
|
||||
|
||||
public:
|
||||
- DenormalEnabler() { EnableDenormals(); }
|
||||
- ~DenormalEnabler() final { RestoreState(); }
|
||||
+ DenormalEnabler() {
|
||||
+ saved_csr_ = GetCsr();
|
||||
+ EnableDenormals();
|
||||
+ }
|
||||
+ ~DenormalEnabler() final { SetCsr(saved_csr_); }
|
||||
+
|
||||
+ private:
|
||||
+ unsigned saved_csr_ = 0;
|
||||
};
|
||||
|
||||
#else
|
||||
// FIXME: add implementations for other architectures and compilers
|
||||
-class DenormalDisabler {
|
||||
+class DenormalModifier final {
|
||||
+ public:
|
||||
+ virtual ~DenormalModifier() = default;
|
||||
+ static void DisableDenormals() {}
|
||||
+ static void EnableDenormals() {}
|
||||
+};
|
||||
+
|
||||
+class DenormalDisabler final {
|
||||
STACK_ALLOCATED();
|
||||
|
||||
public:
|
||||
@@ -179,7 +190,7 @@ class DenormalDisabler {
|
||||
}
|
||||
};
|
||||
|
||||
-class DenormalEnabler {
|
||||
+class DenormalEnabler final {
|
||||
STACK_ALLOCATED();
|
||||
|
||||
public:
|
||||
diff --git a/third_party/blink/renderer/platform/audio/denormal_disabler_test.cc b/third_party/blink/renderer/platform/audio/denormal_disabler_test.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5083bbf2da9d4e0e12f1a4608d5e14e4ca910297
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/renderer/platform/audio/denormal_disabler_test.cc
|
||||
@@ -0,0 +1,51 @@
|
||||
+// Copyright 2025 The Chromium Authors
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
|
||||
+
|
||||
+#include "testing/gtest/include/gtest/gtest.h"
|
||||
+
|
||||
+namespace blink {
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+bool DenormalsAreFlushedToZero() {
|
||||
+ volatile double denorm = 2.225e-308;
|
||||
+ return !((denorm / 2.0) > 0.0);
|
||||
+}
|
||||
+
|
||||
+TEST(DenormalDisablerTest, DisableScoped) {
|
||||
+ const bool already_flushed = DenormalsAreFlushedToZero();
|
||||
+ if (!already_flushed) {
|
||||
+ DenormalDisabler scoped_disabler;
|
||||
+ EXPECT_TRUE(DenormalsAreFlushedToZero());
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+TEST(DenormalDisablerTest, EnableScoped) {
|
||||
+ const bool already_flushed = DenormalsAreFlushedToZero();
|
||||
+ if (!already_flushed) {
|
||||
+ DenormalDisabler scoped_disabler;
|
||||
+ EXPECT_TRUE(DenormalsAreFlushedToZero());
|
||||
+ {
|
||||
+ DenormalEnabler scoped_enabler;
|
||||
+ EXPECT_FALSE(DenormalsAreFlushedToZero());
|
||||
+ }
|
||||
+ EXPECT_TRUE(DenormalsAreFlushedToZero());
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+TEST(DenormalDisablerTest, ModifyUnscoped) {
|
||||
+ const bool already_flushed = DenormalsAreFlushedToZero();
|
||||
+ if (!already_flushed) {
|
||||
+ DenormalModifier::DisableDenormals();
|
||||
+ EXPECT_TRUE(DenormalsAreFlushedToZero());
|
||||
+ DenormalModifier::EnableDenormals();
|
||||
+ EXPECT_FALSE(DenormalsAreFlushedToZero());
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+} // namespace blink
|
||||
33
patches/chromium/cherry-pick-521faebc8a7c.patch
Normal file
33
patches/chromium/cherry-pick-521faebc8a7c.patch
Normal file
@@ -0,0 +1,33 @@
|
||||
From 521faebc8a7cffe23177c6600bfcfb3c0b9ab1dc Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Thu, 06 Mar 2025 19:39:37 -0800
|
||||
Subject: [PATCH] Disable setting primtive restart for WebGL in the cmd decoder.
|
||||
|
||||
Until it's blocked in ANGLE for WebGL contexts, disable it in the
|
||||
command decoder on the service side.
|
||||
|
||||
Bug: 401059730
|
||||
Change-Id: Ia9c7d951cbd122454afec2f884968e0a709cee77
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6334632
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Commit-Queue: Kenneth Russell <kbr@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1429307}
|
||||
---
|
||||
|
||||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
|
||||
index ad23480..733c553 100644
|
||||
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
|
||||
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
|
||||
@@ -2170,6 +2170,11 @@
|
||||
case GL_DEBUG_OUTPUT:
|
||||
return true;
|
||||
|
||||
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
|
||||
+ // Disable setting primitive restart at the command decoder level until
|
||||
+ // it's blocked in ANGLE for WebGL contexts.
|
||||
+ return feature_info_->IsWebGLContext();
|
||||
+
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
94
patches/chromium/cherry-pick-9dacf5694dfd.patch
Normal file
94
patches/chromium/cherry-pick-9dacf5694dfd.patch
Normal file
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Thu, 6 Mar 2025 16:02:41 -0800
|
||||
Subject: Move WebGL primitive restart state setting to the GPU process.
|
||||
|
||||
ANGLE will validate and initialize this state and errors are generated
|
||||
when the WebGL client also initializes it on startup.
|
||||
|
||||
Initialize it even in the passthrough command decoder temporarily so
|
||||
that ANGLE can roll without breaking WebGL tests.
|
||||
|
||||
Bug: 401059730
|
||||
Change-Id: I0bfee710673bbcea6f915ffc4fc9be20438a2654
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6330188
|
||||
Auto-Submit: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Kenneth Russell <kbr@chromium.org>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1429228}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
index 03a26a5f81dee1cd1bba28621c1ecd30ea709df8..60447a8e71e056db01515db8bc6c56048537870f 100644
|
||||
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
@@ -3285,6 +3285,13 @@ gpu::ContextResult GLES2DecoderImpl::Initialize(
|
||||
}
|
||||
}
|
||||
|
||||
+ if (feature_info_->context_type() == CONTEXT_TYPE_WEBGL2) {
|
||||
+ // If WebGL 2, the PRIMITIVE_RESTART_FIXED_INDEX should be always enabled.
|
||||
+ // See the section <Primitive Restart is Always Enabled> in WebGL 2 spec:
|
||||
+ // https://www.khronos.org/registry/webgl/specs/latest/2.0/#4.1.4
|
||||
+ DoEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
|
||||
+ }
|
||||
+
|
||||
if (group_->gpu_preferences().enable_gpu_driver_debug_logging &&
|
||||
feature_info_->feature_flags().khr_debug) {
|
||||
InitializeGLDebugLogging(true, GLDebugMessageCallback, &logger_);
|
||||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
|
||||
index 54310b8878fa7aeca45e6001cb884a794272138c..e7abe4cb8542aa767ca150db3163f860f9a04b59 100644
|
||||
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
|
||||
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
|
||||
@@ -1065,6 +1065,17 @@ gpu::ContextResult GLES2DecoderPassthroughImpl::Initialize(
|
||||
api()->glDisableFn(GL_TEXTURE_RECTANGLE_ANGLE);
|
||||
#endif
|
||||
|
||||
+ // TEMPORARY: Set primitive restart to enabled by default for WebGL2. Clear
|
||||
+ // errors afterwards so that when this state is initialized and validated in
|
||||
+ // ANGLE, it will not generate errors during command buffer initialization.
|
||||
+ if (feature_info_->context_type() == CONTEXT_TYPE_WEBGL2) {
|
||||
+ // If WebGL 2, the PRIMITIVE_RESTART_FIXED_INDEX should be always enabled.
|
||||
+ // See the section <Primitive Restart is Always Enabled> in WebGL 2 spec:
|
||||
+ // https://www.khronos.org/registry/webgl/specs/latest/2.0/#4.1.4
|
||||
+ api()->glEnableFn(GL_PRIMITIVE_RESTART_FIXED_INDEX);
|
||||
+ CheckErrorCallbackState();
|
||||
+ }
|
||||
+
|
||||
// Register this object as a GPU switching observer.
|
||||
if (feature_info_->IsWebGLContext()) {
|
||||
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
|
||||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
|
||||
index 1683b266f349d4b70ae2861cf4f05542380d8c44..0a0c1b3f6f9fe2caddf86602d2ae9978eff928f1 100644
|
||||
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
|
||||
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
|
||||
@@ -440,6 +440,13 @@ ContextResult GLES2DecoderTestBase::MaybeInitDecoderWithWorkarounds(
|
||||
}
|
||||
#endif
|
||||
|
||||
+ if (init.context_type == CONTEXT_TYPE_WEBGL2 &&
|
||||
+ group_->feature_info()->gl_version_info().is_es3) {
|
||||
+ EXPECT_CALL(*gl_, Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX))
|
||||
+ .Times(1)
|
||||
+ .RetiresOnSaturation();
|
||||
+ }
|
||||
+
|
||||
if (context_->HasRobustness()) {
|
||||
EXPECT_CALL(*gl_, GetGraphicsResetStatusARB())
|
||||
.WillOnce(Return(init.lose_context_on_init ? GL_GUILTY_CONTEXT_RESET_ARB
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
index 6057cf83454f0deabc1904cb5e87b306bda4e788..304f4c7beb87212c70e91770d494254da7ed24bf 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
@@ -1432,12 +1432,6 @@ void WebGLRenderingContextBase::InitializeNewContext() {
|
||||
->GetCapabilities()
|
||||
.mesa_framebuffer_flip_y;
|
||||
|
||||
- // If WebGL 2, the PRIMITIVE_RESTART_FIXED_INDEX should be always enabled.
|
||||
- // See the section <Primitive Restart is Always Enabled> in WebGL 2 spec:
|
||||
- // https://www.khronos.org/registry/webgl/specs/latest/2.0/#4.1.4
|
||||
- if (IsWebGL2())
|
||||
- ContextGL()->Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
|
||||
-
|
||||
// This ensures that the context has a valid "lastFlushID" and won't be
|
||||
// mistakenly identified as the "least recently used" context.
|
||||
ContextGL()->Flush();
|
||||
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Thu, 13 Mar 2025 10:47:00 +0100
|
||||
Subject: fix: take Snapped status into account when showing a window
|
||||
|
||||
Adjusts HWNDMessageHandler::Show to correctly restore windows that were
|
||||
in a snapped state prior to being hidden or maximized. From Windows
|
||||
documentation at
|
||||
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowarranged:
|
||||
|
||||
> A snapped window (see Snap your windows) is considered to be arranged.
|
||||
> You should treat arranged as a window state similar to maximized. Arranged,
|
||||
> maximized, and minimized are mutually exclusive states.
|
||||
|
||||
The logic already took into account a window being maximized and
|
||||
correctly restored it, but if the window was snapped prior to this CL it
|
||||
would be removed from its snapped state when re-shown. This fixes that.
|
||||
|
||||
Upstreamed at https://chromium-review.googlesource.com/c/chromium/src/+/6330848.
|
||||
|
||||
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
|
||||
index 22ed43bdf4dbaccc598135807abc8383c52db50e..c5457e3e58b53ca04697b22a885da654c6c0655f 100644
|
||||
--- a/ui/views/win/hwnd_message_handler.cc
|
||||
+++ b/ui/views/win/hwnd_message_handler.cc
|
||||
@@ -676,7 +676,8 @@ void HWNDMessageHandler::Show(ui::mojom::WindowShowState show_state,
|
||||
SetWindowPlacement(hwnd(), &placement);
|
||||
native_show_state = SW_SHOWMAXIMIZED;
|
||||
} else {
|
||||
- const bool is_maximized = IsMaximized();
|
||||
+ const bool is_maximized_or_arranged =
|
||||
+ IsMaximized() || IsWindowArranged(hwnd());
|
||||
|
||||
// Use SW_SHOW/SW_SHOWNA instead of SW_SHOWNORMAL/SW_SHOWNOACTIVATE so that
|
||||
// the window is not restored to its original position if it is maximized.
|
||||
@@ -686,7 +687,8 @@ void HWNDMessageHandler::Show(ui::mojom::WindowShowState show_state,
|
||||
// position, some do not. See crbug.com/1296710
|
||||
switch (show_state) {
|
||||
case ui::mojom::WindowShowState::kInactive:
|
||||
- native_show_state = is_maximized ? SW_SHOWNA : SW_SHOWNOACTIVATE;
|
||||
+ native_show_state =
|
||||
+ is_maximized_or_arranged ? SW_SHOWNA : SW_SHOWNOACTIVATE;
|
||||
break;
|
||||
case ui::mojom::WindowShowState::kMaximized:
|
||||
native_show_state = SW_SHOWMAXIMIZED;
|
||||
@@ -697,9 +699,11 @@ void HWNDMessageHandler::Show(ui::mojom::WindowShowState show_state,
|
||||
case ui::mojom::WindowShowState::kNormal:
|
||||
if ((GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_TRANSPARENT) ||
|
||||
(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)) {
|
||||
- native_show_state = is_maximized ? SW_SHOWNA : SW_SHOWNOACTIVATE;
|
||||
+ native_show_state =
|
||||
+ is_maximized_or_arranged ? SW_SHOWNA : SW_SHOWNOACTIVATE;
|
||||
} else {
|
||||
- native_show_state = is_maximized ? SW_SHOW : SW_SHOWNORMAL;
|
||||
+ native_show_state =
|
||||
+ is_maximized_or_arranged ? SW_SHOW : SW_SHOWNORMAL;
|
||||
}
|
||||
break;
|
||||
case ui::mojom::WindowShowState::kFullscreen:
|
||||
@@ -0,0 +1,90 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Wilson <mjwilson@chromium.org>
|
||||
Date: Thu, 30 Jan 2025 14:09:57 -0800
|
||||
Subject: Remove DenormalEnabler from ScriptProcessorNode
|
||||
|
||||
This is a follow-up to https://crrev.com/c/6077677
|
||||
|
||||
After experimenting, ScriptProcessorNode JavaScript is already running
|
||||
in a complaint mode so the DenormalEnabler is not necessary.
|
||||
|
||||
Bug: 382005099
|
||||
Change-Id: If9774e60640446c567270a8f065500beecc8a40b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6219685
|
||||
Commit-Queue: Michael Wilson <mjwilson@chromium.org>
|
||||
Reviewed-by: Alvin Ji <alvinji@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1413754}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc b/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc
|
||||
index ea04e2cd2bfb553a58ba6fb9c63c70c5a2690442..d3d44d2a4c87bf5d4191807ec31d87c7e597fef9 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/script_processor_handler.cc
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h"
|
||||
#include "third_party/blink/renderer/modules/webaudio/script_processor_node.h"
|
||||
-#include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
|
||||
@@ -49,9 +48,7 @@ ScriptProcessorHandler::ScriptProcessorHandler(
|
||||
internal_input_bus_(AudioBus::Create(
|
||||
number_of_input_channels,
|
||||
node.context()->GetDeferredTaskHandler().RenderQuantumFrames(),
|
||||
- false)),
|
||||
- allow_denormal_in_processing_(base::FeatureList::IsEnabled(
|
||||
- features::kWebAudioAllowDenormalInProcessing)) {
|
||||
+ false)) {
|
||||
DCHECK_GE(buffer_size_,
|
||||
node.context()->GetDeferredTaskHandler().RenderQuantumFrames());
|
||||
DCHECK_LE(number_of_input_channels, BaseAudioContext::MaxNumberOfChannels());
|
||||
@@ -112,7 +109,7 @@ void ScriptProcessorHandler::Initialize() {
|
||||
AudioHandler::Initialize();
|
||||
}
|
||||
|
||||
-void ScriptProcessorHandler::ProcessInternal(uint32_t frames_to_process) {
|
||||
+void ScriptProcessorHandler::Process(uint32_t frames_to_process) {
|
||||
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("webaudio.audionode"),
|
||||
"ScriptProcessorHandler::Process");
|
||||
|
||||
@@ -241,15 +238,6 @@ void ScriptProcessorHandler::ProcessInternal(uint32_t frames_to_process) {
|
||||
"ScriptProcessorHandler::Process");
|
||||
}
|
||||
|
||||
-void ScriptProcessorHandler::Process(uint32_t frames_to_process) {
|
||||
- if (allow_denormal_in_processing_) {
|
||||
- DenormalEnabler denormal_enabler;
|
||||
- ProcessInternal(frames_to_process);
|
||||
- } else {
|
||||
- ProcessInternal(frames_to_process);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void ScriptProcessorHandler::FireProcessEvent(uint32_t double_buffer_index) {
|
||||
DCHECK(IsMainThread());
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_handler.h b/third_party/blink/renderer/modules/webaudio/script_processor_handler.h
|
||||
index 99103e947ade50f07a16a61bc8702d6097266296..78deeb9219e3d5a98ac4d3b5cd4c98dd403407e3 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/script_processor_handler.h
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/script_processor_handler.h
|
||||
@@ -66,10 +66,6 @@ class ScriptProcessorHandler final : public AudioHandler {
|
||||
const HeapVector<Member<AudioBuffer>>& input_buffers,
|
||||
const HeapVector<Member<AudioBuffer>>& output_buffers);
|
||||
|
||||
- // Used to avoid code duplication when using scoped objects that affect
|
||||
- // `Process`.
|
||||
- void ProcessInternal(uint32_t frames_to_process);
|
||||
-
|
||||
double TailTime() const override;
|
||||
double LatencyTime() const override;
|
||||
bool RequiresTailProcessing() const final;
|
||||
@@ -97,9 +93,6 @@ class ScriptProcessorHandler final : public AudioHandler {
|
||||
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
- // Cached feature flag value
|
||||
- const bool allow_denormal_in_processing_;
|
||||
-
|
||||
base::WeakPtrFactory<ScriptProcessorHandler> weak_ptr_factory_{this};
|
||||
|
||||
FRIEND_TEST_ALL_PREFIXES(ScriptProcessorNodeTest, BufferLifetime);
|
||||
@@ -0,0 +1,390 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xianzhu Wang <wangxianzhu@chromium.org>
|
||||
Date: Fri, 14 Feb 2025 08:58:16 -0800
|
||||
Subject: Revert "blink: Fix over invalidation with view transitions"
|
||||
|
||||
This patch can be removed when we bump Chromium to 135.0.7019.0
|
||||
|
||||
This reverts commit bde2842dd31e89215d395470964797c92773819f.
|
||||
|
||||
Reason for revert: The CL caused crbug.com/391907157.
|
||||
|
||||
Original change's description:
|
||||
> blink: Fix over invalidation with view transitions
|
||||
>
|
||||
> View Transition conditionally generates the view transition effect node
|
||||
> for the LayoutView during the transition. This results in invalidation
|
||||
> of it's scrolling background layer at the start/end of the transition.
|
||||
>
|
||||
> Avoid this by always generating this node for the LayoutView. This is
|
||||
> not necessary for the child LayoutObjects. If they are composited, they
|
||||
> already have an EffectNode which avoids invalidation from paint property
|
||||
> node changes.
|
||||
>
|
||||
> Fixed: 361370195
|
||||
> Change-Id: I1c8c309dea5bb1d2572995bbaafb2fb8003be96e
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5996658
|
||||
> Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
|
||||
> Auto-Submit: Khushal Sagar <khushalsagar@chromium.org>
|
||||
> Commit-Queue: Khushal Sagar <khushalsagar@chromium.org>
|
||||
> Cr-Commit-Position: refs/heads/main@{#1380843}
|
||||
|
||||
Bug: 391907157, 361370195
|
||||
Change-Id: Ifc7bb6fedb326867e5ed608b2c8152844ae2dd95
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6262017
|
||||
Auto-Submit: Xianzhu Wang <wangxianzhu@chromium.org>
|
||||
Commit-Queue: Vladimir Levin <vmpstr@chromium.org>
|
||||
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1420533}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
|
||||
index 4dd99f130cb99355e4d58766a322e8db1e69bca9..9b9851dbb92977d76a842b0a943e969493231275 100644
|
||||
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
|
||||
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
|
||||
@@ -1834,32 +1834,25 @@ void FragmentPaintPropertyTreeBuilder::UpdateViewTransitionEffect() {
|
||||
properties_->ViewTransitionEffect()
|
||||
->SelfOrAncestorParticipatesInViewTransition();
|
||||
|
||||
- const bool is_view_transition_element =
|
||||
+ const bool needs_view_transition_effect =
|
||||
full_context_.direct_compositing_reasons &
|
||||
CompositingReason::kViewTransitionElement;
|
||||
|
||||
- const bool needs_view_transition_effect =
|
||||
- is_view_transition_element ||
|
||||
- (object_.IsLayoutView() && !IsInLocalSubframe(object_) &&
|
||||
- !object_.GetDocument().IsSVGDocument());
|
||||
-
|
||||
if (needs_view_transition_effect) {
|
||||
auto* transition =
|
||||
ViewTransitionUtils::GetTransition(object_.GetDocument());
|
||||
- DCHECK(!is_view_transition_element || transition);
|
||||
+ DCHECK(transition);
|
||||
|
||||
EffectPaintPropertyNode::State state;
|
||||
+ state.direct_compositing_reasons =
|
||||
+ CompositingReason::kViewTransitionElement;
|
||||
state.local_transform_space = context_.current.transform;
|
||||
state.output_clip = context_.current.clip;
|
||||
state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
|
||||
object_.UniqueId(),
|
||||
CompositorElementIdNamespace::kViewTransitionElement);
|
||||
- if (is_view_transition_element) {
|
||||
- state.direct_compositing_reasons =
|
||||
- CompositingReason::kViewTransitionElement;
|
||||
- state.view_transition_element_resource_id =
|
||||
- transition->GetSnapshotId(object_);
|
||||
- }
|
||||
+ state.view_transition_element_resource_id =
|
||||
+ transition->GetSnapshotId(object_);
|
||||
|
||||
// The value isn't set on the root, since clipping rules are different for
|
||||
// the root view transition element.
|
||||
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
|
||||
index b3da3b381113fb6ea17d3d6de7bf2cf43e175362..aa57763835d2e8dbf4d021d58c14e1dd605d5cd6 100644
|
||||
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
|
||||
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
|
||||
@@ -77,17 +77,6 @@ const ScrollPaintPropertyNode* PaintPropertyTreeBuilderTest::DocScroll(
|
||||
return document->GetLayoutView()->FirstFragment().PaintProperties()->Scroll();
|
||||
}
|
||||
|
||||
-const EffectPaintPropertyNode* PaintPropertyTreeBuilderTest::DocEffect(
|
||||
- const Document* document) {
|
||||
- if (!document) {
|
||||
- document = &GetDocument();
|
||||
- }
|
||||
- return document->GetLayoutView()
|
||||
- ->FirstFragment()
|
||||
- .PaintProperties()
|
||||
- ->ViewTransitionEffect();
|
||||
-}
|
||||
-
|
||||
const ObjectPaintProperties*
|
||||
PaintPropertyTreeBuilderTest::PaintPropertiesForElement(const char* name) {
|
||||
return GetDocument()
|
||||
@@ -1058,7 +1047,8 @@ TEST_P(PaintPropertyTreeBuilderTest, EffectNodesInSVG) {
|
||||
PaintPropertiesForElement("groupWithOpacity");
|
||||
EXPECT_EQ(0.6f, group_with_opacity_properties->Effect()->Opacity());
|
||||
EXPECT_EQ(svg_clip, group_with_opacity_properties->Effect()->OutputClip());
|
||||
- EXPECT_EQ(DocEffect(), group_with_opacity_properties->Effect()->Parent());
|
||||
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(),
|
||||
+ group_with_opacity_properties->Effect()->Parent());
|
||||
|
||||
EXPECT_EQ(nullptr, PaintPropertiesForElement("rectWithoutOpacity"));
|
||||
|
||||
@@ -4762,7 +4752,7 @@ TEST_P(PaintPropertyTreeBuilderTest, Reflection) {
|
||||
filter_properties->PaintOffsetTranslation()->Parent());
|
||||
EXPECT_EQ(gfx::Vector2dF(8, 8),
|
||||
filter_properties->PaintOffsetTranslation()->Get2dTranslation());
|
||||
- EXPECT_EQ(filter_properties->Filter()->Parent(), DocEffect());
|
||||
+ EXPECT_TRUE(filter_properties->Filter()->Parent()->IsRoot());
|
||||
EXPECT_EQ(filter_properties->PaintOffsetTranslation(),
|
||||
&filter_properties->Filter()->LocalTransformSpace());
|
||||
EXPECT_EQ(DocContentClip(), filter_properties->Filter()->OutputClip());
|
||||
@@ -4775,7 +4765,7 @@ TEST_P(PaintPropertyTreeBuilderTest, SimpleFilter) {
|
||||
const ObjectPaintProperties* filter_properties =
|
||||
GetLayoutObjectByElementId("filter")->FirstFragment().PaintProperties();
|
||||
EXPECT_FALSE(filter_properties->PaintOffsetTranslation());
|
||||
- EXPECT_EQ(filter_properties->Filter()->Parent(), DocEffect());
|
||||
+ EXPECT_TRUE(filter_properties->Filter()->Parent()->IsRoot());
|
||||
EXPECT_FALSE(filter_properties->PixelMovingFilterClipExpander());
|
||||
EXPECT_EQ(DocScrollTranslation(),
|
||||
&filter_properties->Filter()->LocalTransformSpace());
|
||||
@@ -4792,7 +4782,7 @@ TEST_P(PaintPropertyTreeBuilderTest, PixelMovingFilter) {
|
||||
|
||||
auto* filter = filter_properties->Filter();
|
||||
ASSERT_TRUE(filter);
|
||||
- EXPECT_EQ(filter->Parent(), DocEffect());
|
||||
+ EXPECT_TRUE(filter->Parent()->IsRoot());
|
||||
EXPECT_TRUE(filter->HasFilterThatMovesPixels());
|
||||
EXPECT_EQ(DocScrollTranslation(), &filter->LocalTransformSpace());
|
||||
EXPECT_EQ(DocContentClip(), filter->OutputClip());
|
||||
@@ -4847,7 +4837,7 @@ TEST_P(PaintPropertyTreeBuilderTest, FilterReparentClips) {
|
||||
GetLayoutObjectByElementId("clip")->FirstFragment().PaintProperties();
|
||||
const ObjectPaintProperties* filter_properties =
|
||||
GetLayoutObjectByElementId("filter")->FirstFragment().PaintProperties();
|
||||
- EXPECT_TRUE(DocEffect());
|
||||
+ EXPECT_TRUE(filter_properties->Filter()->Parent()->IsRoot());
|
||||
EXPECT_EQ(clip_properties->OverflowClip(),
|
||||
filter_properties->Filter()->OutputClip());
|
||||
EXPECT_EQ(DocScrollTranslation(),
|
||||
@@ -5089,7 +5079,7 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskSimple) {
|
||||
|
||||
EXPECT_EQ(properties->Effect(),
|
||||
&target->FirstFragment().LocalBorderBoxProperties().Effect());
|
||||
- EXPECT_TRUE(DocEffect());
|
||||
+ EXPECT_TRUE(properties->Effect()->Parent()->IsRoot());
|
||||
EXPECT_EQ(SkBlendMode::kSrcOver, properties->Effect()->BlendMode());
|
||||
EXPECT_EQ(mask_clip->Parent(), properties->Effect()->OutputClip());
|
||||
|
||||
@@ -5118,7 +5108,7 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskWithOutset) {
|
||||
|
||||
EXPECT_EQ(properties->Effect(),
|
||||
&target->FirstFragment().LocalBorderBoxProperties().Effect());
|
||||
- EXPECT_TRUE(DocEffect());
|
||||
+ EXPECT_TRUE(properties->Effect()->Parent()->IsRoot());
|
||||
EXPECT_EQ(SkBlendMode::kSrcOver, properties->Effect()->BlendMode());
|
||||
EXPECT_EQ(mask_clip->Parent(), properties->Effect()->OutputClip());
|
||||
|
||||
@@ -5172,7 +5162,7 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskEscapeClip) {
|
||||
|
||||
EXPECT_EQ(target_properties->Effect(),
|
||||
&target->FirstFragment().LocalBorderBoxProperties().Effect());
|
||||
- EXPECT_TRUE(DocEffect());
|
||||
+ EXPECT_TRUE(target_properties->Effect()->Parent()->IsRoot());
|
||||
EXPECT_EQ(SkBlendMode::kSrcOver, target_properties->Effect()->BlendMode());
|
||||
EXPECT_EQ(nullptr, target_properties->Effect()->OutputClip());
|
||||
|
||||
@@ -5215,7 +5205,7 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskInline) {
|
||||
|
||||
EXPECT_EQ(properties->Effect(),
|
||||
&target->FirstFragment().LocalBorderBoxProperties().Effect());
|
||||
- EXPECT_TRUE(DocEffect());
|
||||
+ EXPECT_TRUE(properties->Effect()->Parent()->IsRoot());
|
||||
EXPECT_EQ(SkBlendMode::kSrcOver, properties->Effect()->BlendMode());
|
||||
EXPECT_EQ(mask_clip->Parent(), properties->Effect()->OutputClip());
|
||||
|
||||
@@ -5316,7 +5306,8 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGBlending) {
|
||||
ASSERT_TRUE(svg_root_properties->Effect());
|
||||
EXPECT_EQ(SkBlendMode::kSrcOver, svg_root_properties->Effect()->BlendMode());
|
||||
|
||||
- EXPECT_EQ(DocEffect(), svg_root_properties->Effect()->Parent());
|
||||
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(),
|
||||
+ svg_root_properties->Effect()->Parent());
|
||||
EXPECT_EQ(svg_root_properties->Effect(), rect_properties->Effect()->Parent());
|
||||
}
|
||||
|
||||
@@ -5338,7 +5329,8 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGRootBlending) {
|
||||
ASSERT_TRUE(svg_root_properties->Effect());
|
||||
EXPECT_EQ(SkBlendMode::kMultiply, svg_root_properties->Effect()->BlendMode());
|
||||
|
||||
- EXPECT_EQ(DocEffect(), html_properties->Effect()->Parent());
|
||||
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(),
|
||||
+ html_properties->Effect()->Parent());
|
||||
EXPECT_EQ(html_properties->Effect(), svg_root_properties->Effect()->Parent());
|
||||
}
|
||||
|
||||
@@ -6454,7 +6446,7 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGRootCompositedClipPathSimple) {
|
||||
|
||||
const auto* effect = properties->Effect();
|
||||
ASSERT_NE(nullptr, effect);
|
||||
- EXPECT_EQ(DocEffect(), effect->Parent());
|
||||
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(), effect->Parent());
|
||||
EXPECT_EQ(transform, &effect->LocalTransformSpace());
|
||||
EXPECT_EQ(clip_path_clip, effect->OutputClip());
|
||||
EXPECT_EQ(SkBlendMode::kSrcOver, effect->BlendMode());
|
||||
@@ -6492,7 +6484,7 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGRootCompositedClipPathComplex) {
|
||||
const auto* effect = properties->Effect();
|
||||
ASSERT_NE(nullptr, effect);
|
||||
EXPECT_TRUE(effect->HasDirectCompositingReasons());
|
||||
- EXPECT_EQ(DocEffect(), effect->Parent());
|
||||
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(), effect->Parent());
|
||||
EXPECT_EQ(transform, &effect->LocalTransformSpace());
|
||||
EXPECT_EQ(clip_path_clip, effect->OutputClip());
|
||||
EXPECT_EQ(SkBlendMode::kSrcOver, effect->BlendMode());
|
||||
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
|
||||
index 7ab50dfc1dbfacba271f1a189f990e8dd78c4b21..252f6e568fbecb29c210e52bc8a43b34d002417d 100644
|
||||
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
|
||||
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
|
||||
@@ -34,7 +34,6 @@ class PaintPropertyTreeBuilderTest : public PaintControllerPaintTest {
|
||||
const Document* = nullptr);
|
||||
const ClipPaintPropertyNode* DocContentClip(const Document* = nullptr);
|
||||
const ScrollPaintPropertyNode* DocScroll(const Document* = nullptr);
|
||||
- const EffectPaintPropertyNode* DocEffect(const Document* = nullptr);
|
||||
|
||||
// Return the local border box's paint offset. For more details, see
|
||||
// ObjectPaintProperties::localBorderBoxProperties().
|
||||
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_test.cc b/third_party/blink/renderer/core/view_transition/view_transition_test.cc
|
||||
index a6fa914af41568cde2fbbe59c7bbbb1de5f59d0f..bb0473719d38c049c0a92bd5f533a351e8cd8484 100644
|
||||
--- a/third_party/blink/renderer/core/view_transition/view_transition_test.cc
|
||||
+++ b/third_party/blink/renderer/core/view_transition/view_transition_test.cc
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
|
||||
#include "third_party/blink/renderer/core/dom/element.h"
|
||||
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
|
||||
+#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
|
||||
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
|
||||
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
|
||||
#include "third_party/blink/renderer/core/html/html_element.h"
|
||||
@@ -32,7 +33,6 @@
|
||||
#include "third_party/blink/renderer/core/layout/physical_box_fragment.h"
|
||||
#include "third_party/blink/renderer/core/navigation_api/navigation_api.h"
|
||||
#include "third_party/blink/renderer/core/navigation_api/navigation_history_entry.h"
|
||||
-#include "third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h"
|
||||
#include "third_party/blink/renderer/core/paint/paint_layer.h"
|
||||
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
|
||||
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
|
||||
@@ -706,100 +706,6 @@ TEST_P(ViewTransitionTest, ViewTransitionElementInvalidation) {
|
||||
UpdateAllLifecyclePhasesAndFinishDirectives();
|
||||
}
|
||||
|
||||
-namespace {
|
||||
-void AssertOnlyViewTransitionElementsInvalidated(
|
||||
- PaintArtifactCompositor* compositor) {
|
||||
- const char kViewTransition[] = "view-transition";
|
||||
- const char kLayoutViewTransition[] = "ViewTransition";
|
||||
- compositor->ForAllContentLayersForTesting(
|
||||
- [&](ContentLayerClientImpl* client) {
|
||||
- if (::testing::Matcher<std::string>(
|
||||
- ::testing::ContainsRegex(kViewTransition))
|
||||
- .Matches(client->Layer().DebugName())) {
|
||||
- return;
|
||||
- }
|
||||
- if (::testing::Matcher<std::string>(
|
||||
- ::testing::ContainsRegex(kLayoutViewTransition))
|
||||
- .Matches(client->Layer().DebugName())) {
|
||||
- return;
|
||||
- }
|
||||
- auto* tracking = client->GetRasterInvalidator().GetTracking();
|
||||
- EXPECT_FALSE(tracking->HasInvalidations())
|
||||
- << client->Layer().DebugName();
|
||||
- for (const auto& invalidation : tracking->Invalidations()) {
|
||||
- LOG(ERROR) << "Invalidation " << invalidation;
|
||||
- }
|
||||
- });
|
||||
-}
|
||||
-} // namespace
|
||||
-
|
||||
-TEST_P(ViewTransitionTest, NoInvalidationOnRoot) {
|
||||
- SetHtmlInnerHTML(R"HTML(
|
||||
- <style>
|
||||
- /* TODO(crbug.com/1336462): html.css is parsed before runtime flags are enabled */
|
||||
- html { view-transition-name: root; backgrond: grey; }
|
||||
- #element {
|
||||
- width: 100px;
|
||||
- height: 100px;
|
||||
- view-transition-name: shared;
|
||||
- will-change: transform;
|
||||
- }
|
||||
- </style>
|
||||
-
|
||||
- <div id=element></div>
|
||||
- <div>test</div>
|
||||
- )HTML");
|
||||
-
|
||||
- // Run all lifecycle phases to ensure paint is clean.
|
||||
- UpdateAllLifecyclePhasesForTest();
|
||||
-
|
||||
- GetDocument().View()->SetTracksRasterInvalidations(true);
|
||||
-
|
||||
- ScriptState* script_state = GetScriptState();
|
||||
- ScriptState::Scope scope(script_state);
|
||||
-
|
||||
- auto start_setup_lambda =
|
||||
- [](const v8::FunctionCallbackInfo<v8::Value>& info) {};
|
||||
-
|
||||
- // This callback sets the elements for the start phase of the transition.
|
||||
- auto start_setup_callback =
|
||||
- v8::Function::New(script_state->GetContext(), start_setup_lambda, {})
|
||||
- .ToLocalChecked();
|
||||
-
|
||||
- auto* compositor = GetLocalFrameView()->GetPaintArtifactCompositor();
|
||||
- auto* transition = ViewTransitionSupplement::startViewTransition(
|
||||
- script_state, GetDocument(),
|
||||
- V8ViewTransitionCallback::Create(start_setup_callback),
|
||||
- ASSERT_NO_EXCEPTION);
|
||||
-
|
||||
- UpdateAllLifecyclePhasesForTest();
|
||||
- {
|
||||
- SCOPED_TRACE("old dom capture");
|
||||
- AssertOnlyViewTransitionElementsInvalidated(compositor);
|
||||
- }
|
||||
-
|
||||
- // Finish the prepare phase, mutate the DOM and start the animation.
|
||||
- UpdateAllLifecyclePhasesAndFinishDirectives();
|
||||
- test::RunPendingTasks();
|
||||
- EXPECT_EQ(GetState(transition), State::kAnimating);
|
||||
-
|
||||
- // The start phase should generate pseudo elements for rendering new live
|
||||
- // content.
|
||||
- UpdateAllLifecyclePhasesAndFinishDirectives();
|
||||
- {
|
||||
- SCOPED_TRACE("animation started");
|
||||
- AssertOnlyViewTransitionElementsInvalidated(compositor);
|
||||
- }
|
||||
-
|
||||
- // Finish the animations which should remove the pseudo element tree.
|
||||
- FinishTransition();
|
||||
- UpdateAllLifecyclePhasesAndFinishDirectives();
|
||||
- {
|
||||
- SCOPED_TRACE("transition finished");
|
||||
- AssertOnlyViewTransitionElementsInvalidated(compositor);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
TEST_P(ViewTransitionTest, InspectorStyleResolver) {
|
||||
SetHtmlInnerHTML(R"HTML(
|
||||
<style>
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
|
||||
index 4952082b87f80611b16a0730615bc0eaabe79791..d8568a1052ec82a8d56736aee7929ca9c4a4656c 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
|
||||
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
|
||||
@@ -1524,15 +1524,6 @@ void PaintArtifactCompositor::ShowDebugData() {
|
||||
}
|
||||
#endif
|
||||
|
||||
-void PaintArtifactCompositor::ForAllContentLayersForTesting(
|
||||
- base::FunctionRef<void(ContentLayerClientImpl*)> func) const {
|
||||
- for (auto& pending_layer : pending_layers_) {
|
||||
- if (auto* client = pending_layer.GetContentLayerClient()) {
|
||||
- func(client);
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
ContentLayerClientImpl* PaintArtifactCompositor::ContentLayerClientForTesting(
|
||||
wtf_size_t i) const {
|
||||
for (auto& pending_layer : pending_layers_) {
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
|
||||
index fc4339bff1763d6dd6e99e3332e0e3bd1729e859..7d8a4526c9adcedf3ee0955aa2e7736a1d5e9e20 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
|
||||
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
|
||||
@@ -231,8 +231,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
|
||||
void ShowDebugData();
|
||||
#endif
|
||||
|
||||
- void ForAllContentLayersForTesting(
|
||||
- base::FunctionRef<void(ContentLayerClientImpl*)> func) const;
|
||||
// Returns the ith ContentLayerClientImpl for testing.
|
||||
ContentLayerClientImpl* ContentLayerClientForTesting(wtf_size_t i) const;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
chore_allow_customizing_microtask_policy_per_context.patch
|
||||
deps_add_v8_object_setinternalfieldfornodecore.patch
|
||||
revert_fastapi_promote_deprecation_of_fastapitypedarray.patch
|
||||
cherry-pick-2b4812d502b2.patch
|
||||
cherry-pick-91343bb45c78.patch
|
||||
|
||||
38
patches/v8/cherry-pick-2b4812d502b2.patch
Normal file
38
patches/v8/cherry-pick-2b4812d502b2.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 2b4812d502b2bbd2eeace4d383dd1bb3252702ba Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Flückiger <olivf@chromium.org>
|
||||
Date: Thu, 27 Feb 2025 09:19:22 +0100
|
||||
Subject: [PATCH] merged: [maglev] Add missing ClearAllocationBlock
|
||||
|
||||
Fixed: 398065918
|
||||
(cherry picked from commit eb9b25970b0ad4a3f8ce23d8de3583c62e5d6b87)
|
||||
|
||||
Change-Id: I20f3979984c1df11509f1630cf4c4c4460d6a83a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6304712
|
||||
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
|
||||
Auto-Submit: Olivier Flückiger <olivf@chromium.org>
|
||||
Commit-Queue: Olivier Flückiger <olivf@chromium.org>
|
||||
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/13.4@{#29}
|
||||
Cr-Branched-From: 0f87a54dade4353b6ece1d7591ca8c66f90c1c93-refs/heads/13.4.114@{#1}
|
||||
Cr-Branched-From: 27af2e9363b2701abc5f3feb701b1dad7d1a9fe8-refs/heads/main@{#98459}
|
||||
---
|
||||
|
||||
diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc
|
||||
index bf6a86f..1535afc 100644
|
||||
--- a/src/maglev/maglev-graph-builder.cc
|
||||
+++ b/src/maglev/maglev-graph-builder.cc
|
||||
@@ -12487,7 +12487,13 @@
|
||||
CreateHeapNumber(node->Cast<Float64Constant>()->value()),
|
||||
allocation_type);
|
||||
} else {
|
||||
- node = GetTaggedValue(node);
|
||||
+ ValueNode* new_node = GetTaggedValue(node);
|
||||
+ if (new_node != node && new_node->properties().can_allocate()) {
|
||||
+ // TODO(olivf): Remove this and instead always clear when we
|
||||
+ // emit an allocating instruction.
|
||||
+ ClearCurrentAllocationBlock();
|
||||
+ }
|
||||
+ node = new_node;
|
||||
}
|
||||
values[i] = node;
|
||||
}
|
||||
48
patches/v8/cherry-pick-91343bb45c78.patch
Normal file
48
patches/v8/cherry-pick-91343bb45c78.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
From 91343bb45c78ac5cf3d214f68161d8150d81fa8c Mon Sep 17 00:00:00 2001
|
||||
From: Darius Mercadier <dmercadier@chromium.org>
|
||||
Date: Tue, 18 Feb 2025 09:32:04 +0100
|
||||
Subject: [PATCH] [M132-LTS][turbofan] Disable escape analysis for TrustedHeapConstant
|
||||
|
||||
More precisely: prevent eliding objects that contain
|
||||
TrustedHeapConstant, because it can lead to this constant flowing into
|
||||
a Phis where other inputs are regular HeapConstant, which confuses
|
||||
decompression optimization and leads to memory corruption.
|
||||
|
||||
(cherry picked from commit b75e527fb521dca5e7621928846c0c7c6becc8dd)
|
||||
|
||||
Fixed: chromium:390743124
|
||||
Change-Id: Ic60e4d7dd156367f7d4bb385d422591384c3033c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6278358
|
||||
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Auto-Submit: Darius Mercadier <dmercadier@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#98748}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6317725
|
||||
Reviewed-by: Darius Mercadier <dmercadier@chromium.org>
|
||||
Commit-Queue: Gyuyoung Kim (xWF) <qkim@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/13.2@{#82}
|
||||
Cr-Branched-From: 24068c59cedad9ee976ddc05431f5f497b1ebd71-refs/heads/13.2.152@{#1}
|
||||
Cr-Branched-From: 6054ba94db0969220be4f94dc1677fc4696bdc4f-refs/heads/main@{#97085}
|
||||
---
|
||||
|
||||
diff --git a/src/compiler/escape-analysis.cc b/src/compiler/escape-analysis.cc
|
||||
index eb223bc..c9a7bc9 100644
|
||||
--- a/src/compiler/escape-analysis.cc
|
||||
+++ b/src/compiler/escape-analysis.cc
|
||||
@@ -622,6 +622,16 @@
|
||||
Node* value = current->ValueInput(1);
|
||||
const VirtualObject* vobject = current->GetVirtualObject(object);
|
||||
Variable var;
|
||||
+ if (value->opcode() == IrOpcode::kTrustedHeapConstant) {
|
||||
+ // TODO(dmercadier): enable escaping objects containing
|
||||
+ // TrustedHeapConstants. This is currently disabled because it leads to
|
||||
+ // bugs when Trusted HeapConstant and regular HeapConstant flow into the
|
||||
+ // same Phi, which can then be marked as Compressed, messing up the
|
||||
+ // tagging of the Trusted HeapConstant.
|
||||
+ current->SetEscaped(object);
|
||||
+ current->SetEscaped(value);
|
||||
+ break;
|
||||
+ }
|
||||
// BoundedSize fields cannot currently be materialized by the deoptimizer,
|
||||
// so we must not dematerialze them.
|
||||
if (vobject && !vobject->HasEscaped() &&
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"bullseye_amd64": {
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "7c93e71bf9c4cd0825aa59fb2479054d981e36ba9be34ecf4c1d73051cae40fe",
|
||||
"Sha256Sum": "0be326b106f0df7b8547ec8d3b58ccb95435c8414a45cda675c4805821d4d860",
|
||||
"SysrootDir": "debian_bullseye_amd64-sysroot",
|
||||
"Tarball": "debian_bullseye_amd64_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_arm64": {
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "d649177e37aef2c043e54e670e42934f18558c0e730c1b854719ca7463e2b1eb",
|
||||
"Sha256Sum": "1225cd518c1609e54033bb6a1c687875d4f4c21b2dbd5d5d81c4b5927d0fc0f1",
|
||||
"SysrootDir": "debian_bullseye_arm64-sysroot",
|
||||
"Tarball": "debian_bullseye_arm64_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
@@ -22,28 +22,28 @@
|
||||
},
|
||||
"bullseye_armhf": {
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "fe3b9203e30e70f533776d565501bc1e3d4ebf6eeb909b2c2bfca0df807e1be0",
|
||||
"Sha256Sum": "ed5a71ce5fc6d1691817c3b203139328ee88395c9e54ff726f67c84ee1561e65",
|
||||
"SysrootDir": "debian_bullseye_armhf-sysroot",
|
||||
"Tarball": "debian_bullseye_armhf_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_i386": {
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "4efcb1870129da1ad5c3b634903a4efcc0ca9abd67dd5a993cca144ea9b5d31f",
|
||||
"Sha256Sum": "57f800042b0c4bd00a8755da165823cc70decc0481b78d751924db7470af6b5e",
|
||||
"SysrootDir": "debian_bullseye_i386-sysroot",
|
||||
"Tarball": "debian_bullseye_i386_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_mips64el": {
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "c3a3bf3b0aa40ec90747c951942d40077ff6796b336818eaba6fa21564249a00",
|
||||
"Sha256Sum": "187b8644a949d0124cb00fa099a8a5842e9a88bb48d8d1c682604ebf546796b7",
|
||||
"SysrootDir": "debian_bullseye_mips64el-sysroot",
|
||||
"Tarball": "debian_bullseye_mips64el_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
},
|
||||
"bullseye_mipsel": {
|
||||
"Key": "20230611T210420Z-2",
|
||||
"Sha256Sum": "564de884ed1810e1cf3a20d94edfa21972ac2be9568bf1526d093c31f15ef225",
|
||||
"Sha256Sum": "f08771dc7a813e7f0fd540b49a1b611416979630b0009e9ecc51f999a7543081",
|
||||
"SysrootDir": "debian_bullseye_mipsel-sysroot",
|
||||
"Tarball": "debian_bullseye_mipsel_sysroot.tar.xz",
|
||||
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
|
||||
|
||||
@@ -43,7 +43,7 @@ class UtilityProcessWrapper final
|
||||
: public gin::Wrappable<UtilityProcessWrapper>,
|
||||
public gin_helper::Pinnable<UtilityProcessWrapper>,
|
||||
public gin_helper::EventEmitterMixin<UtilityProcessWrapper>,
|
||||
public mojo::MessageReceiver,
|
||||
private mojo::MessageReceiver,
|
||||
public node::mojom::NodeServiceClient,
|
||||
public content::ServiceProcessHost::Observer {
|
||||
public:
|
||||
|
||||
@@ -2181,6 +2181,17 @@ void WebContents::DidFinishNavigation(
|
||||
if (is_main_frame) {
|
||||
Emit("did-navigate", url, http_response_code, http_status_text);
|
||||
}
|
||||
|
||||
content::NavigationEntry* entry = navigation_handle->GetNavigationEntry();
|
||||
|
||||
// This check is needed due to an issue in Chromium
|
||||
// Upstream is open to patching:
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1178663
|
||||
// If a history entry has been made and the forward/back call has been
|
||||
// made, proceed with setting the new title
|
||||
if (entry &&
|
||||
(entry->GetTransitionType() & ui::PAGE_TRANSITION_FORWARD_BACK))
|
||||
WebContents::TitleWasSet(entry);
|
||||
}
|
||||
if (is_guest())
|
||||
Emit("load-commit", url, is_main_frame);
|
||||
@@ -2201,15 +2212,6 @@ void WebContents::DidFinishNavigation(
|
||||
frame_process_id, frame_routing_id);
|
||||
}
|
||||
}
|
||||
content::NavigationEntry* entry = navigation_handle->GetNavigationEntry();
|
||||
|
||||
// This check is needed due to an issue in Chromium
|
||||
// Check the Chromium issue to keep updated:
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1178663
|
||||
// If a history entry has been made and the forward/back call has been made,
|
||||
// proceed with setting the new title
|
||||
if (entry && (entry->GetTransitionType() & ui::PAGE_TRANSITION_FORWARD_BACK))
|
||||
WebContents::TitleWasSet(entry);
|
||||
}
|
||||
|
||||
void WebContents::TitleWasSet(content::NavigationEntry* entry) {
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace electron {
|
||||
// A non-blink version of blink::MessagePort.
|
||||
class MessagePort final : public gin::Wrappable<MessagePort>,
|
||||
public gin_helper::CleanedUpAtExit,
|
||||
public mojo::MessageReceiver {
|
||||
private mojo::MessageReceiver {
|
||||
public:
|
||||
~MessagePort() override;
|
||||
static gin::Handle<MessagePort> Create(v8::Isolate* isolate);
|
||||
|
||||
@@ -365,10 +365,10 @@ ElectronBrowserContext::ElectronBrowserContext(
|
||||
BrowserContextDependencyManager::GetInstance()
|
||||
->CreateBrowserContextServices(this);
|
||||
|
||||
extension_system_ = static_cast<extensions::ElectronExtensionSystem*>(
|
||||
auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
|
||||
extensions::ExtensionSystem::Get(this));
|
||||
extension_system_->InitForRegularProfile(true /* extensions_enabled */);
|
||||
extension_system_->FinishInitialization();
|
||||
extension_system->InitForRegularProfile(true /* extensions_enabled */);
|
||||
extension_system->FinishInitialization();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -377,11 +377,6 @@ ElectronBrowserContext::~ElectronBrowserContext() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
NotifyWillBeDestroyed();
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// the DestroyBrowserContextServices() call below frees this.
|
||||
extension_system_ = nullptr;
|
||||
#endif
|
||||
|
||||
// Notify any keyed services of browser context destruction.
|
||||
BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
|
||||
this);
|
||||
@@ -834,34 +829,23 @@ ElectronBrowserContext* ElectronBrowserContext::From(
|
||||
const std::string& partition,
|
||||
bool in_memory,
|
||||
base::Value::Dict options) {
|
||||
PartitionKey key(partition, in_memory);
|
||||
ElectronBrowserContext* browser_context = browser_context_map()[key].get();
|
||||
if (browser_context) {
|
||||
return browser_context;
|
||||
auto& context = browser_context_map()[PartitionKey(partition, in_memory)];
|
||||
if (!context) {
|
||||
context.reset(new ElectronBrowserContext{std::cref(partition), in_memory,
|
||||
std::move(options)});
|
||||
}
|
||||
|
||||
auto* new_context = new ElectronBrowserContext(std::cref(partition),
|
||||
in_memory, std::move(options));
|
||||
browser_context_map()[key] =
|
||||
std::unique_ptr<ElectronBrowserContext>(new_context);
|
||||
return new_context;
|
||||
return context.get();
|
||||
}
|
||||
|
||||
ElectronBrowserContext* ElectronBrowserContext::FromPath(
|
||||
const base::FilePath& path,
|
||||
base::Value::Dict options) {
|
||||
PartitionKey key(path);
|
||||
|
||||
ElectronBrowserContext* browser_context = browser_context_map()[key].get();
|
||||
if (browser_context) {
|
||||
return browser_context;
|
||||
auto& context = browser_context_map()[PartitionKey(path)];
|
||||
if (!context) {
|
||||
context.reset(
|
||||
new ElectronBrowserContext{std::cref(path), false, std::move(options)});
|
||||
}
|
||||
|
||||
auto* new_context =
|
||||
new ElectronBrowserContext(std::cref(path), false, std::move(options));
|
||||
browser_context_map()[key] =
|
||||
std::unique_ptr<ElectronBrowserContext>(new_context);
|
||||
return new_context;
|
||||
return context.get();
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -13,12 +13,10 @@
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/media_stream_request.h"
|
||||
#include "content/public/browser/resource_context.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/shell/browser/media/media_device_id_salt.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "services/network/public/mojom/ssl_config.mojom.h"
|
||||
@@ -43,12 +41,6 @@ namespace storage {
|
||||
class SpecialStoragePolicy;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
namespace extensions {
|
||||
class ElectronExtensionSystem;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace electron {
|
||||
|
||||
class ElectronDownloadManagerDelegate;
|
||||
@@ -154,15 +146,6 @@ class ElectronBrowserContext : public content::BrowserContext {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
extensions::ElectronExtensionSystem* extension_system() {
|
||||
// Guard usages of extension_system() with !IsOffTheRecord()
|
||||
// There is no extension system for in-memory sessions
|
||||
DCHECK(!IsOffTheRecord());
|
||||
return extension_system_;
|
||||
}
|
||||
#endif
|
||||
|
||||
ProtocolRegistry* protocol_registry() const {
|
||||
return protocol_registry_.get();
|
||||
}
|
||||
@@ -237,11 +220,6 @@ class ElectronBrowserContext : public content::BrowserContext {
|
||||
bool use_cache_ = true;
|
||||
int max_cache_size_ = 0;
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// Owned by the KeyedService system.
|
||||
raw_ptr<extensions::ElectronExtensionSystem> extension_system_;
|
||||
#endif
|
||||
|
||||
// Shared URLLoaderFactory.
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
|
||||
|
||||
|
||||
@@ -344,9 +344,6 @@ int ElectronBrowserMainParts::PreCreateThreads() {
|
||||
// Force MediaCaptureDevicesDispatcher to be created on UI thread.
|
||||
MediaCaptureDevicesDispatcher::GetInstance();
|
||||
|
||||
// Force MediaCaptureDevicesDispatcher to be created on UI thread.
|
||||
MediaCaptureDevicesDispatcher::GetInstance();
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
ui::InitIdleMonitor();
|
||||
Browser::Get()->ApplyForcedRTL();
|
||||
|
||||
@@ -823,13 +823,7 @@ std::u16string FileSystemAccessPermissionContext::GetPickerTitle(
|
||||
? IDS_FILE_SYSTEM_ACCESS_CHOOSER_OPEN_WRITABLE_DIRECTORY_TITLE
|
||||
: IDS_FILE_SYSTEM_ACCESS_CHOOSER_OPEN_READABLE_DIRECTORY_TITLE);
|
||||
break;
|
||||
case blink::mojom::TypeSpecificFilePickerOptionsUnion::Tag::
|
||||
kSaveFilePickerOptions:
|
||||
title = l10n_util::GetStringUTF16(
|
||||
IDS_FILE_SYSTEM_ACCESS_CHOOSER_OPEN_SAVE_FILE_TITLE);
|
||||
break;
|
||||
case blink::mojom::TypeSpecificFilePickerOptionsUnion::Tag::
|
||||
kOpenFilePickerOptions:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return title;
|
||||
|
||||
@@ -9,14 +9,101 @@
|
||||
|
||||
#include "base/containers/fixed_flat_map.h"
|
||||
#include "base/containers/map_util.h"
|
||||
#include "base/strings/cstring_view.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "chrome/grit/platform_locale_settings.h"
|
||||
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
|
||||
#include "third_party/icu/source/common/unicode/uchar.h"
|
||||
#include "third_party/icu/source/common/unicode/uscript.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
|
||||
// If a font name in prefs default values starts with a comma, consider it's a
|
||||
// comma-separated font list and resolve it to the first available font.
|
||||
#define PREFS_FONT_LIST 1
|
||||
#include "ui/gfx/font_list.h"
|
||||
#else
|
||||
#define PREFS_FONT_LIST 0
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// On Windows with antialiasing we want to use an alternate fixed font like
|
||||
// Consolas, which looks much better than Courier New.
|
||||
bool ShouldUseAlternateDefaultFixedFont(const std::string& script) {
|
||||
if (!base::StartsWith(script, "courier",
|
||||
base::CompareCase::INSENSITIVE_ASCII)) {
|
||||
return false;
|
||||
}
|
||||
UINT smooth_type = 0;
|
||||
SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smooth_type, 0);
|
||||
return smooth_type == FE_FONTSMOOTHINGCLEARTYPE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns the script of the font pref |pref_name|. For example, suppose
|
||||
// |pref_name| is "webkit.webprefs.fonts.serif.Hant". Since the script code for
|
||||
// the script name "Hant" is USCRIPT_TRADITIONAL_HAN, the function returns
|
||||
// USCRIPT_TRADITIONAL_HAN. |pref_name| must be a valid font pref name.
|
||||
UScriptCode GetScriptOfFontPref(const base::cstring_view pref_name) {
|
||||
// ICU script names are four letters.
|
||||
static const size_t kScriptNameLength = 4;
|
||||
|
||||
size_t len = pref_name.size();
|
||||
DCHECK_GT(len, kScriptNameLength);
|
||||
const char* scriptName = pref_name.substr(len - kScriptNameLength).data();
|
||||
int32_t code = u_getPropertyValueEnum(UCHAR_SCRIPT, scriptName);
|
||||
DCHECK(code >= 0 && code < USCRIPT_CODE_LIMIT);
|
||||
return static_cast<UScriptCode>(code);
|
||||
}
|
||||
|
||||
// Returns the primary script used by the browser's UI locale. For example, if
|
||||
// the locale is "ru", the function returns USCRIPT_CYRILLIC, and if the locale
|
||||
// is "en", the function returns USCRIPT_LATIN.
|
||||
UScriptCode GetScriptOfBrowserLocale(const std::string& locale) {
|
||||
// For Chinese locales, uscript_getCode() just returns USCRIPT_HAN but our
|
||||
// per-script fonts are for USCRIPT_SIMPLIFIED_HAN and
|
||||
// USCRIPT_TRADITIONAL_HAN.
|
||||
if (locale == "zh-CN") {
|
||||
return USCRIPT_SIMPLIFIED_HAN;
|
||||
}
|
||||
if (locale == "zh-TW") {
|
||||
return USCRIPT_TRADITIONAL_HAN;
|
||||
}
|
||||
// For Korean and Japanese, multiple scripts are returned by
|
||||
// |uscript_getCode|, but we're passing a one entry buffer leading
|
||||
// the buffer to be filled by USCRIPT_INVALID_CODE. We need to
|
||||
// hard-code the results for them.
|
||||
if (locale == "ko") {
|
||||
return USCRIPT_HANGUL;
|
||||
}
|
||||
if (locale == "ja") {
|
||||
return USCRIPT_JAPANESE;
|
||||
}
|
||||
|
||||
UScriptCode code = USCRIPT_INVALID_CODE;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
uscript_getCode(locale.c_str(), &code, 1, &err);
|
||||
|
||||
if (U_FAILURE(err)) {
|
||||
code = USCRIPT_INVALID_CODE;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
struct FontDefault {
|
||||
const char* pref_name;
|
||||
int resource_id;
|
||||
};
|
||||
|
||||
// The following list of font defaults was copied from
|
||||
// https://chromium.googlesource.com/chromium/src/+/69.0.3497.106/chrome/browser/ui/prefs/prefs_tab_helper.cc#152
|
||||
//
|
||||
@@ -25,22 +112,18 @@ namespace {
|
||||
//
|
||||
// vvvvv DO NOT EDIT vvvvv
|
||||
|
||||
struct FontDefault {
|
||||
const char* pref_name;
|
||||
int resource_id;
|
||||
};
|
||||
|
||||
// Font pref defaults. The prefs that have defaults vary by platform, since not
|
||||
// all platforms have fonts for all scripts for all generic families.
|
||||
// TODO(falken): add proper defaults when possible for all
|
||||
// platforms/scripts/generic families.
|
||||
const FontDefault kFontDefaults[] = {
|
||||
constexpr auto kFontDefaults = std::to_array<FontDefault>({
|
||||
{prefs::kWebKitStandardFontFamily, IDS_STANDARD_FONT_FAMILY},
|
||||
{prefs::kWebKitFixedFontFamily, IDS_FIXED_FONT_FAMILY},
|
||||
{prefs::kWebKitSerifFontFamily, IDS_SERIF_FONT_FAMILY},
|
||||
{prefs::kWebKitSansSerifFontFamily, IDS_SANS_SERIF_FONT_FAMILY},
|
||||
{prefs::kWebKitCursiveFontFamily, IDS_CURSIVE_FONT_FAMILY},
|
||||
{prefs::kWebKitFantasyFontFamily, IDS_FANTASY_FONT_FAMILY},
|
||||
{prefs::kWebKitMathFontFamily, IDS_MATH_FONT_FAMILY},
|
||||
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
|
||||
{prefs::kWebKitStandardFontFamilyJapanese,
|
||||
IDS_STANDARD_FONT_FAMILY_JAPANESE},
|
||||
@@ -102,7 +185,7 @@ const FontDefault kFontDefaults[] = {
|
||||
{prefs::kWebKitFixedFontFamilyTraditionalHan,
|
||||
IDS_FIXED_FONT_FAMILY_TRADITIONAL_HAN},
|
||||
#endif
|
||||
};
|
||||
});
|
||||
|
||||
// ^^^^^ DO NOT EDIT ^^^^^
|
||||
|
||||
@@ -125,6 +208,9 @@ auto MakeDefaultFontCopier() {
|
||||
|
||||
WP defaults;
|
||||
|
||||
std::set<std::string> fonts_with_defaults;
|
||||
UScriptCode browser_script =
|
||||
GetScriptOfBrowserLocale(g_browser_process->GetApplicationLocale());
|
||||
// Populate `defaults`'s ScriptFontFamilyMaps with the values from
|
||||
// the kFontDefaults array in the "DO NOT EDIT" section of this file.
|
||||
//
|
||||
@@ -133,11 +219,75 @@ auto MakeDefaultFontCopier() {
|
||||
// "webkit.webprefs.fonts.fixed.Zyyy" splits into family name
|
||||
// "webkit.webprefs.fonts.fixed" and script "Zyyy". (Yes, "Zyyy" is real.
|
||||
// See pref_font_script_names-inl.h for the full list :)
|
||||
for (const auto& [pref_name, resource_id] : kFontDefaults) {
|
||||
const auto [family, script] = *base::RSplitStringOnce(pref_name, '.');
|
||||
if (auto* family_map_ptr = base::FindOrNull(FamilyMapByName, family)) {
|
||||
FamilyMap& family_map = defaults.**family_map_ptr;
|
||||
family_map[std::string{script}] = l10n_util::GetStringUTF16(resource_id);
|
||||
for (auto [pref_name, resource_id] : kFontDefaults) {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
if (pref_name == prefs::kWebKitFixedFontFamily) {
|
||||
if (ShouldUseAlternateDefaultFixedFont(
|
||||
l10n_util::GetStringUTF8(resource_id))) {
|
||||
resource_id = IDS_FIXED_FONT_FAMILY_ALT_WIN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
UScriptCode pref_script =
|
||||
GetScriptOfFontPref(UNSAFE_BUFFERS(base::cstring_view(pref_name)));
|
||||
// Suppress this default font pref value if it is for the primary script of
|
||||
// the browser's UI locale. For example, if the pref is for the sans-serif
|
||||
// font for the Cyrillic script, and the browser locale is "ru" (Russian),
|
||||
// the default is suppressed. Otherwise, the default would override the
|
||||
// user's font preferences when viewing pages in their native language.
|
||||
// This is because users have no way yet of customizing their per-script
|
||||
// font preferences. The font prefs accessible in the options UI are for
|
||||
// the default, unknown script; these prefs have less priority than the
|
||||
// per-script font prefs when the script of the content is known. This code
|
||||
// can possibly be removed later if users can easily access per-script font
|
||||
// prefs (e.g., via the extensions workflow), or the problem turns out to
|
||||
// not be really critical after all.
|
||||
if (browser_script != pref_script) {
|
||||
std::string value = l10n_util::GetStringUTF8(resource_id);
|
||||
#if PREFS_FONT_LIST
|
||||
if (value.starts_with(',')) {
|
||||
value = gfx::FontList::FirstAvailableOrFirst(value);
|
||||
}
|
||||
#else // !PREFS_FONT_LIST
|
||||
DCHECK(!value.starts_with(','))
|
||||
<< "This platform doesn't support default font lists. " << pref_name
|
||||
<< "=" << value;
|
||||
#endif // PREFS_FONT_LIST
|
||||
const auto [family, script] = *base::RSplitStringOnce(pref_name, '.');
|
||||
if (auto* family_map_ptr = base::FindOrNull(FamilyMapByName, family)) {
|
||||
FamilyMap& family_map = defaults.**family_map_ptr;
|
||||
family_map[std::string{script}] = base::UTF8ToUTF16(value);
|
||||
}
|
||||
fonts_with_defaults.insert(pref_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the font concatenated with script name so this stays at RO memory
|
||||
// rather than allocated in heap.
|
||||
// clang-format off
|
||||
static const auto kFontFamilyMap = std::to_array<const char *>({
|
||||
#define EXPAND_SCRIPT_FONT(map_name, script_name) map_name "." script_name,
|
||||
|
||||
#include "chrome/common/pref_font_script_names-inl.h"
|
||||
ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_CURSIVE)
|
||||
ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_FIXED)
|
||||
ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_SANSERIF)
|
||||
ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_SERIF)
|
||||
ALL_FONT_SCRIPTS(WEBKIT_WEBPREFS_FONTS_STANDARD)
|
||||
|
||||
#undef EXPAND_SCRIPT_FONT
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
for (const char* const pref_name : kFontFamilyMap) {
|
||||
if (fonts_with_defaults.find(pref_name) == fonts_with_defaults.end()) {
|
||||
// We haven't already set a default value for this font preference, so set
|
||||
// an empty string as the default.
|
||||
const auto [family, script] = *base::RSplitStringOnce(pref_name, '.');
|
||||
if (auto* family_map_ptr = base::FindOrNull(FamilyMapByName, family)) {
|
||||
FamilyMap& family_map = defaults.**family_map_ptr;
|
||||
family_map[std::string{script}] = std::u16string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,12 @@ struct WebPreferences;
|
||||
|
||||
namespace electron {
|
||||
|
||||
// Set the default font preferences. The functionality is copied from
|
||||
// chrome/browser/prefs_tab_helper.cc with modifications to work
|
||||
// without a preference service and cache chrome/browser/font_family_cache.cc
|
||||
// that persists across app sessions.
|
||||
// Keep the core logic in sync to avoid performance regressions
|
||||
// Refs https://issues.chromium.org/issues/400473071
|
||||
void SetFontDefaults(blink::web_pref::WebPreferences* prefs);
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
@@ -16,7 +17,7 @@
|
||||
|
||||
namespace accelerator_util {
|
||||
|
||||
bool StringToAccelerator(const std::string& shortcut,
|
||||
bool StringToAccelerator(const std::string_view shortcut,
|
||||
ui::Accelerator* accelerator) {
|
||||
if (!base::IsStringASCII(shortcut)) {
|
||||
LOG(ERROR) << "The accelerator string can only contain ASCII characters, "
|
||||
@@ -26,14 +27,14 @@ bool StringToAccelerator(const std::string& shortcut,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> tokens = base::SplitString(
|
||||
const std::vector<std::string_view> tokens = base::SplitStringPiece(
|
||||
shortcut, "+", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
|
||||
// Now, parse it into an accelerator.
|
||||
int modifiers = ui::EF_NONE;
|
||||
ui::KeyboardCode key = ui::VKEY_UNKNOWN;
|
||||
std::optional<char16_t> shifted_char;
|
||||
for (const auto& token : tokens) {
|
||||
for (const std::string_view token : tokens) {
|
||||
ui::KeyboardCode code = electron::KeyboardCodeFromStr(token, &shifted_char);
|
||||
if (shifted_char)
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define ELECTRON_SHELL_BROWSER_UI_ACCELERATOR_UTIL_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "shell/browser/ui/electron_menu_model.h"
|
||||
@@ -21,7 +21,7 @@ typedef struct {
|
||||
typedef std::map<ui::Accelerator, MenuItem> AcceleratorTable;
|
||||
|
||||
// Parse a string as an accelerator.
|
||||
bool StringToAccelerator(const std::string& shortcut,
|
||||
bool StringToAccelerator(std::string_view shortcut,
|
||||
ui::Accelerator* accelerator);
|
||||
|
||||
// Generate a table that contains menu model's accelerators and command ids.
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef ELECTRON_SHELL_COMMON_GIN_HELPER_CONSTRUCTOR_H_
|
||||
#define ELECTRON_SHELL_COMMON_GIN_HELPER_CONSTRUCTOR_H_
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "shell/common/gin_helper/function_template.h"
|
||||
#include "shell/common/gin_helper/wrappable_base.h"
|
||||
|
||||
@@ -12,131 +14,40 @@ namespace gin_helper {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// This set of templates invokes a base::RepeatingCallback by converting the
|
||||
// Arguments into native types. It relies on the function_template.h to provide
|
||||
// helper templates.
|
||||
inline WrappableBase* InvokeFactory(
|
||||
gin::Arguments* args,
|
||||
const base::RepeatingCallback<WrappableBase*()>& callback) {
|
||||
return callback.Run();
|
||||
}
|
||||
// Convert a `gin::Argument`'s arguments into a tuple of native types
|
||||
// by iteratively calling gin_helper::GetNextArgument().
|
||||
template <typename... Types>
|
||||
class GinArgumentsToTuple {
|
||||
public:
|
||||
[[nodiscard]] static std::pair<bool /*ok*/, std::tuple<Types...>> GetArgs(
|
||||
gin::Arguments* args) {
|
||||
bool ok = true;
|
||||
InvokerOptions opts{.holder_is_first_argument = true};
|
||||
auto tup = std::make_tuple(GetNextArg<Types>(args, opts, ok)...);
|
||||
return {ok, std::move(tup)};
|
||||
}
|
||||
|
||||
template <typename P1>
|
||||
inline WrappableBase* InvokeFactory(
|
||||
gin::Arguments* args,
|
||||
const base::RepeatingCallback<WrappableBase*(P1)>& callback) {
|
||||
typename CallbackParamTraits<P1>::LocalType a1;
|
||||
if (!gin_helper::GetNextArgument(args, {.holder_is_first_argument = true}, 0,
|
||||
&a1))
|
||||
return nullptr;
|
||||
return callback.Run(a1);
|
||||
}
|
||||
private:
|
||||
template <typename T>
|
||||
static T GetNextArg(gin::Arguments* args, InvokerOptions& opts, bool& ok) {
|
||||
auto val = T{};
|
||||
ok = ok && gin_helper::GetNextArgument(args, opts, 0, &val);
|
||||
opts.holder_is_first_argument = false;
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename P1, typename P2>
|
||||
inline WrappableBase* InvokeFactory(
|
||||
// Invoke a callback with arguments extracted from `args`.
|
||||
template <typename... Types>
|
||||
WrappableBase* InvokeFactory(
|
||||
gin::Arguments* args,
|
||||
const base::RepeatingCallback<WrappableBase*(P1, P2)>& callback) {
|
||||
typename CallbackParamTraits<P1>::LocalType a1;
|
||||
typename CallbackParamTraits<P2>::LocalType a2;
|
||||
if (!gin_helper::GetNextArgument(args, {.holder_is_first_argument = true}, 0,
|
||||
&a1) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a2))
|
||||
return nullptr;
|
||||
return callback.Run(a1, a2);
|
||||
}
|
||||
|
||||
template <typename P1, typename P2, typename P3>
|
||||
inline WrappableBase* InvokeFactory(
|
||||
gin::Arguments* args,
|
||||
const base::RepeatingCallback<WrappableBase*(P1, P2, P3)>& callback) {
|
||||
typename CallbackParamTraits<P1>::LocalType a1;
|
||||
typename CallbackParamTraits<P2>::LocalType a2;
|
||||
typename CallbackParamTraits<P3>::LocalType a3;
|
||||
if (!gin_helper::GetNextArgument(args, {.holder_is_first_argument = true}, 0,
|
||||
&a1) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a2) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a3))
|
||||
return nullptr;
|
||||
return callback.Run(a1, a2, a3);
|
||||
}
|
||||
|
||||
template <typename P1, typename P2, typename P3, typename P4>
|
||||
inline WrappableBase* InvokeFactory(
|
||||
gin::Arguments* args,
|
||||
const base::RepeatingCallback<WrappableBase*(P1, P2, P3, P4)>& callback) {
|
||||
typename CallbackParamTraits<P1>::LocalType a1;
|
||||
typename CallbackParamTraits<P2>::LocalType a2;
|
||||
typename CallbackParamTraits<P3>::LocalType a3;
|
||||
typename CallbackParamTraits<P4>::LocalType a4;
|
||||
if (!gin_helper::GetNextArgument(args, {.holder_is_first_argument = true}, 0,
|
||||
&a1) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a2) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a3) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a4))
|
||||
return nullptr;
|
||||
return callback.Run(a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
template <typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
inline WrappableBase* InvokeFactory(
|
||||
gin::Arguments* args,
|
||||
const base::RepeatingCallback<WrappableBase*(P1, P2, P3, P4, P5)>&
|
||||
callback) {
|
||||
typename CallbackParamTraits<P1>::LocalType a1;
|
||||
typename CallbackParamTraits<P2>::LocalType a2;
|
||||
typename CallbackParamTraits<P3>::LocalType a3;
|
||||
typename CallbackParamTraits<P4>::LocalType a4;
|
||||
typename CallbackParamTraits<P5>::LocalType a5;
|
||||
if (!gin_helper::GetNextArgument(args, {.holder_is_first_argument = true}, 0,
|
||||
&a1) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a2) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a3) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a4) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a5))
|
||||
return nullptr;
|
||||
return callback.Run(a1, a2, a3, a4, a5);
|
||||
}
|
||||
|
||||
template <typename P1,
|
||||
typename P2,
|
||||
typename P3,
|
||||
typename P4,
|
||||
typename P5,
|
||||
typename P6>
|
||||
inline WrappableBase* InvokeFactory(
|
||||
gin::Arguments* args,
|
||||
const base::RepeatingCallback<WrappableBase*(P1, P2, P3, P4, P5, P6)>&
|
||||
callback) {
|
||||
typename CallbackParamTraits<P1>::LocalType a1;
|
||||
typename CallbackParamTraits<P2>::LocalType a2;
|
||||
typename CallbackParamTraits<P3>::LocalType a3;
|
||||
typename CallbackParamTraits<P4>::LocalType a4;
|
||||
typename CallbackParamTraits<P5>::LocalType a5;
|
||||
typename CallbackParamTraits<P6>::LocalType a6;
|
||||
if (!gin_helper::GetNextArgument(args, {.holder_is_first_argument = true}, 0,
|
||||
&a1) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a2) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a3) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a4) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a5) ||
|
||||
!gin_helper::GetNextArgument(args, {.holder_is_first_argument = false}, 0,
|
||||
&a6))
|
||||
return nullptr;
|
||||
return callback.Run(a1, a2, a3, a4, a5, a6);
|
||||
const base::RepeatingCallback<WrappableBase*(Types...)>& callback) {
|
||||
auto [ok, tup] = GinArgumentsToTuple<Types...>::GetArgs(args);
|
||||
if (!ok)
|
||||
return {};
|
||||
return std::apply(
|
||||
[&callback](Types... args) { return callback.Run(std::move(args)...); },
|
||||
std::move(tup));
|
||||
}
|
||||
|
||||
template <typename Sig>
|
||||
@@ -151,7 +62,7 @@ void InvokeNew(const base::RepeatingCallback<Sig>& factory,
|
||||
WrappableBase* object;
|
||||
{
|
||||
// Don't continue if the constructor throws an exception.
|
||||
v8::TryCatch try_catch(isolate);
|
||||
v8::TryCatch try_catch{isolate};
|
||||
object = internal::InvokeFactory(args, factory);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
|
||||
@@ -366,14 +366,14 @@ void SetNodeOptions(base::Environment* env) {
|
||||
if (electron::fuses::IsNodeOptionsEnabled()) {
|
||||
std::string options;
|
||||
env->GetVar("NODE_OPTIONS", &options);
|
||||
std::vector<std::string> parts = base::SplitString(
|
||||
const std::vector<std::string_view> parts = base::SplitStringPiece(
|
||||
options, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
|
||||
bool is_packaged_app = electron::api::App::IsPackaged();
|
||||
|
||||
for (const auto& part : parts) {
|
||||
for (const std::string_view part : parts) {
|
||||
// Strip off values passed to individual NODE_OPTIONs
|
||||
std::string option = part.substr(0, part.find('='));
|
||||
const std::string_view option = part.substr(0, part.find('='));
|
||||
|
||||
if (is_packaged_app && !pkg_opts.contains(option)) {
|
||||
// Explicitly disallow majority of NODE_OPTIONS in packaged apps
|
||||
|
||||
@@ -86,6 +86,9 @@ void WebWorkerObserver::WorkerScriptReadyForEvaluation(
|
||||
}
|
||||
}
|
||||
|
||||
// We do not want to crash Web Workers on unhandled rejections.
|
||||
env->options()->unhandled_rejections = "warn-with-error-code";
|
||||
|
||||
// Add Electron extended APIs.
|
||||
electron_bindings_->BindTo(env->isolate(), env->process_object());
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace electron {
|
||||
// for the lifetime of a Utility Process which
|
||||
// also means that GC lifecycle is ignored by this class.
|
||||
class ParentPort final : public gin::Wrappable<ParentPort>,
|
||||
public mojo::MessageReceiver {
|
||||
private mojo::MessageReceiver {
|
||||
public:
|
||||
static ParentPort* GetInstance();
|
||||
static gin::Handle<ParentPort> Create(v8::Isolate* isolate);
|
||||
|
||||
@@ -10,24 +10,17 @@ import { defer } from './lib/spec-helpers';
|
||||
import { closeAllWindows } from './lib/window-helpers';
|
||||
|
||||
describe('process module', () => {
|
||||
describe('renderer process', () => {
|
||||
let w: BrowserWindow;
|
||||
before(async () => {
|
||||
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, contextIsolation: false } });
|
||||
await w.loadURL('about:blank');
|
||||
});
|
||||
after(closeAllWindows);
|
||||
|
||||
function generateSpecs (invoke: <T extends (...args: any[]) => any>(fn: T, ...args: Parameters<T>) => Promise<ReturnType<T>>) {
|
||||
describe('process.getCreationTime()', () => {
|
||||
it('returns a creation time', async () => {
|
||||
const creationTime = await w.webContents.executeJavaScript('process.getCreationTime()');
|
||||
const creationTime = await invoke(() => process.getCreationTime());
|
||||
expect(creationTime).to.be.a('number').and.be.at.least(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getCPUUsage()', () => {
|
||||
it('returns a cpu usage object', async () => {
|
||||
const cpuUsage = await w.webContents.executeJavaScript('process.getCPUUsage()');
|
||||
const cpuUsage = await invoke(() => process.getCPUUsage());
|
||||
expect(cpuUsage.percentCPUUsage).to.be.a('number');
|
||||
expect(cpuUsage.cumulativeCPUUsage).to.be.a('number');
|
||||
expect(cpuUsage.idleWakeupsPerSecond).to.be.a('number');
|
||||
@@ -36,7 +29,7 @@ describe('process module', () => {
|
||||
|
||||
describe('process.getBlinkMemoryInfo()', () => {
|
||||
it('returns blink memory information object', async () => {
|
||||
const heapStats = await w.webContents.executeJavaScript('process.getBlinkMemoryInfo()');
|
||||
const heapStats = await invoke(() => process.getBlinkMemoryInfo());
|
||||
expect(heapStats.allocated).to.be.a('number');
|
||||
expect(heapStats.total).to.be.a('number');
|
||||
});
|
||||
@@ -44,7 +37,7 @@ describe('process module', () => {
|
||||
|
||||
describe('process.getProcessMemoryInfo()', () => {
|
||||
it('resolves promise successfully with valid data', async () => {
|
||||
const memoryInfo = await w.webContents.executeJavaScript('process.getProcessMemoryInfo()');
|
||||
const memoryInfo = await invoke(() => process.getProcessMemoryInfo());
|
||||
expect(memoryInfo).to.be.an('object');
|
||||
if (process.platform === 'linux' || process.platform === 'win32') {
|
||||
expect(memoryInfo.residentSet).to.be.a('number').greaterThan(0);
|
||||
@@ -57,7 +50,7 @@ describe('process module', () => {
|
||||
|
||||
describe('process.getSystemMemoryInfo()', () => {
|
||||
it('returns system memory info object', async () => {
|
||||
const systemMemoryInfo = await w.webContents.executeJavaScript('process.getSystemMemoryInfo()');
|
||||
const systemMemoryInfo = await invoke(() => process.getSystemMemoryInfo());
|
||||
expect(systemMemoryInfo.free).to.be.a('number');
|
||||
expect(systemMemoryInfo.total).to.be.a('number');
|
||||
});
|
||||
@@ -65,113 +58,14 @@ describe('process module', () => {
|
||||
|
||||
describe('process.getSystemVersion()', () => {
|
||||
it('returns a string', async () => {
|
||||
const systemVersion = await w.webContents.executeJavaScript('process.getSystemVersion()');
|
||||
const systemVersion = await invoke(() => process.getSystemVersion());
|
||||
expect(systemVersion).to.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getHeapStatistics()', () => {
|
||||
it('returns heap statistics object', async () => {
|
||||
const heapStats = await w.webContents.executeJavaScript('process.getHeapStatistics()');
|
||||
expect(heapStats.totalHeapSize).to.be.a('number');
|
||||
expect(heapStats.totalHeapSizeExecutable).to.be.a('number');
|
||||
expect(heapStats.totalPhysicalSize).to.be.a('number');
|
||||
expect(heapStats.totalAvailableSize).to.be.a('number');
|
||||
expect(heapStats.usedHeapSize).to.be.a('number');
|
||||
expect(heapStats.heapSizeLimit).to.be.a('number');
|
||||
expect(heapStats.mallocedMemory).to.be.a('number');
|
||||
expect(heapStats.peakMallocedMemory).to.be.a('number');
|
||||
expect(heapStats.doesZapGarbage).to.be.a('boolean');
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.takeHeapSnapshot()', () => {
|
||||
it('returns true on success', async () => {
|
||||
const filePath = path.join(app.getPath('temp'), 'test.heapsnapshot');
|
||||
defer(() => {
|
||||
try {
|
||||
fs.unlinkSync(filePath);
|
||||
} catch {
|
||||
// ignore error
|
||||
}
|
||||
});
|
||||
|
||||
const success = await w.webContents.executeJavaScript(`process.takeHeapSnapshot(${JSON.stringify(filePath)})`);
|
||||
expect(success).to.be.true();
|
||||
const stats = fs.statSync(filePath);
|
||||
expect(stats.size).not.to.be.equal(0);
|
||||
});
|
||||
|
||||
it('returns false on failure', async () => {
|
||||
const success = await w.webContents.executeJavaScript('process.takeHeapSnapshot("")');
|
||||
expect(success).to.be.false();
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.contextId', () => {
|
||||
it('is a string', async () => {
|
||||
const contextId = await w.webContents.executeJavaScript('process.contextId');
|
||||
expect(contextId).to.be.a('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('main process', () => {
|
||||
describe('process.getCreationTime()', () => {
|
||||
it('returns a creation time', () => {
|
||||
const creationTime = process.getCreationTime();
|
||||
expect(creationTime).to.be.a('number').and.be.at.least(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getCPUUsage()', () => {
|
||||
it('returns a cpu usage object', () => {
|
||||
const cpuUsage = process.getCPUUsage();
|
||||
expect(cpuUsage.percentCPUUsage).to.be.a('number');
|
||||
expect(cpuUsage.cumulativeCPUUsage).to.be.a('number');
|
||||
expect(cpuUsage.idleWakeupsPerSecond).to.be.a('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getBlinkMemoryInfo()', () => {
|
||||
it('returns blink memory information object', () => {
|
||||
const heapStats = process.getBlinkMemoryInfo();
|
||||
expect(heapStats.allocated).to.be.a('number');
|
||||
expect(heapStats.total).to.be.a('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getProcessMemoryInfo()', () => {
|
||||
it('resolves promise successfully with valid data', async () => {
|
||||
const memoryInfo = await process.getProcessMemoryInfo();
|
||||
expect(memoryInfo).to.be.an('object');
|
||||
if (process.platform === 'linux' || process.platform === 'win32') {
|
||||
expect(memoryInfo.residentSet).to.be.a('number').greaterThan(0);
|
||||
}
|
||||
expect(memoryInfo.private).to.be.a('number').greaterThan(0);
|
||||
// Shared bytes can be zero
|
||||
expect(memoryInfo.shared).to.be.a('number').greaterThan(-1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getSystemMemoryInfo()', () => {
|
||||
it('returns system memory info object', () => {
|
||||
const systemMemoryInfo = process.getSystemMemoryInfo();
|
||||
expect(systemMemoryInfo.free).to.be.a('number');
|
||||
expect(systemMemoryInfo.total).to.be.a('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getSystemVersion()', () => {
|
||||
it('returns a string', () => {
|
||||
const systemVersion = process.getSystemVersion();
|
||||
expect(systemVersion).to.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.getHeapStatistics()', () => {
|
||||
it('returns heap statistics object', async () => {
|
||||
const heapStats = process.getHeapStatistics();
|
||||
const heapStats = await invoke(() => process.getHeapStatistics());
|
||||
expect(heapStats.totalHeapSize).to.be.a('number');
|
||||
expect(heapStats.totalHeapSizeExecutable).to.be.a('number');
|
||||
expect(heapStats.totalPhysicalSize).to.be.a('number');
|
||||
@@ -187,7 +81,7 @@ describe('process module', () => {
|
||||
describe('process.takeHeapSnapshot()', () => {
|
||||
// DISABLED-FIXME(nornagon): this seems to take a really long time when run in the
|
||||
// main process, for unknown reasons.
|
||||
it('returns true on success', () => {
|
||||
it('returns true on success', async () => {
|
||||
const filePath = path.join(app.getPath('temp'), 'test.heapsnapshot');
|
||||
defer(() => {
|
||||
try {
|
||||
@@ -197,16 +91,41 @@ describe('process module', () => {
|
||||
}
|
||||
});
|
||||
|
||||
const success = process.takeHeapSnapshot(filePath);
|
||||
const success = await invoke((filePath: string) => process.takeHeapSnapshot(filePath), filePath);
|
||||
expect(success).to.be.true();
|
||||
const stats = fs.statSync(filePath);
|
||||
expect(stats.size).not.to.be.equal(0);
|
||||
});
|
||||
|
||||
it('returns false on failure', async () => {
|
||||
const success = process.takeHeapSnapshot('');
|
||||
const success = await invoke((filePath: string) => process.takeHeapSnapshot(filePath), '');
|
||||
expect(success).to.be.false();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('renderer process', () => {
|
||||
let w: BrowserWindow;
|
||||
before(async () => {
|
||||
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, contextIsolation: false } });
|
||||
await w.loadURL('about:blank');
|
||||
});
|
||||
after(closeAllWindows);
|
||||
|
||||
generateSpecs((fn, ...args) => {
|
||||
const jsonArgs = args.map(value => JSON.stringify(value)).join(',');
|
||||
return w.webContents.executeJavaScript(`(${fn.toString()})(${jsonArgs})`);
|
||||
});
|
||||
|
||||
describe('process.contextId', () => {
|
||||
it('is a string', async () => {
|
||||
const contextId = await w.webContents.executeJavaScript('process.contextId');
|
||||
expect(contextId).to.be.a('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('main process', () => {
|
||||
generateSpecs((fn, ...args) => fn(...args));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -213,7 +213,6 @@ describe('utilityProcess module', () => {
|
||||
const child = utilityProcess.fork(fixtureFile, [], {
|
||||
stdio: 'pipe'
|
||||
});
|
||||
await once(child, 'spawn');
|
||||
expect(child.stdout).to.not.be.null();
|
||||
let log = '';
|
||||
child.stdout!.on('data', (chunk) => {
|
||||
@@ -278,7 +277,6 @@ describe('utilityProcess module', () => {
|
||||
const child = utilityProcess.fork(path.join(fixturesPath, 'log.js'), [], {
|
||||
stdio: 'pipe'
|
||||
});
|
||||
await once(child, 'spawn');
|
||||
expect(child.stdout).to.not.be.null();
|
||||
let log = '';
|
||||
child.stdout!.on('data', (chunk) => {
|
||||
@@ -311,7 +309,6 @@ describe('utilityProcess module', () => {
|
||||
const child = utilityProcess.fork(path.join(fixturesPath, 'log.js'), [], {
|
||||
stdio: ['ignore', 'pipe', 'pipe']
|
||||
});
|
||||
await once(child, 'spawn');
|
||||
expect(child.stderr).to.not.be.null();
|
||||
let log = '';
|
||||
child.stderr!.on('data', (chunk) => {
|
||||
|
||||
@@ -631,6 +631,17 @@ describe('webContents module', () => {
|
||||
w.webContents.navigationHistory.goBack();
|
||||
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(0);
|
||||
});
|
||||
|
||||
it('should have the same window title if navigating back within the page', async () => {
|
||||
const title = 'Test';
|
||||
w.webContents.on('did-finish-load', () => {
|
||||
w.setTitle(title);
|
||||
w.loadURL(`file://${fixturesPath}/pages/navigation-history-anchor-in-page.html#next`);
|
||||
});
|
||||
await w.loadURL(`file://${fixturesPath}/pages/navigation-history-anchor-in-page.html`);
|
||||
w.webContents.navigationHistory.goBack();
|
||||
expect(w.getTitle()).to.equal(title);
|
||||
});
|
||||
});
|
||||
|
||||
describe('navigationHistory.canGoForward and navigationHistory.goForward API', () => {
|
||||
@@ -653,6 +664,16 @@ describe('webContents module', () => {
|
||||
w.webContents.navigationHistory.goForward();
|
||||
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(1);
|
||||
});
|
||||
|
||||
it('should have the same window title if navigating forward within the page', async () => {
|
||||
const title = 'Test';
|
||||
w.webContents.on('did-finish-load', () => {
|
||||
w.setTitle(title);
|
||||
w.loadURL(`file://${fixturesPath}/pages/navigation-history-anchor-in-page.html#next`);
|
||||
});
|
||||
await w.loadURL(`file://${fixturesPath}/pages/navigation-history-anchor-in-page.html`);
|
||||
expect(w.getTitle()).to.equal(title);
|
||||
});
|
||||
});
|
||||
|
||||
describe('navigationHistory.canGoToOffset(index) and navigationHistory.goToOffset(index) API', () => {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const dns = require('node:dns');
|
||||
|
||||
console.log(dns.getDefaultResultOrder());
|
||||
process.exit(0);
|
||||
const write = (writable, chunk) => new Promise((resolve) => writable.write(chunk, resolve));
|
||||
|
||||
write(process.stdout, `${dns.getDefaultResultOrder()}\n`)
|
||||
.then(() => process.exit(0));
|
||||
|
||||
6
spec/fixtures/api/utility-process/esm.mjs
vendored
6
spec/fixtures/api/utility-process/esm.mjs
vendored
@@ -1,2 +1,4 @@
|
||||
console.log(import.meta.url);
|
||||
process.exit(0);
|
||||
const write = (writable, chunk) => new Promise((resolve) => writable.write(chunk, resolve));
|
||||
|
||||
write(process.stdout, `${import.meta.url}\n`)
|
||||
.then(() => process.exit(0));
|
||||
|
||||
5
spec/fixtures/pages/navigation-history-anchor-in-page.html
vendored
Normal file
5
spec/fixtures/pages/navigation-history-anchor-in-page.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
<span id="next">This is content.</span>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user