ma1 pushed to branch tor-browser-115.1.0esr-13.0-1 at The Tor Project / Applications / Tor Browser
Commits:
-
a9279174
by Edgar Chen at 2023-07-31T23:49:06+02:00
-
9f2eaedb
by Edgar Chen at 2023-07-31T23:49:06+02:00
-
30d19aa0
by Eitan Isaacson at 2023-07-31T23:49:07+02:00
-
efee8978
by Jon Coppeard at 2023-07-31T23:49:07+02:00
12 changed files:
- accessible/android/SessionAccessibility.cpp
- accessible/android/SessionAccessibility.h
- accessible/ipc/DocAccessibleParent.cpp
- accessible/ipc/DocAccessibleParent.h
- accessible/ipc/moz.build
- browser/base/content/browser-fullScreenAndPointerLock.js
- browser/base/content/fullscreen-and-pointerlock.inc.xhtml
- browser/base/content/test/fullscreen/browser_fullscreen_warning.js
- dom/tests/browser/browser_pointerlock_warning.js
- js/src/gc/GC.cpp
- js/src/gc/ParallelMarking.cpp
- js/src/vm/HelperThreadState.h
Changes:
| ... | ... | @@ -269,12 +269,9 @@ RefPtr<SessionAccessibility> SessionAccessibility::GetInstanceFor( |
| 269 | 269 | return GetInstanceFor(doc->GetPresShell());
|
| 270 | 270 | }
|
| 271 | 271 | } else {
|
| 272 | - DocAccessibleParent* remoteDoc = aAccessible->AsRemote()->Document();
|
|
| 273 | - if (remoteDoc->mSessionAccessibility) {
|
|
| 274 | - return remoteDoc->mSessionAccessibility;
|
|
| 275 | - }
|
|
| 276 | 272 | dom::CanonicalBrowsingContext* cbc =
|
| 277 | - static_cast<dom::BrowserParent*>(remoteDoc->Manager())
|
|
| 273 | + static_cast<dom::BrowserParent*>(
|
|
| 274 | + aAccessible->AsRemote()->Document()->Manager())
|
|
| 278 | 275 | ->GetBrowsingContext()
|
| 279 | 276 | ->Top();
|
| 280 | 277 | dom::BrowserParent* bp = cbc->GetBrowserParent();
|
| ... | ... | @@ -285,10 +282,7 @@ RefPtr<SessionAccessibility> SessionAccessibility::GetInstanceFor( |
| 285 | 282 | if (auto element = bp->GetOwnerElement()) {
|
| 286 | 283 | if (auto doc = element->OwnerDoc()) {
|
| 287 | 284 | if (nsPresContext* presContext = doc->GetPresContext()) {
|
| 288 | - RefPtr<SessionAccessibility> sessionAcc =
|
|
| 289 | - GetInstanceFor(presContext->PresShell());
|
|
| 290 | - remoteDoc->mSessionAccessibility = sessionAcc;
|
|
| 291 | - return sessionAcc;
|
|
| 285 | + return GetInstanceFor(presContext->PresShell());
|
|
| 292 | 286 | }
|
| 293 | 287 | } else {
|
| 294 | 288 | MOZ_ASSERT_UNREACHABLE(
|
| ... | ... | @@ -684,14 +678,7 @@ void SessionAccessibility::PopulateNodeInfo( |
| 684 | 678 | }
|
| 685 | 679 | |
| 686 | 680 | Accessible* SessionAccessibility::GetAccessibleByID(int32_t aID) const {
|
| 687 | - Accessible* accessible = mIDToAccessibleMap.Get(aID);
|
|
| 688 | - if (accessible && accessible->IsLocal() &&
|
|
| 689 | - accessible->AsLocal()->IsDefunct()) {
|
|
| 690 | - MOZ_ASSERT_UNREACHABLE("Registered accessible is defunct!");
|
|
| 691 | - return nullptr;
|
|
| 692 | - }
|
|
| 693 | - |
|
| 694 | - return accessible;
|
|
| 681 | + return mIDToAccessibleMap.Get(aID);
|
|
| 695 | 682 | }
|
| 696 | 683 | |
| 697 | 684 | #ifdef DEBUG
|
| ... | ... | @@ -705,6 +692,58 @@ static bool IsDetachedDoc(Accessible* aAccessible) { |
| 705 | 692 | }
|
| 706 | 693 | #endif
|
| 707 | 694 | |
| 695 | +SessionAccessibility::IDMappingEntry::IDMappingEntry(Accessible* aAccessible)
|
|
| 696 | + : mInternalID(0) {
|
|
| 697 | + *this = aAccessible;
|
|
| 698 | +}
|
|
| 699 | + |
|
| 700 | +SessionAccessibility::IDMappingEntry&
|
|
| 701 | +SessionAccessibility::IDMappingEntry::operator=(Accessible* aAccessible) {
|
|
| 702 | + mInternalID = aAccessible->ID();
|
|
| 703 | + MOZ_ASSERT(!(mInternalID & IS_REMOTE), "First bit is used in accessible ID!");
|
|
| 704 | + if (aAccessible->IsRemote()) {
|
|
| 705 | + mInternalID |= IS_REMOTE;
|
|
| 706 | + }
|
|
| 707 | + |
|
| 708 | + Accessible* docAcc = nsAccUtils::DocumentFor(aAccessible);
|
|
| 709 | + MOZ_ASSERT(docAcc);
|
|
| 710 | + if (docAcc) {
|
|
| 711 | + MOZ_ASSERT(docAcc->IsRemote() == aAccessible->IsRemote());
|
|
| 712 | + if (docAcc->IsRemote()) {
|
|
| 713 | + mDoc = docAcc->AsRemote()->AsDoc();
|
|
| 714 | + } else {
|
|
| 715 | + mDoc = docAcc->AsLocal();
|
|
| 716 | + }
|
|
| 717 | + }
|
|
| 718 | + |
|
| 719 | + return *this;
|
|
| 720 | +}
|
|
| 721 | + |
|
| 722 | +SessionAccessibility::IDMappingEntry::operator Accessible*() const {
|
|
| 723 | + if (mInternalID == 0) {
|
|
| 724 | + return static_cast<LocalAccessible*>(mDoc.get());
|
|
| 725 | + }
|
|
| 726 | + |
|
| 727 | + if (mInternalID == IS_REMOTE) {
|
|
| 728 | + return static_cast<DocAccessibleParent*>(mDoc.get());
|
|
| 729 | + }
|
|
| 730 | + |
|
| 731 | + if (mInternalID & IS_REMOTE) {
|
|
| 732 | + return static_cast<DocAccessibleParent*>(mDoc.get())
|
|
| 733 | + ->GetAccessible(mInternalID & ~IS_REMOTE);
|
|
| 734 | + }
|
|
| 735 | + |
|
| 736 | + Accessible* accessible =
|
|
| 737 | + static_cast<LocalAccessible*>(mDoc.get())
|
|
| 738 | + ->AsDoc()
|
|
| 739 | + ->GetAccessibleByUniqueID(reinterpret_cast<void*>(mInternalID));
|
|
| 740 | + // If the accessible is retrievable from the DocAccessible, it can't be
|
|
| 741 | + // defunct.
|
|
| 742 | + MOZ_ASSERT(!accessible->AsLocal()->IsDefunct());
|
|
| 743 | + |
|
| 744 | + return accessible;
|
|
| 745 | +}
|
|
| 746 | + |
|
| 708 | 747 | void SessionAccessibility::RegisterAccessible(Accessible* aAccessible) {
|
| 709 | 748 | if (IPCAccessibilityActive()) {
|
| 710 | 749 | // Don't register accessible in content process.
|
| ... | ... | @@ -766,7 +805,6 @@ void SessionAccessibility::UnregisterAccessible(Accessible* aAccessible) { |
| 766 | 805 | }
|
| 767 | 806 | |
| 768 | 807 | RefPtr<SessionAccessibility> sessionAcc = GetInstanceFor(aAccessible);
|
| 769 | - MOZ_ASSERT(sessionAcc, "Need SessionAccessibility to unregister Accessible!");
|
|
| 770 | 808 | if (sessionAcc) {
|
| 771 | 809 | Accessible* registeredAcc =
|
| 772 | 810 | sessionAcc->mIDToAccessibleMap.Get(virtualViewID);
|
| ... | ... | @@ -110,10 +110,34 @@ class SessionAccessibility final |
| 110 | 110 | jni::NativeWeakPtr<widget::GeckoViewSupport> mWindow; // Parent only
|
| 111 | 111 | java::SessionAccessibility::NativeProvider::GlobalRef mSessionAccessibility;
|
| 112 | 112 | |
| 113 | + class IDMappingEntry {
|
|
| 114 | + public:
|
|
| 115 | + explicit IDMappingEntry(Accessible* aAccessible);
|
|
| 116 | + |
|
| 117 | + IDMappingEntry& operator=(Accessible* aAccessible);
|
|
| 118 | + |
|
| 119 | + operator Accessible*() const;
|
|
| 120 | + |
|
| 121 | + private:
|
|
| 122 | + // A strong reference to a DocAccessible or DocAccessibleParent. They don't
|
|
| 123 | + // share any useful base class except nsISupports, so we use that.
|
|
| 124 | + // When we retrieve the document from this reference we cast it to
|
|
| 125 | + // LocalAccessible in the DocAccessible case because DocAccessible has
|
|
| 126 | + // multiple inheritance paths for nsISupports.
|
|
| 127 | + RefPtr<nsISupports> mDoc;
|
|
| 128 | + // The ID of the accessible as used in the internal doc mapping.
|
|
| 129 | + // We rely on this ID being pointer derived and therefore divisible by two
|
|
| 130 | + // so we can use the first bit to mark if it is remote or not.
|
|
| 131 | + uint64_t mInternalID;
|
|
| 132 | + |
|
| 133 | + static const uintptr_t IS_REMOTE = 0x1;
|
|
| 134 | + };
|
|
| 135 | + |
|
| 113 | 136 | /*
|
| 114 | 137 | * This provides a mapping from 32 bit id to accessible objects.
|
| 115 | 138 | */
|
| 116 | - nsTHashMap<nsUint32HashKey, Accessible*> mIDToAccessibleMap;
|
|
| 139 | + nsBaseHashtable<nsUint32HashKey, IDMappingEntry, Accessible*>
|
|
| 140 | + mIDToAccessibleMap;
|
|
| 117 | 141 | };
|
| 118 | 142 | |
| 119 | 143 | } // namespace a11y
|
| ... | ... | @@ -29,7 +29,6 @@ |
| 29 | 29 | #endif
|
| 30 | 30 | |
| 31 | 31 | #if defined(ANDROID)
|
| 32 | -# include "mozilla/a11y/SessionAccessibility.h"
|
|
| 33 | 32 | # define ACQUIRE_ANDROID_LOCK \
|
| 34 | 33 | MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
|
| 35 | 34 | #else
|
| ... | ... | @@ -29,10 +29,6 @@ class xpcAccessibleGeneric; |
| 29 | 29 | class DocAccessiblePlatformExtParent;
|
| 30 | 30 | #endif
|
| 31 | 31 | |
| 32 | -#ifdef ANDROID
|
|
| 33 | -class SessionAccessibility;
|
|
| 34 | -#endif
|
|
| 35 | - |
|
| 36 | 32 | /*
|
| 37 | 33 | * These objects live in the main process and comunicate with and represent
|
| 38 | 34 | * an accessible document in a content process.
|
| ... | ... | @@ -348,10 +344,6 @@ class DocAccessibleParent : public RemoteAccessible, |
| 348 | 344 | |
| 349 | 345 | size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) override;
|
| 350 | 346 | |
| 351 | -#ifdef ANDROID
|
|
| 352 | - RefPtr<SessionAccessibility> mSessionAccessibility;
|
|
| 353 | -#endif
|
|
| 354 | - |
|
| 355 | 347 | private:
|
| 356 | 348 | ~DocAccessibleParent();
|
| 357 | 349 |
| ... | ... | @@ -24,11 +24,6 @@ else: |
| 24 | 24 | LOCAL_INCLUDES += [
|
| 25 | 25 | "/accessible/mac",
|
| 26 | 26 | ]
|
| 27 | - elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android":
|
|
| 28 | - LOCAL_INCLUDES += [
|
|
| 29 | - "/accessible/android",
|
|
| 30 | - "/widget/android",
|
|
| 31 | - ]
|
|
| 32 | 27 | else:
|
| 33 | 28 | LOCAL_INCLUDES += [
|
| 34 | 29 | "/accessible/other",
|
| ... | ... | @@ -62,9 +62,14 @@ var PointerlockFsWarning = { |
| 62 | 62 | this._element = document.getElementById(elementId);
|
| 63 | 63 | // Setup event listeners
|
| 64 | 64 | this._element.addEventListener("transitionend", this);
|
| 65 | + this._element.addEventListener("transitioncancel", this);
|
|
| 65 | 66 | window.addEventListener("mousemove", this, true);
|
| 67 | + window.addEventListener("activate", this);
|
|
| 68 | + window.addEventListener("deactivate", this);
|
|
| 66 | 69 | // The timeout to hide the warning box after a while.
|
| 67 | 70 | this._timeoutHide = new this.Timeout(() => {
|
| 71 | + window.removeEventListener("activate", this);
|
|
| 72 | + window.removeEventListener("deactivate", this);
|
|
| 68 | 73 | this._state = "hidden";
|
| 69 | 74 | }, timeout);
|
| 70 | 75 | // The timeout to show the warning box when the pointer is at the top
|
| ... | ... | @@ -116,11 +121,10 @@ var PointerlockFsWarning = { |
| 116 | 121 | return;
|
| 117 | 122 | }
|
| 118 | 123 | |
| 119 | - // Explicitly set the last state to hidden to avoid the warning
|
|
| 120 | - // box being hidden immediately because of mousemove.
|
|
| 121 | - this._state = "onscreen";
|
|
| 122 | - this._lastState = "hidden";
|
|
| 123 | - this._timeoutHide.start();
|
|
| 124 | + if (Services.focus.activeWindow == window) {
|
|
| 125 | + this._state = "onscreen";
|
|
| 126 | + this._timeoutHide.start();
|
|
| 127 | + }
|
|
| 124 | 128 | },
|
| 125 | 129 | |
| 126 | 130 | /**
|
| ... | ... | @@ -148,7 +152,10 @@ var PointerlockFsWarning = { |
| 148 | 152 | this._element.hidden = true;
|
| 149 | 153 | // Remove all event listeners
|
| 150 | 154 | this._element.removeEventListener("transitionend", this);
|
| 155 | + this._element.removeEventListener("transitioncancel", this);
|
|
| 151 | 156 | window.removeEventListener("mousemove", this, true);
|
| 157 | + window.removeEventListener("activate", this);
|
|
| 158 | + window.removeEventListener("deactivate", this);
|
|
| 152 | 159 | // Clear fields
|
| 153 | 160 | this._element = null;
|
| 154 | 161 | this._timeoutHide = null;
|
| ... | ... | @@ -186,7 +193,7 @@ var PointerlockFsWarning = { |
| 186 | 193 | }
|
| 187 | 194 | if (newState != "hidden") {
|
| 188 | 195 | if (currentState != "hidden") {
|
| 189 | - this._element.setAttribute(newState, true);
|
|
| 196 | + this._element.setAttribute(newState, "");
|
|
| 190 | 197 | } else {
|
| 191 | 198 | // When the previous state is hidden, the display was none,
|
| 192 | 199 | // thus no box was constructed. We need to wait for the new
|
| ... | ... | @@ -197,7 +204,7 @@ var PointerlockFsWarning = { |
| 197 | 204 | requestAnimationFrame(() => {
|
| 198 | 205 | requestAnimationFrame(() => {
|
| 199 | 206 | if (this._element) {
|
| 200 | - this._element.setAttribute(newState, true);
|
|
| 207 | + this._element.setAttribute(newState, "");
|
|
| 201 | 208 | }
|
| 202 | 209 | });
|
| 203 | 210 | });
|
| ... | ... | @@ -217,7 +224,7 @@ var PointerlockFsWarning = { |
| 217 | 224 | } else if (this._timeoutShow.delay >= 0) {
|
| 218 | 225 | this._timeoutShow.start();
|
| 219 | 226 | }
|
| 220 | - } else {
|
|
| 227 | + } else if (state != "onscreen") {
|
|
| 221 | 228 | let elemRect = this._element.getBoundingClientRect();
|
| 222 | 229 | if (state == "hiding" && this._lastState != "hidden") {
|
| 223 | 230 | // If we are on the hiding transition, and the pointer
|
| ... | ... | @@ -239,12 +246,23 @@ var PointerlockFsWarning = { |
| 239 | 246 | }
|
| 240 | 247 | break;
|
| 241 | 248 | }
|
| 242 | - case "transitionend": {
|
|
| 249 | + case "transitionend":
|
|
| 250 | + case "transitioncancel": {
|
|
| 243 | 251 | if (this._state == "hiding") {
|
| 244 | 252 | this._element.hidden = true;
|
| 245 | 253 | }
|
| 246 | 254 | break;
|
| 247 | 255 | }
|
| 256 | + case "activate": {
|
|
| 257 | + this._state = "onscreen";
|
|
| 258 | + this._timeoutHide.start();
|
|
| 259 | + break;
|
|
| 260 | + }
|
|
| 261 | + case "deactivate": {
|
|
| 262 | + this._state = "hidden";
|
|
| 263 | + this._timeoutHide.cancel();
|
|
| 264 | + break;
|
|
| 265 | + }
|
|
| 248 | 266 | }
|
| 249 | 267 | },
|
| 250 | 268 | };
|
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| 4 | 4 | |
| 5 | 5 | <html:div id="fullscreen-and-pointerlock-wrapper">
|
| 6 | - <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true">
|
|
| 6 | + <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="">
|
|
| 7 | 7 | <html:div class="pointerlockfswarning-domain-text">
|
| 8 | 8 | <html:span class="pointerlockfswarning-domain" data-l10n-name="domain"/>
|
| 9 | 9 | </html:div>
|
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | </html:button>
|
| 21 | 21 | </html:div>
|
| 22 | 22 | |
| 23 | - <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="true">
|
|
| 23 | + <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="">
|
|
| 24 | 24 | <html:div class="pointerlockfswarning-domain-text">
|
| 25 | 25 | <html:span class="pointerlockfswarning-domain" data-l10n-name="domain"/>
|
| 26 | 26 | </html:div>
|
| ... | ... | @@ -3,14 +3,35 @@ |
| 3 | 3 | |
| 4 | 4 | "use strict";
|
| 5 | 5 | |
| 6 | -add_task(async function test_fullscreen_display_none() {
|
|
| 6 | +function checkWarningState(aWarningElement, aExpectedState, aMsg) {
|
|
| 7 | + ["hidden", "ontop", "onscreen"].forEach(state => {
|
|
| 8 | + is(
|
|
| 9 | + aWarningElement.hasAttribute(state),
|
|
| 10 | + state == aExpectedState,
|
|
| 11 | + `${aMsg} - check ${state} attribute.`
|
|
| 12 | + );
|
|
| 13 | + });
|
|
| 14 | +}
|
|
| 15 | + |
|
| 16 | +async function waitForWarningState(aWarningElement, aExpectedState) {
|
|
| 17 | + await BrowserTestUtils.waitForAttribute(aExpectedState, aWarningElement, "");
|
|
| 18 | + checkWarningState(
|
|
| 19 | + aWarningElement,
|
|
| 20 | + aExpectedState,
|
|
| 21 | + `Wait for ${aExpectedState} state`
|
|
| 22 | + );
|
|
| 23 | +}
|
|
| 24 | + |
|
| 25 | +add_setup(async function init() {
|
|
| 7 | 26 | await SpecialPowers.pushPrefEnv({
|
| 8 | 27 | set: [
|
| 9 | 28 | ["full-screen-api.enabled", true],
|
| 10 | 29 | ["full-screen-api.allow-trusted-requests-only", false],
|
| 11 | 30 | ],
|
| 12 | 31 | });
|
| 32 | +});
|
|
| 13 | 33 | |
| 34 | +add_task(async function test_fullscreen_display_none() {
|
|
| 14 | 35 | await BrowserTestUtils.withNewTab(
|
| 15 | 36 | {
|
| 16 | 37 | gBrowser,
|
| ... | ... | @@ -30,11 +51,13 @@ add_task(async function test_fullscreen_display_none() { |
| 30 | 51 | },
|
| 31 | 52 | async function (browser) {
|
| 32 | 53 | let warning = document.getElementById("fullscreen-warning");
|
| 33 | - let warningShownPromise = BrowserTestUtils.waitForAttribute(
|
|
| 34 | - "onscreen",
|
|
| 54 | + checkWarningState(
|
|
| 35 | 55 | warning,
|
| 36 | - "true"
|
|
| 56 | + "hidden",
|
|
| 57 | + "Should not show full screen warning initially"
|
|
| 37 | 58 | );
|
| 59 | + |
|
| 60 | + let warningShownPromise = waitForWarningState(warning, "onscreen");
|
|
| 38 | 61 | // Enter fullscreen
|
| 39 | 62 | await SpecialPowers.spawn(browser, [], async () => {
|
| 40 | 63 | let frame = content.document.querySelector("iframe");
|
| ... | ... | @@ -54,39 +77,33 @@ add_task(async function test_fullscreen_display_none() { |
| 54 | 77 | );
|
| 55 | 78 | document.getElementById("fullscreen-exit-button").click();
|
| 56 | 79 | await exitFullscreenPromise;
|
| 80 | + |
|
| 81 | + checkWarningState(
|
|
| 82 | + warning,
|
|
| 83 | + "hidden",
|
|
| 84 | + "Should hide fullscreen warning after exiting fullscreen"
|
|
| 85 | + );
|
|
| 57 | 86 | }
|
| 58 | 87 | );
|
| 59 | 88 | });
|
| 60 | 89 | |
| 61 | 90 | add_task(async function test_fullscreen_pointerlock_conflict() {
|
| 62 | - await SpecialPowers.pushPrefEnv({
|
|
| 63 | - set: [
|
|
| 64 | - ["full-screen-api.enabled", true],
|
|
| 65 | - ["full-screen-api.allow-trusted-requests-only", false],
|
|
| 66 | - ],
|
|
| 67 | - });
|
|
| 68 | - |
|
| 69 | 91 | await BrowserTestUtils.withNewTab("https://example.com", async browser => {
|
| 70 | 92 | let fsWarning = document.getElementById("fullscreen-warning");
|
| 71 | 93 | let plWarning = document.getElementById("pointerlock-warning");
|
| 72 | 94 | |
| 73 | - is(
|
|
| 74 | - fsWarning.getAttribute("onscreen"),
|
|
| 75 | - null,
|
|
| 76 | - "Should not show full screen warning initially."
|
|
| 77 | - );
|
|
| 78 | - is(
|
|
| 79 | - plWarning.getAttribute("onscreen"),
|
|
| 80 | - null,
|
|
| 81 | - "Should not show pointer lock warning initially."
|
|
| 82 | - );
|
|
| 83 | - |
|
| 84 | - let fsWarningShownPromise = BrowserTestUtils.waitForAttribute(
|
|
| 85 | - "onscreen",
|
|
| 95 | + checkWarningState(
|
|
| 86 | 96 | fsWarning,
|
| 87 | - "true"
|
|
| 97 | + "hidden",
|
|
| 98 | + "Should not show full screen warning initially"
|
|
| 99 | + );
|
|
| 100 | + checkWarningState(
|
|
| 101 | + plWarning,
|
|
| 102 | + "hidden",
|
|
| 103 | + "Should not show pointer lock warning initially"
|
|
| 88 | 104 | );
|
| 89 | 105 | |
| 106 | + let fsWarningShownPromise = waitForWarningState(fsWarning, "onscreen");
|
|
| 90 | 107 | info("Entering full screen and pointer lock.");
|
| 91 | 108 | await SpecialPowers.spawn(browser, [], async () => {
|
| 92 | 109 | await content.document.body.requestFullscreen();
|
| ... | ... | @@ -94,15 +111,10 @@ add_task(async function test_fullscreen_pointerlock_conflict() { |
| 94 | 111 | });
|
| 95 | 112 | |
| 96 | 113 | await fsWarningShownPromise;
|
| 97 | - is(
|
|
| 98 | - fsWarning.getAttribute("onscreen"),
|
|
| 99 | - "true",
|
|
| 100 | - "Should show full screen warning."
|
|
| 101 | - );
|
|
| 102 | - is(
|
|
| 103 | - plWarning.getAttribute("onscreen"),
|
|
| 104 | - null,
|
|
| 105 | - "Should not show pointer lock warning."
|
|
| 114 | + checkWarningState(
|
|
| 115 | + plWarning,
|
|
| 116 | + "hidden",
|
|
| 117 | + "Should not show pointer lock warning"
|
|
| 106 | 118 | );
|
| 107 | 119 | |
| 108 | 120 | info("Exiting pointerlock");
|
| ... | ... | @@ -110,18 +122,19 @@ add_task(async function test_fullscreen_pointerlock_conflict() { |
| 110 | 122 | await content.document.exitPointerLock();
|
| 111 | 123 | });
|
| 112 | 124 | |
| 113 | - is(
|
|
| 114 | - fsWarning.getAttribute("onscreen"),
|
|
| 115 | - "true",
|
|
| 116 | - "Should still show full screen warning."
|
|
| 125 | + checkWarningState(
|
|
| 126 | + fsWarning,
|
|
| 127 | + "onscreen",
|
|
| 128 | + "Should still show full screen warning"
|
|
| 117 | 129 | );
|
| 118 | - is(
|
|
| 119 | - plWarning.getAttribute("onscreen"),
|
|
| 120 | - null,
|
|
| 121 | - "Should not show pointer lock warning."
|
|
| 130 | + checkWarningState(
|
|
| 131 | + plWarning,
|
|
| 132 | + "hidden",
|
|
| 133 | + "Should not show pointer lock warning"
|
|
| 122 | 134 | );
|
| 123 | 135 | |
| 124 | 136 | // Cleanup
|
| 137 | + info("Exiting fullscreen");
|
|
| 125 | 138 | await document.exitFullscreen();
|
| 126 | 139 | });
|
| 127 | 140 | }); |
| ... | ... | @@ -15,6 +15,25 @@ const FRAME_TEST_URL = |
| 15 | 15 | encodeURI(BODY_URL) +
|
| 16 | 16 | '"></iframe></body>';
|
| 17 | 17 | |
| 18 | +function checkWarningState(aWarningElement, aExpectedState, aMsg) {
|
|
| 19 | + ["hidden", "ontop", "onscreen"].forEach(state => {
|
|
| 20 | + is(
|
|
| 21 | + aWarningElement.hasAttribute(state),
|
|
| 22 | + state == aExpectedState,
|
|
| 23 | + `${aMsg} - check ${state} attribute.`
|
|
| 24 | + );
|
|
| 25 | + });
|
|
| 26 | +}
|
|
| 27 | + |
|
| 28 | +async function waitForWarningState(aWarningElement, aExpectedState) {
|
|
| 29 | + await BrowserTestUtils.waitForAttribute(aExpectedState, aWarningElement, "");
|
|
| 30 | + checkWarningState(
|
|
| 31 | + aWarningElement,
|
|
| 32 | + aExpectedState,
|
|
| 33 | + `Wait for ${aExpectedState} state`
|
|
| 34 | + );
|
|
| 35 | +}
|
|
| 36 | + |
|
| 18 | 37 | // Make sure the pointerlock warning is shown and exited with the escape key
|
| 19 | 38 | add_task(async function show_pointerlock_warning_escape() {
|
| 20 | 39 | let urls = [TEST_URL, FRAME_TEST_URL];
|
| ... | ... | @@ -24,11 +43,7 @@ add_task(async function show_pointerlock_warning_escape() { |
| 24 | 43 | let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
| 25 | 44 | |
| 26 | 45 | let warning = document.getElementById("pointerlock-warning");
|
| 27 | - let warningShownPromise = BrowserTestUtils.waitForAttribute(
|
|
| 28 | - "onscreen",
|
|
| 29 | - warning,
|
|
| 30 | - "true"
|
|
| 31 | - );
|
|
| 46 | + let warningShownPromise = waitForWarningState(warning, "onscreen");
|
|
| 32 | 47 | |
| 33 | 48 | let expectedWarningText;
|
| 34 | 49 | |
| ... | ... | @@ -49,11 +64,7 @@ add_task(async function show_pointerlock_warning_escape() { |
| 49 | 64 | |
| 50 | 65 | ok(true, "Pointerlock warning shown");
|
| 51 | 66 | |
| 52 | - let warningHiddenPromise = BrowserTestUtils.waitForAttribute(
|
|
| 53 | - "hidden",
|
|
| 54 | - warning,
|
|
| 55 | - ""
|
|
| 56 | - );
|
|
| 67 | + let warningHiddenPromise = waitForWarningState(warning, "hidden");
|
|
| 57 | 68 | |
| 58 | 69 | await BrowserTestUtils.waitForCondition(
|
| 59 | 70 | () => warning.innerText == expectedWarningText,
|
| ... | ... | @@ -1331,6 +1331,11 @@ void GCRuntime::assertNoMarkingWork() const { |
| 1331 | 1331 | }
|
| 1332 | 1332 | #endif
|
| 1333 | 1333 | |
| 1334 | +static size_t GetGCParallelThreadCount() {
|
|
| 1335 | + AutoLockHelperThreadState lock;
|
|
| 1336 | + return HelperThreadState().getGCParallelThreadCount(lock);
|
|
| 1337 | +}
|
|
| 1338 | + |
|
| 1334 | 1339 | bool GCRuntime::updateMarkersVector() {
|
| 1335 | 1340 | MOZ_ASSERT(helperThreadCount >= 1,
|
| 1336 | 1341 | "There must always be at least one mark task");
|
| ... | ... | @@ -1339,8 +1344,8 @@ bool GCRuntime::updateMarkersVector() { |
| 1339 | 1344 | |
| 1340 | 1345 | // Limit worker count to number of GC parallel tasks that can run
|
| 1341 | 1346 | // concurrently, otherwise one thread can deadlock waiting on another.
|
| 1342 | - size_t targetCount = std::min(markingWorkerCount(),
|
|
| 1343 | - HelperThreadState().getGCParallelThreadCount());
|
|
| 1347 | + size_t targetCount =
|
|
| 1348 | + std::min(markingWorkerCount(), GetGCParallelThreadCount());
|
|
| 1344 | 1349 | |
| 1345 | 1350 | if (markers.length() > targetCount) {
|
| 1346 | 1351 | return markers.resize(targetCount);
|
| ... | ... | @@ -103,6 +103,10 @@ bool ParallelMarker::markOneColor(MarkColor color, SliceBudget& sliceBudget) { |
| 103 | 103 | {
|
| 104 | 104 | AutoLockHelperThreadState lock;
|
| 105 | 105 | |
| 106 | + // There should always be enough parallel tasks to run our marking work.
|
|
| 107 | + MOZ_RELEASE_ASSERT(HelperThreadState().getGCParallelThreadCount(lock) >=
|
|
| 108 | + workerCount());
|
|
| 109 | + |
|
| 106 | 110 | for (size_t i = 0; i < workerCount(); i++) {
|
| 107 | 111 | gc->startTask(*tasks[i], lock);
|
| 108 | 112 | }
|
| ... | ... | @@ -333,9 +333,11 @@ class GlobalHelperThreadState { |
| 333 | 333 | |
| 334 | 334 | GCParallelTaskList& gcParallelWorklist() { return gcParallelWorklist_; }
|
| 335 | 335 | |
| 336 | - size_t getGCParallelThreadCount() const { return gcParallelThreadCount; }
|
|
| 336 | + size_t getGCParallelThreadCount(const AutoLockHelperThreadState& lock) const {
|
|
| 337 | + return gcParallelThreadCount;
|
|
| 338 | + }
|
|
| 337 | 339 | void setGCParallelThreadCount(size_t count,
|
| 338 | - const AutoLockHelperThreadState&) {
|
|
| 340 | + const AutoLockHelperThreadState& lock) {
|
|
| 339 | 341 | MOZ_ASSERT(count >= 1);
|
| 340 | 342 | MOZ_ASSERT(count <= threadCount);
|
| 341 | 343 | gcParallelThreadCount = count;
|