Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 09 Feb 2013 11:00:05 -0500
changeset 131312 3758b066f5aeb41c1ee7e605ed7e4ab38e1141ff
parent 131311 91a509f46a4907d2c7bb85289f166acde812d404 (current diff)
parent 131306 08388ff940dfe3e9b8fe4d23818ab991e1617332 (diff)
child 131313 c56fb4d49ea7ae2c35555aa110d49fffa461376a
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone21.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
Merge m-c to inbound.
dom/ipc/nsICachedFileDescriptorListener.h
ipc/glue/FileDescriptorUtils.cpp
ipc/glue/FileDescriptorUtils.h
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -17,20 +17,17 @@ EXPORT_LIBRARY = 1
 ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
 endif # !_MSC_VER
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 TEST_DIRS += tests
 endif
 
-EXPORTS = \
-  nsICachedFileDescriptorListener.h \
-  PCOMContentPermissionRequestChild.h \
-  $(NULL)
+EXPORTS = PCOMContentPermissionRequestChild.h
 
 EXPORTS_NAMESPACES = \
   mozilla \
   mozilla/dom \
   mozilla/dom/ipc \
   $(NULL)
 
 EXPORTS_mozilla = \
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -26,17 +26,16 @@ include "mozilla/layout/RenderFrameUtils
 
 using IPC::Principal;
 using gfxMatrix;
 using gfxRect;
 using gfxSize;
 using mozilla::layers::LayersBackend;
 using mozilla::layers::FrameMetrics;
 using mozilla::layout::ScrollingBehavior;
-using mozilla::void_t;
 using mozilla::WindowsHandle;
 using nscolor;
 using nsCompositionEvent;
 using nsIMEUpdatePreference;
 using nsIntPoint;
 using nsIntRect;
 using nsIntSize;
 using nsKeyEvent;
@@ -286,18 +285,16 @@ child:
      * |Show()| and |Move()| take IntSizes rather than Rects because
      * content processes always render to a virtual <0, 0> top-left
      * point.
      */
     Show(nsIntSize size);
 
     LoadURL(nsCString uri);
 
-    CacheFileDescriptor(nsString path, FileDescriptor fd);
-
     UpdateDimensions(nsRect rect, nsIntSize size, ScreenOrientation orientation) compress;
 
     UpdateFrame(FrameMetrics frame) compress;
 
     /**
      * Requests handling of a double tap. |point| is in CSS pixels, relative to
      * the scroll offset. This message is expected to round-trip back to
      * ZoomToRect() with a rect indicating where we should zoom to.
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -13,17 +13,16 @@
 #include "ContentChild.h"
 #include "IndexedDBChild.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/IntentionalCrash.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
 #include "mozilla/dom/PContentChild.h"
 #include "mozilla/dom/PContentDialogChild.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
-#include "mozilla/ipc/FileDescriptorUtils.h"
 #include "mozilla/layers/AsyncPanZoomController.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layout/RenderFrameChild.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/unused.h"
 #include "mozIApplication.h"
 #include "nsComponentManagerUtils.h"
@@ -33,17 +32,16 @@
 #include "nsEventListenerManager.h"
 #include <algorithm>
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 #include "mozilla/dom/Element.h"
 #include "nsIAppsService.h"
 #include "nsIBaseWindow.h"
-#include "nsICachedFileDescriptorListener.h"
 #include "nsIComponentManager.h"
 #include "nsIDocumentInlines.h"
 #include "nsIDOMClassInfo.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIDocShell.h"
@@ -118,108 +116,16 @@ ContentListener::HandleEvent(nsIDOMEvent
 
 class ContentDialogChild : public PContentDialogChild
 {
 public:
   virtual bool Recv__delete__(const InfallibleTArray<int>& aIntParams,
                               const InfallibleTArray<nsString>& aStringParams);
 };
 
-class TabChild::CachedFileDescriptorInfo
-{
-    struct PathOnlyComparatorHelper
-    {
-        bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
-                    const CachedFileDescriptorInfo& b) const
-        {
-            return a->mPath == b.mPath;
-        }
-    };
-
-    struct PathAndCallbackComparatorHelper
-    {
-        bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
-                    const CachedFileDescriptorInfo& b) const
-        {
-            return a->mPath == b.mPath &&
-                   a->mCallback == b.mCallback;
-        }
-    };
-
-public:
-    nsString mPath;
-    FileDescriptor mFileDescriptor;
-    nsCOMPtr<nsICachedFileDescriptorListener> mCallback;
-    bool mCanceled;
-
-    CachedFileDescriptorInfo(const nsAString& aPath)
-      : mPath(aPath), mCanceled(false)
-    { }
-
-    CachedFileDescriptorInfo(const nsAString& aPath,
-                             const FileDescriptor& aFileDescriptor)
-      : mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false)
-    { }
-
-    CachedFileDescriptorInfo(const nsAString& aPath,
-                             nsICachedFileDescriptorListener* aCallback)
-      : mPath(aPath), mCallback(aCallback), mCanceled(false)
-    { }
-
-    PathOnlyComparatorHelper PathOnlyComparator() const
-    {
-        return PathOnlyComparatorHelper();
-    }
-
-    PathAndCallbackComparatorHelper PathAndCallbackComparator() const
-    {
-        return PathAndCallbackComparatorHelper();
-    }
-
-    void FireCallback() const
-    {
-        mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor);
-    }
-};
-
-class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable
-{
-    typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo;
-
-    nsAutoPtr<CachedFileDescriptorInfo> mInfo;
-
-public:
-    CachedFileDescriptorCallbackRunnable(CachedFileDescriptorInfo* aInfo)
-      : mInfo(aInfo)
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-        MOZ_ASSERT(aInfo);
-        MOZ_ASSERT(!aInfo->mPath.IsEmpty());
-        MOZ_ASSERT(aInfo->mCallback);
-    }
-
-    void Dispatch()
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-
-        nsresult rv = NS_DispatchToCurrentThread(this);
-        NS_ENSURE_SUCCESS_VOID(rv);
-    }
-
-private:
-    NS_IMETHOD Run()
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-        MOZ_ASSERT(mInfo);
-
-        mInfo->FireCallback();
-        return NS_OK;
-    }
-};
-
 StaticRefPtr<TabChild> sPreallocatedTab;
 
 /*static*/ void
 TabChild::PreloadSlowThings()
 {
     MOZ_ASSERT(!sPreallocatedTab);
 
     nsRefPtr<TabChild> tab(new TabChild(TabContext(), /* chromeFlags */ 0));
@@ -1206,140 +1112,16 @@ TabChild::RecvLoadURL(const nsCString& u
 
 #ifdef MOZ_CRASHREPORTER
     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), uri);
 #endif
 
     return true;
 }
 
