зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland
This commit is contained in:
Коммит
6aa98d7df0
|
@ -46,12 +46,7 @@ jobs:
|
|||
run-on-projects:
|
||||
- mozilla-central
|
||||
- date
|
||||
when:
|
||||
by-project:
|
||||
# Match buildbot starts for now
|
||||
date: [{hour: 15, minute: 0}]
|
||||
mozilla-central: [{hour: 10, minute: 0}]
|
||||
# No default
|
||||
when: [] # never (hook only)
|
||||
|
||||
- name: nightly-android
|
||||
job:
|
||||
|
|
|
@ -911,7 +911,6 @@ var RefreshBlocker = {
|
|||
this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
|
||||
.createInstance(Ci.nsIWebProgress);
|
||||
this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
this._filter.target = tabEventTarget;
|
||||
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
|
|
|
@ -14,8 +14,6 @@ skip-if = !debug
|
|||
[browser_tabopen_squeeze_reflows.js]
|
||||
[browser_tabswitch_reflows.js]
|
||||
[browser_toolbariconcolor_restyles.js]
|
||||
[browser_urlbar_search_reflows.js]
|
||||
skip-if = os == 'mac' && !debug # Disabled due to frequent failures. Bug 1384582
|
||||
[browser_windowclose_reflows.js]
|
||||
[browser_windowopen_reflows.js]
|
||||
skip-if = os == 'linux' # Disabled due to frequent failures. Bug 1380465.
|
||||
|
|
|
@ -10,15 +10,12 @@
|
|||
* for tips on how to do that.
|
||||
*/
|
||||
const EXPECTED_APPMENU_OPEN_REFLOWS = [
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"show/</<@chrome://browser/content/customizableui/panelUI.js",
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"get_alignmentPosition@chrome://global/content/bindings/popup.xml",
|
||||
"adjustArrowPosition@chrome://global/content/bindings/popup.xml",
|
||||
"onxblpopupshowing@chrome://global/content/bindings/popup.xml",
|
||||
|
@ -26,33 +23,55 @@ const EXPECTED_APPMENU_OPEN_REFLOWS = [
|
|||
"show/</<@chrome://browser/content/customizableui/panelUI.js",
|
||||
],
|
||||
|
||||
times: 2, // This number should only ever go down - never up.
|
||||
},
|
||||
[
|
||||
"get_alignmentPosition@chrome://global/content/bindings/popup.xml",
|
||||
"adjustArrowPosition@chrome://global/content/bindings/popup.xml",
|
||||
"onxblpopupshowing@chrome://global/content/bindings/popup.xml",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"show/</<@chrome://browser/content/customizableui/panelUI.js",
|
||||
],
|
||||
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"get_alignmentPosition@chrome://global/content/bindings/popup.xml",
|
||||
"adjustArrowPosition@chrome://global/content/bindings/popup.xml",
|
||||
"onxblpopuppositioned@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"get_alignmentPosition@chrome://global/content/bindings/popup.xml",
|
||||
"handleEvent@resource:///modules/PanelMultiView.jsm",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"handleEvent@resource:///modules/PanelMultiView.jsm",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
|
||||
times: 6, // This number should only ever go down - never up.
|
||||
},
|
||||
[
|
||||
"handleEvent@resource:///modules/PanelMultiView.jsm",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"handleEvent@resource:///modules/PanelMultiView.jsm",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"handleEvent@resource:///modules/PanelMultiView.jsm",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"handleEvent@resource:///modules/PanelMultiView.jsm",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"handleEvent@resource:///modules/PanelMultiView.jsm",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
],
|
||||
];
|
||||
|
||||
const EXPECTED_APPMENU_SUBVIEW_REFLOWS = [
|
||||
|
@ -65,14 +84,15 @@ const EXPECTED_APPMENU_SUBVIEW_REFLOWS = [
|
|||
* If we add more views where this is necessary, we may need to duplicate
|
||||
* these expected reflows further.
|
||||
*/
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"descriptionHeightWorkaround@resource:///modules/PanelMultiView.jsm",
|
||||
"onTransitionEnd@resource:///modules/PanelMultiView.jsm",
|
||||
],
|
||||
|
||||
times: 2, // This number should only ever go down - never up.
|
||||
},
|
||||
[
|
||||
"descriptionHeightWorkaround@resource:///modules/PanelMultiView.jsm",
|
||||
"onTransitionEnd@resource:///modules/PanelMultiView.jsm",
|
||||
],
|
||||
|
||||
/**
|
||||
* Please don't add anything new!
|
||||
|
|
|
@ -15,11 +15,9 @@
|
|||
const EXPECTED_REFLOWS = [
|
||||
// selection change notification may cause querying the focused editor content
|
||||
// by IME and that will cause reflow.
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"select@chrome://global/content/bindings/textbox.xml",
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,13 +10,11 @@
|
|||
* for tips on how to do that.
|
||||
*/
|
||||
const EXPECTED_REFLOWS = [
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"select@chrome://global/content/bindings/textbox.xml",
|
||||
"focusAndSelectUrlBar@chrome://browser/content/browser.js",
|
||||
"_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,264 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
|
||||
"resource://testing-common/PlacesTestUtils.jsm");
|
||||
|
||||
/**
|
||||
* WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
|
||||
* is a whitelist that should slowly go away as we improve the performance of
|
||||
* the front-end. Instead of adding more reflows to the whitelist, you should
|
||||
* be modifying your code to avoid the reflow.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
|
||||
* for tips on how to do that.
|
||||
*/
|
||||
|
||||
/* These reflows happen only the first time the awesomebar panel opens. */
|
||||
const EXPECTED_REFLOWS_FIRST_OPEN = [
|
||||
// Bug 1357054
|
||||
{
|
||||
stack: [
|
||||
"_rebuild@chrome://browser/content/search/search.xml",
|
||||
"set_popup@chrome://browser/content/search/search.xml",
|
||||
"enableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
|
||||
"_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
|
||||
"urlbar_XBL_Constructor/<@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 1, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustSiteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_siteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustSiteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
"invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 9, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"onxblpopupshown@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 5, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_siteIconStart@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 6, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate/this._adjustHeightTimeout<@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
"invalidate@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 390, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
// Bug 1359989
|
||||
{
|
||||
stack: [
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/* These reflows happen everytime the awesomebar panel opens. */
|
||||
const EXPECTED_REFLOWS_SECOND_OPEN = [
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"onxblpopupshown@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"adjustHeight@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate/this._adjustHeightTimeout<@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
|
||||
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
|
||||
"invalidate@chrome://global/content/bindings/autocomplete.xml"
|
||||
],
|
||||
times: 444, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
// Bug 1384256
|
||||
{
|
||||
stack: [
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
times: 3, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
// Bug 1359989
|
||||
{
|
||||
stack: [
|
||||
"openPopup@chrome://global/content/bindings/popup.xml",
|
||||
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
|
||||
"openPopup@chrome://global/content/bindings/autocomplete.xml",
|
||||
"set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns a Promise that resolves once the AwesomeBar popup for a particular
|
||||
* window has appeared after having done a search for its input text.
|
||||
*
|
||||
* @param win (browser window)
|
||||
* The window to do the search in.
|
||||
* @returns Promise
|
||||
*/
|
||||
async function promiseAutocompleteResultPopup(win) {
|
||||
let URLBar = win.gURLBar;
|
||||
URLBar.controller.startSearch(URLBar.value);
|
||||
await BrowserTestUtils.waitForEvent(URLBar.popup, "popupshown");
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return URLBar.controller.searchStatus >=
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH;
|
||||
});
|
||||
let matchCount = URLBar.popup._matchCount;
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return URLBar.popup.richlistbox.childNodes.length == matchCount;
|
||||
});
|
||||
|
||||
URLBar.controller.stopSearch();
|
||||
// There are several setTimeout(fn, 0); calls inside autocomplete.xml
|
||||
// that we need to wait for. Since those have higher priority than
|
||||
// idle callbacks, we can be sure they will have run once this
|
||||
// idle callback is called. The timeout seems to be required in
|
||||
// automation - presumably because the machines can be pretty busy
|
||||
// especially if it's GC'ing from previous tests.
|
||||
await new Promise(resolve => win.requestIdleCallback(resolve, { timeout: 1000 }));
|
||||
|
||||
let hiddenPromise = BrowserTestUtils.waitForEvent(URLBar.popup, "popuphidden");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
|
||||
await hiddenPromise;
|
||||
}
|
||||
|
||||
const SEARCH_TERM = "urlbar-reflows";
|
||||
|
||||
add_task(async function setup() {
|
||||
const NUM_VISITS = 10;
|
||||
let visits = [];
|
||||
|
||||
for (let i = 0; i < NUM_VISITS; ++i) {
|
||||
visits.push({
|
||||
uri: `http://example.com/urlbar-reflows-${i}`,
|
||||
title: `Reflow test for URL bar entry #${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
await PlacesTestUtils.addVisits(visits);
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await PlacesTestUtils.clearHistory();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that there are no unexpected
|
||||
* uninterruptible reflows when typing into the URL bar
|
||||
* with the default values in Places.
|
||||
*/
|
||||
add_task(async function() {
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await ensureNoPreloadedBrowser(win);
|
||||
|
||||
let URLBar = win.gURLBar;
|
||||
let popup = URLBar.popup;
|
||||
|
||||
URLBar.focus();
|
||||
URLBar.value = SEARCH_TERM;
|
||||
let testFn = async function(dirtyFrameFn) {
|
||||
let oldInvalidate = popup.invalidate.bind(popup);
|
||||
let oldResultsAdded = popup.onResultsAdded.bind(popup);
|
||||
|
||||
// We need to invalidate the frame tree outside of the normal
|
||||
// mechanism since invalidations and result additions to the
|
||||
// URL bar occur without firing JS events (which is how we
|
||||
// normally know to dirty the frame tree).
|
||||
popup.invalidate = (reason) => {
|
||||
dirtyFrameFn();
|
||||
oldInvalidate(reason);
|
||||
};
|
||||
|
||||
popup.onResultsAdded = () => {
|
||||
dirtyFrameFn();
|
||||
oldResultsAdded();
|
||||
};
|
||||
|
||||
await promiseAutocompleteResultPopup(win);
|
||||
};
|
||||
|
||||
await withReflowObserver(testFn, EXPECTED_REFLOWS_FIRST_OPEN, win);
|
||||
|
||||
await withReflowObserver(testFn, EXPECTED_REFLOWS_SECOND_OPEN, win);
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
|
@ -13,94 +13,114 @@
|
|||
* for tips on how to do that.
|
||||
*/
|
||||
const EXPECTED_REFLOWS = [
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"select@chrome://global/content/bindings/textbox.xml",
|
||||
"focusAndSelectUrlBar@chrome://browser/content/browser.js",
|
||||
"_delayedStartup@chrome://browser/content/browser.js",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
if (Services.appinfo.OS == "Linux") {
|
||||
if (gMultiProcessBrowser) {
|
||||
EXPECTED_REFLOWS.push({
|
||||
stack: [
|
||||
EXPECTED_REFLOWS.push(
|
||||
[
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
"EventListener.handleEvent*tabbrowser-tabs_XBL_Constructor@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
});
|
||||
);
|
||||
} else {
|
||||
EXPECTED_REFLOWS.push({
|
||||
stack: [
|
||||
EXPECTED_REFLOWS.push(
|
||||
[
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
"inferFromText@chrome://browser/content/browser.js",
|
||||
"handleEvent@chrome://browser/content/browser.js",
|
||||
],
|
||||
});
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
EXPECTED_REFLOWS.push({
|
||||
stack: [
|
||||
EXPECTED_REFLOWS.push(
|
||||
[
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
"inferFromText@chrome://browser/content/browser.js",
|
||||
"handleEvent@chrome://browser/content/browser.js",
|
||||
],
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
if (Services.appinfo.OS == "WINNT") {
|
||||
EXPECTED_REFLOWS.push(
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"verticalMargins@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
times: 2, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"verticalMargins@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
"inferFromText@chrome://browser/content/browser.js",
|
||||
"handleEvent@chrome://browser/content/browser.js",
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
"EventListener.handleEvent*tabbrowser-tabs_XBL_Constructor@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") {
|
||||
EXPECTED_REFLOWS.push(
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"rect@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
times: 4, // This number should only ever go down - never up.
|
||||
},
|
||||
|
||||
{
|
||||
stack: [
|
||||
[
|
||||
"rect@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"rect@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"rect@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"verticalMargins@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
|
||||
[
|
||||
"verticalMargins@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"_update@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"updateAppearance@chrome://browser/content/browser-tabsintitlebar.js",
|
||||
"handleEvent@chrome://browser/content/tabbrowser.xml",
|
||||
],
|
||||
times: 2, // This number should only ever go down - never up.
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,42 +2,59 @@
|
|||
* Async utility function for ensuring that no unexpected uninterruptible
|
||||
* reflows occur during some period of time in a window.
|
||||
*
|
||||
* The helper works by running a JS function before each event is
|
||||
* dispatched that attempts to dirty the layout tree - the idea being
|
||||
* that this puts us in the "worst case scenario" so that any JS
|
||||
* that attempts to query for layout or style information will cause
|
||||
* a reflow to fire. We also dirty the layout tree after each reflow
|
||||
* occurs, for good measure.
|
||||
*
|
||||
* This sounds good in theory, but it's trickier in practice due to
|
||||
* various optimizations in our Layout engine. The default function
|
||||
* for dirtying the layout tree adds a margin to the first element
|
||||
* child it finds in the window to a maximum of 3px, and then goes
|
||||
* back to 0px again and loops.
|
||||
*
|
||||
* This is not sufficient for reflows that we expect to happen within
|
||||
* scrollable frames, as Gecko is able to side-step reflowing the
|
||||
* contents of a scrollable frame if outer frames are dirtied. Because
|
||||
* of this, it's currently possible to override the default node to
|
||||
* dirty with one more appropriate for the test.
|
||||
*
|
||||
* It is also theoretically possible for enough events to fire between
|
||||
* reflows such that the before and after state of the layout tree is
|
||||
* exactly the same, meaning that no reflow is required, which opens
|
||||
* us up to missing expected reflows. This seems to be possible in
|
||||
* theory, but hasn't yet shown up in practice - it's just something
|
||||
* to be aware of.
|
||||
*
|
||||
* Bug 1363361 has been filed for a more reliable way of dirtying layout.
|
||||
*
|
||||
* @param testFn (async function)
|
||||
* The async function that will exercise the browser activity that is
|
||||
* being tested for reflows.
|
||||
*
|
||||
* The testFn will be passed a single argument, which is a frame dirtying
|
||||
* function that can be called if the test needs to trigger frame
|
||||
* dirtying outside of the normal mechanism.
|
||||
* @param expectedReflows (Array, optional)
|
||||
* An Array of Objects representing reflows.
|
||||
* @param expectedStacks (Array, optional)
|
||||
* An Array of Arrays representing stacks.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* // This reflow is caused by lorem ipsum
|
||||
* stack: [
|
||||
* [
|
||||
* "select@chrome://global/content/bindings/textbox.xml",
|
||||
* "focusAndSelectUrlBar@chrome://browser/content/browser.js",
|
||||
* "openLinkIn@chrome://browser/content/utilityOverlay.js",
|
||||
* "openUILinkIn@chrome://browser/content/utilityOverlay.js",
|
||||
* "BrowserOpenTab@chrome://browser/content/browser.js",
|
||||
* ],
|
||||
* // We expect this particular reflow to happen 2 times
|
||||
* times: 2,
|
||||
* },
|
||||
*
|
||||
* {
|
||||
* // This reflow is caused by lorem ipsum. We expect this reflow
|
||||
* // to only happen once, so we can omit the "times" property.
|
||||
* stack: [
|
||||
* // This reflow is caused by lorem ipsum
|
||||
* [
|
||||
* "get_scrollPosition@chrome://global/content/bindings/scrollbox.xml",
|
||||
* "_fillTrailingGap@chrome://browser/content/tabbrowser.xml",
|
||||
* "_handleNewTab@chrome://browser/content/tabbrowser.xml",
|
||||
* "onxbltransitionend@chrome://browser/content/tabbrowser.xml",
|
||||
* ],
|
||||
* }
|
||||
*
|
||||
* ]
|
||||
*
|
||||
|
@ -49,7 +66,7 @@
|
|||
* @param window (browser window, optional)
|
||||
* The browser window to monitor. Defaults to the current window.
|
||||
*/
|
||||
async function withReflowObserver(testFn, expectedReflows = [], win = window) {
|
||||
async function withReflowObserver(testFn, expectedStacks = [], win = window) {
|
||||
let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let dirtyFrameFn = () => {
|
||||
|
@ -64,14 +81,9 @@ async function withReflowObserver(testFn, expectedReflows = [], win = window) {
|
|||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
// We're going to remove the reflows one by one as we see them so that
|
||||
// We're going to remove the stacks one by one as we see them so that
|
||||
// we can check for expected, unseen reflows, so let's clone the array.
|
||||
// While we're at it, for reflows that omit the "times" property, default
|
||||
// it to 1.
|
||||
expectedReflows = expectedReflows.slice(0);
|
||||
expectedReflows.forEach(r => {
|
||||
r.times = r.times || 1;
|
||||
});
|
||||
expectedStacks = expectedStacks.slice(0);
|
||||
|
||||
let observer = {
|
||||
reflow(start, end) {
|
||||
|
@ -92,14 +104,12 @@ async function withReflowObserver(testFn, expectedReflows = [], win = window) {
|
|||
return;
|
||||
}
|
||||
|
||||
let index = expectedReflows.findIndex(reflow => path.startsWith(reflow.stack.join("|")));
|
||||
let index = expectedStacks.findIndex(stack => path.startsWith(stack.join("|")));
|
||||
|
||||
if (index != -1) {
|
||||
Assert.ok(true, "expected uninterruptible reflow: '" +
|
||||
JSON.stringify(pathWithLineNumbers, null, "\t") + "'");
|
||||
if (--expectedReflows[index].times == 0) {
|
||||
expectedReflows.splice(index, 1);
|
||||
}
|
||||
expectedStacks.splice(index, 1);
|
||||
} else {
|
||||
Assert.ok(false, "unexpected uninterruptible reflow \n" +
|
||||
JSON.stringify(pathWithLineNumbers, null, "\t") + "\n");
|
||||
|
@ -125,16 +135,16 @@ async function withReflowObserver(testFn, expectedReflows = [], win = window) {
|
|||
|
||||
try {
|
||||
dirtyFrameFn();
|
||||
await testFn(dirtyFrameFn);
|
||||
await testFn();
|
||||
} finally {
|
||||
for (let remainder of expectedReflows) {
|
||||
for (let remainder of expectedStacks) {
|
||||
Assert.ok(false,
|
||||
`Unused expected reflow: ${JSON.stringify(remainder.stack, null, "\t")}\n` +
|
||||
`This reflow was supposed to be hit ${remainder.times} more time(s).\n` +
|
||||
`Unused expected reflow: ${JSON.stringify(remainder, null, "\t")}.\n` +
|
||||
"This is probably a good thing - just remove it from the " +
|
||||
"expected list.");
|
||||
}
|
||||
|
||||
|
||||
els.removeListenerForAllEvents(win, dirtyFrameFn, true);
|
||||
docShell.removeWeakReflowObserver(observer);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,7 @@ add_task(async function() {
|
|||
"Button (" + button.id + ") starts out with correct anchor");
|
||||
|
||||
let navbar = document.getElementById("nav-bar").customizationTarget;
|
||||
let onMouseUp = BrowserTestUtils.waitForEvent(navbar, "mouseup");
|
||||
simulateItemDrag(button, navbar);
|
||||
await onMouseUp;
|
||||
is(CustomizableUI.getPlacementOfWidget(button.id).area, "nav-bar",
|
||||
"Button (" + button.id + ") ends up in nav-bar");
|
||||
|
||||
|
@ -57,9 +55,7 @@ add_task(async function() {
|
|||
"Button (" + button.id + ") has no anchor in toolbar");
|
||||
|
||||
let panel = document.getElementById("PanelUI-contents");
|
||||
let onMouseUp = BrowserTestUtils.waitForEvent(panel, "mouseup");
|
||||
simulateItemDrag(button, panel);
|
||||
await onMouseUp;
|
||||
is(CustomizableUI.getPlacementOfWidget(button.id).area, "PanelUI-contents",
|
||||
"Button (" + button.id + ") ends up in panel");
|
||||
is(button.getAttribute(kAnchorAttribute), "PanelUI-menu-button",
|
||||
|
|
|
@ -11,7 +11,6 @@ requestLongerTimeout(2);
|
|||
// Test toggling the toolbox quickly and see if there is any race breaking it.
|
||||
|
||||
const URL = "data:text/html;charset=utf-8,Toggling devtools quickly";
|
||||
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
|
||||
|
||||
add_task(function* () {
|
||||
// Make sure this test starts with the selectedTool pref cleared. Previous
|
||||
|
@ -81,10 +80,5 @@ add_task(function* () {
|
|||
});
|
||||
|
||||
function toggle() {
|
||||
// When enabling the input event prioritization, we'll reserve some time to
|
||||
// process input events in each frame. In that case, the synthesized input
|
||||
// events may delay the normal events. Replace synthesized key events by
|
||||
// toggleToolboxCommand to prevent the synthesized input events jam the
|
||||
// content process and cause the test timeout.
|
||||
gDevToolsBrowser.toggleToolboxCommand(window.gBrowser);
|
||||
EventUtils.synthesizeKey("VK_F12", {});
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ function* respondsToMoveEvents(helper, testActor) {
|
|||
yield mouse.move(x, y);
|
||||
} else if (type === "keyboard") {
|
||||
let options = shift ? {shiftKey: true} : {};
|
||||
yield EventUtils.synthesizeAndWaitKey(key, options);
|
||||
yield EventUtils.synthesizeKey(key, options);
|
||||
}
|
||||
yield checkPosition(expected, helper);
|
||||
}
|
||||
|
@ -128,14 +128,14 @@ function* checkPosition({x, y}, {getElementAttribute}) {
|
|||
function* respondsToReturnAndEscape({isElementHidden, show}) {
|
||||
info("Simulating return to select the color and hide the eyedropper");
|
||||
|
||||
yield EventUtils.synthesizeAndWaitKey("VK_RETURN", {});
|
||||
yield EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
let hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper has been hidden");
|
||||
|
||||
info("Showing the eyedropper again and simulating escape to hide it");
|
||||
|
||||
yield show("html");
|
||||
yield EventUtils.synthesizeAndWaitKey("VK_ESCAPE", {});
|
||||
yield EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper has been hidden again");
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef TabGroup_h
|
||||
#define TabGroup_h
|
||||
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
@ -44,7 +43,6 @@ class TabChild;
|
|||
// window.opener. A DocGroup is a member of exactly one TabGroup.
|
||||
|
||||
class DocGroup;
|
||||
class TabChild;
|
||||
|
||||
class TabGroup final : public SchedulerGroup
|
||||
{
|
||||
|
|
|
@ -175,30 +175,6 @@ private:
|
|||
nsSize mSize;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
class NativeInputRunnable final : public PrioritizableRunnable
|
||||
{
|
||||
explicit NativeInputRunnable(already_AddRefed<nsIRunnable>&& aEvent);
|
||||
~NativeInputRunnable() {}
|
||||
public:
|
||||
static already_AddRefed<nsIRunnable> Create(already_AddRefed<nsIRunnable>&& aEvent);
|
||||
};
|
||||
|
||||
NativeInputRunnable::NativeInputRunnable(already_AddRefed<nsIRunnable>&& aEvent)
|
||||
: PrioritizableRunnable(Move(aEvent), nsIRunnablePriority::PRIORITY_INPUT)
|
||||
{
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIRunnable>
|
||||
NativeInputRunnable::Create(already_AddRefed<nsIRunnable>&& aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event(new NativeInputRunnable(Move(aEvent)));
|
||||
return event.forget();
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
LinkedList<OldWindowSize> OldWindowSize::sList;
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils)
|
||||
|
@ -1144,7 +1120,7 @@ nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
|
|||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_DispatchToMainThread(NativeInputRunnable::Create(
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod<int32_t,
|
||||
int32_t,
|
||||
uint32_t,
|
||||
|
@ -1158,7 +1134,7 @@ nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
|
|||
aModifiers,
|
||||
aCharacters,
|
||||
aUnmodifiedCharacters,
|
||||
aObserver)));
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1175,7 +1151,7 @@ nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX,
|
|||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_DispatchToMainThread(NativeInputRunnable::Create(
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod<LayoutDeviceIntPoint, int32_t, int32_t, nsIObserver*>(
|
||||
"nsIWidget::SynthesizeNativeMouseEvent",
|
||||
widget,
|
||||
|
@ -1183,7 +1159,7 @@ nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX,
|
|||
LayoutDeviceIntPoint(aScreenX, aScreenY),
|
||||
aNativeMessage,
|
||||
aModifierFlags,
|
||||
aObserver)));
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1198,13 +1174,12 @@ nsDOMWindowUtils::SendNativeMouseMove(int32_t aScreenX,
|
|||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_DispatchToMainThread(NativeInputRunnable::Create(
|
||||
NewRunnableMethod<LayoutDeviceIntPoint, nsIObserver*>(
|
||||
NS_DispatchToMainThread(NewRunnableMethod<LayoutDeviceIntPoint, nsIObserver*>(
|
||||
"nsIWidget::SynthesizeNativeMouseMove",
|
||||
widget,
|
||||
&nsIWidget::SynthesizeNativeMouseMove,
|
||||
LayoutDeviceIntPoint(aScreenX, aScreenY),
|
||||
aObserver)));
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1226,8 +1201,7 @@ nsDOMWindowUtils::SendNativeMouseScrollEvent(int32_t aScreenX,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(NativeInputRunnable::Create(
|
||||
NewRunnableMethod<mozilla::LayoutDeviceIntPoint,
|
||||
NS_DispatchToMainThread(NewRunnableMethod<mozilla::LayoutDeviceIntPoint,
|
||||
uint32_t,
|
||||
double,
|
||||
double,
|
||||
|
@ -1245,7 +1219,7 @@ nsDOMWindowUtils::SendNativeMouseScrollEvent(int32_t aScreenX,
|
|||
aDeltaZ,
|
||||
aModifierFlags,
|
||||
aAdditionalFlags,
|
||||
aObserver)));
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1267,7 +1241,7 @@ nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(NativeInputRunnable::Create(
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod<uint32_t,
|
||||
nsIWidget::TouchPointerState,
|
||||
LayoutDeviceIntPoint,
|
||||
|
@ -1281,7 +1255,7 @@ nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
|
|||
LayoutDeviceIntPoint(aScreenX, aScreenY),
|
||||
aPressure,
|
||||
aOrientation,
|
||||
aObserver)));
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1296,14 +1270,14 @@ nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(NativeInputRunnable::Create(
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod<LayoutDeviceIntPoint, bool, nsIObserver*>(
|
||||
"nsIWidget::SynthesizeNativeTouchTap",
|
||||
widget,
|
||||
&nsIWidget::SynthesizeNativeTouchTap,
|
||||
LayoutDeviceIntPoint(aScreenX, aScreenY),
|
||||
aLongTap,
|
||||
aObserver)));
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1325,11 +1299,11 @@ nsDOMWindowUtils::ClearNativeTouchSequence(nsIObserver* aObserver)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(NativeInputRunnable::Create(
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod<nsIObserver*>("nsIWidget::ClearNativeTouchSequence",
|
||||
widget,
|
||||
&nsIWidget::ClearNativeTouchSequence,
|
||||
aObserver)));
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -849,13 +849,6 @@ nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::GetTabEventTarget(nsIEventTarget** aTarget)
|
||||
{
|
||||
*aTarget = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
|
||||
nsAString& aAsciiBase64String)
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
interface mozIDOMWindowProxy;
|
||||
interface nsIDocShell;
|
||||
interface nsIContent;
|
||||
interface nsIEventTarget;
|
||||
interface nsIFrameLoader;
|
||||
interface nsIPrincipal;
|
||||
|
||||
|
@ -399,12 +398,6 @@ interface nsIContentFrameMessageManager : nsIMessageManagerGlobal
|
|||
* The top level docshell or null.
|
||||
*/
|
||||
readonly attribute nsIDocShell docShell;
|
||||
|
||||
/**
|
||||
* Returns the SchedulerEventTarget corresponding to the TabGroup
|
||||
* for this frame.
|
||||
*/
|
||||
readonly attribute nsIEventTarget tabEventTarget;
|
||||
};
|
||||
|
||||
[uuid(b39a3324-b574-4f85-8cdb-274d04f807ef)]
|
||||
|
|
|
@ -199,14 +199,6 @@ nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInProcessTabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
|
||||
target.forget(aTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsInProcessTabChildGlobal::FireUnloadEvent()
|
||||
{
|
||||
|
|
|
@ -77,7 +77,6 @@ public:
|
|||
}
|
||||
NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
|
||||
NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
|
||||
NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
|
||||
|
||||
NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
|
||||
|
||||
|
|
|
@ -2867,7 +2867,6 @@ NodeAllowsClickThrough(nsINode* aNode)
|
|||
|
||||
void
|
||||
EventStateManager::PostHandleKeyboardEvent(WidgetKeyboardEvent* aKeyboardEvent,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsEventStatus& aStatus)
|
||||
{
|
||||
if (aStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
|
@ -2875,24 +2874,6 @@ EventStateManager::PostHandleKeyboardEvent(WidgetKeyboardEvent* aKeyboardEvent,
|
|||
}
|
||||
|
||||
if (!aKeyboardEvent->HasBeenPostedToRemoteProcess()) {
|
||||
if (aKeyboardEvent->IsWaitingReplyFromRemoteProcess()) {
|
||||
RefPtr<TabParent> remote = aTargetFrame ?
|
||||
TabParent::GetFrom(aTargetFrame->GetContent()) : nullptr;
|
||||
if (remote && !remote->IsReadyToHandleInputEvents()) {
|
||||
// We need to dispatch the event to the browser element again if we were
|
||||
// waiting for the key reply but the event wasn't sent to the content
|
||||
// process due to the remote browser wasn't ready.
|
||||
WidgetKeyboardEvent keyEvent(*aKeyboardEvent);
|
||||
aKeyboardEvent->MarkAsHandledInRemoteProcess();
|
||||
EventDispatcher::Dispatch(remote->GetOwnerElement(), mPresContext,
|
||||
&keyEvent);
|
||||
if (keyEvent.DefaultPrevented()) {
|
||||
aKeyboardEvent->PreventDefault(!keyEvent.DefaultPreventedByContent());
|
||||
aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// The widget expects a reply for every keyboard event. If the event wasn't
|
||||
// dispatched to a content process (non-e10s or no content process
|
||||
// running), we need to short-circuit here. Otherwise, we need to wait for
|
||||
|
@ -3544,7 +3525,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
case eKeyPress:
|
||||
{
|
||||
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
|
||||
PostHandleKeyboardEvent(keyEvent, mCurrentTarget, *aStatus);
|
||||
PostHandleKeyboardEvent(keyEvent, *aStatus);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ public:
|
|||
nsEventStatus* aStatus);
|
||||
|
||||
void PostHandleKeyboardEvent(WidgetKeyboardEvent* aKeyboardEvent,
|
||||
nsIFrame* aTargetFrame, nsEventStatus& aStatus);
|
||||
nsEventStatus& aStatus);
|
||||
|
||||
/**
|
||||
* DispatchLegacyMouseScrollEvents() dispatches eLegacyMouseLineOrPageScroll
|
||||
|
|
|
@ -1141,28 +1141,9 @@ function doTestZoom(aSettings, aCallback)
|
|||
var scrollTop = gScrollableElement.scrollTop;
|
||||
var scrollLeft = gScrollableElement.scrollLeft;
|
||||
|
||||
fullZoomChangePromise = new Promise(resolve => {
|
||||
if (currentTest.expected & (kNegative | kPositive)) {
|
||||
SpecialPowers.addChromeEventListener("FullZoomChange", function onFullZoomChange() {
|
||||
if (SpecialPowers.getFullZoom(window) != 1) {
|
||||
SpecialPowers.removeChromeEventListener("FullZoomChange", onFullZoomChange)
|
||||
setTimeout(() => resolve(), 0);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
sendWheelAndWait(10, 10, event, function () {
|
||||
is(gScrollableElement.scrollTop, scrollTop, description + "scrolled vertical");
|
||||
is(gScrollableElement.scrollLeft, scrollLeft, description + "scrolled horizontal");
|
||||
|
||||
fullZoomChangePromise.then(() => {
|
||||
// When input event prioritization is enabled, the wheel event may be
|
||||
// dispatched to the content process before the message 'FullZoom' to
|
||||
// zoom in/out. Waiting for the event 'FullZoomChange' and then check
|
||||
// the result.
|
||||
if (!(currentTest.expected & (kNegative | kPositive))) {
|
||||
is(SpecialPowers.getFullZoom(window), 1.0, description + "zoomed");
|
||||
} else {
|
||||
|
@ -1177,17 +1158,12 @@ function doTestZoom(aSettings, aCallback)
|
|||
description + "not zoomed out, got " + SpecialPowers.getFullZoom(window));
|
||||
}
|
||||
}
|
||||
if (SpecialPowers.getFullZoom(window) != 1) {
|
||||
// Only synthesizes key event to reset zoom when necessary to avoid
|
||||
// triggering the next test before the key event is handled. In that
|
||||
// case, the key event may break the next test.
|
||||
|
||||
synthesizeKey("0", { accelKey: true });
|
||||
}
|
||||
onZoomReset(function () {
|
||||
hitEventLoop(doNextTest, 20);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
doNextTest();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1261673
|
|||
<title>Test for Bug 1261673</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -55,15 +54,21 @@ function runTests() {
|
|||
(p["focus"]) ? input.focus() : input.blur();
|
||||
expectChange = p["valueChanged"] == 0 ? expectChange : expectChange + 1;
|
||||
result += parseInt(p["valueChanged"]);
|
||||
sendWheelAndPaint(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }, () => {
|
||||
synthesizeWheel(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] });
|
||||
window.postMessage("finished", "http://mochi.test:8888");
|
||||
testIdx++;
|
||||
}
|
||||
|
||||
window.addEventListener("message", event => {
|
||||
if (event.data == "finished") {
|
||||
ok(input.value == result,
|
||||
"Handle wheel in number input test-" + testIdx + " expect " + result +
|
||||
" get " + input.value);
|
||||
ok(numberChange == expectChange,
|
||||
"UA should fire change event when input's value changed, expect " + expectChange + " get " + numberChange);
|
||||
(++testIdx >= params.length) ? SimpleTest.finish() : runNext();
|
||||
});
|
||||
(testIdx >= params.length) ? SimpleTest.finish() : runNext();
|
||||
}
|
||||
});
|
||||
runNext();
|
||||
}
|
||||
|
||||
|
|
|
@ -171,24 +171,6 @@ ContentBridgeParent::DeallocPBrowserParent(PBrowserParent* aParent)
|
|||
return nsIContentParent::DeallocPBrowserParent(aParent);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentBridgeParent::RecvPBrowserConstructor(PBrowserParent* actor,
|
||||
const TabId& tabId,
|
||||
const TabId& sameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& cpId,
|
||||
const bool& isForBrowser)
|
||||
{
|
||||
return nsIContentParent::RecvPBrowserConstructor(actor,
|
||||
tabId,
|
||||
sameTabGroupAs,
|
||||
context,
|
||||
chromeFlags,
|
||||
cpId,
|
||||
isForBrowser);
|
||||
}
|
||||
|
||||
void
|
||||
ContentBridgeParent::NotifyTabDestroyed()
|
||||
{
|
||||
|
|
|
@ -138,15 +138,6 @@ protected:
|
|||
|
||||
virtual bool DeallocPBrowserParent(PBrowserParent*) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPBrowserConstructor(PBrowserParent* actor,
|
||||
const TabId& tabId,
|
||||
const TabId& sameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& cpId,
|
||||
const bool& isForBrowser) override;
|
||||
|
||||
virtual PIPCBlobInputStreamParent*
|
||||
SendPIPCBlobInputStreamConstructor(PIPCBlobInputStreamParent* aActor,
|
||||
const nsID& aID,
|
||||
|
|
|
@ -1176,9 +1176,6 @@ ContentChild::InitXPCOM(const XPCOMInitData& aXPCOMInit,
|
|||
GfxInfoBase::SetFeatureStatus(aXPCOMInit.gfxFeatureStatus());
|
||||
|
||||
DataStorage::SetCachedStorageEntries(aXPCOMInit.dataStorage());
|
||||
|
||||
// Enable input event prioritization.
|
||||
nsThreadManager::get().EnableMainThreadEventPrioritization();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
|
|
|
@ -2877,24 +2877,6 @@ ContentParent::DeallocPBrowserParent(PBrowserParent* frame)
|
|||
return nsIContentParent::DeallocPBrowserParent(frame);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvPBrowserConstructor(PBrowserParent* actor,
|
||||
const TabId& tabId,
|
||||
const TabId& sameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& cpId,
|
||||
const bool& isForBrowser)
|
||||
{
|
||||
return nsIContentParent::RecvPBrowserConstructor(actor,
|
||||
tabId,
|
||||
sameTabGroupAs,
|
||||
context,
|
||||
chromeFlags,
|
||||
cpId,
|
||||
isForBrowser);
|
||||
}
|
||||
|
||||
PIPCBlobInputStreamParent*
|
||||
ContentParent::AllocPIPCBlobInputStreamParent(const nsID& aID,
|
||||
const uint64_t& aSize)
|
||||
|
|
|
@ -845,15 +845,6 @@ private:
|
|||
|
||||
virtual bool DeallocPBrowserParent(PBrowserParent* frame) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPBrowserConstructor(PBrowserParent* actor,
|
||||
const TabId& tabId,
|
||||
const TabId& sameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& cpId,
|
||||
const bool& isForBrowser) override;
|
||||
|
||||
virtual PIPCBlobInputStreamParent*
|
||||
SendPIPCBlobInputStreamConstructor(PIPCBlobInputStreamParent* aActor,
|
||||
const nsID& aID,
|
||||
|
|
|
@ -542,12 +542,6 @@ parent:
|
|||
*/
|
||||
async RemotePaintIsReady();
|
||||
|
||||
/**
|
||||
* Child informs the parent that the content is ready to handle input
|
||||
* events. This is sent when the TabChild is created.
|
||||
*/
|
||||
async RemoteIsReadyToHandleInputEvents();
|
||||
|
||||
/**
|
||||
* Child informs the parent that the layer tree is already available.
|
||||
*/
|
||||
|
@ -651,9 +645,7 @@ child:
|
|||
* When two consecutive mouse move events would be added to the message queue,
|
||||
* they are 'compressed' by dumping the oldest one.
|
||||
*/
|
||||
prio(input) async RealMouseMoveEvent(WidgetMouseEvent event,
|
||||
ScrollableLayerGuid aGuid,
|
||||
uint64_t aInputBlockId) compress;
|
||||
async RealMouseMoveEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId) compress;
|
||||
/**
|
||||
* Mouse move events with |reason == eSynthesized| are sent via a separate
|
||||
* message because they do not generate DOM 'mousemove' events, and the
|
||||
|
@ -661,29 +653,21 @@ child:
|
|||
* |reason == eReal| event being dropped in favour of an |eSynthesized|
|
||||
* event, and thus a DOM 'mousemove' event to be lost.
|
||||
*/
|
||||
prio(input) async SynthMouseMoveEvent(WidgetMouseEvent event,
|
||||
ScrollableLayerGuid aGuid,
|
||||
uint64_t aInputBlockId);
|
||||
prio(input) async RealMouseButtonEvent(WidgetMouseEvent event,
|
||||
ScrollableLayerGuid aGuid,
|
||||
uint64_t aInputBlockId);
|
||||
prio(input) async RealKeyEvent(WidgetKeyboardEvent event);
|
||||
prio(input) async MouseWheelEvent(WidgetWheelEvent event,
|
||||
ScrollableLayerGuid aGuid,
|
||||
uint64_t aInputBlockId);
|
||||
prio(input) async RealTouchEvent(WidgetTouchEvent aEvent,
|
||||
async SynthMouseMoveEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
async RealMouseButtonEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
async RealKeyEvent(WidgetKeyboardEvent event);
|
||||
async MouseWheelEvent(WidgetWheelEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
async RealTouchEvent(WidgetTouchEvent aEvent,
|
||||
ScrollableLayerGuid aGuid,
|
||||
uint64_t aInputBlockId,
|
||||
nsEventStatus aApzResponse);
|
||||
prio(input) async HandleTap(TapType aType, LayoutDevicePoint point,
|
||||
Modifiers aModifiers, ScrollableLayerGuid aGuid,
|
||||
uint64_t aInputBlockId);
|
||||
prio(input) async RealTouchMoveEvent(WidgetTouchEvent aEvent,
|
||||
async HandleTap(TapType aType, LayoutDevicePoint point, Modifiers aModifiers,
|
||||
ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
async RealTouchMoveEvent(WidgetTouchEvent aEvent,
|
||||
ScrollableLayerGuid aGuid,
|
||||
uint64_t aInputBlockId,
|
||||
nsEventStatus aApzResponse);
|
||||
prio(input) async RealDragEvent(WidgetDragEvent aEvent,
|
||||
uint32_t aDragAction, uint32_t aDropEffect);
|
||||
async RealDragEvent(WidgetDragEvent aEvent, uint32_t aDragAction, uint32_t aDropEffect);
|
||||
async PluginEvent(WidgetPluginEvent aEvent);
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,7 +90,6 @@
|
|||
#include "nsPIWindowRoot.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
@ -322,19 +321,7 @@ private:
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mTabChild);
|
||||
// When enabling input event prioritization, we reserve limited time
|
||||
// to process input events. We may handle the rest in the next frame
|
||||
// when running out of time of the current frame. In that case, input
|
||||
// events may be dispatched after ActorDestroy. Delay
|
||||
// DelayedDeleteRunnable to avoid it to happen.
|
||||
nsThread* thread = nsThreadManager::get().GetCurrentThread();
|
||||
MOZ_ASSERT(thread);
|
||||
bool eventPrioritizationEnabled = false;
|
||||
thread->IsEventPrioritizationEnabled(&eventPrioritizationEnabled);
|
||||
if (eventPrioritizationEnabled && thread->HasPendingInputEvents()) {
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check in case ActorDestroy was called after RecvDestroy message.
|
||||
if (mTabChild->IPCOpen()) {
|
||||
Unused << PBrowserChild::Send__delete__(mTabChild);
|
||||
|
@ -3520,14 +3507,6 @@ TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> target = EventTargetFor(TaskCategory::Other);
|
||||
target.forget(aTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
TabChildGlobal::GetPrincipal()
|
||||
{
|
||||
|
|
|
@ -114,7 +114,6 @@ public:
|
|||
}
|
||||
NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
|
||||
NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
|
||||
NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
|
||||
|
||||
nsresult AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
|
|
|
@ -172,8 +172,6 @@ TabParent::TabParent(nsIContentParent* aManager,
|
|||
, mPreserveLayers(false)
|
||||
, mHasPresented(false)
|
||||
, mHasBeforeUnload(false)
|
||||
, mIsReadyToHandleInputEvents(false)
|
||||
, mIsMouseEnterIntoWidgetEventSuppressed(false)
|
||||
{
|
||||
MOZ_ASSERT(aManager);
|
||||
}
|
||||
|
@ -1083,7 +1081,7 @@ TabParent::SendKeyEvent(const nsAString& aType,
|
|||
int32_t aModifiers,
|
||||
bool aPreventDefault)
|
||||
{
|
||||
if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
Unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
|
||||
|
@ -1114,33 +1112,11 @@ TabParent::SendRealMouseEvent(WidgetMouseEvent& aEvent)
|
|||
mTabSetsCursor = false;
|
||||
}
|
||||
}
|
||||
if (!mIsReadyToHandleInputEvents) {
|
||||
if (eMouseEnterIntoWidget == aEvent.mMessage) {
|
||||
MOZ_ASSERT(!mIsMouseEnterIntoWidgetEventSuppressed);
|
||||
mIsMouseEnterIntoWidgetEventSuppressed = true;
|
||||
} else if (eMouseExitFromWidget == aEvent.mMessage) {
|
||||
MOZ_ASSERT(mIsMouseEnterIntoWidgetEventSuppressed);
|
||||
mIsMouseEnterIntoWidgetEventSuppressed = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ScrollableLayerGuid guid;
|
||||
uint64_t blockId;
|
||||
ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
|
||||
|
||||
if (mIsMouseEnterIntoWidgetEventSuppressed) {
|
||||
// In the case that the TabParent suppressed the eMouseEnterWidget event due
|
||||
// to its corresponding TabChild wasn't ready to handle it, we have to
|
||||
// resend it when the TabChild is ready.
|
||||
mIsMouseEnterIntoWidgetEventSuppressed = false;
|
||||
WidgetMouseEvent localEvent(aEvent);
|
||||
localEvent.mMessage = eMouseEnterIntoWidget;
|
||||
DebugOnly<bool> ret = SendRealMouseButtonEvent(localEvent, guid, blockId);
|
||||
NS_WARNING_ASSERTION(ret, "SendRealMouseButtonEvent(eMouseEnterIntoWidget) failed");
|
||||
MOZ_ASSERT(!ret || localEvent.HasBeenPostedToRemoteProcess());
|
||||
}
|
||||
|
||||
if (eMouseMove == aEvent.mMessage) {
|
||||
if (aEvent.mReason == WidgetMouseEvent::eSynthesized) {
|
||||
DebugOnly<bool> ret = SendSynthMouseMoveEvent(aEvent, guid, blockId);
|
||||
|
@ -1175,7 +1151,7 @@ void
|
|||
TabParent::SendRealDragEvent(WidgetDragEvent& aEvent, uint32_t aDragAction,
|
||||
uint32_t aDropEffect)
|
||||
{
|
||||
if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
aEvent.mRefPoint += GetChildProcessOffset();
|
||||
|
@ -1194,7 +1170,7 @@ TabParent::AdjustTapToChildWidget(const LayoutDevicePoint& aPoint)
|
|||
void
|
||||
TabParent::SendMouseWheelEvent(WidgetWheelEvent& aEvent)
|
||||
{
|
||||
if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1473,7 +1449,7 @@ TabParent::RecvClearNativeTouchSequence(const uint64_t& aObserverId)
|
|||
void
|
||||
TabParent::SendRealKeyEvent(WidgetKeyboardEvent& aEvent)
|
||||
{
|
||||
if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
aEvent.mRefPoint += GetChildProcessOffset();
|
||||
|
@ -1494,7 +1470,7 @@ TabParent::SendRealKeyEvent(WidgetKeyboardEvent& aEvent)
|
|||
void
|
||||
TabParent::SendRealTouchEvent(WidgetTouchEvent& aEvent)
|
||||
{
|
||||
if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1555,7 +1531,7 @@ TabParent::SendHandleTap(TapType aType,
|
|||
const ScrollableLayerGuid& aGuid,
|
||||
uint64_t aInputBlockId)
|
||||
{
|
||||
if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
|
||||
if (mIsDestroyed) {
|
||||
return false;
|
||||
}
|
||||
if ((aType == TapType::eSingleTap || aType == TapType::eSecondTap) &&
|
||||
|
@ -2960,18 +2936,6 @@ TabParent::RecvRemotePaintIsReady()
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabParent::RecvRemoteIsReadyToHandleInputEvents()
|
||||
{
|
||||
// When enabling input event prioritization, input events may preempt other
|
||||
// normal priority IPC messages. To prevent the input events preempt
|
||||
// PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
|
||||
// notify the parent that TabChild is created and ready to handle input
|
||||
// events.
|
||||
SetReadyToHandleInputEvents();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::plugins::PPluginWidgetParent*
|
||||
TabParent::AllocPPluginWidgetParent()
|
||||
{
|
||||
|
|
|
@ -603,9 +603,6 @@ public:
|
|||
void LiveResizeStarted() override;
|
||||
void LiveResizeStopped() override;
|
||||
|
||||
void SetReadyToHandleInputEvents() { mIsReadyToHandleInputEvents = true; }
|
||||
bool IsReadyToHandleInputEvents() { return mIsReadyToHandleInputEvents; }
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
|
@ -631,8 +628,6 @@ protected:
|
|||
|
||||
virtual mozilla::ipc::IPCResult RecvRemotePaintIsReady() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvRemoteIsReadyToHandleInputEvents() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvForcePaintNoOp(const uint64_t& aLayerObserverEpoch) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvSetDimensions(const uint32_t& aFlags,
|
||||
|
@ -783,14 +778,6 @@ private:
|
|||
// beforeunload event listener.
|
||||
bool mHasBeforeUnload;
|
||||
|
||||
// True when the remote browser is created and ready to handle input events.
|
||||
bool mIsReadyToHandleInputEvents;
|
||||
|
||||
// True if we suppress the eMouseEnterIntoWidget event due to the TabChild was
|
||||
// not ready to handle it. We will resend it when the next time we fire a
|
||||
// mouse event and the TabChild is ready.
|
||||
bool mIsMouseEnterIntoWidgetEventSuppressed;
|
||||
|
||||
public:
|
||||
static TabParent* GetTabParentFromLayersId(uint64_t aLayersId);
|
||||
};
|
||||
|
|
|
@ -102,8 +102,7 @@ nsIContentChild::RecvPBrowserConstructor(PBrowserChild* aActor,
|
|||
if (os) {
|
||||
os->NotifyObservers(static_cast<nsITabChild*>(tabChild), "tab-child-created", nullptr);
|
||||
}
|
||||
// Notify parent that we are ready to handle input events.
|
||||
tabChild->SendRemoteIsReadyToHandleInputEvents();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -206,25 +206,6 @@ nsIContentParent::DeallocPBrowserParent(PBrowserParent* aFrame)
|
|||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
nsIContentParent::RecvPBrowserConstructor(PBrowserParent* actor,
|
||||
const TabId& tabId,
|
||||
const TabId& sameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& cpId,
|
||||
const bool& isForBrowser)
|
||||
{
|
||||
TabParent* parent = TabParent::GetFrom(actor);
|
||||
// When enabling input event prioritization, input events may preempt other
|
||||
// normal priority IPC messages. To prevent the input events preempt
|
||||
// PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
|
||||
// notify parent that TabChild is created. In this case, PBrowser is initiated
|
||||
// from content so that we can set TabParent as ready to handle input events.
|
||||
parent->SetReadyToHandleInputEvents();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
PIPCBlobInputStreamParent*
|
||||
nsIContentParent::AllocPIPCBlobInputStreamParent(const nsID& aID,
|
||||
const uint64_t& aSize)
|
||||
|
|
|
@ -117,15 +117,6 @@ protected: // IPDL methods
|
|||
const bool& aIsForBrowser);
|
||||
virtual bool DeallocPBrowserParent(PBrowserParent* frame);
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPBrowserConstructor(PBrowserParent* actor,
|
||||
const TabId& tabId,
|
||||
const TabId& sameTabGroupAs,
|
||||
const IPCTabContext& context,
|
||||
const uint32_t& chromeFlags,
|
||||
const ContentParentId& cpId,
|
||||
const bool& isForBrowser);
|
||||
|
||||
virtual mozilla::ipc::PIPCBlobInputStreamParent*
|
||||
AllocPIPCBlobInputStreamParent(const nsID& aID, const uint64_t& aSize);
|
||||
|
||||
|
|
|
@ -18,14 +18,14 @@ add_task(async function() {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
await EventUtils.synthesizeAndWaitKey("d", { code: "KeyD", repeat: 3 });
|
||||
EventUtils.synthesizeKey("d", { code: "KeyD", repeat: 3 });
|
||||
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
is(content.document.body.getAttribute("data-down"), "2", "Correct number of events");
|
||||
is(content.document.body.getAttribute("data-press"), "2", "Correct number of events");
|
||||
});
|
||||
|
||||
await EventUtils.synthesizeAndWaitKey("p", { code: "KeyP", repeat: 3 });
|
||||
EventUtils.synthesizeKey("p", { code: "KeyP", repeat: 3 });
|
||||
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
is(content.document.body.getAttribute("data-down"), "4", "Correct number of events");
|
||||
|
|
|
@ -43,10 +43,11 @@ add_task(async function() {
|
|||
// but in non-e10s it is handled by the browser UI code and hence won't
|
||||
// reach the web page. As a result, we need to observe the event in
|
||||
// the content process only in e10s mode.
|
||||
if (gMultiProcessBrowser) {
|
||||
return EventUtils.synthesizeAndWaitKey("x", {accelKey: true, shiftKey: true});
|
||||
}
|
||||
var waitForKeypressContent = BrowserTestUtils.waitForContentEvent(aBrowser, "keypress");
|
||||
EventUtils.synthesizeKey("x", {accelKey: true, shiftKey: true});
|
||||
if (gMultiProcessBrowser) {
|
||||
return waitForKeypressContent;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
|
|
@ -93,11 +93,6 @@ function waitFor(eventType, count) {
|
|||
return true;
|
||||
}
|
||||
|
||||
function RunAfterProcessedQueuedInputEvents(aCallback) {
|
||||
let tm = SpecialPowers.Services.tm;
|
||||
tm.dispatchToMainThread(aCallback, SpecialPowers.Ci.nsIRunnablePriority.PRIORITY_INPUT);
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
// The main part of this test should run completely before the child process'
|
||||
// main-thread deals with the touch event, so check to make sure that happens.
|
||||
|
@ -144,8 +139,8 @@ function* test(testDriver) {
|
|||
// scrolling even though we know we haven't yet processed the DOM touch events
|
||||
// in the child process yet.
|
||||
//
|
||||
// Note that the "async callback" we use here is SpecialPowers.tm.dispatchToMainThread
|
||||
// with priority = input, because nothing else does exactly what we want:
|
||||
// Note that the "async callback" we use here is SpecialPowers.executeSoon,
|
||||
// because nothing else does exactly what we want:
|
||||
// - setTimeout(..., 0) does not maintain ordering, because it respects the
|
||||
// time delta provided (i.e. the callback can jump the queue to meet its
|
||||
// deadline).
|
||||
|
@ -154,9 +149,6 @@ function* test(testDriver) {
|
|||
// round-trip time.
|
||||
// - SimpleTest.executeSoon has a codepath that delegates to setTimeout, so
|
||||
// is less reliable if it ever decides to switch to that codepath.
|
||||
// - SpecialPowers.executeSoon dispatches a task to main thread. However,
|
||||
// normal runnables may be preempted by input events and be executed in an
|
||||
// unexpected order.
|
||||
|
||||
// The other problem we need to deal with is the asynchronicity in the chrome
|
||||
// process. That is, we might request a snapshot before the chrome process has
|
||||
|
@ -177,13 +169,13 @@ function* test(testDriver) {
|
|||
// Set up the child process events and callbacks
|
||||
var scroller = document.getElementById('scroller');
|
||||
synthesizeNativeTouch(scroller, 10, 110, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, 0);
|
||||
RunAfterProcessedQueuedInputEvents(testDriver);
|
||||
SpecialPowers.executeSoon(testDriver);
|
||||
for (var i = 1; i < 10; i++) {
|
||||
synthesizeNativeTouch(scroller, 10, 110 - (i * 10), SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, 0);
|
||||
RunAfterProcessedQueuedInputEvents(testDriver);
|
||||
SpecialPowers.executeSoon(testDriver);
|
||||
}
|
||||
synthesizeNativeTouch(scroller, 10, 10, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, null, 0);
|
||||
RunAfterProcessedQueuedInputEvents(testDriver);
|
||||
SpecialPowers.executeSoon(testDriver);
|
||||
ok(true, "Finished setting up event queue");
|
||||
|
||||
// Get our baseline snapshot
|
||||
|
|
|
@ -67,7 +67,8 @@ Message::Message(int32_t routing_id,
|
|||
header()->routing = routing_id;
|
||||
header()->type = type;
|
||||
header()->flags = nestedLevel;
|
||||
set_priority(priority);
|
||||
if (priority == HIGH_PRIORITY)
|
||||
header()->flags |= PRIO_BIT;
|
||||
if (compression == COMPRESSION_ENABLED)
|
||||
header()->flags |= COMPRESS_BIT;
|
||||
else if (compression == COMPRESSION_ALL)
|
||||
|
|
|
@ -46,9 +46,8 @@ class Message : public Pickle {
|
|||
};
|
||||
|
||||
enum PriorityValue {
|
||||
NORMAL_PRIORITY = 0,
|
||||
INPUT_PRIORITY = 1,
|
||||
HIGH_PRIORITY = 2,
|
||||
NORMAL_PRIORITY,
|
||||
HIGH_PRIORITY,
|
||||
};
|
||||
|
||||
enum MessageCompression {
|
||||
|
@ -92,12 +91,17 @@ class Message : public Pickle {
|
|||
}
|
||||
|
||||
PriorityValue priority() const {
|
||||
return static_cast<PriorityValue>((header()->flags & PRIO_MASK) >> 2);
|
||||
if (header()->flags & PRIO_BIT) {
|
||||
return HIGH_PRIORITY;
|
||||
}
|
||||
return NORMAL_PRIORITY;
|
||||
}
|
||||
|
||||
void set_priority(PriorityValue prio) {
|
||||
DCHECK(((prio << 2) & ~PRIO_MASK) == 0);
|
||||
header()->flags = (header()->flags & ~PRIO_MASK) | (prio << 2);
|
||||
header()->flags &= ~PRIO_BIT;
|
||||
if (prio == HIGH_PRIORITY) {
|
||||
header()->flags |= PRIO_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_constructor() const {
|
||||
|
@ -311,16 +315,16 @@ class Message : public Pickle {
|
|||
// flags
|
||||
enum {
|
||||
NESTED_MASK = 0x0003,
|
||||
PRIO_MASK = 0x000C,
|
||||
SYNC_BIT = 0x0010,
|
||||
REPLY_BIT = 0x0020,
|
||||
REPLY_ERROR_BIT = 0x0040,
|
||||
INTERRUPT_BIT = 0x0080,
|
||||
COMPRESS_BIT = 0x0100,
|
||||
COMPRESSALL_BIT = 0x0200,
|
||||
CONSTRUCTOR_BIT = 0x0400,
|
||||
PRIO_BIT = 0x0004,
|
||||
SYNC_BIT = 0x0008,
|
||||
REPLY_BIT = 0x0010,
|
||||
REPLY_ERROR_BIT = 0x0020,
|
||||
INTERRUPT_BIT = 0x0040,
|
||||
COMPRESS_BIT = 0x0080,
|
||||
COMPRESSALL_BIT = 0x0100,
|
||||
CONSTRUCTOR_BIT = 0x0200,
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
TASKTRACER_BIT = 0x0800,
|
||||
TASKTRACER_BIT = 0x0400,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -1976,20 +1976,8 @@ MessageChannel::MessageTask::Clear()
|
|||
NS_IMETHODIMP
|
||||
MessageChannel::MessageTask::GetPriority(uint32_t* aPriority)
|
||||
{
|
||||
switch (mMessage.priority()) {
|
||||
case Message::NORMAL_PRIORITY:
|
||||
*aPriority = PRIORITY_NORMAL;
|
||||
break;
|
||||
case Message::INPUT_PRIORITY:
|
||||
*aPriority = PRIORITY_INPUT;
|
||||
break;
|
||||
case Message::HIGH_PRIORITY:
|
||||
*aPriority = PRIORITY_HIGH;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
*aPriority = mMessage.priority() == Message::HIGH_PRIORITY ?
|
||||
PRIORITY_HIGH : PRIORITY_NORMAL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@ INSIDE_SYNC_NESTED = 2
|
|||
INSIDE_CPOW_NESTED = 3
|
||||
|
||||
NORMAL_PRIORITY = 1
|
||||
INPUT_PRIORITY = 2
|
||||
HIGH_PRIORITY = 3
|
||||
HIGH_PRIORITY = 2
|
||||
|
||||
class Visitor:
|
||||
def defaultVisit(self, node):
|
||||
|
|
|
@ -1727,9 +1727,8 @@ def _generateMessageConstructor(clsname, msgid, segmentSize, nested, prio, prett
|
|||
|
||||
if prio == ipdl.ast.NORMAL_PRIORITY:
|
||||
prioEnum = 'IPC::Message::NORMAL_PRIORITY'
|
||||
elif prio == ipdl.ast.INPUT_PRIORITY:
|
||||
prioEnum = 'IPC::Message::INPUT_PRIORITY'
|
||||
else:
|
||||
assert prio == ipdl.ast.HIGH_PRIORITY
|
||||
prioEnum = 'IPC::Message::HIGH_PRIORITY'
|
||||
|
||||
func.addstmt(
|
||||
|
|
|
@ -503,8 +503,7 @@ def p_Nested(p):
|
|||
def p_Priority(p):
|
||||
"""Priority : ID"""
|
||||
kinds = {'normal': 1,
|
||||
'input': 2,
|
||||
'high': 3}
|
||||
'high': 2}
|
||||
if p[1] not in kinds:
|
||||
_error(locFromTok(p, 1), "Expected normal or high for prio()")
|
||||
|
||||
|
|
|
@ -3,14 +3,11 @@ namespace _ipdltest {
|
|||
|
||||
sync protocol PTestPriority {
|
||||
parent:
|
||||
prio(input) async PMsg1();
|
||||
prio(input) sync PMsg2();
|
||||
prio(high) async PMsg3();
|
||||
prio(high) sync PMsg4();
|
||||
prio(high) async Msg1();
|
||||
prio(high) sync Msg2();
|
||||
|
||||
child:
|
||||
prio(input) async CMsg1();
|
||||
prio(high) async CMsg2();
|
||||
prio(high) async Msg3();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
|
|
|
@ -255,13 +255,6 @@ public:
|
|||
return idleEnd < aDefault ? idleEnd : aDefault;
|
||||
}
|
||||
|
||||
Maybe<TimeStamp> GetNextTickHint()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
TimeStamp nextTick = MostRecentRefresh() + GetTimerRate();
|
||||
return nextTick < TimeStamp::Now() ? Nothing() : Some(nextTick);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void StartTimer() = 0;
|
||||
virtual void StopTimer() = 0;
|
||||
|
@ -2409,17 +2402,6 @@ nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault)
|
|||
return sRegularRateTimer->GetIdleDeadlineHint(aDefault);
|
||||
}
|
||||
|
||||
/* static */ Maybe<TimeStamp>
|
||||
nsRefreshDriver::GetNextTickHint()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sRegularRateTimer) {
|
||||
return Nothing();
|
||||
}
|
||||
return sRegularRateTimer->GetNextTickHint();
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::Disconnect()
|
||||
{
|
||||
|
|
|
@ -345,12 +345,6 @@ public:
|
|||
*/
|
||||
static mozilla::TimeStamp GetIdleDeadlineHint(mozilla::TimeStamp aDefault);
|
||||
|
||||
/**
|
||||
* It returns the expected timestamp of the next tick or nothing if the next
|
||||
* tick is missed.
|
||||
*/
|
||||
static mozilla::Maybe<mozilla::TimeStamp> GetNextTickHint();
|
||||
|
||||
static void DispatchIdleRunnableAfterTick(nsIRunnable* aRunnable,
|
||||
uint32_t aDelay);
|
||||
static void CancelIdleRunnable(nsIRunnable* aRunnable);
|
||||
|
|
|
@ -3123,26 +3123,6 @@ pref("dom.idle_period.throttled_length", 10000);
|
|||
// The amount of idle time (milliseconds) reserved for a long idle period
|
||||
pref("idle_queue.long_period", 50);
|
||||
|
||||
// Control the event prioritization on content main thread
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("prioritized_input_events.enabled", true);
|
||||
#else
|
||||
pref("prioritized_input_events.enabled", false);
|
||||
#endif
|
||||
|
||||
// The maximum and minimum time (milliseconds) we reserve for handling input
|
||||
// events in each frame.
|
||||
pref("prioritized_input_events.duration.max", 8);
|
||||
pref("prioritized_input_events.duration.min", 1);
|
||||
|
||||
// The default amount of time (milliseconds) required for handling a input
|
||||
// event.
|
||||
pref("prioritized_input_events.default_duration_per_event", 1);
|
||||
|
||||
// The number of processed input events we use to predict the amount of time
|
||||
// required to process the following input events.
|
||||
pref("prioritized_input_events.count_for_prediction", 9);
|
||||
|
||||
// The minimum amount of time (milliseconds) required for an idle
|
||||
// period to be scheduled on the main thread. N.B. that
|
||||
// layout.idle_period.time_limit adds padding at the end of the idle
|
||||
|
|
|
@ -678,44 +678,6 @@ function synthesizeNativeMouseMove(aTarget, aOffsetX, aOffsetY, aCallback, aWind
|
|||
utils.sendNativeMouseMove(x * scale, y * scale, null, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper around synthesizeNativeMouseMove that waits for the mouse
|
||||
* event to be dispatched to the target content.
|
||||
*
|
||||
* This API is supposed to be used in those test cases that synthesize some
|
||||
* input events to chrome process and have some checks in content.
|
||||
*/
|
||||
function synthesizeAndWaitNativeMouseMove(aTarget, aOffsetX, aOffsetY,
|
||||
aCallback, aWindow = window) {
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
let ContentTask =
|
||||
_EU_Cu.import("resource://testing-common/ContentTask.jsm", null).ContentTask;
|
||||
|
||||
let eventRegisteredPromise = new Promise(resolve => {
|
||||
mm.addMessageListener("Test:MouseMoveRegistered", function processed(message) {
|
||||
mm.removeMessageListener("Test:MouseMoveRegistered", processed);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
let eventReceivedPromise = ContentTask.spawn(browser, [aOffsetX, aOffsetY],
|
||||
([clientX, clientY]) => {
|
||||
return new Promise(resolve => {
|
||||
addEventListener("mousemove", function onMouseMoveEvent(e) {
|
||||
if (e.clientX == clientX && e.clientY == clientY) {
|
||||
removeEventListener("mousemove", onMouseMoveEvent);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
sendAsyncMessage("Test:MouseMoveRegistered");
|
||||
});
|
||||
});
|
||||
eventRegisteredPromise.then(() => {
|
||||
synthesizeNativeMouseMove(aTarget, aOffsetX, aOffsetY, null, aWindow);
|
||||
});
|
||||
return eventReceivedPromise;
|
||||
}
|
||||
|
||||
function _computeKeyCodeFromChar(aChar)
|
||||
{
|
||||
if (aChar.length != 1) {
|
||||
|
@ -867,51 +829,6 @@ function synthesizeKey(aKey, aEvent, aWindow = window, aCallback)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper around synthesizeKey that waits for the key event to be
|
||||
* dispatched to the target content. It returns a promise which is resolved
|
||||
* when the content receives the key event.
|
||||
*
|
||||
* This API is supposed to be used in those test cases that synthesize some
|
||||
* input events to chrome process and have some checks in content.
|
||||
*/
|
||||
function synthesizeAndWaitKey(aKey, aEvent, aWindow = window,
|
||||
checkBeforeSynthesize, checkAfterSynthesize)
|
||||
{
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
let keyCode = _createKeyboardEventDictionary(aKey, aEvent, aWindow).dictionary.keyCode;
|
||||
let ContentTask = _EU_Cu.import("resource://testing-common/ContentTask.jsm", null).ContentTask;
|
||||
|
||||
let keyRegisteredPromise = new Promise(resolve => {
|
||||
mm.addMessageListener("Test:KeyRegistered", function processed(message) {
|
||||
mm.removeMessageListener("Test:KeyRegistered", processed);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
let keyReceivedPromise = ContentTask.spawn(browser, keyCode, (keyCode) => {
|
||||
return new Promise(resolve => {
|
||||
addEventListener("keyup", function onKeyEvent(e) {
|
||||
if (e.keyCode == keyCode) {
|
||||
removeEventListener("keyup", onKeyEvent);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
sendAsyncMessage("Test:KeyRegistered");
|
||||
});
|
||||
});
|
||||
keyRegisteredPromise.then(() => {
|
||||
if (checkBeforeSynthesize) {
|
||||
checkBeforeSynthesize();
|
||||
}
|
||||
synthesizeKey(aKey, aEvent, aWindow);
|
||||
if (checkAfterSynthesize) {
|
||||
checkAfterSynthesize();
|
||||
}
|
||||
});
|
||||
return keyReceivedPromise;
|
||||
}
|
||||
|
||||
function _parseNativeModifiers(aModifiers, aWindow = window)
|
||||
{
|
||||
var navigator = _getNavigator(aWindow);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "nsITimer.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -18,8 +17,7 @@ using namespace mozilla;
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsBrowserStatusFilter::nsBrowserStatusFilter()
|
||||
: mTarget(GetMainThreadEventTarget())
|
||||
, mCurProgress(0)
|
||||
: mCurProgress(0)
|
||||
, mMaxProgress(0)
|
||||
, mStatusIsDirty(true)
|
||||
, mCurrentPercentage(0)
|
||||
|
@ -114,21 +112,6 @@ nsBrowserStatusFilter::GetLoadType(uint32_t *aLoadType)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBrowserStatusFilter::GetTarget(nsIEventTarget** aTarget)
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> target = mTarget;
|
||||
target.forget(aTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBrowserStatusFilter::SetTarget(nsIEventTarget* aTarget)
|
||||
{
|
||||
mTarget = aTarget;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsBrowserStatusFilter::nsIWebProgressListener
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -379,7 +362,9 @@ nsBrowserStatusFilter::StartDelayTimer()
|
|||
if (!mTimer)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mTimer->SetTarget(mTarget);
|
||||
// Use the system group. The browser status filter is always used by chrome
|
||||
// code.
|
||||
mTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
|
||||
return mTimer->InitWithNamedFuncCallback(
|
||||
TimeoutHandler, this, 160, nsITimer::TYPE_ONE_SHOT,
|
||||
"nsBrowserStatusFilter::TimeoutHandler");
|
||||
|
|
|
@ -46,7 +46,6 @@ private:
|
|||
|
||||
private:
|
||||
nsCOMPtr<nsIWebProgressListener> mListener;
|
||||
nsCOMPtr<nsIEventTarget> mTarget;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
// delayed values
|
||||
|
|
|
@ -34,7 +34,9 @@ async function do_test(test) {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
|
||||
|
||||
info("Moving mouse out of the way.");
|
||||
await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 300, 300);
|
||||
await new Promise(resolve => {
|
||||
EventUtils.synthesizeNativeMouseMove(tab.linkedBrowser, 300, 300, resolve);
|
||||
});
|
||||
|
||||
info("creating input field");
|
||||
await ContentTask.spawn(tab.linkedBrowser, test, async function(test) {
|
||||
|
@ -90,11 +92,15 @@ async function do_test(test) {
|
|||
}, {once: true});
|
||||
});
|
||||
info("Initial mouse move");
|
||||
await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 50, 5);
|
||||
await new Promise(resolve => {
|
||||
EventUtils.synthesizeNativeMouseMove(tab.linkedBrowser, 50, 5, resolve);
|
||||
});
|
||||
info("Waiting");
|
||||
await new Promise(resolve => setTimeout(resolve, 400));
|
||||
info("Second mouse move");
|
||||
await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 70, 5);
|
||||
await new Promise(resolve => {
|
||||
EventUtils.synthesizeNativeMouseMove(tab.linkedBrowser, 70, 5, resolve);
|
||||
});
|
||||
info("Waiting for tooltip to open");
|
||||
let tooltip = await awaitTooltipOpen;
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ var WebProgressListener = {
|
|||
this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
|
||||
.createInstance(Ci.nsIWebProgress);
|
||||
this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||
this._filter.target = tabEventTarget;
|
||||
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
|
|
|
@ -175,11 +175,7 @@ add_task(async function() {
|
|||
let findBar = gFindBar;
|
||||
let initialValue = findBar._findField.value;
|
||||
|
||||
await EventUtils.synthesizeAndWaitKey("f", { accelKey: true }, window, null,
|
||||
() => {
|
||||
isnot(document.activeElement, findBar._findField.inputField,
|
||||
"findbar is not yet focused");
|
||||
});
|
||||
EventUtils.synthesizeKey("f", { accelKey: true }, window);
|
||||
|
||||
let promises = [
|
||||
BrowserTestUtils.sendChar("a", browser),
|
||||
|
@ -187,6 +183,8 @@ add_task(async function() {
|
|||
BrowserTestUtils.sendChar("c", browser)
|
||||
];
|
||||
|
||||
isnot(document.activeElement, findBar._findField.inputField,
|
||||
"findbar is not yet focused");
|
||||
is(findBar._findField.value, initialValue, "still has initial find query");
|
||||
|
||||
await Promise.all(promises);
|
||||
|
|
|
@ -22,7 +22,6 @@ module.exports = {
|
|||
removeWeakMessageListener: false,
|
||||
sendAsyncMessage: false,
|
||||
sendSyncMessage: false,
|
||||
sendRpcMessage: false,
|
||||
tabEventTarget: false
|
||||
sendRpcMessage: false
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nspr.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
|
||||
|
@ -981,27 +980,6 @@ nsDocLoader::GetLoadType(uint32_t *aLoadType)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocLoader::GetTarget(nsIEventTarget** aTarget)
|
||||
{
|
||||
nsCOMPtr<mozIDOMWindowProxy> window;
|
||||
nsresult rv = GetDOMWindow(getter_AddRefs(window));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> piwindow = nsPIDOMWindowOuter::From(window);
|
||||
NS_ENSURE_STATE(piwindow);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = piwindow->TabGroup()->EventTargetFor(mozilla::TaskCategory::Other);
|
||||
target.forget(aTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocLoader::SetTarget(nsIEventTarget* aTarget)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
int64_t nsDocLoader::GetMaxTotalProgress()
|
||||
{
|
||||
int64_t newMaxTotal = 0;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
interface mozIDOMWindowProxy;
|
||||
interface nsIEventTarget;
|
||||
interface nsIWebProgressListener;
|
||||
|
||||
/**
|
||||
|
@ -152,11 +151,4 @@ interface nsIWebProgress : nsISupports
|
|||
* nsIDocShellLoadInfo.idl.
|
||||
*/
|
||||
readonly attribute unsigned long loadType;
|
||||
|
||||
/**
|
||||
* Main thread event target to which progress updates should be
|
||||
* dispatched. This typically will be a SchedulerEventTarget
|
||||
* corresponding to the tab requesting updates.
|
||||
*/
|
||||
attribute nsIEventTarget target;
|
||||
};
|
||||
|
|
|
@ -100,16 +100,6 @@ function onEvent(aEvent)
|
|||
setTimeout(gCallback, 0);
|
||||
}
|
||||
|
||||
function observeKeyUpOnContent(aKeyCode, aCallback)
|
||||
{
|
||||
document.addEventListener("keyup", function keyUp(ev) {
|
||||
if (ev.keyCode == aKeyCode) {
|
||||
document.removeEventListener("keyup", keyUp);
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const kTests = [
|
||||
{ description: "InternalScrollPortEvent (overflow, vertical)",
|
||||
targetID: "scrollable-div", eventType: "overflow",
|
||||
|
@ -160,8 +150,6 @@ const kTests = [
|
|||
document.getElementById(this.targetID).focus();
|
||||
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_A : MAC_VK_ANSI_A,
|
||||
{}, "a", "a");
|
||||
observeKeyUpOnContent(KeyboardEvent.DOM_VK_A, runNextTest);
|
||||
return true;
|
||||
},
|
||||
canRun: function () {
|
||||
return (kIsMac || kIsWin);
|
||||
|
@ -175,8 +163,6 @@ const kTests = [
|
|||
document.getElementById(this.targetID).focus();
|
||||
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_A : MAC_VK_ANSI_A,
|
||||
{}, "a", "a");
|
||||
observeKeyUpOnContent(KeyboardEvent.DOM_VK_A, runNextTest);
|
||||
return true;
|
||||
},
|
||||
canRun: function () {
|
||||
return (kIsMac || kIsWin);
|
||||
|
@ -190,8 +176,6 @@ const kTests = [
|
|||
document.getElementById(this.targetID).focus();
|
||||
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_B : MAC_VK_ANSI_B,
|
||||
{ shiftKey: true }, "B", "B");
|
||||
observeKeyUpOnContent(KeyboardEvent.DOM_VK_B, runNextTest);
|
||||
return true;
|
||||
},
|
||||
canRun: function () {
|
||||
return (kIsMac || kIsWin);
|
||||
|
@ -205,14 +189,6 @@ const kTests = [
|
|||
document.getElementById(this.targetID).focus();
|
||||
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_C : MAC_VK_ANSI_C,
|
||||
{ accelKey: true }, kIsWin ? "\u0003" : "c", "c");
|
||||
|
||||
// On Windows, synthesizeNativeKey will also fire keyup for accelKey
|
||||
// (control key on Windows). We have to wait for it to prevent the key
|
||||
// event break the next test case.
|
||||
let waitKeyCode = _EU_isWin(window) ? KeyboardEvent.DOM_VK_CONTROL :
|
||||
KeyboardEvent.DOM_VK_C;
|
||||
observeKeyUpOnContent(waitKeyCode, runNextTest);
|
||||
return true;
|
||||
},
|
||||
canRun: function () {
|
||||
return (kIsMac || kIsWin);
|
||||
|
@ -349,8 +325,6 @@ const kTests = [
|
|||
document.getElementById(this.targetID).focus();
|
||||
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, kIsWin ? WIN_VK_B : MAC_VK_ANSI_B,
|
||||
{ shiftKey: true }, "B", "B");
|
||||
observeKeyUpOnContent(KeyboardEvent.DOM_VK_B, runNextTest);
|
||||
return true;
|
||||
},
|
||||
canRun: function () {
|
||||
return (kIsMac || kIsWin);
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "InputEventStatistics.h"
|
||||
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
TimeDuration
|
||||
InputEventStatistics::TimeDurationCircularBuffer::GetMean()
|
||||
{
|
||||
return mTotal / (int64_t)mSize;
|
||||
}
|
||||
|
||||
InputEventStatistics::InputEventStatistics()
|
||||
: mEnable(false)
|
||||
{
|
||||
MOZ_ASSERT(Preferences::IsServiceAvailable());
|
||||
uint32_t inputDuration =
|
||||
Preferences::GetUint("prioritized_input_events.default_duration_per_event",
|
||||
sDefaultInputDuration);
|
||||
|
||||
TimeDuration defaultDuration = TimeDuration::FromMilliseconds(inputDuration);
|
||||
|
||||
uint32_t count =
|
||||
Preferences::GetUint("prioritized_input_events.count_for_prediction",
|
||||
sInputCountForPrediction);
|
||||
|
||||
mLastInputDurations =
|
||||
MakeUnique<TimeDurationCircularBuffer>(count, defaultDuration);
|
||||
|
||||
uint32_t maxDuration =
|
||||
Preferences::GetUint("prioritized_input_events.duration.max",
|
||||
sMaxReservedTimeForHandlingInput);
|
||||
|
||||
uint32_t minDuration =
|
||||
Preferences::GetUint("prioritized_input_events.duration.min",
|
||||
sMinReservedTimeForHandlingInput);
|
||||
|
||||
mMaxInputDuration = TimeDuration::FromMilliseconds(maxDuration);
|
||||
mMinInputDuration = TimeDuration::FromMilliseconds(minDuration);
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
InputEventStatistics::GetInputHandlingStartTime(uint32_t aInputCount)
|
||||
{
|
||||
MOZ_ASSERT(mEnable);
|
||||
Maybe<TimeStamp> nextTickHint = nsRefreshDriver::GetNextTickHint();
|
||||
|
||||
if (nextTickHint.isNothing()) {
|
||||
// Return a past time to process input events immediately.
|
||||
return TimeStamp::Now() - TimeDuration::FromMilliseconds(1);
|
||||
}
|
||||
TimeDuration inputCost = mLastInputDurations->GetMean() * aInputCount;
|
||||
inputCost = inputCost > mMaxInputDuration
|
||||
? mMaxInputDuration
|
||||
: inputCost < mMinInputDuration
|
||||
? mMinInputDuration
|
||||
: inputCost;
|
||||
|
||||
return nextTickHint.value() - inputCost;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -1,114 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#if !defined(InputEventStatistics_h_)
|
||||
#define InputEventStatistics_h_
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class InputEventStatistics
|
||||
{
|
||||
// The default amount of time (milliseconds) required for handling a input
|
||||
// event.
|
||||
static const uint16_t sDefaultInputDuration = 1;
|
||||
|
||||
// The number of processed input events we use to predict the amount of time
|
||||
// required to process the following input events.
|
||||
static const uint16_t sInputCountForPrediction = 9;
|
||||
|
||||
// The default maximum and minimum time (milliseconds) we reserve for handling
|
||||
// input events in each frame.
|
||||
static const uint16_t sMaxReservedTimeForHandlingInput = 8;
|
||||
static const uint16_t sMinReservedTimeForHandlingInput = 1;
|
||||
|
||||
class TimeDurationCircularBuffer
|
||||
{
|
||||
int16_t mSize;
|
||||
int16_t mCurrentIndex;
|
||||
nsTArray<TimeDuration> mBuffer;
|
||||
TimeDuration mTotal;
|
||||
|
||||
public:
|
||||
TimeDurationCircularBuffer(uint32_t aSize, TimeDuration& aDefaultValue)
|
||||
: mSize(aSize)
|
||||
, mCurrentIndex(0)
|
||||
{
|
||||
mSize = mSize == 0 ? sInputCountForPrediction : mSize;
|
||||
for (int16_t index = 0; index < mSize; ++index) {
|
||||
mBuffer.AppendElement(aDefaultValue);
|
||||
mTotal += aDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
void Insert(TimeDuration& aDuration)
|
||||
{
|
||||
mTotal += (aDuration - mBuffer[mCurrentIndex]);
|
||||
mBuffer[mCurrentIndex++] = aDuration;
|
||||
if (mCurrentIndex == mSize) {
|
||||
mCurrentIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TimeDuration GetMean();
|
||||
};
|
||||
|
||||
UniquePtr<TimeDurationCircularBuffer> mLastInputDurations;
|
||||
TimeDuration mMaxInputDuration;
|
||||
TimeDuration mMinInputDuration;
|
||||
bool mEnable;
|
||||
|
||||
InputEventStatistics();
|
||||
~InputEventStatistics()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static InputEventStatistics& Get()
|
||||
{
|
||||
static InputEventStatistics sInstance;
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
void UpdateInputDuration(TimeDuration aDuration)
|
||||
{
|
||||
if (!mEnable) {
|
||||
return;
|
||||
}
|
||||
mLastInputDurations->Insert(aDuration);
|
||||
}
|
||||
|
||||
TimeStamp GetInputHandlingStartTime(uint32_t aInputCount);
|
||||
|
||||
void SetEnable(bool aEnable)
|
||||
{
|
||||
mEnable = aEnable;
|
||||
}
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoTimeDurationHelper final
|
||||
{
|
||||
public:
|
||||
AutoTimeDurationHelper()
|
||||
{
|
||||
mStartTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
~AutoTimeDurationHelper()
|
||||
{
|
||||
InputEventStatistics::Get().UpdateInputDuration(TimeStamp::Now() - mStartTime);
|
||||
}
|
||||
|
||||
private:
|
||||
TimeStamp mStartTime;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // InputEventStatistics_h_
|
|
@ -513,18 +513,6 @@ LazyIdleThread::IdleDispatch(already_AddRefed<nsIRunnable> aEvent)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LazyIdleThread::EnableEventPrioritization()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LazyIdleThread::IsEventPrioritizationEnabled(bool* aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LazyIdleThread::RegisterIdlePeriod(already_AddRefed<nsIIdlePeriod> aIdlePeriod)
|
||||
{
|
||||
|
|
|
@ -364,17 +364,8 @@ SchedulerGroup::Runnable::Run()
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SchedulerGroup::Runnable::GetPriority(uint32_t* aPriority)
|
||||
{
|
||||
*aPriority = nsIRunnablePriority::PRIORITY_NORMAL;
|
||||
nsCOMPtr<nsIRunnablePriority> runnablePrio = do_QueryInterface(mRunnable);
|
||||
return runnablePrio ? runnablePrio->GetPriority(aPriority) : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(SchedulerGroup::Runnable,
|
||||
mozilla::Runnable,
|
||||
nsIRunnablePriority,
|
||||
SchedulerGroup::Runnable)
|
||||
|
||||
SchedulerGroup::AutoProcessEvent::AutoProcessEvent()
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
MOZ_ASSERT(IsSafeToRun());
|
||||
}
|
||||
|
||||
class Runnable final : public mozilla::Runnable, public nsIRunnablePriority
|
||||
class Runnable final : public mozilla::Runnable
|
||||
{
|
||||
public:
|
||||
Runnable(already_AddRefed<nsIRunnable>&& aRunnable,
|
||||
|
@ -95,7 +95,6 @@ public:
|
|||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIRUNNABLEPRIORITY
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_SCHEDULERGROUPRUNNABLE_IID);
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -111,8 +110,7 @@ private:
|
|||
}
|
||||
|
||||
static bool
|
||||
UniquePtrLessThan(mozilla::UniquePtr<Entry>& aLeft,
|
||||
mozilla::UniquePtr<Entry>& aRight)
|
||||
UniquePtrLessThan(UniquePtr<Entry>& aLeft, UniquePtr<Entry>& aRight)
|
||||
{
|
||||
// This is reversed because std::push_heap() sorts the "largest" to
|
||||
// the front of the heap. We want that to be the earliest timer.
|
||||
|
@ -125,7 +123,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
nsTArray<mozilla::UniquePtr<Entry>> mTimers;
|
||||
nsTArray<UniquePtr<Entry>> mTimers;
|
||||
uint32_t mAllowedEarlyFiringMicroseconds;
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ EXPORTS.mozilla += [
|
|||
'DeadlockDetector.h',
|
||||
'HangAnnotations.h',
|
||||
'HangMonitor.h',
|
||||
'InputEventStatistics.h',
|
||||
'LazyIdleThread.h',
|
||||
'MainThreadIdlePeriod.h',
|
||||
'Monitor.h',
|
||||
|
@ -70,7 +69,6 @@ UNIFIED_SOURCES += [
|
|||
'BlockingResourceBase.cpp',
|
||||
'HangAnnotations.cpp',
|
||||
'HangMonitor.cpp',
|
||||
'InputEventStatistics.cpp',
|
||||
'LazyIdleThread.cpp',
|
||||
'MainThreadIdlePeriod.cpp',
|
||||
'nsEnvironment.cpp',
|
||||
|
|
|
@ -18,11 +18,10 @@ interface nsIRunnable : nsISupports
|
|||
void run();
|
||||
};
|
||||
|
||||
[scriptable, uuid(e75aa42a-80a9-11e6-afb5-e89d87348e2c)]
|
||||
[uuid(e75aa42a-80a9-11e6-afb5-e89d87348e2c)]
|
||||
interface nsIRunnablePriority : nsISupports
|
||||
{
|
||||
const unsigned short PRIORITY_NORMAL = 0;
|
||||
const unsigned short PRIORITY_INPUT = 1;
|
||||
const unsigned short PRIORITY_HIGH = 2;
|
||||
const unsigned short PRIORITY_HIGH = 1;
|
||||
readonly attribute unsigned long priority;
|
||||
};
|
||||
|
|
|
@ -152,9 +152,6 @@ interface nsIThread : nsISerialEventTarget
|
|||
*/
|
||||
[noscript] void idleDispatch(in alreadyAddRefed_nsIRunnable event);
|
||||
|
||||
[noscript] void enableEventPrioritization();
|
||||
[noscript] bool isEventPrioritizationEnabled();
|
||||
|
||||
/**
|
||||
* Use this attribute to dispatch runnables to the thread. Eventually, the
|
||||
* eventTarget attribute will be the only way to dispatch events to a
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
[ptr] native PRThread(PRThread);
|
||||
|
||||
interface nsIEventTarget;
|
||||
interface nsIRunnable;
|
||||
interface nsIThread;
|
||||
|
||||
|
@ -93,7 +92,7 @@ interface nsIThreadManager : nsISupports
|
|||
* .currentThread.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL);
|
||||
* C++ callers should instead use NS_DispatchToMainThread.
|
||||
*/
|
||||
void dispatchToMainThread(in nsIRunnable event, [optional] in uint32_t priority);
|
||||
void dispatchToMainThread(in nsIRunnable event);
|
||||
|
||||
/**
|
||||
* This queues a runnable to the main thread's idle queue.
|
||||
|
@ -127,9 +126,4 @@ interface nsIThreadManager : nsISupports
|
|||
* moving away from.
|
||||
*/
|
||||
void spinEventLoopUntilEmpty();
|
||||
|
||||
/**
|
||||
* Return the SchedulerEventTarget for the SystemGroup.
|
||||
*/
|
||||
readonly attribute nsIEventTarget systemGroupEventTarget;
|
||||
};
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "nsThreadSyncDispatch.h"
|
||||
#include "LeakRefPtr.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "InputEventStatistics.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
@ -816,156 +815,45 @@ nsThread::DispatchInternal(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags
|
|||
return PutEvent(event.take(), aTarget);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsThread::nsChainedEventQueue::EnablePrioritizationRunnable,
|
||||
nsIRunnable)
|
||||
|
||||
void
|
||||
nsThread::nsChainedEventQueue::EnablePrioritization(MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
MOZ_ASSERT(!mIsInputPrioritizationEnabled);
|
||||
// When enabling event prioritization, there may be some pending events with
|
||||
// different priorities in the normal queue. Create an event in the normal
|
||||
// queue to consume all pending events in the time order to make sure we won't
|
||||
// preempt a pending event (e.g. input) in the normal queue by another newly
|
||||
// created event with the same priority.
|
||||
mNormalQueue->PutEvent(new EnablePrioritizationRunnable(this), aProofOfLock);
|
||||
mInputHandlingStartTime = TimeStamp();
|
||||
mIsInputPrioritizationEnabled = true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsThread::nsChainedEventQueue::
|
||||
GetNormalOrInputOrHighPriorityEvent(bool aMayWait, nsIRunnable** aEvent,
|
||||
nsThread::nsChainedEventQueue::GetEvent(bool aMayWait, nsIRunnable** aEvent,
|
||||
unsigned short* aPriority,
|
||||
MutexAutoLock& aProofOfLock)
|
||||
mozilla::MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
bool retVal = false;
|
||||
do {
|
||||
// Use mProcessHighPriorityQueueRunnable to prevent the high priority events
|
||||
// from consuming all cpu time and causing starvation.
|
||||
if (mProcessHighPriorityQueueRunnable) {
|
||||
MOZ_ASSERT(mHighQueue->HasPendingEvent(aProofOfLock));
|
||||
retVal = mHighQueue->GetEvent(false, aEvent, aProofOfLock);
|
||||
if (mProcessSecondaryQueueRunnable) {
|
||||
MOZ_ASSERT(mSecondaryQueue->HasPendingEvent(aProofOfLock));
|
||||
retVal = mSecondaryQueue->GetEvent(aMayWait, aEvent, aProofOfLock);
|
||||
MOZ_ASSERT(*aEvent);
|
||||
SetPriorityIfNotNull(aPriority, nsIRunnablePriority::PRIORITY_HIGH);
|
||||
mInputHandlingStartTime = TimeStamp();
|
||||
mProcessHighPriorityQueueRunnable = false;
|
||||
if (aPriority) {
|
||||
*aPriority = nsIRunnablePriority::PRIORITY_HIGH;
|
||||
}
|
||||
mProcessSecondaryQueueRunnable = false;
|
||||
return retVal;
|
||||
}
|
||||
mProcessHighPriorityQueueRunnable =
|
||||
mHighQueue->HasPendingEvent(aProofOfLock);
|
||||
|
||||
uint32_t pendingInputCount = mInputQueue->Count(aProofOfLock);
|
||||
if (pendingInputCount > 0) {
|
||||
if (mInputHandlingStartTime.IsNull()) {
|
||||
mInputHandlingStartTime =
|
||||
InputEventStatistics::Get()
|
||||
.GetInputHandlingStartTime(mInputQueue->Count(aProofOfLock));
|
||||
}
|
||||
if (TimeStamp::Now() > mInputHandlingStartTime) {
|
||||
retVal = mInputQueue->GetEvent(false, aEvent, aProofOfLock);
|
||||
MOZ_ASSERT(*aEvent);
|
||||
SetPriorityIfNotNull(aPriority, nsIRunnablePriority::PRIORITY_INPUT);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want to wait if there are some high priority events or input
|
||||
// events in the queues.
|
||||
bool reallyMayWait = aMayWait && !mProcessHighPriorityQueueRunnable &&
|
||||
pendingInputCount == 0;
|
||||
|
||||
retVal = mNormalQueue->GetEvent(reallyMayWait, aEvent, aProofOfLock);
|
||||
if (*aEvent) {
|
||||
// We got an event, return early.
|
||||
SetPriorityIfNotNull(aPriority, nsIRunnablePriority::PRIORITY_NORMAL);
|
||||
return retVal;
|
||||
// We don't want to wait if mSecondaryQueue has some events.
|
||||
bool reallyMayWait =
|
||||
aMayWait && !mSecondaryQueue->HasPendingEvent(aProofOfLock);
|
||||
retVal =
|
||||
mNormalQueue->GetEvent(reallyMayWait, aEvent, aProofOfLock);
|
||||
if (aPriority) {
|
||||
*aPriority = nsIRunnablePriority::PRIORITY_NORMAL;
|
||||
}
|
||||
if (pendingInputCount > 0 && !mProcessHighPriorityQueueRunnable) {
|
||||
// Handle input events if we have time for them.
|
||||
MOZ_ASSERT(mInputQueue->HasPendingEvent(aProofOfLock));
|
||||
retVal = mInputQueue->GetEvent(false, aEvent, aProofOfLock);
|
||||
MOZ_ASSERT(*aEvent);
|
||||
SetPriorityIfNotNull(aPriority, nsIRunnablePriority::PRIORITY_INPUT);
|
||||
return retVal;
|
||||
}
|
||||
} while (aMayWait || mProcessHighPriorityQueueRunnable);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool
|
||||
nsThread::nsChainedEventQueue::
|
||||
GetNormalOrHighPriorityEvent(bool aMayWait, nsIRunnable** aEvent,
|
||||
unsigned short* aPriority,
|
||||
MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
bool retVal = false;
|
||||
do {
|
||||
// Use mProcessHighPriorityQueueRunnable to prevent the high priority events
|
||||
// from consuming all cpu time and causing starvation.
|
||||
if (mProcessHighPriorityQueueRunnable) {
|
||||
MOZ_ASSERT(mHighQueue->HasPendingEvent(aProofOfLock));
|
||||
retVal = mHighQueue->GetEvent(false, aEvent, aProofOfLock);
|
||||
MOZ_ASSERT(*aEvent);
|
||||
SetPriorityIfNotNull(aPriority, nsIRunnablePriority::PRIORITY_HIGH);
|
||||
mProcessHighPriorityQueueRunnable = false;
|
||||
return retVal;
|
||||
}
|
||||
mProcessHighPriorityQueueRunnable =
|
||||
mHighQueue->HasPendingEvent(aProofOfLock);
|
||||
|
||||
// We don't want to wait if there are some events in the high priority
|
||||
// Let's see if we should next time process an event from the secondary
|
||||
// queue.
|
||||
bool reallyMayWait = aMayWait && !mProcessHighPriorityQueueRunnable;
|
||||
mProcessSecondaryQueueRunnable =
|
||||
mSecondaryQueue->HasPendingEvent(aProofOfLock);
|
||||
|
||||
retVal = mNormalQueue->GetEvent(reallyMayWait, aEvent, aProofOfLock);
|
||||
if (*aEvent) {
|
||||
// We got an event, return early.
|
||||
SetPriorityIfNotNull(aPriority, nsIRunnablePriority::PRIORITY_NORMAL);
|
||||
return retVal;
|
||||
}
|
||||
} while (aMayWait || mProcessHighPriorityQueueRunnable);
|
||||
return retVal;
|
||||
}
|
||||
} while(aMayWait || mProcessSecondaryQueueRunnable);
|
||||
|
||||
void
|
||||
nsThread::nsChainedEventQueue::PutEvent(already_AddRefed<nsIRunnable> aEvent,
|
||||
MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
RefPtr<nsIRunnable> event(aEvent);
|
||||
nsCOMPtr<nsIRunnablePriority> runnablePrio(do_QueryInterface(event));
|
||||
uint32_t prio = nsIRunnablePriority::PRIORITY_NORMAL;
|
||||
if (runnablePrio) {
|
||||
runnablePrio->GetPriority(&prio);
|
||||
}
|
||||
switch (prio) {
|
||||
case nsIRunnablePriority::PRIORITY_NORMAL:
|
||||
mNormalQueue->PutEvent(event.forget(), aProofOfLock);
|
||||
break;
|
||||
case nsIRunnablePriority::PRIORITY_INPUT:
|
||||
if (mIsInputPrioritizationEnabled) {
|
||||
mInputQueue->PutEvent(event.forget(), aProofOfLock);
|
||||
} else {
|
||||
mNormalQueue->PutEvent(event.forget(), aProofOfLock);
|
||||
}
|
||||
break;
|
||||
case nsIRunnablePriority::PRIORITY_HIGH:
|
||||
if (mIsInputPrioritizationEnabled) {
|
||||
mHighQueue->PutEvent(event.forget(), aProofOfLock);
|
||||
} else {
|
||||
// During startup, ContentParent sends SetXPCOMProcessAttributes to
|
||||
// initialize ContentChild and enable input event prioritization. After
|
||||
// that, ContentParent sends PBrowserConstructor to create PBrowserChild.
|
||||
// To prevent PBrowserConstructor preempt SetXPCOMProcessAttributes and
|
||||
// cause problems, we have to put high priority events in mNormalQueue to
|
||||
// keep the correct order of initialization.
|
||||
mNormalQueue->PutEvent(event.forget(), aProofOfLock);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1277,24 +1165,6 @@ nsThread::IdleDispatch(already_AddRefed<nsIRunnable> aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThread::EnableEventPrioritization()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MutexAutoLock lock(mLock);
|
||||
// Only support event prioritization for main event queue.
|
||||
mEventsRoot.EnablePrioritization(lock);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThread::IsEventPrioritizationEnabled(bool* aResult)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
*aResult = mEventsRoot.IsPrioritizationEnabled();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_CANARY
|
||||
void canary_alarm_handler(int signum);
|
||||
|
||||
|
@ -1572,10 +1442,7 @@ nsThread::ProcessNextEvent(bool aMayWait, bool* aResult)
|
|||
sMainThreadRunnableName[length] = '\0';
|
||||
}
|
||||
#endif
|
||||
Maybe<AutoTimeDurationHelper> timeDurationHelper;
|
||||
if (priority == nsIRunnablePriority::PRIORITY_INPUT) {
|
||||
timeDurationHelper.emplace();
|
||||
}
|
||||
|
||||
event->Run();
|
||||
} else if (aMayWait) {
|
||||
MOZ_ASSERT(ShuttingDown(),
|
||||
|
|
|
@ -97,16 +97,6 @@ public:
|
|||
static const uint32_t kRunnableNameBufSize = 1000;
|
||||
static mozilla::Array<char, kRunnableNameBufSize> sMainThreadRunnableName;
|
||||
|
||||
// Query whether there are some pending input events in the queue. This method
|
||||
// is supposed to be called on main thread with input event prioritization
|
||||
// enabled.
|
||||
bool HasPendingInputEvents()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
return mEventsRoot.HasPendingEventsInInputQueue(lock);
|
||||
}
|
||||
|
||||
private:
|
||||
void DoMainThreadSpecificProcessing(bool aReallyWait);
|
||||
|
||||
|
@ -152,43 +142,27 @@ protected:
|
|||
|
||||
struct nsThreadShutdownContext* ShutdownInternal(bool aSync);
|
||||
|
||||
// Wrapper for nsEventQueue that supports chaining and prioritization.
|
||||
// Wrapper for nsEventQueue that supports chaining.
|
||||
class nsChainedEventQueue
|
||||
{
|
||||
public:
|
||||
explicit nsChainedEventQueue(mozilla::Mutex& aLock)
|
||||
: mNext(nullptr)
|
||||
, mEventsAvailable(aLock, "[nsChainedEventQueue.mEventsAvailable]")
|
||||
, mIsInputPrioritizationEnabled(false)
|
||||
, mIsReadyToPrioritizeEvents(false)
|
||||
, mProcessHighPriorityQueueRunnable(false)
|
||||
, mProcessSecondaryQueueRunnable(false)
|
||||
{
|
||||
mNormalQueue =
|
||||
mozilla::MakeUnique<nsEventQueue>(mEventsAvailable,
|
||||
nsEventQueue::eSharedCondVarQueue);
|
||||
// All queues need to use the same CondVar!
|
||||
mInputQueue =
|
||||
// Both queues need to use the same CondVar!
|
||||
mSecondaryQueue =
|
||||
mozilla::MakeUnique<nsEventQueue>(mEventsAvailable,
|
||||
nsEventQueue::eSharedCondVarQueue);
|
||||
mHighQueue =
|
||||
mozilla::MakeUnique<nsEventQueue>(mEventsAvailable,
|
||||
nsEventQueue::eSharedCondVarQueue);
|
||||
}
|
||||
|
||||
void EnablePrioritization(mozilla::MutexAutoLock& aProofOfLock);
|
||||
|
||||
bool IsPrioritizationEnabled()
|
||||
{
|
||||
return mIsInputPrioritizationEnabled;
|
||||
}
|
||||
|
||||
bool GetEvent(bool aMayWait, nsIRunnable** aEvent,
|
||||
unsigned short* aPriority,
|
||||
mozilla::MutexAutoLock& aProofOfLock) {
|
||||
return mIsReadyToPrioritizeEvents
|
||||
? GetNormalOrInputOrHighPriorityEvent(aMayWait, aEvent, aPriority, aProofOfLock)
|
||||
: GetNormalOrHighPriorityEvent(aMayWait, aEvent, aPriority, aProofOfLock);
|
||||
}
|
||||
mozilla::MutexAutoLock& aProofOfLock);
|
||||
|
||||
void PutEvent(nsIRunnable* aEvent, mozilla::MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
|
@ -197,82 +171,43 @@ protected:
|
|||
}
|
||||
|
||||
void PutEvent(already_AddRefed<nsIRunnable> aEvent,
|
||||
mozilla::MutexAutoLock& aProofOfLock);
|
||||
mozilla::MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
RefPtr<nsIRunnable> event(aEvent);
|
||||
nsCOMPtr<nsIRunnablePriority> runnablePrio =
|
||||
do_QueryInterface(event);
|
||||
uint32_t prio = nsIRunnablePriority::PRIORITY_NORMAL;
|
||||
if (runnablePrio) {
|
||||
runnablePrio->GetPriority(&prio);
|
||||
}
|
||||
MOZ_ASSERT(prio == nsIRunnablePriority::PRIORITY_NORMAL ||
|
||||
prio == nsIRunnablePriority::PRIORITY_HIGH);
|
||||
if (prio == nsIRunnablePriority::PRIORITY_NORMAL) {
|
||||
mNormalQueue->PutEvent(event.forget(), aProofOfLock);
|
||||
} else {
|
||||
mSecondaryQueue->PutEvent(event.forget(), aProofOfLock);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasPendingEvent(mozilla::MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
return mNormalQueue->HasPendingEvent(aProofOfLock) ||
|
||||
mInputQueue->HasPendingEvent(aProofOfLock) ||
|
||||
mHighQueue->HasPendingEvent(aProofOfLock);
|
||||
}
|
||||
|
||||
bool HasPendingEventsInInputQueue(mozilla::MutexAutoLock& aProofOfLock)
|
||||
{
|
||||
MOZ_ASSERT(mIsInputPrioritizationEnabled);
|
||||
return mInputQueue->HasPendingEvent(aProofOfLock);
|
||||
mSecondaryQueue->HasPendingEvent(aProofOfLock);
|
||||
}
|
||||
|
||||
nsChainedEventQueue* mNext;
|
||||
RefPtr<nsNestedEventTarget> mEventTarget;
|
||||
|
||||
private:
|
||||
bool GetNormalOrInputOrHighPriorityEvent(bool aMayWait,
|
||||
nsIRunnable** aEvent,
|
||||
unsigned short* aPriority,
|
||||
mozilla::MutexAutoLock& aProofOfLock);
|
||||
|
||||
bool GetNormalOrHighPriorityEvent(bool aMayWait, nsIRunnable** aEvent,
|
||||
unsigned short* aPriority,
|
||||
mozilla::MutexAutoLock& aProofOfLock);
|
||||
|
||||
// This is used to flush pending events in nsChainedEventQueue::mNormalQueue
|
||||
// before starting event prioritization.
|
||||
class EnablePrioritizationRunnable final : public nsIRunnable
|
||||
{
|
||||
nsChainedEventQueue* mEventQueue;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit EnablePrioritizationRunnable(nsChainedEventQueue* aQueue)
|
||||
: mEventQueue(aQueue)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
mEventQueue->mIsReadyToPrioritizeEvents = true;
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
~EnablePrioritizationRunnable()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static void SetPriorityIfNotNull(unsigned short* aPriority, short aValue)
|
||||
{
|
||||
if (aPriority) {
|
||||
*aPriority = aValue;
|
||||
}
|
||||
}
|
||||
mozilla::CondVar mEventsAvailable;
|
||||
mozilla::TimeStamp mInputHandlingStartTime;
|
||||
mozilla::UniquePtr<nsEventQueue> mNormalQueue;
|
||||
mozilla::UniquePtr<nsEventQueue> mInputQueue;
|
||||
mozilla::UniquePtr<nsEventQueue> mHighQueue;
|
||||
bool mIsInputPrioritizationEnabled;
|
||||
mozilla::UniquePtr<nsEventQueue> mSecondaryQueue;
|
||||
|
||||
// When enabling input event prioritization, there may be some events in the
|
||||
// queue. We have to process all of them before the new coming events to
|
||||
// prevent the queued events are preempted by the newly ones with the same
|
||||
// priority.
|
||||
bool mIsReadyToPrioritizeEvents;
|
||||
// Try to process one high priority runnable after each normal
|
||||
// priority runnable. This gives the processing model HTML spec has for
|
||||
// 'Update the rendering' in the case only vsync messages are in the
|
||||
// secondary queue and prevents starving the normal queue.
|
||||
bool mProcessHighPriorityQueueRunnable;
|
||||
bool mProcessSecondaryQueueRunnable;
|
||||
};
|
||||
|
||||
class nsNestedEventTarget final : public nsIEventTarget
|
||||
|
|
|
@ -11,10 +11,7 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/InputEventStatistics.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "mozilla/ThreadLocal.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#ifdef MOZ_CANARY
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
@ -330,7 +327,7 @@ NS_IMETHODIMP
|
|||
nsThreadManager::GetCurrentThread(nsIThread** aResult)
|
||||
{
|
||||
// Keep this functioning during Shutdown
|
||||
if (!mMainThread) {
|
||||
if (NS_WARN_IF(!mMainThread)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
*aResult = GetCurrentThread();
|
||||
|
@ -379,14 +376,6 @@ nsThreadManager::SpinEventLoopUntilEmpty()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThreadManager::GetSystemGroupEventTarget(nsIEventTarget** aTarget)
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> target = SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
target.forget(aTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsThreadManager::GetHighestNumberOfThreads()
|
||||
{
|
||||
|
@ -395,7 +384,7 @@ nsThreadManager::GetHighestNumberOfThreads()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThreadManager::DispatchToMainThread(nsIRunnable *aEvent, uint32_t aPriority)
|
||||
nsThreadManager::DispatchToMainThread(nsIRunnable *aEvent)
|
||||
{
|
||||
// Note: C++ callers should instead use NS_DispatchToMainThread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -404,33 +393,10 @@ nsThreadManager::DispatchToMainThread(nsIRunnable *aEvent, uint32_t aPriority)
|
|||
if (NS_WARN_IF(!mMainThread)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
if (aPriority != nsIRunnablePriority::PRIORITY_NORMAL) {
|
||||
nsCOMPtr<nsIRunnable> event(aEvent);
|
||||
return mMainThread->DispatchFromScript(
|
||||
new PrioritizableRunnable(event.forget(), aPriority), 0);
|
||||
}
|
||||
|
||||
return mMainThread->DispatchFromScript(aEvent, 0);
|
||||
}
|
||||
|
||||
void
|
||||
nsThreadManager::EnableMainThreadEventPrioritization()
|
||||
{
|
||||
static bool sIsInitialized = false;
|
||||
if (sIsInitialized) {
|
||||
return;
|
||||
}
|
||||
sIsInitialized = true;
|
||||
MOZ_ASSERT(Preferences::IsServiceAvailable());
|
||||
bool enable =
|
||||
Preferences::GetBool("prioritized_input_events.enabled", false);
|
||||
|
||||
if (!enable) {
|
||||
return;
|
||||
}
|
||||
InputEventStatistics::Get().SetEnable(true);
|
||||
mMainThread->EnableEventPrioritization();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThreadManager::IdleDispatchToMainThread(nsIRunnable *aEvent, uint32_t aTimeout)
|
||||
{
|
||||
|
|
|
@ -53,7 +53,6 @@ public:
|
|||
~nsThreadManager()
|
||||
{
|
||||
}
|
||||
void EnableMainThreadEventPrioritization();
|
||||
|
||||
private:
|
||||
nsThreadManager()
|
||||
|
|
|
@ -88,47 +88,6 @@ already_AddRefed<nsITimer> CreateTimer()
|
|||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(PrioritizableRunnable, Runnable,
|
||||
nsIRunnablePriority)
|
||||
|
||||
PrioritizableRunnable::PrioritizableRunnable(already_AddRefed<nsIRunnable>&& aRunnable,
|
||||
uint32_t aPriority)
|
||||
// Real runnable name is managed by overridding the GetName function.
|
||||
: Runnable("PrioritizableRunnable")
|
||||
, mRunnable(Move(aRunnable))
|
||||
, mPriority(aPriority)
|
||||
{
|
||||
#if DEBUG
|
||||
nsCOMPtr<nsIRunnablePriority> runnablePrio = do_QueryInterface(mRunnable);
|
||||
MOZ_ASSERT(!runnablePrio);
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PrioritizableRunnable::GetName(nsACString& aName)
|
||||
{
|
||||
// Try to get a name from the underlying runnable.
|
||||
nsCOMPtr<nsINamed> named = do_QueryInterface(mRunnable);
|
||||
if (named) {
|
||||
named->GetName(aName);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PrioritizableRunnable::Run()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
return mRunnable->Run();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PrioritizableRunnable::GetPriority(uint32_t* aPriority)
|
||||
{
|
||||
*aPriority = mPriority;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif // XPCOM_GLUE_AVOID_NSPR
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -486,26 +486,6 @@ private:
|
|||
IdleRunnable& operator=(const IdleRunnable&&) = delete;
|
||||
};
|
||||
|
||||
// This class is designed to be a wrapper of a real runnable to support event
|
||||
// prioritizable.
|
||||
class PrioritizableRunnable : public Runnable, public nsIRunnablePriority
|
||||
{
|
||||
public:
|
||||
PrioritizableRunnable(already_AddRefed<nsIRunnable>&& aRunnable,
|
||||
uint32_t aPriority);
|
||||
|
||||
NS_IMETHOD GetName(nsACString& aName) override;
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIRUNNABLEPRIORITY
|
||||
|
||||
protected:
|
||||
virtual ~PrioritizableRunnable() {};
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
uint32_t mPriority;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// An event that can be used to call a C++11 functions or function objects,
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
nsresult InitCommon(uint32_t aDelayMS, uint32_t aType,
|
||||
Callback&& newCallback);
|
||||
|
||||
nsresult InitCommon(const mozilla::TimeDuration& aDelay, uint32_t aType,
|
||||
nsresult InitCommon(const TimeDuration& aDelay, uint32_t aType,
|
||||
Callback&& newCallback);
|
||||
|
||||
Callback& GetCallback()
|
||||
|
@ -200,9 +200,9 @@ public:
|
|||
// Updated only after this timer has been removed from the timer thread.
|
||||
int32_t mGeneration;
|
||||
|
||||
mozilla::TimeDuration mDelay;
|
||||
TimeDuration mDelay;
|
||||
// Updated only after this timer has been removed from the timer thread.
|
||||
mozilla::TimeStamp mTimeout;
|
||||
TimeStamp mTimeout;
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
mozilla::tasktracer::TracedTaskCommon mTracedTask;
|
||||
|
|
Загрузка…
Ссылка в новой задаче