1
/* ***** BEGIN LICENSE BLOCK *****
3
* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
* ***** END LICENSE BLOCK ***** */
9
/*----------------------
12
Original code from Mozilla Firefox v24.0
17
Original CookieManager code is from Mozilla Firefox v0.8, CookieViewer.js
18
Modified original code is commented with "//DY" (I hope)
21
1.00 Original release for Firefox v0.8
23
1.02 Updated for Firefox v0.9:removed cookie Policy & Status props,changed Secure strings
24
1.1.0 New code for deleting unprotected cookies at browser startup
25
1.2.0 Updated Tree code for Mozilla 1.8 Trunk Code Support
26
1.5.0 Rewrite for mozilla 24 support, resync code with the Firefox one.
27
----------------------*/
30
gCookieKeeper._blockDeleteEvent = false;
32
gCookieKeeper.observe = function(aCookie, aTopic, aData) {
34
if (aTopic == OBS_PCOOKIE_TOPIC) {
35
// somewhat a strange object: wrappedJSObject ...
36
this.onProtCookieRemove(aCookie.wrappedJSObject.pcookie);
40
if (aTopic != "cookie-changed") {
44
if (aCookie instanceof Ci.nsICookie2) {
45
var strippedHost = this._makeStrippedHost(aCookie.host);
46
if (aData == "changed") {
47
this._handleCookieChanged(aCookie, strippedHost);
48
} else if (aData == "added") {
49
this._handleCookieAdded(aCookie, strippedHost);
50
} else if (aData == "deleted" && !this._blockDeleteEvent) {
51
this._handleCookieDeleted(aCookie, strippedHost);
53
} else if (aData == "cleared") {
57
this._view.rowCount = 0;
58
this._view.selection.clearSelection();
59
this._updateButtons();
60
} else if (aData == "reload") {
61
// first, clear any existing entries
62
this.observe(aCookie, aTopic, "cleared");
64
// then, reload the list
65
this._populateList(false);
69
gCookieKeeper._handleCookieChanged = function(changedCookie, strippedHost) {
71
var cookieItem = null;
72
if (this._view.mode == VIEW_TREE) {
73
for (let i = 0; i < this._hostOrder.length; i++) {
75
var hostItem = this._hosts[this._hostOrder[i]];
76
if (this._hostOrder[i] == strippedHost) {
77
// Host matches, look for the cookie within this Host collection
78
// and update its data
79
for (let j = 0; j < hostItem.cookies.length; j++) {
81
var currCookie = hostItem.cookies[j];
82
if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
83
currCookie.value = changedCookie.value;
84
currCookie.isSecure = changedCookie.isSecure;
85
currCookie.isDomain = changedCookie.isDomain;
86
currCookie.expires = changedCookie.expires;
87
cookieItem = currCookie;
91
} else if (hostItem.open) {
92
rowIndex += hostItem.cookies.length;
96
// Just walk the filter list to find the item. It doesn't matter that
97
// we don't update the main Host collection when we do this, because
98
// when the filter is reset the Host collection is rebuilt anyway.
99
for (rowIndex = 0; rowIndex < this._view._flatSet.length; rowIndex++) {
100
currCookie = this._view._flatSet[rowIndex];
101
if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
102
currCookie.value = changedCookie.value;
103
currCookie.isSecure = changedCookie.isSecure;
104
currCookie.isDomain = changedCookie.isDomain;
105
currCookie.expires = changedCookie.expires;
106
cookieItem = currCookie;
112
// Make sure the tree display is up to date...
113
this._tree.treeBoxObject.invalidateRow(rowIndex);
114
// ... and if the cookie is selected, update the displayed metadata too
115
if (cookieItem != null && this._view.selection.currentIndex == rowIndex) {
116
this._updateCookieData();
120
gCookieKeeper._handleCookieAdded = function(addedCookie, strippedHost) {
121
var rowCountImpact = 0;
122
var addedHost = { value: 0 };
123
var cookie = this._addCookie(strippedHost, addedCookie, addedHost, false);
124
if (this._view.mode == VIEW_TREE) {
125
// The Host collection for this cookie already exists, and it's not open,
126
// so don't increment the rowCountImpact becaues the user is not going to
127
// see the additional rows as they're hidden.
128
if (addedHost.value || this._hosts[strippedHost].open) {
131
} else if (this._view.mode == VIEW_FLAT || this._cookieMatchesFilter(cookie)) {
133
this._view._flatSet.push(cookie);
136
if (rowCountImpact > 0) {
137
// Now update the tree display at the end
138
var oldRowCount = this._rowCount;
139
this._view._rowCount += rowCountImpact;
140
this._tree.treeBoxObject.rowCountChanged(oldRowCount - 1, rowCountImpact);
142
this._lastSortAscending = !this._lastSortAscending;
143
this.sort(this._lastSortProperty);
144
// Update buttons status
145
this._updateButtons();
149
gCookieKeeper._handleCookieDeleted = function(aCookie, strippedHost) {
150
// Search for the cookie:
151
var currHost = this._hosts[strippedHost];
152
if (typeof(currHost) == "undefined" || currHost == null) {
153
log.e("_handleCookieDeleted: Cookie host " + strippedHost + " not found");
158
const nCookies = currHost.cookies.length;
159
for (; cCookie<nCookies; cCookie++) {
160
var c = currHost.cookies[cCookie];
161
if (c != null && c.host == aCookie.host && c.name == aCookie.name && c.path == aCookie.path) {
167
if (cookie == null) {
168
log.e("_handleCookieDeleted: Cookie not found: " + aCookie.host + ":" + aCookie.name);
171
const cookieViewIndex = this._view._getIndexOfItem(cookie);
175
// Remote the host from _hostOrder
176
idxHO = this._hostOrder.indexOf(strippedHost);
178
this._hostOrder.splice(idxHO, 1);
179
} // else it is an error
180
// Remove the host from the _hosts list
181
delete this._hosts[strippedHost];
183
currHost.cookies.splice(cCookie, 1);
186
var tbo = this._tree.treeBoxObject;
187
var seln = this._view.selection;
188
const curSelIndex = seln.currentIndex;
190
switch (this._view.mode) {
192
// log.d("idxHO=" + idxHO);
193
// log.d("cookieViewIndex=" + cookieViewIndex);
194
if (cookieViewIndex == -1 && idxHO == -1) {
198
this._blockSelectEvent++;
199
// TODO: a more fine update?
200
var rowCountImpact = 0;
201
var rowCount = this._view.rowCount;
209
// log.d("rowCountImpact=" + rowCountImpact);
211
if (rowCountImpact != 0) {
212
rowCount += rowCountImpact;
213
this._view.rowCount = rowCount;
215
seln.clearSelection();
216
this._view._invalidateCache(0);
218
this._blockSelectEvent--;
220
var newSelIndex = curSelIndex;
221
if (cookieViewIndex != curSelIndex) {
222
// The host is selected, not the cookie itself
223
} else if (!currHost.open || (currHost.open && (nCookies == 1 || (nCookies > 1 && cCookie == (nCookies - 1))))) {
224
// very complicated if ...
229
newSelIndex = (newSelIndex >= rowCount) ? rowCount - 1 : newSelIndex;
230
newSelIndex = (newSelIndex < 0) ? 0 : newSelIndex;
231
log.d("curSelIndex=" + curSelIndex + " newSelIndex=" + newSelIndex + " cookieViewIndex=" + cookieViewIndex);
233
seln.select(newSelIndex);
234
tbo.ensureRowIsVisible(newSelIndex);
237
this._blockSelectEvent--;
241
if (!this._cookieMatchesFilter(cookie)) {
247
this._blockSelectEvent++;
249
this._view._flatSet.splice(cookieViewIndex, 1);
250
this._view._rowCount--;
251
tbo.invalidateRow(cookieViewIndex);
252
tbo.rowCountChanged(cookieViewIndex, -1);
255
if (curSelIndex >= cookieViewIndex) {
256
seln.clearSelection();
257
this._blockSelectEvent--;
258
if (curSelIndex >= this._view._flatSet.length) {
259
seln.select(curSelIndex - 1);
261
seln.select(curSelIndex);
264
this._blockSelectEvent--;
270
gCookieKeeper.onProtCookieRemove = function(pCookie) {
271
// Call from gCookieKeeperProtCookiesPrefs.remove()
275
var strippedHost = this._makeStrippedHost(pCookie.host);
276
var host = this._hosts[strippedHost];
277
if (typeof(host) != "undefined") {
278
const nCookies = host.cookies.length;
279
for (let i=0; i<nCookies; i++) {
280
var cookie = host.cookies[i];
281
if (cookie.host == pCookie.host && cookie.name == pCookie.name && cookie.path == pCookie.path) {
282
cookie.isProtected = false;
285
var index = this._view._getIndexOfItem(cookie);
287
this._tree.treeBoxObject.invalidateRow(index);
288
if (this._view.selection.currentIndex == index) {
289
this.onCookieSelected();