mobile/android/chrome/content/PluginHelper.js

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial