Bug 1267289 - add more URL bar tests and fix issue with error pages, r=mikedeboer,mconley

This adds tests for issues brought up in bug 231393, bug 264610, bug 302575 and bug 1129564,
all of which fed into the current implementation of userTypedClear/userTypedValue. I intend
to move us away from userTypedClear, but I'm keen not to regress any of these issues, so
I'm adding automated tests to ensure that doesn't happen.

MozReview-Commit-ID: 1up2MIXzkzG

--HG--
extra : rebase_source : 4d37f13895b8c7e7aba5331664718582c6b2136c
This commit is contained in:
Gijs Kruitbosch 2016-04-25 17:27:35 +01:00
Родитель bfa6750d68
Коммит 1d863b1c09
7 изменённых файлов: 229 добавлений и 9 удалений

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

@ -51,6 +51,8 @@ support-files =
[browser_urlbarEnter.js]
[browser_urlbarEnterAfterMouseOver.js]
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
[browser_urlbarHashChangeProxyState.js]
[browser_urlbarKeepStateAcrossTabSwitches.js]
[browser_urlbarRevert.js]
[browser_urlbarSearchSingleWordNotification.js]
[browser_urlbarSearchSuggestions.js]
@ -67,6 +69,7 @@ support-files =
searchSuggestionEngine.sjs
[browser_urlbarStop.js]
[browser_urlbarTrimURLs.js]
[browser_urlbarUpdateForDomainCompletion.js]
[browser_urlbar_autoFill_backspaced.js]
[browser_urlbar_blanking.js]
support-files =

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

@ -0,0 +1,111 @@
"use strict";
/**
* Check that navigating through both the URL bar and using in-page hash- or ref-
* based links and back or forward navigation updates the URL bar and identity block correctly.
*/
add_task(function* () {
let baseURL = "https://example.org/browser/browser/base/content/test/urlbar/dummy_page.html";
let url = baseURL + "#foo";
yield BrowserTestUtils.withNewTab({ gBrowser, url }, function(browser) {
let identityBox = document.getElementById("identity-box");
let expectedURL = url;
let verifyURLBarState = testType => {
is(gURLBar.textValue, expectedURL, "URL bar visible value should be correct " + testType);
is(gURLBar.value, expectedURL, "URL bar value should be correct " + testType);
ok(identityBox.classList.contains("verifiedDomain"), "Identity box should know we're doing SSL " + testType);
is(gURLBar.getAttribute("pageproxystate"), "valid", "URL bar is in valid page proxy state");
};
verifyURLBarState("at the beginning");
let locationChangePromise;
let resolveLocationChangePromise;
let expectURL = url => {
expectedURL = url;
locationChangePromise = new Promise(r => resolveLocationChangePromise = r);
};
let wpl = {
onLocationChange(wpl, request, location, flags) {
is(location.spec, expectedURL, "Got the expected URL");
resolveLocationChangePromise();
},
};
gBrowser.addProgressListener(wpl);
expectURL(baseURL + "#foo");
gURLBar.select();
EventUtils.sendKey("return");
yield locationChangePromise;
verifyURLBarState("after hitting enter on the same URL a second time");
expectURL(baseURL + "#bar");
gURLBar.value = expectedURL;
gURLBar.select();
EventUtils.sendKey("return");
yield locationChangePromise;
verifyURLBarState("after a URL bar hash navigation");
expectURL(baseURL + "#foo");
yield ContentTask.spawn(browser, null, function() {
let a = content.document.createElement("a");
a.href = "#foo";
a.textContent = "Foo Link";
content.document.body.appendChild(a);
a.click();
});
yield locationChangePromise;
verifyURLBarState("after a page link hash navigation");
expectURL(baseURL + "#bar");
gBrowser.goBack();
yield locationChangePromise;
verifyURLBarState("after going back");
expectURL(baseURL + "#foo");
gBrowser.goForward();
yield locationChangePromise;
verifyURLBarState("after going forward");
expectURL(baseURL + "#foo");
gURLBar.select();
EventUtils.sendKey("return");
yield locationChangePromise;
verifyURLBarState("after hitting enter on the same URL");
gBrowser.removeProgressListener(wpl);
});
});
/**
* Check that initial secure loads that swap remoteness
* get the correct page icon when finished.
*/
add_task(function* () {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
// NB: CPOW usage because new tab pages can be preloaded, in which case no
// load events fire.
yield BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
let url = "https://example.org/browser/browser/base/content/test/urlbar/dummy_page.html#foo";
gURLBar.value = url;
gURLBar.select();
EventUtils.sendKey("return");
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
is(gURLBar.textValue, url, "URL bar visible value should be correct when the page loads from about:newtab");
is(gURLBar.value, url, "URL bar value should be correct when the page loads from about:newtab");
let identityBox = document.getElementById("identity-box");
ok(identityBox.classList.contains("verifiedDomain"),
"Identity box should know we're doing SSL when the page loads from about:newtab");
is(gURLBar.getAttribute("pageproxystate"), "valid",
"URL bar is in valid page proxy state when SSL page with hash loads from about:newtab");
yield BrowserTestUtils.removeTab(tab);
});

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

