--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -39,26 +39,26 @@
#include ../../../toolkit/content/editMenuCommands.inc.xul
<command id="View:PageSource" oncommand="BrowserViewSource(window.gBrowser.selectedBrowser);" observes="canViewSource"/>
<command id="View:PageInfo" oncommand="BrowserPageInfo();"/>
<command id="View:FullScreen" oncommand="BrowserFullScreen();"/>
<command id="View:ReaderView" oncommand="ReaderParent.toggleReaderMode(event);"/>
<command id="cmd_find"
- oncommand="gFindBar.onFindCommand();"
+ oncommand="gLazyFindCommand('onFindCommand')"
observes="isImage"/>
<command id="cmd_findAgain"
- oncommand="gFindBar.onFindAgainCommand(false);"
+ oncommand="gLazyFindCommand('onFindAgainCommand', false)"
observes="isImage"/>
<command id="cmd_findPrevious"
- oncommand="gFindBar.onFindAgainCommand(true);"
+ oncommand="gLazyFindCommand('onFindAgainCommand', true)"
observes="isImage"/>
#ifdef XP_MACOSX
- <command id="cmd_findSelection" oncommand="gFindBar.onFindSelectionCommand();"/>
+ <command id="cmd_findSelection" oncommand="gLazyFindCommand('onFindSelectionCommand')"/>
#endif
<!-- work-around bug 392512 -->
<command id="Browser:AddBookmarkAs"
oncommand="PlacesCommandHook.bookmarkPage(gBrowser.selectedBrowser, true);"/>
<!-- The command disabled state must be manually updated through
PlacesCommandHook.updateBookmarkAllTabsCommand() -->
<command id="Browser:BookmarkAllTabs"
oncommand="PlacesCommandHook.bookmarkCurrentPages();"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -261,28 +261,44 @@ if (AppConstants.platform != "macosx") {
// Smart getter for the findbar. If you don't wish to force the creation of
// the findbar, check gFindBarInitialized first.
Object.defineProperty(this, "gFindBar", {
configurable: true,
enumerable: true,
get() {
- return window.gBrowser.getFindBar();
+ return gBrowser.getCachedFindBar();
},
});
Object.defineProperty(this, "gFindBarInitialized", {
configurable: true,
enumerable: true,
get() {
- return window.gBrowser.isFindBarInitialized();
+ return gBrowser.isFindBarInitialized();
},
});
+Object.defineProperty(this, "gFindBarPromise", {
+ configurable: true,
+ enumerable: true,
+ get() {
+ return gBrowser.getFindBar();
+ },
+});
+
+async function gLazyFindCommand(cmd, ...args) {
+ let fb = await gFindBarPromise;
+ // We could be closed by now, or the tab with XBL binding could have gone away:
+ if (fb && fb[cmd]) {
+ fb[cmd].apply(fb, args);
+ }
+}
+
Object.defineProperty(this, "AddonManager", {
configurable: true,
enumerable: true,
get() {
let tmp = {};
ChromeUtils.import("resource://gre/modules/AddonManager.jsm", tmp);
return this.AddonManager = tmp.AddonManager;
},
@@ -2055,17 +2071,17 @@ function HandleAppCommandEvent(evt) {
break;
case "New":
BrowserOpenTab();
break;
case "Close":
BrowserCloseTabOrWindow();
break;
case "Find":
- gFindBar.onFindCommand();
+ gLazyFindCommand("onFindCommand");
break;
case "Help":
openHelpLink("firefox-help");
break;
case "Open":
BrowserOpenFileWindow();
break;
case "Print":
@@ -3503,17 +3519,17 @@ var PrintPreviewListener = {
syncNotifications.notificationsHidden = true;
}
},
_showChrome() {
if (this._chromeState.notificationsOpen)
gBrowser.getNotificationBox().notificationsHidden = false;
if (this._chromeState.findOpen)
- gFindBar.open();
+ gLazyFindCommand("open");
if (this._chromeState.globalNotificationsOpen)
document.getElementById("global-notificationbox").notificationsHidden = false;
if (this._chromeState.syncNotificationsOpen)
document.getElementById("sync-notifications").notificationsHidden = false;
if (this._chromeState.sidebarOpen)
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -471,30 +471,64 @@ window._gBrowser = {
get userTypedValue() {
return this.mCurrentBrowser.userTypedValue;
},
isFindBarInitialized(aTab) {
return (aTab || this.selectedTab)._findBar != undefined;
},
- getFindBar(aTab) {
- if (!aTab)
- aTab = this.selectedTab;
-
- if (aTab._findBar)
- return aTab._findBar;
-
+ /**
+ * Get the already constructed findbar
+ */
+ getCachedFindBar(aTab = this.selectedTab) {
+ return aTab._findBar;
+ },
+
+ /**
+ * Get the findbar, and create it if it doesn't exist.
+ * @return the find bar (or null if the window or tab is closed/closing in the interim).
+ */
+ async getFindBar(aTab = this.selectedTab) {
+ let findBar = this.getCachedFindBar(aTab);
+ if (findBar) {
+ return findBar;
+ }
+
+ // Avoid re-entrancy by caching the promise we're about to return.
+ if (!aTab._pendingFindBar) {
+ aTab._pendingFindBar = this._createFindBar(aTab);
+ }
+ return aTab._pendingFindBar;
+ },
+
+ /**
+ * 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) {
let findBar = document.createElementNS(this._XUL_NS, "findbar");
let browser = this.getBrowserForTab(aTab);
let browserContainer = this.getBrowserContainer(browser);
browserContainer.appendChild(findBar);
- // Force a style flush to ensure that our binding is attached.
- findBar.clientTop;
+ 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;
+ }
+ }
+ delete aTab._pendingFindBar;
findBar.browser = browser;
findBar._findField.value = this._lastFindValue;
aTab._findBar = findBar;
let event = document.createEvent("Events");
event.initEvent("TabFindInitialized", true, false);
@@ -1118,17 +1152,17 @@ window._gBrowser = {
}
let oldBrowser = oldTab.linkedBrowser;
let newBrowser = newTab.linkedBrowser;
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
if (this.isFindBarInitialized(oldTab)) {
- let findBar = this.getFindBar(oldTab);
+ let findBar = this.getCachedFindBar(oldTab);
oldTab._findBarFocused = (!findBar.hidden &&
findBar._findField.getAttribute("focused") == "true");
}
let activeEl = document.activeElement;
// If focus is on the old tab, move it to the new tab.
if (activeEl == oldTab) {
newTab.focus();
@@ -1692,17 +1726,17 @@ window._gBrowser = {
this._outerWindowIDBrowserMap.set(aBrowser.outerWindowID, aBrowser);
}
if (wasActive)
aBrowser.focus();
// If the findbar has been initialised, reset its browser reference.
if (this.isFindBarInitialized(tab)) {
- this.getFindBar(tab).browser = aBrowser;
+ this.getCachedFindBar(tab).browser = aBrowser;
}
evt = document.createEvent("Events");
evt.initEvent("TabRemotenessChange", true, false);
tab.dispatchEvent(evt);
return true;
},
@@ -3107,20 +3141,27 @@ window._gBrowser = {
otherBrowser.getAttribute("usercontextid") || 0);
delete otherBrowser.registeredOpenURI;
}
// Handle findbar data (if any)
let otherFindBar = aOtherTab._findBar;
if (otherFindBar &&
otherFindBar.findMode == otherFindBar.FIND_NORMAL) {
- let ourFindBar = this.getFindBar(aOurTab);
- ourFindBar._findField.value = otherFindBar._findField.value;
- if (!otherFindBar.hidden)
- ourFindBar.onFindCommand();
+ let oldValue = otherFindBar._findField.value;
+ let wasHidden = otherFindBar.hidden;
+ let ourFindBarPromise = this.getFindBar(aOurTab);
+ ourFindBarPromise.then(ourFindBar => {
+ if (!ourFindBar) {
+ return;
+ }
+ ourFindBar._findField.value = oldValue;
+ if (!wasHidden)
+ ourFindBar.onFindCommand();
+ });
}
// Finish tearing down the tab that's going away.
if (closeWindow) {
aOtherTab.ownerGlobal.close();
} else {
remoteBrowser._endRemoveTab(aOtherTab);
}
@@ -3817,17 +3858,23 @@ window._gBrowser = {
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.
- return this.getFindBar(tab).receiveMessage(aMessage);
+ // 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);
}
}
break;
}
case "RefreshBlocker:Blocked":
{
// The data object is expected to contain the following properties:
// - URI (string)
@@ -4515,17 +4562,17 @@ class TabProgressListener {
}
// If the browser was previously muted, we should restore the muted state.
if (this.mTab.hasAttribute("muted")) {
this.mTab.linkedBrowser.mute();
}
if (gBrowser.isFindBarInitialized(this.mTab)) {
- let findBar = gBrowser.getFindBar(this.mTab);
+ let findBar = gBrowser.getCachedFindBar(this.mTab);
// Close the Find toolbar if we're in old-style TAF mode
if (findBar.findMode != findBar.FIND_NORMAL) {
findBar.close();
}
}
gBrowser.setTabTitle(this.mTab);
--- a/browser/base/content/test/general/browser_bug537013.js
+++ b/browser/base/content/test/general/browser_bug537013.js
@@ -37,29 +37,31 @@ function test() {
gBrowser.removeTab(tabs.pop());
}
});
texts.forEach(aText => addTabWithText(aText));
// Set up the first tab
gBrowser.selectedTab = tabs[0];
+ gBrowser.getFindBar().then(initialTest);
+}
+
+function initialTest() {
setFindString(texts[0]);
// Turn on highlight for testing bug 891638
gFindBar.getElement("highlight").checked = true;
// Make sure the second tab is correct, then set it up
gBrowser.selectedTab = tabs[1];
- gBrowser.selectedTab.addEventListener("TabFindInitialized", continueTests1);
+ gBrowser.selectedTab.addEventListener("TabFindInitialized", continueTests1, {once: true});
// Initialize the findbar
- gFindBar;
+ gBrowser.getFindBar();
}
function continueTests1() {
- gBrowser.selectedTab.removeEventListener("TabFindInitialized",
- continueTests1);
ok(true, "'TabFindInitialized' event properly dispatched!");
ok(gFindBar.hidden, "Second tab doesn't show find bar!");
gFindBar.open();
is(gFindBar._findField.value, texts[0],
"Second tab kept old find value for new initialization!");
setFindString(texts[1]);
// Confirm the first tab is still correct, ensure re-hiding works as expected
@@ -92,16 +94,21 @@ function continueTests3() {
is(gFindBar._findField.getAttribute("focused"), "true",
"Open findbar refocused on tab change!");
gURLBar.focus();
gBrowser.selectedTab = tabs[0];
ok(gFindBar.hidden, "First tab doesn't show find bar!");
// Set up a third tab, no tests here
gBrowser.selectedTab = tabs[2];
+ gBrowser.selectedTab.addEventListener("TabFindInitialized", continueTests4, {once: true});
+ gBrowser.getFindBar();
+}
+
+function continueTests4() {
setFindString(texts[2]);
// Now we jump to the second, then first, and then fourth
gBrowser.selectedTab = tabs[1];
// Test for bug 892384
ok(!gFindBar._findField.hasAttribute("focused"),
"Open findbar not refocused on tab change!");
gBrowser.selectedTab = tabs[0];
--- a/browser/base/content/test/general/browser_bug567306.js
+++ b/browser/base/content/test/general/browser_bug567306.js
@@ -16,17 +16,17 @@ add_task(async function() {
resolve();
});
selectedBrowser.loadURI("data:text/html,<h1 id='h1'>Select Me</h1>");
});
await SimpleTest.promiseFocus(newwindow);
ok(!newwindow.gFindBarInitialized, "find bar is not yet initialized");
- let findBar = newwindow.gFindBar;
+ let findBar = await newwindow.gFindBarPromise;
await ContentTask.spawn(selectedBrowser, { }, async function() {
let elt = content.document.getElementById("h1");
let selection = content.getSelection();
let range = content.document.createRange();
range.setStart(elt, 0);
range.setEnd(elt, 1);
selection.removeAllRanges();
--- a/browser/base/content/test/general/browser_bug749738.js
+++ b/browser/base/content/test/general/browser_bug749738.js
@@ -1,29 +1,30 @@
/* 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/. */
"use strict";
const DUMMY_PAGE = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
-function test() {
- waitForExplicitFinish();
+/**
+ * This test checks that if you search for something on one tab, then close
+ * that tab and have the find bar open on the next tab you get switched to,
+ * closing the find bar in that tab works without exceptions.
+ */
+add_task(async function test_bug749738() {
+ // Open find bar on initial tab.
+ await gFindBarPromise;
- let tab = BrowserTestUtils.addTab(gBrowser);
- gBrowser.selectedTab = tab;
-
- BrowserTestUtils.loadURI(tab.linkedBrowser, DUMMY_PAGE);
- BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
+ await BrowserTestUtils.withNewTab(DUMMY_PAGE, async function() {
+ await gFindBarPromise;
gFindBar.onFindCommand();
EventUtils.sendString("Dummy");
- gBrowser.removeTab(tab);
+ });
- try {
- gFindBar.close();
- ok(true, "findbar.close should not throw an exception");
- } catch (e) {
- ok(false, "findbar.close threw exception: " + e);
- }
- finish();
- });
-}
+ try {
+ gFindBar.close();
+ ok(true, "findbar.close should not throw an exception");
+ } catch (e) {
+ ok(false, "findbar.close threw exception: " + e);
+ }
+});
--- a/browser/base/content/test/general/browser_findbarClose.js
+++ b/browser/base/content/test/general/browser_findbarClose.js
@@ -11,16 +11,17 @@ add_task(async function findbar_test() {
let promise = ContentTask.spawn(newTab.linkedBrowser, null, async function() {
await ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", false);
});
newTab.linkedBrowser.loadURI("http://example.com/browser/" +
"browser/base/content/test/general/test_bug628179.html");
await promise;
+ await gFindBarPromise;
gFindBar.open();
await new ContentTask.spawn(newTab.linkedBrowser, null, async function() {
let iframe = content.document.getElementById("iframe");
let awaitLoad = ContentTaskUtils.waitForEvent(iframe, "load", false);
iframe.src = "http://example.org/";
await awaitLoad;
});
--- a/browser/base/content/test/general/browser_zbug569342.js
+++ b/browser/base/content/test/general/browser_zbug569342.js
@@ -1,80 +1,61 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-var gTab = null;
-
-function load(url, cb) {
- gTab = BrowserTestUtils.addTab(gBrowser, url);
- gBrowser.addEventListener("load", function listener(event) {
- if (event.target.location != url)
- return;
+add_task(async function findBarDisabledOnSomePages() {
+ ok(!gFindBar || gFindBar.hidden, "Find bar should not be visible by default");
- gBrowser.removeEventListener("load", listener, true);
- // Trigger onLocationChange by switching tabs.
- gBrowser.selectedTab = gTab;
- cb();
- }, true);
-}
-
-function test() {
- waitForExplicitFinish();
-
- ok(gFindBar.hidden, "Find bar should not be visible by default");
-
+ let findbarOpenedPromise = BrowserTestUtils.waitForEvent(gBrowser.selectedTab, "TabFindInitialized");
+ document.documentElement.focus();
// Open the Find bar before we navigate to pages that shouldn't have it.
EventUtils.synthesizeKey("f", { accelKey: true });
+ await findbarOpenedPromise;
ok(!gFindBar.hidden, "Find bar should be visible");
- nextTest();
-}
+ let urls = [
+ "about:config",
+ "about:addons",
+ ];
-var urls = [
- "about:config",
- "about:addons",
-];
+ for (let url of urls) {
+ await testFindDisabled(url);
+ }
-function nextTest() {
- let url = urls.shift();
- if (url) {
- testFindDisabled(url, nextTest);
- } else {
- // Make sure the find bar is re-enabled after disabled page is closed.
- testFindEnabled("about:blank", function() {
- EventUtils.synthesizeKey("KEY_Escape");
- ok(gFindBar.hidden, "Find bar should now be hidden");
- finish();
- });
- }
-}
+ // Make sure the find bar is re-enabled after disabled page is closed.
+ await testFindEnabled("about:about");
+ gFindBar.close();
+ ok(gFindBar.hidden, "Find bar should now be hidden");
+});
-function testFindDisabled(url, cb) {
- load(url, function() {
- ok(gFindBar.hidden, "Find bar should not be visible");
- EventUtils.synthesizeKey("/", {}, gTab.linkedBrowser.contentWindow);
- ok(gFindBar.hidden, "Find bar should not be visible");
+function testFindDisabled(url) {
+ return BrowserTestUtils.withNewTab(url, async function(browser) {
+ let waitForFindBar = async () => {
+ await new Promise(r => requestAnimationFrame(r));
+ await new Promise(r => Services.tm.dispatchToMainThread(r));
+ };
+ ok(!gFindBar || gFindBar.hidden, "Find bar should not be visible at the start");
+ await BrowserTestUtils.synthesizeKey("/", {}, browser);
+ await waitForFindBar();
+ ok(!gFindBar || gFindBar.hidden, "Find bar should not be visible after fast find");
EventUtils.synthesizeKey("f", {accelKey: true});
- ok(gFindBar.hidden, "Find bar should not be visible");
+ await waitForFindBar();
+ ok(!gFindBar || gFindBar.hidden, "Find bar should not be visible after find command");
ok(document.getElementById("cmd_find").getAttribute("disabled"),
"Find command should be disabled");
-
- gBrowser.removeTab(gTab);
- cb();
});
}
-function testFindEnabled(url, cb) {
- load(url, function() {
+async function testFindEnabled(url) {
+ return BrowserTestUtils.withNewTab(url, async function(browser) {
ok(!document.getElementById("cmd_find").getAttribute("disabled"),
"Find command should not be disabled");
// Open Find bar and then close it.
+ let findbarOpenedPromise = BrowserTestUtils.waitForEvent(gBrowser.selectedTab, "TabFindInitialized");
EventUtils.synthesizeKey("f", { accelKey: true });
+ await findbarOpenedPromise;
ok(!gFindBar.hidden, "Find bar should be visible again");
EventUtils.synthesizeKey("KEY_Escape");
ok(gFindBar.hidden, "Find bar should now be hidden");
-
- gBrowser.removeTab(gTab);
- cb();
});
}
--- a/browser/base/content/test/sanitize/browser_sanitize-formhistory.js
+++ b/browser/base/content/test/sanitize/browser_sanitize-formhistory.js
@@ -17,16 +17,17 @@ add_task(async function test() {
reject();
}
},
});
});
// Sanitize now so we can test the baseline point.
await Sanitizer.sanitize(["formdata"]);
+ await gFindBarPromise;
ok(!gFindBar.hasTransactions, "pre-test baseline for sanitizer");
gFindBar.getElement("findbar-textbox").value = "m";
ok(gFindBar.hasTransactions, "formdata can be cleared after input");
await Sanitizer.sanitize(["formdata"]);
is(gFindBar.getElement("findbar-textbox").value, "", "findBar textbox should be empty after sanitize");
ok(!gFindBar.hasTransactions, "No transactions after sanitize");
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -176,18 +176,18 @@ const CustomizableWidgets = [
win.saveBrowser(win.gBrowser.selectedBrowser);
}
}, {
id: "find-button",
shortcutId: "key_find",
tooltiptext: "find-button.tooltiptext3",
onCommand(aEvent) {
let win = aEvent.target.ownerGlobal;
- if (win.gFindBar) {
- win.gFindBar.onFindCommand();
+ if (win.gLazyFindCommand) {
+ win.gLazyFindCommand("onFindCommand");
}
}
}, {
id: "open-file-button",
shortcutId: "openFileKb",
tooltiptext: "open-file-button.tooltiptext3",
onCommand(aEvent) {
let win = aEvent.target.ownerGlobal;
--- a/browser/components/customizableui/test/browser_947914_button_find.js
+++ b/browser/components/customizableui/test/browser_947914_button_find.js
@@ -12,15 +12,19 @@ add_task(async function() {
await waitForOverflowButtonShown();
await document.getElementById("nav-bar").overflowable.show();
info("Menu panel was opened");
let findButton = document.getElementById("find-button");
ok(findButton, "Find button exists in Panel Menu");
+ let findBarPromise = gBrowser.isFindBarInitialized() ?
+ null : BrowserTestUtils.waitForEvent(gBrowser.selectedTab, "TabFindInitialized");
+
findButton.click();
+ await findBarPromise;
ok(!gFindBar.hasAttribute("hidden"), "Findbar opened successfully");
// close find bar
gFindBar.close();
info("Findbar was closed");
});
--- a/browser/components/customizableui/test/browser_panel_keyboard_navigation.js
+++ b/browser/components/customizableui/test/browser_panel_keyboard_navigation.js
@@ -89,22 +89,25 @@ add_task(async function testEnterKeyBeha
// Let's test a 'normal' command button.
focusedElement = document.commandDispatcher.focusedElement;
const kFindButtonId = "appMenu-find-button";
while (!focusedElement || !focusedElement.id || focusedElement.id != kFindButtonId) {
EventUtils.synthesizeKey("KEY_ArrowUp");
focusedElement = document.commandDispatcher.focusedElement;
}
+ let findBarPromise = gBrowser.isFindBarInitialized() ?
+ null : BrowserTestUtils.waitForEvent(gBrowser.selectedTab, "TabFindInitialized");
Assert.equal(focusedElement.id, kFindButtonId, "Find button should be selected");
promise = promisePanelHidden(window);
EventUtils.synthesizeKey("KEY_Enter");
await promise;
+ await findBarPromise;
Assert.ok(!gFindBar.hidden, "Findbar should have opened");
gFindBar.close();
});
add_task(async function testLeftRightKeys() {
let promise = promisePanelShown(window);
PanelUI.show();
await promise;
--- a/browser/components/uitour/test/browser_UITour_panel_close_annotation.js
+++ b/browser/components/uitour/test/browser_UITour_panel_close_annotation.js
@@ -11,17 +11,20 @@ var gTestTab;
var gContentAPI;
var gContentWindow;
var highlight = document.getElementById("UITourHighlight");
var tooltip = document.getElementById("UITourTooltip");
function test() {
registerCleanupFunction(() => {
// Close the find bar in case it's open in the remaining tab
- gBrowser.getFindBar(gBrowser.selectedTab).close();
+ let findBar = gBrowser.getCachedFindBar(gBrowser.selectedTab);
+ if (findBar) {
+ findBar.close();
+ }
});
UITourTest();
}
var tests = [
function test_highlight_move_outside_panel(done) {
gContentAPI.showInfo("urlbar", "test title", "test text");
gContentAPI.showHighlight("customize");
--- a/browser/modules/Sanitizer.jsm
+++ b/browser/modules/Sanitizer.jsm
@@ -489,17 +489,17 @@ var Sanitizer = {
// No tab browser? This means that it's too early during startup (typically,
// Session Restore hasn't completed yet). Since we don't have find
// bars at that stage and since Session Restore will not restore
// find bars further down during startup, we have nothing to clear.
continue;
}
for (let tab of tabBrowser.tabs) {
if (tabBrowser.isFindBarInitialized(tab))
- tabBrowser.getFindBar(tab).clear();
+ tabBrowser.getCachedFindBar(tab).clear();
}
// Clear any saved find value
tabBrowser._lastFindValue = "";
}
} catch (ex) {
seenException = ex;
}
--- a/devtools/client/responsive.html/browser/swap.js
+++ b/devtools/client/responsive.html/browser/swap.js
@@ -183,17 +183,17 @@ function swapToInnerBrowser({ tab, conta
// the content in the viewport, instead of the tool page.
tunnel = tunnelToInnerBrowser(tab.linkedBrowser, innerBrowser);
debug("Wait until tunnel start");
await tunnel.start();
// Swapping browsers disconnects the find bar UI from the browser.
// If the find bar has been initialized, reconnect it.
if (gBrowser.isFindBarInitialized(tab)) {
- let findBar = gBrowser.getFindBar(tab);
+ let findBar = gBrowser.getCachedFindBar(tab);
findBar.browser = tab.linkedBrowser;
if (!findBar.hidden) {
// Force the find bar to activate again, restoring the search string.
findBar.onFindCommand();
}
}
// Force the browser UI to match the new state of the tab and browser.
@@ -248,17 +248,17 @@ function swapToInnerBrowser({ tab, conta
// temporary tab used to hold the content via
// `swapBrowsersAndCloseOther`.
dispatchDevToolsBrowserSwap(contentBrowser, tab.linkedBrowser);
swapBrowsersAndCloseOtherSilently(tab, contentTab);
// Swapping browsers disconnects the find bar UI from the browser.
// If the find bar has been initialized, reconnect it.
if (gBrowser.isFindBarInitialized(tab)) {
- let findBar = gBrowser.getFindBar(tab);
+ let findBar = gBrowser.getCachedFindBar(tab);
findBar.browser = tab.linkedBrowser;
if (!findBar.hidden) {
// Force the find bar to activate again, restoring the search string.
findBar.onFindCommand();
}
}
gBrowser = null;
--- a/toolkit/content/tests/browser/browser_bug1198465.js
+++ b/toolkit/content/tests/browser/browser_bug1198465.js
@@ -21,16 +21,21 @@ add_task(async function() {
// So `yield BrowserTestUtils.sendChar()` can't be used here:
// - synthesizing a key in the browser won't actually send it to the
// findbar; the findbar isn't part of the browser content.
// - we need to _not_ wait for _startFindDeferred to be resolved; yielding
// a synthesized keypress on the browser implicitely happens after the
// browser has dispatched its return message with the prefill value for
// the findbar, which essentially nulls these tests.
+ // The parent-side of the sidebar initialization is also async, so we do
+ // need to wait for that. We verify a bit further down that _startFindDeferred
+ // hasn't been resolved yet.
+ await gFindBarPromise;
+
let findBar = gFindBar;
is(findBar._findField.value, "", "findbar is empty");
// Test 1
// Any input in the findbar should erase a previous search.
findBar._findField.value = "xy";
findBar.startFind();
--- a/toolkit/content/tests/browser/browser_bug451286.js
+++ b/toolkit/content/tests/browser/browser_bug451286.js
@@ -130,16 +130,17 @@ function findAgainAndWait() {
onMatchesCountResult() {}
};
gFindBar.browser.finder.addResultListener(listener);
gFindBar.onFindAgainCommand();
});
}
async function openFindBarAndWait() {
+ await gFindBarPromise;
let awaitTransitionEnd = BrowserTestUtils.waitForEvent(gFindBar, "transitionend");
gFindBar.open();
await awaitTransitionEnd;
}
// This test is comparing snapshots. It is necessary to wait for the gFindBar
// to close before taking the snapshot so the gFindBar does not take up space
// on the new snapshot.
--- a/toolkit/content/tests/browser/browser_bug982298.js
+++ b/toolkit/content/tests/browser/browser_bug982298.js
@@ -15,16 +15,17 @@ add_task(async function() {
resolve();
},
onCurrentSelection() {},
onMatchesCountResult() {}
};
info("about to add results listener, open find bar, and send 'F' string");
browser.finder.addResultListener(listener);
});
+ await gFindBarPromise;
gFindBar.onFindCommand();
EventUtils.sendString("F");
info("added result listener and sent string 'F'");
await awaitFindResult;
let awaitScrollDone = BrowserTestUtils.waitForMessage(browser.messageManager, "ScrollDone");
// scroll textarea to bottom
const scrollTest =
--- a/toolkit/content/tests/browser/browser_findbar.js
+++ b/toolkit/content/tests/browser/browser_findbar.js
@@ -12,17 +12,17 @@ const E10S_PARENT_TEST_PAGE_URI = "javas
* by calling stopPropagation on a keypress event on a page.
*/
add_task(async function test_hotkey_event_propagation() {
info("Ensure hotkeys are not affected by stopPropagation.");
// Opening new tab
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
let browser = gBrowser.getBrowserForTab(tab);
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
// Pressing these keys open the findbar.
const HOTKEYS = ["/", "'"];
// Checking if findbar appears when any hotkey is pressed.
for (let key of HOTKEYS) {
is(findbar.hidden, true, "Findbar is hidden now.");
gBrowser.selectedTab = tab;
@@ -59,42 +59,42 @@ add_task(async function test_hotkey_even
add_task(async function test_not_found() {
info("Check correct 'Phrase not found' on new tab");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
// Search for the first word.
await promiseFindFinished("--- THIS SHOULD NEVER MATCH ---", false);
- let findbar = gBrowser.getFindBar();
+ let findbar = gBrowser.getCachedFindBar();
is(findbar._findStatusDesc.textContent, findbar._notFoundStr,
"Findbar status text should be 'Phrase not found'");
gBrowser.removeTab(tab);
});
add_task(async function test_found() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
// Search for a string that WILL be found, with 'Highlight All' on
await promiseFindFinished("S", true);
- ok(!gBrowser.getFindBar()._findStatusDesc.textContent,
+ ok(!gBrowser.getCachedFindBar()._findStatusDesc.textContent,
"Findbar status should be empty");
gBrowser.removeTab(tab);
});
// Setting first findbar to case-sensitive mode should not affect
// new tab find bar.
add_task(async function test_tabwise_case_sensitive() {
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
- let findbar1 = gBrowser.getFindBar();
+ let findbar1 = await gBrowser.getFindBar();
let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
- let findbar2 = gBrowser.getFindBar();
+ let findbar2 = await gBrowser.getFindBar();
// Toggle case sensitivity for first findbar
findbar1.getElement("find-case-sensitive").click();
gBrowser.selectedTab = tab1;
// Not found for first tab.
await promiseFindFinished("S", true);
@@ -125,17 +125,17 @@ add_task(async function test_reinitializ
return;
}
info("Ensure findbar re-initialization at remoteness change.");
// Load a remote page and trigger findbar construction.
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
let browser = gBrowser.getBrowserForTab(tab);
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
// Findbar should operate normally.
await promiseFindFinished("z", false);
is(findbar._findStatusDesc.textContent, findbar._notFoundStr,
"Findbar status text should be 'Phrase not found'");
await promiseFindFinished("s", false);
ok(!findbar._findStatusDesc.textContent, "Findbar status should be empty");
@@ -168,16 +168,17 @@ add_task(async function() {
return;
}
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE_URI);
let browser = tab.linkedBrowser;
ok(!gFindBarInitialized, "findbar isn't initialized yet");
+ await gFindBarPromise;
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");
});
@@ -194,19 +195,19 @@ add_task(async function() {
is(document.activeElement, findBar._findField.inputField,
"findbar is now focused");
is(findBar._findField.value, "abc", "abc fully entered as find query");
await BrowserTestUtils.removeTab(tab);
});
function promiseFindFinished(searchText, highlightOn) {
- return new Promise(resolve => {
+ return new Promise(async (resolve) => {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
findbar.startFind(findbar.FIND_NORMAL);
let highlightElement = findbar.getElement("highlight");
if (highlightElement.checked != highlightOn)
highlightElement.click();
executeSoon(() => {
findbar._findField.value = searchText;
let resultListener;
--- a/toolkit/content/tests/browser/browser_quickfind_editable.js
+++ b/toolkit/content/tests/browser/browser_quickfind_editable.js
@@ -1,14 +1,14 @@
const PAGE = "data:text/html,<div contenteditable>foo</div><input><textarea></textarea>";
const DESIGNMODE_PAGE = "data:text/html,<body onload='document.designMode=\"on\";'>";
const HOTKEYS = ["/", "'"];
async function test_hotkeys(browser, expected) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
for (let key of HOTKEYS) {
is(findbar.hidden, true, "findbar is hidden");
await BrowserTestUtils.sendChar(key, gBrowser.selectedBrowser);
is(findbar.hidden, expected, "findbar should" + (expected ? "" : " not") + " be hidden");
if (!expected) {
await closeFindbarAndWait(findbar);
}
}
--- a/toolkit/content/widgets/findbar.xml
+++ b/toolkit/content/widgets/findbar.xml
@@ -415,17 +415,17 @@
we are removed from a document that is not destroyed. This
needs to be explicitly called in this case -->
<method name="destroy">
<body><![CDATA[
if (this._destroyed)
return;
this._destroyed = true;
- if (this.browser.finder)
+ if (this.browser && this.browser.finder)
this.browser.finder.destroy();
this.browser = null;
let prefsvc = this._prefsvc;
prefsvc.removeObserver("accessibility.typeaheadfind",
this._observer);
prefsvc.removeObserver("accessibility.typeaheadfind.linksonly",
--- a/toolkit/modules/tests/browser/browser_FinderHighlighter.js
+++ b/toolkit/modules/tests/browser/browser_FinderHighlighter.js
@@ -44,17 +44,17 @@ add_task(async function testModalResults
["o", {
rectCount: 492,
insertCalls: [1, 4],
removeCalls: [0, 2]
}]
]);
let url = kFixtureBaseURL + "file_FinderSample.html";
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
for (let [word, expectedResult] of tests) {
await promiseOpenFindbar(findbar);
Assert.ok(!findbar.hidden, "Findbar should be open now.");
let timeout = kIteratorTimeout;
if (word.length == 1)
timeout *= 4;
@@ -71,17 +71,17 @@ add_task(async function testModalResults
});
});
// Test if runtime switching of highlight modes between modal and non-modal works
// as expected.
add_task(async function testModalSwitching() {
let url = kFixtureBaseURL + "file_FinderSample.html";
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
Assert.ok(!findbar.hidden, "Findbar should be open now.");
let word = "Roland";
let expectedResult = {
rectCount: 2,
insertCalls: [2, 4],
@@ -108,17 +108,17 @@ add_task(async function testModalSwitchi
await SpecialPowers.pushPrefEnv({ "set": [[ kPrefModalHighlight, true ]] });
});
// Test if highlighting a dark page is detected properly.
add_task(async function testDarkPageDetection() {
let url = kFixtureBaseURL + "file_FinderSample.html";
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
let word = "Roland";
let expectedResult = {
rectCount: 2,
insertCalls: [1, 3],
removeCalls: [0, 1]
@@ -129,17 +129,17 @@ add_task(async function testDarkPageDete
});
await promiseEnterStringIntoFindField(findbar, word);
await promise;
findbar.close(true);
});
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
let word = "Roland";
let expectedResult = {
rectCount: 2,
insertCalls: [2, 4],
removeCalls: [0, 1]
@@ -167,17 +167,17 @@ add_task(async function testDarkPageDete
findbar.close(true);
});
});
add_task(async function testHighlightAllToggle() {
let url = kFixtureBaseURL + "file_FinderSample.html";
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
let word = "Roland";
let expectedResult = {
rectCount: 2,
insertCalls: [2, 4],
removeCalls: [0, 1]
@@ -211,17 +211,17 @@ add_task(async function testHighlightAll
add_task(async function testXMLDocument() {
let url = "data:text/xml;charset=utf-8," + encodeURIComponent(`<?xml version="1.0"?>
<result>
<Title>Example</Title>
<Error>Error</Error>
</result>`);
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
let word = "Example";
let expectedResult = {
rectCount: 0,
insertCalls: [1, 4],
removeCalls: [0, 1]
@@ -233,17 +233,17 @@ add_task(async function testXMLDocument(
findbar.close(true);
});
});
add_task(async function testHideOnLocationChange() {
let url = kFixtureBaseURL + "file_FinderSample.html";
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
let browser = tab.linkedBrowser;
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
let word = "Roland";
let expectedResult = {
rectCount: 2,
insertCalls: [2, 4],
removeCalls: [0, 1]
@@ -262,17 +262,17 @@ add_task(async function testHideOnLocati
await promise;
await BrowserTestUtils.removeTab(tab);
});
add_task(async function testHideOnClear() {
let url = kFixtureBaseURL + "file_FinderSample.html";
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
let word = "Roland";
let expectedResult = {
rectCount: 2,
insertCalls: [2, 4],
removeCalls: [0, 2]
};
@@ -294,17 +294,17 @@ add_task(async function testHideOnClear(
});
add_task(async function testRectsAndTexts() {
let url = "data:text/html;charset=utf-8," +
encodeURIComponent("<div style=\"width: 150px; border: 1px solid black\">" +
"Here are a lot of words Please use find to highlight some words that wrap" +
" across a line boundary and see what happens.</div>");
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
let word = "words please use find to";
let expectedResult = {
rectCount: 2,
insertCalls: [2, 4],
removeCalls: [0, 2]
};
@@ -317,17 +317,17 @@ add_task(async function testRectsAndText
await promiseEnterStringIntoFindField(findbar, word);
await promise;
});
});
add_task(async function testTooLargeToggle() {
let url = kFixtureBaseURL + "file_FinderSample.html";
await BrowserTestUtils.withNewTab(url, async function(browser) {
- let findbar = gBrowser.getFindBar();
+ let findbar = await gBrowser.getFindBar();
await promiseOpenFindbar(findbar);
await ContentTask.spawn(browser, null, async function() {
let dwu = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let uri = "data:text/css;charset=utf-8," + encodeURIComponent(`
body {
min-height: 1234567px;
--- a/toolkit/modules/tests/browser/head.js
+++ b/toolkit/modules/tests/browser/head.js
@@ -20,17 +20,18 @@ function removeDupes(list) {
function compareLists(list1, list2, kind) {
list1.sort();
removeDupes(list1);
list2.sort();
removeDupes(list2);
is(String(list1), String(list2), `${kind} URLs correct`);
}
-function promiseOpenFindbar(findbar) {
+async function promiseOpenFindbar(findbar) {
+ await gBrowser.getFindBar();
findbar.onFindCommand();
return gFindBar._startFindDeferred && gFindBar._startFindDeferred.promise;
}
function promiseFindResult(findbar, str = null) {
let highlightFinished = false;
let findFinished = false;
return new Promise(resolve => {