Bug 1406585 - Close the autocomplete popup when the crash of a content page or Message Manager disconnection happens. r=MattN
MozReview-Commit-ID: DjSc4R0WBQP
--- a/toolkit/components/satchel/AutoCompletePopup.jsm
+++ b/toolkit/components/satchel/AutoCompletePopup.jsm
@@ -96,22 +96,35 @@ this.AutoCompletePopup = {
"FormAutoComplete:RemoveEntry",
"FormAutoComplete:Invalidate",
],
init() {
for (let msg of this.MESSAGES) {
Services.mm.addMessageListener(msg, this);
}
+ Services.obs.addObserver(this, "message-manager-disconnect");
},
uninit() {
for (let msg of this.MESSAGES) {
Services.mm.removeMessageListener(msg, this);
}
+ Services.obs.removeObserver(this, "message-manager-disconnect");
+ },
+
+ observe(subject, topic, data) {
+ switch (topic) {
+ case "message-manager-disconnect": {
+ if (this.openedPopup) {
+ this.openedPopup.closePopup();
+ }
+ break;
+ }
+ }
},
handleEvent(evt) {
switch (evt.type) {
case "popupshowing": {
this.sendMessageToBrowser("FormAutoComplete:PopupOpened");
break;
}
@@ -307,18 +320,24 @@ this.AutoCompletePopup = {
* The name of the message to send.
* @param {object} data
* The optional data to send with the message.
*/
sendMessageToBrowser(msgName, data) {
let browser = this.weakBrowser ?
this.weakBrowser.get() :
null;
- if (browser) {
+ if (!browser) {
+ return;
+ }
+
+ if (browser.messageManager) {
browser.messageManager.sendAsyncMessage(msgName, data);
+ } else {
+ Cu.reportError(`AutoCompletePopup: No messageManager for message "${msgName}"`);
}
},
stopSearch() {},
/**
* Sends a message to the browser requesting that the input
* that the AutoCompletePopup is open for be focused.
--- a/toolkit/components/satchel/test/browser/browser.ini
+++ b/toolkit/components/satchel/test/browser/browser.ini
@@ -1,6 +1,7 @@
[DEFAULT]
support-files =
!/toolkit/components/satchel/test/subtst_privbrowsing.html
+[browser_close_tab.js]
[browser_popup_mouseover.js]
[browser_privbrowsing_perwindowpb.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/satchel/test/browser/browser_close_tab.js
@@ -0,0 +1,59 @@
+/* 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/. */
+
+const {FormHistory} = Cu.import("resource://gre/modules/FormHistory.jsm", {});
+
+add_task(async function test() {
+ const url = `data:text/html,<input type="text" name="field1">`;
+
+ // Open a dummy tab.
+ await BrowserTestUtils.withNewTab({gBrowser, url}, async function(browser) {});
+
+ await BrowserTestUtils.withNewTab({gBrowser, url}, async function(browser) {
+ const {autoCompletePopup} = browser;
+ const mockHistory = [
+ {op: "add", fieldname: "field1", value: "value1"},
+ ];
+
+ await new Promise(resolve =>
+ FormHistory.update([{op: "remove"}, ...mockHistory],
+ {handleCompletion: resolve})
+ );
+ await ContentTask.spawn(browser, {}, async function() {
+ const input = content.document.querySelector("input");
+
+ input.focus();
+ });
+
+ // show popup
+ await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
+ await TestUtils.waitForCondition(() => {
+ return autoCompletePopup.popupOpen;
+ });
+
+ let listener;
+ let errorLogPromise = new Promise(resolve => {
+ listener = ({message}) => {
+ const ERROR_MSG = "AutoCompletePopup: No messageManager for " +
+ "message \"FormAutoComplete:PopupClosed\"";
+ if (message.includes(ERROR_MSG)) {
+ Assert.ok(true, "Got the error message for inexistent messageManager.");
+ Services.console.unregisterListener(listener);
+ resolve();
+ }
+ };
+ });
+ Services.console.registerListener(listener);
+
+ gBrowser.removeCurrentTab();
+
+ await TestUtils.waitForCondition(() => {
+ return !autoCompletePopup.popupOpen;
+ });
+
+ Assert.ok(!autoCompletePopup.popupOpen, "Ensure the popup is closed.");
+
+ await errorLogPromise;
+ });
+});