Making jar: protocol work in general, and OpenInputStream in particular.
git-svn-id: svn://10.0.0.236/trunk@64583 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
094bb4201d
commit
e8a3ec30ae
@ -37,6 +37,23 @@ static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
|
||||
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
|
||||
static NS_DEFINE_CID(kScriptSecurityManagerCID, NS_SCRIPTSECURITYMANAGER_CID);
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
#include "nsXPIDLString.h"
|
||||
//
|
||||
// Log module for SocketTransport logging...
|
||||
//
|
||||
// To enable logging (see prlog.h for full details):
|
||||
//
|
||||
// set NSPR_LOG_MODULES=nsJarProtocol:5
|
||||
// set NSPR_LOG_FILE=nspr.log
|
||||
//
|
||||
// this enables PR_LOG_DEBUG level information and places all output in
|
||||
// the file nspr.log
|
||||
//
|
||||
PRLogModuleInfo* gJarProtocolLog = nsnull;
|
||||
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsJARDownloadObserver : public nsIStreamObserver
|
||||
@ -56,6 +73,19 @@ public:
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoMonitor monitor(mJARChannel->mMonitor);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
rv = jarCacheTransport->GetURI(getter_AddRefs(jarURI));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = jarURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar download complete %s status=%x",
|
||||
(const char*)jarURLStr, status));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (NS_SUCCEEDED(status) && mJARChannel->mJarCacheTransport) {
|
||||
NS_ASSERTION(jarCacheTransport == (mJARChannel->mJarCacheTransport).get(),
|
||||
"wrong transport");
|
||||
@ -78,13 +108,16 @@ public:
|
||||
rv = jarCacheFile->SetNotificationCallbacks(mJARChannel->mCallbacks);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJARChannel->ExtractJARElement(jarCacheFile);
|
||||
mJARChannel->SetJARBaseFile(jarCacheFile);
|
||||
rv = mOnJARFileAvailable(mJARChannel, mClosure);
|
||||
}
|
||||
mJARChannel->mJarCacheTransport = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsJARDownloadObserver(nsIFile* jarCacheFile, nsJARChannel* jarChannel) {
|
||||
nsJARDownloadObserver(nsIFile* jarCacheFile, nsJARChannel* jarChannel,
|
||||
OnJARFileAvailableFun onJARFileAvailable,
|
||||
void* closure) {
|
||||
NS_INIT_REFCNT();
|
||||
mJarCacheFile = jarCacheFile;
|
||||
mJARChannel = jarChannel;
|
||||
@ -96,8 +129,10 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIFile> mJarCacheFile;
|
||||
nsJARChannel* mJARChannel;
|
||||
nsCOMPtr<nsIFile> mJarCacheFile;
|
||||
nsJARChannel* mJARChannel;
|
||||
OnJARFileAvailableFun mOnJARFileAvailable;
|
||||
void* mClosure;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsJARDownloadObserver, nsIStreamObserver)
|
||||
@ -106,11 +141,24 @@ NS_IMPL_ISUPPORTS1(nsJARDownloadObserver, nsIStreamObserver)
|
||||
|
||||
nsJARChannel::nsJARChannel()
|
||||
: mContentType(nsnull),
|
||||
mContentLength(-1),
|
||||
mStartPosition(0),
|
||||
mReadCount(-1),
|
||||
mJAREntry(nsnull),
|
||||
mMonitor(nsnull),
|
||||
mStatus(NS_OK)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
//
|
||||
// Initialize the global PRLogModule for socket transport logging
|
||||
// if necessary...
|
||||
//
|
||||
if (nsnull == gJarProtocolLog) {
|
||||
gJarProtocolLog = PR_NewLogModule("nsJarProtocol");
|
||||
}
|
||||
#endif /* PR_LOGGING */
|
||||
}
|
||||
|
||||
nsJARChannel::~nsJARChannel()
|
||||
@ -270,11 +318,30 @@ nsJARChannel::SetURI(nsIURI* aURI)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
OpenJARElement(nsJARChannel* channel, void* closure)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIInputStream* *result = (nsIInputStream**)closure;
|
||||
nsAutoCMonitor mon(channel);
|
||||
rv = channel->Open(nsnull, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = channel->GetInputStream(result);
|
||||
mon.Notify(); // wake up OpenInputStream
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::OpenInputStream(nsIInputStream* *result)
|
||||
{
|
||||
NS_NOTREACHED("nsJARChannel::OpenInputStream");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsAutoCMonitor mon(this);
|
||||
nsresult rv;
|
||||
*result = nsnull;
|
||||
rv = EnsureJARFileAvailable(OpenJARElement, result);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (*result == nsnull)
|
||||
mon.Wait();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -291,10 +358,35 @@ nsJARChannel::AsyncOpen(nsIStreamObserver* observer, nsISupports* ctxt)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReadJARElement(nsJARChannel* channel, void* closure)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = channel->AsyncReadJARElement();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
{
|
||||
mUserContext = ctxt;
|
||||
mUserListener = listener;
|
||||
return EnsureJARFileAvailable(ReadJARElement, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable,
|
||||
void* closure)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: EnsureJARFileAvailable %s", (const char*)jarURLStr));
|
||||
#endif
|
||||
|
||||
rv = mURI->GetJARFile(getter_AddRefs(mJARBaseURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
@ -315,14 +407,13 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
if (mLoadGroup)
|
||||
(void)mLoadGroup->AddChannel(this, nsnull);
|
||||
|
||||
// XXX need to set a state variable here to say we're reading
|
||||
mUserContext = ctxt;
|
||||
mUserListener = listener;
|
||||
mJARBaseFile = do_QueryInterface(jarBaseChannel, &rv);
|
||||
|
||||
nsCOMPtr<nsIFileChannel> jarBaseFile = do_QueryInterface(jarBaseChannel, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// then we've already got a local jar file -- no need to download it
|
||||
rv = ExtractJARElement(jarBaseFile);
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: extracting local jar file %s", (const char*)jarURLStr));
|
||||
rv = onJARFileAvailable(this, closure);
|
||||
}
|
||||
else {
|
||||
// otherwise, we need to download the jar file
|
||||
@ -338,18 +429,19 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
if (NS_SUCCEEDED(rv) && filePresent)
|
||||
{
|
||||
// then we've already got the file in the local cache -- no need to download it
|
||||
nsCOMPtr<nsIFileChannel> fileChannel;
|
||||
rv = NS_NewLocalFileChannel(getter_AddRefs(fileChannel),
|
||||
rv = NS_NewLocalFileChannel(getter_AddRefs(mJARBaseFile),
|
||||
jarCacheFile,
|
||||
PR_RDONLY,
|
||||
0);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fileChannel->SetBufferSegmentSize(mBufferSegmentSize);
|
||||
rv = mJARBaseFile->SetBufferSegmentSize(mBufferSegmentSize);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fileChannel->SetBufferMaxSize(mBufferMaxSize);
|
||||
rv = mJARBaseFile->SetBufferMaxSize(mBufferMaxSize);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = ExtractJARElement(fileChannel);
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar file already in cache %s", (const char*)jarURLStr));
|
||||
rv = onJARFileAvailable(this, closure);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -372,10 +464,13 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
rv = mJarCacheTransport->SetNotificationCallbacks(mCallbacks);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIStreamObserver> downloadObserver = new nsJARDownloadObserver(jarCacheFile, this);
|
||||
nsCOMPtr<nsIStreamObserver> downloadObserver =
|
||||
new nsJARDownloadObserver(jarCacheFile, this, onJARFileAvailable, closure);
|
||||
if (downloadObserver == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: downloading jar file %s", (const char*)jarURLStr));
|
||||
nsCOMPtr<nsIInputStream> jarBaseIn;
|
||||
rv = jarBaseChannel->OpenInputStream(getter_AddRefs(jarBaseIn));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -422,13 +517,32 @@ nsJARChannel::GetCacheFile(nsIFile* *cacheFile)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJARChannel::ExtractJARElement(nsIFileChannel* jarBaseFile)
|
||||
nsJARChannel::AsyncReadJARElement()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoMonitor monitor(mMonitor);
|
||||
|
||||
mJARBaseFile = jarBaseFile;
|
||||
NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null");
|
||||
|
||||
if (mLoadGroup) {
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (factory) {
|
||||
nsIStreamListener *newListener;
|
||||
rv = factory->CreateLoadGroupListener(mUserListener, &newListener);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mUserListener = newListener;
|
||||
NS_RELEASE(newListener);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mLoadGroup->AddChannel(this, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -444,6 +558,16 @@ nsJARChannel::ExtractJARElement(nsIFileChannel* jarBaseFile)
|
||||
rv = mJarExtractionTransport->SetNotificationCallbacks(mCallbacks);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: AsyncRead jar entry %s", (const char*)jarURLStr));
|
||||
#endif
|
||||
rv = mJarExtractionTransport->SetTransferOffset(mStartPosition);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mJarExtractionTransport->SetTransferCount(mReadCount);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mJarExtractionTransport->AsyncRead(this, nsnull);
|
||||
return rv;
|
||||
}
|
||||
@ -723,10 +847,27 @@ nsJARChannel::OnStopRequest(nsIChannel* jarExtractionTransport,
|
||||
const PRUnichar* aMsg)
|
||||
{
|
||||
nsresult rv;
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar extraction complete %s status=%x",
|
||||
(const char*)jarURLStr, status));
|
||||
}
|
||||
#endif
|
||||
rv = mUserListener->OnStopRequest(this, mUserContext, status, aMsg);
|
||||
|
||||
if (mLoadGroup) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoadGroup->RemoveChannel(this, context, status, aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
mUserListener = nsnull;
|
||||
mUserContext = nsnull;
|
||||
mJarExtractionTransport = nsnull;
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveChannel(this, nsnull, rv, nsnull);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -751,6 +892,8 @@ NS_IMETHODIMP
|
||||
nsJARChannel::Open(char* *contentType, PRInt32 *contentLength)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kZipReaderCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIZipReader),
|
||||
@ -774,10 +917,16 @@ nsJARChannel::Open(char* *contentType, PRInt32 *contentLength)
|
||||
rv = mJAR->GetEntry(mJAREntry, getter_AddRefs(entry));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = entry->GetRealSize((PRUint32*)contentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (contentLength) {
|
||||
rv = entry->GetRealSize((PRUint32*)contentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return GetContentType(contentType);
|
||||
if (contentType) {
|
||||
rv = GetContentType(contentType);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@ -791,6 +940,12 @@ nsJARChannel::Close(nsresult status)
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::GetInputStream(nsIInputStream* *aInputStream)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: GetInputStream jar entry %s", (const char*)jarURLStr));
|
||||
#endif
|
||||
return mJAR->GetInputStream(mJAREntry, aInputStream);
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
#include "prmon.h"
|
||||
|
||||
class nsIFileChannel;
|
||||
class nsJARChannel;
|
||||
|
||||
#define NS_JARCHANNEL_CID \
|
||||
{ /* 0xc7e410d5-0x85f2-11d3-9f63-006008a6efe9 */ \
|
||||
@ -49,6 +50,9 @@ class nsIFileChannel;
|
||||
|
||||
#define JAR_DIRECTORY "jarCache"
|
||||
|
||||
typedef nsresult
|
||||
(*OnJARFileAvailableFun)(nsJARChannel* channel, void* closure);
|
||||
|
||||
class nsJARChannel : public nsIJARChannel,
|
||||
public nsIStreamListener,
|
||||
public nsIFileSystem
|
||||
@ -70,9 +74,13 @@ public:
|
||||
Create(nsISupports* aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
nsresult Init(nsIJARProtocolHandler* aHandler, nsIURI* uri);
|
||||
nsresult ExtractJARElement(nsIFileChannel* jarFileChannel);
|
||||
nsresult EnsureJARFileAvailable(OnJARFileAvailableFun fun,
|
||||
void* closure);
|
||||
nsresult AsyncReadJARElement();
|
||||
nsresult GetCacheFile(nsIFile* *cacheFile);
|
||||
|
||||
void SetJARBaseFile(nsIFileChannel* channel) { mJARBaseFile = channel; }
|
||||
|
||||
friend class nsJARDownloadObserver;
|
||||
|
||||
protected:
|
||||
|
||||
@ -37,6 +37,23 @@ static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
|
||||
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
|
||||
static NS_DEFINE_CID(kScriptSecurityManagerCID, NS_SCRIPTSECURITYMANAGER_CID);
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
#include "nsXPIDLString.h"
|
||||
//
|
||||
// Log module for SocketTransport logging...
|
||||
//
|
||||
// To enable logging (see prlog.h for full details):
|
||||
//
|
||||
// set NSPR_LOG_MODULES=nsJarProtocol:5
|
||||
// set NSPR_LOG_FILE=nspr.log
|
||||
//
|
||||
// this enables PR_LOG_DEBUG level information and places all output in
|
||||
// the file nspr.log
|
||||
//
|
||||
PRLogModuleInfo* gJarProtocolLog = nsnull;
|
||||
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsJARDownloadObserver : public nsIStreamObserver
|
||||
@ -56,6 +73,19 @@ public:
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoMonitor monitor(mJARChannel->mMonitor);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
rv = jarCacheTransport->GetURI(getter_AddRefs(jarURI));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = jarURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar download complete %s status=%x",
|
||||
(const char*)jarURLStr, status));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (NS_SUCCEEDED(status) && mJARChannel->mJarCacheTransport) {
|
||||
NS_ASSERTION(jarCacheTransport == (mJARChannel->mJarCacheTransport).get(),
|
||||
"wrong transport");
|
||||
@ -78,13 +108,16 @@ public:
|
||||
rv = jarCacheFile->SetNotificationCallbacks(mJARChannel->mCallbacks);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJARChannel->ExtractJARElement(jarCacheFile);
|
||||
mJARChannel->SetJARBaseFile(jarCacheFile);
|
||||
rv = mOnJARFileAvailable(mJARChannel, mClosure);
|
||||
}
|
||||
mJARChannel->mJarCacheTransport = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsJARDownloadObserver(nsIFile* jarCacheFile, nsJARChannel* jarChannel) {
|
||||
nsJARDownloadObserver(nsIFile* jarCacheFile, nsJARChannel* jarChannel,
|
||||
OnJARFileAvailableFun onJARFileAvailable,
|
||||
void* closure) {
|
||||
NS_INIT_REFCNT();
|
||||
mJarCacheFile = jarCacheFile;
|
||||
mJARChannel = jarChannel;
|
||||
@ -96,8 +129,10 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIFile> mJarCacheFile;
|
||||
nsJARChannel* mJARChannel;
|
||||
nsCOMPtr<nsIFile> mJarCacheFile;
|
||||
nsJARChannel* mJARChannel;
|
||||
OnJARFileAvailableFun mOnJARFileAvailable;
|
||||
void* mClosure;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsJARDownloadObserver, nsIStreamObserver)
|
||||
@ -106,11 +141,24 @@ NS_IMPL_ISUPPORTS1(nsJARDownloadObserver, nsIStreamObserver)
|
||||
|
||||
nsJARChannel::nsJARChannel()
|
||||
: mContentType(nsnull),
|
||||
mContentLength(-1),
|
||||
mStartPosition(0),
|
||||
mReadCount(-1),
|
||||
mJAREntry(nsnull),
|
||||
mMonitor(nsnull),
|
||||
mStatus(NS_OK)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
//
|
||||
// Initialize the global PRLogModule for socket transport logging
|
||||
// if necessary...
|
||||
//
|
||||
if (nsnull == gJarProtocolLog) {
|
||||
gJarProtocolLog = PR_NewLogModule("nsJarProtocol");
|
||||
}
|
||||
#endif /* PR_LOGGING */
|
||||
}
|
||||
|
||||
nsJARChannel::~nsJARChannel()
|
||||
@ -270,11 +318,30 @@ nsJARChannel::SetURI(nsIURI* aURI)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
OpenJARElement(nsJARChannel* channel, void* closure)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIInputStream* *result = (nsIInputStream**)closure;
|
||||
nsAutoCMonitor mon(channel);
|
||||
rv = channel->Open(nsnull, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = channel->GetInputStream(result);
|
||||
mon.Notify(); // wake up OpenInputStream
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::OpenInputStream(nsIInputStream* *result)
|
||||
{
|
||||
NS_NOTREACHED("nsJARChannel::OpenInputStream");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsAutoCMonitor mon(this);
|
||||
nsresult rv;
|
||||
*result = nsnull;
|
||||
rv = EnsureJARFileAvailable(OpenJARElement, result);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (*result == nsnull)
|
||||
mon.Wait();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -291,10 +358,35 @@ nsJARChannel::AsyncOpen(nsIStreamObserver* observer, nsISupports* ctxt)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReadJARElement(nsJARChannel* channel, void* closure)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = channel->AsyncReadJARElement();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
{
|
||||
mUserContext = ctxt;
|
||||
mUserListener = listener;
|
||||
return EnsureJARFileAvailable(ReadJARElement, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable,
|
||||
void* closure)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: EnsureJARFileAvailable %s", (const char*)jarURLStr));
|
||||
#endif
|
||||
|
||||
rv = mURI->GetJARFile(getter_AddRefs(mJARBaseURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
@ -315,14 +407,13 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
if (mLoadGroup)
|
||||
(void)mLoadGroup->AddChannel(this, nsnull);
|
||||
|
||||
// XXX need to set a state variable here to say we're reading
|
||||
mUserContext = ctxt;
|
||||
mUserListener = listener;
|
||||
mJARBaseFile = do_QueryInterface(jarBaseChannel, &rv);
|
||||
|
||||
nsCOMPtr<nsIFileChannel> jarBaseFile = do_QueryInterface(jarBaseChannel, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// then we've already got a local jar file -- no need to download it
|
||||
rv = ExtractJARElement(jarBaseFile);
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: extracting local jar file %s", (const char*)jarURLStr));
|
||||
rv = onJARFileAvailable(this, closure);
|
||||
}
|
||||
else {
|
||||
// otherwise, we need to download the jar file
|
||||
@ -338,18 +429,19 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
if (NS_SUCCEEDED(rv) && filePresent)
|
||||
{
|
||||
// then we've already got the file in the local cache -- no need to download it
|
||||
nsCOMPtr<nsIFileChannel> fileChannel;
|
||||
rv = NS_NewLocalFileChannel(getter_AddRefs(fileChannel),
|
||||
rv = NS_NewLocalFileChannel(getter_AddRefs(mJARBaseFile),
|
||||
jarCacheFile,
|
||||
PR_RDONLY,
|
||||
0);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fileChannel->SetBufferSegmentSize(mBufferSegmentSize);
|
||||
rv = mJARBaseFile->SetBufferSegmentSize(mBufferSegmentSize);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fileChannel->SetBufferMaxSize(mBufferMaxSize);
|
||||
rv = mJARBaseFile->SetBufferMaxSize(mBufferMaxSize);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = ExtractJARElement(fileChannel);
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar file already in cache %s", (const char*)jarURLStr));
|
||||
rv = onJARFileAvailable(this, closure);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -372,10 +464,13 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
rv = mJarCacheTransport->SetNotificationCallbacks(mCallbacks);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIStreamObserver> downloadObserver = new nsJARDownloadObserver(jarCacheFile, this);
|
||||
nsCOMPtr<nsIStreamObserver> downloadObserver =
|
||||
new nsJARDownloadObserver(jarCacheFile, this, onJARFileAvailable, closure);
|
||||
if (downloadObserver == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: downloading jar file %s", (const char*)jarURLStr));
|
||||
nsCOMPtr<nsIInputStream> jarBaseIn;
|
||||
rv = jarBaseChannel->OpenInputStream(getter_AddRefs(jarBaseIn));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -422,13 +517,32 @@ nsJARChannel::GetCacheFile(nsIFile* *cacheFile)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJARChannel::ExtractJARElement(nsIFileChannel* jarBaseFile)
|
||||
nsJARChannel::AsyncReadJARElement()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoMonitor monitor(mMonitor);
|
||||
|
||||
mJARBaseFile = jarBaseFile;
|
||||
NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null");
|
||||
|
||||
if (mLoadGroup) {
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (factory) {
|
||||
nsIStreamListener *newListener;
|
||||
rv = factory->CreateLoadGroupListener(mUserListener, &newListener);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mUserListener = newListener;
|
||||
NS_RELEASE(newListener);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mLoadGroup->AddChannel(this, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -444,6 +558,16 @@ nsJARChannel::ExtractJARElement(nsIFileChannel* jarBaseFile)
|
||||
rv = mJarExtractionTransport->SetNotificationCallbacks(mCallbacks);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: AsyncRead jar entry %s", (const char*)jarURLStr));
|
||||
#endif
|
||||
rv = mJarExtractionTransport->SetTransferOffset(mStartPosition);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mJarExtractionTransport->SetTransferCount(mReadCount);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mJarExtractionTransport->AsyncRead(this, nsnull);
|
||||
return rv;
|
||||
}
|
||||
@ -723,10 +847,27 @@ nsJARChannel::OnStopRequest(nsIChannel* jarExtractionTransport,
|
||||
const PRUnichar* aMsg)
|
||||
{
|
||||
nsresult rv;
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar extraction complete %s status=%x",
|
||||
(const char*)jarURLStr, status));
|
||||
}
|
||||
#endif
|
||||
rv = mUserListener->OnStopRequest(this, mUserContext, status, aMsg);
|
||||
|
||||
if (mLoadGroup) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoadGroup->RemoveChannel(this, context, status, aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
mUserListener = nsnull;
|
||||
mUserContext = nsnull;
|
||||
mJarExtractionTransport = nsnull;
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveChannel(this, nsnull, rv, nsnull);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -751,6 +892,8 @@ NS_IMETHODIMP
|
||||
nsJARChannel::Open(char* *contentType, PRInt32 *contentLength)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kZipReaderCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIZipReader),
|
||||
@ -774,10 +917,16 @@ nsJARChannel::Open(char* *contentType, PRInt32 *contentLength)
|
||||
rv = mJAR->GetEntry(mJAREntry, getter_AddRefs(entry));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = entry->GetRealSize((PRUint32*)contentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (contentLength) {
|
||||
rv = entry->GetRealSize((PRUint32*)contentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return GetContentType(contentType);
|
||||
if (contentType) {
|
||||
rv = GetContentType(contentType);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@ -791,6 +940,12 @@ nsJARChannel::Close(nsresult status)
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::GetInputStream(nsIInputStream* *aInputStream)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: GetInputStream jar entry %s", (const char*)jarURLStr));
|
||||
#endif
|
||||
return mJAR->GetInputStream(mJAREntry, aInputStream);
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
#include "prmon.h"
|
||||
|
||||
class nsIFileChannel;
|
||||
class nsJARChannel;
|
||||
|
||||
#define NS_JARCHANNEL_CID \
|
||||
{ /* 0xc7e410d5-0x85f2-11d3-9f63-006008a6efe9 */ \
|
||||
@ -49,6 +50,9 @@ class nsIFileChannel;
|
||||
|
||||
#define JAR_DIRECTORY "jarCache"
|
||||
|
||||
typedef nsresult
|
||||
(*OnJARFileAvailableFun)(nsJARChannel* channel, void* closure);
|
||||
|
||||
class nsJARChannel : public nsIJARChannel,
|
||||
public nsIStreamListener,
|
||||
public nsIFileSystem
|
||||
@ -70,9 +74,13 @@ public:
|
||||
Create(nsISupports* aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
nsresult Init(nsIJARProtocolHandler* aHandler, nsIURI* uri);
|
||||
nsresult ExtractJARElement(nsIFileChannel* jarFileChannel);
|
||||
nsresult EnsureJARFileAvailable(OnJARFileAvailableFun fun,
|
||||
void* closure);
|
||||
nsresult AsyncReadJARElement();
|
||||
nsresult GetCacheFile(nsIFile* *cacheFile);
|
||||
|
||||
void SetJARBaseFile(nsIFileChannel* channel) { mJARBaseFile = channel; }
|
||||
|
||||
friend class nsJARDownloadObserver;
|
||||
|
||||
protected:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user