/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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 nsICookie = Components.interfaces.nsICookie; var gCookiesWindow = { _cm : Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager), _ds : Components.classes["@mozilla.org/intl/scriptabledateformat;1"] .getService(Components.interfaces.nsIScriptableDateFormat), _hosts : {}, _hostOrder : [], _tree : null, _bundle : null, init: function () { var os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); os.addObserver(this, "cookie-changed", false); os.addObserver(this, "perm-changed", false); this._bundle = document.getElementById("bundlePreferences"); this._tree = document.getElementById("cookiesList"); this._populateList(true); document.getElementById("filter").focus(); }, uninit: function () { var os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); os.removeObserver(this, "cookie-changed"); os.removeObserver(this, "perm-changed"); }, _populateList: function (aInitialLoad) { this._loadCookies(); this._tree.view = this._view; if (aInitialLoad) this.sort("rawHost"); if (this._view.rowCount > 0) this._tree.view.selection.select(0); if (aInitialLoad) { if ("arguments" in window && window.arguments[0] && window.arguments[0].filterString) this.setFilter(window.arguments[0].filterString); } else { if (document.getElementById("filter").value != "") this.filter(); } this._updateRemoveAllButton(); this._saveState(); }, _cookieEquals: function (aCookieA, aCookieB, aStrippedHost) { return aCookieA.rawHost == aStrippedHost && aCookieA.name == aCookieB.name && aCookieA.path == aCookieB.path && ChromeUtils.isOriginAttributesEqual(aCookieA.originAttributes, aCookieB.originAttributes); }, observe: function (aCookie, aTopic, aData) { if (aTopic != "cookie-changed") return; if (aCookie instanceof Components.interfaces.nsICookie) { var strippedHost = this._makeStrippedHost(aCookie.host); if (aData == "changed") this._handleCookieChanged(aCookie, strippedHost); else if (aData == "added") this._handleCookieAdded(aCookie, strippedHost); } else if (aData == "cleared") { this._hosts = {}; this._hostOrder = []; var oldRowCount = this._view._rowCount; this._view._rowCount = 0; this._tree.treeBoxObject.rowCountChanged(0, -oldRowCount); this._view.selection.clearSelection(); this._updateRemoveAllButton(); } else if (aData == "reload") { // first, clear any existing entries this.observe(aCookie, aTopic, "cleared"); // then, reload the list this._populateList(false); } // We don't yet handle aData == "deleted" - it's a less common case // and is rather complicated as selection tracking is difficult }, _handleCookieChanged: function (changedCookie, strippedHost) { var rowIndex = 0; var cookieItem = null; if (!this._view._filtered) { for (var i = 0; i < this._hostOrder.length; ++i) { // (var host in this._hosts) { ++rowIndex; var hostItem = this._hosts[this._hostOrder[i]]; // var hostItem = this._hosts[host]; if (this._hostOrder[i] == strippedHost) { // host == strippedHost) { // Host matches, look for the cookie within this Host collection // and update its data for (var j = 0; j < hostItem.cookies.length; ++j) { ++rowIndex; var currCookie = hostItem.cookies[j]; if (this._cookieEquals(currCookie, changedCookie, strippedHost)) { currCookie.value = changedCookie.value; currCookie.isSecure = changedCookie.isSecure; currCookie.isDomain = changedCookie.isDomain; currCookie.expires = changedCookie.expires; cookieItem = currCookie; break; } } } else if (hostItem.open) rowIndex += hostItem.cookies.length; } } else { // Just walk the filter list to find the item. It doesn't matter that // we don't update the main Host collection when we do this, because // when the filter is reset the Host collection is rebuilt anyway. for (rowIndex = 0; rowIndex < this._view._filterSet.length; ++rowIndex) { currCookie = this._view._filterSet[rowIndex]; if (this._cookieEquals(currCookie, changedCookie, strippedHost)) { currCookie.value = changedCookie.value; currCookie.isSecure = changedCookie.isSecure; currCookie.isDomain = changedCookie.isDomain; currCookie.expires = changedCookie.expires; cookieItem = currCookie; break; } } } // Make sure the tree display is up to date... this._tree.treeBoxObject.invalidateRow(rowIndex); // ... and if the cookie is selected, update the displayed metadata too if (cookieItem != null && this._view.selection.currentIndex == rowIndex) this._updateCookieData(cookieItem); }, _handleCookieAdded: function (changedCookie, strippedHost) { var rowCountImpact = 0; var addedHost = { value: 0 }; this._addCookie(strippedHost, changedCookie, addedHost); if (!this._view._filtered) { // The Host collection for this cookie already exists, and it's not open, // so don't increment the rowCountImpact becaues the user is not going to // see the additional rows as they're hidden. if (addedHost.value || this._hosts[strippedHost].open) ++rowCountImpact; } else { // We're in search mode, and the cookie being added matches // the search condition, so add it to the list. var c = this._makeCookieObject(strippedHost, changedCookie); if (this._cookieMatchesFilter(c)) { this._view._filterSet.push(this._makeCookieObject(strippedHost, changedCookie)); ++rowCountImpact; } } // Now update the tree display at the end (we could/should re run the sort // if any to get the position correct.) var oldRowCount = this._rowCount; this._view._rowCount += rowCountImpact; this._tree.treeBoxObject.rowCountChanged(oldRowCount - 1, rowCountImpact); this._updateRemoveAllButton(); }, _view: { _filtered : false, _filterSet : [], _filterValue: "", _rowCount : 0, _cacheValid : 0, _cacheItems : [], get rowCount() { return this._rowCount; }, _getItemAtIndex: function (aIndex) { if (this._filtered) return this._filterSet[aIndex]; var start = 0; var count = 0, hostIndex = 0; var cacheIndex = Math.min(this._cacheValid, aIndex); if (cacheIndex > 0) { var cacheItem = this._cacheItems[cacheIndex]; start = cacheItem['start']; count = hostIndex = cacheItem['count']; } for (var i = start; i < gCookiesWindow._hostOrder.length; ++i) { // var host in gCookiesWindow._hosts) { var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host]; if (!currHost) continue; if (count == aIndex) return currHost; hostIndex = count; var cacheEntry = { 'start' : i, 'count' : count }; var cacheStart = count; if (currHost.open) { if (count < aIndex && aIndex <= (count + currHost.cookies.length)) { // We are looking for an entry within this host's children, // enumerate them looking for the index. ++count; for (var i = 0; i < currHost.cookies.length; ++i) { if (count == aIndex) { var cookie = currHost.cookies[i]; cookie.parentIndex = hostIndex; return cookie; } ++count; } } else { // A host entry was open, but we weren't looking for an index // within that host entry's children, so skip forward over the // entry's children. We need to add one to increment for the // host value too. count += currHost.cookies.length + 1; } } else ++count; for (var j = cacheStart; j < count; j++) this._cacheItems[j] = cacheEntry; this._cacheValid = count - 1; } return null; }, _removeItemAtIndex: function (aIndex, aCount) { var removeCount = aCount === undefined ? 1 : aCount; if (this._filtered) { // remove the cookies from the unfiltered set so that they // don't reappear when the filter is changed. See bug 410863. for (var i = aIndex; i < aIndex + removeCount; ++i) { var item = this._filterSet[i]; var parent = gCookiesWindow._hosts[item.rawHost]; for (var j = 0; j < parent.cookies.length; ++j) { if (item == parent.cookies[j]) { parent.cookies.splice(j, 1); break; } } } this._filterSet.splice(aIndex, removeCount); return; } var item = this._getItemAtIndex(aIndex); if (!item) return; this._invalidateCache(aIndex - 1); if (item.container) { gCookiesWindow._hosts[item.rawHost] = null; } else { var parent = this._getItemAtIndex(item.parentIndex); for (var i = 0; i < parent.cookies.length; ++i) { var cookie = parent.cookies[i]; if (item.rawHost == cookie.rawHost && item.name == cookie.name && item.path == cookie.path && ChromeUtils.isOriginAttributesEqual(item.originAttributes, cookie.originAttributes)) { parent.cookies.splice(i, removeCount); } } } }, _invalidateCache: function (aIndex) { this._cacheValid = Math.min(this._cacheValid, aIndex); }, getCellText: function (aIndex, aColumn) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); if (!item) return ""; if (aColumn.id == "domainCol") return item.rawHost; else if (aColumn.id == "nameCol") return item.name; } else { if (aColumn.id == "domainCol") return this._filterSet[aIndex].rawHost; else if (aColumn.id == "nameCol") return this._filterSet[aIndex].name; } return ""; }, _selection: null, get selection () { return this._selection; }, set selection (val) { this._selection = val; return val; }, getRowProperties: function (aIndex) { return ""; }, getCellProperties: function (aIndex, aColumn) { return ""; }, getColumnProperties: function (aColumn) { return ""; }, isContainer: function (aIndex) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); if (!item) return false; return item.container; } return false; }, isContainerOpen: function (aIndex) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); if (!item) return false; return item.open; } return false; }, isContainerEmpty: function (aIndex) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); if (!item) return false; return item.cookies.length == 0; } return false; }, isSeparator: function (aIndex) { return false; }, isSorted: function (aIndex) { return false; }, canDrop: function (aIndex, aOrientation) { return false; }, drop: function (aIndex, aOrientation) {}, getParentIndex: function (aIndex) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); // If an item has no parent index (i.e. it is at the top level) this // function MUST return -1 otherwise we will go into an infinite loop. // Containers are always top level items in the cookies tree, so make // sure to return the appropriate value here. if (!item || item.container) return -1; return item.parentIndex; } return -1; }, hasNextSibling: function (aParentIndex, aIndex) { if (!this._filtered) { // |aParentIndex| appears to be bogus, but we can get the real // parent index by getting the entry for |aIndex| and reading the // parentIndex field. // The index of the last item in this host collection is the // index of the parent + the size of the host collection, and // aIndex has a next sibling if it is less than this value. var item = this._getItemAtIndex(aIndex); if (item) { if (item.container) { for (var i = aIndex + 1; i < this.rowCount; ++i) { var subsequent = this._getItemAtIndex(i); if (subsequent.container) return true; } return false; } else { var parent = this._getItemAtIndex(item.parentIndex); if (parent && parent.container) return aIndex < item.parentIndex + parent.cookies.length; } } } return aIndex < this.rowCount - 1; }, hasPreviousSibling: function (aIndex) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); if (!item) return false; var parent = this._getItemAtIndex(item.parentIndex); if (parent && parent.container) return aIndex > item.parentIndex + 1; } return aIndex > 0; }, getLevel: function (aIndex) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); if (!item) return 0; return item.level; } return 0; }, getImageSrc: function (aIndex, aColumn) {}, getProgressMode: function (aIndex, aColumn) {}, getCellValue: function (aIndex, aColumn) {}, setTree: function (aTree) {}, toggleOpenState: function (aIndex) { if (!this._filtered) { var item = this._getItemAtIndex(aIndex); if (!item) return; this._invalidateCache(aIndex); var multiplier = item.open ? -1 : 1; var delta = multiplier * item.cookies.length; this._rowCount += delta; item.open = !item.open; gCookiesWindow._tree.treeBoxObject.rowCountChanged(aIndex + 1, delta); gCookiesWindow._tree.treeBoxObject.invalidateRow(aIndex); } }, cycleHeader: function (aColumn) {}, selectionChanged: function () {}, cycleCell: function (aIndex, aColumn) {}, isEditable: function (aIndex, aColumn) { return false; }, isSelectable: function (aIndex, aColumn) { return false; }, setCellValue: function (aIndex, aColumn, aValue) {}, setCellText: function (aIndex, aColumn, aValue) {}, performAction: function (aAction) {}, performActionOnRow: function (aAction, aIndex) {}, performActionOnCell: function (aAction, aindex, aColumn) {} }, _makeStrippedHost: function (aHost) { var formattedHost = aHost.charAt(0) == "." ? aHost.substring(1, aHost.length) : aHost; return formattedHost.substring(0, 4) == "www." ? formattedHost.substring(4, formattedHost.length) : formattedHost; }, _addCookie: function (aStrippedHost, aCookie, aHostCount) { if (!(aStrippedHost in this._hosts) || !this._hosts[aStrippedHost]) { this._hosts[aStrippedHost] = { cookies : [], rawHost : aStrippedHost, level : 0, open : false, container : true }; this._hostOrder.push(aStrippedHost); ++aHostCount.value; } var c = this._makeCookieObject(aStrippedHost, aCookie); this._hosts[aStrippedHost].cookies.push(c); }, _makeCookieObject: function (aStrippedHost, aCookie) { var host = aCookie.host; var formattedHost = host.charAt(0) == "." ? host.substring(1, host.length) : host; var c = { name : aCookie.name, value : aCookie.value, isDomain : aCookie.isDomain, host : aCookie.host, rawHost : aStrippedHost, path : aCookie.path, isSecure : aCookie.isSecure, expires : aCookie.expires, level : 1, container : false, originAttributes: aCookie.originAttributes }; return c; }, _loadCookies: function () { var e = this._cm.enumerator; var hostCount = { value: 0 }; this._hosts = {}; this._hostOrder = []; while (e.hasMoreElements()) { var cookie = e.getNext(); if (cookie && cookie instanceof Components.interfaces.nsICookie) { var strippedHost = this._makeStrippedHost(cookie.host); this._addCookie(strippedHost, cookie, hostCount); } else break; } this._view._rowCount = hostCount.value; }, formatExpiresString: function (aExpires) { if (aExpires) { var date = new Date(1000 * aExpires); return this._ds.FormatDateTime("", this._ds.dateFormatLong, this._ds.timeFormatSeconds, date.getFullYear(), date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); } return this._bundle.getString("expireAtEndOfSession"); }, _updateCookieData: function (aItem) { var seln = this._view.selection; var ids = ["name", "value", "host", "path", "isSecure", "expires"]; var properties; if (aItem && !aItem.container && seln.count > 0) { properties = { name: aItem.name, value: aItem.value, host: aItem.host, path: aItem.path, expires: this.formatExpiresString(aItem.expires), isDomain: aItem.isDomain ? this._bundle.getString("domainColon") : this._bundle.getString("hostColon"), isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly") : this._bundle.getString("forAnyConnection") }; for (var i = 0; i < ids.length; ++i) document.getElementById(ids[i]).disabled = false; } else { var noneSelected = this._bundle.getString("noCookieSelected"); properties = { name: noneSelected, value: noneSelected, host: noneSelected, path: noneSelected, expires: noneSelected, isSecure: noneSelected }; for (i = 0; i < ids.length; ++i) document.getElementById(ids[i]).disabled = true; } for (var property in properties) document.getElementById(property).value = properties[property]; }, onCookieSelected: function () { var properties, item; var seln = this._tree.view.selection; if (!this._view._filtered) item = this._view._getItemAtIndex(seln.currentIndex); else item = this._view._filterSet[seln.currentIndex]; this._updateCookieData(item); var rangeCount = seln.getRangeCount(); var selectedCookieCount = 0; for (var i = 0; i < rangeCount; ++i) { var min = {}; var max = {}; seln.getRangeAt(i, min, max); for (var j = min.value; j <= max.value; ++j) { item = this._view._getItemAtIndex(j); if (!item) continue; if (item.container && !item.open) selectedCookieCount += item.cookies.length; else if (!item.container) ++selectedCookieCount; } } var item = this._view._getItemAtIndex(seln.currentIndex); if (item && seln.count == 1 && item.container && item.open) selectedCookieCount += 2; var removeCookie = document.getElementById("removeCookie"); var removeCookies = document.getElementById("removeCookies"); removeCookie.parentNode.selectedPanel = selectedCookieCount == 1 ? removeCookie : removeCookies; removeCookie.disabled = removeCookies.disabled = !(seln.count > 0); }, performDeletion: function gCookiesWindow_performDeletion(deleteItems) { var psvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); var blockFutureCookies = false; if (psvc.prefHasUserValue("network.cookie.blockFutureCookies")) blockFutureCookies = psvc.getBoolPref("network.cookie.blockFutureCookies"); for (var i = 0; i < deleteItems.length; ++i) { var item = deleteItems[i]; this._cm.remove(item.host, item.name, item.path, blockFutureCookies, item.originAttributes); } }, deleteCookie: function () { // Selection Notes // - Selection always moves to *NEXT* adjacent item unless item // is last child at a given level in which case it moves to *PREVIOUS* // item // // Selection Cases (Somewhat Complicated) // // 1) Single cookie selected, host has single child // v cnn.com // //// cnn.com ///////////// goksdjf@ //// // > atwola.com // // Before SelectedIndex: 1 Before RowCount: 3 // After SelectedIndex: 0 After RowCount: 1 // // 2) Host selected, host open // v goats.com //////////////////////////// // goats.com sldkkfjl // goat.scom flksj133 // > atwola.com // // Before SelectedIndex: 0 Before RowCount: 4 // After SelectedIndex: 0 After RowCount: 1 // // 3) Host selected, host closed // > goats.com //////////////////////////// // > atwola.com // // Before SelectedIndex: 0 Before RowCount: 2 // After SelectedIndex: 0 After RowCount: 1 // // 4) Single cookie selected, host has many children // v goats.com // goats.com sldkkfjl // //// goats.com /////////// flksjl33 //// // > atwola.com // // Before SelectedIndex: 2 Before RowCount: 4 // After SelectedIndex: 1 After RowCount: 3 // // 5) Single cookie selected, host has many children // v goats.com // //// goats.com /////////// flksjl33 //// // goats.com sldkkfjl // > atwola.com // // Before SelectedIndex: 1 Before RowCount: 4 // After SelectedIndex: 1 After RowCount: 3 var seln = this._view.selection; var tbo = this._tree.treeBoxObject; if (seln.count < 1) return; var nextSelected = 0; var rowCountImpact = 0; var deleteItems = []; if (!this._view._filtered) { var ci = seln.currentIndex; nextSelected = ci; var invalidateRow = -1; var item = this._view._getItemAtIndex(ci); if (item.container) { rowCountImpact -= (item.open ? item.cookies.length : 0) + 1; deleteItems = deleteItems.concat(item.cookies); if (!this._view.hasNextSibling(-1, ci)) --nextSelected; this._view._removeItemAtIndex(ci); } else { var parent = this._view._getItemAtIndex(item.parentIndex); --rowCountImpact; if (parent.cookies.length == 1) { --rowCountImpact; deleteItems.push(item); if (!this._view.hasNextSibling(-1, ci)) --nextSelected; if (!this._view.hasNextSibling(-1, item.parentIndex)) --nextSelected; this._view._removeItemAtIndex(item.parentIndex); invalidateRow = item.parentIndex; } else { deleteItems.push(item); if (!this._view.hasNextSibling(-1, ci)) --nextSelected; this._view._removeItemAtIndex(ci); } } this._view._rowCount += rowCountImpact; tbo.rowCountChanged(ci, rowCountImpact); if (invalidateRow != -1) tbo.invalidateRow(invalidateRow); } else { var rangeCount = seln.getRangeCount(); // Traverse backwards through selections to avoid messing // up the indices when they are deleted. // See bug 388079. for (var i = rangeCount - 1; i >= 0; --i) { var min = {}; var max = {}; seln.getRangeAt(i, min, max); nextSelected = min.value; for (var j = min.value; j <= max.value; ++j) { deleteItems.push(this._view._getItemAtIndex(j)); if (!this._view.hasNextSibling(-1, max.value)) --nextSelected; } var delta = max.value - min.value + 1; this._view._removeItemAtIndex(min.value, delta); rowCountImpact = -1 * delta; this._view._rowCount += rowCountImpact; tbo.rowCountChanged(min.value, rowCountImpact); } } this.performDeletion(deleteItems); if (nextSelected < 0) seln.clearSelection(); else { seln.select(nextSelected); this._tree.focus(); } }, deleteAllCookies: function () { if (this._view._filtered) { var rowCount = this._view.rowCount; var deleteItems = []; for (var index = 0; index < rowCount; index++) { deleteItems.push(this._view._getItemAtIndex(index)); } this._view._removeItemAtIndex(0, rowCount); this._view._rowCount = 0; this._tree.treeBoxObject.rowCountChanged(0, -rowCount); this.performDeletion(deleteItems); } else { this._cm.removeAll(); } this._updateRemoveAllButton(); this.focusFilterBox(); }, onCookieKeyPress: function (aEvent) { if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE #ifdef XP_MACOSX || aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE #endif ) { this.deleteCookie(); } }, _lastSortProperty : "", _lastSortAscending: false, sort: function (aProperty) { var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true; // Sort the Non-Filtered Host Collections if (aProperty == "rawHost") { function sortByHost(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); } this._hostOrder.sort(sortByHost); if (!ascending) this._hostOrder.reverse(); } function sortByProperty(a, b) { return a[aProperty].toLowerCase().localeCompare(b[aProperty].toLowerCase()); } for (var host in this._hosts) { var cookies = this._hosts[host].cookies; cookies.sort(sortByProperty); if (!ascending) cookies.reverse(); } // Sort the Filtered List, if in Filtered mode if (this._view._filtered) { this._view._filterSet.sort(sortByProperty); if (!ascending) this._view._filterSet.reverse(); } // Adjust the Sort Indicator var domainCol = document.getElementById("domainCol"); var nameCol = document.getElementById("nameCol"); var sortOrderString = ascending ? "ascending" : "descending"; if (aProperty == "rawHost") { domainCol.setAttribute("sortDirection", sortOrderString); nameCol.removeAttribute("sortDirection"); } else { nameCol.setAttribute("sortDirection", sortOrderString); domainCol.removeAttribute("sortDirection"); } this._view._invalidateCache(0); this._view.selection.clearSelection(); this._view.selection.select(0); this._tree.treeBoxObject.invalidate(); this._tree.treeBoxObject.ensureRowIsVisible(0); this._lastSortAscending = ascending; this._lastSortProperty = aProperty; }, clearFilter: function () { // Revert to single-select in the tree this._tree.setAttribute("seltype", "single"); // Clear the Tree Display this._view._filtered = false; this._view._rowCount = 0; this._tree.treeBoxObject.rowCountChanged(0, -this._view._filterSet.length); this._view._filterSet = []; // Just reload the list to make sure deletions are respected this._loadCookies(); this._tree.view = this._view; // Restore sort order var sortby = this._lastSortProperty; if (sortby == "") { this._lastSortAscending = false; this.sort("rawHost"); } else { this._lastSortAscending = !this._lastSortAscending; this.sort(sortby); } // Restore open state for (var i = 0; i < this._openIndices.length; ++i) this._view.toggleOpenState(this._openIndices[i]); this._openIndices = []; // Restore selection this._view.selection.clearSelection(); for (i = 0; i < this._lastSelectedRanges.length; ++i) { var range = this._lastSelectedRanges[i]; this._view.selection.rangedSelect(range.min, range.max, true); } this._lastSelectedRanges = []; document.getElementById("cookiesIntro").value = this._bundle.getString("cookiesAll"); this._updateRemoveAllButton(); }, _cookieMatchesFilter: function (aCookie) { return aCookie.rawHost.indexOf(this._view._filterValue) != -1 || aCookie.name.indexOf(this._view._filterValue) != -1 || aCookie.value.indexOf(this._view._filterValue) != -1; }, _filterCookies: function (aFilterValue) { this._view._filterValue = aFilterValue; var cookies = []; for (var i = 0; i < gCookiesWindow._hostOrder.length; ++i) { //var host in gCookiesWindow._hosts) { var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host]; if (!currHost) continue; for (var j = 0; j < currHost.cookies.length; ++j) { var cookie = currHost.cookies[j]; if (this._cookieMatchesFilter(cookie)) cookies.push(cookie); } } return cookies; }, _lastSelectedRanges: [], _openIndices: [], _saveState: function () { // Save selection var seln = this._view.selection; this._lastSelectedRanges = []; var rangeCount = seln.getRangeCount(); for (var i = 0; i < rangeCount; ++i) { var min = {}; var max = {}; seln.getRangeAt(i, min, max); this._lastSelectedRanges.push({ min: min.value, max: max.value }); } // Save open states this._openIndices = []; for (i = 0; i < this._view.rowCount; ++i) { var item = this._view._getItemAtIndex(i); if (item && item.container && item.open) this._openIndices.push(i); } }, _updateRemoveAllButton: function gCookiesWindow__updateRemoveAllButton() { document.getElementById("removeAllCookies").disabled = this._view._rowCount == 0; }, filter: function () { var filter = document.getElementById("filter").value; if (filter == "") { gCookiesWindow.clearFilter(); return; } var view = gCookiesWindow._view; view._filterSet = gCookiesWindow._filterCookies(filter); if (!view._filtered) { // Save Display Info for the Non-Filtered mode when we first // enter Filtered mode. gCookiesWindow._saveState(); view._filtered = true; } // Move to multi-select in the tree gCookiesWindow._tree.setAttribute("seltype", "multiple"); // Clear the display var oldCount = view._rowCount; view._rowCount = 0; gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, -oldCount); // Set up the filtered display view._rowCount = view._filterSet.length; gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, view.rowCount); // if the view is not empty then select the first item if (view.rowCount > 0) view.selection.select(0); document.getElementById("cookiesIntro").value = gCookiesWindow._bundle.getString("cookiesFiltered"); this._updateRemoveAllButton(); }, setFilter: function (aFilterString) { document.getElementById("filter").value = aFilterString; this.filter(); }, focusFilterBox: function () { var filter = document.getElementById("filter"); filter.focus(); filter.select(); }, onWindowKeyPress: function (aEvent) { if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) window.close(); } };