-bool
-TabChild::RecvCacheFileDescriptor(const nsString& aPath,
-                                  const FileDescriptor& aFileDescriptor)
-{
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(!aPath.IsEmpty());
-
-    // aFileDescriptor may be invalid here, but the callback will choose how to
-    // handle it.
-
-    // First see if we already have a request for this path.
-    const CachedFileDescriptorInfo search(aPath);
-    uint32_t index =
-        mCachedFileDescriptorInfos.IndexOf(search, 0,
-                                           search.PathOnlyComparator());
-    if (index == mCachedFileDescriptorInfos.NoIndex) {
-        // We haven't had any requests for this path yet. Assume that we will
-        // in a little while and save the file descriptor here.
-        mCachedFileDescriptorInfos.AppendElement(
-            new CachedFileDescriptorInfo(aPath, aFileDescriptor));
-        return true;
-    }
-
-    nsAutoPtr<CachedFileDescriptorInfo>& info =
-        mCachedFileDescriptorInfos[index];
-
-    MOZ_ASSERT(info);
-    MOZ_ASSERT(info->mPath == aPath);
-    MOZ_ASSERT(!info->mFileDescriptor.IsValid());
-    MOZ_ASSERT(info->mCallback);
-
-    // If this callback has been canceled then we can simply close the file
-    // descriptor and forget about the callback.
-    if (info->mCanceled) {
-        // Only close if this is a valid file descriptor.
-        if (aFileDescriptor.IsValid()) {
-            nsRefPtr<CloseFileRunnable> runnable =
-                new CloseFileRunnable(aFileDescriptor);
-            runnable->Dispatch();
-        }
-    } else {
-        // Not canceled so fire the callback.
-        info->mFileDescriptor = aFileDescriptor;
-
-        // We don't need a runnable here because we should already be at the top
-        // of the event loop. Just fire immediately.
-        info->FireCallback();
-    }
-
-    mCachedFileDescriptorInfos.RemoveElementAt(index);
-    return true;
-}
-
-bool
-TabChild::GetCachedFileDescriptor(const nsAString& aPath,
-                                  nsICachedFileDescriptorListener* aCallback)
-{
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(!aPath.IsEmpty());
-    MOZ_ASSERT(aCallback);
-
-    // First see if we've already received a cached file descriptor for this
-    // path.
-    const CachedFileDescriptorInfo search(aPath);
-    uint32_t index =
-        mCachedFileDescriptorInfos.IndexOf(search, 0,
-                                           search.PathOnlyComparator());
-    if (index == mCachedFileDescriptorInfos.NoIndex) {
-        // We haven't received a file descriptor for this path yet. Assume that
-        // we will in a little while and save the request here.
-        mCachedFileDescriptorInfos.AppendElement(
-            new CachedFileDescriptorInfo(aPath, aCallback));
-        return false;
-    }
-
-    nsAutoPtr<CachedFileDescriptorInfo>& info =
-        mCachedFileDescriptorInfos[index];
-
-    MOZ_ASSERT(info);
-    MOZ_ASSERT(info->mPath == aPath);
-    MOZ_ASSERT(!info->mCallback);
-    MOZ_ASSERT(!info->mCanceled);
-
-    info->mCallback = aCallback;
-
-    nsRefPtr<CachedFileDescriptorCallbackRunnable> runnable =
-        new CachedFileDescriptorCallbackRunnable(info);
-    runnable->Dispatch();
-
-    mCachedFileDescriptorInfos.RemoveElementAt(index);
-    return true;
-}
-
-void
-TabChild::CancelCachedFileDescriptorCallback(
-                                     const nsAString& aPath,
-                                     nsICachedFileDescriptorListener* aCallback)
-{
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(!aPath.IsEmpty());
-    MOZ_ASSERT(aCallback);
-
-    const CachedFileDescriptorInfo search(aPath, aCallback);
-    uint32_t index =
-        mCachedFileDescriptorInfos.IndexOf(search, 0,
-                                           search.PathAndCallbackComparator());
-    if (index == mCachedFileDescriptorInfos.NoIndex) {
-        // Nothing to do here.
-        return;
-    }
-
-    nsAutoPtr<CachedFileDescriptorInfo>& info =
-        mCachedFileDescriptorInfos[index];
-
-    MOZ_ASSERT(info);
-    MOZ_ASSERT(info->mPath == aPath);
-    MOZ_ASSERT(!info->mFileDescriptor.IsValid());
-    MOZ_ASSERT(info->mCallback == aCallback);
-    MOZ_ASSERT(!info->mCanceled);
-
-    // Set this flag so that we will close the file descriptor when it arrives.
-    info->mCanceled = true;
-}
-
 void
 TabChild::DoFakeShow()
 {
   RecvShow(nsIntSize(0, 0));
   mDidFakeShow = true;
 }
 
 bool
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -49,17 +49,16 @@
 #include "nsWeakReference.h"
 #include "nsITabChild.h"
 #include "mozilla/Attributes.h"
 #include "FrameMetrics.h"
 #include "ProcessUtils.h"
 #include "mozilla/dom/TabContext.h"
 
 struct gfxMatrix;
-class nsICachedFileDescriptorListener;
 
 namespace mozilla {
 namespace layout {
 class RenderFrameChild;
 }
 
 namespace dom {
 
@@ -192,19 +191,16 @@ public:
      */
     virtual bool DoSendSyncMessage(const nsAString& aMessage,
                                    const mozilla::dom::StructuredCloneData& aData,
                                    InfallibleTArray<nsString>* aJSONRetVal);
     virtual bool DoSendAsyncMessage(const nsAString& aMessage,
                                     const mozilla::dom::StructuredCloneData& aData);
 
     virtual bool RecvLoadURL(const nsCString& uri);
-    virtual bool RecvCacheFileDescriptor(const nsString& aPath,
-                                         const FileDescriptor& aFileDescriptor)
-                                         MOZ_OVERRIDE;
     virtual bool RecvShow(const nsIntSize& size);
     virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const ScreenOrientation& orientation);
     virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
     virtual bool RecvHandleDoubleTap(const nsIntPoint& aPoint);
     virtual bool RecvHandleSingleTap(const nsIntPoint& aPoint);
     virtual bool RecvHandleLongTap(const nsIntPoint& aPoint);
     virtual bool RecvActivate();
     virtual bool RecvDeactivate();
@@ -316,25 +312,16 @@ public:
     /**
      * Get this object's app type.
      *
      * A TabChild's app type corresponds to the value of its frame element's
      * "mozapptype" attribute.
      */
     void GetAppType(nsAString& aAppType) const { aAppType = mAppType; }
 
-    // Returns true if the file descriptor was found in the cache, false
-    // otherwise.
-    bool GetCachedFileDescriptor(const nsAString& aPath,
-                                 nsICachedFileDescriptorListener* aCallback);
-
-    void CancelCachedFileDescriptorCallback(
-                                    const nsAString& aPath,
-                                    nsICachedFileDescriptorListener* aCallback);
-
 protected:
     virtual PRenderFrameChild* AllocPRenderFrame(ScrollingBehavior* aScrolling,
                                                  LayersBackend* aBackend,
                                                  int32_t* aMaxTextureSize,
                                                  uint64_t* aLayersId) MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrame(PRenderFrameChild* aFrame) MOZ_OVERRIDE;
     virtual bool RecvDestroy() MOZ_OVERRIDE;
 
@@ -420,19 +407,16 @@ private:
 
     nsIDOMWindowUtils* GetDOMWindowUtils()
     {
         nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mWebNav);
         nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
         return utils;
     }
 
-    class CachedFileDescriptorInfo;
-    class CachedFileDescriptorCallbackRunnable;
-
     nsCOMPtr<nsIWebNavigation> mWebNav;
     nsCOMPtr<nsIWidget> mWidget;
     nsCOMPtr<nsIURI> mLastURI;
     FrameMetrics mLastMetrics;
     RenderFrameChild* mRemoteFrame;
     nsRefPtr<TabChildGlobal> mTabChildGlobal;
     uint32_t mChromeFlags;
     nsIntRect mOuterRect;
@@ -441,19 +425,16 @@ private:
     // point of the touchstart.
     nsIntPoint mGestureDownPoint;
     // The touch identifier of the active gesture.
     int32_t mActivePointerId;
     // A timer task that fires if the tap-hold timeout is exceeded by
     // the touch we're tracking.  That is, if touchend or a touchmove
     // that exceeds the gesture threshold doesn't happen.
     CancelableTask* mTapHoldTimer;
-    // At present only 1 of these is really expected.
-    nsAutoTArray<nsAutoPtr<CachedFileDescriptorInfo>, 1>
-        mCachedFileDescriptorInfos;
     float mOldViewportWidth;
     nscolor mLastBackgroundColor;
     ScrollingBehavior mScrolling;
     bool mDidFakeShow;
     bool mNotified;
     bool mContentDocumentIsDisplayed;
     bool mTriedBrowserInit;
     nsString mAppType;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -45,143 +45,32 @@
 #include "nsIWidget.h"
 #include "nsIWindowWatcher.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
 #include "nsSerializationHelper.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
-#include "private/pprio.h"
 #include "StructuredCloneUtils.h"
 #include "TabChild.h"
 #include <algorithm>
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::services;
 using namespace mozilla::widget;
 using namespace mozilla::dom::indexedDB;
 
 // The flags passed by the webProgress notifications are 16 bits shifted
 // from the ones registered by webProgressListeners.
 #define NOTIFY_FLAG_SHIFT 16
 
