mobile/android/chrome/content/PluginHelper.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 "use strict";
     6 var PluginHelper = {
     7   showDoorHanger: function(aTab) {
     8     if (!aTab.browser)
     9       return;
    11     // Even though we may not end up showing a doorhanger, this flag
    12     // lets us know that we've tried to show a doorhanger.
    13     aTab.shouldShowPluginDoorhanger = false;
    15     let uri = aTab.browser.currentURI;
    17     // If the user has previously set a plugins permission for this website,
    18     // either play or don't play the plugins instead of showing a doorhanger.
    19     let permValue = Services.perms.testPermission(uri, "plugins");
    20     if (permValue != Services.perms.UNKNOWN_ACTION) {
    21       if (permValue == Services.perms.ALLOW_ACTION)
    22         PluginHelper.playAllPlugins(aTab.browser.contentWindow);
    24       return;
    25     }
    27     let message = Strings.browser.formatStringFromName("clickToPlayPlugins.message2",
    28                                                        [uri.host], 1);
    29     let buttons = [
    30       {
    31         label: Strings.browser.GetStringFromName("clickToPlayPlugins.activate"),
    32         callback: function(aChecked) {
    33           // If the user checked "Don't ask again", make a permanent exception
    34           if (aChecked)
    35             Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.ALLOW_ACTION);
    37           PluginHelper.playAllPlugins(aTab.browser.contentWindow);
    38         }
    39       },
    40       {
    41         label: Strings.browser.GetStringFromName("clickToPlayPlugins.dontActivate"),
    42         callback: function(aChecked) {
    43           // If the user checked "Don't ask again", make a permanent exception
    44           if (aChecked)
    45             Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.DENY_ACTION);
    47           // Other than that, do nothing
    48         }
    49       }
    50     ];
    52     // Add a checkbox with a "Don't ask again" message if the uri contains a
    53     // host. Adding a permanent exception will fail if host is not present.
    54     let options = uri.host ? { checkbox: Strings.browser.GetStringFromName("clickToPlayPlugins.dontAskAgain") } : {};
    56     NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id, options);
    57   },
    59   delayAndShowDoorHanger: function(aTab) {
    60     // To avoid showing the doorhanger if there are also visible plugin
    61     // overlays on the page, delay showing the doorhanger to check if
    62     // visible plugins get added in the near future.
    63     if (!aTab.pluginDoorhangerTimeout) {
    64       aTab.pluginDoorhangerTimeout = setTimeout(function() {
    65         if (this.shouldShowPluginDoorhanger) {
    66           PluginHelper.showDoorHanger(this);
    67         }
    68       }.bind(aTab), 500);
    69     }
    70   },
    72   playAllPlugins: function(aContentWindow) {
    73     let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
    74                             .getInterface(Ci.nsIDOMWindowUtils);
    75     // XXX not sure if we should enable plugins for the parent documents...
    76     let plugins = cwu.plugins;
    77     if (!plugins || !plugins.length)
    78       return;
    80     plugins.forEach(this.playPlugin);
    81   },
    83   playPlugin: function(plugin) {
    84     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
    85     if (!objLoadingContent.activated)
    86       objLoadingContent.playPlugin();
    87   },
    89   stopPlayPreview: function(plugin, playPlugin) {
    90     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
    91     if (objLoadingContent.activated)
    92       return;
    94     if (playPlugin)
    95       objLoadingContent.playPlugin();
    96     else
    97       objLoadingContent.cancelPlayPreview();
    98   },
   100   getPluginPreference: function getPluginPreference() {
   101     let pluginDisable = Services.prefs.getBoolPref("plugin.disable");
   102     if (pluginDisable)
   103       return "0";
   105     let state = Services.prefs.getIntPref("plugin.default.state");
   106     return state == Ci.nsIPluginTag.STATE_CLICKTOPLAY ? "2" : "1";
   107   },
   109   setPluginPreference: function setPluginPreference(aValue) {
   110     switch (aValue) {
   111       case "0": // Enable Plugins = No
   112         Services.prefs.setBoolPref("plugin.disable", true);
   113         Services.prefs.clearUserPref("plugin.default.state");
   114         break;
   115       case "1": // Enable Plugins = Yes
   116         Services.prefs.clearUserPref("plugin.disable");
   117         Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_ENABLED);
   118         break;
   119       case "2": // Enable Plugins = Tap to Play (default)
   120         Services.prefs.clearUserPref("plugin.disable");
   121         Services.prefs.clearUserPref("plugin.default.state");
   122         break;
   123     }
   124   },
   126   // Copied from /browser/base/content/browser.js
   127   isTooSmall : function (plugin, overlay) {
   128     // Is the <object>'s size too small to hold what we want to show?
   129     let pluginRect = plugin.getBoundingClientRect();
   130     // XXX bug 446693. The text-shadow on the submitted-report text at
   131     //     the bottom causes scrollHeight to be larger than it should be.
   132     let overflows = (overlay.scrollWidth > pluginRect.width) ||
   133                     (overlay.scrollHeight - 5 > pluginRect.height);
   135     return overflows;
   136   },
   138   getPluginMimeType: function (plugin) {
   139     var tagMimetype = plugin.actualType;
   141     if (tagMimetype == "") {
   142       tagMimetype = plugin.type;
   143     }
   145     return tagMimetype;
   146   },
   148   handlePluginBindingAttached: function (aTab, aEvent) {
   149     let plugin = aEvent.target;
   150     let doc = plugin.ownerDocument;
   151     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
   152     if (!overlay || overlay._bindingHandled) {
   153       return;
   154     }
   155     overlay._bindingHandled = true;
   157     let eventType = PluginHelper._getBindingType(plugin);
   158     if (!eventType) {
   159       // Not all bindings have handlers
   160       return;
   161     }
   163     switch  (eventType) {
   164       case "PluginClickToPlay": {
   165         // Check if plugins have already been activated for this page, or if
   166         // the user has set a permission to always play plugins on the site
   167         if (aTab.clickToPlayPluginsActivated ||
   168             Services.perms.testPermission(aTab.browser.currentURI, "plugins") ==
   169             Services.perms.ALLOW_ACTION) {
   170           PluginHelper.playPlugin(plugin);
   171           return;
   172         }
   174         // If the plugin is hidden, or if the overlay is too small, show a 
   175         // doorhanger notification
   176         if (PluginHelper.isTooSmall(plugin, overlay)) {
   177           PluginHelper.delayAndShowDoorHanger(aTab);
   178         } else {
   179           // There's a large enough visible overlay that we don't need to show
   180           // the doorhanger.
   181           aTab.shouldShowPluginDoorhanger = false;
   182           overlay.classList.add("visible");
   183         }
   185         // Add click to play listener to the overlay
   186         overlay.addEventListener("click", function(e) {
   187           if (!e.isTrusted)
   188             return;
   189           e.preventDefault();
   190           let win = e.target.ownerDocument.defaultView.top;
   191           let tab = BrowserApp.getTabForWindow(win);
   192           tab.clickToPlayPluginsActivated = true;
   193           PluginHelper.playAllPlugins(win);
   195           NativeWindow.doorhanger.hide("ask-to-play-plugins", tab.id);
   196         }, true);
   198         // Add handlers for over- and underflow in case the plugin gets resized
   199         plugin.addEventListener("overflow", function(event) {
   200           overlay.classList.remove("visible");
   201           PluginHelper.delayAndShowDoorHanger(aTab);
   202         });
   203         plugin.addEventListener("underflow", function(event) {
   204           // This is also triggered if only one dimension underflows,
   205           // the other dimension might still overflow
   206           if (!PluginHelper.isTooSmall(plugin, overlay)) {
   207             overlay.classList.add("visible");
   208           }
   209         });
   211         break;
   212       }
   214       case "PluginPlayPreview": {
   215         let previewContent = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
   216         let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
   217         let mimeType = PluginHelper.getPluginMimeType(plugin);
   218         let playPreviewInfo = pluginHost.getPlayPreviewInfo(mimeType);
   220         if (!playPreviewInfo.ignoreCTP) {
   221           // Check if plugins have already been activated for this page, or if
   222           // the user has set a permission to always play plugins on the site
   223           if (aTab.clickToPlayPluginsActivated ||
   224               Services.perms.testPermission(aTab.browser.currentURI, "plugins") ==
   225               Services.perms.ALLOW_ACTION) {
   226             PluginHelper.playPlugin(plugin);
   227             return;
   228           }
   230           // Always show door hanger for play preview plugins
   231           PluginHelper.delayAndShowDoorHanger(aTab);
   232         }
   234         let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
   235         if (!iframe) {
   236           // lazy initialization of the iframe
   237           iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
   238           iframe.className = "previewPluginContentFrame";
   239           previewContent.appendChild(iframe);
   240         }
   241         iframe.src = playPreviewInfo.redirectURL;
   243         // MozPlayPlugin event can be dispatched from the extension chrome
   244         // code to replace the preview content with the native plugin
   245         previewContent.addEventListener("MozPlayPlugin", function playPluginHandler(e) {
   246           if (!e.isTrusted)
   247             return;
   249           previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
   251           let playPlugin = !aEvent.detail;
   252           PluginHelper.stopPlayPreview(plugin, playPlugin);
   254           // cleaning up: removes overlay iframe from the DOM
   255           let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
   256           if (iframe)
   257             previewContent.removeChild(iframe);
   258         }, true);
   259         break;
   260       }
   262       case "PluginNotFound": {
   263         // On devices where we don't support Flash, there will be a
   264         // "Learn More..." link in the missing plugin error message.
   265         let learnMoreLink = doc.getAnonymousElementByAttribute(plugin, "class", "unsupportedLearnMoreLink");
   266         let learnMoreUrl = Services.urlFormatter.formatURLPref("app.support.baseURL");
   267         learnMoreUrl += "mobile-flash-unsupported";
   268         learnMoreLink.href = learnMoreUrl;
   269         overlay.classList.add("visible");
   270         break;
   271       }
   272     }
   273   },
   275   // Helper to get the binding handler type from a plugin object
   276   _getBindingType: function(plugin) {
   277     if (!(plugin instanceof Ci.nsIObjectLoadingContent))
   278       return null;
   280     switch (plugin.pluginFallbackType) {
   281       case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED:
   282         return "PluginNotFound";
   283       case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
   284         return "PluginClickToPlay";
   285       case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
   286         return "PluginPlayPreview";
   287       default:
   288         // Not all states map to a handler
   289         return null;
   290     }
   291   }
   292 };

mercurial