--- a/suite/common/dataman/dataman.js
+++ b/suite/common/dataman/dataman.js
@@ -437,33 +437,52 @@ var gDomains = {
getDomainFromHost: function domain_getDomainFromHost(aHostname) {
// Find the base domain name for the given host name.
if (!this.xlcache[aHostname]) {
// aHostname is not always an actual host name, but potentially something
// URI-like, e.g. gopher://example.com and newURI doesn't work there as we
// need to display entries for schemes that are not supported (any more).
// nsIURLParser is a fast way to generically ensure a pure host name.
+ var hostName;
// Return vars for nsIURLParser must all be objects,
// see bug 568997 for improvements to that interface.
var schemePos = {}, schemeLen = {}, authPos = {}, authLen = {}, pathPos = {},
pathLen = {}, usernamePos = {}, usernameLen = {}, passwordPos = {},
passwordLen = {}, hostnamePos = {}, hostnameLen = {}, port = {};
- gLocSvc.url.parseURL(aHostname, -1, schemePos, schemeLen, authPos, authLen,
- pathPos, pathLen);
- var auth = aHostname.substring(authPos.value, authPos.value + authLen.value);
- gLocSvc.url.parseAuthority(auth, authLen.value, usernamePos, usernameLen,
- passwordPos, passwordLen, hostnamePos, hostnameLen, port);
- var hostName = auth.substring(hostnamePos.value, hostnamePos.value + hostnameLen.value);
+ try {
+ gLocSvc.url.parseURL(aHostname, -1, schemePos, schemeLen, authPos, authLen,
+ pathPos, pathLen);
+ var auth = aHostname.substring(authPos.value, authPos.value + authLen.value);
+ gLocSvc.url.parseAuthority(auth, authLen.value, usernamePos, usernameLen,
+ passwordPos, passwordLen, hostnamePos, hostnameLen, port);
+ hostName = auth.substring(hostnamePos.value, hostnamePos.value + hostnameLen.value);
+ }
+ catch (e) {
+ // IPv6 host names can come in without [] around them and therefore
+ // cause an error. Those consist of at least two colons and else only
+ // hexadecimal digits. Fix them by putting [] around them.
+ if (/^[a-f0-9]*:[a-f0-9]*:[a-f0-9:]*$/.test(aHostname)) {
+ gDataman.debugMsg("bare IPv6 address found: " + aHostname);
+ hostName = "[" + aHostname + "]";
+ }
+ else {
+ gDataman.debugError("Error while trying to get hostname from input: " + aHostname);
+ gDataman.debugError(e);
+ hostName = aHostname;
+ }
+ }
var domain;
try {
domain = Services.eTLD.getBaseDomainFromHost(hostName);
}
catch (e) {
+ gDataman.debugError("Error while trying to get domain from host name: " + hostName);
+ gDataman.debugError(e);
domain = hostName;
}
this.xlcache[aHostname] = domain;
gDataman.debugMsg("cached: " + aHostname + " -> " + this.xlcache[aHostname]);
}
return this.xlcache[aHostname];
},
@@ -1131,19 +1150,21 @@ var gCookies = {
}
}
}
},
forget: function cookies_forget() {
for (let i = 0; i < this.cookies.length; i++) {
if (gDomains.hostMatchesSelected(this.cookies[i].rawHost)) {
- Services.cookies.remove(this.cookies[i].host, this.cookies[i].name,
- this.cookies[i].path, false);
+ // Remove from internal list needs to be before actually deleting.
+ let delCookie = this.cookies[i];
this.cookies.splice(i, 1);
+ Services.cookies.remove(delCookie.host, delCookie.name,
+ delCookie.path, false);
}
}
gDomains.removeDomainOrFlag(gDomains.selectedDomain.title, "hasCookies");
},
// nsITreeView
__proto__: gBaseTreeView,
get rowCount() {
@@ -2100,18 +2121,20 @@ var gPasswords = {
}
}
}
},
forget: function passwords_forget() {
for (let i = 0; i < this.allSignons.length; i++) {
if (gDomains.hostMatchesSelected(this.allSignons[i].hostname)) {
- Services.logins.removeLogin(this.allSignons[i]);
+ // Remove from internal list needs to be before actually deleting.
+ let delSignon = this.allSignons[i];
this.allSignons.splice(i, 1);
+ Services.logins.removeLogin(delSignon);
}
}
gDomains.removeDomainOrFlag(gDomains.selectedDomain.title, "hasPasswords");
},
// nsITreeView
__proto__: gBaseTreeView,
get rowCount() {
--- a/suite/common/dataman/tests/browser_dataman_basics.js
+++ b/suite/common/dataman/tests/browser_dataman_basics.js
@@ -40,16 +40,20 @@ function test() {
false, true, true, now_epoch + 600);
// Add cookie: secure, HTTPOnly, session
Services.cookies.add("secure.geckoisgecko.org", "", "name2", "value2",
true, true, true, now_epoch + 600);
// Add cookie: secure, non-HTTPOnly, expiry in an hour
Services.cookies.add("drumbeat.org", "", "name3", "value3",
true, false, false, now_epoch + 3600);
+ // Add a cookie for a pure IPv6 address.
+ Services.cookies.add("::1", "", "name4", "value4",
+ false, false, true, now_epoch + 600);
+
// Add a few form history entries
gLocSvc.fhist.addEntry("akey", "value0");
gLocSvc.fhist.addEntry("ekey", "value1");
gLocSvc.fhist.addEntry("ekey", "value2");
gLocSvc.fhist.addEntry("bkey", "value3");
gLocSvc.fhist.addEntry("bkey", "value4");
gLocSvc.fhist.addEntry("ckey", "value5");
@@ -59,16 +63,21 @@ function test() {
loginInfo1.init("http://www.geckoisgecko.org", "http://www.geckoisgecko.org", null,
"dataman", "mysecret", "user", "pwd");
Services.logins.addLogin(loginInfo1);
let loginInfo2 = Components.classes["@mozilla.org/login-manager/loginInfo;1"]
.createInstance(Components.interfaces.nsILoginInfo);
loginInfo2.init("gopher://geckoisgecko.org:4711", null, "foo",
"dataman", "mysecret", "", "");
Services.logins.addLogin(loginInfo2);
+ let loginInfo3 = Components.classes["@mozilla.org/login-manager/loginInfo;1"]
+ .createInstance(Components.interfaces.nsILoginInfo);
+ loginInfo3.init("https://[::1]", null, "foo",
+ "dataman", "mysecret", "", "");
+ Services.logins.addLogin(loginInfo3);
//Services.prefs.setBoolPref("data_manager.debug", true);
gBrowser.addTab();
// Open the Data Manager, testing the menu item.
document.getElementById("tasksDataman").click();
var testIndex = 0;
@@ -84,37 +93,37 @@ function test() {
Services.obs.addObserver(testObs, TEST_DONE, false);
// Trigger the first test now!
Services.obs.notifyObservers(window, TEST_DONE, null);
}
else {
// TEST_DONE triggered, run next test
info("run test #" + (testIndex + 1) + " of " + testFuncs.length +
" (" + testFuncs[testIndex].name + ")");
- testFuncs[testIndex++](win);
+ setTimeout(testFuncs[testIndex++], 0, win);
if (testIndex >= testFuncs.length) {
// Finish this up!
Services.obs.removeObserver(testObs, TEST_DONE);
Services.cookies.removeAll();
gLocSvc.fhist.removeAllEntries();
- finish();
+ setTimeout(finish, 0);
}
}
}
};
waitForExplicitFinish();
Services.obs.addObserver(testObs, DATAMAN_LOADED, false);
}
var testFuncs = [
function test_open_state(aWin) {
is(aWin.document.documentElement.id, "dataman-page",
"The active tab is the Data Manager");
- is(aWin.gDomains.tree.view.rowCount, gPreexistingDomains + 5,
+ is(aWin.gDomains.tree.view.rowCount, gPreexistingDomains + 6,
"The correct number of domains is listed");
is(aWin.gTabs.activePanel, "formdataPanel",
"Form data panel is selected");
aWin.document.getElementById("domainSearch").value = "mo";
aWin.document.getElementById("domainSearch").doCommand();
is(aWin.gDomains.tree.view.selection.count, 0,
"In search, non-matching selection is lost");
@@ -123,22 +132,47 @@ function test_open_state(aWin) {
is(aWin.gDomains.displayedDomains.map(function(aDom) { return aDom.title; })
.join(","),
"mochi.test,mozilla.com,mozilla.org",
"In search, the correct domains are listed");
aWin.gDomains.tree.view.selection.select(0);
aWin.document.getElementById("domainSearch").value = "";
aWin.document.getElementById("domainSearch").doCommand();
- is(aWin.gDomains.tree.view.rowCount, gPreexistingDomains + 5,
+ is(aWin.gDomains.tree.view.rowCount, gPreexistingDomains + 6,
"After search, the correct number of domains is listed");
is(aWin.gDomains.tree.view.selection.count, 1,
"After search, number of selections is correct");
is(aWin.gDomains.selectedDomain.title, "mochi.test",
"After search, matching selection is kept correctly");
+ Services.obs.notifyObservers(window, TEST_DONE, null);
+},
+
+function test_forget_ipv6(aWin) {
+ // The main purpose of IPv6 entries is that things load, delete them ASAP.
+ // Better forget panel tests (more checks) are in test_prefs_panel below.
+ aWin.gDomains.tree.view.selection.select(1);
+ is(aWin.gDomains.selectedDomain.title, "[::1]",
+ "IPv6 domain is selected");
+ aWin.document.getElementById("domain-context-forget").click();
+ is(aWin.gTabs.activePanel, "forgetPanel",
+ "Forget panel is selected");
+
+ aWin.document.getElementById("forgetCookies").click();
+ aWin.document.getElementById("forgetPasswords").click();
+ aWin.document.getElementById("forgetButton").click();
+ is(aWin.document.getElementById("forgetTab").hidden, true,
+ "Forget tab is hidden again");
+ is(aWin.document.getElementById("forgetTab").disabled, true,
+ "Forget panel is disabled again");
+
+ is(aWin.gDomains.tree.view.rowCount, gPreexistingDomains + 5,
+ "The IPv6 domain has been removed from the list");
+ is(aWin.gDomains.tree.view.selection.count, 0,
+ "No domain is selected");
aWin.gDomains.tree.view.selection.select(0);
is(aWin.gDomains.selectedDomain.title, "*",
"* domain is selected again");
Services.obs.notifyObservers(window, TEST_DONE, null);
},
function test_fdata_panel(aWin) {
@@ -253,17 +287,17 @@ function test_cookies_panel(aWin) {
is(aWin.document.getElementById("cookies-context-selectall").disabled, false,
"The select all context menu item is enabled");
is(aWin.document.getElementById("cookies-context-remove").disabled, true,
"The remove context menu item is disabled");
aWin.document.getElementById("cookies-context-selectall").click();
is(aWin.document.getElementById("cookieInfoSendType").value,
"Encrypted connections only",
- "Correct send type for third cookie");
+ "Correct send type for fourth cookie");
isnot(aWin.document.getElementById("cookieInfoExpires").value,
"At end of session",
"Expiry label for this cookie is not session");
aWin.gCookies.updateContext(); // don't actually open it, would be async
is(aWin.document.getElementById("cookies-context-selectall").disabled, true,
"After selecting, the select all context menu item is disabled");
is(aWin.document.getElementById("cookies-context-remove").disabled, false,
"After selecting, the remove context menu item is enabled");