Merge mozilla-central to autoland

This commit is contained in:
Carsten "Tomcat" Book 2017-07-28 09:50:36 +02:00
Родитель 01905b3674 a3353ae62a
Коммит 6aa98d7df0
75 изменённых файлов: 410 добавлений и 1637 удалений

Просмотреть файл

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