@ -0,0 +1,49 @@
"use strict";
/**
* Verify user typed text remains in the URL bar when tab switching, even when
* loads fail.
*/
add_task(function* () {
let input = "i-definitely-dont-exist.example.com";
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
// NB: CPOW usage because new tab pages can be preloaded, in which case no
// load events fire.
yield BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
let errorPageLoaded = BrowserTestUtils.waitForErrorPage(tab.linkedBrowser);
gURLBar.value = input;
gURLBar.select();
EventUtils.sendKey("return");
yield errorPageLoaded;
is(gURLBar.textValue, input, "Text is still in URL bar");
yield BrowserTestUtils.switchTab(gBrowser, tab.previousSibling);
yield BrowserTestUtils.switchTab(gBrowser, tab);
is(gURLBar.textValue, input, "Text is still in URL bar after tab switch");
yield BrowserTestUtils.removeTab(tab);
});
/**
* Invalid URIs fail differently (that is, immediately, in the loadURI call)
* if keyword searches are turned off. Test that this works, too.
*/
add_task(function* () {
let input = "To be or not to be-that is the question";
yield new Promise(resolve => SpecialPowers.pushPrefEnv({set: [["keyword.enabled", false]]}, resolve));
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
// NB: CPOW usage because new tab pages can be preloaded, in which case no
// load events fire.
yield BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
let errorPageLoaded = BrowserTestUtils.waitForErrorPage(tab.linkedBrowser);
gURLBar.value = input;
gURLBar.select();
EventUtils.sendKey("return");
yield errorPageLoaded;
is(gURLBar.textValue, input, "Text is still in URL bar");
is(tab.linkedBrowser.userTypedValue, input, "Text still stored on browser");
yield BrowserTestUtils.switchTab(gBrowser, tab.previousSibling);
yield BrowserTestUtils.switchTab(gBrowser, tab);
is(gURLBar.textValue, input, "Text is still in URL bar after tab switch");
is(tab.linkedBrowser.userTypedValue, input, "Text still stored on browser");
yield BrowserTestUtils.removeTab(tab);
});

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

@ -0,0 +1,17 @@
"use strict";
/**
* Disable keyword.enabled (so no keyword search), and check that when you type in
* "example" and hit enter, the browser loads and the URL bar is updated accordingly.
*/
add_task(function* () {
yield new Promise(resolve => SpecialPowers.pushPrefEnv({set: [["keyword.enabled", false]]}, resolve));
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (browser) {
gURLBar.value = "example";
gURLBar.select();
let loadPromise = BrowserTestUtils.browserLoaded(browser, false, url => url == "http://www.example.com/");
EventUtils.sendKey("return");
yield loadPromise;
is(gURLBar.textValue, "www.example.com");
});
});

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