-class OpenFileAndSendFDRunnable : public nsRunnable
-{
-    const nsString mPath;
-    nsRefPtr<TabParent> mTabParent;
-    nsCOMPtr<nsIEventTarget> mEventTarget;
-    PRFileDesc* mFD;
-
-public:
-    OpenFileAndSendFDRunnable(const nsAString& aPath, TabParent* aTabParent)
-      : mPath(aPath), mTabParent(aTabParent), mFD(nullptr)
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-        MOZ_ASSERT(!aPath.IsEmpty());
-        MOZ_ASSERT(aTabParent);
-    }
-
-    void Dispatch()
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-
-        mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
-        NS_ENSURE_TRUE_VOID(mEventTarget);
-
-        nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
-        NS_ENSURE_SUCCESS_VOID(rv);
-    }
-
-private:
-    ~OpenFileAndSendFDRunnable()
-    {
-        MOZ_ASSERT(!mFD);
-    }
-
-    // This shouldn't be called directly except by the event loop. Use Dispatch
-    // to start the sequence.
-    NS_IMETHOD Run()
-    {
-        if (NS_IsMainThread()) {
-            SendResponse();
-        } else if (mFD) {
-            CloseFile();
-        } else {
-            OpenFile();
-        }
-
-        return NS_OK;
-    }
-
-    void SendResponse()
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-        MOZ_ASSERT(mTabParent);
-        MOZ_ASSERT(mEventTarget);
-        MOZ_ASSERT(mFD);
-
-        nsRefPtr<TabParent> tabParent;
-        mTabParent.swap(tabParent);
-
-        FileDescriptor::PlatformHandleType handle =
-            FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFD));
-
-        mozilla::unused << tabParent->SendCacheFileDescriptor(mPath, handle);
-
-        nsCOMPtr<nsIEventTarget> eventTarget;
-        mEventTarget.swap(eventTarget);
-
-        if (NS_FAILED(eventTarget->Dispatch(this, NS_DISPATCH_NORMAL))) {
-            NS_WARNING("Failed to dispatch to stream transport service!");
-
-            // It's probably safer to take the main thread IO hit here rather
-            // than leak a file descriptor.
-            CloseFile();
-        }
-    }
-
-    void OpenFile()
-    {
-        MOZ_ASSERT(!NS_IsMainThread());
-        MOZ_ASSERT(!mFD);
-
-        nsCOMPtr<nsIFile> file;
-        nsresult rv = NS_NewLocalFile(mPath, false, getter_AddRefs(file));
-        NS_ENSURE_SUCCESS_VOID(rv);
-
-        PRFileDesc* fd;
-        rv = file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
-        NS_ENSURE_SUCCESS_VOID(rv);
-
-        mFD = fd;
-
-        if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
-            NS_WARNING("Failed to dispatch to main thread!");
-
-            CloseFile();
-        }
-    }
-
-    void CloseFile()
-    {
-        // It's possible for this to happen on the main thread if the dispatch
-        // to the stream service fails after we've already opened the file so
-        // we can't assert the thread we're running on.
-
-        MOZ_ASSERT(mFD);
-
-        PR_Close(mFD);
-        mFD = nullptr;
-    }
-};
-
 namespace mozilla {
 namespace dom {
 
 TabParent* sEventCapturer;
 
 TabParent *TabParent::mIMETabParent = nullptr;
 
 NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
@@ -199,17 +88,16 @@ TabParent::TabParent(const TabContext& a
   , mRect(0, 0, 0, 0)
   , mDimensions(0, 0)
   , mOrientation(0)
   , mDPI(0)
   , mShown(false)
   , mUpdatedDimensions(false)
   , mMarkedDestroying(false)
   , mIsDestroyed(false)
-  , mAppPackageFileDescriptorSent(false)
 {
 }
 
 TabParent::~TabParent()
 {
 }
 
 void
@@ -337,76 +225,33 @@ TabParent::AnswerCreateWindow(PBrowserPa
 
     *retval = frameLoader->GetRemoteBrowser();
     return true;
 }
 
 void
 TabParent::LoadURL(nsIURI* aURI)
 {
-    MOZ_ASSERT(aURI);
-
     if (mIsDestroyed) {
-        return;
+      return;
+    }
+    if (!mShown) {
+      nsAutoCString spec;
+      if (aURI) {
+        aURI->GetSpec(spec);
+      }
+      NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
+                                 "Show(). Ignoring LoadURL.\n", spec.get()).get());
+      return;
     }
 
     nsCString spec;
     aURI->GetSpec(spec);
 
-    if (!mShown) {
-        NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
-                                   "Show(). Ignoring LoadURL.\n",
-                                   spec.get()).get());
-        return;
-    }
-
     unused << SendLoadURL(spec);
