mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 14:15:30 +00:00
293 lines
11 KiB
JavaScript
293 lines
11 KiB
JavaScript
/* 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.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);
|
|
}
|
|
},
|
|
{
|
|
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
|
|
}
|
|
}
|
|
];
|
|
|
|
// 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();
|
|
},
|
|
|
|
stopPlayPreview: function(plugin, playPlugin) {
|
|
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
|
if (objLoadingContent.activated)
|
|
return;
|
|
|
|
if (playPlugin)
|
|
objLoadingContent.playPlugin();
|
|
else
|
|
objLoadingContent.cancelPlayPreview();
|
|
},
|
|
|
|
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;
|
|
}
|
|
|
|
case "PluginPlayPreview": {
|
|
let previewContent = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
|
|
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
|
let mimeType = PluginHelper.getPluginMimeType(plugin);
|
|
let playPreviewInfo = pluginHost.getPlayPreviewInfo(mimeType);
|
|
|
|
if (!playPreviewInfo.ignoreCTP) {
|
|
// 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;
|
|
}
|
|
|
|
// Always show door hanger for play preview plugins
|
|
PluginHelper.delayAndShowDoorHanger(aTab);
|
|
}
|
|
|
|
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);
|
|
}
|
|
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(e) {
|
|
if (!e.isTrusted)
|
|
return;
|
|
|
|
previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
|
|
|
|
let playPlugin = !aEvent.detail;
|
|
PluginHelper.stopPlayPreview(plugin, playPlugin);
|
|
|
|
// cleaning up: removes overlay iframe from the DOM
|
|
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
|
if (iframe)
|
|
previewContent.removeChild(iframe);
|
|
}, true);
|
|
break;
|
|
}
|
|
|
|
case "PluginNotFound": {
|
|
// On devices where we don't support Flash, there will be a
|
|
// "Learn More..." link in the missing plugin error message.
|
|
let learnMoreLink = doc.getAnonymousElementByAttribute(plugin, "class", "unsupportedLearnMoreLink");
|
|
let learnMoreUrl = Services.urlFormatter.formatURLPref("app.support.baseURL");
|
|
learnMoreUrl += "mobile-flash-unsupported";
|
|
learnMoreLink.href = learnMoreUrl;
|
|
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";
|
|
case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
|
|
return "PluginPlayPreview";
|
|
default:
|
|
// Not all states map to a handler
|
|
return null;
|
|
}
|
|
}
|
|
};
|