зеркало из https://github.com/mozilla/gecko-dev.git
add popup blocking context menu item. bug 166442 r=brendan,jag
This commit is contained in:
Родитель
3e01ff0e77
Коммит
0dac6bc2ec
|
@ -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">
|
||||
|
|
Загрузка…
Ссылка в новой задаче