-
-    // If this app is a packaged app then we can speed startup by sending over
-    // the file descriptor for the "application.zip" file that it will
-    // invariably request. Only do this once.
-    if (!mAppPackageFileDescriptorSent) {
-        mAppPackageFileDescriptorSent = true;
-
-        nsCOMPtr<mozIApplication> app = GetOwnOrContainingApp();
-        if (app) {
-            nsString manifestURL;
-            nsresult rv = app->GetManifestURL(manifestURL);
-            NS_ENSURE_SUCCESS_VOID(rv);
-
-            if (StringBeginsWith(manifestURL, NS_LITERAL_STRING("app:"))) {
-                nsString basePath;
-                rv = app->GetBasePath(basePath);
-                NS_ENSURE_SUCCESS_VOID(rv);
-
-                nsString appId;
-                rv = app->GetId(appId);
-                NS_ENSURE_SUCCESS_VOID(rv);
-
-                nsCOMPtr<nsIFile> packageFile;
-                rv = NS_NewLocalFile(basePath, false,
-                                     getter_AddRefs(packageFile));
-                NS_ENSURE_SUCCESS_VOID(rv);
-
-                rv = packageFile->Append(appId);
-                NS_ENSURE_SUCCESS_VOID(rv);
-
-                rv = packageFile->Append(NS_LITERAL_STRING("application.zip"));
-                NS_ENSURE_SUCCESS_VOID(rv);
-
-                nsString path;
-                rv = packageFile->GetPath(path);
-                NS_ENSURE_SUCCESS_VOID(rv);
-
-                nsRefPtr<OpenFileAndSendFDRunnable> openFileRunnable =
-                    new OpenFileAndSendFDRunnable(path, this);
-                openFileRunnable->Dispatch();
-            }
-        }
-    }
 }
 
 void
 TabParent::Show(const nsIntSize& size)
 {
     // sigh
     mShown = true;
     mDimensions = size;
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -299,16 +299,14 @@ private:
     void MaybeForwardEventToRenderFrame(const nsInputEvent& aEvent,
                                         nsInputEvent* aOutEvent);
     // When true, we've initiated normal shutdown and notified our
     // managing PContent.
     bool mMarkedDestroying;
     // When true, the TabParent is invalid and we should not send IPC messages
     // anymore.
     bool mIsDestroyed;
-    // Whether we have already sent a FileDescriptor for the app package.
-    bool mAppPackageFileDescriptorSent;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
deleted file mode 100644
--- a/dom/ipc/nsICachedFileDescriptorListener.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 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/. */
-
-#ifndef mozilla_dom_ipc_nsICachedFileDescriptorListener_h
-#define mozilla_dom_ipc_nsICachedFileDescriptorListener_h
-
-#include "nsISupports.h"
-
-#ifndef NS_NO_VTABLE
-#define NS_NO_VTABLE
-#endif
-
-#define NS_ICACHEDFILEDESCRIPTORLISTENER_IID \
-  {0x2cedaee0, 0x6ef2, 0x4f60, {0x9a, 0x6c, 0xdf, 0x4e, 0x4d, 0x65, 0x6a, 0xf7}}
-
-class nsAString;
-
-namespace mozilla {
-namespace ipc {
-class FileDescriptor;
-}
-}
-
-class NS_NO_VTABLE nsICachedFileDescriptorListener : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICACHEDFILEDESCRIPTORLISTENER_IID)
-
-  virtual void
-  OnCachedFileDescriptor(const nsAString& aPath,
-                         const mozilla::ipc::FileDescriptor& aFD) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsICachedFileDescriptorListener,
-                              NS_ICACHEDFILEDESCRIPTORLISTENER_IID)
-
-#endif // mozilla_dom_ipc_nsICachedFileDescriptorListener_h
--- a/ipc/glue/FileDescriptor.cpp
+++ b/ipc/glue/FileDescriptor.cpp
@@ -37,18 +37,17 @@ FileDescriptor::FileDescriptor(PlatformH
   mHandleCreatedByOtherProcessWasUsed(false)
 {
   DuplicateInCurrentProcess(aHandle);
 }
 
 void
 FileDescriptor::DuplicateInCurrentProcess(PlatformHandleType aHandle)
 {
-  MOZ_ASSERT_IF(mHandleCreatedByOtherProcess,
-                mHandleCreatedByOtherProcessWasUsed);
+  MOZ_ASSERT(!mHandleCreatedByOtherProcess);
 
   if (IsValid(aHandle)) {
     PlatformHandleType newHandle;
 #ifdef XP_WIN
     if (DuplicateHandle(GetCurrentProcess(), aHandle, GetCurrentProcess(),
                         &newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
 #else // XP_WIN
     if ((newHandle = dup(aHandle)) != INVALID_HANDLE) {
--- a/ipc/glue/FileDescriptor.h
+++ b/ipc/glue/FileDescriptor.h
@@ -48,19 +48,17 @@ public:
   // This should only ever be created by IPDL.
   struct IPDLPrivate
   {};
 
   FileDescriptor();
 
   FileDescriptor(const FileDescriptor& aOther)
   {
-    // Don't use operator= here because that will call
-    // CloseCurrentProcessHandle() on this (uninitialized) object.
-    Assign(aOther);
+    *this = aOther;
   }
 
   FileDescriptor(PlatformHandleType aHandle);
 
   FileDescriptor(const IPDLPrivate&, const PickleType& aPickle)
 #ifdef XP_WIN
   : mHandle(aPickle)
 #else
@@ -74,17 +72,28 @@ public:
   {
     CloseCurrentProcessHandle();
   }
 
   FileDescriptor&
   operator=(const FileDescriptor& aOther)
   {
     CloseCurrentProcessHandle();
-    Assign(aOther);
+
+    if (aOther.mHandleCreatedByOtherProcess) {
+      mHandleCreatedByOtherProcess = true;
+      mHandleCreatedByOtherProcessWasUsed =
+        aOther.mHandleCreatedByOtherProcessWasUsed;
+      mHandle = aOther.PlatformHandle();
+    } else {
+      DuplicateInCurrentProcess(aOther.PlatformHandle());
+      mHandleCreatedByOtherProcess = false;
+      mHandleCreatedByOtherProcessWasUsed = false;
+    }
+
     return *this;
   }
 
   // Performs platform-specific actions to duplicate mHandle in the other
   // process (e.g. dup() on POSIX, DuplicateHandle() on Windows). Returns a
   // pickled value that can be passed to the other process via IPC.
   PickleType
   ShareTo(const IPDLPrivate&, ProcessHandle aOtherProcess) const;
@@ -108,31 +117,16 @@ public:
 
   bool
   operator==(const FileDescriptor& aOther) const
   {
     return mHandle == aOther.mHandle;
   }
 
 private:
-  void
-  Assign(const FileDescriptor& aOther)
-  {
-    if (aOther.mHandleCreatedByOtherProcess) {
-      mHandleCreatedByOtherProcess = true;
-      mHandleCreatedByOtherProcessWasUsed =
-        aOther.mHandleCreatedByOtherProcessWasUsed;
-      mHandle = aOther.PlatformHandle();
-    } else {
-      DuplicateInCurrentProcess(aOther.PlatformHandle());
-      mHandleCreatedByOtherProcess = false;
-      mHandleCreatedByOtherProcessWasUsed = false;
-    }
-  }
-
   static bool
   IsValid(PlatformHandleType aHandle);
 
   void
   DuplicateInCurrentProcess(PlatformHandleType aHandle);
 
   void
   CloseCurrentProcessHandle();
deleted file mode 100644
--- a/ipc/glue/FileDescriptorUtils.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/* 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 "FileDescriptorUtils.h"
-
-#include "nsIEventTarget.h"
-
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsNetCID.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "prio.h"
-#include "private/pprio.h"
-
-using mozilla::ipc::CloseFileRunnable;
-
-#ifdef DEBUG
-
-CloseFileRunnable::CloseFileRunnable(const FileDescriptor& aFileDescriptor)
-: mFileDescriptor(aFileDescriptor)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aFileDescriptor.IsValid());
-}
-
-#endif // DEBUG
-
-CloseFileRunnable::~CloseFileRunnable()
-{
-  if (mFileDescriptor.IsValid()) {
-    // It's probably safer to take the main thread IO hit here rather than leak
-    // the file descriptor.
-    CloseFile();
-  }
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(CloseFileRunnable, nsIRunnable)
-
-void
-CloseFileRunnable::Dispatch()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIEventTarget> eventTarget =
-    do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
-  NS_ENSURE_TRUE_VOID(eventTarget);
-
-  nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS_VOID(rv);
-}
-
-void
-CloseFileRunnable::CloseFile()
-{
-  // It's possible for this to happen on the main thread if the dispatch to the
-  // stream service fails so we can't assert the thread on which we're running.
-
-  MOZ_ASSERT(mFileDescriptor.IsValid());
-
-  PRFileDesc* fd =
-    PR_ImportFile(PROsfd(mFileDescriptor.PlatformHandle()));
-  NS_WARN_IF_FALSE(fd, "Failed to import file handle!");
-
-  mFileDescriptor = FileDescriptor();
-
-  if (fd) {
-    PR_Close(fd);
-    fd = nullptr;
-  }
-}
-
-NS_IMETHODIMP
-CloseFileRunnable::Run()
-{
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  CloseFile();
-  return NS_OK;
-}
deleted file mode 100644
--- a/ipc/glue/FileDescriptorUtils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-/* 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/. */
-
-#ifndef mozilla_ipc_FileDescriptorUtils_h
-#define mozilla_ipc_FileDescriptorUtils_h
-
-#include "mozilla/ipc/FileDescriptor.h"
-#include "nsIRunnable.h"
-
-namespace mozilla {
-namespace ipc {
-
-// When Dispatch() is called (from main thread) this class arranges to close the
-// provided FileDescriptor on one of the socket transport service threads (to
-// avoid main thread I/O).
-class CloseFileRunnable : public nsIRunnable
-{
-  typedef mozilla::ipc::FileDescriptor FileDescriptor;
-
-  FileDescriptor mFileDescriptor;
-
-public:
-  CloseFileRunnable(const FileDescriptor& aFileDescriptor)
-#ifdef DEBUG
-  ;
-#else
-  : mFileDescriptor(aFileDescriptor)
-  { }
-#endif
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  void Dispatch();
-
-private:
-  ~CloseFileRunnable();
-
-  void CloseFile();
-};
-
-} // namespace ipc
-} // namespace mozilla
-
-#endif // mozilla_ipc_FileDescriptorUtils_h
--- a/ipc/glue/Makefile.in
+++ b/ipc/glue/Makefile.in
@@ -21,17 +21,16 @@ EXPORTS_NAMESPACES = ipc mozilla/ipc
 
 EXPORTS_ipc = IPCMessageUtils.h
 
 EXPORTS_mozilla/ipc = \
   AsyncChannel.h \
   BrowserProcessSubThread.h \
   CrossProcessMutex.h \
   FileDescriptor.h \
-  FileDescriptorUtils.h \
   GeckoChildProcessHost.h \
   InputStreamUtils.h \
   IOThreadChild.h \
   ProcessChild.h \
   ProtocolUtils.h \
   RPCChannel.h \
   SharedMemory.h \
   SharedMemoryBasic.h \
@@ -67,17 +66,16 @@ EXPORTS_mozilla/ipc += SharedMemoryBasic
 else
 EXPORTS_mozilla/ipc += SharedMemoryBasic_chromium.h
 endif #}
 
 CPPSRCS += \
   AsyncChannel.cpp \
   BrowserProcessSubThread.cpp \
   FileDescriptor.cpp \
-  FileDescriptorUtils.cpp \
   GeckoChildProcessHost.cpp \
   InputStreamUtils.cpp \
   MessagePump.cpp \
   ProcessChild.cpp \
   ProtocolUtils.cpp \
   RPCChannel.cpp \
   ScopedXREEmbed.cpp \
   SharedMemory.cpp \
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -13,16 +13,17 @@
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIViewSourceChannel.h"
 #include "nsChannelProperties.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsIFileURL.h"
+#include "nsXULAppAPI.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/net/RemoteOpenFileChild.h"
 #include "nsITabChild.h"
 
 using namespace mozilla;
 using namespace mozilla::net;
 
@@ -343,19 +344,19 @@ nsJARChannel::LookupFile()
     // try to get a nsIFile directly from the url, which will often succeed.
     {
         nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mJarBaseURI);
         if (fileURL)
             fileURL->GetFile(getter_AddRefs(mJarFile));
     }
     // if we're in child process and have special "remoteopenfile:://" scheme,
     // create special nsIFile that gets file handle from parent when opened.
-    if (!mJarFile && !gJarHandler->IsMainProcess()) {
+    if (!mJarFile && XRE_GetProcessType() != GeckoProcessType_Default) {
         nsAutoCString scheme;
-        rv = mJarBaseURI->GetScheme(scheme);
+        nsresult rv = mJarBaseURI->GetScheme(scheme);
         if (NS_SUCCEEDED(rv) && scheme.EqualsLiteral("remoteopenfile")) {
             nsRefPtr<RemoteOpenFileChild> remoteFile = new RemoteOpenFileChild();
             rv = remoteFile->Init(mJarBaseURI);
             NS_ENSURE_SUCCESS(rv, rv);
             mJarFile = remoteFile;
 
             nsIZipReaderCache *jarCache = gJarHandler->JarCache();
             if (jarCache) {
@@ -363,30 +364,23 @@ nsJARChannel::LookupFile()
                 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()
                     return NS_OK;
                 }
             }
 
-            mOpeningRemote = true;
-
-            if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this)) {
-                // JarHandler will trigger OnRemoteFileOpen() after the first
-                // request for this file completes and we'll get a JAR cache
-                // hit.
-                return NS_OK;
-            }
-
             // Open file on parent: OnRemoteFileOpenComplete called when done
             nsCOMPtr<nsITabChild> tabChild;
             NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, tabChild);
             rv = remoteFile->AsyncRemoteFileOpen(PR_RDONLY, this, tabChild.get());
             NS_ENSURE_SUCCESS(rv, rv);
+
+            mOpeningRemote = true;
         }
     }
     // try to handle a nested jar
     if (!mJarFile) {
         nsCOMPtr<nsIJARURI> jarURI = do_QueryInterface(mJarBaseURI);
         if (jarURI) {
             nsCOMPtr<nsIFileURL> fileURL;
             nsCOMPtr<nsIURI> innerJarURI;
@@ -398,48 +392,16 @@ nsJARChannel::LookupFile()
                 jarURI->GetJAREntry(mInnerJarEntry);
             }
         }
     }
 
     return rv;
 }
 
