From 1392f5f223b960d6332f9230687afcd3e8e5276f Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 17 Oct 2022 12:07:37 +0000 Subject: [PATCH 01/14] Issue #2019 - Do not dispatch keypress event for non-printable keys. This will prevent the keypress DOM event from firing on keypresses that do not produce printable keys (e.g. editing nav keys) in content. This should not affect any chrome events that are in use. Event dispatch can be re-enabled if necessary with the added pref. --- editor/libeditor/HTMLEditor.cpp | 9 ++------- editor/libeditor/TextEditor.cpp | 10 ++-------- modules/libpref/init/all.js | 4 ++++ widget/TextEventDispatcher.cpp | 12 ++++++++++++ widget/TextEventDispatcher.h | 4 ++++ widget/TextEvents.h | 24 ++++++++++++++++++++++++ 6 files changed, 48 insertions(+), 15 deletions(-) diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index 6a630cb1c4..130b033bd1 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -664,8 +664,7 @@ HTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) return TypedText(NS_LITERAL_STRING("\t"), eTypedText); } case NS_VK_RETURN: - if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() || - nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) { + if (!nativeKeyEvent->IsInputtingLineBreak()) { return NS_OK; } aKeyEvent->AsEvent()->PreventDefault(); // consumed @@ -677,11 +676,7 @@ HTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) return TypedText(EmptyString(), eTypedBreak); } - // NOTE: On some keyboard layout, some characters are inputted with Control - // key or Alt key, but at that time, widget sets FALSE to these keys. - if (!nativeKeyEvent->mCharCode || nativeKeyEvent->IsControl() || - nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() || - nativeKeyEvent->IsOS()) { + if (!nativeKeyEvent->IsInputtingText()) { // we don't PreventDefault() here or keybindings like control-x won't work return NS_OK; } diff --git a/editor/libeditor/TextEditor.cpp b/editor/libeditor/TextEditor.cpp index 3bee7843ce..4b26eff9cd 100644 --- a/editor/libeditor/TextEditor.cpp +++ b/editor/libeditor/TextEditor.cpp @@ -397,20 +397,14 @@ TextEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) return TypedText(NS_LITERAL_STRING("\t"), eTypedText); } case NS_VK_RETURN: - if (IsSingleLineEditor() || nativeKeyEvent->IsControl() || - nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() || - nativeKeyEvent->IsOS()) { + if (IsSingleLineEditor() || !nativeKeyEvent->IsInputtingLineBreak()) { return NS_OK; } aKeyEvent->AsEvent()->PreventDefault(); return TypedText(EmptyString(), eTypedBreak); } - // NOTE: On some keyboard layout, some characters are inputted with Control - // key or Alt key, but at that time, widget sets FALSE to these keys. - if (!nativeKeyEvent->mCharCode || nativeKeyEvent->IsControl() || - nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() || - nativeKeyEvent->IsOS()) { + if (!nativeKeyEvent->IsInputtingText()) { // we don't PreventDefault() here or keybindings like control-x won't work return NS_OK; } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ec8e6d770f..ec30c9d4b2 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -231,6 +231,10 @@ pref("dom.keyboardevent.code.enabled", true); // even if this is true). pref("dom.keyboardevent.dispatch_during_composition", false); +// If this is true, TextEventDispatcher dispatches keypress events +// for the input of non-printable characters (content only). +pref("dom.keyboardevent.keypress.dispatch_non_printable_in_content", false); + // Whether URL,Location,Link::GetHash should be percent encoded // in setter and percent decoded in getter (old behaviour = true) pref("dom.url.encode_decode_hash", true); diff --git a/widget/TextEventDispatcher.cpp b/widget/TextEventDispatcher.cpp index 6c54376a48..2b058ba9c3 100644 --- a/widget/TextEventDispatcher.cpp +++ b/widget/TextEventDispatcher.cpp @@ -21,6 +21,7 @@ namespace widget { *****************************************************************************/ bool TextEventDispatcher::sDispatchKeyEventsDuringComposition = false; +bool TextEventDispatcher::sDispatchKeyPressEventNonPrintableInContent = false; TextEventDispatcher::TextEventDispatcher(nsIWidget* aWidget) : mWidget(aWidget) @@ -36,6 +37,10 @@ TextEventDispatcher::TextEventDispatcher(nsIWidget* aWidget) &sDispatchKeyEventsDuringComposition, "dom.keyboardevent.dispatch_during_composition", false); + Preferences::AddBoolVarCache( + &sDispatchKeyPressEventNonPrintableInContent, + "dom.keyboardevent.keypress.dispatch_non_printable_in_content", + false); sInitialized = true; } } @@ -531,6 +536,13 @@ TextEventDispatcher::DispatchKeyboardEventInternal( } } + if (!sDispatchKeyPressEventNonPrintableInContent && + keyEvent.mMessage == eKeyPress && + !keyEvent.IsInputtingText() && + !keyEvent.IsInputtingLineBreak()) { + keyEvent.mFlags.mOnlySystemGroupDispatchInContent = true; + } + DispatchInputEvent(mWidget, keyEvent, aStatus); return true; } diff --git a/widget/TextEventDispatcher.h b/widget/TextEventDispatcher.h index 1bed15a3bf..6d28200f5f 100644 --- a/widget/TextEventDispatcher.h +++ b/widget/TextEventDispatcher.h @@ -399,6 +399,10 @@ private: // is a composition. static bool sDispatchKeyEventsDuringComposition; + // If this is true, keypress events for non-printable keys are dispatched to + // event listeners of the system event group in web content. + static bool sDispatchKeyPressEventNonPrintableInContent; + nsresult BeginInputTransactionInternal( TextEventDispatcherListener* aListener, InputTransactionType aType); diff --git a/widget/TextEvents.h b/widget/TextEvents.h index 6c29341144..59aa91b2e0 100644 --- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -183,6 +183,30 @@ public: return IsKeyEventOnPlugin(mMessage); } + bool IsInputtingText() const + { + // NOTE: On some keyboard layouts, some characters are put in with Control + // or Alt keys, but at that time, widget unsets the modifier flag + // from the eKeyPress event, so it does not count as a modifier in + // this check. + return mMessage == eKeyPress && + mCharCode && + !(mModifiers & (MODIFIER_ALT | + MODIFIER_CONTROL | + MODIFIER_META | + MODIFIER_OS)); + } + + bool IsInputtingLineBreak() const + { + return mMessage == eKeyPress && + mKeyNameIndex == KEY_NAME_INDEX_Enter && + !(mModifiers & (MODIFIER_ALT | + MODIFIER_CONTROL | + MODIFIER_META | + MODIFIER_OS)); + } + virtual WidgetEvent* Duplicate() const override { MOZ_ASSERT(mClass == eKeyboardEventClass, From 5699d9673f7ed690854f60607bf3884e33b2ea67 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 17 Oct 2022 15:22:03 +0000 Subject: [PATCH 02/14] Issue #2019 - Follow-up: Adjust content spellchecker to use keydown Since keypress is no longer triggered on all keypresses in content, the spellchecker would potentially not be triggered when it should be. This changes the trigger to keydown, instead. No behavioral changes otherwise. --- extensions/spellcheck/src/mozInlineSpellChecker.cpp | 10 +++++----- extensions/spellcheck/src/mozInlineSpellChecker.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.cpp b/extensions/spellcheck/src/mozInlineSpellChecker.cpp index 6ca17885da..37898c818e 100644 --- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp +++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp @@ -714,7 +714,7 @@ mozInlineSpellChecker::RegisterEventListeners() true, false); piTarget->AddEventListener(NS_LITERAL_STRING("click"), this, false, false); - piTarget->AddEventListener(NS_LITERAL_STRING("keypress"), this, + piTarget->AddEventListener(NS_LITERAL_STRING("keydown"), this, false, false); return NS_OK; } @@ -738,7 +738,7 @@ mozInlineSpellChecker::UnregisterEventListeners() piTarget->RemoveEventListener(NS_LITERAL_STRING("blur"), this, true); piTarget->RemoveEventListener(NS_LITERAL_STRING("click"), this, false); - piTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, false); + piTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, false); return NS_OK; } @@ -1916,8 +1916,8 @@ NS_IMETHODIMP mozInlineSpellChecker::HandleEvent(nsIDOMEvent* aEvent) if (eventType.EqualsLiteral("click")) { return MouseClick(aEvent); } - if (eventType.EqualsLiteral("keypress")) { - return KeyPress(aEvent); + if (eventType.EqualsLiteral("keydown")) { + return KeyDown(aEvent); } return NS_OK; @@ -1943,7 +1943,7 @@ nsresult mozInlineSpellChecker::MouseClick(nsIDOMEvent *aMouseEvent) return NS_OK; } -nsresult mozInlineSpellChecker::KeyPress(nsIDOMEvent* aKeyEvent) +nsresult mozInlineSpellChecker::KeyDown(nsIDOMEvent* aKeyEvent) { nsCOMPtrkeyEvent = do_QueryInterface(aKeyEvent); NS_ENSURE_TRUE(keyEvent, NS_OK); diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.h b/extensions/spellcheck/src/mozInlineSpellChecker.h index 52261f22be..251b5f6f27 100644 --- a/extensions/spellcheck/src/mozInlineSpellChecker.h +++ b/extensions/spellcheck/src/mozInlineSpellChecker.h @@ -197,7 +197,7 @@ public: nsresult Blur(nsIDOMEvent* aEvent); nsresult MouseClick(nsIDOMEvent* aMouseEvent); - nsresult KeyPress(nsIDOMEvent* aKeyEvent); + nsresult KeyDown(nsIDOMEvent* aKeyEvent); mozInlineSpellChecker(); From 808332c2c123cf0cd8ca84bf4016b8fb6354898d Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 18 Oct 2022 12:48:23 +0000 Subject: [PATCH 03/14] Issue #2019 - Follow-up: Make autocomplete and satchel listen to keypress events in the system event group The autocomplete module listens to keypress events for both printable keys and non-printable keys a lot. However, we're stopping dispatching keypress events for non-printable keys in the default event group of web content. This means that autocomplete should listen to keypress events in the system event group. Note that it's difficult to globally change keypress event listeners to keydown event listeners because if we stop keypress events at preceding keydown event in autocomplete or satchel modules, some other modules fail to handle keydown or keypress events before autocomplete, and it's not easy to investigate which keypress event listener in which modules should be changed to a keydown event listener. Therefore, this patch doesn't do that, and uses the event group approach. --- .../satchel/nsFormFillController.cpp | 76 ++++++++++++------- toolkit/content/widgets/autocomplete.xml | 2 +- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp index a89c138fab..aac1870490 100644 --- a/toolkit/components/satchel/nsFormFillController.cpp +++ b/toolkit/components/satchel/nsFormFillController.cpp @@ -5,6 +5,7 @@ #include "nsFormFillController.h" +#include "mozilla/EventListenerManager.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsIFormAutoComplete.h" @@ -40,6 +41,7 @@ #include "nsIScriptSecurityManager.h" #include "nsFocusManager.h" +using namespace mozilla; using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION(nsFormFillController, @@ -1188,23 +1190,29 @@ nsFormFillController::AddWindowListeners(nsPIDOMWindowOuter* aWindow) if (!target) return; - target->AddEventListener(NS_LITERAL_STRING("focus"), this, - true, false); - target->AddEventListener(NS_LITERAL_STRING("blur"), this, - true, false); - target->AddEventListener(NS_LITERAL_STRING("pagehide"), this, - true, false); - target->AddEventListener(NS_LITERAL_STRING("mousedown"), this, - true, false); - target->AddEventListener(NS_LITERAL_STRING("input"), this, - true, false); - target->AddEventListener(NS_LITERAL_STRING("keypress"), this, true, false); - target->AddEventListener(NS_LITERAL_STRING("compositionstart"), this, - true, false); - target->AddEventListener(NS_LITERAL_STRING("compositionend"), this, - true, false); - target->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, - true, false); + EventListenerManager* elm = target->GetOrCreateListenerManager(); + if (NS_WARN_IF(!elm)) { + return; + } + + elm->AddEventListenerByType(this, NS_LITERAL_STRING("focus"), + TrustedEventsAtCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("blur"), + TrustedEventsAtCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"), + TrustedEventsAtCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("mousedown"), + TrustedEventsAtCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("input"), + TrustedEventsAtCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("keypress"), + TrustedEventsAtSystemGroupCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("compositionstart"), + TrustedEventsAtCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("compositionend"), + TrustedEventsAtCapture()); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("contextmenu"), + TrustedEventsAtCapture()); // Note that any additional listeners added should ensure that they ignore // untrusted events, which might be sent by content that's up to no good. @@ -1226,17 +1234,29 @@ nsFormFillController::RemoveWindowListeners(nsPIDOMWindowOuter* aWindow) if (!target) return; - target->RemoveEventListener(NS_LITERAL_STRING("focus"), this, true); - target->RemoveEventListener(NS_LITERAL_STRING("blur"), this, true); - target->RemoveEventListener(NS_LITERAL_STRING("pagehide"), this, true); - target->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true); - target->RemoveEventListener(NS_LITERAL_STRING("input"), this, true); - target->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true); - target->RemoveEventListener(NS_LITERAL_STRING("compositionstart"), this, - true); - target->RemoveEventListener(NS_LITERAL_STRING("compositionend"), this, - true); - target->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true); + EventListenerManager* elm = target->GetOrCreateListenerManager(); + if (NS_WARN_IF(!elm)) { + return; + } + + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("focus"), + TrustedEventsAtCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("blur"), + TrustedEventsAtCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"), + TrustedEventsAtCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("mousedown"), + TrustedEventsAtCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("input"), + TrustedEventsAtCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("keypress"), + TrustedEventsAtSystemGroupCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("compositionstart"), + TrustedEventsAtCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("compositionend"), + TrustedEventsAtCapture()); + elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("contextmenu"), + TrustedEventsAtCapture()); } void diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml index 885eb2eab4..d9160956c8 100644 --- a/toolkit/content/widgets/autocomplete.xml +++ b/toolkit/content/widgets/autocomplete.xml @@ -648,7 +648,7 @@ this.onInput(event); ]]> - Date: Thu, 20 Oct 2022 18:22:30 -0400 Subject: [PATCH 04/14] Issue #1375 - Don't mark nodes in the shadow tree as orphan nodes Port of Bug 1026714 --- dom/base/FragmentOrElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index bfb9c40b2e..0f919c97f0 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1921,7 +1921,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement) } nsAutoCString orphan; - if (!tmp->IsInUncomposedDoc() && + if (!tmp->IsInComposedDoc() && // Ignore xbl:content, which is never in the document and hence always // appears to be orphaned. !tmp->NodeInfo()->Equals(nsGkAtoms::content, kNameSpaceID_XBL)) { From d02383072796fb6e7a77038b9356875088d6eb14 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Wed, 4 May 2022 15:27:02 +0800 Subject: [PATCH 05/14] Issue #1829 - Follow-up: Mac-specific shortcut key for closing the developer tools toolbox window should not be excluded from other platforms --- devtools/client/framework/toolbox-window.xul | 13 ++++++++----- devtools/client/jar.mn | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/devtools/client/framework/toolbox-window.xul b/devtools/client/framework/toolbox-window.xul index cd14a3597c..af8b55fb3d 100644 --- a/devtools/client/framework/toolbox-window.xul +++ b/devtools/client/framework/toolbox-window.xul @@ -26,16 +26,19 @@ key="&closeCmd.key;" command="toolbox-cmd-close" modifiers="accel"/> - +#ifdef XP_MACOSX +#else + +#endif Date: Sat, 18 Jun 2022 14:04:39 +0800 Subject: [PATCH 06/14] Issue #58 - Remove leftover rust build files from /js --- js/src/build.rs | 53 ------------------------------------------------- js/src/lib.rs | 2 -- 2 files changed, 55 deletions(-) delete mode 100644 js/src/build.rs delete mode 100644 js/src/lib.rs diff --git a/js/src/build.rs b/js/src/build.rs deleted file mode 100644 index d4e1082321..0000000000 --- a/js/src/build.rs +++ /dev/null @@ -1,53 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -use std::env; -use std::process::{Command, Stdio}; - -fn main() { - let out_dir = env::var("OUT_DIR").expect("Should have env var OUT_DIR"); - let target = env::var("TARGET").expect("Should have env var TARGET"); - - let js_src = env::var("CARGO_MANIFEST_DIR").expect("Should have env var CARGO_MANIFEST_DIR"); - - env::set_current_dir(&js_src).unwrap(); - - let variant = if cfg!(feature = "debugmozjs") { - "plaindebug" - } else { - "plain" - }; - - let python = env::var("PYTHON").unwrap_or("python2.7".into()); - let mut cmd = Command::new(&python); - cmd.args(&["./devtools/automation/autospider.py", - "--build-only", - "--objdir", &out_dir, - variant]) - .env("SOURCE", &js_src) - .env("PWD", &js_src) - .env("AUTOMATION", "1") - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()); - println!("Running command: {:?}", cmd); - let result = cmd - .status() - .expect("Should spawn autospider OK"); - assert!(result.success(), "autospider should exit OK"); - - println!("cargo:rustc-link-search=native={}/js/src", out_dir); - - if target.contains("windows") { - println!("cargo:rustc-link-lib=winmm"); - println!("cargo:rustc-link-lib=psapi"); - if target.contains("gnu") { - println!("cargo:rustc-link-lib=stdc++"); - } - } else { - println!("cargo:rustc-link-lib=stdc++"); - } - - println!("cargo:rustc-link-lib=static=js_static"); - println!("cargo:outdir={}", out_dir); -} diff --git a/js/src/lib.rs b/js/src/lib.rs deleted file mode 100644 index d8f6ce78db..0000000000 --- a/js/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -extern crate libz_sys; - From 1ae5f60a1bacf71f060f01fbd9bf5eb11bf05098 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sun, 3 Jul 2022 13:20:12 +0800 Subject: [PATCH 07/14] Issue #1793 - Follow-up: Fix incorrect media query --- toolkit/themes/windows/global/console/console.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/themes/windows/global/console/console.css b/toolkit/themes/windows/global/console/console.css index 4fb3fab706..990ce1cf2f 100644 --- a/toolkit/themes/windows/global/console/console.css +++ b/toolkit/themes/windows/global/console/console.css @@ -208,7 +208,7 @@ toolbar#ToolbarMode .toolbarbutton-text { } %ifdef XP_WIN -@media not (-moz-os-version: windows-win10) { +@media not all and (-moz-os-version: windows-win10) { #ToolbarMode { -moz-appearance: -moz-win-browsertabbar-toolbox; } From 2e944692c35ff78c9299a94df73db4a73b46085c Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 4 Apr 2022 11:58:59 +0800 Subject: [PATCH 08/14] Issue #21 - Remove panning/tab animation performance measurements Based on FranklinDM's follow-up for the issue. This would require browser FE changes, particularly removing the associated code in `tabbrowser.xml`, however, that was already done in Pale Moon previously. Other front-end applications may need to take note, though. Based on changes from the following bugs: * Bug 696398 - Need an api to analyze panning performance * Bug 800031 - Include paint time in tab switch telemetry * Bug 820167 - Enable performance measurement of tab animation * Bug 826383 - Improve Start/Stop FrameTimeRecording for telemetry usage --- dom/base/nsDOMWindowUtils.cpp | 69 ----------- dom/interfaces/base/nsIDOMWindowUtils.idl | 34 +----- gfx/layers/Layers.cpp | 109 ------------------ gfx/layers/Layers.h | 51 -------- gfx/layers/basic/BasicLayerManager.cpp | 2 - gfx/layers/client/ClientLayerManager.cpp | 22 ---- gfx/layers/client/ClientLayerManager.h | 5 - .../composite/LayerManagerComposite.cpp | 2 - gfx/layers/ipc/CompositorBridgeChild.cpp | 18 --- gfx/layers/ipc/CompositorBridgeChild.h | 2 - gfx/layers/ipc/CompositorBridgeParent.cpp | 21 ---- gfx/layers/ipc/CompositorBridgeParent.h | 2 - .../ipc/CrossProcessCompositorBridgeParent.h | 2 - gfx/layers/ipc/PCompositorBridge.ipdl | 6 - 14 files changed, 1 insertion(+), 344 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index d38b3c600b..69f1787b9f 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -2367,75 +2367,6 @@ nsDOMWindowUtils::GetCurrentAudioBackend(nsAString& aBackend) return NS_OK; } -NS_IMETHODIMP -nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex) -{ - NS_ENSURE_ARG_POINTER(startIndex); - - nsCOMPtr widget = GetWidget(); - if (!widget) - return NS_ERROR_FAILURE; - - LayerManager *mgr = widget->GetLayerManager(); - if (!mgr) - return NS_ERROR_FAILURE; - - const uint32_t kRecordingMinSize = 60 * 10; // 10 seconds @60 fps. - const uint32_t kRecordingMaxSize = 60 * 60 * 60; // One hour - uint32_t bufferSize = Preferences::GetUint("toolkit.framesRecording.bufferSize", uint32_t(0)); - bufferSize = std::min(bufferSize, kRecordingMaxSize); - bufferSize = std::max(bufferSize, kRecordingMinSize); - *startIndex = mgr->StartFrameTimeRecording(bufferSize); - - return NS_OK; -} - -NS_IMETHODIMP -nsDOMWindowUtils::StopFrameTimeRecording(uint32_t startIndex, - uint32_t *frameCount, - float **frameIntervals) -{ - NS_ENSURE_ARG_POINTER(frameCount); - NS_ENSURE_ARG_POINTER(frameIntervals); - - nsCOMPtr widget = GetWidget(); - if (!widget) - return NS_ERROR_FAILURE; - - LayerManager *mgr = widget->GetLayerManager(); - if (!mgr) - return NS_ERROR_FAILURE; - - nsTArray tmpFrameIntervals; - mgr->StopFrameTimeRecording(startIndex, tmpFrameIntervals); - *frameCount = tmpFrameIntervals.Length(); - - *frameIntervals = (float*)moz_xmalloc(*frameCount * sizeof(float)); - - /* copy over the frame intervals and paint times into the arrays we just allocated */ - for (uint32_t i = 0; i < *frameCount; i++) { - (*frameIntervals)[i] = tmpFrameIntervals[i]; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsDOMWindowUtils::BeginTabSwitch() -{ - nsCOMPtr widget = GetWidget(); - if (!widget) - return NS_ERROR_FAILURE; - - LayerManager *mgr = widget->GetLayerManager(); - if (!mgr) - return NS_ERROR_FAILURE; - - mgr->BeginTabSwitch(); - - return NS_OK; -} - static bool ComputeAnimationValue(nsCSSPropertyID aProperty, Element* aElement, diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index ad45e6e520..1289bd940d 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -49,7 +49,7 @@ interface nsIJSRAIIHelper; interface nsIContentPermissionRequest; interface nsIObserver; -[scriptable, uuid(7fcc7958-77d9-45ff-8c81-277bde5f0dc8)] +[scriptable, uuid(58e97ce9-1d9e-4576-aabf-89480fdeb16d)] interface nsIDOMWindowUtils : nsISupports { /** @@ -1425,38 +1425,6 @@ interface nsIDOMWindowUtils : nsISupports { */ readonly attribute AString currentAudioBackend; - /** - * Record (and return) frame-intervals for frames which were presented - * between calling StartFrameTimeRecording and StopFrameTimeRecording. - * - * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is called too late - * (elements were overwritten since Start), result is considered invalid and hence empty. - * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were less frequent). - * Can be changed (up to 1 hour) via pref: toolkit.framesRecording.bufferSize. - * - Note: the first frame-interval may be longer than expected because last frame - * might have been presented some time before calling StartFrameTimeRecording. - */ - - /** - * Returns a handle which represents current recording start position. - */ - void startFrameTimeRecording([retval] out unsigned long startIndex); - - /** - * Returns number of recorded frames since startIndex was issued, - * and allocates+populates 2 arraye with the recorded data. - * - Allocation is infallible. Should be released even if size is 0. - */ - void stopFrameTimeRecording(in unsigned long startIndex, - [optional] out unsigned long frameCount, - [retval, array, size_is(frameCount)] out float frameIntervals); - - /** - * Signals that we're begining to tab switch. This is used by painting code to - * determine total tab switch time. - */ - void beginTabSwitch(); - /** * The DPI of the display */ diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 991e8ed2f0..724f2c7fdf 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -1545,115 +1545,6 @@ RefLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs) aAttrs = RefLayerAttributes(GetReferentId(), mEventRegionsOverride); } -/** - * StartFrameTimeRecording, together with StopFrameTimeRecording - * enable recording of frame intervals. - * - * To allow concurrent consumers, a cyclic array is used which serves all - * consumers, practically stateless with regard to consumers. - * - * To save resources, the buffer is allocated on first call to StartFrameTimeRecording - * and recording is paused if no consumer which called StartFrameTimeRecording is able - * to get valid results (because the cyclic buffer was overwritten since that call). - * - * To determine availability of the data upon StopFrameTimeRecording: - * - mRecording.mNextIndex increases on each PostPresent, and never resets. - * - Cyclic buffer position is realized as mNextIndex % bufferSize. - * - StartFrameTimeRecording returns mNextIndex. When StopFrameTimeRecording is called, - * the required start index is passed as an arg, and we're able to calculate the required - * length. If this length is bigger than bufferSize, it means data was overwritten. - * otherwise, we can return the entire sequence. - * - To determine if we need to pause, mLatestStartIndex is updated to mNextIndex - * on each call to StartFrameTimeRecording. If this index gets overwritten, - * it means that all earlier start indices obtained via StartFrameTimeRecording - * were also overwritten, hence, no point in recording, so pause. - * - mCurrentRunStartIndex indicates the oldest index of the recording after which - * the recording was not paused. If StopFrameTimeRecording is invoked with a start index - * older than this, it means that some frames were not recorded, so data is invalid. - */ -uint32_t -LayerManager::StartFrameTimeRecording(int32_t aBufferSize) -{ - if (mRecording.mIsPaused) { - mRecording.mIsPaused = false; - - if (!mRecording.mIntervals.Length()) { // Initialize recording buffers - mRecording.mIntervals.SetLength(aBufferSize); - } - - // After being paused, recent values got invalid. Update them to now. - mRecording.mLastFrameTime = TimeStamp::Now(); - - // Any recording which started before this is invalid, since we were paused. - mRecording.mCurrentRunStartIndex = mRecording.mNextIndex; - } - - // If we'll overwrite this index, there are no more consumers with aStartIndex - // for which we're able to provide the full recording, so no point in keep recording. - mRecording.mLatestStartIndex = mRecording.mNextIndex; - return mRecording.mNextIndex; -} - -void -LayerManager::RecordFrame() -{ - if (!mRecording.mIsPaused) { - TimeStamp now = TimeStamp::Now(); - uint32_t i = mRecording.mNextIndex % mRecording.mIntervals.Length(); - mRecording.mIntervals[i] = static_cast((now - mRecording.mLastFrameTime) - .ToMilliseconds()); - mRecording.mNextIndex++; - mRecording.mLastFrameTime = now; - - if (mRecording.mNextIndex > (mRecording.mLatestStartIndex + mRecording.mIntervals.Length())) { - // We've just overwritten the most recent recording start -> pause. - mRecording.mIsPaused = true; - } - } -} - -void -LayerManager::PostPresent() -{ - if (!mTabSwitchStart.IsNull()) { - mTabSwitchStart = TimeStamp(); - } -} - -void -LayerManager::StopFrameTimeRecording(uint32_t aStartIndex, - nsTArray& aFrameIntervals) -{ - uint32_t bufferSize = mRecording.mIntervals.Length(); - uint32_t length = mRecording.mNextIndex - aStartIndex; - if (mRecording.mIsPaused || length > bufferSize || aStartIndex < mRecording.mCurrentRunStartIndex) { - // aStartIndex is too old. Also if aStartIndex was issued before mRecordingNextIndex overflowed (uint32_t) - // and stopped after the overflow (would happen once every 828 days of constant 60fps). - length = 0; - } - - if (!length) { - aFrameIntervals.Clear(); - return; // empty recording, return empty arrays. - } - // Set length in advance to avoid possibly repeated reallocations - aFrameIntervals.SetLength(length); - - uint32_t cyclicPos = aStartIndex % bufferSize; - for (uint32_t i = 0; i < length; i++, cyclicPos++) { - if (cyclicPos == bufferSize) { - cyclicPos = 0; - } - aFrameIntervals[i] = mRecording.mIntervals[cyclicPos]; - } -} - -void -LayerManager::BeginTabSwitch() -{ - mTabSwitchStart = TimeStamp::Now(); -} - static void PrintInfo(std::stringstream& aStream, LayerComposite* aLayerComposite); #ifdef MOZ_DUMP_PAINTING diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 805d41d48e..8b5e0a4ab5 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -586,36 +586,6 @@ public: */ void LogSelf(const char* aPrefix=""); - /** - * Record (and return) frame-intervals and paint-times for frames which were presented - * between calling StartFrameTimeRecording and StopFrameTimeRecording. - * - * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is called too late - * (elements were overwritten since Start), result is considered invalid and hence empty. - * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were less frequent). - * Can be changed (up to 1 hour) via pref: toolkit.framesRecording.bufferSize. - * - Note: the first frame-interval may be longer than expected because last frame - * might have been presented some time before calling StartFrameTimeRecording. - */ - - /** - * Returns a handle which represents current recording start position. - */ - virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize); - - /** - * Clears, then populates aFrameIntervals with the recorded frame timing - * data. The array will be empty if data was overwritten since - * aStartIndex was obtained. - */ - virtual void StopFrameTimeRecording(uint32_t aStartIndex, - nsTArray& aFrameIntervals); - - void RecordFrame(); - void PostPresent(); - - void BeginTabSwitch(); - static bool IsLogEnabled(); static mozilla::LogModule* GetLog(); @@ -686,27 +656,6 @@ protected: TimeStamp mAnimationReadyTime; // The count of pixels that were painted in the current transaction. uint32_t mPaintedPixelCount; -private: - struct FramesTimingRecording - { - // Stores state and data for frame intervals and paint times recording. - // see LayerManager::StartFrameTimeRecording() at Layers.cpp for more details. - FramesTimingRecording() - : mNextIndex(0) - , mLatestStartIndex(0) - , mCurrentRunStartIndex(0) - , mIsPaused(true) - {} - nsTArray mIntervals; - TimeStamp mLastFrameTime; - uint32_t mNextIndex; - uint32_t mLatestStartIndex; - uint32_t mCurrentRunStartIndex; - bool mIsPaused; - }; - FramesTimingRecording mRecording; - - TimeStamp mTabSwitchStart; public: /* diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index 41c37dc8ea..91e0696aa7 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -629,8 +629,6 @@ BasicLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback, if (mWidget) { FlashWidgetUpdateArea(mTarget); } - RecordFrame(); - PostPresent(); if (!mTransactionIncomplete) { // Clear out target if we have a complete transaction. diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index ddca3ec3c1..95af8fb5fc 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -617,28 +617,6 @@ ClientLayerManager::SendInvalidRegion(const nsIntRegion& aRegion) } } -uint32_t -ClientLayerManager::StartFrameTimeRecording(int32_t aBufferSize) -{ - CompositorBridgeChild* renderer = GetRemoteRenderer(); - if (renderer) { - uint32_t startIndex; - renderer->SendStartFrameTimeRecording(aBufferSize, &startIndex); - return startIndex; - } - return -1; -} - -void -ClientLayerManager::StopFrameTimeRecording(uint32_t aStartIndex, - nsTArray& aFrameIntervals) -{ - CompositorBridgeChild* renderer = GetRemoteRenderer(); - if (renderer) { - renderer->SendStopFrameTimeRecording(aStartIndex, &aFrameIntervals); - } -} - void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) { diff --git a/gfx/layers/client/ClientLayerManager.h b/gfx/layers/client/ClientLayerManager.h index 5bcd5e4121..e7ea7f8116 100644 --- a/gfx/layers/client/ClientLayerManager.h +++ b/gfx/layers/client/ClientLayerManager.h @@ -98,11 +98,6 @@ public: virtual void FlushRendering() override; void SendInvalidRegion(const nsIntRegion& aRegion); - virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize) override; - - virtual void StopFrameTimeRecording(uint32_t aStartIndex, - nsTArray& aFrameIntervals) override; - virtual bool NeedsWidgetInvalidation() override { return false; } ShadowableLayer* Hold(Layer* aLayer); diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 0ee11bdfb1..fde5eb1c57 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -966,8 +966,6 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion, const nsIntRegi } mCompositor->GetWidget()->PostRender(&widgetContext); - - RecordFrame(); } already_AddRefed diff --git a/gfx/layers/ipc/CompositorBridgeChild.cpp b/gfx/layers/ipc/CompositorBridgeChild.cpp index f0a1b861ae..ed5c3d52c5 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.cpp +++ b/gfx/layers/ipc/CompositorBridgeChild.cpp @@ -802,24 +802,6 @@ CompositorBridgeChild::SendFlushRendering() return PCompositorBridgeChild::SendFlushRendering(); } -bool -CompositorBridgeChild::SendStartFrameTimeRecording(const int32_t& bufferSize, uint32_t* startIndex) -{ - if (!mCanSend) { - return false; - } - return PCompositorBridgeChild::SendStartFrameTimeRecording(bufferSize, startIndex); -} - -bool -CompositorBridgeChild::SendStopFrameTimeRecording(const uint32_t& startIndex, nsTArray* intervals) -{ - if (!mCanSend) { - return false; - } - return PCompositorBridgeChild::SendStopFrameTimeRecording(startIndex, intervals); -} - bool CompositorBridgeChild::SendNotifyRegionInvalidated(const nsIntRegion& region) { diff --git a/gfx/layers/ipc/CompositorBridgeChild.h b/gfx/layers/ipc/CompositorBridgeChild.h index e5a4906b3e..55b8d37c2d 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.h +++ b/gfx/layers/ipc/CompositorBridgeChild.h @@ -159,8 +159,6 @@ public: bool SendMakeSnapshot(const SurfaceDescriptor& inSnapshot, const gfx::IntRect& dirtyRect); bool SendFlushRendering(); bool SendGetTileSize(int32_t* tileWidth, int32_t* tileHeight); - bool SendStartFrameTimeRecording(const int32_t& bufferSize, uint32_t* startIndex); - bool SendStopFrameTimeRecording(const uint32_t& startIndex, nsTArray* intervals); bool SendNotifyRegionInvalidated(const nsIntRegion& region); bool SendRequestNotifyAfterRemotePaint(); bool SendClearApproximatelyVisibleRegions(uint64_t aLayersId, uint32_t aPresShellId); diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index 25ac10130d..b035403cfe 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -817,27 +817,6 @@ CompositorBridgeParent::Invalidate() } } -bool -CompositorBridgeParent::RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) -{ - if (mLayerManager) { - *aOutStartIndex = mLayerManager->StartFrameTimeRecording(aBufferSize); - } else { - *aOutStartIndex = 0; - } - return true; -} - -bool -CompositorBridgeParent::RecvStopFrameTimeRecording(const uint32_t& aStartIndex, - InfallibleTArray* intervals) -{ - if (mLayerManager) { - mLayerManager->StopFrameTimeRecording(aStartIndex, *intervals); - } - return true; -} - bool CompositorBridgeParent::RecvClearApproximatelyVisibleRegions(const uint64_t& aLayersId, const uint32_t& aPresShellId) diff --git a/gfx/layers/ipc/CompositorBridgeParent.h b/gfx/layers/ipc/CompositorBridgeParent.h index d4f2da54c2..98812f75c8 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -281,8 +281,6 @@ public: } virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override; - virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override; - virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray* intervals) override; // Unused for chrome <-> compositor communication (which this class does). // @see CrossProcessCompositorBridgeParent::RecvRequestNotifyAfterRemotePaint diff --git a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h index 76a90f71b1..919fcfbc4f 100644 --- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h +++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h @@ -56,8 +56,6 @@ public: virtual bool RecvFlushRendering() override { return true; } virtual bool RecvForcePresent() override { return true; } virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return true; } - virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return true; } - virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray* intervals) override { return true; } virtual bool RecvClearApproximatelyVisibleRegions(const uint64_t& aLayersId, const uint32_t& aPresShellId) override; diff --git a/gfx/layers/ipc/PCompositorBridge.ipdl b/gfx/layers/ipc/PCompositorBridge.ipdl index 03a3535063..f47e45d92c 100644 --- a/gfx/layers/ipc/PCompositorBridge.ipdl +++ b/gfx/layers/ipc/PCompositorBridge.ipdl @@ -184,12 +184,6 @@ parent: // work around a windows presentation bug (See Bug 1232042) async ForcePresent(); - sync StartFrameTimeRecording(int32_t bufferSize) - returns (uint32_t startIndex); - - sync StopFrameTimeRecording(uint32_t startIndex) - returns (float[] intervals); - // layersBackendHints is an ordered list of preffered backends where // layersBackendHints[0] is the best backend. If any hints are LayersBackend::LAYERS_NONE // that hint is ignored. From 069b11c14c732ca3863c65e68e23c93d8cee4b80 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 24 Oct 2022 23:45:38 -0500 Subject: [PATCH 09/14] Issue #2022 - Part 1 - Fix transparent windows on MacOS 13 Ventura. During the BaseWindow creation contenView is nil on Ventura... So create a NSView with the requested dimensions and set is as the contenView. --- widget/cocoa/nsCocoaWindow.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index a437504fd1..c15874715c 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -2903,6 +2903,10 @@ static NSMutableSet *gSwizzledFrameViewClasses = nil; { mDrawsIntoWindowFrame = NO; [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag]; + // MacOS 13 Ventura, doesn't seem to create the contentView... so create it ourselves + if(![super contentView]) { + [super setContentView:[[NSView alloc] initWithFrame:aContentRect]]; + } mState = nil; mActiveTitlebarColor = nil; mInactiveTitlebarColor = nil; From 70727d0a0b27b35eb512e268491dc18670b0171f Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 24 Oct 2022 23:47:42 -0500 Subject: [PATCH 10/14] Issue #2022 - Part 2 - Add Ventura version detection. Also add Monterey and Ventura to the graphics driver blocklist. --- widget/GfxDriverInfo.h | 17 +++++++++++++++++ widget/GfxInfoBase.cpp | 28 ++++++++++++++++++++++++++++ widget/cocoa/GfxInfo.mm | 12 ++++++------ widget/cocoa/nsCocoaFeatures.h | 1 + widget/cocoa/nsCocoaFeatures.mm | 13 +++++++++++-- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/widget/GfxDriverInfo.h b/widget/GfxDriverInfo.h index ad4337b0fb..119976bcbc 100644 --- a/widget/GfxDriverInfo.h +++ b/widget/GfxDriverInfo.h @@ -49,6 +49,23 @@ enum class OperatingSystem { Windows8_1, Windows10, Linux, + OSX, + OSX10_5, + OSX10_6, + OSX10_7, + OSX10_8, + OSX10_9, + OSX10_10, + OSX10_11, + OSX10_12, + OSX10_13, + OSX10_14, + OSX10_15, + OSX10_16, + OSX11_0, + OSX12_0, + OSX13_0, + Ios }; enum VersionComparisonOp { diff --git a/widget/GfxInfoBase.cpp b/widget/GfxInfoBase.cpp index 20e2e1476d..d1c7ac4e1e 100644 --- a/widget/GfxInfoBase.cpp +++ b/widget/GfxInfoBase.cpp @@ -264,6 +264,34 @@ BlacklistOSToOperatingSystem(const nsAString& os) return OperatingSystem::Windows10; else if (os.EqualsLiteral("Linux")) return OperatingSystem::Linux; + else if (os.EqualsLiteral("Darwin 9")) + return OperatingSystem::OSX10_5; + else if (os.EqualsLiteral("Darwin 10")) + return OperatingSystem::OSX10_6; + else if (os.EqualsLiteral("Darwin 11")) + return OperatingSystem::OSX10_7; + else if (os.EqualsLiteral("Darwin 12")) + return OperatingSystem::OSX10_8; + else if (os.EqualsLiteral("Darwin 13")) + return OperatingSystem::OSX10_9; + else if (os.EqualsLiteral("Darwin 14")) + return OperatingSystem::OSX10_10; + else if (os.EqualsLiteral("Darwin 15")) + return OperatingSystem::OSX10_11; + else if (os.EqualsLiteral("Darwin 16")) + return OperatingSystem::OSX10_12; + else if (os.EqualsLiteral("Darwin 17")) + return OperatingSystem::OSX10_13; + else if (os.EqualsLiteral("Darwin 18")) + return OperatingSystem::OSX10_14; + else if (os.EqualsLiteral("Darwin 19")) + return OperatingSystem::OSX10_15; + else if (os.EqualsLiteral("Darwin 20")) + return OperatingSystem::OSX11_0; + else if (os.EqualsLiteral("Darwin 21")) + return OperatingSystem::OSX12_0; + else if (os.EqualsLiteral("Darwin 22")) + return OperatingSystem::OSX13_0; // For historical reasons, "All" in blocklist means "All Windows" else if (os.EqualsLiteral("All")) return OperatingSystem::Windows; diff --git a/widget/cocoa/GfxInfo.mm b/widget/cocoa/GfxInfo.mm index 97bb4c8324..8e7edc1967 100644 --- a/widget/cocoa/GfxInfo.mm +++ b/widget/cocoa/GfxInfo.mm @@ -63,12 +63,12 @@ OSXVersionToOperatingSystem(uint32_t aOSXVersion) { } break; case 11: - switch (nsCocoaFeatures::ExtractMinorVersion(aOSXVersion)) { - case 0: - return OperatingSystem::OSX11_0; - default: - break; - } + return OperatingSystem::OSX11_0; + case 12: + return OperatingSystem::OSX12_0; + case 13: + return OperatingSystem::OSX13_0; + default: break; } diff --git a/widget/cocoa/nsCocoaFeatures.h b/widget/cocoa/nsCocoaFeatures.h index c6841a7491..28ad617387 100644 --- a/widget/cocoa/nsCocoaFeatures.h +++ b/widget/cocoa/nsCocoaFeatures.h @@ -26,6 +26,7 @@ public: static bool OnCatalinaOrLater(); static bool OnBigSurOrLater(); static bool OnMontereyOrLater(); + static bool OnVenturaOrLater(); static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0); diff --git a/widget/cocoa/nsCocoaFeatures.mm b/widget/cocoa/nsCocoaFeatures.mm index 2edb958931..fdfdf1023f 100644 --- a/widget/cocoa/nsCocoaFeatures.mm +++ b/widget/cocoa/nsCocoaFeatures.mm @@ -27,6 +27,7 @@ #define MACOS_VERSION_10_16_HEX 0x000A1000 #define MACOS_VERSION_11_0_HEX 0x000B0000 #define MACOS_VERSION_12_0_HEX 0x000C0000 +#define MACOS_VERSION_13_0_HEX 0x000D0000 #include "nsCocoaFeatures.h" #include "nsCocoaUtils.h" @@ -212,7 +213,8 @@ nsCocoaFeatures::OnBigSurOrLater() (macOSVersion() >= MACOS_VERSION_11_0_HEX)); } -/* static */ bool nsCocoaFeatures::OnMontereyOrLater() +/* static */ bool +nsCocoaFeatures::OnMontereyOrLater() { // Monterey pretends to be 10.16 and is indistinguishable from Big Sur. // In practice, this means that an Intel build can return false @@ -221,6 +223,12 @@ nsCocoaFeatures::OnBigSurOrLater() return (macOSVersion() >= MACOS_VERSION_12_0_HEX); } +/* static */ bool +nsCocoaFeatures::OnVenturaOrLater() +{ + return (macOSVersion() >= MACOS_VERSION_13_0_HEX); +} + /* static */ bool nsCocoaFeatures::IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix) { @@ -234,7 +242,8 @@ nsCocoaFeatures::IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFi * for this purpose. Note: using this in a sandboxed process requires allowing * the sysctl in the sandbox policy. */ -/* static */ bool nsCocoaFeatures::ProcessIsRosettaTranslated() +/* static */ bool +nsCocoaFeatures::ProcessIsRosettaTranslated() { int ret = 0; size_t size = sizeof(ret); From 8b8084f6613a19e3603d35e53f8af76fa88e75c3 Mon Sep 17 00:00:00 2001 From: athenian200 Date: Wed, 26 Oct 2022 01:18:43 +0000 Subject: [PATCH 11/14] Issue #1824 - Remove dependency on libdemangle. This may be removed from illumos soon, and it is apparently unused anyway, so leaving it in doesn't make sense. --- toolkit/library/moz.build | 1 - 1 file changed, 1 deletion(-) diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index 4f9b142eb3..4dd7729290 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -253,7 +253,6 @@ if CONFIG['MOZ_ENABLE_LIBPROXY']: if CONFIG['OS_ARCH'] == 'SunOS': OS_LIBS += [ 'elf', - 'demangle', 'sendfile', ] From e69b52eac1364dc02409d666dd94950985ff79e0 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 26 Oct 2022 08:05:04 +0000 Subject: [PATCH 12/14] Hold some strong references on nsRefreshDriver --- dom/base/nsDOMWindowUtils.cpp | 2 +- image/SVGDocumentWrapper.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 69f1787b9f..18204efdc1 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -2409,7 +2409,7 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds) nsPresContext* presContext = GetPresContext(); if (presContext) { - nsRefreshDriver* driver = presContext->RefreshDriver(); + RefPtr driver = presContext->RefreshDriver(); driver->AdvanceTimeAndRefresh(aMilliseconds); RefPtr transaction = GetLayerTransaction(); diff --git a/image/SVGDocumentWrapper.cpp b/image/SVGDocumentWrapper.cpp index d4b71b907c..6438c179e4 100644 --- a/image/SVGDocumentWrapper.cpp +++ b/image/SVGDocumentWrapper.cpp @@ -212,9 +212,12 @@ SVGDocumentWrapper::TickRefreshDriver() nsCOMPtr presShell; mViewer->GetPresShell(getter_AddRefs(presShell)); if (presShell) { - nsPresContext* presContext = presShell->GetPresContext(); + RefPtr presContext = presShell->GetPresContext(); if (presContext) { - presContext->RefreshDriver()->DoTick(); + RefPtr driver = presContext->RefreshDriver(); + if (driver) { + driver->DoTick(); + } } } } From 3fccd404fbdf3ef65e4000b1cc88822a86858aa2 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 26 Oct 2022 09:24:27 +0000 Subject: [PATCH 13/14] [XPCOM] Fix Base64 off-by-one issue and safeguard against this mistake in the future. --- xpcom/io/Base64.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/xpcom/io/Base64.cpp b/xpcom/io/Base64.cpp index fa8e6f86cc..a93c78a7f3 100644 --- a/xpcom/io/Base64.cpp +++ b/xpcom/io/Base64.cpp @@ -246,6 +246,7 @@ EncodeInputStream(nsIInputStream* aInputStream, static const char kBase64URLAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +static_assert(mozilla::ArrayLength(kBase64URLAlphabet) == 0x41); // Maps an encoded character to a value in the Base64 URL alphabet, per // RFC 4648, Table 2. Invalid input characters map to UINT8_MAX. @@ -267,14 +268,19 @@ static const uint8_t kBase64URLDecodeTable[] = { 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, /* a - z */ - 255, 255, 255, 255, + 255, 255, 255, 255, 255 }; +static_assert(mozilla::ArrayLength(kBase64URLDecodeTable) == 0x80); bool Base64URLCharToValue(char aChar, uint8_t* aValue) { uint8_t index = static_cast(aChar); - *aValue = kBase64URLDecodeTable[index & 0x7f]; - return (*aValue != 255) && !(index & ~0x7f); + if (index >= mozilla::ArrayLength(kBase64URLDecodeTable)) { + *aValue = 255; + return false; + } + *aValue = kBase64URLDecodeTable[index]; + return *aValue != 255; } } // namespace From 2f0acd868e3352e0bb2bbd8f86fc2244ffb4bac2 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 26 Oct 2022 13:52:42 +0000 Subject: [PATCH 14/14] [WebGL] Implement webgl.max-size-per-texture-mib --- dom/canvas/WebGLTextureUpload.cpp | 50 ++++++++++++++++++++++--------- gfx/thebes/gfxPrefs.h | 1 + modules/libpref/init/all.js | 1 + 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp index ae60d2a2b0..ed199cfb43 100644 --- a/dom/canvas/WebGLTextureUpload.cpp +++ b/dom/canvas/WebGLTextureUpload.cpp @@ -303,13 +303,13 @@ WebGLContext::FromDomElem(const char* funcName, TexImageTarget target, uint32_t uint32_t height, uint32_t depth, const dom::Element& elem, ErrorResult* const out_error) { - if (elem.IsHTMLElement(nsGkAtoms::canvas)) { - const dom::HTMLCanvasElement* canvas = static_cast(&elem); - if (canvas->IsWriteOnly()) { - out_error->Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } - } + if (elem.IsHTMLElement(nsGkAtoms::canvas)) { + const dom::HTMLCanvasElement* canvas = static_cast(&elem); + if (canvas->IsWriteOnly()) { + out_error->Throw(NS_ERROR_DOM_SECURITY_ERR); + return nullptr; + } + } uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE | nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR; @@ -1032,9 +1032,27 @@ ValidateCompressedTexImageRestrictions(const char* funcName, WebGLContext* webgl } static bool -ValidateTargetForFormat(const char* funcName, WebGLContext* webgl, TexImageTarget target, - const webgl::FormatInfo* format) -{ +ValidateFormatAndSize(const char* funcName, + WebGLContext* webgl, + TexImageTarget target, + const webgl::FormatInfo* format, + const uint32_t width, + const uint32_t height, + const uint32_t depth) { + // Check if texture size will likely be rejected by the driver and give a more + // meaningful error message. + auto baseImageSize = CheckedInt(format->estimatedBytesPerPixel) * + width * height * depth; + if (target == LOCAL_GL_TEXTURE_CUBE_MAP) { + baseImageSize *= 6; + } + + if (!baseImageSize.isValid() || + baseImageSize.value() > (uint64_t)gfxPrefs::WebGLMaxSizePerTextureMB * (1024 * 1024)) { + webgl->ErrorOutOfMemory("Texture size too large; base image MB > webgl.max-size-per-texture-mb"); + return false; + } + // GLES 3.0.4 p127: // "Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are // supported by texture image specification commands only if `target` is TEXTURE_2D, @@ -1137,7 +1155,8 @@ WebGLTexture::TexStorage(const char* funcName, TexTarget target, GLsizei levels, } auto dstFormat = dstUsage->format; - if (!ValidateTargetForFormat(funcName, mContext, testTarget, dstFormat)) + if (!ValidateFormatAndSize(funcName, mContext, testTarget, dstFormat, + width, height, depth)) return; if (dstFormat->compression) { @@ -1264,7 +1283,8 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level, // Check that source and dest info are compatible auto dstFormat = dstUsage->format; - if (!ValidateTargetForFormat(funcName, mContext, target, dstFormat)) + if (!ValidateFormatAndSize(funcName, mContext, target, dstFormat, + blob->mWidth, blob->mHeight, blob->mDepth)) return; if (!mContext->IsWebGL2() && dstFormat->d) { @@ -1484,7 +1504,8 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL return; } - if (!ValidateTargetForFormat(funcName, mContext, target, format)) + if (!ValidateFormatAndSize(funcName, mContext, target, format, + blob->mWidth, blob->mHeight, blob->mDepth)) return; //////////////////////////////////// @@ -2143,7 +2164,8 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal return; const auto& dstFormat = dstUsage->format; - if (!ValidateTargetForFormat(funcName, mContext, target, dstFormat)) + if (!ValidateFormatAndSize(funcName, mContext, target, dstFormat, + width, height, depth)) return; if (!mContext->IsWebGL2() && dstFormat->d) { diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index c49c7b441c..934bca81e4 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -593,6 +593,7 @@ private: DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false); DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, bool, false); DECL_GFX_PREF(Live, "webgl.max-warnings-per-context", WebGLMaxWarningsPerContext, uint32_t, 32); + DECL_GFX_PREF(Live, "webgl.max-size-per-texture-mb", WebGLMaxSizePerTextureMB, uint32_t, 1024); DECL_GFX_PREF(Live, "webgl.min_capability_mode", WebGLMinCapabilityMode, bool, false); DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false); DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index ec30c9d4b2..f9f1e80540 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4280,6 +4280,7 @@ pref("webgl.lose-context-on-memory-pressure", false); pref("webgl.can-lose-context-in-foreground", true); pref("webgl.restore-context-when-visible", true); pref("webgl.max-warnings-per-context", 32); +pref("webgl.max-size-per-texture-mb", 1024); pref("webgl.enable-draft-extensions", false); pref("webgl.enable-privileged-extensions", false); pref("webgl.bypass-shader-validation", false);