Backed out changeset fcd3e501bdac (bug 1828477) for causing gv-junit failures. CLOSED TREE

This commit is contained in:
Cristina Horotan 2023-04-19 17:28:42 +03:00
parent 4b96f8c849
commit dbc5b34a3f
11 changed files with 116 additions and 202 deletions

View File

@ -136,6 +136,21 @@
noautofocus="true"
hidden="true" />
<html:template id="dateTimePickerTemplate">
<!-- for date/time picker. consumeoutsideclicks is set to never, so that
clicks on the anchored input box are never consumed. -->
<panel id="DateTimePickerPanel"
type="arrow"
orient="vertical"
ignorekeys="true"
norolluponanchor="true"
noautofocus="true"
consumeoutsideclicks="never"
level="parent"
tabspecific="true">
</panel>
</html:template>
<html:template id="printPreviewStackTemplate">
<stack class="previewStack" rendering="true" flex="1" previewtype="primary">
<vbox class="previewRendering" flex="1">

View File

@ -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) {

View File

@ -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

View File

@ -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-<tabbrowser> windows
debug("no tabbrowser, exiting now.");
return;
}
{
let browser = topBC.embedderElement;
if (
browser &&
browser.ownerGlobal.gBrowser &&
browser.ownerGlobal.gBrowser.selectedBrowser != browser
Services.focus.activeWindow != window ||
tabbrowser.selectedBrowser != aBrowser
) {
debug("In background tab");
// 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();
if (this.oldFocus) {
// Restore focus to where it was before the picker opened.
this._oldFocus?.focus();
this._oldFocus = null;
this.oldFocus.focus();
this.oldFocus = null;
}
this.removePickerListeners();
this._picker = null;
}

View File

@ -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

View File

@ -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();
});

View File

@ -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;
}
}

View File

@ -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"));
},

View File

@ -617,28 +617,15 @@ 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;
}
// 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();
}
}
}
isTimeField(field) {
return (

View File

@ -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"));
},

View File

@ -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 = {