diff --git a/mozilla/modules/libjar/nsJARChannel.cpp b/mozilla/modules/libjar/nsJARChannel.cpp index d5023432148..b817dcef409 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,7 +215,7 @@ nsJARChannel::Resume() NS_IMETHODIMP nsJARChannel::GetOriginalURI(nsIURI* *aOriginalURI) { - *aOriginalURI = mOriginalURI ? mOriginalURI : nsCOMPtr(mURI); + *aOriginalURI = mOriginalURI ? mOriginalURI : mURI.get(); NS_ADDREF(*aOriginalURI); return NS_OK; } @@ -327,15 +243,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,11 +260,17 @@ 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) - mon.Wait(); + mon.Wait(); + if (mSynchronousInputStream) { + *result = mSynchronousInputStream; // Result of GetInputStream called on transport thread + NS_ADDREF(*result); + mSynchronousInputStream = null_nsCOMPtr(); + } else { + rv = NS_ERROR_FAILURE; + } return rv; } @@ -360,14 +281,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 +308,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 +334,9 @@ nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, rv = mURI->GetJAREntry(&mJAREntry); if (NS_FAILED(rv)) goto error; -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR - - 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; - } + rv = NS_NewDownloader(getter_AddRefs(mDownloader), + mJARBaseURI, this, nsnull, mLoadGroup, mCallbacks, + mLoadAttributes, mBufferSegmentSize, mBufferMaxSize); error: if (NS_FAILED(rv) && mLoadGroup) { @@ -548,57 +346,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 +353,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 +382,7 @@ nsJARChannel::AsyncReadJARElement() } NS_IMETHODIMP -nsJARChannel::AsyncWrite(nsIInputStream* fromStream, +nsJARChannel::AsyncWrite(nsIInputStream* fromStream, nsIStreamObserver* observer, nsISupports* ctxt) { @@ -897,6 +640,28 @@ nsJARChannel::GetSecurityInfo(nsISupports * *aSecurityInfo) return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// nsIDownloadObserver methods: + +NS_IMETHODIMP +nsJARChannel::OnDownloadComplete(nsIDownloader* aDownloader, nsISupports* aClosure, + nsresult aStatus, nsIFile* aFile) +{ + nsresult rv; + if(NS_SUCCEEDED(aStatus) && mDownloader) { + NS_ASSERTION(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 +724,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 +763,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..29bd300a5df 100644 --- a/mozilla/modules/libjar/nsJARURI.cpp +++ b/mozilla/modules/libjar/nsJARURI.cpp @@ -170,72 +170,96 @@ nsJARURI::SetScheme(const char * aScheme) NS_IMETHODIMP nsJARURI::GetUsername(char * *aUsername) { + if (mJARFile) + return mJARFile->GetUsername(aUsername); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetUsername(const char * aUsername) { + if (mJARFile) + return mJARFile->SetUsername(aUsername); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPassword(char * *aPassword) { + if (mJARFile) + return mJARFile->GetPassword(aPassword); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPassword(const char * aPassword) { + if (mJARFile) + return mJARFile->SetPassword(aPassword); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPreHost(char * *aPreHost) { + if (mJARFile) + return mJARFile->GetPreHost(aPreHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPreHost(const char * aPreHost) { + if (mJARFile) + return mJARFile->SetPreHost(aPreHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetHost(char * *aHost) { + if (mJARFile) + return mJARFile->GetHost(aHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetHost(const char * aHost) { + if (mJARFile) + return mJARFile->SetHost(aHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPort(PRInt32 *aPort) { + if (mJARFile) + return mJARFile->GetPort(aPort); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPort(PRInt32 aPort) { + if (mJARFile) + return mJARFile->SetPort(aPort); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPath(char * *aPath) { + if (mJARFile) + return mJARFile->GetPath(aPath); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPath(const char * aPath) { + if (mJARFile) + return mJARFile->SetPath(aPath); return NS_ERROR_FAILURE; } diff --git a/mozilla/netwerk/base/public/MANIFEST_IDL b/mozilla/netwerk/base/public/MANIFEST_IDL index a80092cfdff..b3efaf7b4b3 100644 --- a/mozilla/netwerk/base/public/MANIFEST_IDL +++ b/mozilla/netwerk/base/public/MANIFEST_IDL @@ -4,6 +4,7 @@ nsIAuthenticator.idl nsIChannel.idl +nsIDownloader.idl nsIFileTransportService.idl nsIPasswordManager.idl nsIPrompt.idl @@ -16,6 +17,7 @@ nsISocketTransportService.idl nsIStreamIO.idl nsIStreamListener.idl nsIStreamLoader.idl +nsIDownloader.idl nsIStreamObserver.idl nsIURI.idl nsIURL.idl diff --git a/mozilla/netwerk/base/public/Makefile.in b/mozilla/netwerk/base/public/Makefile.in index 9b81f00014b..af97b0a4433 100644 --- a/mozilla/netwerk/base/public/Makefile.in +++ b/mozilla/netwerk/base/public/Makefile.in @@ -31,6 +31,7 @@ MODULE = necko XPIDLSRCS = \ nsIAuthenticator.idl \ nsIChannel.idl \ + nsIDownloader.idl \ nsIFileStreams.idl \ nsIFileTransportService.idl \ nsIIOService.idl \ @@ -52,6 +53,7 @@ XPIDLSRCS = \ nsIStreamIO.idl \ nsIStreamListener.idl \ nsIStreamLoader.idl \ + nsISocketTransport.idl \ nsIStreamObserver.idl \ nsIURI.idl \ nsIURL.idl \ diff --git a/mozilla/netwerk/base/public/makefile.win b/mozilla/netwerk/base/public/makefile.win index 841b76c01ab..d156aa6274f 100644 --- a/mozilla/netwerk/base/public/makefile.win +++ b/mozilla/netwerk/base/public/makefile.win @@ -55,6 +55,7 @@ XPIDLSRCS = \ .\nsIStreamIO.idl \ .\nsIStreamListener.idl \ .\nsIStreamLoader.idl \ + .\nsIDownloader.idl \ .\nsIStreamObserver.idl \ .\nsIURI.idl \ .\nsIURL.idl \ diff --git a/mozilla/netwerk/base/public/nsIDownloader.idl b/mozilla/netwerk/base/public/nsIDownloader.idl new file mode 100644 index 00000000000..3641116eec1 --- /dev/null +++ b/mozilla/netwerk/base/public/nsIDownloader.idl @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#include "nsISupports.idl" +#include "nsIChannel.idl" + +interface nsIURI; +interface nsILoadGroup; +interface nsIStreamLoader; +interface nsIInterfaceRequestor; +interface nsIFile; +interface nsIDownloader; + +[scriptable, uuid(6e0fc962-4a6f-4fa6-831f-8c26c554407f)] +interface nsIDownloadObserver : nsISupports +{ + void onDownloadComplete(in nsIDownloader downloader, + in nsISupports ctxt, + in nsresult status, + in nsIFile result); +}; + +[scriptable, uuid(9632cc0d-864d-4f92-b7e5-bd8097c4e9a5)] +interface nsIDownloader : nsISupports +{ + void init(in nsIURI uri, + in nsIDownloadObserver completionObserver, + in nsISupports ctxt, + in nsILoadGroup loadGroup, + in nsIInterfaceRequestor notificationCallbacks, + in nsLoadFlags loadAttributes, + in unsigned long bufferSegmentSize, + in unsigned long bufferMaxSize); +}; + +%{C++ + +#define NS_DOWNLOADER_CID \ +{ /* 510a86bb-6019-4ed1-bb4f-965cffd23ece*/ \ + 0x510a86bb, 0x6019, 0x4ed1, { 0xbb, 0x4f, 0x96, 0x5c, 0xff, 0xd2, 0x3e, 0xce } \ +} + +%} diff --git a/mozilla/netwerk/base/public/nsNetUtil.h b/mozilla/netwerk/base/public/nsNetUtil.h index f37bf0f2426..ee23c81e452 100644 --- a/mozilla/netwerk/base/public/nsNetUtil.h +++ b/mozilla/netwerk/base/public/nsNetUtil.h @@ -37,6 +37,7 @@ #include "nsMemory.h" #include "nsCOMPtr.h" #include "nsIHTTPProtocolHandler.h" +#include "nsIDownloader.h" #include "nsIStreamLoader.h" #include "nsIStreamIO.h" #include "nsXPIDLString.h" @@ -312,6 +313,33 @@ NS_NewLoadGroup(nsILoadGroup* *result, nsIStreamObserver* obs) } +inline nsresult +NS_NewDownloader(nsIDownloader* *result, + nsIURI* uri, + nsIDownloadObserver* observer, + nsISupports* context = nsnull, + nsILoadGroup* loadGroup = nsnull, + nsIInterfaceRequestor* notificationCallbacks = nsnull, + nsLoadFlags loadAttributes = nsIChannel::LOAD_NORMAL, + PRUint32 bufferSegmentSize = 0, + PRUint32 bufferMaxSize = 0) +{ + nsresult rv; + nsCOMPtr downloader; + static NS_DEFINE_CID(kDownloaderCID, NS_DOWNLOADER_CID); + rv = nsComponentManager::CreateInstance(kDownloaderCID, + nsnull, + NS_GET_IID(nsIDownloader), + getter_AddRefs(downloader)); + if (NS_FAILED(rv)) return rv; + rv = downloader->Init(uri, observer, context, loadGroup, notificationCallbacks, loadAttributes, + bufferSegmentSize, bufferMaxSize); + if (NS_FAILED(rv)) return rv; + *result = downloader; + NS_ADDREF(*result); + return rv; +} + inline nsresult NS_NewStreamLoader(nsIStreamLoader* *result, nsIURI* uri, diff --git a/mozilla/netwerk/base/src/Makefile.in b/mozilla/netwerk/base/src/Makefile.in index 6073d070d42..3ca8f9779b1 100644 --- a/mozilla/netwerk/base/src/Makefile.in +++ b/mozilla/netwerk/base/src/Makefile.in @@ -51,6 +51,7 @@ CPPSRCS = \ nsInputStreamChannel.cpp \ nsDirectoryIndexStream.cpp \ nsStreamLoader.cpp \ + nsDownloader.cpp \ nsProtocolProxyService.cpp \ nsProxyAutoConfigUtils.cpp \ $(NULL) diff --git a/mozilla/netwerk/base/src/makefile.win b/mozilla/netwerk/base/src/makefile.win index dd732a858ab..dcadfa75060 100644 --- a/mozilla/netwerk/base/src/makefile.win +++ b/mozilla/netwerk/base/src/makefile.win @@ -48,6 +48,7 @@ CPP_OBJS = \ .\$(OBJDIR)\nsInputStreamChannel.obj \ .\$(OBJDIR)\nsDirectoryIndexStream.obj \ .\$(OBJDIR)\nsStreamLoader.obj \ + .\$(OBJDIR)\nsDownloader.obj \ .\$(OBJDIR)\nsProtocolProxyService.obj \ .\$(OBJDIR)\nsProxyAutoConfigUtils.obj \ $(NULL) diff --git a/mozilla/netwerk/base/src/nsDownloader.cpp b/mozilla/netwerk/base/src/nsDownloader.cpp new file mode 100644 index 00000000000..cc8b5c13466 --- /dev/null +++ b/mozilla/netwerk/base/src/nsDownloader.cpp @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#include "nsDownloader.h" +#include "nsIInputStream.h" +#include "nsIURL.h" +#include "nsNetUtil.h" +#include "nsIChannel.h" +#include "nsProxiedService.h" +#include "nsIFile.h" +#include "nsXPIDLString.h" + +#include "nsCacheManager.h" +#include "nsICachedNetData.h" +#include "nsIStreamAsFile.h" + +static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); +static NS_DEFINE_CID(kNetworkCacheManagerCID, NS_CACHE_MANAGER_CID); + +NS_IMETHODIMP +nsDownloader::Init(nsIURI* aURL, + nsIDownloadObserver* aObserver, + nsISupports* aContext, + nsILoadGroup* aGroup, + nsIInterfaceRequestor* aNotificationCallbacks, + nsLoadFlags aLoadAttributes, + PRUint32 aBufferSegmentSize, + PRUint32 aBufferMaxSize) +{ + nsresult rv; + mObserver = aObserver; + mContext = aContext; + nsCOMPtr localFile; + nsCOMPtr channel; + + aLoadAttributes |= nsIChannel::CACHE_AS_FILE; + rv = NS_OpenURI(getter_AddRefs(channel), aURL, nsnull, aGroup, aNotificationCallbacks, + aLoadAttributes, aBufferSegmentSize, aBufferMaxSize); + if (NS_SUCCEEDED(rv) && channel) + rv = channel->GetLocalFile(getter_AddRefs(localFile)); + + if (mObserver && (NS_FAILED(rv) || localFile)) { + // If the open failed or the file is local, call the observer. + // don't callback synchronously as it puts the caller + // in a recursive situation and breaks the asynchronous + // semantics of nsIDownloader + nsresult rv2 = NS_OK; + NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, + kProxyObjectManagerCID, &rv); + if (NS_FAILED(rv2)) return rv2; + + nsCOMPtr pObserver; + rv2 = pIProxyObjectManager->GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsIDownloadObserver), mObserver, + PROXY_ASYNC | PROXY_ALWAYS, getter_AddRefs(pObserver)); + if (NS_FAILED(rv2)) return rv2; + + return pObserver->OnDownloadComplete(this, mContext, rv, localFile); + } + + return channel->AsyncRead(this, aContext); +} + +NS_METHOD +nsDownloader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + if (aOuter) return NS_ERROR_NO_AGGREGATION; + + nsDownloader* it = new nsDownloader(); + if (it == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(it); + nsresult rv = it->QueryInterface(aIID, aResult); + NS_RELEASE(it); + return rv; +} + +NS_IMPL_ISUPPORTS3(nsDownloader, nsIDownloader, + nsIStreamObserver, nsIStreamListener) + +NS_IMETHODIMP +nsDownloader::OnStartRequest(nsIChannel* channel, nsISupports *ctxt) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsDownloader::OnStopRequest(nsIChannel* channel, nsISupports *ctxt, + nsresult aStatus, const PRUnichar* aStatusArg) +{ + nsresult rv; + + nsCOMPtr uri; + rv = channel->GetURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) return rv; + nsXPIDLCString spec; + rv = uri->GetSpec(getter_Copies(spec)); + if (NS_FAILED(rv)) return rv; + + NS_WITH_SERVICE(nsINetDataCacheManager, cacheMgr, kNetworkCacheManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + nsCOMPtr cachedData; + rv = cacheMgr->GetCachedNetData(spec, nsnull, 0, nsINetDataCacheManager::CACHE_AS_FILE, + getter_AddRefs(cachedData)); + + nsCOMPtr file; + if (NS_SUCCEEDED(rv)) { + nsCOMPtr streamAsFile; + streamAsFile = do_QueryInterface(cachedData, &rv); + if (NS_FAILED(rv)) return rv; + + rv = streamAsFile->GetFile(getter_AddRefs(file)); + if (NS_FAILED(rv)) return rv; + rv = aStatus; + } + + return mObserver->OnDownloadComplete(this, mContext, rv, file); +} + +#define BUF_SIZE 1024 + +NS_IMETHODIMP +nsDownloader::OnDataAvailable(nsIChannel* channel, nsISupports *ctxt, + nsIInputStream *inStr, + PRUint32 sourceOffset, PRUint32 count) +{ + // This function simply disposes of the data as it's read in. + // We assume it's already been cached and that's what we're interested in. + nsresult rv = NS_OK; + char buffer[BUF_SIZE]; + PRUint32 len, lenRead; + + rv = inStr->Available(&len); + if (NS_FAILED(rv)) return rv; + + while (len > 0) { + lenRead = PR_MIN(len, BUF_SIZE); + rv = inStr->Read(buffer, lenRead, &lenRead); + if (NS_FAILED(rv) || lenRead == 0) { + return rv; + } + len -= lenRead; + } + + return rv; +} diff --git a/mozilla/netwerk/base/src/nsDownloader.h b/mozilla/netwerk/base/src/nsDownloader.h new file mode 100644 index 00000000000..6c0583050e8 --- /dev/null +++ b/mozilla/netwerk/base/src/nsDownloader.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#ifndef nsDownloader_h__ +#define nsDownloader_h__ + +#include "nsIDownloader.h" +#include "nsIStreamListener.h" +#include "nsCOMPtr.h" +#include "nsString.h" + +class nsDownloader : public nsIDownloader, + public nsIStreamListener + +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOWNLOADER + NS_DECL_NSISTREAMOBSERVER + NS_DECL_NSISTREAMLISTENER + + nsDownloader() { NS_INIT_REFCNT();} ; + virtual ~nsDownloader() {}; + + static NS_METHOD + Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); + +protected: + nsCOMPtr mObserver; + nsCOMPtr mContext; // the observer's context +/// nsCOMPtr mLoadGroup; +}; + +#endif // nsDownloader_h__ diff --git a/mozilla/netwerk/build/nsNetModule.cpp b/mozilla/netwerk/build/nsNetModule.cpp index 0b61b3b9683..04788e106d0 100644 --- a/mozilla/netwerk/build/nsNetModule.cpp +++ b/mozilla/netwerk/build/nsNetModule.cpp @@ -40,6 +40,7 @@ #include "nsLoadGroup.h" #include "nsInputStreamChannel.h" #include "nsStreamLoader.h" +#include "nsDownloader.h" #include "nsAsyncStreamListener.h" #include "nsSyncStreamListener.h" #include "nsFileStreams.h" @@ -393,6 +394,10 @@ static nsModuleComponentInfo gNetModuleInfo[] = { NS_STREAMLOADER_CID, "@mozilla.org/network/stream-loader;1", nsStreamLoader::Create }, + { "Stream-As-File Downloader", + NS_DOWNLOADER_CID, + "@mozilla.org/network/downloader;1", + nsDownloader::Create }, { "Async Stream Observer", NS_ASYNCSTREAMOBSERVER_CID, "@mozilla.org/network/async-stream-observer;1", diff --git a/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp b/mozilla/netwerk/protocol/jar/src/nsJARChannel.cpp index d5023432148..b817dcef409 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,7 +215,7 @@ nsJARChannel::Resume() NS_IMETHODIMP nsJARChannel::GetOriginalURI(nsIURI* *aOriginalURI) { - *aOriginalURI = mOriginalURI ? mOriginalURI : nsCOMPtr(mURI); + *aOriginalURI = mOriginalURI ? mOriginalURI : mURI.get(); NS_ADDREF(*aOriginalURI); return NS_OK; } @@ -327,15 +243,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,11 +260,17 @@ 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) - mon.Wait(); + mon.Wait(); + if (mSynchronousInputStream) { + *result = mSynchronousInputStream; // Result of GetInputStream called on transport thread + NS_ADDREF(*result); + mSynchronousInputStream = null_nsCOMPtr(); + } else { + rv = NS_ERROR_FAILURE; + } return rv; } @@ -360,14 +281,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 +308,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 +334,9 @@ nsJARChannel::EnsureJARFileAvailable(OnJARFileAvailableFun onJARFileAvailable, rv = mURI->GetJAREntry(&mJAREntry); if (NS_FAILED(rv)) goto error; -#ifdef NS_USE_CACHE_MANAGER_FOR_JAR - - 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; - } + rv = NS_NewDownloader(getter_AddRefs(mDownloader), + mJARBaseURI, this, nsnull, mLoadGroup, mCallbacks, + mLoadAttributes, mBufferSegmentSize, mBufferMaxSize); error: if (NS_FAILED(rv) && mLoadGroup) { @@ -548,57 +346,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 +353,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 +382,7 @@ nsJARChannel::AsyncReadJARElement() } NS_IMETHODIMP -nsJARChannel::AsyncWrite(nsIInputStream* fromStream, +nsJARChannel::AsyncWrite(nsIInputStream* fromStream, nsIStreamObserver* observer, nsISupports* ctxt) { @@ -897,6 +640,28 @@ nsJARChannel::GetSecurityInfo(nsISupports * *aSecurityInfo) return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// nsIDownloadObserver methods: + +NS_IMETHODIMP +nsJARChannel::OnDownloadComplete(nsIDownloader* aDownloader, nsISupports* aClosure, + nsresult aStatus, nsIFile* aFile) +{ + nsresult rv; + if(NS_SUCCEEDED(aStatus) && mDownloader) { + NS_ASSERTION(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 +724,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 +763,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..29bd300a5df 100644 --- a/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp +++ b/mozilla/netwerk/protocol/jar/src/nsJARURI.cpp @@ -170,72 +170,96 @@ nsJARURI::SetScheme(const char * aScheme) NS_IMETHODIMP nsJARURI::GetUsername(char * *aUsername) { + if (mJARFile) + return mJARFile->GetUsername(aUsername); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetUsername(const char * aUsername) { + if (mJARFile) + return mJARFile->SetUsername(aUsername); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPassword(char * *aPassword) { + if (mJARFile) + return mJARFile->GetPassword(aPassword); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPassword(const char * aPassword) { + if (mJARFile) + return mJARFile->SetPassword(aPassword); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPreHost(char * *aPreHost) { + if (mJARFile) + return mJARFile->GetPreHost(aPreHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPreHost(const char * aPreHost) { + if (mJARFile) + return mJARFile->SetPreHost(aPreHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetHost(char * *aHost) { + if (mJARFile) + return mJARFile->GetHost(aHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetHost(const char * aHost) { + if (mJARFile) + return mJARFile->SetHost(aHost); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPort(PRInt32 *aPort) { + if (mJARFile) + return mJARFile->GetPort(aPort); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPort(PRInt32 aPort) { + if (mJARFile) + return mJARFile->SetPort(aPort); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::GetPath(char * *aPath) { + if (mJARFile) + return mJARFile->GetPath(aPath); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsJARURI::SetPath(const char * aPath) { + if (mJARFile) + return mJARFile->SetPath(aPath); return NS_ERROR_FAILURE; }