author | Shian-Yow Wu <swu@mozilla.com> |
Fri, 18 Jul 2014 10:46:22 +0800 | |
changeset 194830 | 8912d2088eee28737b418afd8cd1e246fc97c6e7 |
parent 194829 | daa82439f77ff7bac1b577e98b7773ce04bcb3c4 |
child 194831 | f7de657a37ed109072f19e1dffe4867f856a5047 |
push id | 27157 |
push user | ryanvm@gmail.com |
push date | Fri, 18 Jul 2014 19:00:26 +0000 |
treeherder | mozilla-central@ecdb409898a6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | aklotz, jduell |
bugs | 988816 |
milestone | 33.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
|
--- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -2986,16 +2986,24 @@ nsXMLHttpRequest::Send(nsIVariant* aVari nsAutoCString scheme; rv = mChannel->GetURI(getter_AddRefs(uri)); if (NS_SUCCEEDED(rv)) { uri->GetScheme(scheme); if (scheme.LowerCaseEqualsLiteral("app") || scheme.LowerCaseEqualsLiteral("jar")) { mIsMappedArrayBuffer = true; + if (XRE_GetProcessType() != GeckoProcessType_Default) { + nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(mChannel); + // For memory mapping from child process, we need to get file + // descriptor of the JAR file opened remotely on the parent proess. + // Set this to make sure that file descriptor can be obtained by + // child process. + jarChannel->EnsureChildFd(); + } } } } // Start reading from the channel rv = mChannel->AsyncOpen(listener, nullptr); } if (NS_FAILED(rv)) {
--- a/modules/libjar/nsIJARChannel.idl +++ b/modules/libjar/nsIJARChannel.idl @@ -2,17 +2,17 @@ /* 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 "nsIChannel.idl" interface nsIFile; -[scriptable, builtinclass, uuid(063e9698-ec67-4fe2-aa19-d21505beaa61)] +[scriptable, builtinclass, uuid(5a4f8df0-3bd9-45c2-9db9-67e74c3dd47d)] interface nsIJARChannel : nsIChannel { /** * Returns TRUE if the JAR file is not safe (if the content type reported * by the server for a remote JAR is not of an expected type). Scripting, * redirects, and plugins should be disabled when loading from this * channel. */ @@ -22,9 +22,16 @@ interface nsIJARChannel : nsIChannel * Forces the uri to be a app:// uri. */ void setAppURI(in nsIURI uri); /** * Returns the JAR file. */ readonly attribute nsIFile jarFile; + + /** + * For child process, set this to make sure that a valid file descriptor of + * JAR file is always provided when calling NSPRFileDesc(). + * Must be set before Open() or AsyncOpen() to be effective. + */ + void ensureChildFd(); };
--- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -194,16 +194,17 @@ nsJARChannel::nsJARChannel() : mOpened(false) , mAppURI(nullptr) , mContentLength(-1) , mLoadFlags(LOAD_NORMAL) , mStatus(NS_OK) , mIsPending(false) , mIsUnsafe(true) , mOpeningRemote(false) + , mEnsureChildFd(false) { #if defined(PR_LOGGING) if (!gJarProtocolLog) gJarProtocolLog = PR_NewLogModule("nsJarProtocol"); #endif // hold an owning reference to the jar handler NS_ADDREF(gJarHandler); @@ -351,29 +352,30 @@ nsJARChannel::LookupFile() rv = mJarBaseURI->GetScheme(scheme); if (NS_SUCCEEDED(rv) && scheme.EqualsLiteral("remoteopenfile")) { nsRefPtr<RemoteOpenFileChild> remoteFile = new RemoteOpenFileChild(); rv = remoteFile->Init(mJarBaseURI, mAppURI); NS_ENSURE_SUCCESS(rv, rv); mJarFile = remoteFile; nsIZipReaderCache *jarCache = gJarHandler->JarCache(); - if (jarCache) { + if (jarCache && !mEnsureChildFd) { bool cached = false; rv = jarCache->IsCached(mJarFile, &cached); if (NS_SUCCEEDED(rv) && cached) { // zipcache already has file mmapped: don't open on parent, // just return and proceed to cache hit in CreateJarInput() return NS_OK; } } mOpeningRemote = true; - if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this)) { + if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this) && + !mEnsureChildFd) { // JarHandler will trigger OnRemoteFileOpen() after the first // request for this file completes and we'll get a JAR cache // hit. return NS_OK; } // Open file on parent: OnRemoteFileOpenComplete called when done nsCOMPtr<nsITabChild> tabChild; @@ -860,16 +862,23 @@ nsJARChannel::SetAppURI(nsIURI *aURI) { NS_IMETHODIMP nsJARChannel::GetJarFile(nsIFile **aFile) { NS_IF_ADDREF(*aFile = mJarFile); return NS_OK; } +NS_IMETHODIMP +nsJARChannel::EnsureChildFd() +{ + mEnsureChildFd = true; + return NS_OK; +} + //----------------------------------------------------------------------------- // nsIDownloadObserver //----------------------------------------------------------------------------- NS_IMETHODIMP nsJARChannel::OnDownloadComplete(nsIDownloader *downloader, nsIRequest *request, nsISupports *context, @@ -1030,16 +1039,21 @@ nsJARChannel::OnStopRequest(nsIRequest * mPump = 0; mIsPending = false; mDownloader = 0; // this may delete the underlying jar file // Drop notification callbacks to prevent cycles. mCallbacks = 0; mProgressSink = 0; + if (mOpeningRemote) { + // To deallocate file descriptor by RemoteOpenFileChild destructor. + mJarFile = nullptr; + } + return NS_OK; } NS_IMETHODIMP nsJARChannel::OnDataAvailable(nsIRequest *req, nsISupports *ctx, nsIInputStream *stream, uint64_t offset, uint32_t count) {
--- a/modules/libjar/nsJARChannel.h +++ b/modules/libjar/nsJARChannel.h @@ -88,16 +88,17 @@ private: * empty */ uint32_t mContentDisposition; int64_t mContentLength; uint32_t mLoadFlags; nsresult mStatus; bool mIsPending; bool mIsUnsafe; bool mOpeningRemote; + bool mEnsureChildFd; nsCOMPtr<nsIStreamListener> mDownloader; nsCOMPtr<nsIInputStreamPump> mPump; // mRequest is only non-null during OnStartRequest, so we'll have a pointer // to the request if we get called back via RetargetDeliveryTo. nsCOMPtr<nsIRequest> mRequest; nsCOMPtr<nsIFile> mJarFile; nsCOMPtr<nsIURI> mJarBaseURI;
--- a/netwerk/ipc/RemoteOpenFileChild.cpp +++ b/netwerk/ipc/RemoteOpenFileChild.cpp @@ -67,20 +67,30 @@ private: NS_IMPL_ISUPPORTS(RemoteOpenFileChild, nsIFile, nsIHashable, nsICachedFileDescriptorListener) RemoteOpenFileChild::RemoteOpenFileChild(const RemoteOpenFileChild& other) : mTabChild(other.mTabChild) - , mNSPRFileDesc(other.mNSPRFileDesc) + , mNSPRFileDesc(nullptr) , mAsyncOpenCalled(other.mAsyncOpenCalled) - , mNSPROpenCalled(other.mNSPROpenCalled) { +#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA) + // Windows/OSX desktop builds skip remoting, so the file descriptor should + // be nullptr here. + MOZ_ASSERT(!other.mNSPRFileDesc); +#else + if (other.mNSPRFileDesc) { + PROsfd osfd = dup(PR_FileDesc2NativeHandle(other.mNSPRFileDesc)); + mNSPRFileDesc = PR_ImportFile(osfd); + } +#endif + // Note: don't clone mListener or we'll have a refcount leak. other.mURI->Clone(getter_AddRefs(mURI)); if (other.mAppURI) { other.mAppURI->Clone(getter_AddRefs(mAppURI)); } other.mFile->Clone(getter_AddRefs(mFile)); } @@ -118,18 +128,16 @@ RemoteOpenFileChild::~RemoteOpenFileChil unused << mURI.forget(); unused << mAppURI.forget(); unused << mListener.forget(); unused << mTabChild.forget(); } } 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); } } nsresult RemoteOpenFileChild::Init(nsIURI* aRemoteOpenUri, nsIURI* aAppUri) { @@ -342,21 +350,16 @@ RemoteOpenFileChild::Recv__delete__(cons //----------------------------------------------------------------------------- NS_IMETHODIMP RemoteOpenFileChild::Clone(nsIFile **file) { *file = new RemoteOpenFileChild(*this); NS_ADDREF(*file); - // if we transferred ownership of file to clone, forget our pointer. - if (mNSPRFileDesc) { - mNSPRFileDesc = nullptr; - } - return NS_OK; } /* The main event: get file descriptor from parent process */ NS_IMETHODIMP RemoteOpenFileChild::OpenNSPRFileDesc(int32_t aFlags, int32_t aMode, PRFileDesc **aRetval) @@ -365,31 +368,23 @@ RemoteOpenFileChild::OpenNSPRFileDesc(in // Windows and OSX builds: just open nsIFile locally. return mFile->OpenNSPRFileDesc(aFlags, aMode, aRetval); #else if (aFlags != PR_RDONLY) { return NS_ERROR_NOT_AVAILABLE; } - // Unlike regular nsIFile we can't (easily) support multiple open()s. - if (mNSPROpenCalled) { - return NS_ERROR_ALREADY_OPENED; - } - if (!mNSPRFileDesc) { - // client skipped AsyncRemoteFileOpen() or didn't wait for result, or this - // object has been cloned + // Client skipped AsyncRemoteFileOpen() or didn't wait for result. return NS_ERROR_NOT_AVAILABLE; } - // hand off ownership (i.e responsibility to PR_Close() file handle) to caller - *aRetval = mNSPRFileDesc; - mNSPRFileDesc = nullptr; - mNSPROpenCalled = true; + PROsfd osfd = dup(PR_FileDesc2NativeHandle(mNSPRFileDesc)); + *aRetval = PR_ImportFile(osfd); return NS_OK; #endif } //----------------------------------------------------------------------------- // RemoteOpenFileChild::nsIFile functions that we delegate to underlying nsIFile
--- a/netwerk/protocol/app/AppProtocolHandler.cpp +++ b/netwerk/protocol/app/AppProtocolHandler.cpp @@ -122,16 +122,21 @@ NS_IMETHODIMP DummyChannel::SetAppURI(ns return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP DummyChannel::GetJarFile(nsIFile* *aFile) { return NS_ERROR_NOT_IMPLEMENTED; } +NS_IMETHODIMP DummyChannel::EnsureChildFd() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP DummyChannel::Run() { nsresult rv = mListener->OnStartRequest(this, mListenerContext); NS_ENSURE_SUCCESS(rv, rv); mPending = false; rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND); NS_ENSURE_SUCCESS(rv, rv); if (mLoadGroup) {