mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 485701 - Add sort markers/arrows to Password Manager and keep sort direction when clearing filter. r=dolske
This commit is contained in:
parent
ef0be5285c
commit
db69081524
@ -115,7 +115,11 @@ function LoadSignons() {
|
||||
|
||||
// sort and display the table
|
||||
signonsTree.treeBoxObject.view = signonsTreeView;
|
||||
SignonColumnSort('hostname');
|
||||
// The sort column didn't change. SortTree (called by
|
||||
// SignonColumnSort) assumes we want to toggle the sort
|
||||
// direction but here we don't so we have to trick it
|
||||
lastSignonSortAscending = !lastSignonSortAscending;
|
||||
SignonColumnSort(lastSignonSortColumn);
|
||||
|
||||
// disable "remove all signons" button if there are no signons
|
||||
var element = document.getElementById("removeAllSignons");
|
||||
@ -238,15 +242,37 @@ function HandleSignonKeyPress(e) {
|
||||
}
|
||||
}
|
||||
|
||||
var lastSignonSortColumn = "";
|
||||
var lastSignonSortAscending = false;
|
||||
function getColumnByName(column) {
|
||||
switch (column) {
|
||||
case "hostname":
|
||||
return document.getElementById("siteCol");
|
||||
case "username":
|
||||
return document.getElementById("userCol");
|
||||
case "password":
|
||||
return document.getElementById("passwordCol");
|
||||
}
|
||||
}
|
||||
|
||||
var lastSignonSortColumn = "hostname";
|
||||
var lastSignonSortAscending = true;
|
||||
|
||||
function SignonColumnSort(column) {
|
||||
// clear out the sortDirection attribute on the old column
|
||||
var lastSortedCol = getColumnByName(lastSignonSortColumn);
|
||||
lastSortedCol.removeAttribute("sortDirection");
|
||||
|
||||
// sort
|
||||
lastSignonSortAscending =
|
||||
SortTree(signonsTree, signonsTreeView,
|
||||
signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons,
|
||||
column, lastSignonSortColumn, lastSignonSortAscending);
|
||||
lastSignonSortColumn = column;
|
||||
|
||||
// set the sortDirection attribute to get the styling going
|
||||
// first we need to get the right element
|
||||
var sortedCol = getColumnByName(column);
|
||||
sortedCol.setAttribute("sortDirection", lastSignonSortAscending ?
|
||||
"ascending" : "descending");
|
||||
}
|
||||
|
||||
function SignonClearFilter() {
|
||||
@ -258,8 +284,6 @@ function SignonClearFilter() {
|
||||
signonsTreeView._filterSet = [];
|
||||
|
||||
// Just reload the list to make sure deletions are respected
|
||||
lastSignonSortColumn = "";
|
||||
lastSignonSortAscending = false;
|
||||
LoadSignons();
|
||||
|
||||
// Restore selection
|
||||
|
@ -81,7 +81,8 @@
|
||||
onselect="SignonSelected();">
|
||||
<treecols>
|
||||
<treecol id="siteCol" label="&treehead.site.label;" flex="5"
|
||||
onclick="SignonColumnSort('hostname');" persist="width"/>
|
||||
onclick="SignonColumnSort('hostname');" persist="width"
|
||||
sortDirection="ascending"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="userCol" label="&treehead.username.label;" flex="2"
|
||||
onclick="SignonColumnSort('username');" persist="width"/>
|
||||
|
@ -82,7 +82,7 @@ function LoadRejects() {
|
||||
|
||||
// sort and display the table
|
||||
rejectsTree.treeBoxObject.view = rejectsTreeView;
|
||||
RejectColumnSort('host');
|
||||
RejectColumnSort(lastRejectSortColumn);
|
||||
|
||||
var element = document.getElementById("removeAllRejects");
|
||||
if (rejects.length == 0) {
|
||||
@ -126,7 +126,7 @@ function HandleRejectKeyPress(e) {
|
||||
}
|
||||
}
|
||||
|
||||
var lastRejectSortColumn = "";
|
||||
var lastRejectSortColumn = "host";
|
||||
var lastRejectSortAscending = false;
|
||||
|
||||
function RejectColumnSort(column) {
|
||||
@ -134,4 +134,9 @@ function RejectColumnSort(column) {
|
||||
SortTree(rejectsTree, rejectsTreeView, rejects,
|
||||
column, lastRejectSortColumn, lastRejectSortAscending);
|
||||
lastRejectSortColumn = column;
|
||||
|
||||
// set the sortDirection attribute to get the styling going
|
||||
var sortedCol = document.getElementById("rejectCol");
|
||||
sortedCol.setAttribute("sortDirection", lastRejectSortAscending ?
|
||||
"ascending" : "descending");
|
||||
}
|
||||
|
@ -64,7 +64,7 @@
|
||||
onselect="RejectSelected();">
|
||||
<treecols>
|
||||
<treecol id="rejectCol" label="&treehead.site.label;" flex="5"
|
||||
onclick="RejectColumnSort('host');"/>
|
||||
onclick="RejectColumnSort('host');" sortDirection="ascending"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
|
@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_FILES = \
|
||||
browser_passwordmgrdlg.js \
|
||||
browser_passwordmgr_sort.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
|
@ -0,0 +1,266 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ehsan Akhgari.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
|
||||
* Jens Hatlak <jh@junetz.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
pwmgr.removeAllLogins();
|
||||
|
||||
// Add some initial logins
|
||||
let urls = [
|
||||
"http://example.com/",
|
||||
"http://example.org/",
|
||||
"http://mozilla.com/",
|
||||
"http://mozilla.org/",
|
||||
"http://spreadfirefox.com/",
|
||||
"http://planet.mozilla.org/",
|
||||
"https://developer.mozilla.org/",
|
||||
"http://hg.mozilla.org/",
|
||||
"http://mxr.mozilla.org/",
|
||||
"http://feeds.mozilla.org/",
|
||||
];
|
||||
let users = [
|
||||
"user",
|
||||
"username",
|
||||
"ehsan",
|
||||
"ehsan",
|
||||
"john",
|
||||
"what?",
|
||||
"really?",
|
||||
"you sure?",
|
||||
"my user name",
|
||||
"my username",
|
||||
];
|
||||
let pwds = [
|
||||
"password",
|
||||
"password",
|
||||
"mypass",
|
||||
"mypass",
|
||||
"smith",
|
||||
"very secret",
|
||||
"super secret",
|
||||
"absolutely",
|
||||
"mozilla",
|
||||
"mozilla.com",
|
||||
];
|
||||
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
|
||||
Ci.nsILoginInfo, "init");
|
||||
for (let i = 0; i < 10; i++)
|
||||
pwmgr.addLogin(new nsLoginInfo(urls[i], urls[i], null, users[i], pwds[i],
|
||||
"u"+(i+1), "p"+(i+1)));
|
||||
|
||||
// Detect when the password manager window is opened
|
||||
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
let obs = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
// unregister ourself
|
||||
ww.unregisterNotification(this);
|
||||
|
||||
let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
|
||||
win.addEventListener("load", function() {
|
||||
win.removeEventListener("load", arguments.callee, true);
|
||||
setTimeout(doTest, 0);
|
||||
}, true);
|
||||
}
|
||||
};
|
||||
ww.registerNotification(obs);
|
||||
|
||||
// Open the password manager dialog
|
||||
const PWMGR_DLG = "chrome://passwordmgr/content/passwordManager.xul";
|
||||
let pwmgrdlg = window.openDialog(PWMGR_DLG, "Toolkit:PasswordManager", "");
|
||||
|
||||
// the meat of the test
|
||||
function doTest() {
|
||||
let doc = pwmgrdlg.document;
|
||||
let win = doc.defaultView;
|
||||
let sTree = doc.getElementById("signonsTree");
|
||||
let filter = doc.getElementById("filter");
|
||||
let siteCol = doc.getElementById("siteCol");
|
||||
let userCol = doc.getElementById("userCol");
|
||||
let passwordCol = doc.getElementById("passwordCol");
|
||||
|
||||
let toggleCalls = 0;
|
||||
function toggleShowPasswords(func) {
|
||||
let toggleButton = doc.getElementById("togglePasswords");
|
||||
let showMode = (toggleCalls++ % 2) == 0;
|
||||
|
||||
// only watch for a confirmation dialog every other time being called
|
||||
if (showMode) {
|
||||
let obs = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowclosed")
|
||||
ww.unregisterNotification(this);
|
||||
else if (aTopic == "domwindowopened") {
|
||||
let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
|
||||
win.addEventListener("load", function() {
|
||||
win.removeEventListener("load", arguments.callee, true);
|
||||
setTimeout(function() {
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, win)
|
||||
}, 0);
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
ww.registerNotification(obs);
|
||||
}
|
||||
|
||||
let obsSvc = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
obsSvc.addObserver({
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "passwordmgr-password-toggle-complete") {
|
||||
obsSvc.removeObserver(this, "passwordmgr-password-toggle-complete", false);
|
||||
func();
|
||||
}
|
||||
}
|
||||
}, "passwordmgr-password-toggle-complete", false);
|
||||
|
||||
EventUtils.synthesizeMouse(toggleButton, 1, 1, {}, win);
|
||||
}
|
||||
|
||||
function clickCol(col) {
|
||||
EventUtils.synthesizeMouse(col, 20, 1, {}, win);
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
||||
function setFilter(string) {
|
||||
filter.value = string;
|
||||
filter.doCommand();
|
||||
setTimeout(runNextTest, 0);
|
||||
}
|
||||
|
||||
function checkSortMarkers(activeCol) {
|
||||
let isOk = true;
|
||||
let col = null;
|
||||
let hasAttr = false;
|
||||
let treecols = activeCol.parentNode;
|
||||
for (let i = 0; i < treecols.childNodes.length; i++) {
|
||||
col = treecols.childNodes[i];
|
||||
if (col.nodeName != "treecol")
|
||||
continue;
|
||||
hasAttr = col.hasAttribute("sortDirection");
|
||||
isOk &= col == activeCol ? hasAttr : !hasAttr;
|
||||
}
|
||||
ok(isOk, "Only " + activeCol.id + " has a sort marker");
|
||||
}
|
||||
|
||||
function checkSortDirection(col, ascending) {
|
||||
checkSortMarkers(col);
|
||||
let direction = ascending ? "ascending" : "descending";
|
||||
is(col.getAttribute("sortDirection"), direction,
|
||||
col.id + ": sort direction is " + direction);
|
||||
}
|
||||
|
||||
function checkColumnEntries(aCol, expectedValues) {
|
||||
let actualValues = getColumnEntries(aCol);
|
||||
is(actualValues.length, expectedValues.length, "Checking length of expected column");
|
||||
for (let i = 0; i < expectedValues.length; i++)
|
||||
is(actualValues[i], expectedValues[i], "Checking column entry #"+i);
|
||||
}
|
||||
|
||||
function getColumnEntries(aCol) {
|
||||
let entries = [];
|
||||
let column = sTree.columns[aCol];
|
||||
let numRows = sTree.view.rowCount;
|
||||
for (let i = 0; i < numRows; i++)
|
||||
entries.push(sTree.view.getCellText(i, column));
|
||||
return entries;
|
||||
}
|
||||
|
||||
let testCounter = 0;
|
||||
let expectedValues;
|
||||
function runNextTest() {
|
||||
switch (testCounter++) {
|
||||
case 0:
|
||||
expectedValues = urls.slice().sort();
|
||||
checkColumnEntries(0, expectedValues);
|
||||
checkSortDirection(siteCol, true);
|
||||
// Toggle sort direction on Host column
|
||||
clickCol(siteCol);
|
||||
break;
|
||||
case 1:
|
||||
expectedValues.reverse();
|
||||
checkColumnEntries(0, expectedValues);
|
||||
checkSortDirection(siteCol, false);
|
||||
// Sort by Username
|
||||
clickCol(userCol);
|
||||
break;
|
||||
case 2:
|
||||
expectedValues = users.slice().sort();
|
||||
checkColumnEntries(1, expectedValues);
|
||||
checkSortDirection(userCol, true);
|
||||
// Sort by Password
|
||||
clickCol(passwordCol);
|
||||
break;
|
||||
case 3:
|
||||
expectedValues = pwds.slice().sort();
|
||||
checkColumnEntries(2, expectedValues);
|
||||
checkSortDirection(passwordCol, true);
|
||||
// Set filter
|
||||
setFilter("moz");
|
||||
break;
|
||||
case 4:
|
||||
expectedValues = [ "absolutely", "mozilla", "mozilla.com",
|
||||
"mypass", "mypass", "super secret",
|
||||
"very secret" ];
|
||||
checkColumnEntries(2, expectedValues);
|
||||
checkSortDirection(passwordCol, true);
|
||||
// Reset filter
|
||||
setFilter("");
|
||||
break;
|
||||
case 5:
|
||||
expectedValues = pwds.slice().sort();
|
||||
checkColumnEntries(2, expectedValues);
|
||||
checkSortDirection(passwordCol, true);
|
||||
// cleanup
|
||||
pwmgrdlg.close();
|
||||
pwmgr.removeAllLogins();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle Show Passwords to display Password column, then start tests
|
||||
toggleShowPasswords(runNextTest);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user