From dbc5b34a3f8c3881248f67e10d65ee7c8e2b19a3 Mon Sep 17 00:00:00 2001 From: Cristina Horotan Date: Wed, 19 Apr 2023 17:28:42 +0300 Subject: [PATCH] Backed out changeset fcd3e501bdac (bug 1828477) for causing gv-junit failures. CLOSED TREE --- browser/base/content/main-popupset.inc.xhtml | 15 ++++ browser/base/content/tabbrowser.js | 12 +++ .../BrowserTestUtils/BrowserTestUtils.sys.mjs | 81 ------------------- toolkit/actors/DateTimePickerParent.sys.mjs | 69 +++++++--------- .../tests/browser/datetime/browser.ini | 1 - .../datetime/browser_datetime_toplevel.js | 27 ------- .../content/tests/browser/datetime/head.js | 41 ++++++++-- toolkit/content/widgets/datepicker.js | 2 - toolkit/content/widgets/datetimebox.js | 27 ++----- toolkit/content/widgets/timepicker.js | 2 - toolkit/modules/ActorManagerParent.sys.mjs | 41 +++++----- 11 files changed, 116 insertions(+), 202 deletions(-) delete mode 100644 toolkit/content/tests/browser/datetime/browser_datetime_toplevel.js diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml index b44fd760baaa..e53f71e83ec5 100644 --- a/browser/base/content/main-popupset.inc.xhtml +++ b/browser/base/content/main-popupset.inc.xhtml @@ -136,6 +136,21 @@ noautofocus="true" hidden="true" /> + + + + + + diff --git a/browser/base/content/tabbrowser.js b/browser/base/content/tabbrowser.js index 9a2a32b77ffb..fdee5800b310 100644 --- a/browser/base/content/tabbrowser.js +++ b/browser/base/content/tabbrowser.js @@ -172,6 +172,8 @@ arrowKeysShouldWrap: AppConstants == "macosx", + _dateTimePicker: null, + _previewMode: false, _lastFindValue: "", @@ -804,6 +806,16 @@ } }, + _getAndMaybeCreateDateTimePickerPanel() { + if (!this._dateTimePicker) { + let wrapper = document.getElementById("dateTimePickerTemplate"); + wrapper.replaceWith(wrapper.content); + this._dateTimePicker = document.getElementById("DateTimePickerPanel"); + } + + return this._dateTimePicker; + }, + syncThrobberAnimations(aTab) { aTab.ownerGlobal.promiseDocumentFlushed(() => { if (!aTab.container) { diff --git a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.sys.mjs b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.sys.mjs index 3eca23f063d3..6c5a8fa0709f 100644 --- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.sys.mjs +++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.sys.mjs @@ -1412,87 +1412,6 @@ export var BrowserTestUtils = { return menulist.menupopup; }, - /** - * Waits for the datetime picker popup to be shown. - * - * @param {Window} win - * A window to expect the popup in. - * - * @return {Promise} - * Resolves when the popup has been fully opened. The resolution value - * is the select popup. - */ - async waitForDateTimePickerPanelShown(win) { - let getPanel = () => win.document.getElementById("DateTimePickerPanel"); - let panel = getPanel(); - let ensureReady = async () => { - let frame = panel.querySelector("#dateTimePopupFrame"); - let isValidUrl = () => { - return ( - frame.browsingContext?.currentURI?.spec == - "chrome://global/content/datepicker.xhtml" || - frame.browsingContext?.currentURI?.spec == - "chrome://global/content/timepicker.xhtml" - ); - }; - - // Ensure it's loaded. - if (!isValidUrl() || frame.contentDocument.readyState != "complete") { - await new Promise(resolve => { - frame.addEventListener( - "load", - function listener() { - if (isValidUrl()) { - frame.removeEventListener("load", listener, { capture: true }); - resolve(); - } - }, - { capture: true } - ); - }); - } - - // Ensure it's ready. - if (!frame.contentWindow.PICKER_READY) { - await new Promise(resolve => { - frame.contentDocument.addEventListener("PickerReady", resolve, { - once: true, - }); - }); - } - // And that l10n mutations are flushed. - // FIXME(bug 1828721): We should ideally localize everything before - // showing the panel. - if (frame.contentDocument.hasPendingL10nMutations) { - await new Promise(resolve => { - frame.contentDocument.addEventListener( - "L10nMutationsFinished", - resolve, - { - once: true, - } - ); - }); - } - }; - - if (!panel) { - await this.waitForMutationCondition( - win.document, - { childList: true, subtree: true }, - getPanel - ); - panel = getPanel(); - if (panel.state == "open") { - await ensureReady(); - return panel; - } - } - await this.waitForEvent(panel, "popupshown"); - await ensureReady(); - return panel; - }, - /** * Adds a content event listener on the given browser * element. Similar to waitForContentEvent, but the listener will diff --git a/toolkit/actors/DateTimePickerParent.sys.mjs b/toolkit/actors/DateTimePickerParent.sys.mjs index ba78a39ffbdb..f62d10590b63 100644 --- a/toolkit/actors/DateTimePickerParent.sys.mjs +++ b/toolkit/actors/DateTimePickerParent.sys.mjs @@ -25,13 +25,16 @@ export class DateTimePickerParent extends JSWindowActorParent { debug("receiveMessage: " + aMessage.name); switch (aMessage.name) { case "FormDateTime:OpenPicker": { - this.showPicker(aMessage.data); + let topBrowsingContext = this.manager.browsingContext.top; + let browser = topBrowsingContext.embedderElement; + this.showPicker(browser, aMessage.data); break; } case "FormDateTime:ClosePicker": { if (!this._picker) { return; } + this._picker.closePicker(); this.close(); break; } @@ -60,6 +63,7 @@ export class DateTimePickerParent extends JSWindowActorParent { } case "popuphidden": { this.sendAsyncMessage("FormDateTime:PickerClosed", {}); + this._picker.closePicker(); this.close(); break; } @@ -69,62 +73,45 @@ export class DateTimePickerParent extends JSWindowActorParent { } // Get picker from browser and show it anchored to the input box. - showPicker(aData) { + showPicker(aBrowser, aData) { let rect = aData.rect; let type = aData.type; let detail = aData.detail; debug("Opening picker with details: " + JSON.stringify(detail)); - let topBC = this.browsingContext.top; - let window = topBC.topChromeWindow; - if (Services.focus.activeWindow != window) { - debug("Not in the active window"); + + let window = aBrowser.ownerGlobal; + let tabbrowser = window.gBrowser; + if (!tabbrowser) { + // TODO(bug 1828477): Support non- windows + debug("no tabbrowser, exiting now."); return; } - { - let browser = topBC.embedderElement; - if ( - browser && - browser.ownerGlobal.gBrowser && - browser.ownerGlobal.gBrowser.selectedBrowser != browser - ) { - debug("In background tab"); - return; - } + if ( + Services.focus.activeWindow != window || + tabbrowser.selectedBrowser != aBrowser + ) { + // We were sent a message from a window or tab that went into the + // background, so we'll ignore it for now. + return; } - let doc = window.document; - let panel = doc.getElementById("DateTimePickerPanel"); - if (!panel) { - panel = doc.createXULElement("panel"); - panel.id = "DateTimePickerPanel"; - panel.setAttribute("type", "arrow"); - panel.setAttribute("orient", "vertical"); - panel.setAttribute("ignorekeys", "true"); - panel.setAttribute("noautofocus", "true"); - // This ensures that clicks on the anchored input box are never consumed. - panel.setAttribute("consumeoutsideclicks", "never"); - panel.setAttribute("level", "parent"); - panel.setAttribute("tabspecific", "true"); - let container = - doc.getElementById("mainPopupSet") || - doc.querySelector("popupset") || - doc.documentElement.appendChild(doc.createXULElement("popupset")); - container.appendChild(panel); - } - this._oldFocus = doc.activeElement; + let panel = tabbrowser._getAndMaybeCreateDateTimePickerPanel(); + this.oldFocus = window.document.activeElement; this._picker = new lazy.DateTimePickerPanel(panel); this._picker.openPicker(type, rect, detail); + this.addPickerListeners(); } - // Close the picker and do some cleanup. + // Picker is closed, do some cleanup. close() { - this._picker.closePicker(); - // Restore focus to where it was before the picker opened. - this._oldFocus?.focus(); - this._oldFocus = null; + if (this.oldFocus) { + // Restore focus to where it was before the picker opened. + this.oldFocus.focus(); + this.oldFocus = null; + } this.removePickerListeners(); this._picker = null; } diff --git a/toolkit/content/tests/browser/datetime/browser.ini b/toolkit/content/tests/browser/datetime/browser.ini index e4991df5f05e..e12fea89456d 100644 --- a/toolkit/content/tests/browser/datetime/browser.ini +++ b/toolkit/content/tests/browser/datetime/browser.ini @@ -61,7 +61,6 @@ skip-if = os == "linux" && fission && socketprocess_networking && !debug # high frequency intermittent, Bug 1673140 [browser_datetime_showPicker.js] # do not skip -[browser_datetime_toplevel.js] [browser_spinner.js] skip-if = tsan # Frequently times out on TSan diff --git a/toolkit/content/tests/browser/datetime/browser_datetime_toplevel.js b/toolkit/content/tests/browser/datetime/browser_datetime_toplevel.js deleted file mode 100644 index 45cca6c6c260..000000000000 --- a/toolkit/content/tests/browser/datetime/browser_datetime_toplevel.js +++ /dev/null @@ -1,27 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * https://creativecommons.org/publicdomain/zero/1.0/ */ - -add_task(async function() { - let input = document.createElement("input"); - input.type = "date"; - registerCleanupFunction(() => input.remove()); - document.body.appendChild(input); - - let shown = BrowserTestUtils.waitForDateTimePickerPanelShown(window); - - const shadowRoot = SpecialPowers.wrap(input).openOrClosedShadowRoot; - - EventUtils.synthesizeMouseAtCenter( - shadowRoot.getElementById("calendar-button"), - {} - ); - - let popup = await shown; - ok(!!popup, "Should've shown the popup"); - - let hidden = BrowserTestUtils.waitForPopupEvent(popup, "hidden"); - popup.hidePopup(); - - await hidden; - popup.remove(); -}); diff --git a/toolkit/content/tests/browser/datetime/head.js b/toolkit/content/tests/browser/datetime/head.js index ccdf77adf713..3ab8ac7f4bb1 100644 --- a/toolkit/content/tests/browser/datetime/head.js +++ b/toolkit/content/tests/browser/datetime/head.js @@ -9,7 +9,8 @@ */ class DateTimeTestHelper { constructor() { - this.panel = null; + this.panel = gBrowser._getAndMaybeCreateDateTimePickerPanel(); + this.panel.setAttribute("animate", false); this.tab = null; this.frame = null; } @@ -39,8 +40,6 @@ class DateTimeTestHelper { await SpecialPowers.contentTransformsReceived(content); }); - let shown = this.waitForPickerReady(); - if (openMethod === "click") { await SpecialPowers.spawn(bc, [], () => { const input = content.document.querySelector("input"); @@ -53,8 +52,8 @@ class DateTimeTestHelper { content.document.querySelector("input").showPicker(); }); } - this.panel = await shown; this.frame = this.panel.querySelector("#dateTimePopupFrame"); + await this.waitForPickerReady(); } promisePickerClosed() { @@ -80,8 +79,35 @@ class DateTimeTestHelper { ); } - waitForPickerReady() { - return BrowserTestUtils.waitForDateTimePickerPanelShown(window); + async waitForPickerReady() { + let readyPromise; + let loadPromise = new Promise(resolve => { + let listener = () => { + if ( + this.frame.browsingContext.currentURI.spec != + "chrome://global/content/datepicker.xhtml" && + this.frame.browsingContext.currentURI.spec != + "chrome://global/content/timepicker.xhtml" + ) { + return; + } + + this.frame.removeEventListener("load", listener, { capture: true }); + // Add the PickerReady event listener directly inside the load event + // listener to avoid missing the event. + readyPromise = BrowserTestUtils.waitForEvent( + this.frame.contentDocument, + "PickerReady" + ); + resolve(); + }; + + this.frame.addEventListener("load", listener, { capture: true }); + }); + + await loadPromise; + // Wait for picker elements to be ready + await readyPromise; } /** @@ -130,8 +156,9 @@ class DateTimeTestHelper { * Clean up after tests. Remove the frame to prevent leak. */ cleanup() { - this.frame?.remove(); + this.frame.remove(); this.frame = null; + this.panel.removeAttribute("animate"); this.panel = null; } } diff --git a/toolkit/content/widgets/datepicker.js b/toolkit/content/widgets/datepicker.js index 7692d9292f54..ba90155ae214 100644 --- a/toolkit/content/widgets/datepicker.js +++ b/toolkit/content/widgets/datepicker.js @@ -41,8 +41,6 @@ function DatePicker(context) { this._createComponents(); this._update(); this.components.calendar.focusDay(); - // TODO(bug 1828721): This is a bit sad. - window.PICKER_READY = true; document.dispatchEvent(new CustomEvent("PickerReady")); }, diff --git a/toolkit/content/widgets/datetimebox.js b/toolkit/content/widgets/datetimebox.js index 2915e83b9060..fb5db9577e2b 100644 --- a/toolkit/content/widgets/datetimebox.js +++ b/toolkit/content/widgets/datetimebox.js @@ -617,26 +617,13 @@ this.DateTimeBoxWidget = class { let target = aEvent.originalTarget; target.setAttribute("typeBuffer", ""); this.setInputValueFromFields(); - // No need to set and unset the focus state (or closing the picker) if the - // focus is staying within our input. - if (aEvent.relatedTarget == this.mInputElement) { - return; - } - - // If we're in chrome and the focus moves to a separate document - // (relatedTarget is null) we also don't want to close it, since it - // could've moved to the datetime popup itself. - if ( - !aEvent.relatedTarget && - this.mInputElement.nodePrincipal.isSystemPrincipal && - this.window == this.window.top - ) { - return; - } - - this.mInputElement.setFocusState(false); - if (this.mIsPickerOpen) { - this.closeDateTimePicker(); + // No need to set and unset the focus state if the focus is staying within + // our input. Same about closing the picker. + if (aEvent.relatedTarget != this.mInputElement) { + this.mInputElement.setFocusState(false); + if (this.mIsPickerOpen) { + this.closeDateTimePicker(); + } } } diff --git a/toolkit/content/widgets/timepicker.js b/toolkit/content/widgets/timepicker.js index 83c4840a7090..ad6760e06fca 100644 --- a/toolkit/content/widgets/timepicker.js +++ b/toolkit/content/widgets/timepicker.js @@ -35,8 +35,6 @@ function TimePicker(context) { this._setDefaultState(); this._createComponents(); this._setComponentStates(); - // TODO(bug 1828721): This is a bit sad. - window.PICKER_READY = true; document.dispatchEvent(new CustomEvent("PickerReady")); }, diff --git a/toolkit/modules/ActorManagerParent.sys.mjs b/toolkit/modules/ActorManagerParent.sys.mjs index 87d35dc446c3..27ec0880c4cc 100644 --- a/toolkit/modules/ActorManagerParent.sys.mjs +++ b/toolkit/modules/ActorManagerParent.sys.mjs @@ -236,6 +236,23 @@ let JSWINDOWACTORS = { enablePreference: "cookiebanners.bannerClicking.enabled", }, + DateTimePicker: { + parent: { + esModuleURI: "resource://gre/actors/DateTimePickerParent.sys.mjs", + }, + + child: { + esModuleURI: "resource://gre/actors/DateTimePickerChild.sys.mjs", + events: { + MozOpenDateTimePicker: {}, + MozUpdateDateTimePicker: {}, + MozCloseDateTimePicker: {}, + }, + }, + + allFrames: true, + }, + ExtFind: { child: { esModuleURI: "resource://gre/actors/ExtFindChild.sys.mjs", @@ -507,7 +524,6 @@ let JSWINDOWACTORS = { }, }, - includeChrome: true, allFrames: true, }, @@ -566,7 +582,9 @@ if (AppConstants.platform != "android") { allFrames: true, }; - // Note that GeckoView has another implementation in mobile/android/actors. + /** + * Note that GeckoView has another implementation in mobile/android/actors. + */ JSWINDOWACTORS.Select = { parent: { esModuleURI: "resource://gre/actors/SelectParent.sys.mjs", @@ -584,25 +602,6 @@ if (AppConstants.platform != "android") { includeChrome: true, allFrames: true, }; - - // Note that GeckoView handles MozOpenDateTimePicker in GeckoViewPrompt. - JSWINDOWACTORS.DateTimePicker = { - parent: { - esModuleURI: "resource://gre/actors/DateTimePickerParent.sys.mjs", - }, - - child: { - esModuleURI: "resource://gre/actors/DateTimePickerChild.sys.mjs", - events: { - MozOpenDateTimePicker: {}, - MozUpdateDateTimePicker: {}, - MozCloseDateTimePicker: {}, - }, - }, - - includeChrome: true, - allFrames: true, - }; } export var ActorManagerParent = {