diff options
author | Thomas Groman <tgroman@nuegia.net> | 2020-04-20 20:49:37 -0700 |
---|---|---|
committer | Thomas Groman <tgroman@nuegia.net> | 2020-04-20 20:49:37 -0700 |
commit | f9cab004186edb425a9b88ad649726605080a17c (patch) | |
tree | e2dae51d3144e83d097a12e7a1499e3ea93f90be /base/content/browser-plugins.js | |
parent | f428692de8b59ab89a66502c079e1823dfda8aeb (diff) | |
download | webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.gz webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.lz webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.xz webbrowser-f9cab004186edb425a9b88ad649726605080a17c.zip |
move browser to webbrowser/
Diffstat (limited to 'base/content/browser-plugins.js')
-rw-r--r-- | base/content/browser-plugins.js | 781 |
1 files changed, 0 insertions, 781 deletions
diff --git a/base/content/browser-plugins.js b/base/content/browser-plugins.js deleted file mode 100644 index 8382682..0000000 --- a/base/content/browser-plugins.js +++ /dev/null @@ -1,781 +0,0 @@ -# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -const kPrefSessionPersistMinutes = "plugin.sessionPermissionNow.intervalInMinutes"; -const kPrefPersistentDays = "plugin.persistentPermissionAlways.intervalInDays"; - -var gPluginHandler = { - PLUGIN_SCRIPTED_STATE_NONE: 0, - PLUGIN_SCRIPTED_STATE_FIRED: 1, - PLUGIN_SCRIPTED_STATE_DONE: 2, - - getPluginUI: function (plugin, anonid) { - return plugin.ownerDocument. - getAnonymousElementByAttribute(plugin, "anonid", anonid); - }, - - _getPluginInfo: function (pluginElement) { - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - pluginElement.QueryInterface(Ci.nsIObjectLoadingContent); - - let tagMimetype; - 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 { - tagMimetype = pluginElement.actualType; - - if (tagMimetype == "") { - tagMimetype = pluginElement.type; - } - } - - 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, - pluginName: pluginName, - pluginTag: pluginTag, - permissionString: permissionString, - fallbackType: fallbackType, - blocklistState: blocklistState, - }; - }, - - // Map the plugin's name to a filtered version more suitable for user UI. - makeNicePluginName : function (aName) { - if (aName == "Shockwave Flash") - return "Adobe Flash"; - - // Clean up the plugin name by stripping off any trailing version numbers - // or "plugin". EG, "Foo Bar Plugin 1.23_02" --> "Foo Bar" - // Do this by first stripping the numbers, etc. off the end, and then - // removing "Plugin" (and then trimming to get rid of any whitespace). - // (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled) - let newName = aName.replace(/[\s\d\.\-\_\(\)]+$/, "").replace(/\bplug-?in\b/i, "").trim(); - return newName; - }, - - isTooSmall : function (plugin, overlay) { - // Is the <object>'s size too small to hold what we want to show? - let pluginRect = plugin.getBoundingClientRect(); - // XXX bug 446693. The text-shadow on the submitted-report text at - // the bottom causes scrollHeight to be larger than it should be. - // Clamp width/height to properly show CTP overlay on different - // zoom levels when embedded in iframes (rounding bug). (Bug 972237) - let overflows = (overlay.scrollWidth > Math.ceil(pluginRect.width)) || - (overlay.scrollHeight - 5 > Math.ceil(pluginRect.height)); - return overflows; - }, - - addLinkClickCallback: function (linkNode, callbackName /*callbackArgs...*/) { - // XXX just doing (callback)(arg) was giving a same-origin error. bug? - let self = this; - let callbackArgs = Array.prototype.slice.call(arguments).slice(2); - linkNode.addEventListener("click", - function(evt) { - if (!evt.isTrusted) - return; - evt.preventDefault(); - if (callbackArgs.length == 0) - callbackArgs = [ evt ]; - (self[callbackName]).apply(self, callbackArgs); - }, - true); - - linkNode.addEventListener("keydown", - function(evt) { - if (!evt.isTrusted) - return; - if (evt.keyCode == evt.DOM_VK_RETURN) { - evt.preventDefault(); - if (callbackArgs.length == 0) - callbackArgs = [ evt ]; - evt.preventDefault(); - (self[callbackName]).apply(self, callbackArgs); - } - }, - true); - }, - - // Helper to get the binding handler type from a plugin object - _getBindingType : function(plugin) { - if (!(plugin instanceof Ci.nsIObjectLoadingContent)) - return null; - - switch (plugin.pluginFallbackType) { - case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED: - return "PluginNotFound"; - case Ci.nsIObjectLoadingContent.PLUGIN_DISABLED: - return "PluginDisabled"; - case Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED: - return "PluginBlocklisted"; - case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED: - return "PluginOutdated"; - case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY: - return "PluginClickToPlay"; - case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE: - return "PluginVulnerableUpdatable"; - case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE: - return "PluginVulnerableNoUpdate"; - case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW: - return "PluginPlayPreview"; - default: - // Not all states map to a handler - return null; - } - }, - - handleEvent : function(event) { - let plugin; - let doc; - - let eventType = event.type; - if (eventType === "PluginRemoved") { - doc = event.target; - } - else { - plugin = event.target; - doc = plugin.ownerDocument; - - if (!(plugin instanceof Ci.nsIObjectLoadingContent)) - return; - } - - if (eventType == "PluginBindingAttached") { - // The plugin binding fires this event when it is created. - // As an untrusted event, ensure that this object actually has a binding - // and make sure we don't handle it twice - let overlay = this.getPluginUI(plugin, "main"); - if (!overlay || overlay._bindingHandled) { - return; - } - overlay._bindingHandled = true; - - // Lookup the handler for this binding - eventType = this._getBindingType(plugin); - if (!eventType) { - // Not all bindings have handlers - return; - } - } - - let shouldShowNotification = false; - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - if (!browser) - return; - - switch (eventType) { - case "PluginCrashed": - this.pluginInstanceCrashed(plugin, event); - break; - - case "PluginNotFound": - /* No action (plugin finder obsolete) */ - break; - - case "PluginBlocklisted": - case "PluginOutdated": - shouldShowNotification = true; - break; - - case "PluginVulnerableUpdatable": - let updateLink = this.getPluginUI(plugin, "checkForUpdatesLink"); - this.addLinkClickCallback(updateLink, "openPluginUpdatePage"); - /* FALLTHRU */ - - case "PluginVulnerableNoUpdate": - case "PluginClickToPlay": - this._handleClickToPlayEvent(plugin); - let overlay = this.getPluginUI(plugin, "main"); - let pluginName = this._getPluginInfo(plugin).pluginName; - let messageString = gNavigatorBundle.getFormattedString("PluginClickToActivate", [pluginName]); - let overlayText = this.getPluginUI(plugin, "clickToPlay"); - overlayText.textContent = messageString; - if (eventType == "PluginVulnerableUpdatable" || - eventType == "PluginVulnerableNoUpdate") { - let vulnerabilityString = gNavigatorBundle.getString(eventType); - let vulnerabilityText = this.getPluginUI(plugin, "vulnerabilityStatus"); - vulnerabilityText.textContent = vulnerabilityString; - } - shouldShowNotification = true; - break; - - case "PluginPlayPreview": - this._handlePlayPreviewEvent(plugin); - break; - - case "PluginDisabled": - let manageLink = this.getPluginUI(plugin, "managePluginsLink"); - this.addLinkClickCallback(manageLink, "managePlugins"); - shouldShowNotification = true; - break; - - case "PluginInstantiated": - //Pale Moon: don't show the indicator when plugins are enabled/allowed - if (gPrefService.getBoolPref("plugins.always_show_indicator")) { - shouldShowNotification = true; - } - break; - case "PluginRemoved": - shouldShowNotification = true; - break; - } - - // Show the in-content UI if it's not too big. The crashed plugin handler already did this. - if (eventType != "PluginCrashed" && eventType != "PluginRemoved") { - let overlay = this.getPluginUI(plugin, "main"); - if (overlay != null) { - if (!this.isTooSmall(plugin, overlay)) { - overlay.style.visibility = "visible"; - } - plugin.addEventListener("overflow", function(event) { - overlay.style.visibility = "hidden"; - }); - plugin.addEventListener("underflow", function(event) { - // this is triggered if only one dimension underflows, - // the other dimension might still overflow - if (!gPluginHandler.isTooSmall(plugin, overlay)) { - overlay.style.visibility = "visible"; - } - }); - } - } - - // Only show the notification after we've done the isTooSmall check, so - // that the notification can decide whether to show the "alert" icon - if (shouldShowNotification) { - this._showClickToPlayNotification(browser); - } - }, - - isKnownPlugin: function PH_isKnownPlugin(objLoadingContent) { - return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) == - Ci.nsIObjectLoadingContent.TYPE_PLUGIN); - }, - - canActivatePlugin: function PH_canActivatePlugin(objLoadingContent) { - // if this isn't a known plugin, we can't activate it - // (this also guards pluginHost.getPermissionStringForType against - // unexpected input) - if (!gPluginHandler.isKnownPlugin(objLoadingContent)) - return false; - - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType); - let principal = objLoadingContent.ownerDocument.defaultView.top.document.nodePrincipal; - let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString); - - let isFallbackTypeValid = - objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY && - objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE; - - if (objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW) { - // checking if play preview is subject to CTP rules - let playPreviewInfo = pluginHost.getPlayPreviewInfo(objLoadingContent.actualType); - isFallbackTypeValid = !playPreviewInfo.ignoreCTP; - } - - return !objLoadingContent.activated && - pluginPermission != Ci.nsIPermissionManager.DENY_ACTION && - isFallbackTypeValid; - }, - - hideClickToPlayOverlay: function(aPlugin) { - let overlay = this.getPluginUI(aPlugin, "main"); - if (overlay) - overlay.style.visibility = "hidden"; - }, - - stopPlayPreview: function PH_stopPlayPreview(aPlugin, aPlayPlugin) { - let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent); - if (objLoadingContent.activated) - return; - - if (aPlayPlugin) - objLoadingContent.playPlugin(); - else - objLoadingContent.cancelPlayPreview(); - }, - - // Callback for user clicking on a disabled plugin - managePlugins: function (aEvent) { - BrowserOpenAddonsMgr("addons://list/plugin"); - }, - - // Callback for user clicking on the link in a click-to-play plugin - // (where the plugin has an update) - openPluginUpdatePage: function (aEvent) { - openURL(Services.urlFormatter.formatURLPref("plugins.update.url")); - }, - - // Callback for user clicking a "reload page" link - reloadPage: function (browser) { - browser.reload(); - }, - - // Callback for user clicking the help icon - openHelpPage: function () { - openHelpLink("plugin-crashed", false); - }, - - // Event listener for click-to-play plugins. - _handleClickToPlayEvent: function PH_handleClickToPlayEvent(aPlugin) { - let doc = aPlugin.ownerDocument; - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent); - // guard against giving pluginHost.getPermissionStringForType a type - // not associated with any known plugin - if (!gPluginHandler.isKnownPlugin(objLoadingContent)) - return; - let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType); - let principal = doc.defaultView.top.document.nodePrincipal; - let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString); - - let overlay = this.getPluginUI(aPlugin, "main"); - - if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION) { - if (overlay) - overlay.style.visibility = "hidden"; - return; - } - - if (overlay) { - overlay.addEventListener("click", gPluginHandler._overlayClickListener, true); - let closeIcon = gPluginHandler.getPluginUI(aPlugin, "closeIcon"); - closeIcon.addEventListener("click", function(aEvent) { - if (aEvent.button == 0 && aEvent.isTrusted) - gPluginHandler.hideClickToPlayOverlay(aPlugin); - }, true); - } - }, - - _overlayClickListener: { - handleEvent: function PH_handleOverlayClick(aEvent) { - let plugin = document.getBindingParent(aEvent.target); - let contentWindow = plugin.ownerDocument.defaultView.top; - // gBrowser.getBrowserForDocument does not exist in the case where we - // drag-and-dropped a tab from a window containing only that tab. In - // that case, the window gets destroyed. - let browser = gBrowser.getBrowserForDocument ? - gBrowser.getBrowserForDocument(contentWindow.document) : - null; - // If browser is null here, we've been drag-and-dropped from another - // window, and this is the wrong click handler. - if (!browser) { - aEvent.target.removeEventListener("click", gPluginHandler._overlayClickListener, true); - return; - } - let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); - // Have to check that the target is not the link to update the plugin - if (!(aEvent.originalTarget instanceof HTMLAnchorElement) && - (aEvent.originalTarget.getAttribute('anonid') != 'closeIcon') && - aEvent.button == 0 && aEvent.isTrusted) { - gPluginHandler._showClickToPlayNotification(browser, plugin); - aEvent.stopPropagation(); - aEvent.preventDefault(); - } - } - }, - - _handlePlayPreviewEvent: function PH_handlePlayPreviewEvent(aPlugin) { - let doc = aPlugin.ownerDocument; - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); - let pluginInfo = this._getPluginInfo(aPlugin); - let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype); - - let previewContent = this.getPluginUI(aPlugin, "previewPluginContent"); - let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0]; - if (!iframe) { - // lazy initialization of the iframe - iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe"); - iframe.className = "previewPluginContentFrame"; - previewContent.appendChild(iframe); - - // Force a style flush, so that we ensure our binding is attached. - aPlugin.clientTop; - } - iframe.src = playPreviewInfo.redirectURL; - - // MozPlayPlugin event can be dispatched from the extension chrome - // code to replace the preview content with the native plugin - previewContent.addEventListener("MozPlayPlugin", function playPluginHandler(aEvent) { - if (!aEvent.isTrusted) - return; - - previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true); - - let playPlugin = !aEvent.detail; - gPluginHandler.stopPlayPreview(aPlugin, playPlugin); - - // cleaning up: removes overlay iframe from the DOM - let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0]; - if (iframe) - previewContent.removeChild(iframe); - }, true); - - if (!playPreviewInfo.ignoreCTP) { - gPluginHandler._showClickToPlayNotification(browser); - } - }, - - reshowClickToPlayNotification: function PH_reshowClickToPlayNotification() { - let browser = gBrowser.selectedBrowser; - let contentWindow = browser.contentWindow; - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - let doc = contentWindow.document; - let plugins = cwu.plugins; - for (let plugin of plugins) { - let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); - if (overlay) - overlay.removeEventListener("click", gPluginHandler._overlayClickListener, true); - let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); - if (gPluginHandler.canActivatePlugin(objLoadingContent)) - gPluginHandler._handleClickToPlayEvent(plugin); - } - gPluginHandler._showClickToPlayNotification(browser); - }, - - _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; - } - }, - - _makeCenterActions: function PH_makeCenterActions(notification) { - let contentWindow = notification.browser.contentWindow; - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - - let principal = contentWindow.document.nodePrincipal; - - let centerActions = []; - 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 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.pluginPermissionPrePath = permissionObj.principal.originNoSuffix; - pluginInfo.pluginPermissionType = permissionObj.expireType; - } - else { - pluginInfo.pluginPermissionPrePath = principal.originNoSuffix; - 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; - }, - - /** - * 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": - permission = Ci.nsIPermissionManager.ALLOW_ACTION; - expireType = Ci.nsIPermissionManager.EXPIRE_SESSION; - expireTime = Date.now() + Services.prefs.getIntPref(kPrefSessionPersistMinutes) * 60 * 1000; - break; - - case "allowalways": - permission = Ci.nsIPermissionManager.ALLOW_ACTION; - expireType = Ci.nsIPermissionManager.EXPIRE_TIME; - expireTime = Date.now() + - Services.prefs.getIntPref(kPrefPersistentDays) * 24 * 60 * 60 * 1000; - break; - - case "block": - permission = Ci.nsIPermissionManager.PROMPT_ACTION; - expireType = Ci.nsIPermissionManager.EXPIRE_NEVER; - expireTime = 0; - break; - - // In case a plugin has already been allowed in another tab, the "continue allowing" button - // shouldn't change any permissions but should run the plugin-enablement code below. - case "continue": - break; - - default: - Cu.reportError(Error("Unexpected plugin state: " + aNewState)); - return; - } - - let browser = aNotification.browser; - let contentWindow = browser.contentWindow; - if (aNewState != "continue") { - let principal = contentWindow.document.nodePrincipal; - Services.perms.addFromPrincipal(principal, aPluginInfo.permissionString, - permission, expireType, expireTime); - - if (aNewState == "block") { - return; - } - } - - // Manually activate the plugins that would have been automatically - // activated. - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - 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(); - } - } - }, - - _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser, aPrimaryPlugin) { - let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser); - - let contentWindow = aBrowser.contentWindow; - let contentDoc = aBrowser.contentDocument; - let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - // Pale Moon: cwu.plugins may contain non-plugin <object>s, filter them out - let plugins = cwu.plugins.filter(function(plugin) { - return (plugin.getContentTypeForMIMEType(plugin.actualType) == - Ci.nsIObjectLoadingContent.TYPE_PLUGIN); - }); - if (plugins.length == 0) { - if (notification) { - PopupNotifications.remove(notification); - } - return; - } - - let icon = 'plugins-notification-icon'; - for (let plugin of plugins) { - let fallbackType = plugin.pluginFallbackType; - if (fallbackType == plugin.PLUGIN_VULNERABLE_UPDATABLE || - fallbackType == plugin.PLUGIN_VULNERABLE_NO_UPDATE || - fallbackType == plugin.PLUGIN_BLOCKLISTED) { - icon = 'blocked-plugins-notification-icon'; - break; - } - if (fallbackType == plugin.PLUGIN_CLICK_TO_PLAY) { - let overlay = contentDoc.getAnonymousElementByAttribute(plugin, "anonid", "main"); - if (!overlay || overlay.style.visibility == 'hidden') { - icon = 'alert-plugins-notification-icon'; - } - } - } - - let dismissed = notification ? notification.dismissed : true; - if (aPrimaryPlugin) - dismissed = false; - - let primaryPluginPermission = null; - if (aPrimaryPlugin) { - primaryPluginPermission = this._getPluginInfo(aPrimaryPlugin).permissionString; - } - - let options = { - dismissed: dismissed, - eventCallback: this._clickToPlayNotificationEventCallback, - primaryPlugin: primaryPluginPermission - }; - PopupNotifications.show(aBrowser, "click-to-play-plugins", - "", icon, - null, null, options); - }, - - // Crashed-plugin observer. Notified once per plugin crash, before events - // are dispatched to individual plugin instances. - pluginCrashed : function(subject, topic, data) { - let propertyBag = subject; - if (!(propertyBag instanceof Ci.nsIPropertyBag2) || - !(propertyBag instanceof Ci.nsIWritablePropertyBag2)) - return; - }, - - // Crashed-plugin event listener. Called for every instance of a - // plugin in content. - pluginInstanceCrashed: function (plugin, aEvent) { - // Ensure the plugin and event are of the right type. - if (!(aEvent instanceof Ci.nsIDOMDataContainerEvent)) - return; - - let submittedReport = aEvent.getData("submittedCrashReport"); - let doPrompt = true; // XXX followup for .getData("doPrompt"); - let submitReports = true; // XXX followup for .getData("submitReports"); - let pluginName = aEvent.getData("pluginName"); - let pluginDumpID = aEvent.getData("pluginDumpID"); - let browserDumpID = aEvent.getData("browserDumpID"); - - // Remap the plugin name to a more user-presentable form. - pluginName = this.makeNicePluginName(pluginName); - - let messageString = gNavigatorBundle.getFormattedString("crashedpluginsMessage.title", [pluginName]); - - // - // Configure the crashed-plugin placeholder. - // - - // Force a layout flush so the binding is attached. - plugin.clientTop; - let doc = plugin.ownerDocument; - let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox"); - let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus"); - - let crashText = doc.getAnonymousElementByAttribute(plugin, "class", "msgCrashedText"); - crashText.textContent = messageString; - - let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); - - let link = doc.getAnonymousElementByAttribute(plugin, "class", "reloadLink"); - this.addLinkClickCallback(link, "reloadPage", browser); - - let notificationBox = gBrowser.getNotificationBox(browser); - - let isShowing = true; - - // Is the <object>'s size too small to hold what we want to show? - if (this.isTooSmall(plugin, overlay)) { - // First try hiding the crash report submission UI. - statusDiv.removeAttribute("status"); - - if (this.isTooSmall(plugin, overlay)) { - // Hide the overlay's contents. Use visibility style, so that it doesn't - // collapse down to 0x0. - overlay.style.visibility = "hidden"; - isShowing = false; - } - } - - if (isShowing) { - // If a previous plugin on the page was too small and resulted in adding a - // notification bar, then remove it because this plugin instance it big - // enough to serve as in-content notification. - hideNotificationBar(); - doc.mozNoPluginCrashedNotification = true; - } else { - // If another plugin on the page was large enough to show our UI, we don't - // want to show a notification bar. - if (!doc.mozNoPluginCrashedNotification) - showNotificationBar(pluginDumpID, browserDumpID); - } - - function hideNotificationBar() { - let notification = notificationBox.getNotificationWithValue("plugin-crashed"); - if (notification) - notificationBox.removeNotification(notification, true); - } - - function showNotificationBar(pluginDumpID, browserDumpID) { - // If there's already an existing notification bar, don't do anything. - let notification = notificationBox.getNotificationWithValue("plugin-crashed"); - if (notification) - return; - - // Configure the notification bar - let priority = notificationBox.PRIORITY_WARNING_MEDIUM; - let iconURL = "chrome://mozapps/skin/plugins/notifyPluginCrashed.png"; - let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label"); - let reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey"); - let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label"); - let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey"); - - let buttons = [{ - label: reloadLabel, - accessKey: reloadKey, - popup: null, - callback: function() { browser.reload(); }, - }]; - - notification = notificationBox.appendNotification(messageString, "plugin-crashed", - iconURL, priority, buttons); - - // Add the "learn more" link. - let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - let link = notification.ownerDocument.createElementNS(XULNS, "label"); - link.className = "text-link"; - link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore")); - let crashurl = formatURL("app.support.baseURL", true); - crashurl += "plugin-crashed-notificationbar"; - link.href = crashurl; - - let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText"); - description.appendChild(link); - - // Remove the notfication when the page is reloaded. - doc.defaultView.top.addEventListener("unload", function() { - notificationBox.removeNotification(notification); - }, false); - } - - } -}; |