bug 326693 filechannel ignores content-type hints

r+sr=darin
This commit is contained in:
cbiesinger%web.de 2006-02-14 18:46:12 +00:00
Родитель 41d0754579
Коммит 0233b3a085
5 изменённых файлов: 64 добавлений и 16 удалений

Просмотреть файл

@ -167,6 +167,13 @@ nsBaseChannel::Redirect(nsIChannel *newChannel, PRUint32 redirectFlags)
return NS_OK;
}
PRBool
nsBaseChannel::HasContentTypeHint() const
{
NS_ASSERTION(!IsPending(), "HasContentTypeHint called too late");
return !mContentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE);
}
void
nsBaseChannel::SetContentLength64(PRInt64 len)
{

Просмотреть файл

@ -125,6 +125,12 @@ public:
// parameter consists of the flag values defined on nsIChannelEventSink.
nsresult Redirect(nsIChannel *newChannel, PRUint32 redirectFlags);
// Tests whether a type hint was set. Subclasses can use this to decide
// whether to call SetContentType.
// NOTE: This is only reliable if the subclass didn't itself call
// SetContentType, and should also not be called after OpenContentStream.
PRBool HasContentTypeHint() const;
// The URI member should be initialized before the channel is used, and then
// it should never be changed again until the channel is destroyed.
nsIURI *URI() {
@ -154,7 +160,7 @@ public:
}
// This is a short-cut to calling nsIRequest::IsPending()
PRBool IsPending() {
PRBool IsPending() const {
return (mPump != nsnull);
}

Просмотреть файл

@ -269,11 +269,10 @@ nsFileUploadContentStream::OnOutputStreamReady(nsIAsyncOutputStream *unused)
//-----------------------------------------------------------------------------
// Called to construct a blocking file input stream for the given file. This
// method also returns a best guess at the content-type for the data stream.
static nsresult
MakeFileInputStream(nsIFile *file, nsCOMPtr<nsIInputStream> &stream,
nsCString &contentType)
nsresult
nsFileChannel::MakeFileInputStream(nsIFile *file,
nsCOMPtr<nsIInputStream> &stream,
nsCString &contentType)
{
// we accept that this might result in a disk hit to stat the file
PRBool isDir;
@ -287,11 +286,11 @@ MakeFileInputStream(nsIFile *file, nsCOMPtr<nsIInputStream> &stream,
if (isDir) {
rv = nsDirectoryIndexStream::Create(file, getter_AddRefs(stream));
if (NS_SUCCEEDED(rv))
if (NS_SUCCEEDED(rv) && !HasContentTypeHint())
contentType.AssignLiteral(APPLICATION_HTTP_INDEX_FORMAT);
} else {
rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
if (NS_SUCCEEDED(rv)) {
if (NS_SUCCEEDED(rv) && !HasContentTypeHint()) {
// Use file extension to infer content type
nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv);
if (NS_SUCCEEDED(rv)) {
@ -336,7 +335,9 @@ nsFileChannel::OpenContentStream(PRBool async, nsIInputStream **result)
// Since there isn't any content to speak of we just set the content-type
// to something other than "unknown" to avoid triggering the content-type
// sniffer code in nsBaseChannel.
SetContentType(NS_LITERAL_CSTRING(APPLICATION_OCTET_STREAM));
// However, don't override explicitly set types.
if (!HasContentTypeHint())
SetContentType(NS_LITERAL_CSTRING(APPLICATION_OCTET_STREAM));
} else {
nsCAutoString contentType;
nsresult rv = MakeFileInputStream(file, stream, contentType);

Просмотреть файл

@ -58,6 +58,13 @@ public:
}
protected:
// Called to construct a blocking file input stream for the given file. This
// method also returns a best guess at the content-type for the data stream.
// NOTE: If the channel has a type hint set, contentType will be left
// untouched. The caller should not use it in that case.
nsresult MakeFileInputStream(nsIFile *file, nsCOMPtr<nsIInputStream> &stream,
nsCString &contentType);
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result);
private:

Просмотреть файл

@ -5,10 +5,13 @@ const Ci = Components.interfaces;
const Cr = Components.results;
const PR_RDONLY = 0x1; // see prio.h
const special_type = "application/x-our-special-type";
var test_index = 0;
var test_array = [
test_read_file,
test_read_dir,
test_read_dir_1,
test_read_dir_2,
test_upload_file,
do_test_finished
];
@ -137,6 +140,11 @@ function test_read_file() {
function on_read_complete(data) {
dump("*** test_read_file.on_read_complete\n");
// bug 326693
if (chan.contentType != special_type)
do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" +
special_type + ">")
/* read completed successfully. now read data directly from file,
and compare the result. */
var stream = new_file_input_stream(file, false);
@ -146,27 +154,40 @@ function test_read_file() {
run_next_test();
}
chan.contentType = special_type;
chan.asyncOpen(new Listener(on_read_complete), null);
}
function test_read_dir() {
dump("*** test_read_dir\n");
function do_test_read_dir(set_type, expected_type) {
dump("*** test_read_dir(" + set_type + ", " + expected_type + ")\n");
var file = getFile("TmpD");
var chan = new_file_channel(file);
function on_read_complete(data) {
dump("*** test_read_dir.on_read_complete\n");
dump("*** test_read_dir.on_read_complete(" + set_type + ", " + expected_type + ")\n");
// bug 326693
if (chan.contentType != expected_type)
do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" +
expected_type + ">")
/* read of directory completed successfully. */
if (chan.contentType != "application/http-index-format")
do_throw("Unexpected content type!");
run_next_test();
}
if (set_type)
chan.contentType = expected_type;
chan.asyncOpen(new Listener(on_read_complete), null);
}
function test_read_dir_1() {
return do_test_read_dir(false, "application/http-index-format");
}
function test_read_dir_2() {
return do_test_read_dir(true, special_type);
}
function test_upload_file() {
dump("*** test_upload_file\n");
@ -184,6 +205,11 @@ function test_upload_file() {
function on_upload_complete(data) {
dump("*** test_upload_file.on_upload_complete\n");
// bug 326693
if (chan.contentType != special_type)
do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" +
special_type + ">")
/* upload of file completed successfully. */
if (data.length != 0)
do_throw("Upload resulted in data!");
@ -209,6 +235,7 @@ function test_upload_file() {
run_next_test();
}
chan.contentType = special_type;
chan.asyncOpen(new Listener(on_upload_complete), null);
}