-nsresult
-nsJARChannel::OpenLocalFile()
-{
-    MOZ_ASSERT(mIsPending);
-
-    // Local files are always considered safe.
-    mIsUnsafe = false;
-
-    nsRefPtr<nsJARInputThunk> input;
-    nsresult rv = CreateJarInput(gJarHandler->JarCache(),
-                                 getter_AddRefs(input));
-    if (NS_SUCCEEDED(rv)) {
-        // Create input stream pump and call AsyncRead as a block.
-        rv = NS_NewInputStreamPump(getter_AddRefs(mPump), input);
-        if (NS_SUCCEEDED(rv))
-            rv = mPump->AsyncRead(this, nullptr);
-    }
-
-    return rv;
-}
-
-void
-nsJARChannel::NotifyError(nsresult aError)
-{
-    MOZ_ASSERT(NS_FAILED(aError));
-
-    mStatus = aError;
-
-    OnStartRequest(nullptr, nullptr);
-    OnStopRequest(nullptr, nullptr, aError);
-}
-
 //-----------------------------------------------------------------------------
 // nsIRequest
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsJARChannel::GetName(nsACString &result)
 {
     return mJarURI->GetSpec(result);
@@ -782,17 +744,27 @@ nsJARChannel::AsyncOpen(nsIStreamListene
         rv = NS_NewDownloader(getter_AddRefs(mDownloader), this);
         if (NS_SUCCEEDED(rv))
             rv = NS_OpenURI(mDownloader, nullptr, mJarBaseURI, nullptr,
                             mLoadGroup, mCallbacks,
                             mLoadFlags & ~(LOAD_DOCUMENT_URI | LOAD_CALL_CONTENT_SNIFFERS));
     } else if (mOpeningRemote) {
         // nothing to do: already asked parent to open file.
     } else {
-        rv = OpenLocalFile();
+        // local files are always considered safe
+        mIsUnsafe = false;
+
+        nsRefPtr<nsJARInputThunk> input;
+        rv = CreateJarInput(gJarHandler->JarCache(), getter_AddRefs(input));
+        if (NS_SUCCEEDED(rv)) {
+            // create input stream pump and call AsyncRead as a block
+            rv = NS_NewInputStreamPump(getter_AddRefs(mPump), input);
+            if (NS_SUCCEEDED(rv))
+                rv = mPump->AsyncRead(this, nullptr);
+        }
     }
 
     if (NS_FAILED(rv)) {
         mIsPending = false;
         mListenerContext = nullptr;
         mListener = nullptr;
         return rv;
     }
@@ -925,43 +897,56 @@ nsJARChannel::OnDownloadComplete(nsIDown
             rv = NS_NewInputStreamPump(getter_AddRefs(mPump), input);
             if (NS_SUCCEEDED(rv))
                 rv = mPump->AsyncRead(this, nullptr);
         }
         status = rv;
     }
 
     if (NS_FAILED(status)) {
-        NotifyError(status);
+        mStatus = status;
+        OnStartRequest(nullptr, nullptr);
+        OnStopRequest(nullptr, nullptr, status);
     }
 
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsIRemoteOpenFileListener
 //-----------------------------------------------------------------------------
 nsresult
 nsJARChannel::OnRemoteFileOpenComplete(nsresult aOpenStatus)
 {
     nsresult rv = aOpenStatus;
 
-    // NS_ERROR_ALREADY_OPENED here means we'll hit JAR cache in
-    // OpenLocalFile().
-    if (NS_SUCCEEDED(rv) || rv == NS_ERROR_ALREADY_OPENED) {
-        rv = OpenLocalFile();
+    if (NS_SUCCEEDED(rv)) {
+        // files on parent are always considered safe
+        mIsUnsafe = false;
+
+        nsRefPtr<nsJARInputThunk> input;
+        rv = CreateJarInput(gJarHandler->JarCache(), getter_AddRefs(input));
+        if (NS_SUCCEEDED(rv)) {
+            // create input stream pump and call AsyncRead as a block
+            rv = NS_NewInputStreamPump(getter_AddRefs(mPump), input);
+            if (NS_SUCCEEDED(rv))
+                rv = mPump->AsyncRead(this, nullptr);
+        }
     }
 
     if (NS_FAILED(rv)) {
-        NotifyError(rv);
+        mStatus = rv;
+        OnStartRequest(nullptr, nullptr);
+        OnStopRequest(nullptr, nullptr, mStatus);
     }
 
     return NS_OK;
 }
 
+
 //-----------------------------------------------------------------------------
 // nsIStreamListener
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsJARChannel::OnStartRequest(nsIRequest *req, nsISupports *ctx)
 {
     LOG(("nsJARChannel::OnStartRequest [this=%x %s]\n", this, mSpec.get()));
--- a/modules/libjar/nsJARChannel.h
+++ b/modules/libjar/nsJARChannel.h
@@ -46,18 +46,16 @@ public:
     nsJARChannel();
     virtual ~nsJARChannel();
 
     nsresult Init(nsIURI *uri);
 
 private:
     nsresult CreateJarInput(nsIZipReaderCache *, nsJARInputThunk **);
     nsresult LookupFile();
-    nsresult OpenLocalFile();
-    void NotifyError(nsresult aError);
 
 #if defined(PR_LOGGING)
     nsCString                       mSpec;
 #endif
 
     bool                            mOpened;
 
     nsCOMPtr<nsIJARURI>             mJarURI;
--- a/modules/libjar/nsJARProtocolHandler.cpp
+++ b/modules/libjar/nsJARProtocolHandler.cpp
@@ -12,37 +12,27 @@
 #include "nsJARURI.h"
 #include "nsIURL.h"
 #include "nsJARChannel.h"
 #include "nsXPIDLString.h"
 #include "nsString.h"
 #include "nsNetCID.h"
 #include "nsIMIMEService.h"
 #include "nsMimeTypes.h"
-#include "nsIRemoteOpenFileListener.h"
-#include "nsIHashable.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
 
 static NS_DEFINE_CID(kZipReaderCacheCID, NS_ZIPREADERCACHE_CID);
 
 #define NS_JAR_CACHE_SIZE 32
 
 //-----------------------------------------------------------------------------
 
 nsJARProtocolHandler *gJarHandler = nullptr;
 
 nsJARProtocolHandler::nsJARProtocolHandler()
-: mIsMainProcess(XRE_GetProcessType() == GeckoProcessType_Default)
 {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    if (!mIsMainProcess) {
-        mRemoteFileListeners.Init();
-    }
 }
 
 nsJARProtocolHandler::~nsJARProtocolHandler()
 {
 }
 
 nsresult
 nsJARProtocolHandler::Init()
@@ -60,77 +50,16 @@ nsIMIMEService *
 nsJARProtocolHandler::MimeService()
 {
     if (!mMimeService)
         mMimeService = do_GetService("@mozilla.org/mime;1");
 
     return mMimeService.get();
 }
 
-bool
-nsJARProtocolHandler::RemoteOpenFileInProgress(
-                                           nsIHashable *aRemoteFile,
-                                           nsIRemoteOpenFileListener *aListener)
-{
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(aRemoteFile);
-    MOZ_ASSERT(aListener);
-
-    if (IsMainProcess()) {
-        MOZ_NOT_REACHED("Shouldn't be called in the main process!");
-        return false;
-    }
-
-    RemoteFileListenerArray *listeners;
-    if (mRemoteFileListeners.Get(aRemoteFile, &listeners)) {
-        listeners->AppendElement(aListener);
-        return true;
-    }
-
-    // We deliberately don't put the listener in the new array since the first
-    // load is handled differently.
-    mRemoteFileListeners.Put(aRemoteFile, new RemoteFileListenerArray());
-    return false;
-}
-
-void
-nsJARProtocolHandler::RemoteOpenFileComplete(nsIHashable *aRemoteFile,
-                                             nsresult aStatus)
-{
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(aRemoteFile);
-
-    if (IsMainProcess()) {
-        MOZ_NOT_REACHED("Shouldn't be called in the main process!");
-        return;
-    }
-
-    RemoteFileListenerArray *tempListeners;
-    if (!mRemoteFileListeners.Get(aRemoteFile, &tempListeners)) {
-        return;
-    }
-
-    // Save the listeners in a stack array. The call to Remove() below will
-    // delete the tempListeners array.
-    RemoteFileListenerArray listeners;
-    tempListeners->SwapElements(listeners);
-
-    mRemoteFileListeners.Remove(aRemoteFile);
-
-    // Technically we must fail OnRemoteFileComplete() since OpenNSPRFileDesc()
-    // won't succeed here. We've trained nsJARChannel to recognize
-    // NS_ERROR_ALREADY_OPENED in this case as "proceed to JAR cache hit."
-    nsresult status = NS_SUCCEEDED(aStatus) ? NS_ERROR_ALREADY_OPENED : aStatus;
-
-    uint32_t count = listeners.Length();
-    for (uint32_t index = 0; index < count; index++) {
-        listeners[index]->OnRemoteFileOpenComplete(status);
-    }
-}
-
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsJARProtocolHandler,
                               nsIJARProtocolHandler,
                               nsIProtocolHandler,
                               nsISupportsWeakReference)
 
 nsJARProtocolHandler*
 nsJARProtocolHandler::GetSingleton()
 {
--- a/modules/libjar/nsJARProtocolHandler.h
+++ b/modules/libjar/nsJARProtocolHandler.h
@@ -8,28 +8,20 @@
 
 #include "nsIJARProtocolHandler.h"
 #include "nsIProtocolHandler.h"
 #include "nsIJARURI.h"
 #include "nsIZipReader.h"
 #include "nsIMIMEService.h"
 #include "nsWeakReference.h"
 #include "nsCOMPtr.h"
-#include "nsClassHashtable.h"
-#include "nsHashKeys.h"
-
-class nsIHashable;
-class nsIRemoteOpenFileListener;
 
 class nsJARProtocolHandler : public nsIJARProtocolHandler
                            , public nsSupportsWeakReference
 {
-    typedef nsAutoTArray<nsCOMPtr<nsIRemoteOpenFileListener>, 5>
-            RemoteFileListenerArray;
-
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIPROTOCOLHANDLER
     NS_DECL_NSIJARPROTOCOLHANDLER
 
     // nsJARProtocolHandler methods:
     nsJARProtocolHandler();
     virtual ~nsJARProtocolHandler();
@@ -37,32 +29,19 @@ public:
     static nsJARProtocolHandler *GetSingleton();
 
     nsresult Init();
 
     // returns non addref'ed pointer.  
     nsIMIMEService    *MimeService();
     nsIZipReaderCache *JarCache() { return mJARCache; }
 
-    bool IsMainProcess() const { return mIsMainProcess; }
-
-    bool RemoteOpenFileInProgress(nsIHashable *aRemoteFile,
-                                  nsIRemoteOpenFileListener *aListener);
-    void RemoteOpenFileComplete(nsIHashable *aRemoteFile, nsresult aStatus);
-
 protected:
     nsCOMPtr<nsIZipReaderCache> mJARCache;
     nsCOMPtr<nsIMIMEService> mMimeService;
-
-    // Holds lists of RemoteOpenFileChild (not including the 1st) that have
-    // requested the same file from parent.
-    nsClassHashtable<nsHashableHashKey, RemoteFileListenerArray>
-        mRemoteFileListeners;
-
-    bool mIsMainProcess;
 };
 
 extern nsJARProtocolHandler *gJarHandler;
 
 #define NS_JARPROTOCOLHANDLER_CLASSNAME \
     "nsJarProtocolHandler"
 #define NS_JARPROTOCOLHANDLER_CID                    \
 { /* 0xc7e410d4-0x85f2-11d3-9f63-006008a6efe9 */     \
--- a/netwerk/ipc/Makefile.in
+++ b/netwerk/ipc/Makefile.in
@@ -41,14 +41,13 @@ CPPSRCS =               \
   ChannelEventQueue.cpp \
   RemoteOpenFileParent.cpp \
   RemoteOpenFileChild.cpp  \
   $(NULL)
 
 LOCAL_INCLUDES +=                  \
   -I$(srcdir)/../protocol/http \
   -I$(srcdir)/../base/src          \
-  -I$(topsrcdir)/modules/libjar    \
   $(NULL)
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -16,17 +16,16 @@
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/network/TCPSocketParent.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/LoadContext.h"
 #include "nsPrintfCString.h"
 #include "nsHTMLDNSPrefetch.h"
 #include "nsIAppsService.h"
 #include "nsEscape.h"
-#include "RemoteOpenFileParent.h"
 
 using mozilla::dom::TabParent;
 using mozilla::net::PTCPSocketParent;
 using mozilla::dom::TCPSocketParent;
 using IPC::SerializedLoadContext;
 
 namespace mozilla {
 namespace net {
@@ -400,24 +399,16 @@ NeckoParent::AllocPRemoteOpenFile(const 
     }
   }
 
   RemoteOpenFileParent* parent = new RemoteOpenFileParent(fileURL);
   return parent;
 }
 
 bool
-NeckoParent::RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
-                                            const URIParams& aFileURI,
-                                            PBrowserParent* aBrowser)
-{
-  return static_cast<RemoteOpenFileParent*>(aActor)->OpenSendCloseDelete();
-}
-
-bool
 NeckoParent::DeallocPRemoteOpenFile(PRemoteOpenFileParent* actor)
 {
   delete actor;
   return true;
 }
 
 bool
 NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname,
@@ -432,8 +423,9 @@ NeckoParent::RecvCancelHTMLDNSPrefetch(c
                                  const uint16_t& flags,
                                  const nsresult& reason)
 {
   nsHTMLDNSPrefetch::CancelPrefetch(hostname, flags, reason);
   return true;
 }
 
 }} // mozilla::net
