Bug 988816 - Allow to keep file descriptor in JAR cache. r=aklotz, jduell
authorShian-Yow Wu <swu@mozilla.com>
Fri, 18 Jul 2014 10:46:24 +0800
changeset 194831 f7de657a37ed109072f19e1dffe4867f856a5047
parent 194830 8912d2088eee28737b418afd8cd1e246fc97c6e7
child 194832 a5446bb5fa7d082fb022af063811343a57f15376
push id27157
push userryanvm@gmail.com
push dateFri, 18 Jul 2014 19:00:26 +0000
treeherdermozilla-central@ecdb409898a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz, jduell
bugs988816
milestone33.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 988816 - Allow to keep file descriptor in JAR cache. r=aklotz, jduell
modules/libjar/nsIZipReader.idl
modules/libjar/nsJAR.cpp
modules/libjar/nsJAR.h
modules/libjar/nsJARChannel.cpp
modules/libjar/nsZipArchive.cpp
modules/libjar/nsZipArchive.h
netwerk/ipc/RemoteOpenFileChild.cpp
netwerk/ipc/RemoteOpenFileChild.h
--- a/modules/libjar/nsIZipReader.idl
+++ b/modules/libjar/nsIZipReader.idl
@@ -1,16 +1,22 @@
 /* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
+%{C++
+struct PRFileDesc;
+%}
+
+[ptr] native PRFileDescStar(PRFileDesc);
+
 interface nsIUTF8StringEnumerator;
 interface nsIInputStream;
 interface nsIFile;
 interface nsICertificatePrincipal;
 
 [scriptable, uuid(fad6f72f-13d8-4e26-9173-53007a4afe71)]
 interface nsIZipEntry : nsISupports
 {
@@ -187,17 +193,17 @@ interface nsIZipReader : nsISupports
     nsICertificatePrincipal getCertificatePrincipal(in AUTF8String aEntryName);   
     
     readonly attribute uint32_t manifestEntriesCount;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIZipReaderCache
 
-[scriptable, uuid(748050ac-3ab6-4472-bc2a-cb1564ac6a81)]
+[scriptable, uuid(94ecd586-d405-4801-93d3-8ac7bef81bde)]
 interface nsIZipReaderCache : nsISupports
 {
     /**
      * Initializes a new zip reader cache. 
      * @param cacheSize - the number of released entries to maintain before
      *   beginning to throw some out (note that the number of outstanding
      *   entries can be much greater than this number -- this is the count
      *   for those otherwise unused entries)
@@ -223,16 +229,30 @@ interface nsIZipReaderCache : nsISupport
     bool isCached(in nsIFile zipFile);
 
     /**
      * Returns a (possibly shared) nsIZipReader for a zip inside another zip
      *
      * See getZip
      */
     nsIZipReader getInnerZip(in nsIFile zipFile, in AUTF8String zipEntry);
