1 // cookieMonster.js
2 // Tony Schilling
3 // Created: 01/20/2007
4 // Last Updated: 04/25/2008
5
6 // Use XPCOM to detect browser tab changes and
7 // interface to the cookie manager and the
8 // permission manager,
9 // in order to read and possibly update
10 // the cookie status for the current URI
11
12 // Constants
13 const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
14 const nsICookiePermission = Components.interfaces.nsICookiePermission;
15 const CM_ICON_DEFAULT = "chrome://cookiemonster/skin/face-monkey-small.png";
16 const CM_ICON_TEMP_ALLOW = "chrome://cookiemonster/skin/face-angel-temp.png";
17 const CM_ICON_ALLOW = "chrome://cookiemonster/skin/face-angel.png";
18 const CM_ICON_DENY = "chrome://cookiemonster/skin/face-devil-grin.png";
19 const CM_ICON_SESSION = "chrome://cookiemonster/skin/face-glasses.png";
20 const CM_TOP_LEVEL = 0;
21 const CM_SECOND_LEVEL = 1;
22 const CM_URL_STANDARD_LEVEL = 2;
23 const CM_COOKIE_ACCESS_DEFAULT = "Default";
24 const CM_COOKIE_ACCESS_DENY = "Deny";
25 const CM_COOKIE_ACCESS_ALLOW = "Allow";
26 const CM_COOKIE_ACCESS_SESSION = "Session";
27 const CM_COOKIE_ACCESS_TEMP_ALLOW = "Temp";
28 const CM_PERMISSION_TYPE_COOKIE = "cookie";
29 const CM_PREFERENCE_TYPE_COOKIE_TEMP = "tempcookie";
30
31 // Retrieve the URL for the current (active) browser
32 function getURL()
33 {
34 var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
35 getService(Components.interfaces.nsIWindowMediator);
36 var recentWindow = wm.getMostRecentWindow("navigator:browser");
37 return recentWindow ? recentWindow.content.document.location : null;
38 }
39
40
41 // Retrieve cookie information for the current URL
42 var cookieMonster_CookieInfo =
43 {
44 choice: null,
45 _bundle: null,
46 _isExactPerm: false,
47 _tempAllowList: new Array(),
48
49 init: function()
50 {
51 // Declare instance of cookie permission and
52 // query an nsICookiePermission interface
53 this.choice = Components.classes["@mozilla.org/cookie/permission;1"].createInstance();
54 this.choice.QueryInterface(Components.interfaces.nsICookiePermission);
55
56 this._bundle = document.getElementById("cookie-preferences");
57
58 // Check if the method testExactPermission is available
59 // in the version of the Moz engine being used
60 // Note: Currently, testExactPermission is not available
61 // in Moz 1.8 (FF2), but is available in Moz 1.9 (FF3)
62 var accessString = CM_COOKIE_ACCESS_DEFAULT;
63 var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
64 .getService(Components.interfaces.nsIPermissionManager);
65 if (permissionManager.testExactPermission)
66 {
67 this._isExactPerm = true;
68 //alert ("Exact Permsissions is TRUE");
69 }
70 else
71 {
72 //alert ("Exact Permsissions is FALSE");
73 }
74
75 // Check if CM_PREFERENCE_TYPE_COOKIE_TEMP contains
76 // any URLs and if so, add to _tempAllowList
77 this._tempAllowList = cookieMonster_nsPreferences.getStringPrefArray(CM_PREFERENCE_TYPE_COOKIE_TEMP);
78 },
79
80 isExactPermissions: function()
81 {
82 return this._isExactPerm;
83 },
84
85 // Check the cookie access level for the URI and
86 // return this value
87 checkCookieAccess: function(aRequest, aURI)
88 {
89 aRequest.QueryInterface(Components.interfaces.nsIChannel);
90
91 return this.choice.canAccess(aURI , aRequest.originalURI , aRequest);
92 },
93
94 // Check the cookie access level for the URI and
95 // return a string representation of this value
96 checkCookieAccessString: function(aRequest, aURI)
97 {
98 var accessString = CM_COOKIE_ACCESS_DEFAULT;
99
100 aRequest.QueryInterface(Components.interfaces.nsIChannel);
101
102 switch (this.choice.canAccess(aURI , aRequest.originalURI , aRequest))
103 {
104 case 0:
105 accessString = CM_COOKIE_ACCESS_DEFAULT;
106 break;
107 case nsIPermissionManager.ALLOW_ACTION:
108 accessString = CM_COOKIE_ACCESS_ALLOW;
109 break;
110 case nsIPermissionManager.DENY_ACTION:
111 accessString = CM_COOKIE_ACCESS_DENY;
112 break;
113 case nsICookiePermission.ACCESS_SESSION:
114 accessString = CM_COOKIE_ACCESS_SESSION;
115 break;
116 default:
117 accessString = CM_COOKIE_ACCESS_DEFAULT;
118 break;
119 }
120
121 return accessString;
122 },
123
124 // Check the permission access level for the URI and
125 // return a string representation of this value
126 checkPermissionString: function(aURI, aType)
127 {
128 var accessString = CM_COOKIE_ACCESS_DEFAULT;
129 var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
130 .getService(Components.interfaces.nsIPermissionManager);
131
132 switch (permissionManager.testPermission(aURI ,aType))
133 {
134 case 0:
135 accessString = CM_COOKIE_ACCESS_DEFAULT;
136 break;
137 case nsIPermissionManager.ALLOW_ACTION:
138 accessString = CM_COOKIE_ACCESS_ALLOW;
139 break;
140 case nsIPermissionManager.DENY_ACTION:
141 accessString = CM_COOKIE_ACCESS_DENY;
142 break;
143 case nsICookiePermission.ACCESS_SESSION:
144 accessString = CM_COOKIE_ACCESS_SESSION;
145 break;
146 default:
147 accessString = CM_COOKIE_ACCESS_DEFAULT;
148 break;
149 }
150
151 return accessString;
152 },
153
154 // Check the exact permission access level for the URI and
155 // return an array of string representation of the values
156 // for both the top level and 2nd level domain,
157 // plus a standard testPermission on the URI
158 // testExactPermission requires an exact hostname match - subdomains are not a match
159 checkPermissionArray: function(aURI, aType)
160 {
161 var accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
162 var accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
163 var accessString = CM_COOKIE_ACCESS_DEFAULT;
164 var accessArray = new Array(accessStringTop, accessStringSecond, accessString);
165 var secondURI = this.getSecondLevelURI(aURI);
166 var tempURIIndex = -1;
167
168 var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
169 .getService(Components.interfaces.nsIPermissionManager);
170
171 // Determine what test permission method to use based
172 // on the value of _isExactPermission
173 if (this._isExactPerm)
174 {
175 // Top level domain
176 switch (permissionManager.testExactPermission(aURI ,aType))
177 {
178 case 0:
179 accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
180 break;
181 case nsIPermissionManager.ALLOW_ACTION:
182 accessStringTop = CM_COOKIE_ACCESS_ALLOW;
183 break;
184 case nsIPermissionManager.DENY_ACTION:
185 accessStringTop = CM_COOKIE_ACCESS_DENY;
186 break;
187 case nsICookiePermission.ACCESS_SESSION:
188 accessStringTop = CM_COOKIE_ACCESS_SESSION;
189 break;
190 default:
191 accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
192 break;
193 }
194
195 // Second level domain
196 switch (permissionManager.testExactPermission(secondURI ,aType))
197 {
198 case 0:
199 accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
200 break;
201 case nsIPermissionManager.ALLOW_ACTION:
202 accessStringSecond = CM_COOKIE_ACCESS_ALLOW;
203 break;
204 case nsIPermissionManager.DENY_ACTION:
205 accessStringSecond = CM_COOKIE_ACCESS_DENY;
206 break;
207 case nsICookiePermission.ACCESS_SESSION:
208 accessStringSecond = CM_COOKIE_ACCESS_SESSION;
209 break;
210 default:
211 accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
212 break;
213 }
214 }
215 else
216 {
217 // Second level domain
218 switch (permissionManager.testPermission(secondURI ,aType))
219 {
220 case 0:
221 accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
222 break;
223 case nsIPermissionManager.ALLOW_ACTION:
224 accessStringSecond = CM_COOKIE_ACCESS_ALLOW;
225 break;
226 case nsIPermissionManager.DENY_ACTION:
227 accessStringSecond = CM_COOKIE_ACCESS_DENY;
228 break;
229 case nsICookiePermission.ACCESS_SESSION:
230 accessStringSecond = CM_COOKIE_ACCESS_SESSION;
231 break;
232 default:
233 accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
234 break;
235 }
236
237 // Top level domain
238 switch (permissionManager.testPermission(aURI ,aType))
239 {
240 case 0:
241 accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
242 break;
243 case nsIPermissionManager.ALLOW_ACTION:
244 accessStringTop = CM_COOKIE_ACCESS_ALLOW;
245 break;
246 case nsIPermissionManager.DENY_ACTION:
247 accessStringTop = CM_COOKIE_ACCESS_DENY;
248 break;
249 case nsICookiePermission.ACCESS_SESSION:
250 accessStringTop = CM_COOKIE_ACCESS_SESSION;
251 break;
252 default:
253 accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
254 break;
255 }
256 }
257
258 // Standard testPermission for URI (End Result)
259 switch (permissionManager.testPermission(aURI ,aType))
260 {
261 case 0:
262 accessString = CM_COOKIE_ACCESS_DEFAULT;
263 break;
264 case nsIPermissionManager.ALLOW_ACTION:
265 accessString = CM_COOKIE_ACCESS_ALLOW;
266 break;
267 case nsIPermissionManager.DENY_ACTION:
268 accessString = CM_COOKIE_ACCESS_DENY;
269 break;
270 case nsICookiePermission.ACCESS_SESSION:
271 accessString = CM_COOKIE_ACCESS_SESSION;
272 break;
273 default:
274 accessString = CM_COOKIE_ACCESS_DEFAULT;
275 break;
276 }
277
278 // Lastly check to see if this is a temporary permission
279 tempURIIndex = this._tempAllowList.indexOf(aURI.asciiHost);
280 if (tempURIIndex > -1)
281 {
282 accessStringTop = CM_COOKIE_ACCESS_TEMP_ALLOW;
283 accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
284 }
285
286 tempURIIndex = this._tempAllowList.indexOf(secondURI.asciiHost);
287 if (tempURIIndex > -1)
288 {
289 accessStringSecond = CM_COOKIE_ACCESS_TEMP_ALLOW;
290 accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
291
292 // If not ExactPerm and second level is temporary,
293 // then if top level is allow, change to temporary
294 // because any cookies will be deleted upon exit
295 if (!this._isExactPerm && (accessStringTop == CM_COOKIE_ACCESS_ALLOW))
296 {
297 accessStringTop = CM_COOKIE_ACCESS_TEMP_ALLOW;
298 }
299 }
300
301 accessArray[CM_TOP_LEVEL] = accessStringTop;
302 accessArray[CM_SECOND_LEVEL] = accessStringSecond;
303 accessArray[CM_URL_STANDARD_LEVEL] = accessString;
304
305 return accessArray;
306 },
307
308 // Input the numeric permission level and
309 // return a string representation of this value
310 getPermissionString: function(aValue)
311 {
312 var accessString = CM_COOKIE_ACCESS_DEFAULT;
313
314 switch (aValue*1)
315 {
316 case 0:
317 accessString = CM_COOKIE_ACCESS_DEFAULT;
318 break;
319 case nsIPermissionManager.ALLOW_ACTION:
320 accessString = CM_COOKIE_ACCESS_ALLOW;
321 break;
322 case nsIPermissionManager.DENY_ACTION:
323 accessString = CM_COOKIE_ACCESS_DENY;
324 break;
325 case nsICookiePermission.ACCESS_SESSION:
326 accessString = CM_COOKIE_ACCESS_SESSION;
327 break;
328 default:
329 accessString = CM_COOKIE_ACCESS_DEFAULT;
330 break;
331 }
332
333 return accessString;
334 },
335
336 // Input the string representation
337 // of the permission level and
338 // return the numeric representation of this value
339 getPermissionValue: function(aValue)
340 {
341 var accessValue = 0;
342
343 switch (aValue)
344 {
345 case CM_COOKIE_ACCESS_DEFAULT:
346 accessValue = 0;
347 break;
348 case CM_COOKIE_ACCESS_ALLOW:
349 accessValue = nsIPermissionManager.ALLOW_ACTION;
350 break;
351 case CM_COOKIE_ACCESS_DENY:
352 accessValue = nsIPermissionManager.DENY_ACTION;
353 break;
354 case CM_COOKIE_ACCESS_SESSION:
355 accessValue = nsICookiePermission.ACCESS_SESSION;
356 break;
357 default:
358 accessValue = 0;
359 break;
360 }
361
362 return accessValue;
363 },
364
365 // Set override for hosts cookie access
366 setCookieAccess: function(aURI, aAccess, aDomainType)
367 {
368 var hostURI = null;
369 var tempHostIndex = -1;
370
371 if (aDomainType == CM_SECOND_LEVEL)
372 {
373 hostURI = this.getSecondLevelURI(aURI);
374 }
375 else
376 {
377 hostURI = aURI;
378 }
379
380 // Check if temporary access
381 if (aAccess == -1)
382 {
383 this._tempAllowList.push(hostURI.asciiHost);
384 cookieMonster_nsPreferences.setAppendToStringPref(CM_PREFERENCE_TYPE_COOKIE_TEMP, hostURI.asciiHost);
385 aAccess = 1;
386 }
387 else
388 {
389 tempHostIndex = this._tempAllowList.indexOf(hostURI.asciiHost);
390 if (tempHostIndex > -1)
391 {
392 this._tempAllowList.splice(tempHostIndex, 1);
393 cookieMonster_nsPreferences.setStringPrefArray(CM_PREFERENCE_TYPE_COOKIE_TEMP, this._tempAllowList);
394
395 // If the updated permission is Deny or Default, where Default
396 // is Deny, then delete any cookies set for this host
397 if ((aAccess == nsIPermissionManager.DENY_ACTION) ||
398 ((aAccess == 0) && (cookieMonster_PrefObserver.getCookiePrefString() == "Rejected")))
399 {
400 this.resetTempCookieURI(hostURI);
401 }
402 }
403 }
404
405 this.choice.setAccess(hostURI, aAccess);
406
407 // If new access is deny and the preference
408 // deletecookiesondeny is true
409 // then delete existing cookies for this host
410 if ((aAccess == nsIPermissionManager.DENY_ACTION) &&
411 cookieMonster_nsPreferences.getBoolPref("deletecookiesondeny", false))
412 {
413 this.deleteHostCookies(hostURI.host, false);
414 }
415 },
416
417 // Convert URI to Second Level Domain
418 // (i.e. groups.yahoo.com to yahoo.com)
419 getSecondLevelURI: function(aURI)
420 {
421 // Parse the host string
422 var hostString = aURI.asciiHost;
423 var newHostString = null;
424 var newHost = aURI;
425
426 newHostString = cookieMonster_CookieInfo.getSecondLevelHost(hostString);
427
428 try
429 {
430 var ioService = Components.classes["@mozilla.org/network/io-service;1"]
431 .getService(Components.interfaces.nsIIOService);
432 newHost = ioService.newURI("http://"+newHostString, null, null);
433 }
434 catch(ex)
435 {
436 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
437 .getService(Components.interfaces.nsIPromptService);
438 var message = this._bundle.getString("invalidURI");
439 var title = this._bundle.getString("invalidURITitle");
440 promptService.alert(window, title, message);
441 }
442
443 return newHost;
444 },
445
446 // Convert Host String to Second Level Domain
447 // (i.e. groups.yahoo.com to yahoo.com)
448 getSecondLevelHost: function(aHost)
449 {
450 // Parse the host string
451 var checkExp = /^com|^net|^org/i;
452 var newHostString = null;
453
454 // Is this the special case where
455 // the URI ends in two characters
456 var hostParts = aHost.split(".");
457
458 // Do not parse if hostParts.length < 3
459 if (hostParts.length >= 3)
460 {
461 // Normal URI
462 if (hostParts[hostParts.length - 1].length > 2)
463 {
464 newHostString = hostParts[hostParts.length - 2] + "." +
465 hostParts[hostParts.length - 1];
466 }
467 // Check to see if special
468 // (e.g. www.domain.com.au)/com|net|org/
469 else if(checkExp.test(hostParts[hostParts.length - 2]) ||
470 hostParts[hostParts.length - 1].length <= 2)
471 {
472
473 newHostString = hostParts[hostParts.length - 3] + "." +
474 hostParts[hostParts.length - 2] + "." +
475 hostParts[hostParts.length - 1];
476 }
477 else
478 {
479 newHostString = hostParts[hostParts.length - 2] + "." +
480 hostParts[hostParts.length - 1];
481 }
482 }
483 else
484 {
485 newHostString = aHost;
486 }
487
488 //alert("Old Host: " + aHost + " New Host: " + newHostString);
489 return newHostString;
490 },
491
492 // Reset temp cookie list
493 resetTempCookies: function()
494 {
495 // Delete any cookie data for items in _tempAllowList,
496 // then delete any URLs in CM_PREFERENCE_TYPE_COOKIE_TEMP
497 var tempAllowList = cookieMonster_nsPreferences.getStringPrefArray(CM_PREFERENCE_TYPE_COOKIE_TEMP);
498 tempAllowList.forEach(this.resetTempCookieValues, cookieMonster_CookieInfo);
499 cookieMonster_nsPreferences.clearUserPref(CM_PREFERENCE_TYPE_COOKIE_TEMP);
500 },
501
502 // Delete temp cookies from host and reset temp cookie permissions
503 resetTempCookieValues: function(aHost)
504 {
505 var aURI = null;
506
507 // Set aUseBaseDomain to true
508 this.deleteHostCookies(aHost, true);
509
510 try
511 {
512 var ioService = Components.classes["@mozilla.org/network/io-service;1"]
513 .getService(Components.interfaces.nsIIOService);
514 aURI = ioService.newURI("http://"+aHost, null, null);
515 }
516 catch(ex)
517 {
518 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
519 .getService(Components.interfaces.nsIPromptService);
520 var message = this._bundle.getString("invalidURI");
521 var title = this._bundle.getString("invalidURITitle");
522 promptService.alert(window, title, message);
523 }
524
525 this.setCookieAccess(aURI, CM_COOKIE_ACCESS_DEFAULT, CM_TOP_LEVEL);
526 },
527
528 // Delete temp cookies from URI and reset temp cookie permissions
529 resetTempCookieURI: function(aURI)
530 {
531 // Set aUseBaseDomain to true
532 this.deleteHostCookies(aURI.asciiHost, true);
533
534 this.setCookieAccess(aURI, CM_COOKIE_ACCESS_DEFAULT, CM_TOP_LEVEL);
535 },
536
537 // Delete cookies from host
538 deleteHostCookies: function(aHost, aUseBaseDomain)
539 {
540 var deleteHost = aHost;
541 var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
542 .getService(Components.interfaces.nsICookieManager);
543
544 // If checking 2nd level domain names, make sure
545 // deleteHost is a 2nd level domain of aHost
546 if (aUseBaseDomain)
547 {
548 deleteHost = this.getSecondLevelHost(aHost);
549 }
550
551 var iter = cookieManager.enumerator;
552 while (iter.hasMoreElements())
553 {
554 var cookie = iter.getNext();
555
556 if (cookie instanceof Components.interfaces.nsICookie)
557 {
558 // Delete cookies matching aHost
559 var cookieHost = (cookie.host.charAt(0) == ".") ? cookie.host.substring(1,cookie.host.length) : cookie.host;
560
561 // If checking 2nd level domain names, make sure
562 // cookieHost is a 2nd level domain of the cookie
563 if (aUseBaseDomain)
564 {
565 cookieHost = this.getSecondLevelHost(cookieHost);
566 }
567
568 if (cookieHost == deleteHost)
569 {
570 //alert("Delete: " + cookie.host);
571 cookieManager.remove(cookie.host , cookie.name , cookie.path , 0);
572 }
573 }
574 }
575 }
576 }
577
578
579 // Based upon code sample from MozillaZine
580 // http://kb.mozillazine.org/Progress_listeners
581 // Progress listeners allow extensions to be notified of events associated
582 // with documents loading in the browser and with tab switching events.
583 // Progress listeners implement the nsIWebProgressListener interface.
584 // Create an object which implements nsIWebProgressListener
585 var cookieMonster_urlBarListener =
586 {
587 QueryInterface: function(aIID)
588 {
589 if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
590 aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
591 aIID.equals(Components.interfaces.nsISupports))
592 return this;
593 throw Components.results.NS_NOINTERFACE;
594 },
595
596 onLocationChange: function(aProgress, aRequest, aURI)
597 {
598 cookieMonster.processNewURL(aProgress, aRequest, aURI);
599 return 0;
600 },
601
602 onStateChange: function() {},
603 onProgressChange: function() {},
604 onStatusChange: function() {},
605 onSecurityChange: function() {},
606 onLinkIconAvailable: function() {}
607 };
608
609 var cookieMonster =
610 {
611 _oldURL: null,
612 _oldAccess: null,
613 _browser: null,
614 _menuBundle: null,
615 _userDefault: null,
616 _statusBarPanel: null,
617 _statusBarMenu: null,
618 _statusBarMenuId: null,
619 _statusBarSubMenu: null,
620 _statusBarSubMenuId: null,
621 _statusBarMenuArray: null,
622 _secondLevel: false,
623 _secondLevelId: null,
624 _currentSubMenu: CM_SECOND_LEVEL,
625 _menuStatus: false,
626 _iconArray: null,
627 _flagMenuEvent: false,
628
629 init: function()
630 {
631 var copyURI = null;
632 // Listen for webpage loads
633 // gBrowser is only accessible from the scope of Firefox,
634 // to use gBrowser within an extension you must declare it
635 this._browser = document.getElementById("content");
636 this._browser.addProgressListener(cookieMonster_urlBarListener,
637 Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
638 copyURI = Components.classes["@mozilla.org/network/io-service;1"].
639 getService(Components.interfaces.nsIIOService);
640 this._oldURL = copyURI.newURI("about:blank", null, null);
641 //this._oldAccess = 0;
642 this._oldAccess = new Array(CM_COOKIE_ACCESS_DEFAULT, CM_COOKIE_ACCESS_DEFAULT, CM_COOKIE_ACCESS_DEFAULT);
643
644 // Add extension name to cookieMonster_nsPreferences
645 cookieMonster_nsPreferences.mBranch = "cookiemonster";
646
647 // Initialize CookieInfo
648 cookieMonster_CookieInfo.init();
649
650 // Register preferences and permission observers
651 cookieMonster_PrefObserver.register();
652 cookieMonster_ObserverService.register();
653
654 // Retrieve users's default cookie permissions
655 this._userDefault = cookieMonster_PrefObserver.getCookiePrefString();
656
657 // Create a reference to all the menu elements
658 this._menuBundle = document.getElementById("cookie-menu-labels");
659 this._statusBarPanel = document.getElementById("cookiemonster-status");
660
661 // if (cookieMonster_CookieInfo.isExactPermissions())
662 // {
663 // this._statusBarMenuId = "cookie-access";
664 // this._secondLevelId = "second-level";
665 // this._statusBarSubMenuId = "cookie-access-alternate";
666 // }
667 // else
668 // {
669 // this._statusBarMenuId = "cookie-access-old";
670 // this._secondLevelId = "second-level-old";
671 // this._statusBarSubMenuId = "cookie-access-alternate";
672 // }
673
674 this._statusBarMenuId = "cookie-access";
675 this._secondLevelId = "second-level";
676 this._statusBarSubMenuId = "cookie-access-alternate";
677
678 // Retrieve the current value for secondlevelurl and
679 // initialize secondlevelurl in StatusbarMenu
680 this._secondLevel = cookieMonster_nsPreferences.getBoolPref("secondlevelurl", false);
681
682 this._statusBarMenu = document.getElementById(this._statusBarMenuId);
683 this._statusBarMenu.addEventListener('command', function(event) {cookieMonster.extMenuCommandHandler(event)},
684 true);
685
686 this._statusBarSubMenu = document.getElementById(this._statusBarSubMenuId);
687
688 this._statusBarMenuArray = new Array(this._statusBarMenu, this._statusBarSubMenu);
689
690 if (this._secondLevel)
691 {
692 document.getElementById(this._secondLevelId).setAttribute("checked", "true");
693 this.switchCookieSubMenu();
694 }
695
696 // Set tooltip attribute for enhanced tool tip info
697 this._statusBarPanel.removeAttribute("tooltiptext");
698 this._statusBarPanel.setAttribute("tooltip", "cookie-results");
699
700 // Load icons into _iconArray
701 this._iconArray = new Object();
702 this._iconArray[CM_COOKIE_ACCESS_DEFAULT] = CM_ICON_DEFAULT;
703 this._iconArray[CM_COOKIE_ACCESS_TEMP_ALLOW] = CM_ICON_TEMP_ALLOW;
704 this._iconArray[CM_COOKIE_ACCESS_ALLOW] = CM_ICON_ALLOW;
705 this._iconArray[CM_COOKIE_ACCESS_DENY] = CM_ICON_DENY;
706 this._iconArray[CM_COOKIE_ACCESS_SESSION] = CM_ICON_SESSION;
707 },
708
709 uninit: function()
710 {
711 this._browser.removeProgressListener(cookieMonster_urlBarListener);
712
713 // Unregister all observers
714 cookieMonster_PrefObserver.unregister();
715 cookieMonster_ObserverService.unregister();
716 },
717
718 processNewURL: function(aProgress, aRequest, aURI)
719 {
720 var accessLevel = null;
721
722 // Check to see if the URI contains any data
723 if ((aURI != null) && (aURI.asciiHost != undefined))
724 {
725 // If necessary, "Enable" popup menu for statusbar panel
726 this.setStatusMenuEnabled(true);
727
728 // Check if the URI is changing
729 if (aURI.spec != this._oldURL.spec)
730 {
731 // Obtain the access level
732 //accessLevel = cookieMonster_CookieInfo.checkPermissionString(aURI, CM_PERMISSION_TYPE_COOKIE);
733
734 // Update oldURL and oldAccess
735 this._oldURL = aURI.clone();
736 this._oldAccess = cookieMonster_CookieInfo.checkPermissionArray(aURI, CM_PERMISSION_TYPE_COOKIE);
737
738 // if host is empty, "disable" statusbar menu \s\w*
739 if (aURI.asciiHost.replace(/^\s*$/, "") == "")
740 {
741 this.setStatusMenuEnabled(false);
742 }
743 }
744
745 // Update statusbar menu
746 cookieMonster.updateStatusbarMenu(this._oldURL.asciiHost, this._oldAccess);
747 }
748 else
749 {
750 // If URI is blank, then "disable" popup menu for statusbar panel
751 this.setStatusMenuEnabled(false);
752 }
753 },
754
755 // Update the text and menuitems in the statusbar popup menu
756 updateStatusbarMenu: function(aHost, aAccess)
757 {
758 //alert("Host: " + aHost + " Access: " + aAccess[CM_TOP_LEVEL]);
759 var menuNodes = null;
760 var hostDisplay = aHost;
761 var hostDomain = cookieMonster_CookieInfo.getSecondLevelHost(aHost);
762 var hostAccess = aAccess[CM_URL_STANDARD_LEVEL];
763 var checkOldAccess = aAccess[CM_TOP_LEVEL];
764 var icoStatusBar = null;
765 var permissionsDisplayTop = document.getElementById("permissions-top");
766 var permissionsDisplaySecond = document.getElementById("permissions-second");
767 var permissionsDisplayResult = document.getElementById("permissions-result");
768 var cookieTooltipSite = document.getElementById("cookie-group-site");
769 var cookieTooltipDomain = document.getElementById("cookie-group-domain");
770 var cookieTooltipResult = document.getElementById("cookie-group-result");
771 var showCookiesCurrentDomain = document.getElementById("show-cookies-site");
772
773 // If the user has selected 2nd Level domains,
774 // then display as such
775 if (this._secondLevel)
776 {
777 hostDisplay = cookieMonster_CookieInfo.getSecondLevelHost(aHost);
778 checkOldAccess = aAccess[CM_SECOND_LEVEL];
779 }
780
781 // Walk the menus to update the menuitems
782 for (var x = 0; x < this._statusBarMenuArray.length; x++)
783 {
784 if (this._statusBarMenuArray[x].hasChildNodes())
785 {
786 menuNodes = this._statusBarMenuArray[x].childNodes;
787 for (var i = 0; i < menuNodes.length; i++)
788 {
789 var menu = menuNodes [i];
790 if (menu.nodeName != "menuitem")
791 {
792 continue;
793 }
794
795 // If access level matches node, then name
796 // current-access in order for image to show
797 var idName = menu.getAttribute("id").split("-");
798 var idDomain = idName[idName.length - 2];
799 var idParsed = idName[idName.length - 1];
800
801 if (idDomain == "top")
802 {
803 if (idParsed == aAccess[CM_TOP_LEVEL].toString().toLowerCase())
804 {
805 menu.setAttribute("name","current-access");
806 }
807 else
808 {
809 menu.setAttribute("name","cookie-top");
810 }
811 menu.setAttribute("label", this._menuBundle.getString(idParsed) + " " + aHost);
812 }
813 else if (idDomain == "second")
814 {
815 if (idParsed == aAccess[CM_SECOND_LEVEL].toString().toLowerCase())
816 {
817 menu.setAttribute("name","current-access");
818 }
819 else
820 {
821 menu.setAttribute("name","cookie-two");
822 }
823 menu.setAttribute("label", this._menuBundle.getString(idParsed) + " " + hostDomain);
824 }
825 else if (idDomain == "default")
826 {
827 if (idParsed == aAccess[CM_URL_STANDARD_LEVEL].toString().toLowerCase())
828 {
829 menu.setAttribute("name","current-access");
830 }
831 else
832 {
833 menu.setAttribute("name","cookie-default");
834 }
835 menu.setAttribute("label", this._menuBundle.getString(idParsed) + " (" + this._userDefault + ")");
836 }
837 else if (idDomain == "access")
838 {
839 // This is for the old version of the menu
840 if (idParsed == checkOldAccess.toString().toLowerCase())
841 {
842 menu.setAttribute("name","current-access");
843 }
844 else
845 {
846 menu.setAttribute("name","cookie-access");
847 }
848 menu.setAttribute("label", this._menuBundle.getString(idParsed) + " " + hostDisplay);
849
850 // For default, display users cookie permission preferences
851 if (idParsed == CM_COOKIE_ACCESS_DEFAULT.toLowerCase())
852 {
853 menu.setAttribute("label", this._menuBundle.getString(idParsed) + " (" + this._userDefault + ")");
854 }
855 }
856 }
857 }
858 }
859
860 // Add domain name to show cookies for current site
861 showCookiesCurrentDomain.setAttribute("label", this._menuBundle.getString("showcurrentcookies") + " " + hostDomain);
862 showCookiesCurrentDomain.setAttribute("name", hostDomain);
863
864 // Update permissions Synopsis and Enhanced Tooltip
865 permissionsDisplayTop.setAttribute("label", this._menuBundle.getString("sitepermissions") +
866 " (" + aHost + "): " + this._menuBundle.getString(aAccess[CM_TOP_LEVEL]));
867 permissionsDisplaySecond.setAttribute("label", this._menuBundle.getString("domainpermissions") +
868 " (" + hostDomain + "): " + this._menuBundle.getString(aAccess[CM_SECOND_LEVEL]));
869 permissionsDisplayResult.setAttribute("label", this._menuBundle.getString("permissionsresult") +
870 " for " + aHost + ": " + this._menuBundle.getString(hostAccess));
871
872 permissionsDisplayTop.setAttribute("image", this._iconArray[aAccess[CM_TOP_LEVEL]]);
873 permissionsDisplaySecond.setAttribute("image", this._iconArray[aAccess[CM_SECOND_LEVEL]]);
874 permissionsDisplayResult.setAttribute("image", this._iconArray[hostAccess]);
875
876 cookieTooltipSite.firstChild.setAttribute("label", this._menuBundle.getString("sitepermissions") +
877 ": " + this._menuBundle.getString(aAccess[CM_TOP_LEVEL]));
878 cookieTooltipDomain.firstChild.setAttribute("label", this._menuBundle.getString("domainpermissions") +
879 ": " + this._menuBundle.getString(aAccess[CM_SECOND_LEVEL]));
880 cookieTooltipResult.firstChild.setAttribute("label", this._menuBundle.getString("permissionsresult") +
881 ": " + this._menuBundle.getString(hostAccess));
882
883 cookieTooltipSite.firstChild.setAttribute("image", this._iconArray[aAccess[CM_TOP_LEVEL]]);
884 cookieTooltipDomain.firstChild.setAttribute("image", this._iconArray[aAccess[CM_SECOND_LEVEL]]);
885 cookieTooltipResult.firstChild.setAttribute("image", this._iconArray[hostAccess]);
886
887 cookieTooltipSite.lastChild.setAttribute("value", aHost);
888 cookieTooltipDomain.lastChild.setAttribute("value", hostDomain);
889 cookieTooltipResult.lastChild.setAttribute("value", aHost);
890
891 // Set the icon for the status bar menu
892 this._statusBarPanel.setAttribute("src", this._iconArray[hostAccess]);
893 },
894
895 // Swap the menu items in the submenu
896 // with those in the main menu,
897 // based on the _secondLevel flag
898 switchCookieSubMenu: function()
899 {
900 if (this._secondLevel)
901 {
902 this.setCookieSubMenu(CM_TOP_LEVEL);
903 }
904 else
905 {
906 this.setCookieSubMenu(CM_SECOND_LEVEL);
907 }
908 },
909
910 // Move cookie setting menu items for aUrlLevel
911 // to the submenu and place the cookie setting menu items
912 // for the other aUrlLevel in the main menu
913 setCookieSubMenu: function(aUrlLevel)
914 {
915 var cookieMenuItems = new Array(
916 new Array(document.getElementById("cookie-access-top-temp"), document.getElementById("cookie-access-second-temp")),
917 new Array(document.getElementById("cookie-access-top-allow"), document.getElementById("cookie-access-second-allow")),
918 new Array(document.getElementById("cookie-access-top-deny"), document.getElementById("cookie-access-second-deny")),
919 new Array(document.getElementById("cookie-access-top-session"), document.getElementById("cookie-access-second-session"))
920 );
921 var cookieMenuSeparator = document.getElementById("temp-after-this");
922 var swapCookieMenuItems;
923
924 // Check current setting to see if
925 // a switch is necessary
926 if (aUrlLevel != this._currentSubMenu)
927 {
928 // Configure how the cookieMenuItems array values
929 // are sent to the replace command
930 if (aUrlLevel == CM_SECOND_LEVEL)
931 {
932 // Reverse the array order for each menu item
933 for (var i = 0, menuItems; menuItems = cookieMenuItems[i]; i++)
934 {
935 menuItems.reverse();
936 }
937 }
938
939 // Replace menu items in sub menu
940 swapCookieMenuItems = cookieMenuItems.map(function(menuItem)
941 {
942 //alert("swapCookieMenuItems: menuItem " + menuItem[0].getAttribute("id"));
943 var replaceItem = this._statusBarSubMenu.replaceChild(menuItem[0], menuItem[1]);
944 return replaceItem;
945 }, cookieMonster);
946
947 // Add replaced menu items to main status bar menu
948 for (var i = 0, swapMenuItem; swapMenuItem = swapCookieMenuItems[i]; i++)
949 {
950 // Place menu item temp after correct menu separator
951 if (i == 0)
952 {
953 this._statusBarMenu.insertBefore(swapMenuItem, cookieMenuSeparator.nextSibling);
954 }
955 else
956 {
957 this._statusBarMenu.appendChild(swapMenuItem);
958 }
959 }
960
961 // Change this._currentSubMenu to aUrllevel
962 this._currentSubMenu = aUrlLevel;
963 }
964 },
965
966 setStatusMenuEnabled: function(aEnable)
967 {
968 // Set popup attribute to desired status, if necessary
969 if (aEnable != this._menuStatus)
970 {
971 if (aEnable)
972 {
973 this._statusBarPanel.setAttribute("popup", this._statusBarMenuId);
974 }
975 else
976 {
977 // If disable popup, then
978 // set the icon for the status bar menu to default
979 this._statusBarPanel.setAttribute("popup", "");
980 this._statusBarPanel.setAttribute("src", this._iconArray[CM_COOKIE_ACCESS_DEFAULT]);
981 }
982
983 // Set member variable to track status of the menu
984 this._menuStatus = aEnable;
985 }
986 },
987
988 extSetCookieAccess: function(aAccess, domainType)
989 {
990 //alert("Setting Cookie Status for " + this._oldURL.asciiHost);
991 cookieMonster_CookieInfo.setCookieAccess(this._oldURL, aAccess, domainType);
992 this._oldAccess = cookieMonster_CookieInfo.checkPermissionArray(this._oldURL, CM_PERMISSION_TYPE_COOKIE);
993 },
994
995 extResetTempCookies: function()
996 {
997 //alert("Resetting All Temp Cookies Upon Browser Exit");
998 cookieMonster_CookieInfo.resetTempCookies();
999 },
1000
1001 // Process the commands pertaining
1002 // to the menu choices made by the user
1003 extMenuCommandHandler: function(evt)
1004 {
1005 var checkExpCookie = /^cookie-access/i;
1006 var itemPicked = null;
1007 var accessString = null;
1008 var accessValue = null;
1009
1010 var itemPicked = document.getElementById(evt.target.id);
1011 //alert("Menu Command Event Id: " + evt.target.id + " CM_TOP_LEVEL: " + this._oldAccess[CM_TOP_LEVEL]);
1012
1013 // Set menu event flag so we don't double trigger a
1014 // poermissions update
1015 cookieMonster._flagMenuEvent = true;
1016
1017 // If id contains cookie-access and
1018 // name = cookie, then assign new
1019 // cookie access and reload page
1020 if (checkExpCookie.test(evt.target.id))
1021 {
1022 if (itemPicked.getAttribute("name") == "cookie-top")
1023 {
1024 cookieMonster.extSetCookieAccess(evt.target.value, CM_TOP_LEVEL);
1025 }
1026 else if(itemPicked.getAttribute("name") == "cookie-two")
1027 {
1028 cookieMonster.extSetCookieAccess(evt.target.value, CM_SECOND_LEVEL);
1029 }
1030 else if(itemPicked.getAttribute("name") == "cookie-access")
1031 {
1032 if (this._secondLevel)
1033 {
1034 cookieMonster.extSetCookieAccess(evt.target.value, CM_SECOND_LEVEL);
1035 }
1036 else
1037 {
1038 cookieMonster.extSetCookieAccess(evt.target.value, CM_TOP_LEVEL);
1039 }
1040 }
1041 else if(itemPicked.getAttribute("name") == "cookie-default")
1042 {
1043 cookieMonster.extSetCookieAccess(evt.target.value, CM_TOP_LEVEL);
1044 cookieMonster.extSetCookieAccess(evt.target.value, CM_SECOND_LEVEL);
1045 }
1046 this._browser.reload(this._browser.webNavigation.LOAD_FLAGS_BYPASS_CACHE);
1047 //accessString = cookieMonster_CookieInfo.getPermissionString(evt.target.value);
1048 cookieMonster.updateStatusbarMenu(this._oldURL.asciiHost, this._oldAccess);
1049 }
1050 // If id=second-level, then determine
1051 // if it is checked and set variable and
1052 // user preference cookiemonster.secondlevelurl and
1053 // call switchCookieSubMenu to check if the cookie
1054 // submenu needs to be switched
1055 else if ((evt.target.id == this._secondLevelId) &&
1056 (this._secondLevel != itemPicked.getAttribute("checked")))
1057 {
1058 this._secondLevel = itemPicked.getAttribute("checked");
1059 cookieMonster_nsPreferences.setBoolPref("secondlevelurl", this._secondLevel);
1060 }
1061
1062 // Reset menu event flag
1063 cookieMonster._flagMenuEvent = false;
1064
1065 return false;
1066 },
1067
1068 // Set values based on preferences
1069 extUpdateFromPreferences: function(aPref)
1070 {
1071 var accessValue = null;
1072
1073 if (aPref == "secondlevelurl")
1074 {
1075 this._secondLevel = cookieMonster_nsPreferences.getBoolPref("secondlevelurl", false);
1076
1077 if (this._secondLevel)
1078 {
1079 document.getElementById(this._secondLevelId).setAttribute("checked", "true");
1080 }
1081 else
1082 {
1083 document.getElementById(this._secondLevelId).setAttribute("checked", "false");
1084 }
1085
1086 cookieMonster.updateStatusbarMenu(this._oldURL.asciiHost, this._oldAccess);
1087 this.switchCookieSubMenu();
1088 }
1089 else if ((aPref == "cookieBehavior") || (aPref == "lifetimePolicy"))
1090 {
1091 // Retrieve users's updated default cookie permissions and
1092 // update Statusbar menu
1093 this._userDefault = cookieMonster_PrefObserver.getCookiePrefString();
1094 cookieMonster.updateStatusbarMenu(this._oldURL.asciiHost, this._oldAccess);
1095 }
1096 },
1097
1098 // Set values based on permissions
1099 extUpdateFromPermissions: function(aHost)
1100 {
1101 // Retrieve new cookies permission for current URL, reload page and
1102 // update status bar
1103 //alert("Permission Event");
1104 if ((aHost == this._oldURL.host) && !cookieMonster._flagMenuEvent)
1105 {
1106 //alert("Permission Event and Not Menu Event");
1107 this._oldAccess = cookieMonster_CookieInfo.checkPermissionArray(this._oldURL, CM_PERMISSION_TYPE_COOKIE);
1108 this._browser.reload(this._browser.webNavigation.LOAD_FLAGS_BYPASS_CACHE);
1109 cookieMonster.updateStatusbarMenu(this._oldURL.asciiHost, this._oldAccess);
1110 }
1111 }
1112 };
1113
1114 // Edit: for me on Firefox 2.0, I had to change "document" to "window"
1115 // for the following lines to work
1116 window.addEventListener("load", function() {cookieMonster.init()},
1117 false);
1118 window.addEventListener("unload", function() {cookieMonster.uninit()},
1119 false);
1120