diff --git a/extensions/cookie/nsPermissions.cpp b/extensions/cookie/nsPermissions.cpp
index c8dbb28749f..559520a2a83 100644
--- a/extensions/cookie/nsPermissions.cpp
+++ b/extensions/cookie/nsPermissions.cpp
@@ -353,7 +353,6 @@ Permission_AddHost(const nsAFlatCString & host, PRBool permission, PRInt32 type,
typeStruct = NS_STATIC_CAST
(permission_TypeStruct*, hostStruct->permissionList->ElementAt(typeIndex));
if (typeStruct->type == type) {
-
/* type found. Modify the corresponding permission */
typeStruct->permission = permission;
typeFound = PR_TRUE;
@@ -459,7 +458,6 @@ Permission_Save(PRBool notify) {
* host \t permission \t permission ... \n
*/
-
PRInt32 hostCount = permission_list->Count();
for (PRInt32 i = 0; i < hostCount; ++i) {
hostStruct = NS_STATIC_CAST(permission_HostStruct*, permission_list->ElementAt(i));
@@ -632,6 +630,29 @@ PERMISSION_HostCount() {
return permission_list->Count();
}
+PUBLIC PRInt32
+PERMISSION_HostCountForType(PRInt32 type) {
+ if (!permission_list) {
+ return 0;
+ }
+
+ permission_HostStruct * hostStruct;
+ permission_TypeStruct * typeStruct;
+ PRInt32 hostCount = permission_list->Count();
+ PRInt32 hostCountForType = 0;
+ for (PRInt32 i = 0; i < hostCount; ++i) {
+ hostStruct = NS_STATIC_CAST(permission_HostStruct*, permission_list->ElementAt(i));
+ PRInt32 typeCount = hostStruct->permissionList->Count();
+ for (PRInt32 j = 0; j < typeCount; ++j) {
+ typeStruct = NS_STATIC_CAST(permission_TypeStruct *, hostStruct->permissionList->ElementAt(j));
+ if (typeStruct && typeStruct->type == type)
+ hostCountForType++;
+ }
+ }
+
+ return hostCountForType;
+}
+
PUBLIC PRInt32
PERMISSION_TypeCount(PRInt32 host) {
if (!permission_list) {
diff --git a/extensions/cookie/nsPermissions.h b/extensions/cookie/nsPermissions.h
index 55ede6b768d..1caac2bd2ab 100644
--- a/extensions/cookie/nsPermissions.h
+++ b/extensions/cookie/nsPermissions.h
@@ -66,6 +66,7 @@ extern void PERMISSION_RemoveAll();
extern void PERMISSION_DeletePersistentUserData(void);
extern PRInt32 PERMISSION_HostCount();
+extern PRInt32 PERMISSION_HostCountForType(PRInt32 type);
extern PRInt32 PERMISSION_TypeCount(PRInt32 host);
extern nsresult PERMISSION_Enumerate
(PRInt32 hostNumber, PRInt32 typeNumber, char **host, PRInt32 *type, PRBool *capability);
diff --git a/extensions/cookie/nsPopupWindowManager.cpp b/extensions/cookie/nsPopupWindowManager.cpp
index 1f4565b4504..d3398b43dc4 100644
--- a/extensions/cookie/nsPopupWindowManager.cpp
+++ b/extensions/cookie/nsPopupWindowManager.cpp
@@ -40,6 +40,7 @@
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsPermissions.h"
+#include "nsPermission.h"
#include "nsIObserverService.h"
#include "nsIPrefBranch.h"
@@ -58,6 +59,58 @@ static const char sPermissionChangeNotification[] = PPM_CHANGE_NOTIFICATION;
static const char sXPCOMShutdownTopic[] = NS_XPCOM_SHUTDOWN_OBSERVER_ID;
static const char sPrefChangedTopic[] = NS_PREFBRANCH_PREFCHANGE_TOPIC_ID;
+class nsPopupEnumerator : public nsISimpleEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsPopupEnumerator() : mHostCurrent(0), mTypeCurrent(0)
+ {
+ mHostCount = PERMISSION_HostCountForType(WINDOWPERMISSION);
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ *result = mHostCount > mHostCurrent;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ char *host;
+ PRBool capability;
+ PRInt32 type;
+
+ *result = nsnull;
+
+ while (NS_SUCCEEDED(PERMISSION_Enumerate(mHostCurrent, mTypeCurrent++, &host, &type, &capability))) {
+ if ((mTypeCurrent == PERMISSION_TypeCount(mHostCurrent)) || (type == WINDOWPERMISSION)) {
+ mTypeCurrent = 0;
+ mHostCurrent++;
+ }
+ if (type == WINDOWPERMISSION) {
+ nsIPermission *permission = new nsPermission(host, type, capability);
+ *result = permission;
+ NS_ADDREF(*result);
+ break;
+ }
+ }
+ return NS_OK;
+ }
+
+ virtual ~nsPopupEnumerator()
+ {
+ }
+
+ protected:
+ PRInt32 mHostCurrent;
+ PRInt32 mTypeCurrent;
+ PRInt32 mHostCount;
+};
+
+NS_IMPL_ISUPPORTS1(nsPopupEnumerator, nsISimpleEnumerator);
+
//*****************************************************************************
//*** nsPopupWindowManager object management and nsISupports
//*****************************************************************************
@@ -123,14 +176,15 @@ nsPopupWindowManager::Add(nsIURI *aURI, PRBool aPermit)
// if we couldn't initialize the permission manager Permission_AddHost()
// will create a new list that could stomp an existing cookperm.txt
return NS_ERROR_FAILURE;
-
+
nsCAutoString uri;
aURI->GetHostPort(uri);
if (uri.IsEmpty())
return NS_ERROR_FAILURE;
-
+
if (NS_SUCCEEDED(Permission_AddHost(uri, aPermit, WINDOWPERMISSION, PR_TRUE)))
return NotifyObservers(aURI);
+
return NS_ERROR_FAILURE;
}
@@ -205,10 +259,15 @@ nsPopupWindowManager::TestPermission(nsIURI *aURI, PRUint32 *_retval)
NS_IMETHODIMP
nsPopupWindowManager::GetEnumerator(nsISimpleEnumerator **_retval)
{
- NS_ENSURE_ARG_POINTER(_retval);
- *_retval = 0;
+ *_retval = nsnull;
- return NS_ERROR_NOT_IMPLEMENTED;
+ nsPopupEnumerator* popupEnum = new nsPopupEnumerator();
+ if (popupEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(popupEnum);
+ *_retval = popupEnum;
+ return NS_OK;
}
NS_IMETHODIMP
diff --git a/extensions/cookie/resources/content/cookieNavigatorOverlay.xul b/extensions/cookie/resources/content/cookieNavigatorOverlay.xul
index 489fcac7e86..a5dda685466 100644
--- a/extensions/cookie/resources/content/cookieNavigatorOverlay.xul
+++ b/extensions/cookie/resources/content/cookieNavigatorOverlay.xul
@@ -70,7 +70,7 @@
// determine current state (blocked or unblocked) and hide appropriate menu item
var blocked;
-
+
blocked =
permissionmanager.testForBlocking(window._content.location, COOKIEPERMISSION);
enableElement("AllowCookies", blocked);
@@ -80,7 +80,7 @@
permissionmanager.testForBlocking(window._content.location, IMAGEPERMISSION);
enableElement("AllowImages", blocked);
enableElement("BlockImages", !blocked);
-
+
SetPopupMenuEnabledState();
var pref;
@@ -104,19 +104,31 @@
}
function SetPopupMenuEnabledState() {
- // use care choosing which nsIPopupWindowManager constant to compare
- // against. the allow/disallow/sometimes relationship can be subtle.
- var useManager = !pref.getBoolPref("dom.disable_open_during_load");
var suitable = false;
- var enableBlock = false;
- if (useManager) {
- suitable = popupmanager.testSuitability(getBrowser().currentURI);
- if (suitable)
- enableBlock = popupmanager.testPermission(getBrowser().currentURI) != Components.interfaces.nsIPopupWindowManager.DENY_POPUP;
+ var blocked = false;
+ var policy = pref.getBoolPref("dom.disable_open_during_load");
+
+ suitable = popupmanager.testSuitability(getBrowser().currentURI);
+ if (suitable) {
+ if (!policy) // blacklist, test if there is a permission set
+ blocked = (popupmanager.testPermission(getBrowser().currentURI) == Components.interfaces.nsIPopupWindowManager.DENY_POPUP);
+ else { // whitelist, check if it is on list
+ blocked = true;
+ var enumerator = popupmanager.getEnumerator();
+ while (enumerator.hasMoreElements()) {
+ var permission = enumerator.getNext()
+ .QueryInterface(Components.interfaces.nsIPermission);
+ if (permission.capability && getBrowser().currentURI.host == permission.host) {
+ blocked = false;
+ break;
+ }
+ }
+ }
}
- enableElement("BlockPopups", useManager && suitable && enableBlock);
- enableElement("AllowPopups", useManager && suitable && !enableBlock);
- enableElement("ManagePopups", useManager);
+
+ enableElement("BlockPopups", suitable && !blocked);
+ enableElement("AllowPopups", suitable && blocked);
+ enableElement("ManagePopups", true);
}
function enableElement(elementID, enable) {
@@ -156,19 +168,45 @@
element = document.getElementById("BlockImages");
alert(element.getAttribute("msg"));
break;
- case "popupAllow":
- popupmanager.add(getBrowser().currentURI, true);
- element = document.getElementById("AllowPopups");
- alert(element.getAttribute("msg"));
- break;
- case "popupBlock":
- popupmanager.add(getBrowser().currentURI, false);
- element = document.getElementById("BlockPopups");
- alert(element.getAttribute("msg"));
- break;
default:
}
- }
+ }
+
+ function PopupAction(action) {
+ var policy = pref.getBoolPref("dom.disable_open_during_load");
+ var uri = getBrowser().currentURI;
+
+ switch (action) {
+ case "block":
+ if (!policy)
+ popupmanager.add(uri, policy);
+ else
+ popupmanager.remove(uri);
+ break;
+ case "allow":
+ var browsers = getBrowser().browsers;
+ var popupIcon = document.getElementById("popupIcon");
+ if (!policy)
+ popupmanager.remove(uri);
+ else
+ popupmanager.add(uri, policy);
+ for (var i = 0; i < browsers.length; i++) {
+ if (browsers[i].popupDomain == uri.host) {
+ browsers[i].popupDomain = null;
+ popupIcon.hidden = true;
+ }
+ }
+ break;
+ }
+ }
+
+ function ViewPopupManager() {
+ window.openDialog("chrome://communicator/content/popupManager.xul", "",
+ "chrome,resizable=yes,modal=yes",
+ pref.getBoolPref("dom.disable_open_during_load"),
+ "",
+ false);
+ }
]]>
@@ -220,15 +258,15 @@
+ oncommand="PopupAction('block');"/>
+ oncommand="PopupAction('allow');"/>
+ oncommand="ViewPopupManager();"/>
diff --git a/extensions/cookie/resources/content/cookiePrefsOverlay.xul b/extensions/cookie/resources/content/cookiePrefsOverlay.xul
index 0d4ec86138a..f7227a9413d 100644
--- a/extensions/cookie/resources/content/cookiePrefsOverlay.xul
+++ b/extensions/cookie/resources/content/cookiePrefsOverlay.xul
@@ -40,14 +40,12 @@
label="&images.label;"/>
-
diff --git a/extensions/cookie/resources/content/pref-popups.xul b/extensions/cookie/resources/content/pref-popups.xul
index 117b4bbeaed..0062f121886 100644
--- a/extensions/cookie/resources/content/pref-popups.xul
+++ b/extensions/cookie/resources/content/pref-popups.xul
@@ -48,69 +48,143 @@
onload="init()"
headertitle="&title;">
-
+
-
+ var _elementIDs = ["popupPolicy","playSound","playSoundUrl","displayIcon"];
-
+ function blacklistEmpty() {
+ var permissionmanager = Components.classes["@mozilla.org/permissionmanager;1"]
+ .getService(Components.interfaces.nsIPermissionManager);
+
+ var popupManager = Components.classes["@mozilla.org/PopupWindowManager;1"]
+ .getService(Components.interfaces.nsIPopupWindowManager);
+ var enumerator = popupManager.getEnumerator();
+
+ while (enumerator.hasMoreElements()) {
+ var permission = enumerator.getNext()
+ .QueryInterface(Components.interfaces.nsIPermission);
+ if (!permission.capability)
+ return false;
+ }
+ return true;
+ }
+
+ function setButtons() {
+ var exceptionsAllow = document.getElementById("exceptionsAllow");
+ var exceptionsBlock = document.getElementById("exceptionsBlock");
+
+ exceptionsAllow.disabled = (gPolicyButton.value == "true");
+ exceptionsBlock.disabled = (!exceptionsAllow.disabled);
+
+ if (blacklistEmpty() && (gPolicyButton.value == "false")) {
+ gSoundCheckbox.disabled = true;
+ gSoundUrlBox.disabled = true;
+ gSoundUrlButton.disabled = true;
+ gIconCheckbox.disabled = true;
+ }
+ else {
+ gSoundCheckbox.disabled = false;
+ gSoundUrlBox.disabled = false;
+ gSoundUrlButton.disabled = false;
+ gIconCheckbox.disabled = false;
+
+ enableSoundUrl(gSoundCheckbox.checked);
+ }
+ }
+
+ function selectSound() {
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var filepicker = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+
+ filepicker.init(window, document.getElementById("selectSound").getAttribute("filepickertitle"), nsIFilePicker.modeOpen);
+ filepicker.appendFilters(nsIFilePicker.filterAll);
+
+ var ret = filepicker.show();
+ if (ret == nsIFilePicker.returnOK)
+ gSoundUrlBox.value = filepicker.file.path;
+ }
+
+ function enableSoundUrl(soundChecked) {
+ gSoundUrlBox.disabled = !soundChecked;
+ gSoundUrlButton.disabled = !soundChecked;
+ }
+
+ function viewPopups() {
+ window.openDialog("chrome://communicator/content/popupManager.xul", "",
+ "chrome,resizable=yes,modal=yes",
+ (gPolicyButton.value == "true"),
+ "",
+ true);
+ }
+
+ ]]>
+
+
+
diff --git a/extensions/cookie/resources/locale/en-US/cookiePrefsOverlay.dtd b/extensions/cookie/resources/locale/en-US/cookiePrefsOverlay.dtd
index c3f2aebd7f1..e69de29bb2d 100644
--- a/extensions/cookie/resources/locale/en-US/cookiePrefsOverlay.dtd
+++ b/extensions/cookie/resources/locale/en-US/cookiePrefsOverlay.dtd
@@ -1,3 +0,0 @@
-
-
-
diff --git a/extensions/cookie/resources/locale/en-US/pref-popups.dtd b/extensions/cookie/resources/locale/en-US/pref-popups.dtd
index b86a564d9f8..a7d277ac31a 100644
--- a/extensions/cookie/resources/locale/en-US/pref-popups.dtd
+++ b/extensions/cookie/resources/locale/en-US/pref-popups.dtd
@@ -1,16 +1,24 @@
-
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
index 0ced59e4787..c119265dafb 100644
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -447,8 +447,8 @@ pref("dom.disable_window_open_feature.scrollbars", false);
pref("dom.disable_window_open_feature.resizable", false);
pref("dom.disable_window_open_feature.minimizable", false);
pref("dom.disable_window_open_feature.status", false);
-
-pref("dom.allow_scripts_to_close_windows", false);
+
+pref("dom.allow_scripts_to_close_windows", false);
pref("javascript.enabled", true);
pref("javascript.allow.mailnews", false);
@@ -837,4 +837,6 @@ pref("browser.popups.showPopupBlocker", true);
// See http://bugzilla.mozilla.org/show_bug.cgi?id=169483 for further details...
pref("viewmanager.do_doublebuffering", true);
-
+pref("privacy.popups.sound_enabled", true);
+pref("privacy.popups.sound_url", "");
+pref("privacy.popups.statusbar_icon_enabled", true);
diff --git a/themes/classic/jar.mn b/themes/classic/jar.mn
index 21d5c97c5ea..702d8a854b3 100644
--- a/themes/classic/jar.mn
+++ b/themes/classic/jar.mn
@@ -340,3 +340,4 @@ classic.jar:
skin/classic/navigator/icons/minimize.gif (navigator/icons/minimize.gif)
skin/classic/navigator/icons/restore.gif (navigator/icons/restore.gif)
skin/classic/navigator/icons/close.gif (navigator/icons/close.gif)
+ skin/classic/navigator/icons/popup-blocked.png (navigator/icons/popup-blocked.png)
diff --git a/themes/classic/navigator/icons/popup-blocked.png b/themes/classic/navigator/icons/popup-blocked.png
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/themes/classic/navigator/navigator.css b/themes/classic/navigator/navigator.css
index 1065441e65f..7314e49874b 100644
--- a/themes/classic/navigator/navigator.css
+++ b/themes/classic/navigator/navigator.css
@@ -338,6 +338,10 @@
list-style-image: url("chrome://communicator/skin/icons/lock-broken.gif");
}
+#popupIcon {
+ list-style-image: url("chrome://navigator/skin/icons/popup-blocked.png");
+}
+
/* ::::: personal toolbar ::::: */
#home-button {
@@ -351,4 +355,3 @@
#home-button:hover:active {
list-style-image: url("chrome://communicator/skin/bookmarks/home-active.gif");
}
-
diff --git a/themes/modern/jar.mn b/themes/modern/jar.mn
index 1aa6e6570e4..5ff29b6f5bd 100644
--- a/themes/modern/jar.mn
+++ b/themes/modern/jar.mn
@@ -441,3 +441,4 @@ modern.jar:
skin/modern/navigator/toolbar/urlbar-mid.gif (navigator/toolbar/urlbar-mid.gif)
skin/modern/navigator/icons/btn1.gif (navigator/icons/btn1.gif)
skin/modern/navigator/icons/btn1-small.gif (navigator/icons/btn1-small.gif)
+ skin/modern/navigator/icons/popup-blocked.png (navigator/icons/popup-blocked.png)
diff --git a/themes/modern/navigator/icons/popup-blocked.png b/themes/modern/navigator/icons/popup-blocked.png
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/themes/modern/navigator/navigator.css b/themes/modern/navigator/navigator.css
index d25711e4c21..6837c7afdaa 100644
--- a/themes/modern/navigator/navigator.css
+++ b/themes/modern/navigator/navigator.css
@@ -518,3 +518,7 @@
#security-button[level="broken"] {
list-style-image: url("chrome://communicator/skin/icons/lock-broken.gif");
}
+
+#popupIcon {
+ list-style-image: url("chrome://navigator/skin/icons/popup-blocked.png");
+}
diff --git a/xpfe/browser/resources/content/navigator.js b/xpfe/browser/resources/content/navigator.js
index 785e06abf01..de4b9bddab0 100644
--- a/xpfe/browser/resources/content/navigator.js
+++ b/xpfe/browser/resources/content/navigator.js
@@ -147,6 +147,52 @@ const gPopupPermListener = {
}
};
+const POPUP_TYPE = 2;
+const gPopupPrefListener =
+{
+ domain: "dom.disable_open_during_load",
+ observe: function(subject, topic, prefName)
+ {
+ if (topic != "nsPref:changed" || prefName != this.domain)
+ return;
+
+ var browsers = getBrowser().browsers;
+ var policy = pref.getBoolPref(prefName);
+
+ var hosts = [];
+
+ var popupManager = Components.classes["@mozilla.org/PopupWindowManager;1"]
+ .getService(Components.interfaces.nsIPopupWindowManager);
+
+ var enumerator = popupManager.getEnumerator();
+ var count=0;
+ while (enumerator.hasMoreElements()) {
+ var permission = enumerator.getNext()
+ .QueryInterface(Components.interfaces.nsIPermission);
+ if (permission.capability == policy)
+ hosts[permission.host] = permission.host;
+ }
+
+ var popupIcon = document.getElementById("popupIcon");
+
+ if (!policy) { // blacklist
+ for (var i = 0; i < browsers.length; i++) {
+ if (browsers[i].popupDomain in hosts)
+ break;
+ browsers[i].popupDomain = null;
+ popupIcon.hidden = true;
+ }
+ } else { // whitelist
+ for (var i = 0; i < browsers.length; i++) {
+ if (browsers[i].popupDomain in hosts) {
+ browsers[i].popupDomain = null;
+ popupIcon.hidden = true;
+ }
+ }
+ }
+ }
+};
+
/**
* Pref listener handler functions.
* Both functions assume that observer.domain is set to
@@ -428,6 +474,7 @@ function Startup()
addPrefListener(gTabStripPrefListener);
addPrefListener(gHomepagePrefListener);
addPopupPermListener(gPopupPermListener);
+ addPrefListener(gPopupPrefListener);
window.browserContentListener =
new nsBrowserContentListener(window, getBrowser());
@@ -551,6 +598,8 @@ function Startup()
// initiated by a web page script
addEventListener("fullscreen", onFullScreen, false);
+ addEventListener("DOMPopupBlocked", onPopupBlocked, false);
+
// does clicking on the urlbar select its contents?
gClickSelectsAll = pref.getBoolPref("browser.urlbar.clickSelectsAll");
@@ -631,6 +680,7 @@ function Shutdown()
removePrefListener(gTabStripPrefListener);
removePrefListener(gHomepagePrefListener);
removePopupPermListener(gPopupPermListener);
+ removePrefListener(gPopupPrefListener);
window.browserContentListener.close();
// Close the app core.
@@ -1960,6 +2010,64 @@ function onFullScreen()
FullScreen.toggle();
}
+
+function onPopupBlocked(aEvent) {
+ var playSound = pref.getBoolPref("privacy.popups.sound_enabled");
+
+ if (playSound) {
+ var sound = Components.classes["@mozilla.org/sound;1"]
+ .createInstance(Components.interfaces.nsISound);
+
+ var soundUrlSpec = pref.getCharPref("privacy.popups.sound_url");
+
+ //beep if no sound file specified
+ if (!soundUrlSpec)
+ sound.beep();
+
+ if (soundUrlSpec.substr(0, 7) == "file://") {
+ var soundUrl = Components.classes["@mozilla.org/network/standard-url;1"]
+ .createInstance(Components.interfaces.nsIFileURL);
+ soundUrl.spec = soundUrlSpec;
+ var file = soundUrl.file;
+ if (file.exists)
+ sound.play(soundUrl);
+ }
+ else {
+ sound.playSystemSound(soundUrlSpec);
+ }
+ }
+
+ var showIcon = pref.getBoolPref("privacy.popups.statusbar_icon_enabled");
+ if (showIcon) {
+ var doc = aEvent.target;
+ var browsers = getBrowser().browsers;
+ for (var i = 0; i < browsers.length; i++) {
+ if (browsers[i].contentDocument == doc) {
+ var hostPort = browsers[i].currentURI.hostPort;
+ browsers[i].popupDomain = hostPort;
+ if (browsers[i] == getBrowser().selectedBrowser) {
+ var popupIcon = document.getElementById("popupIcon");
+ popupIcon.hidden = false;
+ }
+ }
+ }
+ }
+}
+
+function ViewPopupManager() {
+ var policy = pref.getBoolPref("dom.disable_open_during_load");
+
+ var hostPort = "";
+ try {
+ hostPort = getBrowser().selectedBrowser.currentURI.hostPort;
+ }
+ catch(ex) { }
+
+ //open blacklist or whitelist with web site prefilled to unblock
+ window.openDialog("chrome://communicator/content/popupManager.xul", "",
+ "chrome,resizable=yes", policy, hostPort, false);
+}
+
// Set up a lame hack to avoid opening two bookmarks.
// Could otherwise happen with two Ctrl-B's in a row.
var gDisableHistory = false;
diff --git a/xpfe/browser/resources/content/navigator.xul b/xpfe/browser/resources/content/navigator.xul
index 14de8a68572..c803822e0cb 100644
--- a/xpfe/browser/resources/content/navigator.xul
+++ b/xpfe/browser/resources/content/navigator.xul
@@ -412,6 +412,7 @@ Contributor(s):
+
diff --git a/xpfe/browser/resources/content/nsBrowserStatusHandler.js b/xpfe/browser/resources/content/nsBrowserStatusHandler.js
index 2dfa26234b2..0bad5d1bc22 100644
--- a/xpfe/browser/resources/content/nsBrowserStatusHandler.js
+++ b/xpfe/browser/resources/content/nsBrowserStatusHandler.js
@@ -339,6 +339,21 @@ nsBrowserStatusHandler.prototype =
}
UpdateBackForwardButtons();
+ var blank = (location == "about:blank") || (location == "");
+ var browser = getBrowser().mCurrentBrowser;
+
+ //clear popupDomain accordingly so that icon will go away when visiting
+ //an unblocked site after a blocked site. note: if a popup is blocked
+ //the icon will stay as long as we are in the same domain.
+ if (blank ||
+ !("popupDomain" in browser) ||
+ aLocation.hostPort != browser.popupDomain) {
+ browser.popupDomain = null;
+ }
+
+ var popupIcon = document.getElementById("popupIcon");
+ popupIcon.hidden = !browser.popupDomain;
+
this.locationChanged = true;
},
diff --git a/xpfe/communicator/jar.mn b/xpfe/communicator/jar.mn
index 2844186bb75..116800f7c20 100644
--- a/xpfe/communicator/jar.mn
+++ b/xpfe/communicator/jar.mn
@@ -31,27 +31,31 @@ comm.jar:
content/communicator/printPreviewBindings.xml (resources/content/printPreviewBindings.xml)
content/communicator/printing.js (resources/content/printing.js)
content/communicator/plugins.html (resources/content/plugins.html)
+ content/communicator/popupManager.js (resources/content/popupManager.js)
+ content/communicator/popupManager.xul (resources/content/popupManager.xul)
en-US.jar:
- locale/en-US/communicator/contents.rdf (resources/locale/en-US/contents.rdf)
- locale/en-US/communicator/utilityOverlay.dtd (resources/locale/en-US/utilityOverlay.dtd)
- locale/en-US/communicator/utilityOverlay.properties (resources/locale/en-US/utilityOverlay.properties)
- locale/en-US/communicator/openLocation.dtd (resources/locale/en-US/openLocation.dtd)
- locale/en-US/communicator/openLocation.properties (resources/locale/en-US/openLocation.properties)
- locale/en-US/communicator/taskbar.rdf (resources/locale/en-US/taskbar.rdf)
- locale/en-US/communicator/tasksOverlay.dtd (resources/locale/en-US/tasksOverlay.dtd)
- locale/en-US/communicator/taskbarOverlay.dtd (resources/locale/en-US/taskbarOverlay.dtd)
- locale/en-US/communicator/contentAreaCommands.dtd (resources/locale/en-US/contentAreaCommands.dtd)
- locale/en-US/communicator/contentAreaCommands.properties (resources/locale/en-US/contentAreaCommands.properties)
- locale/en-US/communicator/askViewZoom.dtd (resources/locale/en-US/askViewZoom.dtd)
- locale/en-US/communicator/viewZoomOverlay.dtd (resources/locale/en-US/viewZoomOverlay.dtd)
- locale/en-US/communicator/viewZoomOverlay.properties (resources/locale/en-US/viewZoomOverlay.properties)
- locale/en-US/communicator/printPreview.dtd (resources/locale/en-US/printPreview.dtd)
- locale/en-US/communicator/printPageSetup.dtd (resources/locale/en-US/printPageSetup.dtd)
- locale/en-US/communicator/printPageSetup.properties (resources/locale/en-US/printPageSetup.properties)
+ locale/en-US/communicator/contents.rdf (resources/locale/en-US/contents.rdf)
+ locale/en-US/communicator/utilityOverlay.dtd (resources/locale/en-US/utilityOverlay.dtd)
+ locale/en-US/communicator/utilityOverlay.properties (resources/locale/en-US/utilityOverlay.properties)
+ locale/en-US/communicator/openLocation.dtd (resources/locale/en-US/openLocation.dtd)
+ locale/en-US/communicator/openLocation.properties (resources/locale/en-US/openLocation.properties)
+ locale/en-US/communicator/taskbar.rdf (resources/locale/en-US/taskbar.rdf)
+ locale/en-US/communicator/tasksOverlay.dtd (resources/locale/en-US/tasksOverlay.dtd)
+ locale/en-US/communicator/taskbarOverlay.dtd (resources/locale/en-US/taskbarOverlay.dtd)
+ locale/en-US/communicator/contentAreaCommands.dtd (resources/locale/en-US/contentAreaCommands.dtd)
+ locale/en-US/communicator/contentAreaCommands.properties (resources/locale/en-US/contentAreaCommands.properties)
+ locale/en-US/communicator/askViewZoom.dtd (resources/locale/en-US/askViewZoom.dtd)
+ locale/en-US/communicator/viewZoomOverlay.dtd (resources/locale/en-US/viewZoomOverlay.dtd)
+ locale/en-US/communicator/viewZoomOverlay.properties (resources/locale/en-US/viewZoomOverlay.properties)
+ locale/en-US/communicator/printPreview.dtd (resources/locale/en-US/printPreview.dtd)
+ locale/en-US/communicator/printPageSetup.dtd (resources/locale/en-US/printPageSetup.dtd)
+ locale/en-US/communicator/printPageSetup.properties (resources/locale/en-US/printPageSetup.properties)
+ locale/en-US/communicator/popupManager.dtd (resources/locale/en-US/popupManager.dtd)
+ locale/en-US/communicator/popupManager.properties (resources/locale/en-US/popupManager.properties)
US.jar:
- locale/US/communicator-region/contents.rdf (resources/locale/en-US/contents-region.rdf)
+ locale/US/communicator-region/contents.rdf (resources/locale/en-US/contents-region.rdf)
locale/US/communicator-region/region.dtd (resources/locale/en-US/region.dtd)
locale/US/communicator-region/region.properties (resources/locale/en-US/region.properties)
locale/US/communicator-region/taskbar.rdf (resources/locale/en-US/taskbar.rdf)
diff --git a/xpfe/communicator/resources/content/popupManager.js b/xpfe/communicator/resources/content/popupManager.js
new file mode 100644
index 00000000000..28d31bd3175
--- /dev/null
+++ b/xpfe/communicator/resources/content/popupManager.js
@@ -0,0 +1,428 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the NPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var popupManager = null;
+
+var permissions = [];
+
+var listCapability; // the capability of sites on the currently viewed list
+// TRUE: current popup policy is BLOCK ALL WITH EXCEPTIONS - sites on
+// the whitelist are allowed and have permission.capability = true
+// FALSE: current popup policy is ALLOW ALL WITH EXCEPTIONS - sites on
+// the blacklist are blocked and have permission.capability = false
+
+const POPUP_TYPE = 2;
+
+var additions = [];
+var removals = [];
+
+const SIMPLEURI_CONTRACTID = "@mozilla.org/network/simple-uri;1";
+
+var sortColumn = "host";
+var lastSort = false;
+
+var permissionsTreeView = {
+ rowCount: 0,
+ setTree: function(tree) {},
+ getImageSrc: function(row, column) {},
+ getProgressMode: function(row, column) {},
+ getCellValue: function(row, column) {},
+ getCellText: function(row, column) {
+ var rv = permissions[row].host;
+ return rv;
+ },
+ isSeparator: function(index) { return false; },
+ isSorted: function() { return false; },
+ isContainer: function(index) { return false; },
+ cycleHeader: function(aColId, aElt) {},
+ getRowProperties: function(row, column,prop) {},
+ getColumnProperties: function(column, columnElement, prop) {},
+ getCellProperties: function(row, prop) {}
+};
+
+var permissionsTree;
+var popupStringBundle;
+
+function Startup() {
+ popupManager = Components.classes["@mozilla.org/PopupWindowManager;1"]
+ .getService(Components.interfaces.nsIPopupWindowManager);
+
+ permissionsTree = document.getElementById("permissionsTree");
+
+ popupStringBundle = document.getElementById("popupStringBundle");
+ var title;
+
+ if (window.arguments[0]) {
+ document.getElementById("blockExcept").hidden = false;
+ lastSort = (permissionsTree.getAttribute("lastSortWhitelist") == "true");
+ title = popupStringBundle.getString("whitelistTitle");
+ }
+ else {
+ document.getElementById("allowExcept").hidden = false;
+ lastSort = (permissionsTree.getAttribute("lastSortBlacklist") == "true");
+ title = popupStringBundle.getString("blacklistTitle");
+ }
+
+ document.getElementById("popupManager").setAttribute("title", title);
+
+ listCapability = window.arguments[0];
+
+ loadPermissions(permissions);
+ loadTree();
+
+ if (window.arguments[1]) { // dialog opened from statusbar icon
+ if (listCapability) {
+ document.getElementById("addSiteBox").value = window.arguments[1];
+ }
+ else {
+ // pre-pend '.' so we always match on host boundaries. Otherwise
+ // we might think notfoo.com matches foo.com
+ var currentLoc = '.'+window.arguments[1];
+ var nextHost;
+ var inList;
+
+ var matchIndex;
+ var matchLength = 0;
+
+ for (var i = 0; i < permissionsTreeView.rowCount; i++) {
+ nextHost = '.'+permissions[i].host;
+
+ if (currentLoc.length < nextHost.length)
+ continue; // can't be a match, list host is more specific
+
+ // look for an early out exact match -- check length first for speed
+ if (currentLoc.length == nextHost.length && nextHost == currentLoc) {
+ inList = true;
+ matchIndex = i;
+ break;
+ }
+
+ if (nextHost == currentLoc.substr(currentLoc.length - nextHost.length)) {
+ inList = true;
+ if (listCapability) // host is already on whitelist, don't prefill
+ break;
+
+ if (nextHost.length > matchLength) {
+ matchIndex = i;
+ matchLength = nextHost.length;
+ }
+ }
+ }
+
+ if (inList) // host is in blacklist, select for removal
+ permissionsTree.treeBoxObject.view.selection.select(matchIndex);
+ }
+ }
+
+ document.documentElement.addEventListener("keypress", onReturnHit, true);
+
+ window.sizeToContent();
+}
+
+function onAccept() {
+ finalizeChanges();
+
+ var unblocked;
+
+ if (listCapability) {
+ unblocked = additions;
+ permissionsTree.setAttribute("lastSortWhitelist", !lastSort);
+ }
+ else {
+ unblocked = removals;
+ permissionsTree.setAttribute("lastSortBlacklist", !lastSort);
+ }
+
+ var nextLocation;
+ var nextUnblocked;
+
+ var windowMediator = Components.classes['@mozilla.org/appshell/window-mediator;1']
+ .getService(Components.interfaces.nsIWindowMediator);
+ var enumerator = windowMediator.getEnumerator("navigator:browser");
+
+ //if a site that is currently open is unblocked, make icon go away
+ while(enumerator.hasMoreElements()) {
+ var win = enumerator.getNext();
+
+ var browsers = win.getBrowser().browsers;
+ for (var i = 0; i < browsers.length; i++) {
+ try {
+ nextLocation = browsers[i].currentURI.hostPort;
+ }
+ catch(ex) {
+ //blank window
+ }
+
+ if (nextLocation) {
+ nextLocation = '.'+nextLocation;
+ for (var j in unblocked) {
+ nextUnblocked = '.'+unblocked[j];
+
+ if (nextUnblocked.length > nextLocation.length)
+ continue; // can't be a match
+
+ if (nextUnblocked ==
+ nextLocation.substr(nextLocation.length - nextUnblocked.length)) {
+ browsers[i].popupDomain = null;
+ win.document.getElementById("popupIcon").hidden = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (window.arguments[2])
+ window.opener.setButtons();
+
+
+ return true;
+}
+
+function Permission(host, number) {
+ this.host = host;
+ this.number = number;
+}
+
+function loadPermissions(table) {
+ var enumerator = popupManager.getEnumerator();
+ var count = 0;
+
+ while (enumerator.hasMoreElements()) {
+ var permission = enumerator.getNext()
+ .QueryInterface(Components.interfaces.nsIPermission);
+ if (permission.capability == listCapability) {
+ var host = permission.host;
+ table[count] = new Permission(host,count++);
+ }
+ }
+}
+
+function loadTree() {
+ var rowCount = permissions.length;
+ permissionsTreeView.rowCount = rowCount;
+ permissionsTree.treeBoxObject.view = permissionsTreeView;
+ permissionColumnSort();
+
+ if (permissions.length == 0)
+ document.getElementById("removeAllPermissions").setAttribute("disabled","true");
+ else
+ document.getElementById("removeAllPermissions").removeAttribute("disabled");
+}
+
+function permissionColumnSort() {
+ lastSort =
+ SortTree(permissionsTree, permissionsTreeView, permissions,
+ sortColumn, sortColumn, lastSort);
+}
+
+function permissionSelected() {
+ var selections = GetTreeSelections(permissionsTree);
+ if (selections.length) {
+ document.getElementById("removePermission").removeAttribute("disabled");
+ }
+}
+
+function deletePermissions() {
+ var selections = GetTreeSelections(permissionsTree);
+
+ for (var s = selections.length - 1; s >= 0; s--) {
+ var i = selections[s];
+
+ var host = permissions[i].host;
+ updatePendingRemovals(host);
+
+ permissions[i] = null;
+ }
+
+ for (var j = 0; j < permissions.length; j++) {
+ if (permissions[j] == null) {
+ var k = j;
+ while ((k < permissions.length) && (permissions[k] == null)) {
+ k++;
+ }
+ permissions.splice(j, k-j);
+ }
+ }
+
+ var box = permissionsTree.treeBoxObject;
+ var firstRow = box.getFirstVisibleRow();
+ if (firstRow > (permissions.length - 1) ) {
+ firstRow = permissions.length - 1;
+ }
+ permissionsTreeView.rowCount = permissions.length;
+ box.rowCountChanged(0, permissions.length);
+ box.scrollToRow(firstRow);
+
+ if (permissions.length) {
+ var nextSelection = (selections[0] < permissions.length) ? selections[0] : permissions.length - 1;
+ box.view.selection.select(-1);
+ box.view.selection.select(nextSelection);
+ }
+ else {
+ document.getElementById("removePermission").setAttribute("disabled", "true")
+ document.getElementById("removeAllPermissions").setAttribute("disabled","true");
+
+ permissionsTree.treeBoxObject.view.selection.select(-1);
+ }
+}
+
+function deleteAllPermissions() {
+ for (var i = 0; i < permissions.length; i++) {
+ var host = permissions[i].host;
+ updatePendingRemovals(host);
+ }
+
+ permissions.length = 0;
+ clearTree();
+}
+
+function updatePendingRemovals(host) {
+ if (additions[host] != null)
+ additions[host] = null;
+ else
+ removals[host] = host;
+}
+
+function clearTree() {
+ permissionsTree.treeBoxObject.view.selection.select(-1);
+
+ permissionsTreeView.rowCount = 0;
+ permissionsTree.treeBoxObject.invalidate();
+
+ document.getElementById("removePermission").setAttribute("disabled", "true")
+ document.getElementById("removeAllPermissions").setAttribute("disabled","true");
+}
+
+function finalizeChanges() {
+ var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+
+ //note: the scheme will be taken off later, it is being added now only to
+ //create the uri for add/remove
+ for (var i in additions) {
+ var host = additions[i];
+ if (host != null) {
+ host = "http://" + host;
+ var uri = ioService.newURI(host, null, null);
+ popupManager.add(uri, listCapability);
+ }
+ }
+
+ for (var i in removals) {
+ var host = removals[i];
+ if (host != null) {
+ host = "http://" + host;
+ var uri = ioService.newURI(host, null, null);
+ popupManager.remove(uri);
+ }
+ }
+
+}
+
+function handlePermissionKeyPress(e) {
+ if (e.keyCode == 46) {
+ deletePermissions();
+ }
+}
+
+function addPermission() {
+ var addSiteBox = document.getElementById("addSiteBox");
+ var host = addSiteBox.value;
+
+ if (host != "") {
+ host = host.replace(/^\s*([-\w]*:\/*)?/, ""); // trim any leading space and scheme
+
+ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+ .getService(Components.interfaces.nsIPromptService);
+ var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+
+ try {
+ var uri = ioService.newURI("http://"+host, null, null);
+ }
+ catch(ex) {
+ var msgInvalid = popupStringBundle.getFormattedString("alertInvalid", [host]);
+ if (promptService)
+ promptService.alert(window, "", msgInvalid);
+ addSiteBox.value = "";
+ return;
+ }
+
+ if (!host) {
+ addSiteBox.value = "";
+ return;
+ }
+
+ var length = permissions.length;
+
+ var isDuplicate = false;
+ for (var i = 0; i < length; i++) {
+ if (permissions[i].host == host) {
+ var msgDuplicate = popupStringBundle.getFormattedString("alertDuplicate", [host]);
+ if (promptService)
+ promptService.alert(window, "", msgDuplicate);
+ isDuplicate = true;
+ break;
+ }
+ }
+
+ if (!isDuplicate) {
+ var newPermission = new Permission(host, length);
+ permissions.push(newPermission);
+
+ lastSort = !lastSort; //keep same sort direction
+ loadTree();
+
+ if (removals[host] != null)
+ removals[host] = null;
+ else
+ additions[host] = host;
+ }
+
+ addSiteBox.value = "";
+ }
+}
+
+function onReturnHit(event) {
+ var focusedElement = document.commandDispatcher.focusedElement;
+ var addSiteBox = document.getElementById("addSiteBox");
+ if (event.keyCode == 13) {
+ if (focusedElement) {
+ if (focusedElement.id == "permissionsTree")
+ return;
+ else {
+ event.preventBubble();
+ if (focusedElement == addSiteBox.inputField) {
+ var addSiteButton = document.getElementById("addSiteButton");
+ addSiteButton.doCommand();
+ }
+ }
+ }
+ }
+}
+
+function doHelpButton() {
+ openHelp("pop_up_blocking_prefs");
+ return true;
+}
+
diff --git a/xpfe/communicator/resources/content/popupManager.xul b/xpfe/communicator/resources/content/popupManager.xul
new file mode 100644
index 00000000000..7340e49b930
--- /dev/null
+++ b/xpfe/communicator/resources/content/popupManager.xul
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
diff --git a/xpfe/communicator/resources/locale/en-US/popupManager.dtd b/xpfe/communicator/resources/locale/en-US/popupManager.dtd
new file mode 100644
index 00000000000..e3af863251d
--- /dev/null
+++ b/xpfe/communicator/resources/locale/en-US/popupManager.dtd
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xpfe/communicator/resources/locale/en-US/popupManager.properties b/xpfe/communicator/resources/locale/en-US/popupManager.properties
new file mode 100644
index 00000000000..5d50057cbc9
--- /dev/null
+++ b/xpfe/communicator/resources/locale/en-US/popupManager.properties
@@ -0,0 +1,4 @@
+blacklistTitle=Popup Exceptions - Suppressed Web Sites
+whitelistTitle=Popup Exceptions - Allowed Web Sites
+alertDuplicate=The web site %S already exists in this list.
+alertInvalid=The web site %S is invalid.
diff --git a/xpfe/components/permissions/content/permissionsManager.js b/xpfe/components/permissions/content/permissionsManager.js
new file mode 100644
index 00000000000..28d31bd3175
--- /dev/null
+++ b/xpfe/components/permissions/content/permissionsManager.js
@@ -0,0 +1,428 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the NPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var popupManager = null;
+
+var permissions = [];
+
+var listCapability; // the capability of sites on the currently viewed list
+// TRUE: current popup policy is BLOCK ALL WITH EXCEPTIONS - sites on
+// the whitelist are allowed and have permission.capability = true
+// FALSE: current popup policy is ALLOW ALL WITH EXCEPTIONS - sites on
+// the blacklist are blocked and have permission.capability = false
+
+const POPUP_TYPE = 2;
+
+var additions = [];
+var removals = [];
+
+const SIMPLEURI_CONTRACTID = "@mozilla.org/network/simple-uri;1";
+
+var sortColumn = "host";
+var lastSort = false;
+
+var permissionsTreeView = {
+ rowCount: 0,
+ setTree: function(tree) {},
+ getImageSrc: function(row, column) {},
+ getProgressMode: function(row, column) {},
+ getCellValue: function(row, column) {},
+ getCellText: function(row, column) {
+ var rv = permissions[row].host;
+ return rv;
+ },
+ isSeparator: function(index) { return false; },
+ isSorted: function() { return false; },
+ isContainer: function(index) { return false; },
+ cycleHeader: function(aColId, aElt) {},
+ getRowProperties: function(row, column,prop) {},
+ getColumnProperties: function(column, columnElement, prop) {},
+ getCellProperties: function(row, prop) {}
+};
+
+var permissionsTree;
+var popupStringBundle;
+
+function Startup() {
+ popupManager = Components.classes["@mozilla.org/PopupWindowManager;1"]
+ .getService(Components.interfaces.nsIPopupWindowManager);
+
+ permissionsTree = document.getElementById("permissionsTree");
+
+ popupStringBundle = document.getElementById("popupStringBundle");
+ var title;
+
+ if (window.arguments[0]) {
+ document.getElementById("blockExcept").hidden = false;
+ lastSort = (permissionsTree.getAttribute("lastSortWhitelist") == "true");
+ title = popupStringBundle.getString("whitelistTitle");
+ }
+ else {
+ document.getElementById("allowExcept").hidden = false;
+ lastSort = (permissionsTree.getAttribute("lastSortBlacklist") == "true");
+ title = popupStringBundle.getString("blacklistTitle");
+ }
+
+ document.getElementById("popupManager").setAttribute("title", title);
+
+ listCapability = window.arguments[0];
+
+ loadPermissions(permissions);
+ loadTree();
+
+ if (window.arguments[1]) { // dialog opened from statusbar icon
+ if (listCapability) {
+ document.getElementById("addSiteBox").value = window.arguments[1];
+ }
+ else {
+ // pre-pend '.' so we always match on host boundaries. Otherwise
+ // we might think notfoo.com matches foo.com
+ var currentLoc = '.'+window.arguments[1];
+ var nextHost;
+ var inList;
+
+ var matchIndex;
+ var matchLength = 0;
+
+ for (var i = 0; i < permissionsTreeView.rowCount; i++) {
+ nextHost = '.'+permissions[i].host;
+
+ if (currentLoc.length < nextHost.length)
+ continue; // can't be a match, list host is more specific
+
+ // look for an early out exact match -- check length first for speed
+ if (currentLoc.length == nextHost.length && nextHost == currentLoc) {
+ inList = true;
+ matchIndex = i;
+ break;
+ }
+
+ if (nextHost == currentLoc.substr(currentLoc.length - nextHost.length)) {
+ inList = true;
+ if (listCapability) // host is already on whitelist, don't prefill
+ break;
+
+ if (nextHost.length > matchLength) {
+ matchIndex = i;
+ matchLength = nextHost.length;
+ }
+ }
+ }
+
+ if (inList) // host is in blacklist, select for removal
+ permissionsTree.treeBoxObject.view.selection.select(matchIndex);
+ }
+ }
+
+ document.documentElement.addEventListener("keypress", onReturnHit, true);
+
+ window.sizeToContent();
+}
+
+function onAccept() {
+ finalizeChanges();
+
+ var unblocked;
+
+ if (listCapability) {
+ unblocked = additions;
+ permissionsTree.setAttribute("lastSortWhitelist", !lastSort);
+ }
+ else {
+ unblocked = removals;
+ permissionsTree.setAttribute("lastSortBlacklist", !lastSort);
+ }
+
+ var nextLocation;
+ var nextUnblocked;
+
+ var windowMediator = Components.classes['@mozilla.org/appshell/window-mediator;1']
+ .getService(Components.interfaces.nsIWindowMediator);
+ var enumerator = windowMediator.getEnumerator("navigator:browser");
+
+ //if a site that is currently open is unblocked, make icon go away
+ while(enumerator.hasMoreElements()) {
+ var win = enumerator.getNext();
+
+ var browsers = win.getBrowser().browsers;
+ for (var i = 0; i < browsers.length; i++) {
+ try {
+ nextLocation = browsers[i].currentURI.hostPort;
+ }
+ catch(ex) {
+ //blank window
+ }
+
+ if (nextLocation) {
+ nextLocation = '.'+nextLocation;
+ for (var j in unblocked) {
+ nextUnblocked = '.'+unblocked[j];
+
+ if (nextUnblocked.length > nextLocation.length)
+ continue; // can't be a match
+
+ if (nextUnblocked ==
+ nextLocation.substr(nextLocation.length - nextUnblocked.length)) {
+ browsers[i].popupDomain = null;
+ win.document.getElementById("popupIcon").hidden = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (window.arguments[2])
+ window.opener.setButtons();
+
+
+ return true;
+}
+
+function Permission(host, number) {
+ this.host = host;
+ this.number = number;
+}
+
+function loadPermissions(table) {
+ var enumerator = popupManager.getEnumerator();
+ var count = 0;
+
+ while (enumerator.hasMoreElements()) {
+ var permission = enumerator.getNext()
+ .QueryInterface(Components.interfaces.nsIPermission);
+ if (permission.capability == listCapability) {
+ var host = permission.host;
+ table[count] = new Permission(host,count++);
+ }
+ }
+}
+
+function loadTree() {
+ var rowCount = permissions.length;
+ permissionsTreeView.rowCount = rowCount;
+ permissionsTree.treeBoxObject.view = permissionsTreeView;
+ permissionColumnSort();
+
+ if (permissions.length == 0)
+ document.getElementById("removeAllPermissions").setAttribute("disabled","true");
+ else
+ document.getElementById("removeAllPermissions").removeAttribute("disabled");
+}
+
+function permissionColumnSort() {
+ lastSort =
+ SortTree(permissionsTree, permissionsTreeView, permissions,
+ sortColumn, sortColumn, lastSort);
+}
+
+function permissionSelected() {
+ var selections = GetTreeSelections(permissionsTree);
+ if (selections.length) {
+ document.getElementById("removePermission").removeAttribute("disabled");
+ }
+}
+
+function deletePermissions() {
+ var selections = GetTreeSelections(permissionsTree);
+
+ for (var s = selections.length - 1; s >= 0; s--) {
+ var i = selections[s];
+
+ var host = permissions[i].host;
+ updatePendingRemovals(host);
+
+ permissions[i] = null;
+ }
+
+ for (var j = 0; j < permissions.length; j++) {
+ if (permissions[j] == null) {
+ var k = j;
+ while ((k < permissions.length) && (permissions[k] == null)) {
+ k++;
+ }
+ permissions.splice(j, k-j);
+ }
+ }
+
+ var box = permissionsTree.treeBoxObject;
+ var firstRow = box.getFirstVisibleRow();
+ if (firstRow > (permissions.length - 1) ) {
+ firstRow = permissions.length - 1;
+ }
+ permissionsTreeView.rowCount = permissions.length;
+ box.rowCountChanged(0, permissions.length);
+ box.scrollToRow(firstRow);
+
+ if (permissions.length) {
+ var nextSelection = (selections[0] < permissions.length) ? selections[0] : permissions.length - 1;
+ box.view.selection.select(-1);
+ box.view.selection.select(nextSelection);
+ }
+ else {
+ document.getElementById("removePermission").setAttribute("disabled", "true")
+ document.getElementById("removeAllPermissions").setAttribute("disabled","true");
+
+ permissionsTree.treeBoxObject.view.selection.select(-1);
+ }
+}
+
+function deleteAllPermissions() {
+ for (var i = 0; i < permissions.length; i++) {
+ var host = permissions[i].host;
+ updatePendingRemovals(host);
+ }
+
+ permissions.length = 0;
+ clearTree();
+}
+
+function updatePendingRemovals(host) {
+ if (additions[host] != null)
+ additions[host] = null;
+ else
+ removals[host] = host;
+}
+
+function clearTree() {
+ permissionsTree.treeBoxObject.view.selection.select(-1);
+
+ permissionsTreeView.rowCount = 0;
+ permissionsTree.treeBoxObject.invalidate();
+
+ document.getElementById("removePermission").setAttribute("disabled", "true")
+ document.getElementById("removeAllPermissions").setAttribute("disabled","true");
+}
+
+function finalizeChanges() {
+ var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+
+ //note: the scheme will be taken off later, it is being added now only to
+ //create the uri for add/remove
+ for (var i in additions) {
+ var host = additions[i];
+ if (host != null) {
+ host = "http://" + host;
+ var uri = ioService.newURI(host, null, null);
+ popupManager.add(uri, listCapability);
+ }
+ }
+
+ for (var i in removals) {
+ var host = removals[i];
+ if (host != null) {
+ host = "http://" + host;
+ var uri = ioService.newURI(host, null, null);
+ popupManager.remove(uri);
+ }
+ }
+
+}
+
+function handlePermissionKeyPress(e) {
+ if (e.keyCode == 46) {
+ deletePermissions();
+ }
+}
+
+function addPermission() {
+ var addSiteBox = document.getElementById("addSiteBox");
+ var host = addSiteBox.value;
+
+ if (host != "") {
+ host = host.replace(/^\s*([-\w]*:\/*)?/, ""); // trim any leading space and scheme
+
+ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+ .getService(Components.interfaces.nsIPromptService);
+ var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+
+ try {
+ var uri = ioService.newURI("http://"+host, null, null);
+ }
+ catch(ex) {
+ var msgInvalid = popupStringBundle.getFormattedString("alertInvalid", [host]);
+ if (promptService)
+ promptService.alert(window, "", msgInvalid);
+ addSiteBox.value = "";
+ return;
+ }
+
+ if (!host) {
+ addSiteBox.value = "";
+ return;
+ }
+
+ var length = permissions.length;
+
+ var isDuplicate = false;
+ for (var i = 0; i < length; i++) {
+ if (permissions[i].host == host) {
+ var msgDuplicate = popupStringBundle.getFormattedString("alertDuplicate", [host]);
+ if (promptService)
+ promptService.alert(window, "", msgDuplicate);
+ isDuplicate = true;
+ break;
+ }
+ }
+
+ if (!isDuplicate) {
+ var newPermission = new Permission(host, length);
+ permissions.push(newPermission);
+
+ lastSort = !lastSort; //keep same sort direction
+ loadTree();
+
+ if (removals[host] != null)
+ removals[host] = null;
+ else
+ additions[host] = host;
+ }
+
+ addSiteBox.value = "";
+ }
+}
+
+function onReturnHit(event) {
+ var focusedElement = document.commandDispatcher.focusedElement;
+ var addSiteBox = document.getElementById("addSiteBox");
+ if (event.keyCode == 13) {
+ if (focusedElement) {
+ if (focusedElement.id == "permissionsTree")
+ return;
+ else {
+ event.preventBubble();
+ if (focusedElement == addSiteBox.inputField) {
+ var addSiteButton = document.getElementById("addSiteButton");
+ addSiteButton.doCommand();
+ }
+ }
+ }
+ }
+}
+
+function doHelpButton() {
+ openHelp("pop_up_blocking_prefs");
+ return true;
+}
+
diff --git a/xpfe/components/permissions/content/permissionsManager.xul b/xpfe/components/permissions/content/permissionsManager.xul
new file mode 100644
index 00000000000..7340e49b930
--- /dev/null
+++ b/xpfe/components/permissions/content/permissionsManager.xul
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
diff --git a/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul b/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul
index 489fcac7e86..a5dda685466 100644
--- a/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul
+++ b/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul
@@ -70,7 +70,7 @@
// determine current state (blocked or unblocked) and hide appropriate menu item
var blocked;
-
+
blocked =
permissionmanager.testForBlocking(window._content.location, COOKIEPERMISSION);
enableElement("AllowCookies", blocked);
@@ -80,7 +80,7 @@
permissionmanager.testForBlocking(window._content.location, IMAGEPERMISSION);
enableElement("AllowImages", blocked);
enableElement("BlockImages", !blocked);
-
+
SetPopupMenuEnabledState();
var pref;
@@ -104,19 +104,31 @@
}
function SetPopupMenuEnabledState() {
- // use care choosing which nsIPopupWindowManager constant to compare
- // against. the allow/disallow/sometimes relationship can be subtle.
- var useManager = !pref.getBoolPref("dom.disable_open_during_load");
var suitable = false;
- var enableBlock = false;
- if (useManager) {
- suitable = popupmanager.testSuitability(getBrowser().currentURI);
- if (suitable)
- enableBlock = popupmanager.testPermission(getBrowser().currentURI) != Components.interfaces.nsIPopupWindowManager.DENY_POPUP;
+ var blocked = false;
+ var policy = pref.getBoolPref("dom.disable_open_during_load");
+
+ suitable = popupmanager.testSuitability(getBrowser().currentURI);
+ if (suitable) {
+ if (!policy) // blacklist, test if there is a permission set
+ blocked = (popupmanager.testPermission(getBrowser().currentURI) == Components.interfaces.nsIPopupWindowManager.DENY_POPUP);
+ else { // whitelist, check if it is on list
+ blocked = true;
+ var enumerator = popupmanager.getEnumerator();
+ while (enumerator.hasMoreElements()) {
+ var permission = enumerator.getNext()
+ .QueryInterface(Components.interfaces.nsIPermission);
+ if (permission.capability && getBrowser().currentURI.host == permission.host) {
+ blocked = false;
+ break;
+ }
+ }
+ }
}
- enableElement("BlockPopups", useManager && suitable && enableBlock);
- enableElement("AllowPopups", useManager && suitable && !enableBlock);
- enableElement("ManagePopups", useManager);
+
+ enableElement("BlockPopups", suitable && !blocked);
+ enableElement("AllowPopups", suitable && blocked);
+ enableElement("ManagePopups", true);
}
function enableElement(elementID, enable) {
@@ -156,19 +168,45 @@
element = document.getElementById("BlockImages");
alert(element.getAttribute("msg"));
break;
- case "popupAllow":
- popupmanager.add(getBrowser().currentURI, true);
- element = document.getElementById("AllowPopups");
- alert(element.getAttribute("msg"));
- break;
- case "popupBlock":
- popupmanager.add(getBrowser().currentURI, false);
- element = document.getElementById("BlockPopups");
- alert(element.getAttribute("msg"));
- break;
default:
}
- }
+ }
+
+ function PopupAction(action) {
+ var policy = pref.getBoolPref("dom.disable_open_during_load");
+ var uri = getBrowser().currentURI;
+
+ switch (action) {
+ case "block":
+ if (!policy)
+ popupmanager.add(uri, policy);
+ else
+ popupmanager.remove(uri);
+ break;
+ case "allow":
+ var browsers = getBrowser().browsers;
+ var popupIcon = document.getElementById("popupIcon");
+ if (!policy)
+ popupmanager.remove(uri);
+ else
+ popupmanager.add(uri, policy);
+ for (var i = 0; i < browsers.length; i++) {
+ if (browsers[i].popupDomain == uri.host) {
+ browsers[i].popupDomain = null;
+ popupIcon.hidden = true;
+ }
+ }
+ break;
+ }
+ }
+
+ function ViewPopupManager() {
+ window.openDialog("chrome://communicator/content/popupManager.xul", "",
+ "chrome,resizable=yes,modal=yes",
+ pref.getBoolPref("dom.disable_open_during_load"),
+ "",
+ false);
+ }
]]>
@@ -220,15 +258,15 @@
+ oncommand="PopupAction('block');"/>
+ oncommand="PopupAction('allow');"/>
+ oncommand="ViewPopupManager();"/>
diff --git a/xpfe/components/permissions/locale/en-US/permissionsManager.dtd b/xpfe/components/permissions/locale/en-US/permissionsManager.dtd
new file mode 100644
index 00000000000..e3af863251d
--- /dev/null
+++ b/xpfe/components/permissions/locale/en-US/permissionsManager.dtd
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xpfe/components/permissions/locale/en-US/permissionsManager.properties b/xpfe/components/permissions/locale/en-US/permissionsManager.properties
new file mode 100644
index 00000000000..5d50057cbc9
--- /dev/null
+++ b/xpfe/components/permissions/locale/en-US/permissionsManager.properties
@@ -0,0 +1,4 @@
+blacklistTitle=Popup Exceptions - Suppressed Web Sites
+whitelistTitle=Popup Exceptions - Allowed Web Sites
+alertDuplicate=The web site %S already exists in this list.
+alertInvalid=The web site %S is invalid.
diff --git a/xpfe/components/prefwindow/resources/content/cookiePrefsOverlay.xul b/xpfe/components/prefwindow/resources/content/cookiePrefsOverlay.xul
index 0d4ec86138a..f7227a9413d 100644
--- a/xpfe/components/prefwindow/resources/content/cookiePrefsOverlay.xul
+++ b/xpfe/components/prefwindow/resources/content/cookiePrefsOverlay.xul
@@ -40,14 +40,12 @@
label="&images.label;"/>
-
diff --git a/xpfe/components/prefwindow/resources/content/permissionsPrefsOverlay.xul b/xpfe/components/prefwindow/resources/content/permissionsPrefsOverlay.xul
index 0d4ec86138a..f7227a9413d 100644
--- a/xpfe/components/prefwindow/resources/content/permissionsPrefsOverlay.xul
+++ b/xpfe/components/prefwindow/resources/content/permissionsPrefsOverlay.xul
@@ -40,14 +40,12 @@
label="&images.label;"/>
-
diff --git a/xpfe/components/prefwindow/resources/content/pref-popups.xul b/xpfe/components/prefwindow/resources/content/pref-popups.xul
index 117b4bbeaed..0062f121886 100644
--- a/xpfe/components/prefwindow/resources/content/pref-popups.xul
+++ b/xpfe/components/prefwindow/resources/content/pref-popups.xul
@@ -48,69 +48,143 @@
onload="init()"
headertitle="&title;">
-
+
-
+ var _elementIDs = ["popupPolicy","playSound","playSoundUrl","displayIcon"];
-
+ function blacklistEmpty() {
+ var permissionmanager = Components.classes["@mozilla.org/permissionmanager;1"]
+ .getService(Components.interfaces.nsIPermissionManager);
+
+ var popupManager = Components.classes["@mozilla.org/PopupWindowManager;1"]
+ .getService(Components.interfaces.nsIPopupWindowManager);
+ var enumerator = popupManager.getEnumerator();
+
+ while (enumerator.hasMoreElements()) {
+ var permission = enumerator.getNext()
+ .QueryInterface(Components.interfaces.nsIPermission);
+ if (!permission.capability)
+ return false;
+ }
+ return true;
+ }
+
+ function setButtons() {
+ var exceptionsAllow = document.getElementById("exceptionsAllow");
+ var exceptionsBlock = document.getElementById("exceptionsBlock");
+
+ exceptionsAllow.disabled = (gPolicyButton.value == "true");
+ exceptionsBlock.disabled = (!exceptionsAllow.disabled);
+
+ if (blacklistEmpty() && (gPolicyButton.value == "false")) {
+ gSoundCheckbox.disabled = true;
+ gSoundUrlBox.disabled = true;
+ gSoundUrlButton.disabled = true;
+ gIconCheckbox.disabled = true;
+ }
+ else {
+ gSoundCheckbox.disabled = false;
+ gSoundUrlBox.disabled = false;
+ gSoundUrlButton.disabled = false;
+ gIconCheckbox.disabled = false;
+
+ enableSoundUrl(gSoundCheckbox.checked);
+ }
+ }
+
+ function selectSound() {
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var filepicker = Components.classes["@mozilla.org/filepicker;1"]
+ .createInstance(nsIFilePicker);
+
+ filepicker.init(window, document.getElementById("selectSound").getAttribute("filepickertitle"), nsIFilePicker.modeOpen);
+ filepicker.appendFilters(nsIFilePicker.filterAll);
+
+ var ret = filepicker.show();
+ if (ret == nsIFilePicker.returnOK)
+ gSoundUrlBox.value = filepicker.file.path;
+ }
+
+ function enableSoundUrl(soundChecked) {
+ gSoundUrlBox.disabled = !soundChecked;
+ gSoundUrlButton.disabled = !soundChecked;
+ }
+
+ function viewPopups() {
+ window.openDialog("chrome://communicator/content/popupManager.xul", "",
+ "chrome,resizable=yes,modal=yes",
+ (gPolicyButton.value == "true"),
+ "",
+ true);
+ }
+
+ ]]>
+
+
+
diff --git a/xpfe/components/prefwindow/resources/content/pref-scripts.js b/xpfe/components/prefwindow/resources/content/pref-scripts.js
index 85a94bf3205..805298c811e 100644
--- a/xpfe/components/prefwindow/resources/content/pref-scripts.js
+++ b/xpfe/components/prefwindow/resources/content/pref-scripts.js
@@ -44,7 +44,6 @@ function changeDisabledState(state){
//Set the states of the groupbox children state based on the "javascript enabled" checkbox value
document.getElementById("allowScripts").disabled = state;
document.getElementById("allowWindowMoveResize").disabled = state;
- document.getElementById("allowWindowOpen").disabled = state;
document.getElementById("allowImageSrcChange").disabled = state;
document.getElementById("allowDocumentCookieSet").disabled = state;
document.getElementById("allowDocumentCookieGet").disabled = state;
@@ -87,8 +86,7 @@ function Startup(){
//If scriptData does not exist, then it is the first time the panel was shown and we default to false
if (!("scriptData" in data)){
- var changedList = ["allowWindowOpenChanged",
- "allowWindowMoveResizeChanged",
+ var changedList = ["allowWindowMoveResizeChanged",
"allowWindowStatusChangeChanged",
"allowWindowFlipChanged",
"allowDocumentCookieSetChanged",
@@ -102,7 +100,6 @@ function Startup(){
data.scriptData[ changedList[run] ].value = false;
}
- document.getElementById("allowWindowOpen").checked = getPrefValueForCheckbox("dom.disable_open_during_load");
document.getElementById("allowWindowMoveResize").checked = getPrefValueForCheckbox("dom.disable_window_move_resize");
document.getElementById("allowWindowFlip").checked = getPrefValueForCheckbox("dom.disable_window_flip");
document.getElementById("allowWindowStatusChange").checked = getPrefValueForCheckbox("dom.disable_window_status_change");
@@ -142,11 +139,6 @@ function doOnOk(){
}
var data = parent.hPrefWindow.wsm.dataManager.pageData["chrome://communicator/content/pref/pref-scripts.xul"];
-
- if (data.scriptData["allowWindowOpenChanged"].value){
- parent.hPrefWindow.setPref("bool", "dom.disable_open_during_load",
- !getCheckboxValue('allowWindowOpen'));
- }
if (data.scriptData["allowWindowMoveResizeChanged"].value){
parent.hPrefWindow.setPref("bool", "dom.disable_window_move_resize",
diff --git a/xpfe/components/prefwindow/resources/content/pref-scripts.xul b/xpfe/components/prefwindow/resources/content/pref-scripts.xul
index 636372c1781..09225d1a05f 100644
--- a/xpfe/components/prefwindow/resources/content/pref-scripts.xul
+++ b/xpfe/components/prefwindow/resources/content/pref-scripts.xul
@@ -48,7 +48,6 @@
-
diff --git a/xpfe/components/prefwindow/resources/locale/en-US/cookiePrefsOverlay.dtd b/xpfe/components/prefwindow/resources/locale/en-US/cookiePrefsOverlay.dtd
index c3f2aebd7f1..e69de29bb2d 100644
--- a/xpfe/components/prefwindow/resources/locale/en-US/cookiePrefsOverlay.dtd
+++ b/xpfe/components/prefwindow/resources/locale/en-US/cookiePrefsOverlay.dtd
@@ -1,3 +0,0 @@
-
-
-
diff --git a/xpfe/components/prefwindow/resources/locale/en-US/permissionsPrefsOverlay.dtd b/xpfe/components/prefwindow/resources/locale/en-US/permissionsPrefsOverlay.dtd
index c3f2aebd7f1..e69de29bb2d 100644
--- a/xpfe/components/prefwindow/resources/locale/en-US/permissionsPrefsOverlay.dtd
+++ b/xpfe/components/prefwindow/resources/locale/en-US/permissionsPrefsOverlay.dtd
@@ -1,3 +0,0 @@
-
-
-
diff --git a/xpfe/components/prefwindow/resources/locale/en-US/pref-popups.dtd b/xpfe/components/prefwindow/resources/locale/en-US/pref-popups.dtd
index b86a564d9f8..a7d277ac31a 100644
--- a/xpfe/components/prefwindow/resources/locale/en-US/pref-popups.dtd
+++ b/xpfe/components/prefwindow/resources/locale/en-US/pref-popups.dtd
@@ -1,16 +1,24 @@
-
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-