Bug 1048579. Always sniff for media loads. r=bzbarsky

--HG--
extra : rebase_source : 39b6d37dbbf138095856954bee583e84cfd971b5
This commit is contained in:
Robert O'Callahan 2014-08-23 00:08:14 +12:00
parent 7dce50ada5
commit 8071af10c3
19 changed files with 58 additions and 186 deletions

View File

@ -1201,7 +1201,8 @@ nsresult HTMLMediaElement::LoadResource()
loadGroup,
nullptr,
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
nsIChannel::LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN,
nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS,
channelPolicy);
NS_ENSURE_SUCCESS(rv,rv);

View File

@ -3,10 +3,6 @@
<head>
<title>Media test: chained ogg files.</title>
<meta charset='utf-8'>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>

View File

@ -2,11 +2,8 @@
<html>
<head>
<title>Media test: seek test 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">

View File

@ -2,11 +2,8 @@
<html>
<head>
<title>Media test: seek test 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">

View File

@ -2,11 +2,8 @@
<html>
<head>
<title>Media test: seek test 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">

View File

@ -2,11 +2,8 @@
<html>
<head>
<title>Media test: seek test 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">

View File

@ -2,11 +2,8 @@
<html>
<head>
<title>Media test: seek test 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">

View File

@ -2,11 +2,8 @@
<html>
<head>
<title>Media test: seek test 1</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">

View File

@ -2,13 +2,9 @@
<html>
<head>
<title>Media test: X-Content-Duration</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">
<pre id="test">

View File

