Mozilla/mozilla/suite/common/bindings/notification.xml
neil%parkwaycc.co.uk e6667eb685 Bug 413963 Password manager has unsafe dependency on browser r=gavin a=damons
git-svn-id: svn://10.0.0.236/trunk@244332 18797224-902f-48f8-a5cc-f745e15eee43
2008-01-29 12:25:00 +00:00

625 lines
25 KiB
XML

<?xml version="1.0"?>
<!DOCTYPE bindings [
<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
%notificationDTD;
]>
<bindings id="browserNotificationBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="browser-notificationbox"
extends="chrome://global/content/bindings/notification.xml#notificationbox">
<implementation implements="nsIObserver, nsIWebProgressListener, nsIDOMEventListener">
<field name="_stringBundle" readonly="true">
<![CDATA[
Components.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService)
.createBundle("chrome://communicator/locale/notification.properties");
]]>
</field>
<field name="_brandStringBundle" readonly="true">
<![CDATA[
Components.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService)
.createBundle("chrome://branding/locale/brand.properties");
]]>
</field>
<field name="_prefs" readonly="true">
<![CDATA[
Components.classes['@mozilla.org/preferences-service;1']
.getService(Components.interfaces.nsIPrefBranch2);
]]>
</field>
<field name="_activeBrowser">null</field>
<property name="activeBrowser" readonly="true">
<getter>
<![CDATA[
if (!this._activeBrowser) {
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var browsers = this.getElementsByTagNameNS(XUL_NS, "browser");
if (browsers.length == 1) {
this._activeBrowser = browsers.item(0);
} else if (browsers.length) {
for (var i = 0; i < browsers.length; i++) {
if (browsers.item(i).docShell) {
this._activeBrowser = browsers.item(i);
break;
}
}
}
}
return this._activeBrowser;
]]>
</getter>
</property>
<field name="_addedProgressListener">false</field>
<method name="addProgressListener">
<body>
<![CDATA[
if (this.activeBrowser && !this._addedProgressListener) {
this.activeBrowser.webProgress.addProgressListener(this, Components.interfaces.nsIWebProgress.NOTIFY_LOCATION);
this._addedProgressListener = true;
}
]]>
</body>
</method>
<method name="onLocationChange">
<parameter name="aWebProgress" />
<parameter name="aRequest" />
<parameter name="aLocation" />
<body>
<![CDATA[
var errorPage = aRequest && !Components.isSuccessCode(aRequest.status);
if (aWebProgress.DOMWindow == this.activeBrowser.contentWindow &&
(aWebProgress.isLoadingDocument || errorPage)) {
this.missingPlugins = {};
if (this.popupCount) {
this.popupCount = 0;
this.notifyPopupCountChanged();
}
// XXX should be: removeTransientNotifications(true) once bug 303327 is fixed
this.removeTransientNotifications();
}
]]>
</body>
</method>
<method name="observe">
<parameter name="aSubject" />
<parameter name="aTopic" />
<parameter name="aData" />
<body>
<![CDATA[
var browser = this.activeBrowser;
// inactive sidebar panel:
if (!browser || !browser.docShell)
return;
switch (aTopic) {
case "xpinstall-install-blocked":
var installInfo = aSubject.QueryInterface(Components.interfaces.nsIXPIInstallInfo);
if (installInfo.originatingWindow.top != browser.contentWindow)
return;
var notificationName, messageString, buttons, host;
try {
// this fails with nsSimpleURIs like data: URIs
host = installInfo.originatingURI.host;
} catch (ex) {
host = this._stringBundle.GetStringFromName("xpinstallHostNotAvailable");
}
if (!this._prefs.getBoolPref("xpinstall.enabled")) {
notificationName = "xpinstall-disabled";
if (this._prefs.prefIsLocked("xpinstall.enabled")) {
messageString = this._stringBundle.GetStringFromName("xpinstallDisabledMessageLocked");
buttons = [];
} else {
var prefBranch = this._prefs;
messageString = this._stringBundle.GetStringFromName("xpinstallDisabledMessage");
buttons = [{
label: this._stringBundle.GetStringFromName("xpinstallDisabledButton"),
accessKey: this._stringBundle.GetStringFromName("xpinstallDisabledButton.accesskey"),
popup: null,
callback: function editPrefs() {
prefBranch.setBoolPref("xpinstall.enabled", true);
return false;
}
}];
}
} else {
notificationName = "xpinstall";
var brandShortName = this._brandStringBundle.GetStringFromName("brandShortName");
messageString = this._stringBundle.formatStringFromName("xpinstallPromptWarning",
[brandShortName, host], 2);
buttons = [{
label: this._stringBundle.GetStringFromName("xpinstallPromptInstallButton"),
accessKey: this._stringBundle.GetStringFromName("xpinstallPromptInstallButton.accesskey"),
popup: null,
callback: function allowInstall() {
var mgr = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
.createInstance(Components.interfaces.nsIXPInstallManager);
mgr.initManagerWithInstallInfo(installInfo);
return false;
}
}];
}
if (!this.getNotificationWithValue(notificationName)) {
const priority = this.PRIORITY_WARNING_MEDIUM;
const iconURL = "chrome://mozapps/skin/xpinstall/xpinstallItemGeneric.png";
this.appendNotification(messageString, notificationName,
iconURL, priority, buttons);
}
break;
case "nsPref:changed":
if (aData == "privacy.popups.showBrowserMessage") {
if (this._prefs.getBoolPref(aData))
return;
var popupNotification = this.getNotificationWithValue("popup-blocked");
if (popupNotification)
this.removeNotification(popupNotification);
}
if (aData == "plugins.hide_infobar_for_missing_plugin") {
if (!this._prefs.getBoolPref(aData))
return;
var pluginNotification = this.getNotificationWithValue("missing-plugins");
if (pluginNotification)
this.removeNotification(pluginNotification);
}
if (aData == "dom.disable_open_during_load") {
// remove notifications when popup blocking has been turned off
if (this._prefs.getBoolPref(aData) || !this.popupCount)
return;
var popupNotification = this.getNotificationWithValue("popup-blocked");
if (popupNotification)
this.removeNotification(popupNotification);
this.popupCount = 0;
this.notifyPopupCountChanged();
}
break;
case "perm-changed":
var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
if (permission.type != "popup" || aData != "added" || !this.popupCount)
return;
try {
var hostport = this.activeBrowser.currentURI.hostPort;
} catch (ex) {
// we can't do much without a hostport here
return;
}
var host = '.' + permission.host;
hostport = '.' + hostport;
if (host == hostport.slice(-host.length)) {
var popupNotification = this.getNotificationWithValue("popup-blocked");
if (popupNotification)
this.removeNotification(popupNotification);
this.popupCount = 0;
this.notifyPopupCountChanged();
}
break;
}
]]>
</body>
</method>
<field name="missingPlugins">{}</field>
<method name="getPluginInfo">
<parameter name="pluginElement"/>
<body>
<![CDATA[
var mimetype;
var pluginsPage;
if (pluginElement instanceof HTMLAppletElement) {
mimetype = "application/x-java-vm";
} else {
if (pluginElement instanceof HTMLObjectElement) {
pluginsPage = pluginElement.codebase;
} else {
pluginsPage = pluginElement.getAttribute("pluginspage");
if (pluginsPage) {
var doc = pluginElement.ownerDocument;
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
pluginsPage = ioService.newURI(pluginsPage, doc.characterSet, doc.documentURIObject).spec;
}
}
mimetype = pluginElement.QueryInterface(Components.interfaces.nsIObjectLoadingContent)
.actualType;
if (!mimetype) {
mimetype = pluginElement.type;
}
}
return {mimetype: mimetype, pluginsPage: pluginsPage};
]]>
</body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body>
<![CDATA[
var missingPlugins = {};
var pluginInfo = this.getPluginInfo(aEvent.target);
missingPlugins[pluginInfo.mimetype] = pluginInfo;
window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"", "chrome,resizable=yes",
{plugins: missingPlugins, browser: this.activeBrowser});
aEvent.preventDefault();
]]>
</body>
</method>
<method name="playSoundForBlockedPopup">
<body>
<![CDATA[
var playSound = this._prefs.getBoolPref("privacy.popups.sound_enabled");
if (playSound) {
var sound = Components.classes["@mozilla.org/sound;1"]
.createInstance(Components.interfaces.nsISound);
var soundUrlSpec = this._prefs.getCharPref("privacy.popups.sound_url");
if (!soundUrlSpec) {
sound.beep();
return;
}
if (soundUrlSpec.substr(0, 7) == "file://") {
var fileHandler = Components.classes["@mozilla.org/network/protocol;1?name=file"]
.getService(Components.interfaces.nsIFileProtocolHandler);
var file = fileHandler.getFileFromURLSpec(soundUrlSpec);
if (file.exists()) {
var soundUrl = fileHandler.newFileURI(file);
sound.play(soundUrl);
}
} else {
sound.playSystemSound(soundUrlSpec);
}
}
]]>
</body>
</method>
<field name="popupCount">0</field>
<method name="notifyPopupCountChanged">
<body>
<![CDATA[
var event = document.createEvent("Events");
event.initEvent("PopupCountChanged", true, true);
this.dispatchEvent(event);
]]>
</body>
</method>
<method name="allowPopupsForSite">
<parameter name="aEvent"/>
<body>
<![CDATA[
const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
var uri = this.activeBrowser.currentURI;
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(nsIPermissionManager);
pm.add(uri, "popup", nsIPermissionManager.ALLOW_ACTION);
this.removeCurrentNotification();
]]>
</body>
</method>
<constructor>
<![CDATA[
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "xpinstall-install-blocked", false);
os.addObserver(this, "perm-changed", false);
this._prefs.addObserver("plugins.hide_infobar_for_missing_plugin", this, false);
this._prefs.addObserver("privacy.popups.showBrowserMessage", this, false);
this._prefs.addObserver("dom.disable_open_during_load", this, false);
this.addProgressListener();
]]>
</constructor>
<destructor>
<![CDATA[
this.destroy();
]]>
</destructor>
<field name="mDestroyed">false</field>
<!-- This is necessary because the destructor doesn't always get called when
we are removed from a tabbrowser. This will be explicitly called by tabbrowser -->
<method name="destroy">
<body>
<![CDATA[
if (this.mDestroyed)
return;
this.mDestroyed = true;
if (this._addedProgressListener) {
this.activeBrowser.webProgress.removeProgressListener(this);
this._addedProgressListener = false;
}
this._activeBrowser = null;
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
try {
os.removeObserver(this, "xpinstall-install-blocked");
} catch (ex) {}
try {
os.removeObserver(this, "perm-changed");
} catch (ex) {}
try {
this._prefs.removeObserver("plugins.hide_infobar_for_missing_plugin", this);
} catch (ex) {}
try {
this._prefs.removeObserver("privacy.popups.showBrowserMessage", this);
} catch (ex) {}
try {
this._prefs.removeObserver("dom.disable_open_during_load", this);
} catch (ex) {}
]]>
</body>
</method>
</implementation>
<handlers>
<handler event="DOMUpdatePageReport" phase="capturing">
<![CDATA[
var browser = this.activeBrowser;
if (!browser.pageReport)
return;
// this.popupCount can be 0, while browser.pageReport has not been cleared.
if (!this.popupCount && browser.pageReport.length > 1) {
this.popupCount = browser.pageReport.length;
} else {
this.popupCount++;
}
this.playSoundForBlockedPopup();
this.notifyPopupCountChanged();
// Check for duplicates and remove the old occurence of this url,
// to update the features.
var lastItemPlace = browser.pageReport.length - 1;
var lastItem = browser.pageReport[lastItemPlace];
for (var i = 0; i < lastItemPlace; i++) {
if (browser.pageReport[i].popupWindowURI.equals(lastItem.popupWindowURI)) {
browser.pageReport.splice(i, 1);
break;
}
}
// Limit the length of the menu to some reasonable size.
// We only add one item every time in browser.xml, so no need for more complex stuff.
if (browser.pageReport.length > 100)
browser.pageReport.shift();
if (this._prefs.getBoolPref("privacy.popups.showBrowserMessage"))
{
var brandShortName = this._brandStringBundle.GetStringFromName("brandShortName");
var message;
if (this.popupCount > 1)
message = this._stringBundle.formatStringFromName("popupWarningMultiple", [brandShortName, this.popupCount], 2);
else
message = this._stringBundle.formatStringFromName("popupWarning", [brandShortName], 1);
var notification = this.getNotificationWithValue("popup-blocked");
if (notification) {
notification.label = message;
} else {
var popupButtonText = this._stringBundle.GetStringFromName("popupWarningButton");
var popupButtonAccesskey = this._stringBundle.GetStringFromName("popupWarningButton.accesskey");
var buttons = [{
label: popupButtonText,
accessKey: popupButtonAccesskey,
popup: "popupNotificationMenu",
callback: null
}];
const priority = this.PRIORITY_WARNING_MEDIUM;
this.appendNotification(message, "popup-blocked",
"chrome://navigator/skin/icons/popup-blocked.png",
priority, buttons);
}
}
]]>
</handler>
<handler event="PluginNotFound">
<![CDATA[
// Since we are expecting also untrusted events, make sure
// that the target is a plugin
if (!(event.target instanceof Components.interfaces.nsIObjectLoadingContent))
return;
// For broken non-object plugin tags, register a click handler so
// that the user can click the plugin replacement to get the new
// plugin. Object tags can, and often do, deal with that themselves,
// so don't stomp on the page developers toes.
if (!(event.target instanceof HTMLObjectElement))
event.target.addEventListener("click", this, false);
if (this._prefs.getBoolPref("plugins.hide_infobar_for_missing_plugin"))
return;
var pluginInfo = this.getPluginInfo(event.target);
this.missingPlugins[pluginInfo.mimetype] = pluginInfo;
if (!this.getNotificationWithValue("missing-plugins")) {
var blockedNotification = this.getNotificationWithValue("blocked-plugins");
if (blockedNotification)
blockedNotification.close();
var self = this;
var messageString = this._stringBundle.GetStringFromName("missingpluginsMessage.title");
var buttons = [{
label: this._stringBundle.GetStringFromName("missingpluginsMessage.button.label"),
accessKey: this._stringBundle.GetStringFromName("missingpluginsMessage.button.accesskey"),
popup: null,
callback: function openPluginInstallerWizard() {
window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"", "chrome,resizable=yes",
{plugins: self.missingPlugins, browser: self.activeBrowser});
}
}];
const priority = this.PRIORITY_WARNING_MEDIUM;
const iconURL = "chrome://mozapps/skin/plugins/pluginGeneric.png";
this.appendNotification(messageString, "missing-plugins",
iconURL, priority, buttons);
}
]]>
</handler>
<handler event="PluginBlocklisted">
<![CDATA[
// Since we are expecting also untrusted events, make sure
// that the target is a plugin
if (!(event.target instanceof Components.interfaces.nsIObjectLoadingContent))
return;
if (this._prefs.getBoolPref("plugins.hide_infobar_for_missing_plugin"))
return;
var pluginInfo = this.getPluginInfo(event.target);
this.missingPlugins[pluginInfo.mimetype] = pluginInfo;
if (this.getNotificationWithValue("missing-plugins") ||
this.getNotificationWithValue("blocked-plugins"))
return;
var self = this;
var messageString = this._stringBundle.GetStringFromName("blockedpluginsMessage.title");
var buttons = [{
label: this._stringBundle.GetStringFromName("blockedpluginsMessage.infoButton.label"),
accessKey: this._stringBundle.GetStringFromName("blockedpluginsMessage.infoButton.accesskey"),
popup: null,
callback: function getBlocklistInfo() {
var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Components.interfaces.nsIURLFormatter);
var url = formatter.formatURLPref("extensions.blocklist.detailsURL");
const kExistingWindow = Components.interfaces.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW;
const kNewWindow = Components.interfaces.nsIBrowserDOMWindow.OPEN_NEWWINDOW;
var browserWin;
var whereToOpen = self._prefs.getIntPref("browser.link.open_external");
if (whereToOpen != kNewWindow) {
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
browserWin = windowManager.getMostRecentWindow("navigator:browser");
}
if (!browserWin) {
var browserURL = "chrome://navigator/content/navigator.xul";
try {
browserURL = self._prefs.getCharPref("browser.chromeURL");
} catch (ex) {}
window.openDialog(browserURL, "_blank", "chrome,all,dialog=no", url);
} else {
if (whereToOpen == kExistingWindow)
browserWin.loadURI(url);
else {
// new tab
var browser = browserWin.getBrowser();
var newTab = browser.addTab(url);
browser.selectedTab = newTab;
}
browserWin.content.focus();
}
return true;
}
}, {
label: this._stringBundle.GetStringFromName("blockedpluginsMessage.searchButton.label"),
accessKey: this._stringBundle.GetStringFromName("blockedpluginsMessage.searchButton.accesskey"),
popup: null,
callback: function openPluginInstallerWizard() {
window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"", "chrome,resizable=yes",
{plugins: self.missingPlugins, browser: self.activeBrowser});
}
}];
const priority = this.PRIORITY_WARNING_MEDIUM;
const iconURL = "chrome://mozapps/skin/plugins/pluginGeneric.png";
this.appendNotification(messageString, "blocked-plugins",
iconURL, priority, buttons);
]]>
</handler>
<handler event="NewPluginInstalled">
<![CDATA[
this.missingPlugins = {};
// clean up the UI after a new plugin has been installed.
var notification = this.getNotificationWithValue("missing-plugins");
if (notification)
this.removeNotification(notification);
// reload the browser to make the new plugin show.
this.activeBrowser.reload();
]]>
</handler>
</handlers>
</binding>
<binding id="sidebar-notification"
extends="chrome://global/content/bindings/notification.xml#notification">
<content>
<xul:vbox class="notification-inner outset" flex="1" xbl:inherits="type">
<xul:hbox align="center">
<xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image"/>
<xul:spacer flex="1"/>
<xul:toolbarbutton ondblclick="event.stopPropagation();"
class="messageCloseButton tabbable"
xbl:inherits="hidden=hideclose"
tooltiptext="&closeNotification.tooltip;"
oncommand="document.getBindingParent(this).close();"/>
</xul:hbox>
<xul:description anonid="messageText" class="messageText" flex="1" xbl:inherits="xbl:text=label"/>
<xul:hbox anonid="details"
oncommand="document.getBindingParent(this)._doButtonCommand(event);">
<xul:spacer flex="1"/>
<children/>
</xul:hbox>
</xul:vbox>
</content>
</binding>
</bindings>