mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 880735 part D - New doorhanger frontend code. Removes all logic which shows the plugin doorhanger automatically, including on scripting. Always show the doorhanger when there is a plugin present on the page, even if that plugin is currently enabled. Make the "always" choices clear to the user. r=jaws
This commit is contained in:
parent
fd595f38a6
commit
b02c781c12
@ -4,6 +4,8 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
const kPrefNotifyMissingFlash = "plugins.notifyMissingFlash";
|
||||
const kPrefSessionPersistMinutes = "plugin.sessionPermissionNow.intervalInMinutes";
|
||||
const kPrefPersistentDays = "plugin.persistentPermissionAlways.intervalInDays";
|
||||
|
||||
var gPluginHandler = {
|
||||
PLUGIN_SCRIPTED_STATE_NONE: 0,
|
||||
@ -24,48 +26,49 @@ var gPluginHandler = {
|
||||
#endif
|
||||
|
||||
_getPluginInfo: function (pluginElement) {
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
pluginElement.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
|
||||
let tagMimetype;
|
||||
let pluginsPage;
|
||||
let pluginName = gNavigatorBundle.getString("pluginInfo.unknownPlugin");
|
||||
let pluginTag = null;
|
||||
let permissionString = null;
|
||||
let fallbackType = null;
|
||||
let blocklistState = null;
|
||||
|
||||
if (pluginElement instanceof HTMLAppletElement) {
|
||||
tagMimetype = "application/x-java-vm";
|
||||
} else {
|
||||
if (pluginElement instanceof HTMLObjectElement) {
|
||||
pluginsPage = pluginElement.getAttribute("codebase");
|
||||
} else {
|
||||
pluginsPage = pluginElement.getAttribute("pluginspage");
|
||||
}
|
||||
|
||||
// only attempt if a pluginsPage is defined.
|
||||
if (pluginsPage) {
|
||||
let doc = pluginElement.ownerDocument;
|
||||
let docShell = findChildShell(doc, gBrowser.docShell, null);
|
||||
try {
|
||||
pluginsPage = makeURI(pluginsPage, doc.characterSet, docShell.currentURI).spec;
|
||||
} catch (ex) {
|
||||
pluginsPage = "";
|
||||
}
|
||||
}
|
||||
|
||||
tagMimetype = pluginElement.QueryInterface(Ci.nsIObjectLoadingContent)
|
||||
.actualType;
|
||||
tagMimetype = pluginElement.actualType;
|
||||
|
||||
if (tagMimetype == "") {
|
||||
tagMimetype = pluginElement.type;
|
||||
}
|
||||
}
|
||||
|
||||
if (tagMimetype) {
|
||||
let navMimeType = navigator.mimeTypes.namedItem(tagMimetype);
|
||||
if (navMimeType && navMimeType.enabledPlugin) {
|
||||
pluginName = navMimeType.enabledPlugin.name;
|
||||
pluginName = gPluginHandler.makeNicePluginName(pluginName);
|
||||
if (gPluginHandler.isKnownPlugin(pluginElement)) {
|
||||
pluginTag = pluginHost.getPluginTagForType(pluginElement.actualType);
|
||||
pluginName = gPluginHandler.makeNicePluginName(pluginTag.name);
|
||||
|
||||
permissionString = pluginHost.getPermissionStringForType(pluginElement.actualType);
|
||||
fallbackType = pluginElement.defaultFallbackType;
|
||||
blocklistState = pluginHost.getBlocklistStateForType(pluginElement.actualType);
|
||||
// Make state-softblocked == state-notblocked for our purposes,
|
||||
// they have the same UI. STATE_OUTDATED should not exist for plugin
|
||||
// items, but let's alias it anyway, just in case.
|
||||
if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED ||
|
||||
blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
|
||||
blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
return { mimetype: tagMimetype,
|
||||
pluginsPage: pluginsPage,
|
||||
pluginName: pluginName };
|
||||
pluginName: pluginName,
|
||||
pluginTag: pluginTag,
|
||||
permissionString: permissionString,
|
||||
fallbackType: fallbackType,
|
||||
blocklistState: blocklistState,
|
||||
};
|
||||
},
|
||||
|
||||
// Map the plugin's name to a filtered version more suitable for user UI.
|
||||
@ -240,6 +243,8 @@ var gPluginHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
|
||||
|
||||
switch (eventType) {
|
||||
case "PluginCrashed":
|
||||
this.pluginInstanceCrashed(plugin, event);
|
||||
@ -263,7 +268,7 @@ var gPluginHandler = {
|
||||
|
||||
case "PluginBlocklisted":
|
||||
case "PluginOutdated":
|
||||
this.pluginUnavailable(plugin, eventType);
|
||||
this._showClickToPlayNotification(browser);
|
||||
break;
|
||||
|
||||
case "PluginVulnerableUpdatable":
|
||||
@ -285,6 +290,7 @@ var gPluginHandler = {
|
||||
let vulnerabilityText = doc.getAnonymousElementByAttribute(plugin, "anonid", "vulnerabilityStatus");
|
||||
vulnerabilityText.textContent = vulnerabilityString;
|
||||
}
|
||||
this._showClickToPlayNotification(browser);
|
||||
break;
|
||||
|
||||
case "PluginPlayPreview":
|
||||
@ -294,16 +300,11 @@ var gPluginHandler = {
|
||||
case "PluginDisabled":
|
||||
let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
|
||||
this.addLinkClickCallback(manageLink, "managePlugins");
|
||||
this._showClickToPlayNotification(browser);
|
||||
break;
|
||||
|
||||
case "PluginScripted":
|
||||
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
|
||||
if (browser._pluginScriptedState == this.PLUGIN_SCRIPTED_STATE_NONE) {
|
||||
browser._pluginScriptedState = this.PLUGIN_SCRIPTED_STATE_FIRED;
|
||||
setTimeout(function() {
|
||||
gPluginHandler.handlePluginScripted(this);
|
||||
}.bind(browser), 500);
|
||||
}
|
||||
case "PluginInstantiated":
|
||||
this._showClickToPlayNotification(browser);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -315,45 +316,6 @@ var gPluginHandler = {
|
||||
}
|
||||
},
|
||||
|
||||
_notificationDisplayedOnce: false,
|
||||
handlePluginScripted: function PH_handlePluginScripted(aBrowser) {
|
||||
let contentWindow = aBrowser.contentWindow;
|
||||
if (!contentWindow)
|
||||
return;
|
||||
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let plugins = cwu.plugins.filter(function(plugin) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
return gPluginHandler.canActivatePlugin(objLoadingContent);
|
||||
});
|
||||
|
||||
let haveVisibleCTPPlugin = plugins.some(function(plugin) {
|
||||
let doc = plugin.ownerDocument;
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
if (!overlay)
|
||||
return false;
|
||||
|
||||
// if the plugin's style is 240x200, it's a good bet we set that in
|
||||
// toolkit/mozapps/plugins/content/pluginProblemContent.css
|
||||
// (meaning this plugin was never actually given a size, so it's really
|
||||
// not part of visible content)
|
||||
let computedStyle = contentWindow.getComputedStyle(plugin);
|
||||
let isInvisible = ((computedStyle.width == "240px" &&
|
||||
computedStyle.height == "200px") ||
|
||||
gPluginHandler.isTooSmall(plugin, overlay));
|
||||
return !isInvisible;
|
||||
});
|
||||
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
|
||||
if (notification && plugins.length > 0 && !haveVisibleCTPPlugin && !this._notificationDisplayedOnce) {
|
||||
notification.reshow();
|
||||
this._notificationDisplayedOnce = true;
|
||||
}
|
||||
|
||||
aBrowser._pluginScriptedState = this.PLUGIN_SCRIPTED_STATE_DONE;
|
||||
},
|
||||
|
||||
isKnownPlugin: function PH_isKnownPlugin(objLoadingContent) {
|
||||
return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
|
||||
Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
||||
@ -386,40 +348,6 @@ var gPluginHandler = {
|
||||
isFallbackTypeValid;
|
||||
},
|
||||
|
||||
activatePlugins: function PH_activatePlugins(aContentWindow) {
|
||||
let browser = gBrowser.getBrowserForDocument(aContentWindow.document);
|
||||
browser._clickToPlayAllPluginsActivated = true;
|
||||
let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let plugins = cwu.plugins;
|
||||
for (let plugin of plugins) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (gPluginHandler.canActivatePlugin(objLoadingContent))
|
||||
objLoadingContent.playPlugin();
|
||||
}
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", browser);
|
||||
if (notification)
|
||||
notification.remove();
|
||||
},
|
||||
|
||||
activateSinglePlugin: function PH_activateSinglePlugin(aContentWindow, aPlugin) {
|
||||
let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (gPluginHandler.canActivatePlugin(objLoadingContent))
|
||||
objLoadingContent.playPlugin();
|
||||
|
||||
let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let pluginNeedsActivation = gPluginHandler._pluginNeedsActivationExceptThese([aPlugin]);
|
||||
let browser = gBrowser.getBrowserForDocument(aContentWindow.document);
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", browser);
|
||||
if (notification) {
|
||||
notification.remove();
|
||||
}
|
||||
if (pluginNeedsActivation) {
|
||||
gPluginHandler._showClickToPlayNotification(browser);
|
||||
}
|
||||
},
|
||||
|
||||
hideClickToPlayOverlay: function(aPlugin) {
|
||||
let overlay = aPlugin.ownerDocument.getAnonymousElementByAttribute(aPlugin, "class", "mainBox");
|
||||
if (overlay)
|
||||
@ -577,13 +505,6 @@ var gPluginHandler = {
|
||||
return;
|
||||
}
|
||||
|
||||
let pluginInfo = this._getPluginInfo(aPlugin);
|
||||
if (browser._clickToPlayAllPluginsActivated ||
|
||||
browser._clickToPlayPluginsActivated.get(pluginInfo.pluginName)) {
|
||||
objLoadingContent.playPlugin();
|
||||
return;
|
||||
}
|
||||
|
||||
if (overlay) {
|
||||
overlay.addEventListener("click", gPluginHandler._overlayClickListener, true);
|
||||
let closeIcon = doc.getAnonymousElementByAttribute(aPlugin, "anonid", "closeIcon");
|
||||
@ -592,8 +513,6 @@ var gPluginHandler = {
|
||||
gPluginHandler.hideClickToPlayOverlay(aPlugin);
|
||||
}, true);
|
||||
}
|
||||
|
||||
gPluginHandler._showClickToPlayNotification(browser);
|
||||
},
|
||||
|
||||
_overlayClickListener: {
|
||||
@ -617,13 +536,7 @@ var gPluginHandler = {
|
||||
if (!(aEvent.originalTarget instanceof HTMLAnchorElement) &&
|
||||
(aEvent.originalTarget.getAttribute('anonid') != 'closeIcon') &&
|
||||
aEvent.button == 0 && aEvent.isTrusted) {
|
||||
if (objLoadingContent.pluginFallbackType ==
|
||||
Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE ||
|
||||
objLoadingContent.pluginFallbackType ==
|
||||
Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE)
|
||||
gPluginHandler._showClickToPlayNotification(browser, true);
|
||||
else
|
||||
gPluginHandler.activateSinglePlugin(contentWindow, plugin);
|
||||
gPluginHandler._showClickToPlayNotification(browser, plugin);
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
@ -637,16 +550,6 @@ var gPluginHandler = {
|
||||
let pluginInfo = this._getPluginInfo(aPlugin);
|
||||
let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype);
|
||||
|
||||
if (!playPreviewInfo.ignoreCTP) {
|
||||
// if click-to-play rules used, play plugin at once if plugins were
|
||||
// activated for this window
|
||||
if (browser._clickToPlayAllPluginsActivated ||
|
||||
browser._clickToPlayPluginsActivated.get(pluginInfo.pluginName)) {
|
||||
objLoadingContent.playPlugin();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let previewContent = doc.getAnonymousElementByAttribute(aPlugin, "class", "previewPluginContent");
|
||||
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
||||
if (!iframe) {
|
||||
@ -684,10 +587,6 @@ var gPluginHandler = {
|
||||
|
||||
reshowClickToPlayNotification: function PH_reshowClickToPlayNotification() {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
if (!browser._clickToPlayPluginsActivated)
|
||||
browser._clickToPlayPluginsActivated = new Map();
|
||||
if (!browser._pluginScriptedState)
|
||||
browser._pluginScriptedState = gPluginHandler.PLUGIN_SCRIPTED_STATE_NONE;
|
||||
let contentWindow = browser.contentWindow;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
@ -701,6 +600,7 @@ var gPluginHandler = {
|
||||
if (gPluginHandler.canActivatePlugin(objLoadingContent))
|
||||
gPluginHandler._handleClickToPlayEvent(plugin);
|
||||
}
|
||||
gPluginHandler._showClickToPlayNotification(browser);
|
||||
},
|
||||
|
||||
// returns true if there is a plugin on this page that needs activation
|
||||
@ -718,242 +618,186 @@ var gPluginHandler = {
|
||||
return pluginNeedsActivation;
|
||||
},
|
||||
|
||||
/* Gets all plugins currently in the page of the given name */
|
||||
_getPluginsByName: function PH_getPluginsByName(aDOMWindowUtils, aName) {
|
||||
let plugins = [];
|
||||
for (let plugin of aDOMWindowUtils.plugins) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (gPluginHandler.canActivatePlugin(objLoadingContent)) {
|
||||
let pluginName = this._getPluginInfo(plugin).pluginName;
|
||||
if (aName == pluginName) {
|
||||
plugins.push(objLoadingContent);
|
||||
}
|
||||
}
|
||||
_clickToPlayNotificationEventCallback: function PH_ctpEventCallback(event) {
|
||||
if (event == "showing") {
|
||||
gPluginHandler._makeCenterActions(this);
|
||||
}
|
||||
else if (event == "dismissed") {
|
||||
// Once the popup is dismissed, clicking the icon should show the full
|
||||
// list again
|
||||
this.options.primaryPlugin = null;
|
||||
}
|
||||
return plugins;
|
||||
},
|
||||
|
||||
_makeCenterActions: function PH_makeCenterActions(aBrowser) {
|
||||
let contentWindow = aBrowser.contentWindow;
|
||||
_makeCenterActions: function PH_makeCenterActions(notification) {
|
||||
let browser = notification.browser;
|
||||
let contentWindow = browser.contentWindow;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let pluginsDictionary = new Map();
|
||||
for (let plugin of cwu.plugins) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (gPluginHandler.canActivatePlugin(objLoadingContent)) {
|
||||
let pluginName = this._getPluginInfo(plugin).pluginName;
|
||||
if (!pluginsDictionary.has(pluginName))
|
||||
pluginsDictionary.set(pluginName, []);
|
||||
pluginsDictionary.get(pluginName).push(objLoadingContent);
|
||||
}
|
||||
}
|
||||
|
||||
let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(browser.currentURI);
|
||||
|
||||
let centerActions = [];
|
||||
for (let [pluginName, namedPluginArray] of pluginsDictionary) {
|
||||
let plugin = namedPluginArray[0];
|
||||
let warn = false;
|
||||
let warningText = "";
|
||||
let updateLink = Services.urlFormatter.formatURLPref("plugins.update.url");
|
||||
if (plugin.pluginFallbackType) {
|
||||
if (plugin.pluginFallbackType ==
|
||||
Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE) {
|
||||
warn = true;
|
||||
warningText = gNavigatorBundle.getString("vulnerableUpdatablePluginWarning");
|
||||
}
|
||||
else if (plugin.pluginFallbackType ==
|
||||
Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE) {
|
||||
warn = true;
|
||||
warningText = gNavigatorBundle.getString("vulnerableNoUpdatePluginWarning");
|
||||
updateLink = "";
|
||||
}
|
||||
let pluginsFound = new Set();
|
||||
for (let plugin of cwu.plugins) {
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (plugin.getContentTypeForMIMEType(plugin.actualType) != Ci.nsIObjectLoadingContent.TYPE_PLUGIN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let action = {
|
||||
message: pluginName,
|
||||
warn: warn,
|
||||
warningText: warningText,
|
||||
updateLink: updateLink,
|
||||
label: gNavigatorBundle.getString("activateSinglePlugin"),
|
||||
callback: function() {
|
||||
let plugins = gPluginHandler._getPluginsByName(cwu, this.message);
|
||||
for (let objLoadingContent of plugins) {
|
||||
objLoadingContent.playPlugin();
|
||||
}
|
||||
aBrowser._clickToPlayPluginsActivated.set(this.message, true);
|
||||
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
|
||||
if (notification &&
|
||||
!gPluginHandler._pluginNeedsActivationExceptThese(plugins)) {
|
||||
notification.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
centerActions.push(action);
|
||||
}
|
||||
|
||||
return centerActions;
|
||||
},
|
||||
|
||||
_setPermissionForPlugins: function PH_setPermissionForPlugins(aBrowser, aPermission, aPluginList) {
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
for (let plugin of aPluginList) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// canActivatePlugin will return false if this isn't a known plugin type,
|
||||
// so the pluginHost.getPermissionStringForType call is protected
|
||||
if (gPluginHandler.canActivatePlugin(objLoadingContent)) {
|
||||
let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
|
||||
Services.perms.add(aBrowser.currentURI, permissionString, aPermission);
|
||||
let pluginInfo = this._getPluginInfo(plugin);
|
||||
if (pluginInfo.permissionString === null) {
|
||||
Components.utils.reportError("No permission string for active plugin.");
|
||||
continue;
|
||||
}
|
||||
if (pluginsFound.has(pluginInfo.permissionString)) {
|
||||
continue;
|
||||
}
|
||||
pluginsFound.add(pluginInfo.permissionString);
|
||||
|
||||
// Add the per-site permissions and details URLs to pluginInfo here
|
||||
// because they are more expensive to compute and so we avoid it in
|
||||
// the tighter loop above.
|
||||
let permissionObj = Services.perms.
|
||||
getPermissionObject(principal, pluginInfo.permissionString, false);
|
||||
if (permissionObj) {
|
||||
pluginInfo.pluginPermissionHost = permissionObj.host;
|
||||
pluginInfo.pluginPermissionType = permissionObj.expireType;
|
||||
}
|
||||
else {
|
||||
pluginInfo.pluginPermissionHost = browser.currentURI.host;
|
||||
pluginInfo.pluginPermissionType = undefined;
|
||||
}
|
||||
|
||||
let url;
|
||||
// TODO: allow the blocklist to specify a better link, bug 873093
|
||||
if (pluginInfo.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) {
|
||||
url = Services.urlFormatter.formatURLPref("plugins.update.url");
|
||||
}
|
||||
else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
|
||||
url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
|
||||
}
|
||||
pluginInfo.detailsLink = url;
|
||||
|
||||
centerActions.push(pluginInfo);
|
||||
}
|
||||
centerActions.sort(function(a, b) {
|
||||
return a.pluginName.localeCompare(b.pluginName);
|
||||
});
|
||||
|
||||
notification.options.centerActions = centerActions;
|
||||
},
|
||||
|
||||
_showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aForceOpenNotification) {
|
||||
let contentWindow = aBrowser.contentWindow;
|
||||
let messageString = gNavigatorBundle.getString("activatePluginsMessage.message");
|
||||
let mainAction = {
|
||||
label: gNavigatorBundle.getString("activateAllPluginsMessage.label"),
|
||||
accessKey: gNavigatorBundle.getString("activatePluginsMessage.accesskey"),
|
||||
callback: function() { gPluginHandler.activatePlugins(contentWindow); }
|
||||
};
|
||||
let centerActions = gPluginHandler._makeCenterActions(aBrowser);
|
||||
/**
|
||||
* Called from the plugin doorhanger to set the new permissions for a plugin
|
||||
* and activate plugins if necessary.
|
||||
* aNewState should be either "allownow" "allowalways" or "block"
|
||||
*/
|
||||
_updatePluginPermission: function PH_setPermissionForPlugins(aNotification, aPluginInfo, aNewState) {
|
||||
let permission;
|
||||
let expireType;
|
||||
let expireTime;
|
||||
|
||||
switch (aNewState) {
|
||||
case "allownow":
|
||||
if (aPluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
expireType = Ci.nsIPermissionManager.EXPIRE_SESSION;
|
||||
expireTime = Date.now() + Services.prefs.getIntPref(kPrefSessionPersistMinutes) * 60 * 1000;
|
||||
break;
|
||||
|
||||
case "allowalways":
|
||||
if (aPluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
expireType = Ci.nsIPermissionManager.EXPIRE_TIME;
|
||||
expireTime = Date.now() +
|
||||
Services.prefs.getIntPref(kPrefPersistentDays) * 24 * 60 * 60 * 1000;
|
||||
break;
|
||||
|
||||
case "block":
|
||||
if (aPluginInfo.fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
permission = Ci.nsIPermissionManager.PROMPT_ACTION;
|
||||
expireType = Ci.nsIPermissionManager.EXPIRE_NEVER;
|
||||
expireTime = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
Cu.reportError(Error("Unexpected plugin state: " + aNewState));
|
||||
return;
|
||||
}
|
||||
|
||||
let browser = aNotification.browser;
|
||||
Services.perms.add(browser.currentURI, aPluginInfo.permissionString,
|
||||
permission, expireType, expireTime);
|
||||
|
||||
if (aNewState == "block") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Manually activate the plugins that would have been automatically
|
||||
// activated.
|
||||
let contentWindow = browser.contentWindow;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let haveVulnerablePlugin = cwu.plugins.some(function(plugin) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
return (gPluginHandler.canActivatePlugin(objLoadingContent) &&
|
||||
(objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE ||
|
||||
objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE));
|
||||
});
|
||||
if (haveVulnerablePlugin) {
|
||||
messageString = gNavigatorBundle.getString("vulnerablePluginsMessage");
|
||||
let plugins = cwu.plugins;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
|
||||
for (let plugin of plugins) {
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// canActivatePlugin will return false if this isn't a known plugin type,
|
||||
// so the pluginHost.getPermissionStringForType call is protected
|
||||
if (gPluginHandler.canActivatePlugin(plugin) &&
|
||||
aPluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
|
||||
plugin.playPlugin();
|
||||
}
|
||||
}
|
||||
let secondaryActions = [{
|
||||
label: gNavigatorBundle.getString("activatePluginsMessage.always"),
|
||||
accessKey: gNavigatorBundle.getString("activatePluginsMessage.always.accesskey"),
|
||||
callback: function () {
|
||||
gPluginHandler._setPermissionForPlugins(aBrowser, Ci.nsIPermissionManager.ALLOW_ACTION, cwu.plugins);
|
||||
gPluginHandler.activatePlugins(contentWindow);
|
||||
}
|
||||
},{
|
||||
label: gNavigatorBundle.getString("activatePluginsMessage.never"),
|
||||
accessKey: gNavigatorBundle.getString("activatePluginsMessage.never.accesskey"),
|
||||
callback: function () {
|
||||
gPluginHandler._setPermissionForPlugins(aBrowser, Ci.nsIPermissionManager.DENY_ACTION, cwu.plugins);
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
|
||||
if (notification)
|
||||
notification.remove();
|
||||
gPluginHandler._removeClickToPlayOverlays(contentWindow);
|
||||
}
|
||||
}];
|
||||
},
|
||||
|
||||
_showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aPrimaryPlugin) {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
|
||||
|
||||
let contentWindow = aBrowser.contentWindow;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let plugins = cwu.plugins;
|
||||
if (plugins.length == 0) {
|
||||
if (notification) {
|
||||
PopupNotifications.remove(notification);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let haveVulnerablePlugin = plugins.some(function(plugin) {
|
||||
let fallbackType = plugin.pluginFallbackType;
|
||||
return fallbackType == plugin.PLUGIN_VULNERABLE_UPDATABLE ||
|
||||
fallbackType == plugin.PLUGIN_VULNERABLE_NO_UPDATE ||
|
||||
fallbackType == plugin.PLUGIN_BLOCKLISTED;
|
||||
});
|
||||
let dismissed = notification ? notification.dismissed : true;
|
||||
// Always show the doorhanger if the anchor is not available.
|
||||
if (!isElementVisible(gURLBar) || aForceOpenNotification)
|
||||
if (!isElementVisible(gURLBar) || aPrimaryPlugin)
|
||||
dismissed = false;
|
||||
let options = { dismissed: dismissed, centerActions: centerActions };
|
||||
let icon = haveVulnerablePlugin ? "blocked-plugins-notification-icon" : "plugins-notification-icon"
|
||||
PopupNotifications.show(aBrowser, "click-to-play-plugins",
|
||||
messageString, icon,
|
||||
mainAction, secondaryActions, options);
|
||||
},
|
||||
|
||||
_removeClickToPlayOverlays: function PH_removeClickToPlayOverlays(aContentWindow) {
|
||||
let doc = aContentWindow.document;
|
||||
let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
for (let plugin of cwu.plugins) {
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
// for already activated plugins, there will be no overlay
|
||||
if (overlay)
|
||||
overlay.style.visibility = "hidden";
|
||||
}
|
||||
},
|
||||
|
||||
// event listener for blocklisted/outdated plugins.
|
||||
pluginUnavailable: function (plugin, eventType) {
|
||||
let browser = gBrowser.getBrowserForDocument(plugin.ownerDocument
|
||||
.defaultView.top.document);
|
||||
if (!browser.missingPlugins)
|
||||
browser.missingPlugins = new Map();
|
||||
|
||||
var pluginInfo = this._getPluginInfo(plugin);
|
||||
browser.missingPlugins.set(pluginInfo.mimetype, pluginInfo);
|
||||
|
||||
var notificationBox = gBrowser.getNotificationBox(browser);
|
||||
|
||||
// Should only display one of these warnings per page.
|
||||
// In order of priority, they are: outdated > missing > blocklisted
|
||||
let outdatedNotification = notificationBox.getNotificationWithValue("outdated-plugins");
|
||||
let blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins");
|
||||
|
||||
function showBlocklistInfo() {
|
||||
var url = formatURL("extensions.blocklist.detailsURL", true);
|
||||
gBrowser.loadOneTab(url, {inBackground: false});
|
||||
return true;
|
||||
let primaryPluginPermission = null;
|
||||
if (aPrimaryPlugin) {
|
||||
primaryPluginPermission = this._getPluginInfo(aPrimaryPlugin).permissionString;
|
||||
}
|
||||
|
||||
function showOutdatedPluginsInfo() {
|
||||
gPrefService.setBoolPref("plugins.update.notifyUser", false);
|
||||
var url = formatURL("plugins.update.url", true);
|
||||
gBrowser.loadOneTab(url, {inBackground: false});
|
||||
return true;
|
||||
}
|
||||
|
||||
let notifications = {
|
||||
PluginBlocklisted : {
|
||||
barID : "blocked-plugins",
|
||||
iconURL : "chrome://mozapps/skin/plugins/notifyPluginBlocked.png",
|
||||
message : gNavigatorBundle.getString("blockedpluginsMessage.title"),
|
||||
buttons : [{
|
||||
label : gNavigatorBundle.getString("blockedpluginsMessage.infoButton.label"),
|
||||
accessKey : gNavigatorBundle.getString("blockedpluginsMessage.infoButton.accesskey"),
|
||||
popup : null,
|
||||
callback : showBlocklistInfo
|
||||
},
|
||||
{
|
||||
label : gNavigatorBundle.getString("blockedpluginsMessage.searchButton.label"),
|
||||
accessKey : gNavigatorBundle.getString("blockedpluginsMessage.searchButton.accesskey"),
|
||||
popup : null,
|
||||
callback : showOutdatedPluginsInfo
|
||||
}],
|
||||
},
|
||||
PluginOutdated : {
|
||||
barID : "outdated-plugins",
|
||||
iconURL : "chrome://mozapps/skin/plugins/notifyPluginOutdated.png",
|
||||
message : gNavigatorBundle.getString("outdatedpluginsMessage.title"),
|
||||
buttons : [{
|
||||
label : gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.label"),
|
||||
accessKey : gNavigatorBundle.getString("outdatedpluginsMessage.updateButton.accesskey"),
|
||||
popup : null,
|
||||
callback : showOutdatedPluginsInfo
|
||||
}],
|
||||
},
|
||||
let options = {
|
||||
dismissed: dismissed,
|
||||
eventCallback: this._clickToPlayNotificationEventCallback,
|
||||
primaryPlugin: primaryPluginPermission
|
||||
};
|
||||
|
||||
// If there is already an outdated plugin notification then do nothing
|
||||
if (outdatedNotification)
|
||||
return;
|
||||
|
||||
if (eventType == "PluginBlocklisted") {
|
||||
if (gPrefService.getBoolPref("plugins.hide_infobar_for_blocked_plugin"))
|
||||
return;
|
||||
|
||||
if (blockedNotification)
|
||||
return;
|
||||
}
|
||||
else if (eventType == "PluginOutdated") {
|
||||
if (gPrefService.getBoolPref("plugins.hide_infobar_for_outdated_plugin"))
|
||||
return;
|
||||
|
||||
// Cancel any notification about blocklisting/missing plugins
|
||||
if (blockedNotification)
|
||||
blockedNotification.close();
|
||||
}
|
||||
|
||||
let notify = notifications[eventType];
|
||||
notificationBox.appendNotification(notify.message, notify.barID, notify.iconURL,
|
||||
notificationBox.PRIORITY_WARNING_MEDIUM,
|
||||
notify.buttons);
|
||||
let icon = haveVulnerablePlugin ? "blocked-plugins-notification-icon" : "plugins-notification-icon";
|
||||
PopupNotifications.show(aBrowser, "click-to-play-plugins",
|
||||
"", icon,
|
||||
null, null, options);
|
||||
},
|
||||
|
||||
// Crashed-plugin observer. Notified once per plugin crash, before events
|
||||
|
@ -506,8 +506,8 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
|
||||
}
|
||||
|
||||
popupnotification-centeritem {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#center-item");
|
||||
.plugin-popupnotification-centeritem {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#plugin-popupnotification-center-item");
|
||||
}
|
||||
|
||||
/* override hidden="true" for the status bar compatibility shim
|
||||
|
@ -752,9 +752,9 @@ var gBrowserInit = {
|
||||
|
||||
// Note that the XBL binding is untrusted
|
||||
gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
|
||||
gBrowser.addEventListener("PluginScripted", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginInstantiated", gPluginHandler, true);
|
||||
|
||||
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
||||
|
||||
|
@ -299,7 +299,7 @@ function clearPluginPermissionTemplate() {
|
||||
}
|
||||
|
||||
function initPluginsRow() {
|
||||
var vulnerableLabel = document.getElementById("browserBundle").getString("vulnerableNoUpdatePluginWarning");
|
||||
let vulnerableLabel = document.getElementById("browserBundle").getString("pluginActivateVulnerable.label");
|
||||
let pluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
|
||||
|
||||
let permissionMap = Map();
|
||||
|
@ -8,6 +8,8 @@
|
||||
<!DOCTYPE bindings [
|
||||
<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
|
||||
%notificationDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
]>
|
||||
|
||||
<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl"
|
||||
@ -1376,122 +1378,471 @@
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="center-item">
|
||||
<binding id="plugin-popupnotification-center-item">
|
||||
<content align="center">
|
||||
<xul:vbox flex="1" class="center-item-box"
|
||||
xbl:inherits="warn,showseparator,padbottom">
|
||||
<xul:hbox flex="1" align="center">
|
||||
<xul:image class="center-item-icon"
|
||||
xbl:inherits="src=itemicon"/>
|
||||
<xul:description class="center-item-label"
|
||||
xbl:inherits="xbl:text=itemtext"/>
|
||||
<xul:spacer flex="1"/>
|
||||
<xul:button class="popup-notification-menubutton center-item-button"
|
||||
oncommand="document.getBindingParent(this).runCallback();"
|
||||
xbl:inherits="label=buttonlabel"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox flex="1" align="center" class="center-item-warning">
|
||||
<xul:image class="center-item-warning-icon"/>
|
||||
<xul:label class="center-item-warning-description" xbl:inherits="xbl:text=warningText"/>
|
||||
<xul:label xbl:inherits="href=updateLink" value="&checkForUpdates;" class="text-link"/>
|
||||
<xul:spacer flex="1"/>
|
||||
<xul:vbox pack="center" anonid="itemBox" class="itemBox">
|
||||
<xul:description anonid="center-item-label" />
|
||||
<xul:hbox flex="1" pack="start" align="center" anonid="center-item-warning">
|
||||
<xul:image anonid="center-item-warning-icon" class="center-item-warning-icon"/>
|
||||
<xul:label anonid="center-item-warning-label"/>
|
||||
<xul:label anonid="center-item-link" value="&checkForUpdates;" class="text-link"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="center">
|
||||
<xul:menulist class="center-item-menulist"
|
||||
anonid="center-item-menulist">
|
||||
<xul:menupopup>
|
||||
<xul:menuitem anonid="allownow" value="allownow"
|
||||
label="&pluginActivateNow.label;" />
|
||||
<xul:menuitem anonid="allowalways" value="allowalways"
|
||||
label="&pluginActivateAlways.label;" />
|
||||
<xul:menuitem anonid="block" value="block"
|
||||
label="&pluginBlockNow.label;" />
|
||||
</xul:menupopup>
|
||||
</xul:menulist>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
<resources>
|
||||
<stylesheet src="chrome://global/skin/notification.css"/>
|
||||
</resources>
|
||||
<implementation>
|
||||
<field name="action"></field>
|
||||
<method name="runCallback">
|
||||
<body><![CDATA[
|
||||
let action = this.action;
|
||||
action.callback();
|
||||
let cas = action.popupnotification.notification.options.centerActions;
|
||||
cas.splice(cas.indexOf(action), 1);
|
||||
PopupNotifications._dismiss();
|
||||
]]></body>
|
||||
</method>
|
||||
<constructor><![CDATA[
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "center-item-label").value = this.action.pluginName;
|
||||
|
||||
let curState = "block";
|
||||
if (this.action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
if (this.action.pluginPermissionType == Ci.nsIPermissionManager.EXPIRE_SESSION) {
|
||||
curState = "allownow";
|
||||
}
|
||||
else {
|
||||
curState = "allowalways";
|
||||
}
|
||||
}
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").value = curState;
|
||||
|
||||
let warningString = "";
|
||||
let linkString = "";
|
||||
|
||||
let link = document.getAnonymousElementByAttribute(this, "anonid", "center-item-link");
|
||||
|
||||
let url;
|
||||
let linkHandler;
|
||||
|
||||
if (this.action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED) {
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").hidden = true;
|
||||
warningString = gNavigatorBundle.getString("pluginActivateDisabled.label");
|
||||
linkString = gNavigatorBundle.getString("pluginActivateDisabled.manage");
|
||||
linkHandler = function(event) {
|
||||
event.preventDefault();
|
||||
gPluginHandler.managePlugins();
|
||||
};
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning-icon").hidden = true;
|
||||
}
|
||||
else {
|
||||
url = this.action.detailsLink;
|
||||
|
||||
switch (this.action.blocklistState) {
|
||||
case Ci.nsIBlocklistService.STATE_NOT_BLOCKED:
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning").hidden = true;
|
||||
break;
|
||||
case Ci.nsIBlocklistService.STATE_BLOCKED:
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").hidden = true;
|
||||
warningString = gNavigatorBundle.getString("pluginActivateBlocked.label");
|
||||
linkString = gNavigatorBundle.getString("pluginActivate.learnMore");
|
||||
break;
|
||||
case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
|
||||
warningString = gNavigatorBundle.getString("pluginActivateOutdated.label");
|
||||
linkString = gNavigatorBundle.getString("pluginActivate.updateLabel");
|
||||
break;
|
||||
case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
|
||||
warningString = gNavigatorBundle.getString("pluginActivateVulnerable.label");
|
||||
linkString = gNavigatorBundle.getString("pluginActivate.riskLabel");
|
||||
break;
|
||||
}
|
||||
}
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning-label").value = warningString;
|
||||
|
||||
if (url || linkHandler) {
|
||||
link.value = linkString;
|
||||
if (url) {
|
||||
link.href = url;
|
||||
}
|
||||
if (linkHandler) {
|
||||
link.addEventListener("click", linkHandler, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
link.hidden = true;
|
||||
}
|
||||
]]></constructor>
|
||||
<property name="value">
|
||||
<getter>
|
||||
return document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"center-item-menulist").value;
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="click-to-play-plugins-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
|
||||
<content align="start" class="click-to-play-plugins-notification-content">
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox class="click-to-play-plugins-notification-icon-box" flex="1">
|
||||
<xul:image class="popup-notification-icon"
|
||||
xbl:inherits="popupid,src=icon"/>
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:vbox>
|
||||
<xul:spacer class="click-to-play-plugins-notification-separator"/>
|
||||
<xul:vbox flex="1" class="popup-notification-main-box"
|
||||
xbl:inherits="popupid">
|
||||
<xul:box class="click-to-play-plugins-notification-description-box" flex="1">
|
||||
<xul:description xbl:inherits="xbl:text=label"/>
|
||||
</xul:box>
|
||||
<xul:spacer class="click-to-play-plugins-notification-separator"/>
|
||||
<xul:vbox class="click-to-play-plugins-notification-center-box">
|
||||
<children includes="popupnotification-centeritem"/>
|
||||
</xul:vbox>
|
||||
<xul:spacer class="click-to-play-plugins-notification-separator"/>
|
||||
<xul:hbox class="click-to-play-plugins-notification-button-container"
|
||||
pack="end" align="center">
|
||||
<xul:button anonid="button"
|
||||
class="popup-notification-menubutton"
|
||||
type="menu-button"
|
||||
xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
|
||||
<xul:menupopup anonid="menupopup"
|
||||
xbl:inherits="oncommand=menucommand">
|
||||
<children/>
|
||||
<xul:menuitem class="menuitem-iconic popup-notification-closeitem"
|
||||
label="&closeNotificationItem.label;"
|
||||
xbl:inherits="oncommand=closeitemcommand"/>
|
||||
</xul:menupopup>
|
||||
</xul:button>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
<xul:vbox flex="1" align="stretch" class="popup-notification-main-box"
|
||||
xbl:inherits="popupid">
|
||||
<xul:hbox class="click-to-play-plugins-notification-description-box" flex="1" align="start">
|
||||
<xul:description flex="1">
|
||||
<html:span anonid="click-to-play-plugins-notification-description" />
|
||||
 
|
||||
<xul:label class="text-link" anonid="click-to-play-plugins-notification-link" />
|
||||
</xul:description>
|
||||
<xul:toolbarbutton anonid="closebutton"
|
||||
class="messageCloseButton popup-notification-closebutton tabbable"
|
||||
xbl:inherits="oncommand=closebuttoncommand"
|
||||
tooltiptext="&closeNotification.tooltip;"/>
|
||||
</xul:hbox>
|
||||
<xul:grid anonid="click-to-play-plugins-notification-center-box">
|
||||
<xul:columns>
|
||||
<xul:column flex="1"/>
|
||||
<xul:column/>
|
||||
</xul:columns>
|
||||
<xul:rows>
|
||||
<children includes="row"/>
|
||||
<xul:hbox pack="start" anonid="plugin-notification-showbox">
|
||||
<xul:button label="&pluginNotification.showAll.label;"
|
||||
accesskey="&pluginNotification.showAll.accesskey;"
|
||||
class="plugin-notification-showbutton"
|
||||
oncommand="document.getBindingParent(this)._setState(2)"/>
|
||||
</xul:hbox>
|
||||
</xul:rows>
|
||||
</xul:grid>
|
||||
<xul:hbox anonid="button-container"
|
||||
class="click-to-play-plugins-notification-button-container"
|
||||
pack="center" align="center">
|
||||
<xul:button anonid="primarybutton"
|
||||
class="popup-notification-menubutton"
|
||||
oncommand="document.getBindingParent(this)._onButton(this)"/>
|
||||
<xul:button anonid="secondarybutton"
|
||||
class="popup-notification-menubutton"
|
||||
oncommand="document.getBindingParent(this)._onButton(this);"/>
|
||||
</xul:hbox>
|
||||
<xul:box hidden="true">
|
||||
<children/>
|
||||
</xul:box>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
<resources>
|
||||
<stylesheet src="chrome://global/skin/notification.css"/>
|
||||
</resources>
|
||||
<implementation>
|
||||
<field name="button" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "button");
|
||||
<field name="_states">
|
||||
({SINGLE: 0, MULTI_COLLAPSED: 1, MULTI_EXPANDED: 2})
|
||||
</field>
|
||||
<field name="menupopup" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "menupopup");
|
||||
<field name="_primaryButton">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "primarybutton");
|
||||
</field>
|
||||
<field name="_secondaryButton">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "secondarybutton")
|
||||
</field>
|
||||
<field name="_buttonContainer">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "button-container")
|
||||
</field>
|
||||
<field name="_brandShortName">
|
||||
document.getElementById("bundle_brand").getString("brandShortName")
|
||||
</field>
|
||||
<field name="_items">[]</field>
|
||||
<constructor><![CDATA[
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let popupnotification = this;
|
||||
let item = null;
|
||||
let prev = null;
|
||||
this.notification.options.centerActions.forEach(function(action) {
|
||||
action.popupnotification = popupnotification;
|
||||
item = document.createElementNS(XUL_NS, "popupnotification-centeritem");
|
||||
for (let action of this.notification.options.centerActions) {
|
||||
let item = document.createElementNS(XUL_NS, "row");
|
||||
item.setAttribute("class", "plugin-popupnotification-centeritem");
|
||||
item.action = action;
|
||||
item.setAttribute("itemtext", action.message);
|
||||
item.setAttribute("buttonlabel", action.label);
|
||||
item.setAttribute("warn", action.warn);
|
||||
item.setAttribute("warningText", action.warningText);
|
||||
item.setAttribute("updateLink", action.updateLink);
|
||||
if (prev &&
|
||||
(prev.getAttribute("warn") == "true" ||
|
||||
item.getAttribute("warn") == "true")) {
|
||||
item.setAttribute("showseparator", true);
|
||||
if (prev.getAttribute("warn") != "true") {
|
||||
prev.setAttribute("padbottom", true);
|
||||
}
|
||||
}
|
||||
popupnotification.appendChild(item);
|
||||
prev = item;
|
||||
});
|
||||
if (item != null) {
|
||||
item.setAttribute("padbottom", "true");
|
||||
this.appendChild(item);
|
||||
this._items.push(item);
|
||||
}
|
||||
if (this.notification.options.centerActions.length == 1) {
|
||||
this._setState(this._states.SINGLE);
|
||||
} else if (this.notification.options.primaryPlugin) {
|
||||
this._setState(this._states.MULTI_COLLAPSED);
|
||||
} else {
|
||||
this._setState(this._states.MULTI_EXPANDED);
|
||||
}
|
||||
]]></constructor>
|
||||
<method name="_setState">
|
||||
<parameter name="state" />
|
||||
<body><![CDATA[
|
||||
var grid = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-center-box");
|
||||
|
||||
if (this._states.SINGLE == state) {
|
||||
grid.hidden = true;
|
||||
this._setupSingleState();
|
||||
return;
|
||||
}
|
||||
|
||||
this._setupDescription("pluginActivateMultiple.message");
|
||||
|
||||
var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox");
|
||||
|
||||
var dialogStrings = Services.strings.createBundle("chrome://global/locale/dialog.properties");
|
||||
this._primaryButton.label = dialogStrings.GetStringFromName("button-accept");
|
||||
this._primaryButton.setAttribute("default", "true");
|
||||
|
||||
this._secondaryButton.label = dialogStrings.GetStringFromName("button-cancel");
|
||||
this._primaryButton.setAttribute("action", "_multiAccept");
|
||||
this._secondaryButton.setAttribute("action", "_cancel");
|
||||
|
||||
grid.hidden = false;
|
||||
|
||||
if (this._states.MULTI_COLLAPSED == state) {
|
||||
for (let child of this.childNodes) {
|
||||
if (child.tagName != "row") {
|
||||
continue;
|
||||
}
|
||||
child.hidden = this.notification.options.primaryPlugin !=
|
||||
child.action.permissionString;
|
||||
}
|
||||
showBox.hidden = false;
|
||||
}
|
||||
else {
|
||||
for (let child of this.childNodes) {
|
||||
if (child.tagName != "row") {
|
||||
continue;
|
||||
}
|
||||
child.hidden = false;
|
||||
}
|
||||
showBox.hidden = true;
|
||||
}
|
||||
this._setupLink(null);
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_setupSingleState">
|
||||
<body><![CDATA[
|
||||
var action = this.notification.options.centerActions[0];
|
||||
var host = action.pluginPermissionHost;
|
||||
|
||||
let label, linkLabel, linkUrl, button1, button2;
|
||||
|
||||
if (action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
button1 = {
|
||||
label: "pluginBlockNow.label",
|
||||
accesskey: "pluginBlockNow.accesskey",
|
||||
action: "_singleBlock"
|
||||
};
|
||||
button2 = {
|
||||
label: "pluginContinue.label",
|
||||
accesskey: "pluginContinue.accesskey",
|
||||
action: "_cancel",
|
||||
default: true
|
||||
};
|
||||
switch (action.blocklistState) {
|
||||
case Ci.nsIBlocklistService.STATE_NOT_BLOCKED:
|
||||
label = "pluginEnabled.message";
|
||||
linkLabel = "pluginActivate.learnMore";
|
||||
break;
|
||||
|
||||
case Ci.nsIBlocklistService.STATE_BLOCKED:
|
||||
Cu.reportError(Error("Cannot happen!"));
|
||||
break;
|
||||
|
||||
case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
|
||||
label = "pluginEnabledOutdated.message";
|
||||
linkLabel = "pluginActivate.updateLabel";
|
||||
break;
|
||||
|
||||
case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
|
||||
label = "pluginEnabledVulnerable.message";
|
||||
linkLabel = "pluginActivate.riskLabel"
|
||||
break;
|
||||
|
||||
default:
|
||||
Cu.reportError(Error("Unexpected blocklist state"));
|
||||
}
|
||||
}
|
||||
else if (action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED) {
|
||||
let linkElement =
|
||||
document.getAnonymousElementByAttribute(
|
||||
this, "anonid", "click-to-play-plugins-notification-link");
|
||||
linkElement.value = gNavigatorBundle.getString("pluginActivateDisabled.manage");
|
||||
linkElement.setAttribute("onclick", "gPluginHandler.managePlugins()");
|
||||
|
||||
let descElement = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
|
||||
descElement.textContent = gNavigatorBundle.getFormattedString(
|
||||
"pluginActivateDisabled.message", [action.pluginName, this._brandShortName]);
|
||||
this._buttonContainer.hidden = true;
|
||||
return;
|
||||
}
|
||||
else if (action.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) {
|
||||
let descElement = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
|
||||
descElement.textContent = gNavigatorBundle.getFormattedString(
|
||||
"pluginActivateBlocked.message", [action.pluginName, this._brandShortName]);
|
||||
this._setupLink("pluginActivate.learnMore", action.detailsLink);
|
||||
this._buttonContainer.hidden = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
button1 = {
|
||||
label: "pluginActivateNow.label",
|
||||
accesskey: "pluginActivateNow.accesskey",
|
||||
action: "_singleActivateNow"
|
||||
};
|
||||
button2 = {
|
||||
label: "pluginActivateAlways.label",
|
||||
accesskey: "pluginActivateAlways.accesskey",
|
||||
action: "_singleActivateAlways"
|
||||
};
|
||||
switch (action.blocklistState) {
|
||||
case Ci.nsIBlocklistService.STATE_NOT_BLOCKED:
|
||||
label = "pluginActivateNew.message";
|
||||
linkLabel = "pluginActivate.learnMore";
|
||||
button2.default = true;
|
||||
break;
|
||||
|
||||
case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
|
||||
label = "pluginActivateOutdated.label";
|
||||
linkLabel = "pluginActivate.updateLabel";
|
||||
button1.default = true;
|
||||
break;
|
||||
|
||||
case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
|
||||
label = "pluginActivateVulnerable.message";
|
||||
linkLabel = "pluginActivate.riskLabel"
|
||||
button1.default = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
Cu.reportError(Error("Unexpected blocklist state"));
|
||||
}
|
||||
}
|
||||
this._setupDescription(label, action.pluginName, host);
|
||||
this._setupLink(linkLabel, action.detailsLink);
|
||||
|
||||
this._primaryButton.label = gNavigatorBundle.getString(button1.label);
|
||||
this._primaryButton.accesskey = gNavigatorBundle.getString(button1.accesskey);
|
||||
this._primaryButton.setAttribute("action", button1.action);
|
||||
|
||||
this._secondaryButton.label = gNavigatorBundle.getString(button2.label);
|
||||
this._secondaryButton.accesskey = gNavigatorBundle.getString(button2.accesskey);
|
||||
this._secondaryButton.setAttribute("action", button2.action);
|
||||
if (button1.default) {
|
||||
this._primaryButton.setAttribute("default", "true");
|
||||
}
|
||||
else if (button2.default) {
|
||||
this._secondaryButton.setAttribute("default", "true");
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_setupDescription">
|
||||
<parameter name="baseString" />
|
||||
<parameter name="pluginName" /> <!-- null for the multiple-plugin case -->
|
||||
<parameter name="host" />
|
||||
<body><![CDATA[
|
||||
var bsn = this._brandShortName;
|
||||
var span = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
|
||||
while (span.lastChild) {
|
||||
span.removeChild(span.lastChild);
|
||||
}
|
||||
|
||||
if (!host) {
|
||||
host = this.notification.browser.currentURI.host;
|
||||
}
|
||||
var args = ["__host__", this._brandShortName];
|
||||
if (pluginName) {
|
||||
args.unshift(pluginName);
|
||||
}
|
||||
var bases = gNavigatorBundle.getFormattedString(baseString, args).
|
||||
split("__host__", 2);
|
||||
|
||||
span.appendChild(document.createTextNode(bases[0]));
|
||||
var hostSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em");
|
||||
hostSpan.appendChild(document.createTextNode(host));
|
||||
span.appendChild(hostSpan);
|
||||
span.appendChild(document.createTextNode(bases[1]));
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_setupLink">
|
||||
<parameter name="linkString"/>
|
||||
<parameter name="linkUrl" />
|
||||
<body><![CDATA[
|
||||
var link = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-link");
|
||||
if (!linkString || !linkUrl) {
|
||||
link.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
link.hidden = false;
|
||||
link.value = gNavigatorBundle.getString(linkString);
|
||||
link.href = linkUrl;
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_onButton">
|
||||
<parameter name="aButton" />
|
||||
<body><![CDATA[
|
||||
let methodName = aButton.getAttribute("action");
|
||||
this[methodName]();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_singleActivateNow">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
"allownow");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_singleBlock">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
"block");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_singleActivateAlways">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
"allowalways");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_multiAccept">
|
||||
<body><![CDATA[
|
||||
for (let item of this._items) {
|
||||
let action = item.action;
|
||||
if (action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED ||
|
||||
action.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) {
|
||||
continue;
|
||||
}
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
item.action, item.value);
|
||||
}
|
||||
this._cancel();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_cancel">
|
||||
<body><![CDATA[
|
||||
PopupNotifications._dismiss();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_accept">
|
||||
<parameter name="aEvent" />
|
||||
<body><![CDATA[
|
||||
if (aEvent.defaultPrevented)
|
||||
return;
|
||||
aEvent.preventDefault();
|
||||
if (this._primaryButton.getAttribute("default") == "true") {
|
||||
this._primaryButton.click();
|
||||
}
|
||||
else if (this._secondaryButton.getAttribute("default") == "true") {
|
||||
this._secondaryButton.click();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
<handlers>
|
||||
<!-- The _accept method checks for .defaultPrevented so that if focus is in a button,
|
||||
enter activates the button and not this default action -->
|
||||
<handler event="keypress" keycode="VK_ENTER" group="system" action="this._accept(event);"/>
|
||||
<handler event="keypress" keycode="VK_RETURN" group="system" action="this._accept(event);"/>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="splitmenu">
|
||||
|
@ -681,3 +681,11 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
||||
<!ENTITY mixedContentBlocked.moreinfo "Most websites will still work properly even when this content is blocked.">
|
||||
|
||||
<!ENTITY pointerLock.notification.message "Press ESC at any time to show it again.">
|
||||
|
||||
<!ENTITY pluginNotification.showAll.label "Show All">
|
||||
<!ENTITY pluginNotification.showAll.accesskey "S">
|
||||
|
||||
<!-- LOCALIZATION NOTE (pluginActivateNow.label, pluginActivateAlways.label, pluginBlockNow.label): These should be the same as the matching strings in browser.properties -->
|
||||
<!ENTITY pluginActivateNow.label "Allow Now">
|
||||
<!ENTITY pluginActivateAlways.label "Allow and Remember">
|
||||
<!ENTITY pluginBlockNow.label "Block Plugin">
|
||||
|
@ -118,6 +118,52 @@ crashedpluginsMessage.reloadButton.accesskey=R
|
||||
crashedpluginsMessage.submitButton.label=Submit a crash report
|
||||
crashedpluginsMessage.submitButton.accesskey=S
|
||||
crashedpluginsMessage.learnMore=Learn More…
|
||||
|
||||
## Plugin doorhanger strings
|
||||
# LOCALIZATION NOTE (pluginActivateNw.message): Used for newly-installed
|
||||
# plugins which are not known to be unsafe. %1$S is the plugin name and %2$S
|
||||
# is the site domain.
|
||||
pluginActivateNew.message=Allow %2$S to run "%1$S"?
|
||||
pluginActivateMultiple.message=Allow %S to run plugins?
|
||||
pluginActivate.learnMore=Learn More…
|
||||
# LOCALIZATION NOTE (pluginActivateOutdated.message, pluginActivateOutdated.label):
|
||||
# These strings are used when an unsafe plugin has an update available.
|
||||
# %1$S is the plugin name, %2$S is the domain, and %3$S is brandShortName.
|
||||
pluginActivateOutdated.message=%3$S has prevented the outdated plugin "%1$S" from running on %2$S.
|
||||
pluginActivateOutdated.label=Outdated plugin
|
||||
pluginActivate.updateLabel=Update now…
|
||||
# LOCALIZATION NOTE (pluginActivateVulnerable.message, pluginActivateVulnerable.label):
|
||||
# These strings are used when an unsafe plugin has no update available.
|
||||
# %1$S is the plugin name, %2$S is the domain, and %3$S is brandShortName.
|
||||
pluginActivateVulnerable.message=%3$S has prevented the unsafe plugin "%1$S" from running on %2$S.
|
||||
pluginActivateVulnerable.label=Vulnerable plugin!
|
||||
pluginActivate.riskLabel=What's the risk?
|
||||
# LOCALIZATION NOTE (pluginActivateBlocked.message): %1$S is the plugin name, %2$S is brandShortName
|
||||
pluginActivateBlocked.message=%2$S has blocked "%1$S" for your protection.
|
||||
pluginActivateBlocked.label=Blocked for your protection
|
||||
pluginActivateDisabled.message="%S" is disabled.
|
||||
pluginActivateDisabled.label=Disabled
|
||||
pluginActivateDisabled.manage=Manage plugins…
|
||||
pluginEnabled.message="%S" is enabled on %S.
|
||||
pluginEnabledOutdated.message=Outdated plugin "%S" is enabled on %S.
|
||||
pluginEnabledVulnerable.message=Insecure plugin "%S" is enabled on %S.
|
||||
|
||||
# LOCALIZATION NOTE (pluginActivateNow.label, pluginActivateAlways.label, pluginBlockNow.label): These should be the same as the matching strings in browser.dtd
|
||||
# LOCALIZATION NOTE (pluginActivateNow.label): This button will enable the
|
||||
# plugin in the current session for an short time (about an hour), auto-renewed
|
||||
# if the site keeps using the plugin.
|
||||
pluginActivateNow.label=Allow Now
|
||||
pluginActivateNow.accesskey=N
|
||||
# LOCALIZATION NOTE (pluginActivateAlways.label): This button will enable the
|
||||
# plugin for a long while (90 days), auto-renewed if the site keeps using the
|
||||
# plugin.
|
||||
pluginActivateAlways.label=Allow and Remember
|
||||
pluginActivateAlways.accesskey=R
|
||||
pluginBlockNow.label=Block Plugin
|
||||
pluginBlockNow.accesskey=B
|
||||
pluginContinue.label=Continue Allowing
|
||||
pluginContinue.accesskey=C
|
||||
|
||||
activatePluginsMessage.message=Would you like to activate the plugins on this page?
|
||||
activateAllPluginsMessage.label=Activate All Plugins
|
||||
activatePluginsMessage.accesskey=A
|
||||
|
@ -2246,7 +2246,7 @@ chatbox {
|
||||
border-top: 1px solid hsla(0,0%,100%,.2);
|
||||
-moz-border-start: 1px solid hsla(0,0%,100%,.2);
|
||||
margin: 0px;
|
||||
padding: 15px 11px 14px 11px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.center-item-box {
|
||||
|
@ -3912,7 +3912,7 @@ panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .
|
||||
border-top: 1px solid hsla(0,0%,100%,.2);
|
||||
-moz-border-start: 1px solid hsla(0,0%,100%,.2);
|
||||
margin: 0px;
|
||||
padding: 16px 16px 17px 16px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.center-item-box {
|
||||
|
@ -3037,7 +3037,7 @@ chatbox {
|
||||
border-top: 1px solid hsla(0,0%,100%,.2);
|
||||
-moz-border-start: 1px solid hsla(0,0%,100%,.2);
|
||||
margin: 0px;
|
||||
padding: 16px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.center-item-box {
|
||||
|
@ -1855,6 +1855,13 @@ pref("plugins.click_to_play", false);
|
||||
// The default value for nsIPluginTag.enabledState (STATE_ENABLED = 2)
|
||||
pref("plugin.default.state", 2);
|
||||
|
||||
// How long in minutes we will allow a plugin to work after the user has chosen
|
||||
// to allow it "now"
|
||||
pref("plugin.sessionPermissionNow.intervalInMinutes", 60);
|
||||
// How long in days we will allow a plugin to work after the user has chosen
|
||||
// to allow it persistently.
|
||||
pref("plugin.persistentPermissionAlways.intervalInDays", 90);
|
||||
|
||||
#ifndef DEBUG
|
||||
// How long a plugin is allowed to process a synchronous IPC message
|
||||
// before we consider it "hung".
|
||||
|
Loading…
Reference in New Issue
Block a user