+
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -64,26 +64,20 @@ protected:
   virtual PWebSocketParent* AllocPWebSocket(PBrowserParent* browser,
                                             const SerializedLoadContext& aSerialized);
   virtual bool DeallocPWebSocket(PWebSocketParent*);
   virtual PTCPSocketParent* AllocPTCPSocket(const nsString& aHost,
                                             const uint16_t& aPort,
                                             const bool& useSSL,
                                             const nsString& aBinaryType,
                                             PBrowserParent* aBrowser);
-
-  virtual PRemoteOpenFileParent* AllocPRemoteOpenFile(const URIParams& aFileURI,
-                                                      PBrowserParent* aBrowser)
-                                                      MOZ_OVERRIDE;
-  virtual bool RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
-                                              const URIParams& aFileURI,
-                                              PBrowserParent* aBrowser)
-                                              MOZ_OVERRIDE;
-  virtual bool DeallocPRemoteOpenFile(PRemoteOpenFileParent* aActor)
-                                      MOZ_OVERRIDE;
+  virtual PRemoteOpenFileParent* AllocPRemoteOpenFile(
+                                            const URIParams& fileuri,
+                                            PBrowserParent* browser);
+  virtual bool DeallocPRemoteOpenFile(PRemoteOpenFileParent* actor);
 
   virtual bool RecvPTCPSocketConstructor(PTCPSocketParent*,
                                          const nsString& aHost,
                                          const uint16_t& aPort,
                                          const bool& useSSL,
                                          const nsString& aBinaryType,
                                          PBrowserParent* aBrowser);
   virtual bool DeallocPTCPSocket(PTCPSocketParent*);
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -42,18 +42,16 @@ parent:
   PCookieService();
   PHttpChannel(nullable PBrowser browser,
                SerializedLoadContext loadContext);
   PWyciwygChannel();
   PFTPChannel(PBrowser browser, SerializedLoadContext loadContext);
   PWebSocket(PBrowser browser, SerializedLoadContext loadContext);
   PTCPSocket(nsString host, uint16_t port, bool useSSL, nsString binaryType,
              nullable PBrowser browser);
-
-  // Request that the parent open a file.
   PRemoteOpenFile(URIParams fileuri, nullable PBrowser browser);
 
   HTMLDNSPrefetch(nsString hostname, uint16_t flags);
   CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
 
 };
 
 
--- a/netwerk/ipc/PRemoteOpenFile.ipdl
+++ b/netwerk/ipc/PRemoteOpenFile.ipdl
@@ -13,16 +13,25 @@ namespace net {
 /**
  * Protocol to support RemoteOpenFile, an nsIFile that opens it's file handle on
  * the parent instead of the child (since child lacks permission to do so).
  */
 protocol PRemoteOpenFile
 {
   manager PNecko;
 
+parent:
+  // Tell parent to open file. URI to open was passed and vetted for security in
+  // IPDL constructor: see NeckoParent::AllocPRemoteOpenFile()
+  AsyncOpenFile();
+
+  __delete__();
+
 child:
   // Your file handle is ready, Sir...
-  __delete__(FileDescriptor fd);
+  FileOpened(FileDescriptor fd);
+  // Trying to send invalid fd crashes, so we need separate method for failure
+  FileDidNotOpen();
 };
 
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/ipc/RemoteOpenFileChild.cpp
+++ b/netwerk/ipc/RemoteOpenFileChild.cpp
@@ -1,94 +1,44 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* 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 "mozilla/net/NeckoChild.h"
 #include "mozilla/net/RemoteOpenFileChild.h"
-
-#include "mozilla/ipc/FileDescriptor.h"
-#include "mozilla/ipc/FileDescriptorUtils.h"
+#include "nsIRemoteOpenFileListener.h"
 #include "mozilla/ipc/URIUtils.h"
-#include "mozilla/net/NeckoChild.h"
-#include "nsThreadUtils.h"
-#include "nsJARProtocolHandler.h"
-#include "nsIRemoteOpenFileListener.h"
 
 // needed to alloc/free NSPR file descriptors
 #include "private/pprio.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
-//-----------------------------------------------------------------------------
-// Helper class to dispatch events async on windows/OSX
-//-----------------------------------------------------------------------------
-
-class CallsListenerInNewEvent : public nsRunnable
-{
-public:
-    CallsListenerInNewEvent(nsIRemoteOpenFileListener *aListener, nsresult aRv)
-      : mListener(aListener), mRV(aRv)
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-        MOZ_ASSERT(aListener);
-    }
-
-    void Dispatch()
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-
-        nsresult rv = NS_DispatchToCurrentThread(this);
-        NS_ENSURE_SUCCESS_VOID(rv);
-    }
+NS_IMPL_THREADSAFE_ISUPPORTS2(RemoteOpenFileChild,
+                              nsIFile,
+                              nsIHashable)
 
