diff --git a/mozilla/modules/libjar/nsJARChannel.cpp b/mozilla/modules/libjar/nsJARChannel.cpp index 75eeee87e3a..153bfba9833 100644 --- a/mozilla/modules/libjar/nsJARChannel.cpp +++ b/mozilla/modules/libjar/nsJARChannel.cpp @@ -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 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 mJarCacheFile; - nsJARChannel* mJARChannel; + nsCOMPtr 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 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 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 downloadObserver = new nsJARDownloadObserver(jarCacheFile, this); + nsCOMPtr 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 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 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 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); } diff --git a/mozilla/modules/libjar/nsJARChannel.h b/mozilla/modules/libjar/nsJARChannel.h index 2bba7d4645b..b1803b95aa0 100644 --- a/mozilla/modules/libjar/nsJARChannel.h +++ b/mozilla/modules/libjar/nsJARChannel.h @@ -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: diff --git a/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp b/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp index 75eeee87e3a..153bfba9833 100644 --- a/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp +++ b/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp @@ -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 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 mJarCacheFile; - nsJARChannel* mJARChannel; + nsCOMPtr 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 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 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 downloadObserver = new nsJARDownloadObserver(jarCacheFile, this); + nsCOMPtr 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 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 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 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); } diff --git a/mozilla/netwerk/protocol/jar/src/nsJARChannel.h b/mozilla/netwerk/protocol/jar/src/nsJARChannel.h index 2bba7d4645b..b1803b95aa0 100644 --- a/mozilla/netwerk/protocol/jar/src/nsJARChannel.h +++ b/mozilla/netwerk/protocol/jar/src/nsJARChannel.h @@ -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: