Bug 870553 - Adds whitelist to PlayPreview API. r=joshmoz

This commit is contained in:
Yury Delendik 2015-02-03 13:41:11 -06:00
parent 7a1be97773
commit 305bb56ecc
9 changed files with 285 additions and 8 deletions

View File

@ -39,6 +39,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
@ -72,6 +73,7 @@ run-if = crashreporter
[browser_pluginnotification.js]
[browser_pluginplaypreview.js]
[browser_pluginplaypreview2.js]
[browser_pluginplaypreview3.js]
[browser_pluginCrashCommentAndURL.js]
run-if = crashreporter
[browser_plugins_added_dynamically.js]

View File

@ -0,0 +1,134 @@
/* 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/. */
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();
}

View 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>

View File

@ -20,6 +20,7 @@ var EXPORTED_SYMBOLS = ['ShumwayBootstrapUtils'];
const PREF_PREFIX = 'shumway.';
const PREF_IGNORE_CTP = PREF_PREFIX + 'ignoreCTP';
const PREF_WHITELIST = PREF_PREFIX + 'swf.whitelist';
const SWF_CONTENT_TYPE = 'application/x-shockwave-flash';
let Cc = Components.classes;
@ -43,6 +44,14 @@ function getBoolPref(pref, def) {
}
}
function getStringPref(pref, def) {
try {
return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
} catch (ex) {
return def;
}
}
function log(str) {
dump(str + '\n');
}
@ -79,7 +88,9 @@ var ShumwayBootstrapUtils = {
if (registerOverlayPreview) {
var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
Ph.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP);
var whitelist = getStringPref(PREF_WHITELIST);
Ph.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP,
undefined, whitelist);
}
},
@ -92,4 +103,4 @@ var ShumwayBootstrapUtils = {
Ph.unregisterPlayPreviewMimeType(SWF_CONTENT_TYPE);
}
}
};
};

View File

@ -3165,6 +3165,17 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
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);

View File

@ -18,6 +18,13 @@ 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, uuid(e8fe94f0-b877-46d0-931a-090967fb1e83)]
@ -86,10 +93,14 @@ interface nsIPluginHost : nsISupports
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 redirectURL,
[optional] in AUTF8String whitelist);
void unregisterPlayPreviewMimeType(in AUTF8String mimeType);

View File

@ -1494,7 +1494,8 @@ nsPluginHost::EnumerateSiteData(const nsACString& domain,
NS_IMETHODIMP
nsPluginHost::RegisterPlayPreviewMimeType(const nsACString& mimeType,
bool ignoreCTP,
const nsACString& redirectURL)
const nsACString& redirectURL,
const nsACString& whitelist)
{
nsAutoCString mt(mimeType);
nsAutoCString url(redirectURL);
@ -1503,9 +1504,10 @@ nsPluginHost::RegisterPlayPreviewMimeType(const nsACString& mimeType,
url.AssignLiteral("data:application/x-moz-playpreview;,");
url.Append(mimeType);
}
nsAutoCString wl(whitelist);
nsRefPtr<nsPluginPlayPreviewInfo> playPreview =
new nsPluginPlayPreviewInfo(mt.get(), ignoreCTP, url.get());
new nsPluginPlayPreviewInfo(mt.get(), ignoreCTP, url.get(), wl.get());
mPlayPreviewMimeTypes.AppendElement(playPreview);
return NS_OK;
}

View File

@ -4,13 +4,16 @@
* 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)
: mMimeType(aMimeType), mIgnoreCTP(aIgnoreCTP), mRedirectURL(aRedirectURL) {}
const char* aRedirectURL,
const char* aWhitelist)
: mMimeType(aMimeType), mIgnoreCTP(aIgnoreCTP), mRedirectURL(aRedirectURL),
mWhitelist(aWhitelist) {}
nsPluginPlayPreviewInfo::nsPluginPlayPreviewInfo(
const nsPluginPlayPreviewInfo* aSource)
@ -20,6 +23,7 @@ nsPluginPlayPreviewInfo::nsPluginPlayPreviewInfo(
mMimeType = aSource->mMimeType;
mIgnoreCTP = aSource->mIgnoreCTP;
mRedirectURL = aSource->mRedirectURL;
mWhitelist = aSource->mWhitelist;
}
nsPluginPlayPreviewInfo::~nsPluginPlayPreviewInfo()
@ -48,3 +52,94 @@ nsPluginPlayPreviewInfo::GetRedirectURL(nsACString& aRedirectURL)
aRedirectURL = mRedirectURL;
return NS_OK;
}
NS_IMETHODIMP
nsPluginPlayPreviewInfo::GetWhitelist(nsACString& aWhitelist)
{
aWhitelist = mWhitelist;
return NS_OK;
}
NS_IMETHODIMP
nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
const nsACString& aObjectURI,
bool *_retval)
{
if (mWhitelist.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;
mWhitelist.BeginReading(start);
mWhitelist.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;
}

View File

@ -19,12 +19,14 @@ public:
nsPluginPlayPreviewInfo(const char* aMimeType,
bool aIgnoreCTP,
const char* aRedirectURL);
const char* aRedirectURL,
const char* aWhitelist);
explicit nsPluginPlayPreviewInfo(const nsPluginPlayPreviewInfo* aSource);
nsCString mMimeType;
bool mIgnoreCTP;
nsCString mRedirectURL;
nsCString mWhitelist;
};