@ -1,12 +1,8 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: mozStopDownload</title>
<title>Media test: sniffing</title>
<meta charset='utf-8'>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
@ -22,23 +18,15 @@ function finish_test(element) {
manager.finished(element.token);
}
function onApplicationOctetStreamLoaded(e) {
var t = e.target;
t.removeEventListener('loadedmetadata', onApplicationOctetStreamLoaded);
ok(true, "The media loads when served with application/octet-stream.");
finish_test(t);
}
function checkApplicationOctetStream(t) {
t.src = t.src.replace("&nomime", "&type=application/octet-stream");
t.addEventListener("loadedmetadata", onApplicationOctetStreamLoaded);
}
function onmetadataloaded(e) {
var t = e.target;
t.removeEventListener('loadedmetadata', onmetadataloaded)
ok(true, "The media loads when served without a Content-Type.");
checkApplicationOctetStream(t);
++t.srcIndex;
ok(true, "The media loads when loaded via " + t.src);
if (t.srcIndex < t.srcList.length) {
t.src = t.srcList[t.srcIndex];
} else {
finish_test(t);
}
}
function onerror(e) {
@ -53,7 +41,16 @@ function startTest(test, token) {
var element = document.createElement(elemType);
// This .sjs file serve the media file without Content-Type header, or with a
// specific Content-Type header.
element.src = 'contentType.sjs?file=' + test.name + "&nomime";
var baseSrc = 'contentType.sjs?file=' + test.name;
element.srcList = [
baseSrc + "&nomime",
baseSrc + "&type=application/octet-stream",
baseSrc + "&type=audio/wav",
baseSrc + "&type=text/html",
baseSrc + "&type=absolute_nonsense"
];
element.srcIndex = 0;
element.src = element.srcList[element.srcIndex];
element.token = token;
element.controls = true;
element.preload = "metadata";

View File

@ -2,10 +2,6 @@
<html>
<head>
<title>Media test: networkState</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>

View File

@ -2,11 +2,8 @@
<html>
<head>
<title>Media test: server lies about range requests</title>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onunload="mediaTestCleanup();">

View File

@ -241,12 +241,11 @@ interface nsIChannel : nsIRequest
const unsigned long LOAD_CLASSIFY_URI = 1 << 22;
/**
* If this flag is set and a server's response is Content-Type
* application/octet-steam, the server's Content-Type will be ignored and
* the channel content will be sniffed as though no Content-Type had been
* passed.
* If this flag is set, the media-type content sniffer will be allowed
* to override any server-set content-type. Otherwise it will only
* be allowed to override "no content type" and application/octet-stream.
*/
const unsigned long LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN = 1 << 23;
const unsigned long LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 1 << 23;
/**
* Set to let explicitely provided credentials be used over credentials

View File

@ -719,15 +719,11 @@ nsBaseChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
MOZ_ASSERT(request == mPump);
// If our content type is unknown or if the content type is
// application/octet-stream and the caller requested it, use the content type
// If our content type is unknown, use the content type
// sniffer. If the sniffer is not available for some reason, then we just keep
// going as-is.
bool shouldSniff = mContentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE) ||
((mLoadFlags & LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN) &&
mContentType.EqualsLiteral(APPLICATION_OCTET_STREAM));
if (NS_SUCCEEDED(mStatus) && shouldSniff) {
if (NS_SUCCEEDED(mStatus) &&
mContentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE)) {
mPump->PeekStream(CallUnknownTypeSniffer, static_cast<nsIChannel*>(this));
}

View File

@ -863,12 +863,8 @@ nsHttpChannel::CallOnStartRequest()
}
}
bool shouldSniff = mResponseHead && (mResponseHead->ContentType().IsEmpty() ||
((mResponseHead->ContentType().EqualsLiteral(APPLICATION_OCTET_STREAM) &&
(mLoadFlags & LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN))));
bool unknownDecoderStarted = false;
if (shouldSniff) {
if (mResponseHead && mResponseHead->ContentType().IsEmpty()) {
MOZ_ASSERT(mConnectionInfo, "Should have connection info here");
if (!mContentTypeHint.IsEmpty())
mResponseHead->SetContentType(mContentTypeHint);

View File

@ -1,90 +0,0 @@
// This file tests the flag LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN.
Cu.import("resource://testing-common/httpd.js");
const octetStreamType = "application/octet-stream";
const sniffedType = "application/x-sniffed";
const snifferCID = Components.ID("{954f3fdd-d717-4c02-9464-7c2da617d21d}");
const snifferContract = "@mozilla.org/network/unittest/contentsniffer;1";
const categoryName = "content-sniffing-services";
var sniffer = {
QueryInterface: function sniffer_qi(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIFactory) ||
iid.equals(Components.interfaces.nsIContentSniffer))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
createInstance: function sniffer_ci(outer, iid) {
if (outer)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
lockFactory: function sniffer_lockf(lock) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
getMIMETypeFromContent: function (request, data, length) {
return sniffedType;
}
};
var listener = {
onStartRequest: function test_onStartR(request, ctx) {
// We should have sniffed the type of the file.
var chan = request.QueryInterface(Components.interfaces.nsIChannel);
do_check_eq(chan.contentType, sniffedType);
},
onDataAvailable: function test_ODA() {
throw Components.results.NS_ERROR_UNEXPECTED;
},
onStopRequest: function test_onStopR(request, ctx, status) {
do_test_finished();
}
};
function handler(metadata, response) {
response.setHeader("Content-Type", octetStreamType);
}
function makeChan(url) {
var ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var chan = ios.newChannel(url, null, null);
// Force sniffing if we have "application/octet-stream" as Content-Type
chan.loadFlags |= Components.interfaces
.nsIChannel
.LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN;
return chan;
}
XPCOMUtils.defineLazyGetter(this, "url", function() {
return "http://localhost:" + httpserv.identity.primaryPort + "/test";
});
var httpserv = null;
function run_test() {
httpserv = new HttpServer();
httpserv.registerPathHandler("/test", handler);
httpserv.start(-1);
// Register our fake sniffer that always returns the content-type we want.
Components.manager.nsIComponentRegistrar.registerFactory(snifferCID,
"Unit test content sniffer", snifferContract, sniffer);
var catMan = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Components.interfaces.nsICategoryManager);
catMan.nsICategoryManager.addCategoryEntry(categoryName, snifferContract,
snifferContract, false, true);
var chan = makeChan(url);
chan.asyncOpen(listener, null);
do_test_pending();
}

View File

@ -170,7 +170,6 @@ skip-if = bits != 32
[test_content_length_underrun.js]
[test_event_sink.js]
[test_extract_charset_from_content_type.js]
[test_force_sniffing.js]
[test_fallback_no-cache-entry_canceled.js]
[test_fallback_no-cache-entry_passing.js]
[test_fallback_redirect-to-different-origin_canceled.js]

View File

@ -102,17 +102,21 @@ nsMediaSniffer::GetMIMETypeFromContent(nsIRequest* aRequest,
const uint32_t aLength,
nsACString& aSniffedType)
{
// For media, we want to sniff only if the Content-Type is unknown, or if it
// is application/octet-stream.
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (channel) {
nsAutoCString contentType;
nsresult rv = channel->GetContentType(contentType);
NS_ENSURE_SUCCESS(rv, rv);
if (!contentType.IsEmpty() &&
!contentType.EqualsLiteral(APPLICATION_OCTET_STREAM) &&
!contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE)) {
return NS_ERROR_NOT_AVAILABLE;
nsLoadFlags loadFlags = 0;
channel->GetLoadFlags(&loadFlags);
if (!(loadFlags & nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE)) {
// For media, we want to sniff only if the Content-Type is unknown, or if it
// is application/octet-stream.
nsAutoCString contentType;
nsresult rv = channel->GetContentType(contentType);
NS_ENSURE_SUCCESS(rv, rv);
if (!contentType.IsEmpty() &&
!contentType.EqualsLiteral(APPLICATION_OCTET_STREAM) &&
!contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE)) {
return NS_ERROR_NOT_AVAILABLE;
}
}
}

View File

@ -19,17 +19,17 @@ var testRan = 0;
// should not be changed.
const tests = [
// Those three first case are the case of a media loaded in a media element.
// The first two should be sniffeed.
// All three should be sniffed.
{ contentType: "",
expectedContentType: "application/ogg",
flags: Ci.nsIChannel.LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN },
flags: Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS | Ci.nsIChannel.LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE },
{ contentType: "application/octet-stream",
expectedContentType: "application/ogg",
flags: Ci.nsIChannel.LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN },
flags: Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS | Ci.nsIChannel.LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE },
{ contentType: "application/something",
expectedContentType: "application/something",
flags: Ci.nsIChannel.LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN },
// This last case tests the case of a channel opened while allowing content
expectedContentType: "application/ogg",
flags: Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS | Ci.nsIChannel.LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE },
// This last cases test the case of a channel opened while allowing content
// sniffers to override the content-type, like in the docshell.
{ contentType: "application/octet-stream",
expectedContentType: "application/ogg",
@ -37,6 +37,9 @@ const tests = [
{ contentType: "",
expectedContentType: "application/ogg",
flags: Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS },
{ contentType: "application/something",
expectedContentType: "application/something",
flags: Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS },
];
// A basic listener that reads checks the if we sniffed properly.