+
+    /**
+     * Whether to keep NSPR file descriptor for newly opened files in the cache.
+     * When aMustCacheFd is enabled and a file is given, the file will be flushed
+     * from the cache if its file descriptor was not cached.
+     * Note: currently not supported on Windows platform.
+     */
+    void setMustCacheFd(in nsIFile zipFile, in bool aMustCacheFd);
+
+    /**
+     * Returns the cached NSPR file descriptor of the file.
+     * Note: currently not supported on Windows platform.
+     */
+    PRFileDescStar getFd(in nsIFile zipFile);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
 %{C++
 
 #define NS_ZIPREADER_CID                             \
 { /* 88e2fd0b-f7f4-480c-9483-7846b00e8dad */         \
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -136,17 +136,17 @@ nsJAR::Open(nsIFile* zipFile)
 
   // The omnijar is special, it is opened early on and closed late
   // this avoids reopening it
   nsRefPtr<nsZipArchive> zip = mozilla::Omnijar::GetReader(zipFile);
   if (zip) {
     mZip = zip;
     return NS_OK;
   }
-  return mZip->OpenArchive(zipFile);
+  return mZip->OpenArchive(zipFile, mCache ? mCache->IsMustCacheFdEnabled() : false);
 }
 
 NS_IMETHODIMP
 nsJAR::OpenInner(nsIZipReader *aZipReader, const nsACString &aZipEntry)
 {
   NS_ENSURE_ARG_POINTER(aZipReader);
   if (mOpened) return NS_ERROR_FAILURE; // Already open!
 
@@ -386,16 +386,36 @@ nsJAR::GetManifestEntriesCount(uint32_t*
 nsresult
 nsJAR::GetJarPath(nsACString& aResult)
 {
   NS_ENSURE_ARG_POINTER(mZipFile);
 
   return mZipFile->GetNativePath(aResult);
 }
 
+nsresult
+nsJAR::GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc)
+{
+  if (!aNSPRFileDesc) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  *aNSPRFileDesc = nullptr;
+
+  if (!mZip) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsRefPtr<nsZipHandle> handle = mZip->GetFD();
+  if (!handle) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return handle->GetNSPRFileDesc(aNSPRFileDesc);
+}
+
 //----------------------------------------------
 // nsJAR private implementation
 //----------------------------------------------
 nsresult
 nsJAR::LoadEntry(const nsACString &aFilename, char** aBuf, uint32_t* aBufLen)
 {
   //-- Get a stream for reading the file
   nsresult rv;
@@ -1004,16 +1024,17 @@ nsJARItem::GetPermissions(uint32_t* aPer
 ////////////////////////////////////////////////////////////////////////////////
 // nsIZipReaderCache
 
 NS_IMPL_ISUPPORTS(nsZipReaderCache, nsIZipReaderCache, nsIObserver, nsISupportsWeakReference)
 
 nsZipReaderCache::nsZipReaderCache()
   : mLock("nsZipReaderCache.mLock")
   , mZips(16)
+  , mMustCacheFd(false)
 #ifdef ZIP_CACHE_HIT_RATE
     ,
     mZipCacheLookups(0),
     mZipCacheHits(0),
     mZipCacheFlushes(0),
     mZipSyncMisses(0)
 #endif
 {
@@ -1099,17 +1120,16 @@ nsZipReaderCache::GetZip(nsIFile* zipFil
   if (zip) {
 #ifdef ZIP_CACHE_HIT_RATE
     mZipCacheHits++;
 #endif
     zip->ClearReleaseTime();
   } else {
     zip = new nsJAR();
     zip->SetZipReaderCache(this);
-
     rv = zip->Open(zipFile);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     MOZ_ASSERT(!mZips.Contains(uri));
     mZips.Put(uri, zip);
   }
@@ -1157,16 +1177,97 @@ nsZipReaderCache::GetInnerZip(nsIFile* z
 
     MOZ_ASSERT(!mZips.Contains(uri));
     mZips.Put(uri, zip);
   }
   zip.forget(result);
   return rv;
 }
 
+NS_IMETHODIMP
+nsZipReaderCache::SetMustCacheFd(nsIFile* zipFile, bool aMustCacheFd)
+{
+#if defined(XP_WIN)
+  MOZ_CRASH("Not implemented");
+  return NS_ERROR_NOT_IMPLEMENTED;
+#else
+  mMustCacheFd = aMustCacheFd;
+
+  if (!aMustCacheFd) {
+    return NS_OK;
+  }
+
+  if (!zipFile) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsresult rv;
+  nsAutoCString uri;
+  rv = zipFile->GetNativePath(uri);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  uri.Insert(NS_LITERAL_CSTRING("file:"), 0);
+
+  MutexAutoLock lock(mLock);
+  nsRefPtr<nsJAR> zip;
+  mZips.Get(uri, getter_AddRefs(zip));
+  if (!zip) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Flush the file from the cache if its file descriptor was not cached.
+  PRFileDesc* fd = nullptr;
+  zip->GetNSPRFileDesc(&fd);
+  if (!fd) {
+#ifdef ZIP_CACHE_HIT_RATE
+    mZipCacheFlushes++;
+#endif
+    zip->SetZipReaderCache(nullptr);
+    mZips.Remove(uri);
+  }
+  return NS_OK;
+#endif /* XP_WIN */
+}
+
+NS_IMETHODIMP
+nsZipReaderCache::GetFd(nsIFile* zipFile, PRFileDesc** aRetVal)
+{
+#if defined(XP_WIN)
+  MOZ_CRASH("Not implemented");
+  return NS_ERROR_NOT_IMPLEMENTED;
+#else
+  if (!zipFile) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsresult rv;
+  nsAutoCString uri;
+  rv = zipFile->GetNativePath(uri);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  uri.Insert(NS_LITERAL_CSTRING("file:"), 0);
+
+  MutexAutoLock lock(mLock);
+  nsRefPtr<nsJAR> zip;
+  mZips.Get(uri, getter_AddRefs(zip));
+  if (!zip) {
+    return NS_ERROR_FAILURE;
+  }
+
+  zip->ClearReleaseTime();
+  rv = zip->GetNSPRFileDesc(aRetVal);
+  // Do this to avoid possible deadlock on mLock with ReleaseZip().
+  MutexAutoUnlock unlock(mLock);
+  nsRefPtr<nsJAR> zipTemp = zip.forget();
+  return rv;
+#endif /* XP_WIN */
+}
+
 static PLDHashOperator
 FindOldestZip(const nsACString &aKey, nsJAR* aZip, void* aClosure)
 {
   nsJAR** oldestPtr = static_cast<nsJAR**>(aClosure);
   nsJAR* oldest = *oldestPtr;
   nsJAR* current = aZip;
   PRIntervalTime currentReleaseTime = current->GetReleaseTime();
   if (currentReleaseTime != PR_INTERVAL_NO_TIMEOUT) {
--- a/modules/libjar/nsJAR.h
+++ b/modules/libjar/nsJAR.h
@@ -90,16 +90,18 @@ class nsJAR : public nsIZipReader
     void ClearReleaseTime() {
       mReleaseTime = PR_INTERVAL_NO_TIMEOUT;
     }
 
     void SetZipReaderCache(nsZipReaderCache* cache) {
       mCache = cache;
     }
 
+    nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc);
+
   protected:
     typedef nsClassHashtable<nsCStringHashKey, nsJARManifestItem> ManifestDataHashtable;
 
     //-- Private data members
     nsCOMPtr<nsIFile>        mZipFile;        // The zip/jar file on disk
     nsCString                mOuterZipEntry;  // The entry in the zip this zip is reading from
     nsRefPtr<nsZipArchive>   mZip;            // The underlying zip archive
     ManifestDataHashtable    mManifestData;   // Stores metadata for each entry
@@ -190,25 +192,30 @@ public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIZIPREADERCACHE
   NS_DECL_NSIOBSERVER
 
   nsZipReaderCache();
 
   nsresult ReleaseZip(nsJAR* reader);
 
+  bool IsMustCacheFdEnabled() {
+    return mMustCacheFd;
+  }
+
   typedef nsRefPtrHashtable<nsCStringHashKey, nsJAR> ZipsHashtable;
 
 protected:
 
   virtual ~nsZipReaderCache();
 
   mozilla::Mutex        mLock;
   uint32_t              mCacheSize;
   ZipsHashtable         mZips;
+  bool                  mMustCacheFd;
 
 #ifdef ZIP_CACHE_HIT_RATE
   uint32_t              mZipCacheLookups;
   uint32_t              mZipCacheHits;
   uint32_t              mZipCacheFlushes;
   uint32_t              mZipSyncMisses;
 #endif
 
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -17,16 +17,17 @@
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsIFileURL.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/net/RemoteOpenFileChild.h"
 #include "nsITabChild.h"
+#include "private/pprio.h"
 
 using namespace mozilla;
 using namespace mozilla::net;
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 // the entry for a directory will either be empty (in the case of the
 // top-level directory) or will end with a slash
@@ -352,36 +353,61 @@ nsJARChannel::LookupFile()
         rv = mJarBaseURI->GetScheme(scheme);
         if (NS_SUCCEEDED(rv) && scheme.EqualsLiteral("remoteopenfile")) {
             nsRefPtr<RemoteOpenFileChild> remoteFile = new RemoteOpenFileChild();
             rv = remoteFile->Init(mJarBaseURI, mAppURI);
             NS_ENSURE_SUCCESS(rv, rv);
             mJarFile = remoteFile;
 
             nsIZipReaderCache *jarCache = gJarHandler->JarCache();
-            if (jarCache && !mEnsureChildFd) {
+            if (jarCache) {
                 bool cached = false;
                 rv = jarCache->IsCached(mJarFile, &cached);
                 if (NS_SUCCEEDED(rv) && cached) {
                     // zipcache already has file mmapped: don't open on parent,
-                    // just return and proceed to cache hit in CreateJarInput()
+                    // just return and proceed to cache hit in CreateJarInput().
+                    // When the file descriptor is needed, get it from JAR cache
+                    // if available, otherwise do the remote open to get a new
+                    // one.
+                    #if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
+                    // Windows/OSX desktop builds skip remoting, we don't need
+                    // file descriptor here.
                     return NS_OK;
+                    #else
+                    if (!mEnsureChildFd) {
+                        return NS_OK;
+                    }
+                    PRFileDesc *fd = nullptr;
+                    jarCache->GetFd(mJarFile, &fd);
+                    if (fd) {
+                        PROsfd osfd = dup(PR_FileDesc2NativeHandle(fd));
+                        if (osfd == -1) {
+                            return NS_ERROR_FAILURE;
+                        }
+                        remoteFile->SetNSPRFileDesc(PR_ImportFile(osfd));
+                        return NS_OK;
+                    }
+                    #endif
                 }
             }
 
             mOpeningRemote = true;
 
             if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this) &&
                 !mEnsureChildFd) {
                 // JarHandler will trigger OnRemoteFileOpen() after the first
                 // request for this file completes and we'll get a JAR cache
                 // hit.
                 return NS_OK;
             }
 
+            if (mEnsureChildFd && jarCache) {
+                jarCache->SetMustCacheFd(remoteFile, true);
+            }
+
             // Open file on parent: OnRemoteFileOpenComplete called when done
             nsCOMPtr<nsITabChild> tabChild;
             NS_QueryNotificationCallbacks(this, tabChild);
             nsCOMPtr<nsILoadContext> loadContext;
             NS_QueryNotificationCallbacks(this, loadContext);
             rv = remoteFile->AsyncRemoteFileOpen(PR_RDONLY, this, tabChild,
                                                  loadContext);
             NS_ENSURE_SUCCESS(rv, rv);
@@ -1039,17 +1065,21 @@ nsJARChannel::OnStopRequest(nsIRequest *
     mPump = 0;
     mIsPending = false;
     mDownloader = 0; // this may delete the underlying jar file
 
     // Drop notification callbacks to prevent cycles.
     mCallbacks = 0;
     mProgressSink = 0;
 
-    if (mOpeningRemote) {
+    if (mEnsureChildFd) {
+      nsIZipReaderCache *jarCache = gJarHandler->JarCache();
+      if (jarCache) {
+          jarCache->SetMustCacheFd(mJarFile, false);
+      }
       // To deallocate file descriptor by RemoteOpenFileChild destructor.
       mJarFile = nullptr;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/modules/libjar/nsZipArchive.cpp
+++ b/modules/libjar/nsZipArchive.cpp
@@ -166,17 +166,18 @@ nsZipHandle::nsZipHandle()
   , mRefCnt(0)
 {
   MOZ_COUNT_CTOR(nsZipHandle);
 }
 
 NS_IMPL_ADDREF(nsZipHandle)
 NS_IMPL_RELEASE(nsZipHandle)
 
-nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret, PRFileDesc **aFd)
+nsresult nsZipHandle::Init(nsIFile *file, bool aMustCacheFd, nsZipHandle **ret,
+                           PRFileDesc **aFd)
 {
   mozilla::AutoFDClose fd;
   int32_t flags = PR_RDONLY;
 #if defined(XP_WIN)
   flags |= nsIFile::OS_READAHEAD;
 #endif
   nsresult rv = file->OpenNSPRFileDesc(flags, 0000, &fd.rwget());
   if (NS_FAILED(rv))
@@ -203,16 +204,20 @@ nsresult nsZipHandle::Init(nsIFile *file
     PR_CloseFileMap(map);
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
 #if defined(XP_WIN)
   if (aFd) {
     *aFd = fd.forget();
   }
+#else
+  if (aMustCacheFd) {
+    handle->mNSPRFileDesc = fd.forget();
+  }
 #endif
   handle->mMap = map;
   handle->mFile.Init(file);
   handle->mLen = (uint32_t) size;
   handle->mFileData = buf;
   handle.forget(ret);
   return NS_OK;
 }
@@ -239,16 +244,26 @@ nsresult nsZipHandle::Init(nsZipArchive 
   return NS_OK;
 }
 
 int64_t nsZipHandle::SizeOfMapping()
 {
     return mLen;
 }
 
+nsresult nsZipHandle::GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc)
+{
+  if (!aNSPRFileDesc) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+
+  *aNSPRFileDesc = mNSPRFileDesc;
+  return NS_OK;
+}
+
 nsZipHandle::~nsZipHandle()
 {
   if (mMap) {
     PR_MemUnmap((void *)mFileData, mLen);
     PR_CloseFileMap(mMap);
   }
   mFileData = nullptr;
   mMap = nullptr;
@@ -274,24 +289,25 @@ nsresult nsZipArchive::OpenArchive(nsZip
   nsresult rv = BuildFileList(aFd);
   if (NS_SUCCEEDED(rv)) {
     if (aZipHandle->mFile)
       aZipHandle->mFile.GetURIString(mURI);
   }
   return rv;
 }
 
-nsresult nsZipArchive::OpenArchive(nsIFile *aFile)
+nsresult nsZipArchive::OpenArchive(nsIFile *aFile, bool aMustCacheFd)
 {
   nsRefPtr<nsZipHandle> handle;
 #if defined(XP_WIN)
   mozilla::AutoFDClose fd;
-  nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle), &fd.rwget());
+  nsresult rv = nsZipHandle::Init(aFile, aMustCacheFd, getter_AddRefs(handle),
+                                  &fd.rwget());
 #else
-  nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle));
+  nsresult rv = nsZipHandle::Init(aFile, aMustCacheFd, getter_AddRefs(handle));
 #endif
   if (NS_FAILED(rv))
     return rv;
 
 #if defined(XP_WIN)
   return OpenArchive(handle, fd.get());
 #else
   return OpenArchive(handle);
--- a/modules/libjar/nsZipArchive.h
+++ b/modules/libjar/nsZipArchive.h
@@ -115,20 +115,21 @@ public:
    */
   nsresult OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd = nullptr);
 
   /** 
    * OpenArchive 
    * 
    * Convenience function that generates nsZipHandle
    *
-   * @param   aFile  The file used to access the zip
+   * @param   aFile         The file used to access the zip
+   * @param   aMustCacheFd  Optional flag to keep the PRFileDesc in nsZipHandle
    * @return  status code
    */
-  nsresult OpenArchive(nsIFile *aFile);
+  nsresult OpenArchive(nsIFile *aFile, bool aMustCacheFd = false);
 
   /**
    * Test the integrity of items in this archive by running
    * a CRC check after extracting each item into a memory 
    * buffer.  If an entry name is supplied only the 
    * specified item is tested.  Else, if null is supplied
    * then all the items in the archive are tested.
    *
@@ -375,36 +376,39 @@ public:
     return ret;
   }
 };
 
 class nsZipHandle {
 friend class nsZipArchive;
 friend class mozilla::FileLocation;
 public:
-  static nsresult Init(nsIFile *file, nsZipHandle **ret,
+  static nsresult Init(nsIFile *file, bool aMustCacheFd, nsZipHandle **ret,
                        PRFileDesc **aFd = nullptr);
   static nsresult Init(nsZipArchive *zip, const char *entry,
                        nsZipHandle **ret);
 
   NS_METHOD_(MozExternalRefCountType) AddRef(void);
   NS_METHOD_(MozExternalRefCountType) Release(void);
 
   int64_t SizeOfMapping();
 
+  nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc);
+
 protected:
   const uint8_t * mFileData; /* pointer to mmaped file */
   uint32_t        mLen;      /* length of file and memory mapped area */
   mozilla::FileLocation mFile; /* source file if any, for logging */
 
 private:
   nsZipHandle();
   ~nsZipHandle();
 
   PRFileMap *                       mMap;    /* nspr datastructure for mmap */
+  mozilla::AutoFDClose              mNSPRFileDesc;
   nsAutoPtr<nsZipItemPtr<uint8_t> > mBuf;
   mozilla::ThreadSafeAutoRefCnt     mRefCnt; /* ref count */
   NS_DECL_OWNINGTHREAD
 };
 
 nsresult gZlibInit(z_stream *zs);
 
 #endif /* nsZipArchive_h_ */
--- a/netwerk/ipc/RemoteOpenFileChild.cpp
+++ b/netwerk/ipc/RemoteOpenFileChild.cpp
@@ -244,16 +244,28 @@ RemoteOpenFileChild::AsyncRemoteFileOpen
   AddIPDLReference();
 
   mListener = aListener;
   mAsyncOpenCalled = true;
   return NS_OK;
 #endif
 }
 
+nsresult
+RemoteOpenFileChild::SetNSPRFileDesc(PRFileDesc* aNSPRFileDesc)
+{
+  MOZ_ASSERT(!mNSPRFileDesc);
+  if (mNSPRFileDesc) {
+    return NS_ERROR_ALREADY_OPENED;
+  }
+
+  mNSPRFileDesc = aNSPRFileDesc;
+  return NS_OK;
+}
+
 void
 RemoteOpenFileChild::OnCachedFileDescriptor(const nsAString& aPath,
                                             const FileDescriptor& aFD)
 {
 #ifdef DEBUG
   if (!aPath.IsEmpty()) {
     MOZ_ASSERT(mFile);
 
--- a/netwerk/ipc/RemoteOpenFileChild.h
+++ b/netwerk/ipc/RemoteOpenFileChild.h
@@ -72,16 +72,18 @@ public:
   // Send message to parent to tell it to open file handle for file.
   // TabChild is required, for IPC security.
   // Note: currently only PR_RDONLY is supported for 'flags'
   nsresult AsyncRemoteFileOpen(int32_t aFlags,
                                nsIRemoteOpenFileListener* aListener,
                                nsITabChild* aTabChild,
                                nsILoadContext *aLoadContext);
 
+  nsresult SetNSPRFileDesc(PRFileDesc* aNSPRFileDesc);
+
   void ReleaseIPDLReference()
   {
     Release();
   }
 
 private:
   RemoteOpenFileChild(const RemoteOpenFileChild& other);