Bug 1194669 - Dismissing the urlbar search suggestions opt-in notification in one window should dismiss it in all windows. r=mak

This commit is contained in:
Drew Willcoxon 2015-08-26 10:41:36 -07:00
parent 0860025d7d
commit 28016c14ec
2 changed files with 134 additions and 46 deletions

View File

@ -18,7 +18,7 @@ add_task(function* prepare() {
// Disable the notification for future tests so it doesn't interfere with
// them. clearUserPref() won't work because by default the pref is false.
Services.prefs.setBoolPref(CHOICE_PREF, true);
yield setUserMadeChoicePref(true);
// Make sure the popup is closed for the next test.
gURLBar.blur();
@ -30,7 +30,7 @@ add_task(function* focus() {
// Focusing the urlbar used to open the popup in order to show the
// notification, but it doesn't anymore. Make sure it does not.
Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
Services.prefs.setBoolPref(CHOICE_PREF, false);
yield setUserMadeChoicePref(false);
gURLBar.blur();
gURLBar.focus();
Assert.ok(!gURLBar.popup.popupOpen, "popup should remain closed");
@ -38,7 +38,7 @@ add_task(function* focus() {
add_task(function* dismissWithoutResults() {
Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
Services.prefs.setBoolPref(CHOICE_PREF, false);
yield setUserMadeChoicePref(false);
gURLBar.blur();
gURLBar.focus();
let popupPromise = promisePopupShown(gURLBar.popup);
@ -64,7 +64,7 @@ add_task(function* dismissWithoutResults() {
add_task(function* dismissWithResults() {
Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
Services.prefs.setBoolPref(CHOICE_PREF, false);
yield setUserMadeChoicePref(false);
gURLBar.blur();
gURLBar.focus();
yield promiseAutocompleteResultPopup("foo");
@ -88,7 +88,7 @@ add_task(function* dismissWithResults() {
add_task(function* disable() {
Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
Services.prefs.setBoolPref(CHOICE_PREF, false);
yield setUserMadeChoicePref(false);
gURLBar.blur();
gURLBar.focus();
yield promiseAutocompleteResultPopup("foo");
@ -102,32 +102,32 @@ add_task(function* disable() {
yield transitionPromise;
gURLBar.blur();
yield promiseAutocompleteResultPopup("foo");
assertSuggestionsPresent(false);
Assert.ok(!suggestionsPresent());
});
add_task(function* enable() {
Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, false);
Services.prefs.setBoolPref(CHOICE_PREF, false);
yield setUserMadeChoicePref(false);
gURLBar.blur();
gURLBar.focus();
yield promiseAutocompleteResultPopup("foo");
assertVisible(true);
assertSuggestionsPresent(false);
Assert.ok(!suggestionsPresent());
let enableButton = document.getAnonymousElementByAttribute(
gURLBar.popup, "anonid", "search-suggestions-notification-enable"
);
let searchPromise = promiseSearchComplete();
let searchPromise = promiseSuggestionsPresent();
enableButton.click();
yield searchPromise;
// Clicking Yes should trigger a new search so that suggestions appear
// immediately.
assertSuggestionsPresent(true);
Assert.ok(suggestionsPresent());
gURLBar.blur();
gURLBar.focus();
// Suggestions should still be present in a new search of course.
yield promiseAutocompleteResultPopup("bar");
assertSuggestionsPresent(true);
Assert.ok(suggestionsPresent());
});
add_task(function* privateWindow() {
@ -142,10 +142,76 @@ add_task(function* privateWindow() {
yield BrowserTestUtils.closeWindow(win);
});
function assertSuggestionsPresent(expectedPresent) {
add_task(function* multipleWindows() {
// Opening multiple windows, using their urlbars, and then dismissing the
// notification in one should dismiss the notification in all.
Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, false);
yield setUserMadeChoicePref(false);
gURLBar.focus();
yield promiseAutocompleteResultPopup("win1");
assertVisible(true);
let win2 = yield BrowserTestUtils.openNewBrowserWindow();
win2.gURLBar.focus();
yield promiseAutocompleteResultPopup("win2", win2);
assertVisible(true, win2);
let win3 = yield BrowserTestUtils.openNewBrowserWindow();
win3.gURLBar.focus();
yield promiseAutocompleteResultPopup("win3", win3);
assertVisible(true, win3);
let enableButton = win3.document.getAnonymousElementByAttribute(
win3.gURLBar.popup, "anonid", "search-suggestions-notification-enable"
);
let transitionPromise = promiseTransition(win3);
enableButton.click();
yield transitionPromise;
assertVisible(false, win3);
win2.gURLBar.focus();
yield promiseAutocompleteResultPopup("win2done", win2);
assertVisible(false, win2);
gURLBar.focus();
yield promiseAutocompleteResultPopup("win1done");
assertVisible(false);
yield BrowserTestUtils.closeWindow(win2);
yield BrowserTestUtils.closeWindow(win3);
});
/**
* Setting the choice pref triggers a pref observer in the urlbar, which hides
* the notification if it's present. This function returns a promise that's
* resolved once the observer fires.
*
* @param userMadeChoice A boolean, the pref's new value.
* @return A Promise that's resolved when the observer fires -- or, if the pref
* is currently the given value, that's resolved immediately.
*/
function setUserMadeChoicePref(userMadeChoice) {
return new Promise(resolve => {
let currentUserMadeChoice = Services.prefs.getBoolPref(CHOICE_PREF);
if (currentUserMadeChoice != userMadeChoice) {
Services.prefs.addObserver(CHOICE_PREF, function obs(subj, topic, data) {
Services.prefs.removeObserver(CHOICE_PREF, obs);
resolve();
}, false);
}
Services.prefs.setBoolPref(CHOICE_PREF, userMadeChoice);
if (currentUserMadeChoice == userMadeChoice) {
resolve();
}
});
}
function suggestionsPresent() {
let controller = gURLBar.popup.input.controller;
let matchCount = controller.matchCount;
let actualPresent = false;
let present = false;
for (let i = 0; i < matchCount; i++) {
let url = controller.getValueAt(i);
let [, type, paramStr] = url.match(/^moz-action:([^,]+),(.*)$/);
@ -153,10 +219,17 @@ function assertSuggestionsPresent(expectedPresent) {
try {
params = JSON.parse(paramStr);
} catch (err) {}
let isSuggestion = type == "searchengine" && "searchSuggestion" in params;
actualPresent = actualPresent || isSuggestion;
if (type == "searchengine" && "searchSuggestion" in params) {
return true;
}
}
Assert.equal(actualPresent, expectedPresent);
return false;
}
function promiseSuggestionsPresent() {
return new Promise(resolve => {
waitForCondition(suggestionsPresent, resolve);
});
}
function assertVisible(visible, win=window) {
@ -165,10 +238,10 @@ function assertVisible(visible, win=window) {
Assert.equal(style.visibility, visible ? "visible" : "collapse");
}
function promiseTransition() {
function promiseTransition(win=window) {
return new Promise(resolve => {
gURLBar.popup.addEventListener("transitionend", function onEnd() {
gURLBar.popup.removeEventListener("transitionend", onEnd, true);
win.gURLBar.popup.addEventListener("transitionend", function onEnd() {
win.gURLBar.popup.removeEventListener("transitionend", onEnd, true);
// The urlbar needs to handle the transitionend first, but that happens
// naturally since promises are resolved at the end of the current tick.
resolve();

View File

@ -665,6 +665,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
case "userMadeSearchSuggestionsChoice":
this._userMadeSearchSuggestionsChoice =
this._prefs.getBoolPref(aData);
this.popup.searchSuggestionsNotificationWasDismissed(
this._prefs.getBoolPref("suggest.searches")
);
break;
case "trimURLs":
this._mayTrimURLs = this._prefs.getBoolPref(aData);
@ -1553,17 +1556,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<method name="dismissSearchSuggestionsNotification">
<parameter name="enableSuggestions"/>
<body><![CDATA[
Services.prefs.setBoolPref(
"browser.urlbar.userMadeSearchSuggestionsChoice", true
);
Services.prefs.setBoolPref(
"browser.urlbar.suggest.searches", enableSuggestions
);
this._hideSearchSuggestionsNotification(true);
if (enableSuggestions && this.input.textValue) {
// Start a new search so that suggestions appear immediately.
this.input.controller.startSearch(this.input.textValue);
}
Services.prefs.setBoolPref(
"browser.urlbar.userMadeSearchSuggestionsChoice", true
);
// The input's pref observer will now hide the notification.
]]></body>
</method>
@ -1688,14 +1687,27 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
</body>
</method>
<method name="_hideSearchSuggestionsNotification">
<parameter name="animate"/>
<method name="searchSuggestionsNotificationWasDismissed">
<parameter name="enableSuggestions"/>
<body>
<![CDATA[
if (animate) {
this._hideSearchSuggestionsNotificationWithAnimation();
if (!this.popupOpen) {
this._hideSearchSuggestionsNotification();
return;
}
this._hideSearchSuggestionsNotificationWithAnimation().then(() => {
if (enableSuggestions && this.input.textValue) {
// Start a new search so that suggestions appear immediately.
this.input.controller.startSearch(this.input.textValue);
}
});
]]>
</body>
</method>
<method name="_hideSearchSuggestionsNotification">
<body>
<![CDATA[
this.classList.remove("showSearchSuggestionsNotification");
this.richlistbox.flex = 1;
this.removeAttribute("dontanimate");
@ -1712,23 +1724,26 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<method name="_hideSearchSuggestionsNotificationWithAnimation">
<body>
<![CDATA[
let notificationHeight = this.searchSuggestionsNotification
.getBoundingClientRect()
.height;
this.searchSuggestionsNotification.style.marginTop =
"-" + notificationHeight + "px";
return new Promise(resolve => {
let notificationHeight = this.searchSuggestionsNotification
.getBoundingClientRect()
.height;
this.searchSuggestionsNotification.style.marginTop =
"-" + notificationHeight + "px";
let popupHeightPx =
(this.getBoundingClientRect().height - notificationHeight) + "px";
this.style.height = popupHeightPx;
let popupHeightPx =
(this.getBoundingClientRect().height - notificationHeight) + "px";
this.style.height = popupHeightPx;
let onTransitionEnd = () => {
this.removeEventListener("transitionend", onTransitionEnd, true);
this.searchSuggestionsNotification.style.marginTop = "0px";
this.style.removeProperty("height");
this._hideSearchSuggestionsNotification(false);
};
this.addEventListener("transitionend", onTransitionEnd, true);
let onTransitionEnd = () => {
this.removeEventListener("transitionend", onTransitionEnd, true);
this.searchSuggestionsNotification.style.marginTop = "0px";
this.style.removeProperty("height");
this._hideSearchSuggestionsNotification();
resolve();
};
this.addEventListener("transitionend", onTransitionEnd, true);
});
]]>
</body>
</method>