@ -815,11 +815,14 @@ var SessionStoreInternal = {
} else {
// If the user was typing into the URL bar when we crashed, but hadn't hit
// enter yet, then we just need to write that value to the URL bar without
// loading anything. This must happen after the load, since it will clear
// loading anything. This must happen after the load, as the load will clear
// userTypedValue.
let tabData = TabState.collect(tab);
if (tabData.userTypedValue && !tabData.userTypedClear) {
browser.userTypedValue = tabData.userTypedValue;
if (data.didStartLoad) {
browser.userTypedClear++;
}
win.URLBarSetURI();
}
@ -2527,7 +2530,6 @@ var SessionStoreInternal = {
tabState.index = historyIndex + 1;
tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length));
} else {
tabState.userTypedValue = null;
options.loadArguments = recentLoadArguments;
}

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

@ -177,7 +177,7 @@ var MessageListener = {
sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
});
sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch});
sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch, didStartLoad});
if (!didStartLoad) {
// Pretend that the load succeeded so that event handlers fire correctly.

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

@ -528,6 +528,8 @@ this.BrowserTestUtils = {
* event is the expected one, or false if it should be ignored and
* listening should continue. If not specified, the first event with
* the specified name resolves the returned promise.
* @param {bool} wantsUntrusted [optional]
* Whether to accept untrusted events
*
* @note Because this function is intended for testing, any error in checkFn
* will cause the returned promise to be rejected instead of waiting for
@ -535,12 +537,15 @@ this.BrowserTestUtils = {
*
* @returns {Promise}
*/
waitForContentEvent(browser, eventName, capture, checkFn) {
let parameters = { eventName,
capture,
checkFnSource: checkFn ? checkFn.toSource() : null };
waitForContentEvent(browser, eventName, capture = false, checkFn, wantsUntrusted = false) {
let parameters = {
eventName,
capture,
checkFnSource: checkFn ? checkFn.toSource() : null,
wantsUntrusted,
};
return ContentTask.spawn(browser, parameters,
function({ eventName, capture, checkFnSource }) {
function({ eventName, capture, checkFnSource, wantsUntrusted }) {
let checkFn;
if (checkFnSource) {
checkFn = eval(`(() => (${checkFnSource}))()`);
@ -557,11 +562,44 @@ this.BrowserTestUtils = {
}
removeEventListener(eventName, listener, capture);
completion();
}, capture);
}, capture, wantsUntrusted);
});
});
},
/**
* Like browserLoaded, but waits for an error page to appear.
* This explicitly deals with cases where the browser is not currently remote and a
* remoteness switch will occur before the error page is loaded, which is tricky
* because error pages don't fire 'regular' load events that we can rely on.
*
* @param {xul:browser} browser
* A xul:browser.
*
* @return {Promise}
* @resolves When an error page has been loaded in the browser.
*/
waitForErrorPage(browser) {
let waitForLoad = () =>
this.waitForContentEvent(browser, "AboutNetErrorLoad", false, null, true);
let win = browser.ownerDocument.defaultView;
let tab = win.gBrowser.getTabForBrowser(browser);
if (!tab || browser.isRemoteBrowser || !win.gMultiProcessBrowser) {
return waitForLoad();
}
// We're going to switch remoteness when loading an error page. We need to be
// quite careful in order to make sure we're adding the listener in time to
// get this event:
return new Promise((resolve, reject) => {
tab.addEventListener("TabRemotenessChange", function onTRC() {
tab.removeEventListener("TabRemotenessChange", onTRC);
waitForLoad().then(resolve, reject);
});
});
},
/**
* Versions of EventUtils.jsm synthesizeMouse functions that synthesize a
* mouse event in a child process and return promises that resolve when the