-private:
-    NS_IMETHOD Run()
-    {
-        MOZ_ASSERT(NS_IsMainThread());
-        MOZ_ASSERT(mListener);
-
-        mListener->OnRemoteFileOpenComplete(mRV);
-        return NS_OK;
-    }
-
-    nsCOMPtr<nsIRemoteOpenFileListener> mListener;
-    nsresult mRV;
-};
-
-//-----------------------------------------------------------------------------
-// RemoteOpenFileChild
-//-----------------------------------------------------------------------------
-
-NS_IMPL_THREADSAFE_ISUPPORTS3(RemoteOpenFileChild,
-                              nsIFile,
-                              nsIHashable,
-                              nsICachedFileDescriptorListener)
 
 RemoteOpenFileChild::RemoteOpenFileChild(const RemoteOpenFileChild& other)
-  : mTabChild(other.mTabChild)
-  , mNSPRFileDesc(other.mNSPRFileDesc)
+  : mNSPRFileDesc(other.mNSPRFileDesc)
   , mAsyncOpenCalled(other.mAsyncOpenCalled)
   , mNSPROpenCalled(other.mNSPROpenCalled)
 {
   // Note: don't clone mListener or we'll have a refcount leak.
   other.mURI->Clone(getter_AddRefs(mURI));
   other.mFile->Clone(getter_AddRefs(mFile));
 }
 
 RemoteOpenFileChild::~RemoteOpenFileChild()
 {
-  if (mListener) {
-    NotifyListener(NS_ERROR_UNEXPECTED);
-  }
-
   if (mNSPRFileDesc) {
     // If we handed out fd we shouldn't have pointer to it any more.
     MOZ_ASSERT(!mNSPROpenCalled);
     // PR_Close both closes the file and deallocates the PRFileDesc
     PR_Close(mNSPRFileDesc);
   }
 }
 
@@ -147,158 +97,118 @@ RemoteOpenFileChild::AsyncRemoteFileOpen
   if (mAsyncOpenCalled) {
     return NS_ERROR_ALREADY_OPENED;
   }
 
   if (aFlags != PR_RDONLY) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  mTabChild = static_cast<TabChild*>(aTabChild);
-
-  if (MissingRequiredTabChild(mTabChild, "remoteopenfile")) {
+  mozilla::dom::TabChild* tabChild = nullptr;
+  if (aTabChild) {
+    tabChild = static_cast<mozilla::dom::TabChild*>(aTabChild);
+  }
+  if (MissingRequiredTabChild(tabChild, "remoteopenfile")) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
   // Windows/OSX desktop builds skip remoting, and just open file in child
   // process when asked for NSPR handle
-  nsRefPtr<CallsListenerInNewEvent> runnable =
-    new CallsListenerInNewEvent(aListener, NS_OK);
-  runnable->Dispatch();
-
+  aListener->OnRemoteFileOpenComplete(NS_OK);
   mAsyncOpenCalled = true;
   return NS_OK;
 #else
-  nsString path;
-  if (NS_FAILED(mFile->GetPath(path))) {
-    MOZ_NOT_REACHED("Couldn't get path from file!");
-  }
-
-  if (mTabChild) {
-    if (mTabChild->GetCachedFileDescriptor(path, this)) {
-      // The file descriptor was found in the cache and OnCachedFileDescriptor()
-      // will be called with it.
-      return NS_OK;
-    }
-  }
-
   URIParams uri;
   SerializeURI(mURI, uri);
 
-  gNeckoChild->SendPRemoteOpenFileConstructor(this, uri, mTabChild);
+  gNeckoChild->SendPRemoteOpenFileConstructor(this, uri, tabChild);
 
-  // The chrome process now has a logical ref to us until it calls Send__delete.
+  // Can't seem to reply from within IPDL Parent constructor, so send open as
+  // separate message
+  SendAsyncOpenFile();
+
+  // The chrome process now has a logical ref to us until we call Send__delete
   AddIPDLReference();
 
   mListener = aListener;
   mAsyncOpenCalled = true;
   return NS_OK;
 #endif
 }
 
-void
-RemoteOpenFileChild::OnCachedFileDescriptor(const nsAString& aPath,
-                                            const FileDescriptor& aFD)
-{
-#ifdef DEBUG
-  if (!aPath.IsEmpty()) {
-    MOZ_ASSERT(mFile);
-
-    nsString path;
-    if (NS_FAILED(mFile->GetPath(path))) {
-      MOZ_NOT_REACHED("Couldn't get path from file!");
-    }
-
-    MOZ_ASSERT(path == aPath, "Paths don't match!");
-  }
-#endif
-
-  HandleFileDescriptorAndNotifyListener(aFD, /* aFromRecvDelete */ false);
-}
-
-void
-RemoteOpenFileChild::HandleFileDescriptorAndNotifyListener(
-                                                      const FileDescriptor& aFD,
-                                                      bool aFromRecvDelete)
-{
-#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
-  MOZ_NOT_REACHED("OS X and Windows shouldn't be doing IPDL here");
-#else
-  if (!mListener) {
-    // We already notified our listener (either in response to a cached file
-    // descriptor callback or through the normal messaging mechanism). Close the
-    // file descriptor if it is valid.
-    if (aFD.IsValid()) {
-      nsRefPtr<CloseFileRunnable> runnable = new CloseFileRunnable(aFD);
-      runnable->Dispatch();
-    }
-    return;
-  }
-
-  MOZ_ASSERT(!mNSPRFileDesc);
-
-  nsRefPtr<TabChild> tabChild;
-  mTabChild.swap(tabChild);
-
-  // If RemoteOpenFile reply (Recv__delete__) for app's application.zip comes
-  // back sooner than the parent-pushed fd (TabChild::RecvCacheFileDescriptor())
-  // have TabChild cancel running callbacks, since we'll call them in
-  // NotifyListener.
-  if (tabChild && aFromRecvDelete) {
-    nsString path;
-    if (NS_FAILED(mFile->GetPath(path))) {
-      MOZ_NOT_REACHED("Couldn't get path from file!");
-    }
-
-    tabChild->CancelCachedFileDescriptorCallback(path, this);
-  }
-
-  if (aFD.IsValid()) {
-    mNSPRFileDesc = PR_ImportFile(aFD.PlatformHandle());
-    if (!mNSPRFileDesc) {
-      NS_WARNING("Failed to import file handle!");
-    }
-  }
-
-  NotifyListener(mNSPRFileDesc ? NS_OK : NS_ERROR_FILE_NOT_FOUND);
-#endif
-}
-
-void
-RemoteOpenFileChild::NotifyListener(nsresult aResult)
-{
-  MOZ_ASSERT(mListener);
-  mListener->OnRemoteFileOpenComplete(aResult);
-  mListener = nullptr;     // release ref to listener
-
-  nsRefPtr<nsJARProtocolHandler> handler(gJarHandler);
-  NS_WARN_IF_FALSE(handler, "nsJARProtocolHandler is already gone!");
-
-  if (handler) {
-    handler->RemoteOpenFileComplete(this, aResult);
-  }
-}
 
 //-----------------------------------------------------------------------------
 // RemoteOpenFileChild::PRemoteOpenFileChild
 //-----------------------------------------------------------------------------
 
 bool
-RemoteOpenFileChild::Recv__delete__(const FileDescriptor& aFD)
+RemoteOpenFileChild::RecvFileOpened(const FileDescriptor& aFD)
 {
 #if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
-  NS_NOTREACHED("OS X and Windows shouldn't be doing IPDL here");
+  NS_NOTREACHED("osX and Windows shouldn't be doing IPDL here");
 #else
-  HandleFileDescriptorAndNotifyListener(aFD, /* aFromRecvDelete */ true);
+  if (!aFD.IsValid()) {
+    return RecvFileDidNotOpen();
+  }
+
+  MOZ_ASSERT(!mNSPRFileDesc);
+  mNSPRFileDesc = PR_AllocFileDesc(aFD.PlatformHandle(), PR_GetFileMethods());
+
+  MOZ_ASSERT(mListener);
+  mListener->OnRemoteFileOpenComplete(NS_OK);
+  mListener = nullptr;     // release ref to listener
+
+  // This calls NeckoChild::DeallocPRemoteOpenFile(), which deletes |this| if
+  // IPDL holds the last reference.  Don't rely on |this| existing after here!
+  Send__delete__(this);
 #endif
 
   return true;
 }
 
