Bug 1024388: Allow JAR channels to retarget to a different thread. r=bz,jduell

This commit is contained in:
Kyle Huey 2014-06-17 09:39:23 -07:00
parent 823b7d1989
commit 813d4f144a
3 changed files with 74 additions and 9 deletions

View File

@ -224,6 +224,8 @@ NS_IMPL_ISUPPORTS_INHERITED(nsJARChannel,
nsIRequestObserver,
nsIDownloadObserver,
nsIRemoteOpenFileListener,
nsIThreadRetargetableRequest,
nsIThreadRetargetableStreamListener,
nsIJARChannel)
nsresult
@ -434,6 +436,20 @@ nsJARChannel::NotifyError(nsresult aError)
OnStopRequest(nullptr, nullptr, aError);
}
void
nsJARChannel::FireOnProgress(uint64_t aProgress)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mProgressSink);
if (mLoadFlags & LOAD_BACKGROUND) {
return;
}
mProgressSink->OnProgress(this, nullptr, aProgress,
uint64_t(mContentLength));
}
//-----------------------------------------------------------------------------
// nsIRequest
//-----------------------------------------------------------------------------
@ -972,7 +988,11 @@ nsJARChannel::OnStartRequest(nsIRequest *req, nsISupports *ctx)
{
LOG(("nsJARChannel::OnStartRequest [this=%x %s]\n", this, mSpec.get()));
return mListener->OnStartRequest(this, mListenerContext);
mRequest = req;
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
mRequest = nullptr;
return rv;
}
NS_IMETHODIMP
@ -1020,9 +1040,44 @@ nsJARChannel::OnDataAvailable(nsIRequest *req, nsISupports *ctx,
// simply report progress here instead of hooking ourselves up as a
// nsITransportEventSink implementation.
// XXX do the 64-bit stuff for real
if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND))
mProgressSink->OnProgress(this, nullptr, offset + count,
uint64_t(mContentLength));
if (mProgressSink && NS_SUCCEEDED(rv)) {
if (NS_IsMainThread()) {
FireOnProgress(offset + count);
} else {
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethodWithArg<uint64_t>(this,
&nsJARChannel::FireOnProgress,
offset + count);
NS_DispatchToMainThread(runnable);
}
}
return rv; // let the pump cancel on failure
}
NS_IMETHODIMP
nsJARChannel::RetargetDeliveryTo(nsIEventTarget* aEventTarget)
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIThreadRetargetableRequest> request = do_QueryInterface(mRequest);
if (!request) {
return NS_ERROR_NO_INTERFACE;
}
return request->RetargetDeliveryTo(aEventTarget);
}
NS_IMETHODIMP
nsJARChannel::CheckListenerChain()
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
do_QueryInterface(mListener);
if (!listener) {
return NS_ERROR_NO_INTERFACE;
}
return listener->CheckListenerChain();
}

View File

@ -16,6 +16,8 @@
#include "nsIZipReader.h"
#include "nsIDownloader.h"
#include "nsILoadGroup.h"
#include "nsIThreadRetargetableRequest.h"
#include "nsIThreadRetargetableStreamListener.h"
#include "nsHashPropertyBag.h"
#include "nsIFile.h"
#include "nsIURI.h"
@ -31,6 +33,8 @@ class nsJARChannel : public nsIJARChannel
, public nsIDownloadObserver
, public nsIStreamListener
, public nsIRemoteOpenFileListener
, public nsIThreadRetargetableRequest
, public nsIThreadRetargetableStreamListener
, public nsHashPropertyBag
{
public:
@ -42,18 +46,23 @@ public:
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREMOTEOPENFILELISTENER
NS_DECL_NSITHREADRETARGETABLEREQUEST
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
nsJARChannel();
virtual ~nsJARChannel();
nsresult Init(nsIURI *uri);
private:
virtual ~nsJARChannel();
nsresult CreateJarInput(nsIZipReaderCache *, nsJARInputThunk **);
nsresult LookupFile();
nsresult OpenLocalFile();
void NotifyError(nsresult aError);
void FireOnProgress(uint64_t aProgress);
#if defined(PR_LOGGING)
nsCString mSpec;
#endif
@ -85,6 +94,9 @@ private:
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;
nsCString mJarEntry;

View File

@ -20,8 +20,8 @@ interface nsIThreadRetargetableRequest : nsISupports
/**
* Called to retarget delivery of OnDataAvailable to another thread. Should
* only be called before AsyncOpen for nsIWebsocketChannels, or during
* OnStartRequest for nsIHttpChannels.
* Note: For nsIHttpChannels, OnStartRequest and OnStopRequest will still be
* OnStartRequest for nsIChannels.
* Note: For nsIChannels, OnStartRequest and OnStopRequest will still be
* delivered on the main thread.
*
* @param aNewTarget New event target, e.g. thread or threadpool.
@ -33,5 +33,3 @@ interface nsIThreadRetargetableRequest : nsISupports
*/
void retargetDeliveryTo(in nsIEventTarget aNewTarget);
};