author | Phil Ringnalda <philringnalda@gmail.com> |
Wed, 06 Feb 2013 22:23:33 -0800 | |
changeset 121130 | 278f5973b2c8c8062b8618da043ef8b704b4e6f9 |
parent 121129 | 67f1ba2a8cb9ae676d3c131beeefd1bfb20c2793 |
child 121131 | 4a2f6b878f6ebfe4c5c9dfc92ec4d91286649381 |
push id | 24274 |
push user | ryanvm@gmail.com |
push date | Thu, 07 Feb 2013 14:55:15 +0000 |
treeherder | mozilla-central@1c88f3f30540 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 835698 |
milestone | 21.0a1 |
backs out | 4b47185f48f8ab06d1abaff5ecde31cc209dade1 |
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
|
--- 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)); @@ -1208,140 +1114,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/RemoteOpenFileChild.cpp +++ b/netwerk/ipc/RemoteOpenFileChild.cpp @@ -1,53 +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 "nsJARProtocolHandler.h" -#include "nsIRemoteOpenFileListener.h" // needed to alloc/free NSPR file descriptors #include "private/pprio.h" using namespace mozilla::ipc; namespace mozilla { namespace net { -NS_IMPL_THREADSAFE_ISUPPORTS3(RemoteOpenFileChild, +NS_IMPL_THREADSAFE_ISUPPORTS2(RemoteOpenFileChild, nsIFile, - nsIHashable, - nsICachedFileDescriptorListener) + nsIHashable) + 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); } } @@ -106,178 +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 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); // 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, /* aFromRecvFileOpened */ false); -} - -void -RemoteOpenFileChild::HandleFileDescriptorAndNotifyListener( - const FileDescriptor& aFD, - bool aFromRecvFileOpened) -{ -#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 there is a pending callback and we're being called from IPDL then we - // need to cancel it. - if (tabChild && aFromRecvFileOpened) { - 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::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, /* aFromRecvFileOpened */ 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("OS X and Windows shouldn't be doing IPDL here"); + NS_NOTREACHED("osX and Windows shouldn't be doing IPDL here"); #else - HandleFileDescriptorAndNotifyListener(FileDescriptor(), - /* aFromRecvFileOpened */ true); + 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); @@ -726,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 @@ -4,26 +4,20 @@ * 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/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. * @@ -39,75 +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 RecvFileOpened(const FileDescriptor&); virtual bool RecvFileDidNotOpen(); - virtual void OnCachedFileDescriptor(const nsAString& aPath, - const FileDescriptor& aFD) MOZ_OVERRIDE; - - void HandleFileDescriptorAndNotifyListener(const FileDescriptor&, - bool aFromRecvFileOpened); - - void NotifyListener(nsresult aResult); - // 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 +