summaryrefslogtreecommitdiffstats
path: root/mobile/android/chrome/content/PluginHelper.js
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/chrome/content/PluginHelper.js')
-rw-r--r--mobile/android/chrome/content/PluginHelper.js221
1 files changed, 221 insertions, 0 deletions
diff --git a/mobile/android/chrome/content/PluginHelper.js b/mobile/android/chrome/content/PluginHelper.js
new file mode 100644
index 000000000..59d87fa7c
--- /dev/null
+++ b/mobile/android/chrome/content/PluginHelper.js
@@ -0,0 +1,221 @@
+/* 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/. */
+"use strict";
+
+var PluginHelper = {
+ showDoorHanger: function(aTab) {
+ if (!aTab.browser)
+ return;
+
+ // Even though we may not end up showing a doorhanger, this flag
+ // lets us know that we've tried to show a doorhanger.
+ aTab.shouldShowPluginDoorhanger = false;
+
+ let uri = aTab.browser.currentURI;
+
+ // If the user has previously set a plugins permission for this website,
+ // either play or don't play the plugins instead of showing a doorhanger.
+ let permValue = Services.perms.testPermission(uri, "plugins");
+ if (permValue != Services.perms.UNKNOWN_ACTION) {
+ if (permValue == Services.perms.ALLOW_ACTION)
+ PluginHelper.playAllPlugins(aTab.browser.contentWindow);
+
+ return;
+ }
+
+ let message = Strings.browser.formatStringFromName("clickToPlayPlugins.message2",
+ [uri.host], 1);
+ let buttons = [
+ {
+ label: Strings.browser.GetStringFromName("clickToPlayPlugins.dontActivate"),
+ callback: function(aChecked) {
+ // If the user checked "Don't ask again", make a permanent exception
+ if (aChecked)
+ Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.DENY_ACTION);
+
+ // Other than that, do nothing
+ }
+ },
+ {
+ label: Strings.browser.GetStringFromName("clickToPlayPlugins.activate"),
+ callback: function(aChecked) {
+ // If the user checked "Don't ask again", make a permanent exception
+ if (aChecked)
+ Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.ALLOW_ACTION);
+
+ PluginHelper.playAllPlugins(aTab.browser.contentWindow);
+ },
+ positive: true
+ }
+ ];
+
+ // Add a checkbox with a "Don't ask again" message if the uri contains a
+ // host. Adding a permanent exception will fail if host is not present.
+ let options = uri.host ? { checkbox: Strings.browser.GetStringFromName("clickToPlayPlugins.dontAskAgain") } : {};
+
+ NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id, options);
+ },
+
+ delayAndShowDoorHanger: function(aTab) {
+ // To avoid showing the doorhanger if there are also visible plugin
+ // overlays on the page, delay showing the doorhanger to check if
+ // visible plugins get added in the near future.
+ if (!aTab.pluginDoorhangerTimeout) {
+ aTab.pluginDoorhangerTimeout = setTimeout(function() {
+ if (this.shouldShowPluginDoorhanger) {
+ PluginHelper.showDoorHanger(this);
+ }
+ }.bind(aTab), 500);
+ }
+ },
+
+ playAllPlugins: function(aContentWindow) {
+ let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ // XXX not sure if we should enable plugins for the parent documents...
+ let plugins = cwu.plugins;
+ if (!plugins || !plugins.length)
+ return;
+
+ plugins.forEach(this.playPlugin);
+ },
+
+ playPlugin: function(plugin) {
+ let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+ if (!objLoadingContent.activated)
+ objLoadingContent.playPlugin();
+ },
+
+ getPluginPreference: function getPluginPreference() {
+ let pluginDisable = Services.prefs.getBoolPref("plugin.disable");
+ if (pluginDisable)
+ return "0";
+
+ let state = Services.prefs.getIntPref("plugin.default.state");
+ return state == Ci.nsIPluginTag.STATE_CLICKTOPLAY ? "2" : "1";
+ },
+
+ setPluginPreference: function setPluginPreference(aValue) {
+ switch (aValue) {
+ case "0": // Enable Plugins = No
+ Services.prefs.setBoolPref("plugin.disable", true);
+ Services.prefs.clearUserPref("plugin.default.state");
+ break;
+ case "1": // Enable Plugins = Yes
+ Services.prefs.clearUserPref("plugin.disable");
+ Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_ENABLED);
+ break;
+ case "2": // Enable Plugins = Tap to Play (default)
+ Services.prefs.clearUserPref("plugin.disable");
+ Services.prefs.clearUserPref("plugin.default.state");
+ break;
+ }
+ },
+
+ // Copied from /browser/base/content/browser.js
+ 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.
+ let overflows = (overlay.scrollWidth > pluginRect.width) ||
+ (overlay.scrollHeight - 5 > pluginRect.height);
+
+ return overflows;
+ },
+
+ getPluginMimeType: function (plugin) {
+ var tagMimetype = plugin.actualType;
+
+ if (tagMimetype == "") {
+ tagMimetype = plugin.type;
+ }
+
+ return tagMimetype;
+ },
+
+ handlePluginBindingAttached: function (aTab, aEvent) {
+ let plugin = aEvent.target;
+ let doc = plugin.ownerDocument;
+ let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
+ if (!overlay || overlay._bindingHandled) {
+ return;
+ }
+ overlay._bindingHandled = true;
+
+ let eventType = PluginHelper._getBindingType(plugin);
+ if (!eventType) {
+ // Not all bindings have handlers
+ return;
+ }
+
+ switch (eventType) {
+ case "PluginClickToPlay": {
+ // Check if plugins have already been activated for this page, or if
+ // the user has set a permission to always play plugins on the site
+ if (aTab.clickToPlayPluginsActivated ||
+ Services.perms.testPermission(aTab.browser.currentURI, "plugins") ==
+ Services.perms.ALLOW_ACTION) {
+ PluginHelper.playPlugin(plugin);
+ return;
+ }
+
+ // If the plugin is hidden, or if the overlay is too small, show a
+ // doorhanger notification
+ if (PluginHelper.isTooSmall(plugin, overlay)) {
+ PluginHelper.delayAndShowDoorHanger(aTab);
+ } else {
+ // There's a large enough visible overlay that we don't need to show
+ // the doorhanger.
+ aTab.shouldShowPluginDoorhanger = false;
+ overlay.classList.add("visible");
+ }
+
+ // Add click to play listener to the overlay
+ overlay.addEventListener("click", function(e) {
+ if (!e.isTrusted)
+ return;
+ e.preventDefault();
+ let win = e.target.ownerDocument.defaultView.top;
+ let tab = BrowserApp.getTabForWindow(win);
+ tab.clickToPlayPluginsActivated = true;
+ PluginHelper.playAllPlugins(win);
+
+ NativeWindow.doorhanger.hide("ask-to-play-plugins", tab.id);
+ }, true);
+
+ // Add handlers for over- and underflow in case the plugin gets resized
+ plugin.addEventListener("overflow", function(event) {
+ overlay.classList.remove("visible");
+ PluginHelper.delayAndShowDoorHanger(aTab);
+ });
+ plugin.addEventListener("underflow", function(event) {
+ // This is also triggered if only one dimension underflows,
+ // the other dimension might still overflow
+ if (!PluginHelper.isTooSmall(plugin, overlay)) {
+ overlay.classList.add("visible");
+ }
+ });
+
+ break;
+ }
+ }
+ },
+
+ // 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_CLICK_TO_PLAY:
+ return "PluginClickToPlay";
+ default:
+ // Not all states map to a handler
+ return null;
+ }
+ }
+};