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 116759 b027df4ba1e8f2c1ade179f90bbb6cb70bf40861
parent 116758 9268740945659fbd43cf25580c7baff9c8c9ecc2
child 116760 f818459666b292dbe2703e15009f5aef1bd89ffb
push id2735
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 23:12:38 +0000
treeherdermozilla-aurora@b3950b0ad29a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs282432
milestone19.0a1
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;
 };