Bug 988816 - Support multiple OpenNSPRFileOpen() on RemoteOpenFile. r=aklotz, jduell

This commit is contained in:
Shian-Yow Wu 2014-07-18 10:46:22 +08:00
parent 87bcf4c0d6
commit a968b880df
6 changed files with 53 additions and 23 deletions

View File

@ -2991,6 +2991,14 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
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();
}
}
}
}

View File

@ -7,7 +7,7 @@
interface nsIFile;
[scriptable, builtinclass, uuid(063e9698-ec67-4fe2-aa19-d21505beaa61)]
[scriptable, builtinclass, uuid(5a4f8df0-3bd9-45c2-9db9-67e74c3dd47d)]
interface nsIJARChannel : nsIChannel
{
/**
@ -27,4 +27,11 @@ interface nsIJARChannel : nsIChannel
* 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();
};

View File

@ -199,6 +199,7 @@ nsJARChannel::nsJARChannel()
, mIsPending(false)
, mIsUnsafe(true)
, mOpeningRemote(false)
, mEnsureChildFd(false)
{
#if defined(PR_LOGGING)
if (!gJarProtocolLog)
@ -356,7 +357,7 @@ nsJARChannel::LookupFile()
mJarFile = remoteFile;
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
if (jarCache) {
if (jarCache && !mEnsureChildFd) {
bool cached = false;
rv = jarCache->IsCached(mJarFile, &cached);
if (NS_SUCCEEDED(rv) && cached) {
@ -368,7 +369,8 @@ nsJARChannel::LookupFile()
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.
@ -865,6 +867,13 @@ nsJARChannel::GetJarFile(nsIFile **aFile)
return NS_OK;
}
NS_IMETHODIMP
nsJARChannel::EnsureChildFd()
{
mEnsureChildFd = true;
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsIDownloadObserver
//-----------------------------------------------------------------------------
@ -1035,6 +1044,11 @@ nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
mCallbacks = 0;
mProgressSink = 0;
if (mOpeningRemote) {
// To deallocate file descriptor by RemoteOpenFileChild destructor.
mJarFile = nullptr;
}
return NS_OK;
}

View File

@ -93,6 +93,7 @@ private:
bool mIsPending;
bool mIsUnsafe;
bool mOpeningRemote;
bool mEnsureChildFd;
nsCOMPtr<nsIStreamListener> mDownloader;
nsCOMPtr<nsIInputStreamPump> mPump;

View File

@ -72,10 +72,20 @@ NS_IMPL_ISUPPORTS(RemoteOpenFileChild,
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) {
@ -123,8 +133,6 @@ RemoteOpenFileChild::~RemoteOpenFileChild()
}
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);
}
@ -347,11 +355,6 @@ 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;
}
@ -370,21 +373,13 @@ RemoteOpenFileChild::OpenNSPRFileDesc(int32_t aFlags, int32_t aMode,
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

View File

@ -127,6 +127,11 @@ 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);