Bug 1371523 - remove find bar sync ipc message, r=mikedeboer

MozReview-Commit-ID: C0VO0U3UJ76

--HG--
extra : rebase_source : 4c29a0d740ff8b18dea35428a3f88ab5093ecc91
extra : source : cbf007a7027f20ecc1641ea9cc07e98817a49862
This commit is contained in:
Gijs Kruitbosch 2018-03-21 17:10:40 +00:00
Родитель d1c700ab6c
Коммит 3929672b94
6 изменённых файлов: 161 добавлений и 103 удалений

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

@ -54,9 +54,8 @@ window._gBrowser = {
// To correctly handle keypresses for potential FindAsYouType, while
// the tab's find bar is not yet initialized.
this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
Services.prefs.addObserver("accessibility.typeaheadfind", this);
messageManager.addMessageListener("Findbar:Keypress", this);
this._setFindbarData();
XPCOMUtils.defineLazyPreferenceGetter(this, "animationsEnabled",
"toolkit.cosmeticAnimations.enabled");
@ -438,6 +437,27 @@ window._gBrowser = {
return this.selectedBrowser.userTypedValue;
},
_setFindbarData() {
// Ensure we know what the find bar key is in the content process:
let initialProcessData = Services.ppmm.initialProcessData;
if (!initialProcessData.findBarShortcutData) {
let keyEl = document.getElementById("key_find");
let mods = keyEl.getAttribute("modifiers")
.replace(/accel/i, AppConstants.platform == "macosx" ? "meta" : "control");
initialProcessData.findBarShortcutData = {
key: keyEl.getAttribute("key"),
modifiers: {
shiftKey: mods.includes("shift"),
ctrlKey: mods.includes("control"),
altKey: mods.includes("alt"),
metaKey: mods.includes("meta"),
},
};
Services.ppmm.broadcastAsyncMessage("Findbar:ShortcutData",
initialProcessData.findBarShortcutData);
}
},
isFindBarInitialized(aTab) {
return (aTab || this.selectedTab)._findBar != undefined;
},
@ -469,27 +489,19 @@ window._gBrowser = {
/**
* Create a findbar instance.
* @param aTab the tab to create the find bar for.
* @param aForce Whether to force a sync flush to trigger XBL construction immediately.
* @return the created findbar, or null if the window or tab is closed/closing.
*/
async _createFindBar(aTab, aForce = false) {
async _createFindBar(aTab) {
let findBar = document.createElementNS(this._XUL_NS, "findbar");
let browser = this.getBrowserForTab(aTab);
let browserContainer = this.getBrowserContainer(browser);
browserContainer.appendChild(findBar);
if (aForce) {
// Force a style flush to ensure that our binding is attached.
// Remove after bug 1371523 makes more of this async.
findBar.clientTop;
} else {
await new Promise(r => requestAnimationFrame(r));
if (window.closed || aTab.closing) {
delete aTab._pendingFindBar;
return null;
}
}
await new Promise(r => requestAnimationFrame(r));
delete aTab._pendingFindBar;
if (window.closed || aTab.closing) {
return null;
}
findBar.browser = browser;
findBar._findField.value = this._lastFindValue;
@ -3787,30 +3799,11 @@ window._gBrowser = {
case "Findbar:Keypress":
{
let tab = this.getTabForBrowser(browser);
// If the find bar for this tab is not yet alive, only initialize
// it if there's a possibility FindAsYouType will be used.
// There's no point in doing it for most random keypresses.
if (!this.isFindBarInitialized(tab) &&
data.shouldFastFind) {
let shouldFastFind = this._findAsYouType;
if (!shouldFastFind) {
// Please keep in sync with toolkit/content/widgets/findbar.xml
const FAYT_LINKS_KEY = "'";
const FAYT_TEXT_KEY = "/";
let charCode = data.fakeEvent.charCode;
let key = charCode ? String.fromCharCode(charCode) : null;
shouldFastFind = key == FAYT_LINKS_KEY || key == FAYT_TEXT_KEY;
}
if (shouldFastFind) {
// Make sure we return the result.
// This needs sync initialization of the find bar, unfortunately.
// bug 1371523 tracks removing all of this.
// This returns a promise, so don't use the result...
this._createFindBar(tab, true);
// ... just grab the 'cached' version now we know it exists.
this.getCachedFindBar().receiveMessage(aMessage);
}
if (!this.isFindBarInitialized(tab)) {
let fakeEvent = data;
this.getFindBar(tab).then(findbar => {
findbar._onBrowserKeypress(fakeEvent);
});
}
break;
}
@ -3879,12 +3872,6 @@ window._gBrowser = {
}
break;
}
case "nsPref:changed":
{
// This is the only pref observed.
this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
break;
}
}
},
@ -3945,8 +3932,6 @@ window._gBrowser = {
this._switcher.destroy();
}
}
Services.prefs.removeObserver("accessibility.typeaheadfind", this);
},
_setupEventListeners() {

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

@ -172,8 +172,11 @@ var testData = [
},
];
function sendKeys(aKeys) {
function sendKeys(aKeys, aElem) {
for (let i = 0; i < aKeys.length; i++) {
// Force layout flush between keys to ensure focus is correct.
// This shouldn't be necessary; bug 1450219 tracks this.
aElem.clientTop;
let key = aKeys[i];
if (key.startsWith("KEY_")) {
synthesizeKey(key);
@ -189,7 +192,7 @@ function test() {
for (let { keys, initialVal, expectedVal } of testData) {
elem.focus();
elem.value = initialVal;
sendKeys(keys);
sendKeys(keys, elem);
is(elem.value, expectedVal,
"Test with " + keys + ", result should be " + expectedVal);
elem.value = "";

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

@ -17,6 +17,8 @@ ChromeUtils.defineModuleGetter(this, "SelectContentHelper",
"resource://gre/modules/SelectContentHelper.jsm");
ChromeUtils.defineModuleGetter(this, "FindContent",
"resource://gre/modules/FindContent.jsm");
ChromeUtils.defineModuleGetter(this, "RemoteFinder",
"resource://gre/modules/RemoteFinder.jsm");
var global = this;
@ -927,16 +929,37 @@ var FindBar = {
_findMode: 0,
/**
* _findKey and _findModifiers are used to determine whether a keypress
* is a user attempting to use the find shortcut, after which we'll
* route keypresses to the parent until we know the findbar has focus
* there. To do this, we need shortcut data from the parent.
*/
_findKey: null,
_findModifiers: null,
init() {
addMessageListener("Findbar:UpdateState", this);
Services.els.addSystemEventListener(global, "keypress", this, false);
Services.els.addSystemEventListener(global, "mouseup", this, false);
this._initShortcutData();
},
receiveMessage(msg) {
switch (msg.name) {
case "Findbar:UpdateState":
this._findMode = msg.data.findMode;
this._quickFindTimeout = msg.data.hasQuickFindTimeout;
if (msg.data.isOpenAndFocused) {
this._keepPassingUntilToldOtherwise = false;
}
break;
case "Findbar:ShortcutData":
// Set us up to never need this again for the lifetime of this process,
// and remove the listener.
Services.cpmm.initialProcessData.findBarShortcutData = msg.data;
Services.cpmm.removeMessageListener("Findbar:ShortcutData", this);
this._initShortcutData(msg.data);
break;
}
},
@ -952,6 +975,36 @@ var FindBar = {
}
},
/**
* Use initial process data for find key/modifier data if we have it.
* Otherwise, add a listener so we get the data when the parent process has
* it.
*/
_initShortcutData(data = Services.cpmm.initialProcessData.findBarShortcutData) {
if (data) {
this._findKey = data.key;
this._findModifiers = data.modifiers;
} else {
Services.cpmm.addMessageListener("Findbar:ShortcutData", this);
}
},
/**
* Check whether this key event will start the findbar in the parent,
* in which case we should pass any further key events to the parent to avoid
* them being lost.
* @param aEvent the key event to check.
*/
_eventMatchesFindShortcut(aEvent) {
let modifiers = this._findModifiers;
if (!modifiers) {
return false;
}
return aEvent.ctrlKey == modifiers.ctrlKey && aEvent.altKey == modifiers.altKey &&
aEvent.shiftKey == modifiers.shiftKey && aEvent.metaKey == modifiers.metaKey &&
aEvent.key == this._findKey;
},
/**
* Returns whether FAYT can be used for the given event in
* the current content state.
@ -970,9 +1023,14 @@ var FindBar = {
},
_onKeypress(event) {
const FAYT_LINKS_KEY = "'";
const FAYT_TEXT_KEY = "/";
if (this._eventMatchesFindShortcut(event)) {
this._keepPassingUntilToldOtherwise = true;
}
// Useless keys:
if (event.ctrlKey || event.altKey || event.metaKey || event.defaultPrevented) {
return undefined;
return;
}
// Check the focused element etc.
@ -980,9 +1038,39 @@ var FindBar = {
// Can we even use find in this page at all?
if (!fastFind.can) {
return undefined;
return;
}
if (this._keepPassingUntilToldOtherwise) {
this._passKeyToParent(event);
return;
}
if (!fastFind.should) {
return;
}
let charCode = event.charCode;
// If the find bar is open and quick find is on, send the key to the parent.
if (this._findMode != this.FIND_NORMAL && this._quickFindTimeout) {
if (!charCode)
return;
this._passKeyToParent(event);
} else {
let key = charCode ? String.fromCharCode(charCode) : null;
let manualstartFAYT = (key == FAYT_LINKS_KEY || key == FAYT_TEXT_KEY);
let autostartFAYT = !manualstartFAYT && RemoteFinder._findAsYouType && key && key != " ";
if (manualstartFAYT || autostartFAYT) {
let mode = (key == FAYT_LINKS_KEY || (autostartFAYT && RemoteFinder._typeAheadLinksOnly)) ?
this.FIND_LINKS : this.FIND_TYPEAHEAD;
// Set _findMode immediately (without waiting for child->parent->child roundtrip)
// to ensure we pass any further keypresses, too.
this._findMode = mode;
this._passKeyToParent(event);
}
}
},
_passKeyToParent(event) {
event.preventDefault();
let fakeEvent = {};
for (let k in event) {
if (typeof event[k] != "object" && typeof event[k] != "function" &&
@ -990,16 +1078,7 @@ var FindBar = {
fakeEvent[k] = event[k];
}
}
// sendSyncMessage returns an array of the responses from all listeners
let rv = sendSyncMessage("Findbar:Keypress", {
fakeEvent,
shouldFastFind: fastFind.should
});
if (rv.includes(false)) {
event.preventDefault();
return false;
}
return undefined;
sendAsyncMessage("Findbar:Keypress", fakeEvent);
},
_onMouseup(event) {

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

@ -161,7 +161,7 @@ add_task(async function test_reinitialization_at_remoteness_change() {
* Ensure that the initial typed characters aren't lost immediately after
* opening the find bar.
*/
add_task(async function() {
add_task(async function e10sLostKeys() {
// This test only makes sence in e10s evironment.
if (!gMultiProcessBrowser) {
info("Skipping this test because of non-e10s environment.");
@ -169,7 +169,6 @@ add_task(async function() {
}
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
let browser = tab.linkedBrowser;
ok(!gFindBarInitialized, "findbar isn't initialized yet");
@ -177,21 +176,19 @@ add_task(async function() {
let findBar = gFindBar;
let initialValue = findBar._findField.value;
await EventUtils.synthesizeAndWaitKey("f", { accelKey: true }, window, null,
() => {
await EventUtils.synthesizeAndWaitKey("f", { accelKey: true }, window, null, () => {
// We can't afford to wait for the promise to resolve, by then the
// find bar is visible and focused, so sending characters to the
// content browser wouldn't work.
isnot(document.activeElement, findBar._findField.inputField,
"findbar is not yet focused");
EventUtils.synthesizeKey("a");
EventUtils.synthesizeKey("b");
EventUtils.synthesizeKey("c");
is(findBar._findField.value, initialValue, "still has initial find query");
});
let promises = [
BrowserTestUtils.sendChar("a", browser),
BrowserTestUtils.sendChar("b", browser),
BrowserTestUtils.sendChar("c", browser)
];
is(findBar._findField.value, initialValue, "still has initial find query");
await Promise.all(promises);
await BrowserTestUtils.waitForCondition(() => findBar._findField.value.length == 3);
is(document.activeElement, findBar._findField.inputField,
"findbar is now focused");
is(findBar._findField.value, "abc", "abc fully entered as find query");

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

@ -115,10 +115,11 @@
]]></handler>
<handler event="focus"><![CDATA[
let findbar = this.findbar;
if (/Mac/.test(navigator.platform)) {
let findbar = this.findbar;
findbar._onFindFieldFocus();
}
findbar._updateBrowserWithState();
]]></handler>
<handler event="compositionstart"><![CDATA[
@ -128,6 +129,7 @@
if (findbar._quickFindTimeout) {
clearTimeout(findbar._quickFindTimeout);
findbar._quickFindTimeout = null;
findbar._updateBrowserWithState();
}
]]></handler>
@ -467,6 +469,7 @@
// findbar is already hidden.
if (this._isIMEComposing || this.hidden) {
this._quickFindTimeout = null;
this._updateBrowserWithState();
return;
}
@ -475,6 +478,7 @@
this.close();
this._quickFindTimeout = null;
}, this._quickFindTimeoutLength);
this._updateBrowserWithState();
]]></body>
</method>
@ -746,6 +750,7 @@
this.browser.finder.onFindbarClose();
this._cancelTimers();
this._updateBrowserWithState();
this._findFailedString = null;
]]></body>
@ -830,41 +835,26 @@
]]></body>
</method>
<!-- We get a fake event object through an IPC message which contains the
data we need to make a decision. We then return |true| if and only if
the page gets to deal with the event itself. Everywhere we return
false, the message sender will take care of calling event.preventDefault
on the real event. -->
<!-- We get a fake event object through an IPC message when FAYT is being used
from within the browser. We then stuff that input in the find bar here. -->
<method name="_onBrowserKeypress">
<parameter name="aFakeEvent"/>
<parameter name="aShouldFastFind"/>
<body><![CDATA[
const FAYT_LINKS_KEY = "'";
const FAYT_TEXT_KEY = "/";
// Fast keypresses can stack up when the content process is slow or
// hangs when in e10s mode. We make sure the findbar isn't 'opened'
// several times in a row, because then the find query is selected
// each time, losing characters typed initially.
let inputField = this._findField.inputField;
if (!this.hidden && document.activeElement == inputField) {
this._dispatchKeypressEvent(inputField, aFakeEvent);
return false;
if (!this.hidden && this._findField.inputField == document.activeElement) {
this._dispatchKeypressEvent(this._findField.inputField, aFakeEvent);
return;
}
if (this._findMode != this.FIND_NORMAL && this._quickFindTimeout) {
if (!aFakeEvent.charCode)
return true;
this._findField.select();
this._findField.focus();
this._dispatchKeypressEvent(this._findField.inputField, aFakeEvent);
return false;
return;
}
if (!aShouldFastFind)
return true;
let key = aFakeEvent.charCode ? String.fromCharCode(aFakeEvent.charCode) : null;
let manualstartFAYT = (key == FAYT_LINKS_KEY || key == FAYT_TEXT_KEY);
let autostartFAYT = !manualstartFAYT && this._findAsYouType &&
@ -887,10 +877,7 @@
this._dispatchKeypressEvent(this._findField.inputField, aFakeEvent);
else
this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND);
return false;
}
return undefined;
]]></body>
</method>
@ -906,10 +893,9 @@
if (!this.hidden && this._findMode != this.FIND_NORMAL)
this.close();
break;
case "Findbar:Keypress":
return this._onBrowserKeypress(aMessage.data.fakeEvent,
aMessage.data.shouldFastFind);
this._onBrowserKeypress(aMessage.data);
break;
}
return undefined;
]]></body>
@ -919,7 +905,9 @@
<body><![CDATA[
if (this._browser && this._browser.messageManager) {
this._browser.messageManager.sendAsyncMessage("Findbar:UpdateState", {
findMode: this._findMode
findMode: this._findMode,
isOpenAndFocused: !this.hidden && document.activeElement == this._findField.inputField,
hasQuickFindTimeout: !!this._quickFindTimeout,
});
}
]]></body>

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

@ -328,3 +328,9 @@ RemoteFinderListener.prototype = {
}
}
};
XPCOMUtils.defineLazyPreferenceGetter(RemoteFinder, "_typeAheadLinksOnly",
"accessibility.typeaheadfind.linksonly");
XPCOMUtils.defineLazyPreferenceGetter(RemoteFinder, "_findAsYouType",
"accessibility.typeaheadfind");