+bool
+RemoteOpenFileChild::RecvFileDidNotOpen()
+{
+#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
+  NS_NOTREACHED("osX and Windows shouldn't be doing IPDL here");
+#else
+  MOZ_ASSERT(!mNSPRFileDesc);
+  printf_stderr("RemoteOpenFileChild: file was not opened!\n");
+
+  MOZ_ASSERT(mListener);
+  mListener->OnRemoteFileOpenComplete(NS_ERROR_FILE_NOT_FOUND);
+  mListener = nullptr;     // release ref to listener
+
+  // This calls NeckoChild::DeallocPRemoteOpenFile(), which deletes |this| if
+  // IPDL holds the last reference.  Don't rely on |this| existing after here!
+  Send__delete__(this);
+#endif
+
+  return true;
+}
+
+void
+RemoteOpenFileChild::AddIPDLReference()
+{
+  AddRef();
+}
+
+void
+RemoteOpenFileChild::ReleaseIPDLReference()
+{
+  // if we haven't gotten fd from parent yet, we're not going to.
+  if (mListener) {
+    mListener->OnRemoteFileOpenComplete(NS_ERROR_UNEXPECTED);
+    mListener = nullptr;
+  }
+
+  Release();
+}
+
 //-----------------------------------------------------------------------------
 // RemoteOpenFileChild::nsIFile functions that we override logic for
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 RemoteOpenFileChild::Clone(nsIFile **file)
 {
   *file = new RemoteOpenFileChild(*this);
@@ -747,8 +657,9 @@ RemoteOpenFileChild::GetHashCode(uint32_
   if (hashable) {
     return hashable->GetHashCode(aResult);
   }
   return NS_ERROR_UNEXPECTED;
 }
 
 } // namespace net
 } // namespace mozilla
+
--- a/netwerk/ipc/RemoteOpenFileChild.h
+++ b/netwerk/ipc/RemoteOpenFileChild.h
@@ -2,29 +2,22 @@
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* 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/. */
 
 #ifndef _RemoteOpenFileChild_h
 #define _RemoteOpenFileChild_h
 
-#include "mozilla/Attributes.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/net/PRemoteOpenFileChild.h"
-#include "nsICachedFileDescriptorListener.h"
 #include "nsILocalFile.h"
 #include "nsIRemoteOpenFileListener.h"
 
 namespace mozilla {
-
-namespace ipc {
-class FileDescriptor;
-}
-
 namespace net {
 
 /**
  * RemoteOpenFileChild: a thin wrapper around regular nsIFile classes that does
  * IPC to open a file handle on parent instead of child.  Used when we can't
  * open file handle on child (don't have permission), but we don't want the
  * overhead of shipping all I/O traffic across IPDL.  Example: JAR files.
  *
@@ -40,74 +33,55 @@ namespace net {
  *
  * This class should only be instantiated in a child process.
  *
  */
 class RemoteOpenFileChild MOZ_FINAL
   : public PRemoteOpenFileChild
   , public nsIFile
   , public nsIHashable
-  , public nsICachedFileDescriptorListener
 {
-  typedef mozilla::dom::TabChild TabChild;
-  typedef mozilla::ipc::FileDescriptor FileDescriptor;
-
 public:
   RemoteOpenFileChild()
     : mNSPRFileDesc(nullptr)
     , mAsyncOpenCalled(false)
     , mNSPROpenCalled(false)
   {}
 
   virtual ~RemoteOpenFileChild();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIFILE
   NS_DECL_NSIHASHABLE
 
   // URI must be scheme 'remoteopenfile://': otherwise looks like a file:// uri.
   nsresult Init(nsIURI* aRemoteOpenUri);
 
+  void AddIPDLReference();
+  void ReleaseIPDLReference();
+
   // 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);
-
-  void ReleaseIPDLReference()
-  {
-    Release();
-  }
-
 private:
   RemoteOpenFileChild(const RemoteOpenFileChild& other);
 
 protected:
-  void AddIPDLReference()
-  {
-    AddRef();
-  }
-
-  virtual bool Recv__delete__(const FileDescriptor&) MOZ_OVERRIDE;
-
-  virtual void OnCachedFileDescriptor(const nsAString& aPath,
-                                      const FileDescriptor& aFD) MOZ_OVERRIDE;
-
-  void HandleFileDescriptorAndNotifyListener(const FileDescriptor&,
-                                             bool aFromRecvDelete);
-
-  void NotifyListener(nsresult aResult);
+  virtual bool RecvFileOpened(const FileDescriptor&);
+  virtual bool RecvFileDidNotOpen();
 
   // regular nsIFile object, that we forward most calls to.
   nsCOMPtr<nsIFile> mFile;
   nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIRemoteOpenFileListener> mListener;
-  nsRefPtr<TabChild> mTabChild;
   PRFileDesc* mNSPRFileDesc;
   bool mAsyncOpenCalled;
   bool mNSPROpenCalled;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // _RemoteOpenFileChild_h
+
--- a/netwerk/ipc/RemoteOpenFileParent.cpp
+++ b/netwerk/ipc/RemoteOpenFileParent.cpp
@@ -12,51 +12,60 @@
 #if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA)
 #include <fcntl.h>
 #include <unistd.h>
 #endif
 
 namespace mozilla {
 namespace net {
 
+RemoteOpenFileParent::RemoteOpenFileParent(nsIFileURL *aURI)
+  : mURI(aURI)
+#if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA)
+  , mFd(-1)
+#endif
+{}
+
+RemoteOpenFileParent::~RemoteOpenFileParent()
+{
+#if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA)
+  if (mFd != -1) {
+    // close file handle now that other process has it open, else we'll leak
+    // file handles in parent process
+    close(mFd);
+  }
+#endif
+}
+
 bool
-RemoteOpenFileParent::OpenSendCloseDelete()
+RemoteOpenFileParent::RecvAsyncOpenFile()
 {
 #if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
-  MOZ_NOT_REACHED("OS X and Windows shouldn't be doing IPDL here");
+  NS_NOTREACHED("osX and Windows shouldn't be doing IPDL here");
 #else
 
   // TODO: make this async!
 
-  FileDescriptor fileDescriptor;
-
   nsAutoCString path;
   nsresult rv = mURI->GetFilePath(path);
-  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "GetFilePath failed!");
-
   NS_UnescapeURL(path);
-
   if (NS_SUCCEEDED(rv)) {
     int fd = open(path.get(), O_RDONLY);
-    if (fd == -1) {
-      printf_stderr("RemoteOpenFileParent: file '%s' was not found!\n",
-                    path.get());
-    } else {
-      fileDescriptor = FileDescriptor(fd);
+    if (fd != -1) {
+      unused << SendFileOpened(FileDescriptor(fd));
+      // file handle needs to stay open until it's shared with child (and IPDL
+      // is async, so hasn't happened yet). Close in destructor.
+      mFd = fd;
+      return true;
     }
   }
 
-  // Sending a potentially invalid file descriptor is just fine.
-  unused << Send__delete__(this, fileDescriptor);
-
-  if (fileDescriptor.IsValid()) {
-    // close file now that other process has it open, else we'll leak fds in the
-    // parent process.
-    close(fileDescriptor.PlatformHandle());
-  }
-
+  // Note: sending an invalid file descriptor currently kills the child process:
+  // but that's ok for our use case (failing to open application.jar).
+  printf_stderr("RemoteOpenFileParent: file '%s' was not found!\n", path.get());
+  unused << SendFileDidNotOpen();
 #endif // OS_TYPE
 
   return true;
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/ipc/RemoteOpenFileParent.h
+++ b/netwerk/ipc/RemoteOpenFileParent.h
@@ -13,22 +13,26 @@
 #include "nsIFileURL.h"
 
 namespace mozilla {
 namespace net {
 
 class RemoteOpenFileParent : public PRemoteOpenFileParent
 {
 public:
-  RemoteOpenFileParent(nsIFileURL* aURI)
-  : mURI(aURI)
-  {}
+  RemoteOpenFileParent(nsIFileURL* aURI);
 
-  bool OpenSendCloseDelete();
+ ~RemoteOpenFileParent();
+
+  virtual bool RecvAsyncOpenFile();
 
 private:
   nsCOMPtr<nsIFileURL> mURI;
+
+#if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA)
+  int mFd;
+#endif
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // mozilla_net_RemoteOpenFileParent_h