add popup blocking context menu item. bug 166442 r=brendan,jag

This commit is contained in:
danm%netscape.com 2002-09-28 16:14:43 +00:00
Родитель 3e01ff0e77
Коммит 0dac6bc2ec
4 изменённых файлов: 156 добавлений и 1 удалений

Просмотреть файл

@ -130,6 +130,25 @@ const gHomepagePrefListener =
}
};
// popup window permission change listener
const gPopupPermListener = {
observe: function(subject, topic, data) {
if (topic == "popup-perm-close") {
// close the window if we're a popup and our opener's URI matches
// the URI in the notification
var popupOpenerURI = maybeInitPopupContext();
if (popupOpenerURI) {
const IOS = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
closeURI = IOS.newURI(data, null, null);
if (closeURI.host == popupOpenerURI.host)
window.close();
}
}
}
};
/**
* Pref listener handler functions.
* Both functions assume that observer.domain is set to
@ -155,6 +174,20 @@ function removePrefListener(observer)
}
}
function addPopupPermListener(observer)
{
const OS = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
OS.addObserver(observer, "popup-perm-close", false);
}
function removePopupPermListener(observer)
{
const OS = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
OS.removeObserver(observer, "popup-perm-close");
}
/**
* We can avoid adding multiple load event listeners and save some time by adding
* one listener that calls all real handlers.
@ -378,6 +411,7 @@ function Startup()
addPrefListener(gButtonPrefListener);
addPrefListener(gTabStripPrefListener);
addPrefListener(gHomepagePrefListener);
addPopupPermListener(gPopupPermListener);
window.browserContentListener =
new nsBrowserContentListener(window, getBrowser());
@ -576,6 +610,7 @@ function Shutdown()
removePrefListener(gButtonPrefListener);
removePrefListener(gTabStripPrefListener);
removePrefListener(gHomepagePrefListener);
removePopupPermListener(gPopupPermListener);
window.browserContentListener.close();
// Close the app core.
@ -1953,3 +1988,34 @@ function checkTheme()
}
}
}
// opener may not have been initialized by load time (chrome windows only)
// so call this function some time later.
function maybeInitPopupContext()
{
// it's not a popup with no opener
if (!window.content.opener)
return null;
try {
// are we a popup window?
const CI = Components.interfaces;
var xulwin = window
.QueryInterface(CI.nsIInterfaceRequestor)
.getInterface(CI.nsIWebNavigation)
.QueryInterface(CI.nsIDocShellTreeItem).treeOwner
.QueryInterface(CI.nsIInterfaceRequestor)
.getInterface(CI.nsIXULWindow);
if (xulwin.contextFlags &
CI.nsIWindowCreator2.PARENT_IS_LOADING_OR_RUNNING_TIMEOUT) {
// return our opener's URI
const IOS = Components.classes["@mozilla.org/network/io-service;1"]
.getService(CI.nsIIOService);
var spec = Components.lookupMethod(window.content.opener, "location")
.call();
return IOS.newURI(spec, null, null);
}
} catch(e) {
}
return null;
}

Просмотреть файл

@ -45,6 +45,16 @@
<popup id="contentAreaContextMenu"
onpopupshowing="gContextMenu = new nsContextMenu( this ); return gContextMenu.shouldDisplay;"
onpopuphiding="gContextMenu = null;">
<menuitem id="popupwindow-reject"
label="&popupWindowRejectCmd.label;"
accesskey="&popupWindowRejectCmd.accesskey;"
oncommand="gContextMenu.rejectPopupWindows(event.shiftKey);"/>
<menuitem id="popupwindow-allow"
label="&popupWindowAllowCmd.label;"
accesskey="&popupWindowAllowCmd.accesskey;"
oncommand="gContextMenu.allowPopupWindows();"/>
<menuseparator id="context-sep-popup"/>
<menuitem id="context-openlink"
label="&openLinkCmd.label;"
accesskey="&openLinkCmd.accesskey;"

Просмотреть файл

@ -36,6 +36,7 @@
function nsContextMenu( xulMenu ) {
this.target = null;
this.menu = null;
this.popupURL = null;
this.onTextInput = false;
this.onImage = false;
this.onLink = false;
@ -69,6 +70,8 @@ nsContextMenu.prototype = {
this.isTextSelected = this.isTextSelection();
this.initPopupURL();
// Initialize (disable/remove) menu items.
this.initItems();
},
@ -149,6 +152,19 @@ nsContextMenu.prototype = {
this.showItem( "context-searchselect", this.isTextSelected );
this.showItem( "frame", this.inFrame );
this.showItem( "frame-sep", this.inFrame );
var blocking = true;
if (this.popupURL)
try {
const PM = Components.classes["@mozilla.org/PopupWindowManager;1"]
.getService(Components.interfaces.nsIPopupWindowManager);
blocking = PM.testPermission(this.popupURL) ==
Components.interfaces.nsIPopupWindowManager.eDisallow;
} catch (e) {
}
this.showItem( "popupwindow-reject", this.popupURL && !blocking);
this.showItem( "popupwindow-allow", this.popupURL && blocking);
this.showItem( "context-sep-popup", this.popupURL);
},
initClipboardItems : function () {
@ -397,6 +413,48 @@ nsContextMenu.prototype = {
elem = elem.parentNode;
}
},
initPopupURL: function() {
// quick check: if no opener, it can't be a popup
if (!window.content.opener)
return;
try {
var show = false;
// is it a popup window?
const CI = Components.interfaces;
var xulwin = window
.QueryInterface(CI.nsIInterfaceRequestor)
.getInterface(CI.nsIWebNavigation)
.QueryInterface(CI.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(CI.nsIInterfaceRequestor)
.getInterface(CI.nsIXULWindow);
if (xulwin.contextFlags &
CI.nsIWindowCreator2.PARENT_IS_LOADING_OR_RUNNING_TIMEOUT) {
// do the pref settings allow site-by-site popup management?
const PB = Components.classes["@mozilla.org/preferences-service;1"]
.getService(CI.nsIPrefBranch);
show = !PB.getBoolPref("dom.disable_open_during_load") &&
PB.getIntPref("privacy.popups.policy") ==
CI.nsIPopupWindowManager.eAllow &&
PB.getBoolPref("privacy.popups.usecustom");
}
if (show) {
// initialize popupURL
const IOS = Components.classes["@mozilla.org/network/io-service;1"]
.getService(CI.nsIIOService);
var spec = Components.lookupMethod(window.content.opener, "location")
.call();
this.popupURL = IOS.newURI(spec, null, null);
// but cancel if it's an unsuitable URL
const PM = Components.classes["@mozilla.org/PopupWindowManager;1"]
.getService(CI.nsIPopupWindowManager);
if (!PM.testSuitability(this.popupURL))
this.popupURL = null;
}
} catch(e) {
}
},
// Returns the computed style attribute for the given element.
getComputedStyle: function( elem, prop ) {
return elem.ownerDocument.defaultView.getComputedStyle( elem, '' ).getPropertyValue( prop );
@ -441,6 +499,23 @@ nsContextMenu.prototype = {
return false;
}
},
// Block popup windows
rejectPopupWindows: function(andClose) {
const PM = Components.classes["@mozilla.org/PopupWindowManager;1"]
.getService(Components.interfaces.nsIPopupWindowManager);
PM.add(this.popupURL, false);
if (andClose) {
const OS = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
OS.notifyObservers(window, "popup-perm-close", this.popupURL.spec);
}
},
// Unblock popup windows
allowPopupWindows: function() {
const PM = Components.classes["@mozilla.org/PopupWindowManager;1"]
.getService(Components.interfaces.nsIPopupWindowManager);
PM.add(this.popupURL, true);
},
// Open linked-to URL in a new window.
openLink : function () {
// Determine linked-to URL.

Просмотреть файл

@ -1,4 +1,8 @@
<!-- Context Menu -->
<!ENTITY popupWindowRejectCmd.label "Reject pop-up windows from this site">
<!ENTITY popupWindowRejectCmd.accesskey "">
<!ENTITY popupWindowAllowCmd.label "Allow pop-up windows from this site">
<!ENTITY popupWindowAllowCmd.accesskey "">
<!ENTITY openLinkCmd.label "Open Link in New Window">
<!ENTITY openLinkCmd.accesskey "W">
<!ENTITY openLinkCmdInTab.label "Open Link in New Tab">
@ -78,4 +82,4 @@
<!ENTITY undoCmd.accesskey "U">
<!ENTITY thisFrameMenu.label "This Frame">
<!ENTITY thisFrameMenu.accesskey "h">
<!ENTITY search.accesskey "W">
<!ENTITY search.accesskey "W">