diff --git a/mozilla/modules/libjar/nsJARChannel.cpp b/mozilla/modules/libjar/nsJARChannel.cpp index d5023432148..4d45badad2c 100644 --- a/mozilla/modules/libjar/nsJARChannel.cpp +++ b/mozilla/modules/libjar/nsJARChannel.cpp @@ -12,7 +12,7 @@ * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Copyright (C) 1998,2000 Netscape Communications Corporation. All Rights * Reserved. * */ @@ -20,11 +20,10 @@ #include "nsNetUtil.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" -#include "nsSpecialSystemDirectory.h" #include "nsJARChannel.h" #include "nsCRT.h" #include "nsIFileTransportService.h" -#include "nsIURL.h" +#include "nsIURI.h" #include "nsCExternalHandlerService.h" #include "nsIMIMEService.h" #include "nsAutoLock.h" @@ -33,13 +32,6 @@ #include "nsScriptSecurityManager.h" #include "nsIAggregatePrincipal.h" #include "nsXPIDLString.h" -#include "nsDirectoryServiceDefs.h" - -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR -#include "nsINetDataCacheManager.h" -#include "nsICachedNetData.h" -#include "nsIStreamAsFile.h" -#endif static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID); static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); @@ -63,70 +55,6 @@ PRLogModuleInfo* gJarProtocolLog = nsnull; //////////////////////////////////////////////////////////////////////////////// -class nsJARDownloadObserver : public nsIStreamObserver -{ -public: - NS_DECL_ISUPPORTS - - NS_IMETHOD OnStartRequest(nsIChannel* jarCacheTransport, - nsISupports* context) { - return NS_OK; - } - - NS_IMETHOD OnStopRequest(nsIChannel* jarCacheTransport, nsISupports* context, - nsresult aStatus, const PRUnichar* aStatusArg) { - 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, aStatus)); - } - } -#endif - if (NS_SUCCEEDED(aStatus) && mJARChannel->mJarCacheTransport) { - NS_ASSERTION(jarCacheTransport == (mJARChannel->mJarCacheTransport).get(), - "wrong transport"); - // after successfully downloading the jar file to the cache, - // start the extraction process: - rv = mOnJARFileAvailable(mJARChannel, mClosure); - } - mJARChannel->mJarCacheTransport = nsnull; - return rv; - } - - nsJARDownloadObserver(nsJARChannel* jarChannel, - OnJARFileAvailableFun onJARFileAvailable, - void* closure) - : mJARChannel(jarChannel), - mOnJARFileAvailable(onJARFileAvailable), - mClosure(closure) - { - NS_INIT_REFCNT(); - NS_ADDREF(mJARChannel); - } - - virtual ~nsJARDownloadObserver() { - NS_RELEASE(mJARChannel); - } - -protected: - nsJARChannel* mJARChannel; - OnJARFileAvailableFun mOnJARFileAvailable; - void* mClosure; -}; - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARDownloadObserver, nsIStreamObserver) - -//////////////////////////////////////////////////////////////////////////////// - #define NS_DEFAULT_JAR_BUFFER_SEGMENT_SIZE (16*1024) #define NS_DEFAULT_JAR_BUFFER_MAX_SIZE (256*1024) @@ -165,13 +93,14 @@ nsJARChannel::~nsJARChannel() PR_DestroyMonitor(mMonitor); } -NS_IMPL_THREADSAFE_ISUPPORTS6(nsJARChannel, +NS_IMPL_THREADSAFE_ISUPPORTS7(nsJARChannel, nsIJARChannel, nsIChannel, nsIRequest, nsIStreamObserver, nsIStreamListener, - nsIStreamIO) + nsIStreamIO, + nsIDownloadObserver) NS_METHOD nsJARChannel::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) @@ -243,11 +172,6 @@ nsJARChannel::Cancel(nsresult status) nsresult rv; nsAutoMonitor monitor(mMonitor); - if (mJarCacheTransport) { - rv = mJarCacheTransport->Cancel(status); - if (NS_FAILED(rv)) return rv; - mJarCacheTransport = nsnull; - } if (mJarExtractionTransport) { rv = mJarExtractionTransport->Cancel(status); if (NS_FAILED(rv)) return rv; @@ -263,10 +187,6 @@ nsJARChannel::Suspend() nsresult rv; nsAutoMonitor monitor(mMonitor); - if (mJarCacheTransport) { - rv = mJarCacheTransport->Suspend(); - if (NS_FAILED(rv)) return rv; - } if (mJarExtractionTransport) { rv = mJarExtractionTransport->Suspend(); if (NS_FAILED(rv)) return rv; @@ -281,10 +201,6 @@ nsJARChannel::Resume() nsresult rv; nsAutoMonitor monitor(mMonitor); - if (mJarCacheTransport) { - rv = mJarCacheTransport->Resume(); - if (NS_FAILED(rv)) return rv; - } if (mJarExtractionTransport) { rv = mJarExtractionTransport->Resume(); if (NS_FAILED(rv)) return rv; @@ -299,8 +215,12 @@ nsJARChannel::Resume() NS_IMETHODIMP nsJARChannel::GetOriginalURI(nsIURI* *aOriginalURI) { - *aOriginalURI = mOriginalURI ? mOriginalURI : nsCOMPtr(mURI); - NS_ADDREF(*aOriginalURI); + if (mOriginalURI) + *aOriginalURI = mOriginalURI; + else + *aOriginalURI = NS_STATIC_CAST(nsIURI*, mURI); + + NS_IF_ADDREF(*aOriginalURI); return NS_OK; } @@ -327,15 +247,14 @@ nsJARChannel::SetURI(nsIURI* aURI) return rv; } -static nsresult -OpenJARElement(nsJARChannel* jarChannel, void* closure) +nsresult +nsJARChannel::OpenJARElement() { nsresult rv; - nsIInputStream* *result = (nsIInputStream**)closure; - nsAutoCMonitor mon(jarChannel); - rv = jarChannel->Open(nsnull, nsnull); - if (NS_FAILED(rv)) return rv; - rv = jarChannel->GetInputStream(result); + nsAutoCMonitor mon(this); + rv = Open(nsnull, nsnull); + if (NS_SUCCEEDED(rv)) + rv = GetInputStream(getter_AddRefs(mSynchronousInputStream)); mon.Notify(); // wake up OpenInputStream return rv; } @@ -345,12 +264,20 @@ nsJARChannel::OpenInputStream(nsIInputStream* *result) { nsAutoCMonitor mon(this); nsresult rv; - *result = nsnull; - rv = EnsureJARFileAvailable(OpenJARElement, result); + mSynchronousRead = PR_TRUE; + rv = EnsureJARFileAvailable(); if (NS_FAILED(rv)) return rv; - if (*result == nsnull) + if (mSynchronousInputStream == nsnull) mon.Wait(); - return rv; + if (mSynchronousInputStream) + { + *result = mSynchronousInputStream; // Result of GetInputStream called on transport thread + NS_ADDREF(*result); + mSynchronousInputStream = null_nsCOMPtr(); + return NS_OK; + } + else + return NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -360,14 +287,6 @@ nsJARChannel::OpenOutputStream(nsIOutputStream* *result) return NS_ERROR_NOT_IMPLEMENTED; } -static nsresult -ReadJARElement(nsJARChannel* jarChannel, void* closure) -{ - nsresult rv; - rv = jarChannel->AsyncReadJARElement(); - return rv; -} - NS_IMETHODIMP nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt) { @@ -395,31 +314,19 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt) if (NS_FAILED(rv)) return rv; } - return EnsureJARFileAvailable(ReadJARElement, nsnull); + mSynchronousRead = PR_FALSE; + return EnsureJARFileAvailable(); } nsresult -nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, - void* closure) +nsJARChannel::EnsureJARFileAvailable() { - // There are 3 cases to dealing with jar files: - // 1. They exist on the local disk and don't need to be cached - // 2. They have already been downloaded and exist in the cache - // 3. They need to be downloaded and cached nsresult rv; nsCOMPtr jarBaseChannel; nsCOMPtr jarCacheFile; nsCOMPtr jarCacheTransport; nsCOMPtr jarBaseIn; -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR - nsCOMPtr cacheMgr; - nsXPIDLCString jarBaseSpec; - nsCOMPtr cachedData; - nsCOMPtr streamAsFile; - nsCOMPtr file; -#endif - #ifdef PR_LOGGING nsXPIDLCString jarURLStr; mURI->GetSpec(getter_Copies(jarURLStr)); @@ -433,112 +340,13 @@ nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, rv = mURI->GetJAREntry(&mJAREntry); if (NS_FAILED(rv)) goto error; -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR + rv = NS_NewDownloader(getter_AddRefs(mDownloader), + mJARBaseURI, this, nsnull, mSynchronousRead, mLoadGroup, mCallbacks, + mLoadAttributes, mBufferSegmentSize, mBufferMaxSize); - cacheMgr = do_GetService(NS_NETWORK_CACHE_MANAGER_CONTRACTID, &rv); - if (NS_FAILED(rv)) goto error; - - rv = mJARBaseURI->GetSpec(getter_Copies(jarBaseSpec)); - if (NS_FAILED(rv)) goto error; - - rv = cacheMgr->GetCachedNetData(jarBaseSpec, nsnull, 0, nsINetDataCacheManager::CACHE_AS_FILE, - getter_AddRefs(cachedData)); - if (NS_SUCCEEDED(rv)) { - streamAsFile = do_QueryInterface(cachedData, &rv); - if (NS_FAILED(rv)) goto error; - - rv = streamAsFile->GetFile(getter_AddRefs(file)); - if (NS_FAILED(rv)) goto error; - } -#endif - - rv = NS_OpenURI(getter_AddRefs(jarBaseChannel), mJARBaseURI, nsnull); - if (NS_FAILED(rv)) goto error; - - rv = jarBaseChannel->GetLocalFile(getter_AddRefs(jarCacheFile)); - if (NS_SUCCEEDED(rv) && jarCacheFile) { - // Case 1: Local file - // we've already got a local jar file -- no need to download it - - rv = NS_NewLocalFileChannel(getter_AddRefs(mJARBaseFile), - jarCacheFile, PR_RDONLY, 0); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferSegmentSize(mBufferSegmentSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferMaxSize(mBufferMaxSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetLoadAttributes(mLoadAttributes); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) return rv; - - PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, - ("nsJarProtocol: extracting local jar file %s", (const char*)jarURLStr)); - rv = onJARFileAvailable(this, closure); - goto error; - } - - rv = GetCacheFile(getter_AddRefs(jarCacheFile)); - if (NS_FAILED(rv)) goto error; - - PRBool filePresent; - rv = jarCacheFile->IsFile(&filePresent); - if (NS_SUCCEEDED(rv) && filePresent) { - // failed downloads can sometimes leave a zero-length file, so check for that too: - PRInt64 size; - rv = jarCacheFile->GetFileSize(&size); - if (NS_FAILED(rv)) goto error; - if (!LL_IS_ZERO(size)) { - // Case 2: Already downloaded - // we've already got the file in the local cache -- no need to download it - PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, - ("nsJarProtocol: jar file already in cache %s", (const char*)jarURLStr)); - rv = onJARFileAvailable(this, closure); - goto error; - } - } - - // Case 3: Download jar file and cache - { - NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv); - if (NS_FAILED(rv)) goto error; - - nsAutoMonitor monitor(mMonitor); - - nsCOMPtr downloadObserver = - new nsJARDownloadObserver(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)); - - // set up the jarBaseChannel for getting input: - rv = jarBaseChannel->SetLoadAttributes(mLoadAttributes); - if (NS_FAILED(rv)) goto error; - rv = jarBaseChannel->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) goto error; - - rv = jarBaseChannel->OpenInputStream(getter_AddRefs(jarBaseIn)); - if (NS_FAILED(rv)) goto error; - - // use a file transport to serve as a data pump for the download (done - // on some other thread) - rv = fts->CreateTransport(jarCacheFile, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0664, - getter_AddRefs(mJarCacheTransport)); - if (NS_FAILED(rv)) goto error; - rv = mJarCacheTransport->SetBufferSegmentSize(mBufferSegmentSize); - if (NS_FAILED(rv)) goto error; - rv = mJarCacheTransport->SetBufferMaxSize(mBufferMaxSize); - if (NS_FAILED(rv)) goto error; -#if 0 // don't give callbacks for writing to disk - rv = mJarCacheTransport->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) goto error; -#endif - - rv = mJarCacheTransport->AsyncWrite(jarBaseIn, downloadObserver, nsnull); - return rv; - } + // if DownloadComplete() was called early, need to release the reference. + if (mSynchronousRead && mSynchronousInputStream) + mDownloader = null_nsCOMPtr(); error: if (NS_FAILED(rv) && mLoadGroup) { @@ -548,57 +356,6 @@ nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, return rv; } -nsresult -nsJARChannel::GetCacheFile(nsIFile* *cacheFile) -{ - // XXX change later to use the real network cache - nsresult rv; - - nsCOMPtr jarCacheFile; - rv = NS_GetSpecialDirectory(NS_XPCOM_COMPONENT_DIR, - getter_AddRefs(jarCacheFile)); - if (NS_FAILED(rv)) return rv; - - jarCacheFile->Append("jarCache"); - - PRBool exists; - rv = jarCacheFile->Exists(&exists); - if (NS_FAILED(rv)) return rv; - if (!exists) { - rv = jarCacheFile->Create(nsIFile::DIRECTORY_TYPE, 0775); - if (NS_FAILED(rv)) return rv; - } - - nsCOMPtr jarBaseURL = do_QueryInterface(mJARBaseURI, &rv); - if (NS_FAILED(rv)) return rv; - - char* jarFileName; - rv = jarBaseURL->GetFileName(&jarFileName); - if (NS_FAILED(rv)) return rv; - rv = jarCacheFile->Append(jarFileName); - nsCRT::free(jarFileName); - if (NS_FAILED(rv)) return rv; - - *cacheFile = jarCacheFile; - NS_ADDREF(*cacheFile); - - // also set up the jar base file channel while we're here - rv = NS_NewLocalFileChannel(getter_AddRefs(mJARBaseFile), - jarCacheFile, - PR_RDONLY, - 0); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferSegmentSize(mBufferSegmentSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferMaxSize(mBufferMaxSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetLoadAttributes(mLoadAttributes); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) return rv; - return rv; -} - nsresult nsJARChannel::AsyncReadJARElement() { @@ -606,10 +363,6 @@ nsJARChannel::AsyncReadJARElement() nsAutoMonitor monitor(mMonitor); - // Ensure that we have mJARBaseFile at this point. We'll need it in our - // nsIFileSystem implementation that accesses the jar file. - NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null"); - NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv); if (NS_FAILED(rv)) return rv; @@ -639,7 +392,7 @@ nsJARChannel::AsyncReadJARElement() } NS_IMETHODIMP -nsJARChannel::AsyncWrite(nsIInputStream* fromStream, +nsJARChannel::AsyncWrite(nsIInputStream* fromStream, nsIStreamObserver* observer, nsISupports* ctxt) { @@ -897,6 +650,28 @@ nsJARChannel::GetSecurityInfo(nsISupports * *aSecurityInfo) return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// nsIDownloadObserver methods: + +NS_IMETHODIMP +nsJARChannel::OnDownloadComplete(nsIDownloader* aDownloader, nsISupports* aClosure, + nsresult aStatus, nsIFile* aFile) +{ + nsresult rv=aStatus; + if(NS_SUCCEEDED(aStatus)) { + NS_ASSERTION(!mDownloader ||(aDownloader == mDownloader.get()), "wrong downloader"); + mDownloadedJARFile = aFile; + // after successfully downloading the jar file to the cache, + // start the extraction process: + if (mSynchronousRead) + rv = OpenJARElement(); + else + rv = AsyncReadJARElement(); + } + mDownloader = null_nsCOMPtr(); + return rv; +} + //////////////////////////////////////////////////////////////////////////////// // nsIStreamObserver methods: @@ -959,20 +734,14 @@ nsJARChannel::EnsureZipReader() { if (mJAR == nsnull) { nsresult rv; - if (mJARBaseFile == nsnull) + if (mDownloadedJARFile == nsnull) return NS_ERROR_FAILURE; -// NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null"); - - nsCOMPtr fs; - rv = mJARBaseFile->GetFile(getter_AddRefs(fs)); - if (NS_FAILED(rv)) return rv; - nsCOMPtr jarCache; rv = mJARProtocolHandler->GetJARCache(getter_AddRefs(jarCache)); if (NS_FAILED(rv)) return rv; - rv = jarCache->GetZip(fs, getter_AddRefs(mJAR)); + rv = jarCache->GetZip(mDownloadedJARFile, getter_AddRefs(mJAR)); if (NS_FAILED(rv)) return rv; } return NS_OK; @@ -1004,17 +773,6 @@ nsJARChannel::Open(char* *contentType, PRInt32 *contentLength) NS_IMETHODIMP nsJARChannel::Close(nsresult status) { -/* - nsresult rv; - - nsCOMPtr jarCache; - rv = mJARProtocolHandler->GetJARCache(getter_AddRefs(jarCache)); - if (NS_FAILED(rv)) return rv; - rv = jarCache->ReleaseZip(mJAR); - if (NS_FAILED(rv)) return rv; - - mJAR = null_nsCOMPtr(); -*/ return NS_OK; } diff --git a/mozilla/modules/libjar/nsJARChannel.h b/mozilla/modules/libjar/nsJARChannel.h index f4c7445ef21..9bfdf71c3c4 100644 --- a/mozilla/modules/libjar/nsJARChannel.h +++ b/mozilla/modules/libjar/nsJARChannel.h @@ -14,7 +14,7 @@ * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All + * Copyright (C) 1998,2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): @@ -36,6 +36,8 @@ #include "nsCOMPtr.h" #include "nsIFile.h" #include "prmon.h" +#include "nsIDownloader.h" +#include "nsIInputStream.h" class nsIFileChannel; class nsJARChannel; @@ -48,14 +50,10 @@ class nsJARChannel; {0x9f, 0x63, 0x00, 0x60, 0x08, 0xa6, 0xef, 0xe9} \ } -#define JAR_DIRECTORY "jarCache" - -typedef nsresult -(*OnJARFileAvailableFun)(nsJARChannel* channel, void* closure); - class nsJARChannel : public nsIJARChannel, public nsIStreamListener, - public nsIStreamIO + public nsIStreamIO, + public nsIDownloadObserver { public: NS_DECL_ISUPPORTS @@ -65,6 +63,7 @@ public: NS_DECL_NSISTREAMOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSISTREAMIO + NS_DECL_NSIDOWNLOADOBSERVER nsJARChannel(); virtual ~nsJARChannel(); @@ -74,10 +73,9 @@ public: Create(nsISupports* aOuter, REFNSIID aIID, void **aResult); nsresult Init(nsIJARProtocolHandler* aHandler, nsIURI* uri); - nsresult EnsureJARFileAvailable(OnJARFileAvailableFun fun, - void* closure); + nsresult EnsureJARFileAvailable(); + nsresult OpenJARElement(); nsresult AsyncReadJARElement(); - nsresult GetCacheFile(nsIFile* *cacheFile); nsresult EnsureZipReader(); friend class nsJARDownloadObserver; @@ -99,15 +97,17 @@ protected: char* mContentType; PRInt32 mContentLength; nsCOMPtr mJARBaseURI; - nsCOMPtr mJARBaseFile; char* mJAREntry; nsCOMPtr mJAR; + nsCOMPtr mDownloadedJARFile; PRUint32 mBufferSegmentSize; PRUint32 mBufferMaxSize; nsresult mStatus; + PRBool mSynchronousRead; + nsCOMPtr mSynchronousInputStream; PRMonitor* mMonitor; - nsCOMPtr mJarCacheTransport; + nsCOMPtr mDownloader; nsCOMPtr mJarExtractionTransport; }; diff --git a/mozilla/modules/libjar/nsJARURI.cpp b/mozilla/modules/libjar/nsJARURI.cpp index 783da977632..ea640fa7da2 100644 --- a/mozilla/modules/libjar/nsJARURI.cpp +++ b/mozilla/modules/libjar/nsJARURI.cpp @@ -37,6 +37,8 @@ nsJARURI::nsJARURI() nsJARURI::~nsJARURI() { + if (mJAREntry) + nsMemory::Free(mJAREntry); } NS_IMPL_THREADSAFE_ISUPPORTS2(nsJARURI, nsIJARURI, nsIURI) diff --git a/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp b/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp index d5023432148..4d45badad2c 100644 --- a/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp +++ b/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp @@ -12,7 +12,7 @@ * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Copyright (C) 1998,2000 Netscape Communications Corporation. All Rights * Reserved. * */ @@ -20,11 +20,10 @@ #include "nsNetUtil.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" -#include "nsSpecialSystemDirectory.h" #include "nsJARChannel.h" #include "nsCRT.h" #include "nsIFileTransportService.h" -#include "nsIURL.h" +#include "nsIURI.h" #include "nsCExternalHandlerService.h" #include "nsIMIMEService.h" #include "nsAutoLock.h" @@ -33,13 +32,6 @@ #include "nsScriptSecurityManager.h" #include "nsIAggregatePrincipal.h" #include "nsXPIDLString.h" -#include "nsDirectoryServiceDefs.h" - -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR -#include "nsINetDataCacheManager.h" -#include "nsICachedNetData.h" -#include "nsIStreamAsFile.h" -#endif static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID); static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); @@ -63,70 +55,6 @@ PRLogModuleInfo* gJarProtocolLog = nsnull; //////////////////////////////////////////////////////////////////////////////// -class nsJARDownloadObserver : public nsIStreamObserver -{ -public: - NS_DECL_ISUPPORTS - - NS_IMETHOD OnStartRequest(nsIChannel* jarCacheTransport, - nsISupports* context) { - return NS_OK; - } - - NS_IMETHOD OnStopRequest(nsIChannel* jarCacheTransport, nsISupports* context, - nsresult aStatus, const PRUnichar* aStatusArg) { - 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, aStatus)); - } - } -#endif - if (NS_SUCCEEDED(aStatus) && mJARChannel->mJarCacheTransport) { - NS_ASSERTION(jarCacheTransport == (mJARChannel->mJarCacheTransport).get(), - "wrong transport"); - // after successfully downloading the jar file to the cache, - // start the extraction process: - rv = mOnJARFileAvailable(mJARChannel, mClosure); - } - mJARChannel->mJarCacheTransport = nsnull; - return rv; - } - - nsJARDownloadObserver(nsJARChannel* jarChannel, - OnJARFileAvailableFun onJARFileAvailable, - void* closure) - : mJARChannel(jarChannel), - mOnJARFileAvailable(onJARFileAvailable), - mClosure(closure) - { - NS_INIT_REFCNT(); - NS_ADDREF(mJARChannel); - } - - virtual ~nsJARDownloadObserver() { - NS_RELEASE(mJARChannel); - } - -protected: - nsJARChannel* mJARChannel; - OnJARFileAvailableFun mOnJARFileAvailable; - void* mClosure; -}; - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARDownloadObserver, nsIStreamObserver) - -//////////////////////////////////////////////////////////////////////////////// - #define NS_DEFAULT_JAR_BUFFER_SEGMENT_SIZE (16*1024) #define NS_DEFAULT_JAR_BUFFER_MAX_SIZE (256*1024) @@ -165,13 +93,14 @@ nsJARChannel::~nsJARChannel() PR_DestroyMonitor(mMonitor); } -NS_IMPL_THREADSAFE_ISUPPORTS6(nsJARChannel, +NS_IMPL_THREADSAFE_ISUPPORTS7(nsJARChannel, nsIJARChannel, nsIChannel, nsIRequest, nsIStreamObserver, nsIStreamListener, - nsIStreamIO) + nsIStreamIO, + nsIDownloadObserver) NS_METHOD nsJARChannel::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) @@ -243,11 +172,6 @@ nsJARChannel::Cancel(nsresult status) nsresult rv; nsAutoMonitor monitor(mMonitor); - if (mJarCacheTransport) { - rv = mJarCacheTransport->Cancel(status); - if (NS_FAILED(rv)) return rv; - mJarCacheTransport = nsnull; - } if (mJarExtractionTransport) { rv = mJarExtractionTransport->Cancel(status); if (NS_FAILED(rv)) return rv; @@ -263,10 +187,6 @@ nsJARChannel::Suspend() nsresult rv; nsAutoMonitor monitor(mMonitor); - if (mJarCacheTransport) { - rv = mJarCacheTransport->Suspend(); - if (NS_FAILED(rv)) return rv; - } if (mJarExtractionTransport) { rv = mJarExtractionTransport->Suspend(); if (NS_FAILED(rv)) return rv; @@ -281,10 +201,6 @@ nsJARChannel::Resume() nsresult rv; nsAutoMonitor monitor(mMonitor); - if (mJarCacheTransport) { - rv = mJarCacheTransport->Resume(); - if (NS_FAILED(rv)) return rv; - } if (mJarExtractionTransport) { rv = mJarExtractionTransport->Resume(); if (NS_FAILED(rv)) return rv; @@ -299,8 +215,12 @@ nsJARChannel::Resume() NS_IMETHODIMP nsJARChannel::GetOriginalURI(nsIURI* *aOriginalURI) { - *aOriginalURI = mOriginalURI ? mOriginalURI : nsCOMPtr(mURI); - NS_ADDREF(*aOriginalURI); + if (mOriginalURI) + *aOriginalURI = mOriginalURI; + else + *aOriginalURI = NS_STATIC_CAST(nsIURI*, mURI); + + NS_IF_ADDREF(*aOriginalURI); return NS_OK; } @@ -327,15 +247,14 @@ nsJARChannel::SetURI(nsIURI* aURI) return rv; } -static nsresult -OpenJARElement(nsJARChannel* jarChannel, void* closure) +nsresult +nsJARChannel::OpenJARElement() { nsresult rv; - nsIInputStream* *result = (nsIInputStream**)closure; - nsAutoCMonitor mon(jarChannel); - rv = jarChannel->Open(nsnull, nsnull); - if (NS_FAILED(rv)) return rv; - rv = jarChannel->GetInputStream(result); + nsAutoCMonitor mon(this); + rv = Open(nsnull, nsnull); + if (NS_SUCCEEDED(rv)) + rv = GetInputStream(getter_AddRefs(mSynchronousInputStream)); mon.Notify(); // wake up OpenInputStream return rv; } @@ -345,12 +264,20 @@ nsJARChannel::OpenInputStream(nsIInputStream* *result) { nsAutoCMonitor mon(this); nsresult rv; - *result = nsnull; - rv = EnsureJARFileAvailable(OpenJARElement, result); + mSynchronousRead = PR_TRUE; + rv = EnsureJARFileAvailable(); if (NS_FAILED(rv)) return rv; - if (*result == nsnull) + if (mSynchronousInputStream == nsnull) mon.Wait(); - return rv; + if (mSynchronousInputStream) + { + *result = mSynchronousInputStream; // Result of GetInputStream called on transport thread + NS_ADDREF(*result); + mSynchronousInputStream = null_nsCOMPtr(); + return NS_OK; + } + else + return NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -360,14 +287,6 @@ nsJARChannel::OpenOutputStream(nsIOutputStream* *result) return NS_ERROR_NOT_IMPLEMENTED; } -static nsresult -ReadJARElement(nsJARChannel* jarChannel, void* closure) -{ - nsresult rv; - rv = jarChannel->AsyncReadJARElement(); - return rv; -} - NS_IMETHODIMP nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt) { @@ -395,31 +314,19 @@ nsJARChannel::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt) if (NS_FAILED(rv)) return rv; } - return EnsureJARFileAvailable(ReadJARElement, nsnull); + mSynchronousRead = PR_FALSE; + return EnsureJARFileAvailable(); } nsresult -nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, - void* closure) +nsJARChannel::EnsureJARFileAvailable() { - // There are 3 cases to dealing with jar files: - // 1. They exist on the local disk and don't need to be cached - // 2. They have already been downloaded and exist in the cache - // 3. They need to be downloaded and cached nsresult rv; nsCOMPtr jarBaseChannel; nsCOMPtr jarCacheFile; nsCOMPtr jarCacheTransport; nsCOMPtr jarBaseIn; -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR - nsCOMPtr cacheMgr; - nsXPIDLCString jarBaseSpec; - nsCOMPtr cachedData; - nsCOMPtr streamAsFile; - nsCOMPtr file; -#endif - #ifdef PR_LOGGING nsXPIDLCString jarURLStr; mURI->GetSpec(getter_Copies(jarURLStr)); @@ -433,112 +340,13 @@ nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, rv = mURI->GetJAREntry(&mJAREntry); if (NS_FAILED(rv)) goto error; -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR + rv = NS_NewDownloader(getter_AddRefs(mDownloader), + mJARBaseURI, this, nsnull, mSynchronousRead, mLoadGroup, mCallbacks, + mLoadAttributes, mBufferSegmentSize, mBufferMaxSize); - cacheMgr = do_GetService(NS_NETWORK_CACHE_MANAGER_CONTRACTID, &rv); - if (NS_FAILED(rv)) goto error; - - rv = mJARBaseURI->GetSpec(getter_Copies(jarBaseSpec)); - if (NS_FAILED(rv)) goto error; - - rv = cacheMgr->GetCachedNetData(jarBaseSpec, nsnull, 0, nsINetDataCacheManager::CACHE_AS_FILE, - getter_AddRefs(cachedData)); - if (NS_SUCCEEDED(rv)) { - streamAsFile = do_QueryInterface(cachedData, &rv); - if (NS_FAILED(rv)) goto error; - - rv = streamAsFile->GetFile(getter_AddRefs(file)); - if (NS_FAILED(rv)) goto error; - } -#endif - - rv = NS_OpenURI(getter_AddRefs(jarBaseChannel), mJARBaseURI, nsnull); - if (NS_FAILED(rv)) goto error; - - rv = jarBaseChannel->GetLocalFile(getter_AddRefs(jarCacheFile)); - if (NS_SUCCEEDED(rv) && jarCacheFile) { - // Case 1: Local file - // we've already got a local jar file -- no need to download it - - rv = NS_NewLocalFileChannel(getter_AddRefs(mJARBaseFile), - jarCacheFile, PR_RDONLY, 0); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferSegmentSize(mBufferSegmentSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferMaxSize(mBufferMaxSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetLoadAttributes(mLoadAttributes); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) return rv; - - PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, - ("nsJarProtocol: extracting local jar file %s", (const char*)jarURLStr)); - rv = onJARFileAvailable(this, closure); - goto error; - } - - rv = GetCacheFile(getter_AddRefs(jarCacheFile)); - if (NS_FAILED(rv)) goto error; - - PRBool filePresent; - rv = jarCacheFile->IsFile(&filePresent); - if (NS_SUCCEEDED(rv) && filePresent) { - // failed downloads can sometimes leave a zero-length file, so check for that too: - PRInt64 size; - rv = jarCacheFile->GetFileSize(&size); - if (NS_FAILED(rv)) goto error; - if (!LL_IS_ZERO(size)) { - // Case 2: Already downloaded - // we've already got the file in the local cache -- no need to download it - PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, - ("nsJarProtocol: jar file already in cache %s", (const char*)jarURLStr)); - rv = onJARFileAvailable(this, closure); - goto error; - } - } - - // Case 3: Download jar file and cache - { - NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv); - if (NS_FAILED(rv)) goto error; - - nsAutoMonitor monitor(mMonitor); - - nsCOMPtr downloadObserver = - new nsJARDownloadObserver(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)); - - // set up the jarBaseChannel for getting input: - rv = jarBaseChannel->SetLoadAttributes(mLoadAttributes); - if (NS_FAILED(rv)) goto error; - rv = jarBaseChannel->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) goto error; - - rv = jarBaseChannel->OpenInputStream(getter_AddRefs(jarBaseIn)); - if (NS_FAILED(rv)) goto error; - - // use a file transport to serve as a data pump for the download (done - // on some other thread) - rv = fts->CreateTransport(jarCacheFile, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0664, - getter_AddRefs(mJarCacheTransport)); - if (NS_FAILED(rv)) goto error; - rv = mJarCacheTransport->SetBufferSegmentSize(mBufferSegmentSize); - if (NS_FAILED(rv)) goto error; - rv = mJarCacheTransport->SetBufferMaxSize(mBufferMaxSize); - if (NS_FAILED(rv)) goto error; -#if 0 // don't give callbacks for writing to disk - rv = mJarCacheTransport->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) goto error; -#endif - - rv = mJarCacheTransport->AsyncWrite(jarBaseIn, downloadObserver, nsnull); - return rv; - } + // if DownloadComplete() was called early, need to release the reference. + if (mSynchronousRead && mSynchronousInputStream) + mDownloader = null_nsCOMPtr(); error: if (NS_FAILED(rv) && mLoadGroup) { @@ -548,57 +356,6 @@ nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, return rv; } -nsresult -nsJARChannel::GetCacheFile(nsIFile* *cacheFile) -{ - // XXX change later to use the real network cache - nsresult rv; - - nsCOMPtr jarCacheFile; - rv = NS_GetSpecialDirectory(NS_XPCOM_COMPONENT_DIR, - getter_AddRefs(jarCacheFile)); - if (NS_FAILED(rv)) return rv; - - jarCacheFile->Append("jarCache"); - - PRBool exists; - rv = jarCacheFile->Exists(&exists); - if (NS_FAILED(rv)) return rv; - if (!exists) { - rv = jarCacheFile->Create(nsIFile::DIRECTORY_TYPE, 0775); - if (NS_FAILED(rv)) return rv; - } - - nsCOMPtr jarBaseURL = do_QueryInterface(mJARBaseURI, &rv); - if (NS_FAILED(rv)) return rv; - - char* jarFileName; - rv = jarBaseURL->GetFileName(&jarFileName); - if (NS_FAILED(rv)) return rv; - rv = jarCacheFile->Append(jarFileName); - nsCRT::free(jarFileName); - if (NS_FAILED(rv)) return rv; - - *cacheFile = jarCacheFile; - NS_ADDREF(*cacheFile); - - // also set up the jar base file channel while we're here - rv = NS_NewLocalFileChannel(getter_AddRefs(mJARBaseFile), - jarCacheFile, - PR_RDONLY, - 0); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferSegmentSize(mBufferSegmentSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetBufferMaxSize(mBufferMaxSize); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetLoadAttributes(mLoadAttributes); - if (NS_FAILED(rv)) return rv; - rv = mJARBaseFile->SetNotificationCallbacks(mCallbacks); - if (NS_FAILED(rv)) return rv; - return rv; -} - nsresult nsJARChannel::AsyncReadJARElement() { @@ -606,10 +363,6 @@ nsJARChannel::AsyncReadJARElement() nsAutoMonitor monitor(mMonitor); - // Ensure that we have mJARBaseFile at this point. We'll need it in our - // nsIFileSystem implementation that accesses the jar file. - NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null"); - NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv); if (NS_FAILED(rv)) return rv; @@ -639,7 +392,7 @@ nsJARChannel::AsyncReadJARElement() } NS_IMETHODIMP -nsJARChannel::AsyncWrite(nsIInputStream* fromStream, +nsJARChannel::AsyncWrite(nsIInputStream* fromStream, nsIStreamObserver* observer, nsISupports* ctxt) { @@ -897,6 +650,28 @@ nsJARChannel::GetSecurityInfo(nsISupports * *aSecurityInfo) return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// nsIDownloadObserver methods: + +NS_IMETHODIMP +nsJARChannel::OnDownloadComplete(nsIDownloader* aDownloader, nsISupports* aClosure, + nsresult aStatus, nsIFile* aFile) +{ + nsresult rv=aStatus; + if(NS_SUCCEEDED(aStatus)) { + NS_ASSERTION(!mDownloader ||(aDownloader == mDownloader.get()), "wrong downloader"); + mDownloadedJARFile = aFile; + // after successfully downloading the jar file to the cache, + // start the extraction process: + if (mSynchronousRead) + rv = OpenJARElement(); + else + rv = AsyncReadJARElement(); + } + mDownloader = null_nsCOMPtr(); + return rv; +} + //////////////////////////////////////////////////////////////////////////////// // nsIStreamObserver methods: @@ -959,20 +734,14 @@ nsJARChannel::EnsureZipReader() { if (mJAR == nsnull) { nsresult rv; - if (mJARBaseFile == nsnull) + if (mDownloadedJARFile == nsnull) return NS_ERROR_FAILURE; -// NS_ASSERTION(mJARBaseFile, "mJARBaseFile is null"); - - nsCOMPtr fs; - rv = mJARBaseFile->GetFile(getter_AddRefs(fs)); - if (NS_FAILED(rv)) return rv; - nsCOMPtr jarCache; rv = mJARProtocolHandler->GetJARCache(getter_AddRefs(jarCache)); if (NS_FAILED(rv)) return rv; - rv = jarCache->GetZip(fs, getter_AddRefs(mJAR)); + rv = jarCache->GetZip(mDownloadedJARFile, getter_AddRefs(mJAR)); if (NS_FAILED(rv)) return rv; } return NS_OK; @@ -1004,17 +773,6 @@ nsJARChannel::Open(char* *contentType, PRInt32 *contentLength) NS_IMETHODIMP nsJARChannel::Close(nsresult status) { -/* - nsresult rv; - - nsCOMPtr jarCache; - rv = mJARProtocolHandler->GetJARCache(getter_AddRefs(jarCache)); - if (NS_FAILED(rv)) return rv; - rv = jarCache->ReleaseZip(mJAR); - if (NS_FAILED(rv)) return rv; - - mJAR = null_nsCOMPtr(); -*/ return NS_OK; } diff --git a/mozilla/netwerk/protocol/jar/src/nsJARChannel.h b/mozilla/netwerk/protocol/jar/src/nsJARChannel.h index f4c7445ef21..9bfdf71c3c4 100644 --- a/mozilla/netwerk/protocol/jar/src/nsJARChannel.h +++ b/mozilla/netwerk/protocol/jar/src/nsJARChannel.h @@ -14,7 +14,7 @@ * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All + * Copyright (C) 1998,2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): @@ -36,6 +36,8 @@ #include "nsCOMPtr.h" #include "nsIFile.h" #include "prmon.h" +#include "nsIDownloader.h" +#include "nsIInputStream.h" class nsIFileChannel; class nsJARChannel; @@ -48,14 +50,10 @@ class nsJARChannel; {0x9f, 0x63, 0x00, 0x60, 0x08, 0xa6, 0xef, 0xe9} \ } -#define JAR_DIRECTORY "jarCache" - -typedef nsresult -(*OnJARFileAvailableFun)(nsJARChannel* channel, void* closure); - class nsJARChannel : public nsIJARChannel, public nsIStreamListener, - public nsIStreamIO + public nsIStreamIO, + public nsIDownloadObserver { public: NS_DECL_ISUPPORTS @@ -65,6 +63,7 @@ public: NS_DECL_NSISTREAMOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSISTREAMIO + NS_DECL_NSIDOWNLOADOBSERVER nsJARChannel(); virtual ~nsJARChannel(); @@ -74,10 +73,9 @@ public: Create(nsISupports* aOuter, REFNSIID aIID, void **aResult); nsresult Init(nsIJARProtocolHandler* aHandler, nsIURI* uri); - nsresult EnsureJARFileAvailable(OnJARFileAvailableFun fun, - void* closure); + nsresult EnsureJARFileAvailable(); + nsresult OpenJARElement(); nsresult AsyncReadJARElement(); - nsresult GetCacheFile(nsIFile* *cacheFile); nsresult EnsureZipReader(); friend class nsJARDownloadObserver; @@ -99,15 +97,17 @@ protected: char* mContentType; PRInt32 mContentLength; nsCOMPtr mJARBaseURI; - nsCOMPtr mJARBaseFile; char* mJAREntry; nsCOMPtr mJAR; + nsCOMPtr mDownloadedJARFile; PRUint32 mBufferSegmentSize; PRUint32 mBufferMaxSize; nsresult mStatus; + PRBool mSynchronousRead; + nsCOMPtr mSynchronousInputStream; PRMonitor* mMonitor; - nsCOMPtr mJarCacheTransport; + nsCOMPtr mDownloader; nsCOMPtr mJarExtractionTransport; }; diff --git a/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp b/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp index 783da977632..ea640fa7da2 100644 --- a/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp +++ b/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp @@ -37,6 +37,8 @@ nsJARURI::nsJARURI() nsJARURI::~nsJARURI() { + if (mJAREntry) + nsMemory::Free(mJAREntry); } NS_IMPL_THREADSAFE_ISUPPORTS2(nsJARURI, nsIJARURI, nsIURI)