mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Backed out changeset 2d9ed9032a45 (bug 1192831) for suspicion of causing bug 1178709 to spike.
This commit is contained in:
parent
1f37202f72
commit
7e078b31d6
@ -34,6 +34,7 @@ support-files =
|
||||
plugin_test.html
|
||||
plugin_test2.html
|
||||
plugin_test3.html
|
||||
plugin_test_w_src.html
|
||||
plugin_two_types.html
|
||||
plugin_unknown.html
|
||||
plugin_crashCommentAndURL.html
|
||||
@ -75,6 +76,12 @@ skip-if = !crashreporter
|
||||
[browser_pluginCrashCommentAndURL.js]
|
||||
skip-if = !crashreporter
|
||||
[browser_pageInfo_plugins.js]
|
||||
[browser_pluginplaypreview.js]
|
||||
skip-if = e10s # bug 1148827
|
||||
[browser_pluginplaypreview2.js]
|
||||
skip-if = e10s # bug 1148827
|
||||
[browser_pluginplaypreview3.js]
|
||||
skip-if = e10s # bug 1148827
|
||||
[browser_pluginCrashReportNonDeterminism.js]
|
||||
skip-if = !crashreporter || os == 'linux' # Bug 1152811
|
||||
|
||||
|
317
browser/base/content/test/plugins/browser_pluginplaypreview.js
Normal file
317
browser/base/content/test/plugins/browser_pluginplaypreview.js
Normal file
@ -0,0 +1,317 @@
|
||||
var rootDir = getRootDirectory(gTestPath);
|
||||
const gTestRoot = rootDir;
|
||||
|
||||
var gTestBrowser = null;
|
||||
var gNextTest = null;
|
||||
var gNextTestSkip = 0;
|
||||
var gPlayPreviewPluginActualEvents = 0;
|
||||
var gPlayPreviewPluginExpectedEvents = 1;
|
||||
|
||||
var gPlayPreviewRegistration = null;
|
||||
|
||||
function registerPlayPreview(mimeType, targetUrl) {
|
||||
|
||||
function StreamConverterFactory() {}
|
||||
StreamConverterFactory.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
|
||||
_targetConstructor: null,
|
||||
|
||||
register: function register(targetConstructor) {
|
||||
this._targetConstructor = targetConstructor;
|
||||
var proto = targetConstructor.prototype;
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(proto.classID, proto.classDescription,
|
||||
proto.contractID, this);
|
||||
},
|
||||
|
||||
unregister: function unregister() {
|
||||
var proto = this._targetConstructor.prototype;
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.unregisterFactory(proto.classID, this);
|
||||
this._targetConstructor = null;
|
||||
},
|
||||
|
||||
// nsIFactory
|
||||
createInstance: function createInstance(aOuter, iid) {
|
||||
if (aOuter !== null)
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
return (new (this._targetConstructor)).QueryInterface(iid);
|
||||
},
|
||||
|
||||
// nsIFactory
|
||||
lockFactory: function lockFactory(lock) {
|
||||
// No longer used as of gecko 1.7.
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
};
|
||||
|
||||
function OverlayStreamConverter() {}
|
||||
OverlayStreamConverter.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsISupports,
|
||||
Ci.nsIStreamConverter,
|
||||
Ci.nsIStreamListener,
|
||||
Ci.nsIRequestObserver
|
||||
]),
|
||||
|
||||
classID: Components.ID('{4c6030f7-e20a-264f-0f9b-ada3a9e97384}'),
|
||||
classDescription: 'overlay-test-data Component',
|
||||
contractID: '@mozilla.org/streamconv;1?from=application/x-moz-playpreview&to=*/*',
|
||||
|
||||
// nsIStreamConverter::convert
|
||||
convert: function(aFromStream, aFromType, aToType, aCtxt) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
// nsIStreamConverter::asyncConvertData
|
||||
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
||||
var isValidRequest = false;
|
||||
try {
|
||||
var request = aCtxt;
|
||||
request.QueryInterface(Ci.nsIChannel);
|
||||
var spec = request.URI.spec;
|
||||
var expectedSpec = 'data:application/x-moz-playpreview;,' + mimeType;
|
||||
isValidRequest = (spec == expectedSpec);
|
||||
} catch (e) { }
|
||||
if (!isValidRequest)
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Store the listener passed to us
|
||||
this.listener = aListener;
|
||||
},
|
||||
|
||||
// nsIStreamListener::onDataAvailable
|
||||
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
|
||||
// Do nothing since all the data loading is handled by the viewer.
|
||||
ok(false, "onDataAvailable should not be called");
|
||||
},
|
||||
|
||||
// nsIRequestObserver::onStartRequest
|
||||
onStartRequest: function(aRequest, aContext) {
|
||||
|
||||
// Setup the request so we can use it below.
|
||||
aRequest.QueryInterface(Ci.nsIChannel);
|
||||
// Cancel the request so the viewer can handle it.
|
||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
|
||||
// Create a new channel that is viewer loaded as a resource.
|
||||
var ioService = Services.io;
|
||||
var channel = ioService.newChannel2(targetUrl,
|
||||
null,
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
channel.asyncOpen(this.listener, aContext);
|
||||
},
|
||||
|
||||
// nsIRequestObserver::onStopRequest
|
||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||
// Do nothing.
|
||||
}
|
||||
};
|
||||
|
||||
var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
ph.registerPlayPreviewMimeType(mimeType, true); // ignoring CTP rules
|
||||
|
||||
var factory = new StreamConverterFactory();
|
||||
factory.register(OverlayStreamConverter);
|
||||
|
||||
return (gPlayPreviewRegistration = {
|
||||
unregister: function() {
|
||||
ph.unregisterPlayPreviewMimeType(mimeType);
|
||||
factory.unregister();
|
||||
gPlayPreviewRegistration = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function unregisterPlayPreview() {
|
||||
gPlayPreviewRegistration.unregister();
|
||||
}
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
if (gPlayPreviewRegistration)
|
||||
gPlayPreviewRegistration.unregister();
|
||||
Services.prefs.clearUserPref("plugins.click_to_play");
|
||||
});
|
||||
|
||||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
|
||||
registerPlayPreview('application/x-test', 'about:');
|
||||
prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function handleBindingAttached(evt) {
|
||||
if (evt.target instanceof Ci.nsIObjectLoadingContent &&
|
||||
evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
|
||||
gPlayPreviewPluginActualEvents++;
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
// The plugin events are async dispatched and can come after the load event
|
||||
// This just allows the events to fire before we then go on to test the states
|
||||
|
||||
// iframe might triggers load event as well, making sure we skip some to let
|
||||
// all iframes on the page be loaded as well
|
||||
if (gNextTestSkip) {
|
||||
gNextTestSkip--;
|
||||
return;
|
||||
}
|
||||
executeSoon(gNextTest);
|
||||
}
|
||||
|
||||
function prepareTest(nextTest, url, skip) {
|
||||
gNextTest = nextTest;
|
||||
gNextTestSkip = skip;
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Tests a page with normal play preview registration (1/2)
|
||||
function test1a() {
|
||||
var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification");
|
||||
|
||||
var pluginInfo = getTestPlugin();
|
||||
ok(pluginInfo, "Should have a test plugin");
|
||||
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
|
||||
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
|
||||
ok(overlay, "Test 1a, the overlay div is expected");
|
||||
|
||||
var iframe = overlay.getElementsByClassName("previewPluginContentFrame")[0];
|
||||
ok(iframe && iframe.localName == "iframe", "Test 1a, the overlay iframe is expected");
|
||||
var iframeHref = iframe.contentWindow.location.href;
|
||||
ok(iframeHref == "about:", "Test 1a, the overlay about: content is expected");
|
||||
|
||||
var rect = iframe.getBoundingClientRect();
|
||||
ok(rect.width == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being replaced by actual plugin");
|
||||
ok(rect.height == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being replaced by actual plugin");
|
||||
|
||||
var e = overlay.ownerDocument.createEvent("CustomEvent");
|
||||
e.initCustomEvent("MozPlayPlugin", true, true, null);
|
||||
overlay.dispatchEvent(e);
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin to stop play preview");
|
||||
}
|
||||
|
||||
// Tests that activating via MozPlayPlugin through the notification works (part 2/2)
|
||||
function test1b() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
|
||||
|
||||
is(gPlayPreviewPluginActualEvents, gPlayPreviewPluginExpectedEvents,
|
||||
"There should be exactly one PluginPlayPreview event");
|
||||
|
||||
unregisterPlayPreview();
|
||||
|
||||
prepareTest(test2, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests a page with a working plugin in it -- the mime type was just unregistered.
|
||||
function test2() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 2, Plugin should be activated");
|
||||
|
||||
registerPlayPreview('application/x-unknown', 'about:');
|
||||
|
||||
prepareTest(test3, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests a page with a working plugin in it -- diffent play preview type is reserved.
|
||||
function test3() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 3, Plugin should be activated");
|
||||
|
||||
unregisterPlayPreview();
|
||||
|
||||
registerPlayPreview('application/x-test', 'about:');
|
||||
Services.prefs.setBoolPref("plugins.click_to_play", true);
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
|
||||
prepareTest(test4a, gTestRoot + "plugin_test.html", 1);
|
||||
}
|
||||
|
||||
// Test a fallback to the click-to-play
|
||||
function test4a() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 4a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 4a, Plugin should not be activated");
|
||||
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
|
||||
ok(overlay, "Test 4a, the overlay div is expected");
|
||||
|
||||
var e = overlay.ownerDocument.createEvent("CustomEvent");
|
||||
e.initCustomEvent("MozPlayPlugin", true, true, true);
|
||||
overlay.dispatchEvent(e);
|
||||
var condition = function() objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY;
|
||||
waitForCondition(condition, test4b, "Test 4a, Waited too long for plugin to stop play preview");
|
||||
}
|
||||
|
||||
function test4b() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 4b, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 4b, Plugin should not be activated");
|
||||
|
||||
prepareTest(test5a, gTestRoot + "plugin_test.html", 1);
|
||||
}
|
||||
|
||||
// Test a bypass of the click-to-play
|
||||
function test5a() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 5a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 5a, Plugin should not be activated");
|
||||
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
|
||||
ok(overlay, "Test 5a, the overlay div is expected");
|
||||
|
||||
var e = overlay.ownerDocument.createEvent("CustomEvent");
|
||||
e.initCustomEvent("MozPlayPlugin", true, true, false);
|
||||
overlay.dispatchEvent(e);
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test5b, "Test 5a, Waited too long for plugin to stop play preview");
|
||||
}
|
||||
|
||||
function test5b() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 5b, Plugin should be activated");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
171
browser/base/content/test/plugins/browser_pluginplaypreview2.js
Normal file
171
browser/base/content/test/plugins/browser_pluginplaypreview2.js
Normal file
@ -0,0 +1,171 @@
|
||||
var rootDir = getRootDirectory(gTestPath);
|
||||
const gTestRoot = rootDir;
|
||||
|
||||
var gTestBrowser = null;
|
||||
var gNextTest = null;
|
||||
var gNextTestSkip = 0;
|
||||
var gPlayPreviewPluginActualEvents = 0;
|
||||
var gPlayPreviewPluginExpectedEvents = 1;
|
||||
|
||||
var gPlayPreviewRegistration = null;
|
||||
|
||||
function registerPlayPreview(mimeType, targetUrl) {
|
||||
var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
ph.registerPlayPreviewMimeType(mimeType, false, targetUrl);
|
||||
|
||||
return (gPlayPreviewRegistration = {
|
||||
unregister: function() {
|
||||
ph.unregisterPlayPreviewMimeType(mimeType);
|
||||
gPlayPreviewRegistration = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function unregisterPlayPreview() {
|
||||
gPlayPreviewRegistration.unregister();
|
||||
}
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
if (gPlayPreviewRegistration)
|
||||
gPlayPreviewRegistration.unregister();
|
||||
Services.prefs.clearUserPref("plugins.click_to_play");
|
||||
});
|
||||
|
||||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
|
||||
Services.prefs.setBoolPref("plugins.click_to_play", true);
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
|
||||
|
||||
registerPlayPreview('application/x-test', 'about:');
|
||||
prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function handleBindingAttached(evt) {
|
||||
if (evt.target instanceof Ci.nsIObjectLoadingContent &&
|
||||
evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
|
||||
gPlayPreviewPluginActualEvents++;
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
// The plugin events are async dispatched and can come after the load event
|
||||
// This just allows the events to fire before we then go on to test the states
|
||||
|
||||
// iframe might triggers load event as well, making sure we skip some to let
|
||||
// all iframes on the page be loaded as well
|
||||
if (gNextTestSkip) {
|
||||
gNextTestSkip--;
|
||||
return;
|
||||
}
|
||||
executeSoon(gNextTest);
|
||||
}
|
||||
|
||||
function prepareTest(nextTest, url, skip) {
|
||||
gNextTest = nextTest;
|
||||
gNextTestSkip = skip;
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Tests a page with normal play preview registration (1/2)
|
||||
function test1a() {
|
||||
var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification");
|
||||
|
||||
var pluginInfo = getTestPlugin();
|
||||
ok(pluginInfo, "Should have a test plugin");
|
||||
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
|
||||
|
||||
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
|
||||
ok(overlay, "Test 1a, the overlay div is expected");
|
||||
|
||||
var iframe = overlay.getElementsByClassName("previewPluginContentFrame")[0];
|
||||
ok(iframe && iframe.localName == "iframe", "Test 1a, the overlay iframe is expected");
|
||||
var iframeHref = iframe.contentWindow.location.href;
|
||||
ok(iframeHref == "about:", "Test 1a, the overlay about: content is expected");
|
||||
|
||||
var rect = iframe.getBoundingClientRect();
|
||||
ok(rect.width == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being replaced by actual plugin");
|
||||
ok(rect.height == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being replaced by actual plugin");
|
||||
|
||||
var e = overlay.ownerDocument.createEvent("CustomEvent");
|
||||
e.initCustomEvent("MozPlayPlugin", true, true, null);
|
||||
overlay.dispatchEvent(e);
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin to stop play preview");
|
||||
}
|
||||
|
||||
// Tests that activating via MozPlayPlugin through the notification works (part 2/2)
|
||||
function test1b() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
|
||||
|
||||
is(gPlayPreviewPluginActualEvents, gPlayPreviewPluginExpectedEvents,
|
||||
"There should be exactly one PluginPlayPreview event");
|
||||
|
||||
unregisterPlayPreview();
|
||||
|
||||
prepareTest(test2, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests a page with a working plugin in it -- the mime type was just unregistered.
|
||||
function test2() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 2, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 2, Plugin should not be activated");
|
||||
|
||||
registerPlayPreview('application/x-unknown', 'about:');
|
||||
|
||||
prepareTest(test3, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests a page with a working plugin in it -- diffent play preview type is reserved.
|
||||
function test3() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 3, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 3, Plugin should not be activated");
|
||||
|
||||
unregisterPlayPreview();
|
||||
|
||||
registerPlayPreview('application/x-test', 'about:');
|
||||
Services.prefs.setBoolPref("plugins.click_to_play", false);
|
||||
var plugin = getTestPlugin();
|
||||
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||
prepareTest(test4, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests a page with a working plugin in it -- click-to-play is off
|
||||
function test4() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 4, Plugin should be activated");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
130
browser/base/content/test/plugins/browser_pluginplaypreview3.js
Normal file
130
browser/base/content/test/plugins/browser_pluginplaypreview3.js
Normal file
@ -0,0 +1,130 @@
|
||||
var rootDir = getRootDirectory(gTestPath);
|
||||
const gTestRoot = rootDir;
|
||||
|
||||
var gTestBrowser = null;
|
||||
var gNextTest = null;
|
||||
var gNextTestSkip = 0;
|
||||
|
||||
var gPlayPreviewRegistration = null;
|
||||
|
||||
var gTestPluginType = 'application/x-test';
|
||||
var gTestPluginPreviewUrl = 'about:';
|
||||
|
||||
function registerPlayPreview(whitelist) {
|
||||
var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
ph.registerPlayPreviewMimeType(gTestPluginType, true,
|
||||
gTestPluginPreviewUrl, whitelist);
|
||||
|
||||
return (gPlayPreviewRegistration = {
|
||||
unregister: function() {
|
||||
ph.unregisterPlayPreviewMimeType(gTestPluginType);
|
||||
gPlayPreviewRegistration = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function unregisterPlayPreview() {
|
||||
gPlayPreviewRegistration.unregister();
|
||||
}
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
if (gPlayPreviewRegistration) {
|
||||
gPlayPreviewRegistration.unregister();
|
||||
}
|
||||
});
|
||||
|
||||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
|
||||
|
||||
registerPlayPreview('@*plugin_test.html');
|
||||
prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
// The plugin events are async dispatched and can come after the load event
|
||||
// This just allows the events to fire before we then go on to test the states
|
||||
|
||||
// iframe might triggers load event as well, making sure we skip some to let
|
||||
// all iframes on the page be loaded as well
|
||||
if (gNextTestSkip) {
|
||||
gNextTestSkip--;
|
||||
return;
|
||||
}
|
||||
executeSoon(gNextTest);
|
||||
}
|
||||
|
||||
function prepareTest(nextTest, url, skip) {
|
||||
gNextTest = nextTest;
|
||||
gNextTestSkip = skip;
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Tests plugin on a whitelisted page.
|
||||
function test1a() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
|
||||
ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
|
||||
|
||||
unregisterPlayPreview();
|
||||
|
||||
registerPlayPreview('@*plugin_wrong.html');
|
||||
var plugin = getTestPlugin();
|
||||
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||
prepareTest(test1b, gTestRoot + "plugin_test.html");
|
||||
}
|
||||
|
||||
// Tests plugin on a non-whitelisted page.
|
||||
function test1b() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
|
||||
|
||||
unregisterPlayPreview();
|
||||
|
||||
registerPlayPreview('*browser_pluginplaypreview3.js');
|
||||
var plugin = getTestPlugin();
|
||||
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||
prepareTest(test2a, gTestRoot + "plugin_test_w_src.html");
|
||||
}
|
||||
|
||||
// Tests plugin with whitelisted src/data.
|
||||
function test2a() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 2a, Plugin should not be activated");
|
||||
|
||||
unregisterPlayPreview();
|
||||
|
||||
registerPlayPreview('*plugin_test_w_src.html');
|
||||
var plugin = getTestPlugin();
|
||||
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||
prepareTest(test2b, gTestRoot + "plugin_test_w_src.html");
|
||||
}
|
||||
|
||||
// Tests plugin with non-whitelisted src/data.
|
||||
function test2b() {
|
||||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 2b, Plugin should be activated");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
9
browser/base/content/test/plugins/plugin_test_w_src.html
Normal file
9
browser/base/content/test/plugins/plugin_test_w_src.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<embed id="test" src="browser_pluginplaypreview3.js" style="width: 200px; height: 200px" type="application/x-test">
|
||||
</body>
|
||||
</html>
|
@ -311,6 +311,8 @@ PluginContent.prototype = {
|
||||
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;
|
||||
@ -415,6 +417,10 @@ PluginContent.prototype = {
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
|
||||
case "PluginPlayPreview":
|
||||
this._handlePlayPreviewEvent(plugin);
|
||||
break;
|
||||
|
||||
case "PluginDisabled":
|
||||
let manageLink = this.getPluginUI(plugin, "managePluginsLink");
|
||||
this.addLinkClickCallback(manageLink, "forwardCallback", "managePlugins");
|
||||
@ -525,6 +531,12 @@ PluginContent.prototype = {
|
||||
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;
|
||||
@ -537,6 +549,17 @@ PluginContent.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
stopPlayPreview: function (plugin, playPlugin) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (objLoadingContent.activated)
|
||||
return;
|
||||
|
||||
if (playPlugin)
|
||||
objLoadingContent.playPlugin();
|
||||
else
|
||||
objLoadingContent.cancelPlayPreview();
|
||||
},
|
||||
|
||||
// Forward a link click callback to the chrome process.
|
||||
forwardCallback: function (name) {
|
||||
this.global.sendAsyncMessage("PluginContent:LinkClickCallback", { name: name });
|
||||
@ -618,6 +641,49 @@ PluginContent.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_handlePlayPreviewEvent: function (plugin) {
|
||||
let doc = plugin.ownerDocument;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let pluginInfo = this._getPluginInfo(plugin);
|
||||
let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype);
|
||||
|
||||
let previewContent = this.getPluginUI(plugin, "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.
|
||||
plugin.clientTop;
|
||||
}
|
||||
iframe.src = playPreviewInfo.redirectURL;
|
||||
|
||||
// MozPlayPlugin event can be dispatched from the extension chrome
|
||||
// code to replace the preview content with the native plugin
|
||||
let playPluginHandler = (event) => {
|
||||
if (!event.isTrusted)
|
||||
return;
|
||||
|
||||
previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
|
||||
|
||||
let playPlugin = !event.detail;
|
||||
this.stopPlayPreview(plugin, playPlugin);
|
||||
|
||||
// cleaning up: removes overlay iframe from the DOM
|
||||
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
||||
if (iframe)
|
||||
previewContent.removeChild(iframe);
|
||||
};
|
||||
|
||||
previewContent.addEventListener("MozPlayPlugin", playPluginHandler, true);
|
||||
|
||||
if (!playPreviewInfo.ignoreCTP) {
|
||||
this._showClickToPlayNotification(plugin, false);
|
||||
}
|
||||
},
|
||||
|
||||
reshowClickToPlayNotification: function () {
|
||||
let contentWindow = this.global.content;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
|
@ -25,7 +25,7 @@ class nsNPAPIPluginInstance;
|
||||
* interface to mirror this interface when changing it.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(2eb3195e-3eea-4083-bb1d-d2d70fa35ccb)]
|
||||
[scriptable, uuid(5efbd411-5bbe-4de1-9f3a-1c3459696eb2)]
|
||||
interface nsIObjectLoadingContent : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -65,6 +65,8 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
const unsigned long PLUGIN_VULNERABLE_UPDATABLE = 9;
|
||||
// The plugin is vulnerable (no update available)
|
||||
const unsigned long PLUGIN_VULNERABLE_NO_UPDATE = 10;
|
||||
// The plugin is in play preview mode
|
||||
const unsigned long PLUGIN_PLAY_PREVIEW = 11;
|
||||
|
||||
/**
|
||||
* The actual mime type (the one we got back from the network
|
||||
@ -126,7 +128,8 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
in boolean submittedCrashReport);
|
||||
|
||||
/**
|
||||
* This method will play a plugin that has been stopped by click-to-play.
|
||||
* This method will play a plugin that has been stopped by the
|
||||
* click-to-play plugins or play-preview features.
|
||||
*/
|
||||
void playPlugin();
|
||||
|
||||
@ -141,7 +144,7 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
/**
|
||||
* This attribute will return true if the current content type has been
|
||||
* activated, either explicitly or by passing checks that would have it be
|
||||
* click-to-play.
|
||||
* click-to-play or play-preview.
|
||||
*/
|
||||
readonly attribute boolean activated;
|
||||
|
||||
@ -181,6 +184,11 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
readonly attribute bool hasRunningPlugin;
|
||||
|
||||
/**
|
||||
* This method will disable the play-preview plugin state.
|
||||
*/
|
||||
void cancelPlayPreview();
|
||||
|
||||
/**
|
||||
* If this plugin runs out-of-process, it has a runID to differentiate
|
||||
* between different times the plugin process has been instantiated.
|
||||
|
@ -715,6 +715,7 @@ nsObjectLoadingContent::nsObjectLoadingContent()
|
||||
, mInstantiating(false)
|
||||
, mNetworkCreated(true)
|
||||
, mActivated(false)
|
||||
, mPlayPreviewCanceled(false)
|
||||
, mIsStopping(false)
|
||||
, mIsLoading(false)
|
||||
, mScriptRequested(false) {}
|
||||
@ -1405,6 +1406,8 @@ nsObjectLoadingContent::ObjectState() const
|
||||
return NS_EVENT_STATE_USERDISABLED;
|
||||
case eFallbackClickToPlay:
|
||||
return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
|
||||
case eFallbackPlayPreview:
|
||||
return NS_EVENT_STATE_TYPE_PLAY_PREVIEW;
|
||||
case eFallbackDisabled:
|
||||
return NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_HANDLER_DISABLED;
|
||||
case eFallbackBlocklisted:
|
||||
@ -3119,7 +3122,7 @@ nsObjectLoadingContent::PlayPlugin()
|
||||
LOG(("OBJLC [%p]: Activated by user", this));
|
||||
}
|
||||
|
||||
// If we're in a click-to-play state, reload.
|
||||
// If we're in a click-to-play or play preview state, we need to reload
|
||||
// Fallback types >= eFallbackClickToPlay are plugin-replacement types, see
|
||||
// header
|
||||
if (mType == eType_Null && mFallbackType >= eFallbackClickToPlay) {
|
||||
@ -3134,6 +3137,7 @@ nsObjectLoadingContent::Reload(bool aClearActivation)
|
||||
{
|
||||
if (aClearActivation) {
|
||||
mActivated = false;
|
||||
mPlayPreviewCanceled = false;
|
||||
}
|
||||
|
||||
return LoadObject(true, true);
|
||||
@ -3173,6 +3177,22 @@ nsObjectLoadingContent::GetHasRunningPlugin(bool *aHasPlugin)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::CancelPlayPreview()
|
||||
{
|
||||
if (!nsContentUtils::IsCallerChrome())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
mPlayPreviewCanceled = true;
|
||||
|
||||
// If we're in play preview state already, reload
|
||||
if (mType == eType_Null && mFallbackType == eFallbackPlayPreview) {
|
||||
return LoadObject(true, true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::GetRunID(uint32_t* aRunID)
|
||||
{
|
||||
@ -3218,6 +3238,31 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
|
||||
|
||||
nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
|
||||
|
||||
nsCOMPtr<nsIPluginPlayPreviewInfo> playPreviewInfo;
|
||||
bool isPlayPreviewSpecified = NS_SUCCEEDED(pluginHost->GetPlayPreviewInfo(
|
||||
mContentType, getter_AddRefs(playPreviewInfo)));
|
||||
if (isPlayPreviewSpecified) {
|
||||
// Checking PlayPreview whitelist as well.
|
||||
nsCString uriSpec, baseSpec;
|
||||
if (mURI) {
|
||||
mURI->GetSpec(uriSpec);
|
||||
}
|
||||
if (mBaseURI) {
|
||||
mBaseURI->GetSpec(baseSpec);
|
||||
}
|
||||
playPreviewInfo->CheckWhitelist(baseSpec, uriSpec, &isPlayPreviewSpecified);
|
||||
}
|
||||
bool ignoreCTP = false;
|
||||
if (isPlayPreviewSpecified) {
|
||||
playPreviewInfo->GetIgnoreCTP(&ignoreCTP);
|
||||
}
|
||||
if (isPlayPreviewSpecified && !mPlayPreviewCanceled &&
|
||||
ignoreCTP) {
|
||||
// play preview in ignoreCTP mode is shown even if the native plugin
|
||||
// is not present/installed
|
||||
aReason = eFallbackPlayPreview;
|
||||
return false;
|
||||
}
|
||||
// at this point if it's not a plugin, we let it play/fallback
|
||||
if (!aIgnoreCurrentType && mType != eType_Plugin) {
|
||||
return true;
|
||||
@ -3227,6 +3272,8 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
|
||||
// * Assume a default of click-to-play
|
||||
// * If globally disabled, per-site permissions cannot override.
|
||||
// * If blocklisted, override the reason with the blocklist reason
|
||||
// * If not blocklisted but playPreview, override the reason with the
|
||||
// playPreview reason.
|
||||
// * Check per-site permissions and follow those if specified.
|
||||
// * Honor per-plugin disabled permission
|
||||
// * Blocklisted plugins are forced to CtP
|
||||
@ -3262,6 +3309,12 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
|
||||
aReason = eFallbackVulnerableNoUpdate;
|
||||
}
|
||||
|
||||
if (aReason == eFallbackClickToPlay && isPlayPreviewSpecified &&
|
||||
!mPlayPreviewCanceled && !ignoreCTP) {
|
||||
// play preview in click-to-play mode is shown instead of standard CTP UI
|
||||
aReason = eFallbackPlayPreview;
|
||||
}
|
||||
|
||||
// Check the permission manager for permission based on the principal of
|
||||
// the toplevel content.
|
||||
|
||||
|
@ -94,6 +94,9 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
eFallbackVulnerableUpdatable = nsIObjectLoadingContent::PLUGIN_VULNERABLE_UPDATABLE,
|
||||
// The plugin is vulnerable (no update available)
|
||||
eFallbackVulnerableNoUpdate = nsIObjectLoadingContent::PLUGIN_VULNERABLE_NO_UPDATE,
|
||||
// The plugin is disabled and play preview content is displayed until
|
||||
// the extension code enables it by sending the MozPlayPlugin event
|
||||
eFallbackPlayPreview = nsIObjectLoadingContent::PLUGIN_PLAY_PREVIEW
|
||||
};
|
||||
|
||||
nsObjectLoadingContent();
|
||||
@ -222,6 +225,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
{
|
||||
return !!mInstanceOwner;
|
||||
}
|
||||
void CancelPlayPreview(mozilla::ErrorResult& aRv)
|
||||
{
|
||||
aRv = CancelPlayPreview();
|
||||
}
|
||||
void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aRv)
|
||||
{
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
@ -615,13 +622,16 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
// activated by PlayPlugin(). (see ShouldPlay())
|
||||
bool mActivated : 1;
|
||||
|
||||
// Used to keep track of whether or not a plugin is blocked by play-preview.
|
||||
bool mPlayPreviewCanceled : 1;
|
||||
|
||||
// Protects DoStopPlugin from reentry (bug 724781).
|
||||
bool mIsStopping : 1;
|
||||
|
||||
// Protects LoadObject from re-entry
|
||||
bool mIsLoading : 1;
|
||||
|
||||
// For plugin stand-in types (click-to-play) tracks
|
||||
// For plugin stand-in types (click-to-play, play preview, ...) tracks
|
||||
// whether content js has tried to access the plugin script object.
|
||||
bool mScriptRequested : 1;
|
||||
|
||||
|
@ -262,6 +262,8 @@ private:
|
||||
#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(42)
|
||||
// Element is rtl (for :dir pseudo-class)
|
||||
#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(43)
|
||||
// Handler for play preview plugin
|
||||
#define NS_EVENT_STATE_TYPE_PLAY_PREVIEW NS_DEFINE_EVENT_STATE_MACRO(44)
|
||||
// Element is highlighted (devtools inspector)
|
||||
#define NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED NS_DEFINE_EVENT_STATE_MACRO(45)
|
||||
// Element is an unresolved custom element candidate
|
||||
|
@ -32,6 +32,7 @@ EXPORTS += [
|
||||
'nsPluginLogging.h',
|
||||
'nsPluginNativeWindow.h',
|
||||
'nsPluginNativeWindowGtk.h',
|
||||
'nsPluginPlayPreviewInfo.h',
|
||||
'nsPluginsCID.h',
|
||||
'nsPluginsDir.h',
|
||||
'nsPluginTags.h',
|
||||
@ -47,6 +48,7 @@ UNIFIED_SOURCES += [
|
||||
'nsNPAPIPluginStreamListener.cpp',
|
||||
'nsPluginInstanceOwner.cpp',
|
||||
'nsPluginModule.cpp',
|
||||
'nsPluginPlayPreviewInfo.cpp',
|
||||
'nsPluginStreamListenerPeer.cpp',
|
||||
'nsPluginTags.cpp',
|
||||
'PluginPRLibrary.cpp',
|
||||
|
@ -12,6 +12,21 @@
|
||||
"@mozilla.org/plugin/host;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(57069ada-2845-46ef-b57f-233596d1c02c)]
|
||||
interface nsIPluginPlayPreviewInfo : nsISupports
|
||||
{
|
||||
readonly attribute AUTF8String mimeType;
|
||||
readonly attribute boolean ignoreCTP;
|
||||
readonly attribute AUTF8String redirectURL;
|
||||
readonly attribute AUTF8String whitelist;
|
||||
|
||||
/**
|
||||
* Checks if pageURI and objectURI matches once of the entries in
|
||||
* the whitelist. If whitelist is empty, returns true.
|
||||
*/
|
||||
boolean checkWhitelist(in AUTF8String pageURI, in AUTF8String objectURI);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(9c311778-7c2c-4ad8-b439-b8a2786a20dd)]
|
||||
interface nsIClearSiteDataCallback : nsISupports
|
||||
{
|
||||
@ -21,7 +36,7 @@ interface nsIClearSiteDataCallback : nsISupports
|
||||
void callback(in nsresult rv);
|
||||
};
|
||||
|
||||
[scriptable, uuid(f938f5ba-7093-42cd-a559-af8039d99204)]
|
||||
[scriptable, uuid(0f73bbd2-fc89-41df-b31b-38c09903d187)]
|
||||
interface nsIPluginHost : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -87,6 +102,27 @@ interface nsIPluginHost : nsISupports
|
||||
*/
|
||||
boolean siteHasData(in nsIPluginTag plugin, in AUTF8String domain);
|
||||
|
||||
/**
|
||||
* Registers the play preview plugin mode for specific mime type
|
||||
*
|
||||
* @param mimeType: specifies plugin mime type.
|
||||
* @param ignoreCTP: if true, the play preview ignores CTP rules, e.g.
|
||||
whitelisted websites, will not notify about plugin
|
||||
presence in the address bar.
|
||||
* @param redirectURL: specifies url for the overlay iframe
|
||||
* @param whitelist: specifies plugin whitelist in form of comma separated
|
||||
* "[@page_url object_url|@page_url|object_url]" entries,
|
||||
* e.g. @http://example.org/* http://example.org/t.swf
|
||||
*/
|
||||
void registerPlayPreviewMimeType(in AUTF8String mimeType,
|
||||
[optional] in boolean ignoreCTP,
|
||||
[optional] in AUTF8String redirectURL,
|
||||
[optional] in AUTF8String whitelist);
|
||||
|
||||
void unregisterPlayPreviewMimeType(in AUTF8String mimeType);
|
||||
|
||||
nsIPluginPlayPreviewInfo getPlayPreviewInfo(in AUTF8String mimeType);
|
||||
|
||||
/**
|
||||
* Get the "permission string" for the plugin. This is a string that can be
|
||||
* passed to the permission manager to see whether the plugin is allowed to
|
||||
|
@ -1598,6 +1598,58 @@ nsPluginHost::UnregisterFakePlugin(const nsACString& aHandlerURI)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginHost::RegisterPlayPreviewMimeType(const nsACString& mimeType,
|
||||
bool ignoreCTP,
|
||||
const nsACString& redirectURL,
|
||||
const nsACString& whitelist)
|
||||
{
|
||||
nsAutoCString mt(mimeType);
|
||||
nsAutoCString url(redirectURL);
|
||||
if (url.Length() == 0) {
|
||||
// using default play preview iframe URL, if redirectURL is not specified
|
||||
url.AssignLiteral("data:application/x-moz-playpreview;,");
|
||||
url.Append(mimeType);
|
||||
}
|
||||
nsAutoCString wl(whitelist);
|
||||
|
||||
nsRefPtr<nsPluginPlayPreviewInfo> playPreview =
|
||||
new nsPluginPlayPreviewInfo(mt.get(), ignoreCTP, url.get(), wl.get());
|
||||
mPlayPreviewMimeTypes.AppendElement(playPreview);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginHost::UnregisterPlayPreviewMimeType(const nsACString& mimeType)
|
||||
{
|
||||
nsAutoCString mimeTypeToRemove(mimeType);
|
||||
for (uint32_t i = mPlayPreviewMimeTypes.Length(); i > 0; i--) {
|
||||
nsRefPtr<nsPluginPlayPreviewInfo> pp = mPlayPreviewMimeTypes[i - 1];
|
||||
if (PL_strcasecmp(pp.get()->mMimeType.get(), mimeTypeToRemove.get()) == 0) {
|
||||
mPlayPreviewMimeTypes.RemoveElementAt(i - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginHost::GetPlayPreviewInfo(const nsACString& mimeType,
|
||||
nsIPluginPlayPreviewInfo** aResult)
|
||||
{
|
||||
nsAutoCString mimeTypeToFind(mimeType);
|
||||
for (uint32_t i = 0; i < mPlayPreviewMimeTypes.Length(); i++) {
|
||||
nsRefPtr<nsPluginPlayPreviewInfo> pp = mPlayPreviewMimeTypes[i];
|
||||
if (PL_strcasecmp(pp.get()->mMimeType.get(), mimeTypeToFind.get()) == 0) {
|
||||
*aResult = new nsPluginPlayPreviewInfo(pp.get());
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
*aResult = nullptr;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// FIXME-jsplugins Is this method actually needed?
|
||||
NS_IMETHODIMP
|
||||
nsPluginHost::GetFakePlugin(const nsACString & aMimeType,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "prlink.h"
|
||||
#include "prclist.h"
|
||||
#include "nsIPluginTag.h"
|
||||
#include "nsPluginPlayPreviewInfo.h"
|
||||
#include "nsPluginsDir.h"
|
||||
#include "nsPluginDirServiceProvider.h"
|
||||
#include "nsAutoPtr.h"
|
||||
@ -368,6 +369,7 @@ private:
|
||||
nsRefPtr<nsPluginTag> mPlugins;
|
||||
nsRefPtr<nsPluginTag> mCachedPlugins;
|
||||
nsRefPtr<nsInvalidPluginTag> mInvalidPlugins;
|
||||
nsTArray< nsRefPtr<nsPluginPlayPreviewInfo> > mPlayPreviewMimeTypes;
|
||||
|
||||
nsTArray< nsRefPtr<nsFakePluginTag> > mFakePlugins;
|
||||
|
||||
|
154
dom/plugins/base/nsPluginPlayPreviewInfo.cpp
Normal file
154
dom/plugins/base/nsPluginPlayPreviewInfo.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/* -*- Mode: C++; 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/. */
|
||||
|
||||
#include "nsPluginPlayPreviewInfo.h"
|
||||
#include "nsWildCard.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsPluginPlayPreviewInfo::nsPluginPlayPreviewInfo(const char* aMimeType,
|
||||
bool aIgnoreCTP,
|
||||
const char* aRedirectURL,
|
||||
const char* aWhitelist)
|
||||
: mMimeType(aMimeType), mIgnoreCTP(aIgnoreCTP), mRedirectURL(aRedirectURL),
|
||||
mWhitelist(aWhitelist) {}
|
||||
|
||||
nsPluginPlayPreviewInfo::nsPluginPlayPreviewInfo(
|
||||
const nsPluginPlayPreviewInfo* aSource)
|
||||
{
|
||||
MOZ_ASSERT(aSource);
|
||||
|
||||
mMimeType = aSource->mMimeType;
|
||||
mIgnoreCTP = aSource->mIgnoreCTP;
|
||||
mRedirectURL = aSource->mRedirectURL;
|
||||
mWhitelist = aSource->mWhitelist;
|
||||
}
|
||||
|
||||
nsPluginPlayPreviewInfo::~nsPluginPlayPreviewInfo()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPluginPlayPreviewInfo, nsIPluginPlayPreviewInfo)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginPlayPreviewInfo::GetMimeType(nsACString& aMimeType)
|
||||
{
|
||||
aMimeType = mMimeType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginPlayPreviewInfo::GetIgnoreCTP(bool* aIgnoreCTP)
|
||||
{
|
||||
*aIgnoreCTP = mIgnoreCTP;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginPlayPreviewInfo::GetRedirectURL(nsACString& aRedirectURL)
|
||||
{
|
||||
aRedirectURL = mRedirectURL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginPlayPreviewInfo::GetWhitelist(nsACString& aWhitelist)
|
||||
{
|
||||
aWhitelist = mWhitelist;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
|
||||
const nsACString& aObjectURI,
|
||||
const nsACString& aWhitelist,
|
||||
bool *_retval)
|
||||
{
|
||||
if (aWhitelist.Length() == 0) {
|
||||
// Considering empty whitelist as '*' entry.
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Parses whitelist as comma separated entries of
|
||||
// [@page_url object_url|@page_url|object_url]
|
||||
// where page_url and object_url pattern matches for aPageURI
|
||||
// and aObjectURI, and performs matching as the same time.
|
||||
nsACString::const_iterator start, end;
|
||||
aWhitelist.BeginReading(start);
|
||||
aWhitelist.EndReading(end);
|
||||
|
||||
nsAutoCString pageURI(aPageURI);
|
||||
nsAutoCString objectURI(aObjectURI);
|
||||
nsACString::const_iterator pos = start, entryStart, entryEnd;
|
||||
nsACString::const_iterator pagePatternStart, pagePatternEnd;
|
||||
nsACString::const_iterator objectPatternStart, objectPatternEnd;
|
||||
int matchResult;
|
||||
bool matched, didMatching;
|
||||
while (pos != end) {
|
||||
matched = true;
|
||||
didMatching = false;
|
||||
entryStart = pos;
|
||||
// Looking for end of the entry.
|
||||
while (pos != end && *pos != ',') {
|
||||
pos++;
|
||||
}
|
||||
entryEnd = pos;
|
||||
if (entryStart != entryEnd && *entryStart == '@') {
|
||||
// Pattern for aPageURL is found, finding a space or end of the entry.
|
||||
pagePatternStart = entryStart;
|
||||
pagePatternStart++;
|
||||
pagePatternEnd = pagePatternStart;
|
||||
while (pagePatternEnd != entryEnd && *pagePatternEnd != ' ') {
|
||||
pagePatternEnd++;
|
||||
}
|
||||
nsAutoCString pagePattern(Substring(pagePatternStart, pagePatternEnd));
|
||||
matchResult = NS_WildCardMatch(pageURI.get(), pagePattern.get(), true);
|
||||
matched &= matchResult == MATCH;
|
||||
didMatching = true;
|
||||
objectPatternStart = pagePatternEnd;
|
||||
} else {
|
||||
objectPatternStart = entryStart;
|
||||
}
|
||||
while (objectPatternStart != entryEnd && *objectPatternStart == ' ') {
|
||||
objectPatternStart++;
|
||||
}
|
||||
if (objectPatternStart != entryEnd) {
|
||||
// Pattern for aObjectURL is found, removing trailing spaces.
|
||||
objectPatternEnd = entryEnd;
|
||||
--objectPatternEnd;
|
||||
while (objectPatternStart != objectPatternEnd &&
|
||||
*objectPatternEnd == ' ') {
|
||||
objectPatternEnd--;
|
||||
};
|
||||
objectPatternEnd++;
|
||||
nsAutoCString objectPattern(Substring(objectPatternStart,
|
||||
objectPatternEnd));
|
||||
matchResult = NS_WildCardMatch(objectURI.get(), objectPattern.get(), true);
|
||||
matched &= matchResult == MATCH;
|
||||
didMatching = true;
|
||||
}
|
||||
// Ignoring match result for empty entries.
|
||||
if (didMatching && matched) {
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
if (pos == end) {
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
|
||||
const nsACString& aObjectURI,
|
||||
bool *_retval)
|
||||
{
|
||||
return CheckWhitelist(aPageURI, aObjectURI, mWhitelist, _retval);
|
||||
}
|
45
dom/plugins/base/nsPluginPlayPreviewInfo.h
Normal file
45
dom/plugins/base/nsPluginPlayPreviewInfo.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* -*- Mode: C++; 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/. */
|
||||
|
||||
#ifndef nsPluginPlayPreviewInfo_h_
|
||||
#define nsPluginPlayPreviewInfo_h_
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsIPluginHost.h"
|
||||
|
||||
class nsPluginPlayPreviewInfo : public nsIPluginPlayPreviewInfo
|
||||
{
|
||||
virtual ~nsPluginPlayPreviewInfo();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGINPLAYPREVIEWINFO
|
||||
|
||||
nsPluginPlayPreviewInfo(const char* aMimeType,
|
||||
bool aIgnoreCTP,
|
||||
const char* aRedirectURL,
|
||||
const char* aWhitelist);
|
||||
explicit nsPluginPlayPreviewInfo(const nsPluginPlayPreviewInfo* aSource);
|
||||
|
||||
/** This function checks aPageURI and aObjectURI against the whitelist
|
||||
* specified in aWhitelist. This is public static function because this
|
||||
* whitelist checking code needs to be accessed without any instances of
|
||||
* nsIPluginPlayPreviewInfo. In particular, the Shumway whitelist is
|
||||
* obtained directly from prefs and compared using this code for telemetry
|
||||
* purposes.
|
||||
*/
|
||||
static nsresult CheckWhitelist(const nsACString& aPageURI,
|
||||
const nsACString& aObjectURI,
|
||||
const nsACString& aWhitelist,
|
||||
bool *_retval);
|
||||
|
||||
nsCString mMimeType;
|
||||
bool mIgnoreCTP;
|
||||
nsCString mRedirectURL;
|
||||
nsCString mWhitelist;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsPluginPlayPreviewInfo_h_
|
@ -167,7 +167,26 @@ PluginInstanceParent::InitMetadata(const nsACString& aMimeType,
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIURI> baseUri(owner->GetBaseURI());
|
||||
return NS_SUCCEEDED(NS_MakeAbsoluteURI(mSrcAttribute, aSrcAttribute, baseUri));
|
||||
nsresult rv = NS_MakeAbsoluteURI(mSrcAttribute, aSrcAttribute, baseUri);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
// Check the whitelist
|
||||
nsAutoCString baseUrlSpec;
|
||||
rv = baseUri->GetSpec(baseUrlSpec);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
auto whitelist = Preferences::GetCString(kShumwayWhitelistPref);
|
||||
// Empty whitelist is interpreted by CheckWhitelist as "allow everything,"
|
||||
// which is not valid for our use case and should be treated as a failure.
|
||||
if (whitelist.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
rv = nsPluginPlayPreviewInfo::CheckWhitelist(baseUrlSpec, mSrcAttribute,
|
||||
whitelist,
|
||||
&mIsWhitelistedForShumway);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -129,6 +129,9 @@ interface MozObjectLoadingContent {
|
||||
// The plugin is vulnerable (no update available)
|
||||
[ChromeOnly]
|
||||
const unsigned long PLUGIN_VULNERABLE_NO_UPDATE = 10;
|
||||
// The plugin is in play preview mode
|
||||
[ChromeOnly]
|
||||
const unsigned long PLUGIN_PLAY_PREVIEW = 11;
|
||||
|
||||
/**
|
||||
* The actual mime type (the one we got back from the network
|
||||
@ -160,8 +163,8 @@ interface MozObjectLoadingContent {
|
||||
sequence<MozPluginParameter> getPluginParameters();
|
||||
|
||||
/**
|
||||
* This method will play a plugin that has been stopped by the click-to-play
|
||||
* feature.
|
||||
* This method will play a plugin that has been stopped by the
|
||||
* click-to-play plugins or play-preview features.
|
||||
*/
|
||||
[ChromeOnly, Throws]
|
||||
void playPlugin();
|
||||
@ -178,7 +181,7 @@ interface MozObjectLoadingContent {
|
||||
/**
|
||||
* This attribute will return true if the current content type has been
|
||||
* activated, either explicitly or by passing checks that would have it be
|
||||
* click-to-play.
|
||||
* click-to-play or play-preview.
|
||||
*/
|
||||
[ChromeOnly]
|
||||
readonly attribute boolean activated;
|
||||
@ -203,6 +206,12 @@ interface MozObjectLoadingContent {
|
||||
[ChromeOnly]
|
||||
readonly attribute boolean hasRunningPlugin;
|
||||
|
||||
/**
|
||||
* This method will disable the play-preview plugin state.
|
||||
*/
|
||||
[ChromeOnly, Throws]
|
||||
void cancelPlayPreview();
|
||||
|
||||
[ChromeOnly, Throws]
|
||||
readonly attribute unsigned long runID;
|
||||
};
|
||||
|
@ -179,6 +179,8 @@ CSS_STATE_PSEUDO_CLASS(mozTypeUnsupportedPlatform, ":-moz-type-unsupported-platf
|
||||
NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM)
|
||||
CSS_STATE_PSEUDO_CLASS(mozHandlerClickToPlay, ":-moz-handler-clicktoplay", 0, "",
|
||||
NS_EVENT_STATE_TYPE_CLICK_TO_PLAY)
|
||||
CSS_STATE_PSEUDO_CLASS(mozHandlerPlayPreview, ":-moz-handler-playpreview", 0, "",
|
||||
NS_EVENT_STATE_TYPE_PLAY_PREVIEW)
|
||||
CSS_STATE_PSEUDO_CLASS(mozHandlerVulnerableUpdatable, ":-moz-handler-vulnerable-updatable", 0, "",
|
||||
NS_EVENT_STATE_VULNERABLE_UPDATABLE)
|
||||
CSS_STATE_PSEUDO_CLASS(mozHandlerVulnerableNoUpdate, ":-moz-handler-vulnerable-no-update", 0, "",
|
||||
|
@ -87,6 +87,17 @@ var PluginHelper = {
|
||||
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)
|
||||
@ -201,6 +212,54 @@ var PluginHelper = {
|
||||
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.
|
||||
@ -224,6 +283,8 @@ var PluginHelper = {
|
||||
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;
|
||||
|
@ -67,6 +67,7 @@
|
||||
</html:div>
|
||||
<html:button class="closeIcon" anonid="closeIcon" title="&hidePluginBtn.label;"/>
|
||||
</html:div>
|
||||
<html:div class="previewPluginContent" anonid="previewPluginContent"><!-- iframe and its src will be set at runtime --></html:div>
|
||||
<html:div style="display:none;"><children/></html:div>
|
||||
</content>
|
||||
<implementation>
|
||||
|
@ -8,18 +8,21 @@ embed:-moz-handler-disabled,
|
||||
embed:-moz-handler-blocked,
|
||||
embed:-moz-handler-crashed,
|
||||
embed:-moz-handler-clicktoplay,
|
||||
embed:-moz-handler-playpreview,
|
||||
embed:-moz-handler-vulnerable-updatable,
|
||||
embed:-moz-handler-vulnerable-no-update,
|
||||
applet:-moz-handler-disabled,
|
||||
applet:-moz-handler-blocked,
|
||||
applet:-moz-handler-crashed,
|
||||
applet:-moz-handler-clicktoplay,
|
||||
applet:-moz-handler-playpreview,
|
||||
applet:-moz-handler-vulnerable-updatable,
|
||||
applet:-moz-handler-vulnerable-no-update,
|
||||
object:-moz-handler-disabled,
|
||||
object:-moz-handler-blocked,
|
||||
object:-moz-handler-crashed,
|
||||
object:-moz-handler-clicktoplay,
|
||||
object:-moz-handler-playpreview,
|
||||
object:-moz-handler-vulnerable-updatable,
|
||||
object:-moz-handler-vulnerable-no-update {
|
||||
display: inline-block;
|
||||
|
@ -71,6 +71,10 @@ html|applet:not([height]), html|applet[height=""] {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
:-moz-handler-playpreview .mainBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:-moz-handler-clicktoplay .hoverBox,
|
||||
:-moz-handler-vulnerable-updatable .hoverBox,
|
||||
:-moz-handler-vulnerable-no-update .hoverBox {
|
||||
@ -84,6 +88,23 @@ html|applet:not([height]), html|applet[height=""] {
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.previewPluginContent {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.previewPluginContent > iframe {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
border: none;
|
||||
}
|
||||
|
||||
:-moz-handler-playpreview .previewPluginContent {
|
||||
display: block;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.msg {
|
||||
display: none;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user