Bug 282432 - Calling asyncOpen on a file channel should notify about file not found errors asynchronously instead of throwing from asyncOpen. r=bz
authorOonishi Atsushi <torisugari@gmail.com>
Thu, 01 Nov 2012 19:23:13 -0400
changeset 112087 b027df4ba1e8f2c1ade179f90bbb6cb70bf40861
parent 112086 9268740945659fbd43cf25580c7baff9c8c9ecc2
child 112088 f818459666b292dbe2703e15009f5aef1bd89ffb
push id17405
push userryanvm@gmail.com
push dateThu, 01 Nov 2012 23:23:17 +0000
treeherdermozilla-inbound@7f272ec628b4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs282432
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 282432 - Calling asyncOpen on a file channel should notify about file not found errors asynchronously instead of throwing from asyncOpen. r=bz
netwerk/protocol/file/nsFileChannel.cpp
netwerk/protocol/file/nsFileChannel.h
--- a/netwerk/protocol/file/nsFileChannel.cpp
+++ b/netwerk/protocol/file/nsFileChannel.cpp
@@ -268,34 +268,43 @@ nsFileChannel::nsFileChannel(nsIURI *uri
   } else {
     SetURI(uri);
   }
 }
 
 nsresult
 nsFileChannel::MakeFileInputStream(nsIFile *file,
                                    nsCOMPtr<nsIInputStream> &stream,
-                                   nsCString &contentType)
+                                   nsCString &contentType,
+                                   bool async)
 {
   // we accept that this might result in a disk hit to stat the file
   bool isDir;
   nsresult rv = file->IsDirectory(&isDir);
   if (NS_FAILED(rv)) {
     // canonicalize error message
     if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
       rv = NS_ERROR_FILE_NOT_FOUND;
-    return rv;
+
+    if (async && (NS_ERROR_FILE_NOT_FOUND == rv)) {
+      // We don't return "Not Found" errors here. Since we could not find
+      // the file, it's not a directory anyway.
+      isDir = false;
+    } else {
+      return rv;
+    }
   }
 
   if (isDir) {
     rv = nsDirectoryIndexStream::Create(file, getter_AddRefs(stream));
     if (NS_SUCCEEDED(rv) && !HasContentTypeHint())
       contentType.AssignLiteral(APPLICATION_HTTP_INDEX_FORMAT);
   } else {
-    rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
+    rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file, -1, -1,
+                                    async? nsIFileInputStream::DEFER_OPEN : 0);
     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)) {
         mime->GetTypeFromFile(file, contentType);
       }
     }
   }
@@ -359,28 +368,35 @@ nsFileChannel::OpenContentStream(bool as
     // 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.
     // However, don't override explicitly set types.
     if (!HasContentTypeHint())
       SetContentType(NS_LITERAL_CSTRING(APPLICATION_OCTET_STREAM));
   } else {
     nsAutoCString contentType;
-    rv = MakeFileInputStream(file, stream, contentType);
+    rv = MakeFileInputStream(file, stream, contentType, async);
     if (NS_FAILED(rv))
       return rv;
 
     EnableSynthesizedProgressEvents(true);
 
     // fixup content length and type
     if (mContentLength < 0) {
       int64_t size;
       rv = file->GetFileSize(&size);
-      if (NS_FAILED(rv))
-        return rv;
+      if (NS_FAILED(rv)) {
+        if (async && 
+            (NS_ERROR_FILE_NOT_FOUND == rv ||
+             NS_ERROR_FILE_TARGET_DOES_NOT_EXIST == rv)) {
+          size = 0;
+        } else {
+          return rv;
+        }
+      }
       mContentLength = size;
     }
     if (!contentType.IsEmpty())
       SetContentType(contentType);
   }
 
   *result = nullptr;
   stream.swap(*result);
--- a/netwerk/protocol/file/nsFileChannel.h
+++ b/netwerk/protocol/file/nsFileChannel.h
@@ -23,17 +23,17 @@ public:
   nsFileChannel(nsIURI *uri);
 
 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);
+                               nsCString &contentType, bool async);
 
   virtual nsresult OpenContentStream(bool async, nsIInputStream **result,
                                      nsIChannel** channel);
 
 private:
   nsCOMPtr<nsIInputStream> mUploadStream;
   int64_t mUploadLength;
 };