From 0233b3a0855e1e9813618af35dd7af4fb215f215 Mon Sep 17 00:00:00 2001 From: "cbiesinger%web.de" Date: Tue, 14 Feb 2006 18:46:12 +0000 Subject: [PATCH] bug 326693 filechannel ignores content-type hints r+sr=darin --- netwerk/base/src/nsBaseChannel.cpp | 7 ++++ netwerk/base/src/nsBaseChannel.h | 8 +++- netwerk/protocol/file/src/nsFileChannel.cpp | 17 +++++---- netwerk/protocol/file/src/nsFileChannel.h | 7 ++++ netwerk/test/unit/test_file_protocol.js | 41 +++++++++++++++++---- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/netwerk/base/src/nsBaseChannel.cpp b/netwerk/base/src/nsBaseChannel.cpp index 98875ae4d28..22b21513fb3 100644 --- a/netwerk/base/src/nsBaseChannel.cpp +++ b/netwerk/base/src/nsBaseChannel.cpp @@ -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) { diff --git a/netwerk/base/src/nsBaseChannel.h b/netwerk/base/src/nsBaseChannel.h index 4ed68ae2feb..ca241a1cf9a 100644 --- a/netwerk/base/src/nsBaseChannel.h +++ b/netwerk/base/src/nsBaseChannel.h @@ -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); } diff --git a/netwerk/protocol/file/src/nsFileChannel.cpp b/netwerk/protocol/file/src/nsFileChannel.cpp index 57c4ebe4185..f613b1745cf 100644 --- a/netwerk/protocol/file/src/nsFileChannel.cpp +++ b/netwerk/protocol/file/src/nsFileChannel.cpp @@ -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 &stream, - nsCString &contentType) +nsresult +nsFileChannel::MakeFileInputStream(nsIFile *file, + nsCOMPtr &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 &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 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); diff --git a/netwerk/protocol/file/src/nsFileChannel.h b/netwerk/protocol/file/src/nsFileChannel.h index b0e0e191cb0..cc559abd563 100644 --- a/netwerk/protocol/file/src/nsFileChannel.h +++ b/netwerk/protocol/file/src/nsFileChannel.h @@ -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 &stream, + nsCString &contentType); + virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result); private: diff --git a/netwerk/test/unit/test_file_protocol.js b/netwerk/test/unit/test_file_protocol.js index d31f0b6d565..3ce8329a0d3 100644 --- a/netwerk/test/unit/test_file_protocol.js +++ b/netwerk/test/unit/test_file_protocol.js @@ -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); }