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