mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
fixes bug 209560 "Secure JS doesn't work from https JARs" r=dougt sr=alecf
This commit is contained in:
parent
7b3142ec4c
commit
0692f0b9d0
@ -225,7 +225,12 @@ nsJAR::Open()
|
||||
NS_IMETHODIMP
|
||||
nsJAR::Close()
|
||||
{
|
||||
#ifdef STANDALONE
|
||||
// nsZipReadState::CloseArchive closes the file descriptor
|
||||
#else
|
||||
if (mFd)
|
||||
PR_Close(mFd);
|
||||
#endif
|
||||
mFd = nsnull;
|
||||
PRInt32 err = mZip.CloseArchive();
|
||||
return ziperr2nsresult(err);
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
static NS_DEFINE_CID(kScriptSecurityManagerCID, NS_SCRIPTSECURITYMANAGER_CID);
|
||||
static NS_DEFINE_CID(kInputStreamChannelCID, NS_INPUTSTREAMCHANNEL_CID);
|
||||
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -63,7 +64,12 @@ public:
|
||||
{
|
||||
NS_ASSERTION(mJarFile, "no jar file");
|
||||
}
|
||||
virtual ~nsJARInputThunk() {}
|
||||
|
||||
virtual ~nsJARInputThunk()
|
||||
{
|
||||
if (!mJarCache && mJarReader)
|
||||
mJarReader->Close();
|
||||
}
|
||||
|
||||
void GetJarReader(nsIZipReader **result)
|
||||
{
|
||||
@ -96,8 +102,18 @@ nsJARInputThunk::EnsureJarStream()
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = mJarCache->GetZip(mJarFile, getter_AddRefs(mJarReader));
|
||||
if (mJarCache)
|
||||
rv = mJarCache->GetZip(mJarFile, getter_AddRefs(mJarReader));
|
||||
else {
|
||||
// create an uncached jar reader
|
||||
mJarReader = do_CreateInstance(kZipReaderCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJarReader->Init(mJarFile);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJarReader->Open();
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJarReader->GetInputStream(mJarEntry.get(),
|
||||
@ -205,7 +221,7 @@ nsJARChannel::Init(nsIURI *uri)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJARChannel::CreateJarInput()
|
||||
nsJARChannel::CreateJarInput(nsIZipReaderCache *jarCache)
|
||||
{
|
||||
// important to pass a clone of the file since the nsIFile impl is not
|
||||
// necessarily MT-safe
|
||||
@ -213,7 +229,7 @@ nsJARChannel::CreateJarInput()
|
||||
nsresult rv = mJarFile->Clone(getter_AddRefs(clonedFile));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mJarInput = new nsJARInputThunk(clonedFile, mJarEntry, gJarHandler->JarCache());
|
||||
mJarInput = new nsJARInputThunk(clonedFile, mJarEntry, jarCache);
|
||||
if (!mJarInput)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(mJarInput);
|
||||
@ -242,7 +258,7 @@ nsJARChannel::EnsureJarInput(PRBool blocking)
|
||||
}
|
||||
|
||||
if (mJarFile) {
|
||||
rv = CreateJarInput();
|
||||
rv = CreateJarInput(gJarHandler->JarCache());
|
||||
}
|
||||
else if (blocking) {
|
||||
NS_NOTREACHED("need sync downloader");
|
||||
@ -250,9 +266,11 @@ nsJARChannel::EnsureJarInput(PRBool blocking)
|
||||
}
|
||||
else {
|
||||
// kick off an async download of the base URI...
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader),
|
||||
mJarBaseURI, this, nsnull, PR_FALSE,
|
||||
mLoadGroup, mCallbacks, mLoadFlags);
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader), this);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = NS_OpenURI(mDownloader, nsnull, mJarBaseURI, nsnull,
|
||||
mLoadGroup, mCallbacks,
|
||||
mLoadFlags & ~LOAD_DOCUMENT_URI);
|
||||
}
|
||||
return rv;
|
||||
|
||||
@ -606,14 +624,13 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
|
||||
nsISupports *closure,
|
||||
nsresult status,
|
||||
nsIFile *file)
|
||||
nsresult status,
|
||||
nsIFile *file)
|
||||
{
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
mJarFile = file;
|
||||
|
||||
nsresult rv = CreateJarInput();
|
||||
nsresult rv = CreateJarInput(nsnull);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// create input stream pump
|
||||
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
|
||||
@ -628,7 +645,6 @@ nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
|
||||
OnStopRequest(nsnull, nsnull, status);
|
||||
}
|
||||
|
||||
mDownloader = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -665,6 +681,7 @@ nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
|
||||
mPump = 0;
|
||||
NS_IF_RELEASE(mJarInput);
|
||||
mIsPending = PR_FALSE;
|
||||
mDownloader = 0; // this may delete the underlying jar file
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIZipReader.h"
|
||||
#include "nsIDownloader.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIFile.h"
|
||||
@ -75,7 +76,7 @@ public:
|
||||
nsresult Init(nsIURI *uri);
|
||||
|
||||
private:
|
||||
nsresult CreateJarInput();
|
||||
nsresult CreateJarInput(nsIZipReaderCache *);
|
||||
nsresult EnsureJarInput(PRBool blocking);
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
@ -98,8 +99,8 @@ private:
|
||||
PRBool mIsPending;
|
||||
|
||||
nsJARInputThunk *mJarInput;
|
||||
nsCOMPtr<nsIStreamListener> mDownloader;
|
||||
nsCOMPtr<nsIInputStreamPump> mPump;
|
||||
nsCOMPtr<nsIDownloader> mDownloader;
|
||||
nsCOMPtr<nsIFile> mJarFile;
|
||||
nsCOMPtr<nsIURI> mJarBaseURI;
|
||||
nsCString mJarEntry;
|
||||
|
@ -1,65 +1,82 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIRequest.idl"
|
||||
#include "nsIStreamListener.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsILoadGroup;
|
||||
interface nsIInterfaceRequestor;
|
||||
interface nsIFile;
|
||||
interface nsIDownloader;
|
||||
interface nsIDownloadObserver;
|
||||
|
||||
[scriptable, uuid(6e0fc962-4a6f-4fa6-831f-8c26c554407f)]
|
||||
/**
|
||||
* nsIDownloader
|
||||
*
|
||||
* A downloader is a special implementation of a nsIStreamListener that will
|
||||
* make the contents of the stream available as a file. This may utilize the
|
||||
* disk cache as an optimization to avoid an extra copy of the data on disk.
|
||||
* The resulting file is valid from the time the downloader completes until
|
||||
* the last reference to the downloader is released.
|
||||
*/
|
||||
[scriptable, uuid(fafe41a9-a531-4d6d-89bc-588a6522fb4e)]
|
||||
interface nsIDownloader : nsIStreamListener
|
||||
{
|
||||
/**
|
||||
* Initialize this downloader
|
||||
*
|
||||
* @param observer
|
||||
* the observer to be notified when the download completes.
|
||||
* @param downloadLocation
|
||||
* the location where the stream contents should be written.
|
||||
* if null, the downloader will select a location and the
|
||||
* resulting file will be deleted (or otherwise made invalid)
|
||||
* when the downloader object is destroyed. if an explicit
|
||||
* download location is specified then the resulting file will
|
||||
* not be deleted, and it will be the callers responsibility
|
||||
* to keep track of the file, etc.
|
||||
*/
|
||||
void init(in nsIDownloadObserver observer,
|
||||
in nsIFile downloadLocation);
|
||||
};
|
||||
|
||||
[scriptable, uuid(814bd098-4dfb-46dd-8305-9052c998ed94)]
|
||||
interface nsIDownloadObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called to signal a download that has completed.
|
||||
*/
|
||||
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 boolean synchronous,
|
||||
in nsILoadGroup loadGroup,
|
||||
in nsIInterfaceRequestor notificationCallbacks,
|
||||
in nsLoadFlags loadAttributes);
|
||||
in nsresult status,
|
||||
in nsIFile result);
|
||||
};
|
||||
|
@ -366,24 +366,17 @@ NS_NewLoadGroup(nsILoadGroup **result,
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
inline nsresult
|
||||
NS_NewDownloader(nsIDownloader **result,
|
||||
nsIURI *uri,
|
||||
nsIDownloadObserver *observer,
|
||||
nsISupports *context = nsnull,
|
||||
PRBool synchronous = PR_FALSE,
|
||||
nsILoadGroup *loadGroup = nsnull,
|
||||
nsIInterfaceRequestor *callbacks = nsnull,
|
||||
PRUint32 loadFlags = nsIRequest::LOAD_NORMAL)
|
||||
NS_NewDownloader(nsIStreamListener **result,
|
||||
nsIDownloadObserver *observer,
|
||||
nsIFile *downloadLocation = nsnull)
|
||||
{
|
||||
nsresult rv;
|
||||
static NS_DEFINE_CID(kDownloaderCID, NS_DOWNLOADER_CID);
|
||||
nsCOMPtr<nsIDownloader> downloader =
|
||||
do_CreateInstance(kDownloaderCID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = downloader->Init(uri, observer, context, synchronous, loadGroup,
|
||||
callbacks, loadFlags);
|
||||
rv = downloader->Init(observer, downloadLocation);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
NS_ADDREF(*result = downloader);
|
||||
}
|
||||
|
@ -1,147 +1,162 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDownloader.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsProxiedService.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileURL.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
|
||||
// XXX this code is ripped from profile/src/nsProfile.cpp and is further
|
||||
// duplicated in uriloader/exthandler. this should probably be moved
|
||||
// into xpcom or some other shared library.
|
||||
#include <stdlib.h>
|
||||
#define TABLE_SIZE 36
|
||||
static const char table[] =
|
||||
{ 'a','b','c','d','e','f','g','h','i','j',
|
||||
'k','l','m','n','o','p','q','r','s','t',
|
||||
'u','v','w','x','y','z','0','1','2','3',
|
||||
'4','5','6','7','8','9' };
|
||||
static void
|
||||
MakeRandomString(char *buf, PRInt32 bufLen)
|
||||
{
|
||||
// turn PR_Now() into milliseconds since epoch
|
||||
// and salt rand with that.
|
||||
double fpTime;
|
||||
LL_L2D(fpTime, PR_Now());
|
||||
srand((uint)(fpTime * 1e-6 + 0.5)); // use 1e-6, granularity of PR_Now() on the mac is seconds
|
||||
|
||||
// XXX this API seems all wrong for "sync" downloading
|
||||
PRInt32 i;
|
||||
for (i=0;i<bufLen;i++) {
|
||||
*buf++ = table[rand()%TABLE_SIZE];
|
||||
}
|
||||
*buf = 0;
|
||||
}
|
||||
// XXX
|
||||
|
||||
nsDownloader::~nsDownloader()
|
||||
{
|
||||
if (mLocation && mLocationIsTemp) {
|
||||
// release the sink first since it may still hold an open file
|
||||
// descriptor to mLocation. this needs to happen before the
|
||||
// file can be removed otherwise the Remove call will fail.
|
||||
mSink = 0;
|
||||
|
||||
nsresult rv = mLocation->Remove(PR_FALSE);
|
||||
if (NS_FAILED(rv))
|
||||
NS_ERROR("unable to remove temp file");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsDownloader,
|
||||
nsIDownloader,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownloader::Init(nsIURI* aURL,
|
||||
nsIDownloadObserver* aObserver,
|
||||
nsISupports* aContext,
|
||||
PRBool aIsSynchronous,
|
||||
nsILoadGroup* aGroup,
|
||||
nsIInterfaceRequestor* aCallbacks,
|
||||
nsLoadFlags aLoadFlags)
|
||||
nsDownloader::Init(nsIDownloadObserver *observer, nsIFile *location)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aObserver);
|
||||
nsresult rv;
|
||||
|
||||
mObserver = aObserver;
|
||||
mContext = aContext;
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
||||
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURL);
|
||||
if (fileURL)
|
||||
fileURL->GetFile(getter_AddRefs(file));
|
||||
|
||||
if (file) {
|
||||
if (aIsSynchronous)
|
||||
return mObserver->OnDownloadComplete(this, mContext, rv, file);
|
||||
|
||||
// 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
|
||||
nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
|
||||
do_GetService(kProxyObjectManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIDownloadObserver> pObserver;
|
||||
rv = pIProxyObjectManager->GetProxyForObject(NS_CURRENT_EVENTQ,
|
||||
NS_GET_IID(nsIDownloadObserver), mObserver,
|
||||
PROXY_ASYNC | PROXY_ALWAYS, getter_AddRefs(pObserver));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return pObserver->OnDownloadComplete(this, mContext, NS_OK, file);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel), aURL, nsnull,
|
||||
aGroup, aCallbacks, aLoadFlags);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return channel->AsyncOpen(this, aContext);
|
||||
mObserver = observer;
|
||||
mLocation = location;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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,
|
||||
nsIRequestObserver, nsIStreamListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownloader::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICachingChannel> caching = do_QueryInterface(request, &rv);
|
||||
if (caching)
|
||||
rv = caching->SetCacheAsFile(PR_TRUE);
|
||||
// Returning failure from here will cancel the load
|
||||
return rv;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (!mLocation) {
|
||||
nsCOMPtr<nsICachingChannel> caching = do_QueryInterface(request, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = caching->SetCacheAsFile(PR_TRUE);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
// OK, we will need to stream the data to disk ourselves. Make
|
||||
// sure mLocation exists.
|
||||
if (!mLocation) {
|
||||
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mLocation));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char buf[13];
|
||||
MakeRandomString(buf, 8);
|
||||
memcpy(buf+8, ".tmp", 5);
|
||||
rv = mLocation->AppendNative(nsDependentCString(buf, 12));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mLocation->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mLocationIsTemp = PR_TRUE;
|
||||
}
|
||||
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(mSink), mLocation);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// we could wrap this output stream with a buffered output stream,
|
||||
// but it shouldn't be necessary since we will be writing large
|
||||
// chunks given to us via OnDataAvailable.
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownloader::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
|
||||
nsresult aStatus)
|
||||
nsDownloader::OnStopRequest(nsIRequest *request,
|
||||
nsISupports *ctxt,
|
||||
nsresult status)
|
||||
{
|
||||
nsCOMPtr<nsIFile> file;
|
||||
if (NS_SUCCEEDED(aStatus))
|
||||
{
|
||||
nsCOMPtr<nsICachingChannel> caching = do_QueryInterface(request, &aStatus);
|
||||
if (caching)
|
||||
aStatus = caching->GetCacheFile(getter_AddRefs(file));
|
||||
}
|
||||
if (!mSink && NS_SUCCEEDED(status)) {
|
||||
nsCOMPtr<nsICachingChannel> caching = do_QueryInterface(request, &status);
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
status = caching->GetCacheFile(getter_AddRefs(mLocation));
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
NS_ASSERTION(mLocation, "success without a cache file");
|
||||
// ok, then we need to hold a reference to the cache token in
|
||||
// order to ensure that the cache file remains valid until we
|
||||
// get destroyed.
|
||||
caching->GetCacheToken(getter_AddRefs(mCacheToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mObserver->OnDownloadComplete(this, mContext, aStatus, file);
|
||||
mObserver->OnDownloadComplete(this, status, mLocation);
|
||||
mObserver = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
@ -152,17 +167,19 @@ nsDownloader::ConsumeData(nsIInputStream* in,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount)
|
||||
{
|
||||
*writeCount = count;
|
||||
return NS_OK;
|
||||
nsDownloader *self = (nsDownloader *) closure;
|
||||
if (self->mSink)
|
||||
return self->mSink->Write(fromRawSegment, count, writeCount);
|
||||
|
||||
*writeCount = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDownloader::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
|
||||
nsIInputStream *inStr,
|
||||
PRUint32 sourceOffset, PRUint32 count)
|
||||
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.
|
||||
PRUint32 lenRead;
|
||||
return inStr->ReadSegments(nsDownloader::ConsumeData, nsnull, count, &lenRead);
|
||||
PRUint32 n;
|
||||
return inStr->ReadSegments(ConsumeData, this, count, &n);
|
||||
}
|
||||
|
@ -1,37 +1,37 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
@ -39,36 +39,35 @@
|
||||
#define nsDownloader_h__
|
||||
|
||||
#include "nsIDownloader.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsDownloader : public nsIDownloader,
|
||||
public nsIStreamListener
|
||||
|
||||
class nsDownloader : public nsIDownloader
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOWNLOADER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOWNLOADER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
nsDownloader() { } ;
|
||||
virtual ~nsDownloader() {};
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
nsDownloader() : mLocationIsTemp(PR_FALSE) {}
|
||||
|
||||
protected:
|
||||
static NS_METHOD ConsumeData(nsIInputStream* in,
|
||||
void* closure,
|
||||
const char* fromRawSegment,
|
||||
PRUint32 toOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount);
|
||||
virtual ~nsDownloader();
|
||||
|
||||
nsCOMPtr<nsIDownloadObserver> mObserver;
|
||||
nsCOMPtr<nsISupports> mContext; // the observer's context
|
||||
static NS_METHOD ConsumeData(nsIInputStream *in,
|
||||
void *closure,
|
||||
const char *fromRawSegment,
|
||||
PRUint32 toOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount);
|
||||
|
||||
nsCOMPtr<nsIDownloadObserver> mObserver;
|
||||
nsCOMPtr<nsIFile> mLocation;
|
||||
nsCOMPtr<nsIOutputStream> mSink;
|
||||
nsCOMPtr<nsISupports> mCacheToken;
|
||||
PRBool mLocationIsTemp;
|
||||
};
|
||||
|
||||
#endif // nsDownloader_h__
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include "nsLoadGroup.h"
|
||||
#include "nsStreamLoader.h"
|
||||
#include "nsUnicharStreamLoader.h"
|
||||
#include "nsDownloader.h"
|
||||
#include "nsAsyncStreamListener.h"
|
||||
#include "nsFileStreams.h"
|
||||
#include "nsBufferedStreams.h"
|
||||
@ -95,6 +94,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsInputStreamPump)
|
||||
#include "nsInputStreamChannel.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsInputStreamChannel)
|
||||
|
||||
#include "nsDownloader.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloader)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "nsStreamConverterService.h"
|
||||
@ -606,7 +608,7 @@ static const nsModuleComponentInfo gNetModuleInfo[] = {
|
||||
{ NS_DOWNLOADER_CLASSNAME,
|
||||
NS_DOWNLOADER_CID,
|
||||
NS_DOWNLOADER_CONTRACTID,
|
||||
nsDownloader::Create },
|
||||
nsDownloaderConstructor },
|
||||
{ NS_REQUESTOBSERVERPROXY_CLASSNAME,
|
||||
NS_REQUESTOBSERVERPROXY_CID,
|
||||
NS_REQUESTOBSERVERPROXY_CONTRACTID,
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
static NS_DEFINE_CID(kScriptSecurityManagerCID, NS_SCRIPTSECURITYMANAGER_CID);
|
||||
static NS_DEFINE_CID(kInputStreamChannelCID, NS_INPUTSTREAMCHANNEL_CID);
|
||||
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -63,7 +64,12 @@ public:
|
||||
{
|
||||
NS_ASSERTION(mJarFile, "no jar file");
|
||||
}
|
||||
virtual ~nsJARInputThunk() {}
|
||||
|
||||
virtual ~nsJARInputThunk()
|
||||
{
|
||||
if (!mJarCache && mJarReader)
|
||||
mJarReader->Close();
|
||||
}
|
||||
|
||||
void GetJarReader(nsIZipReader **result)
|
||||
{
|
||||
@ -96,8 +102,18 @@ nsJARInputThunk::EnsureJarStream()
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = mJarCache->GetZip(mJarFile, getter_AddRefs(mJarReader));
|
||||
if (mJarCache)
|
||||
rv = mJarCache->GetZip(mJarFile, getter_AddRefs(mJarReader));
|
||||
else {
|
||||
// create an uncached jar reader
|
||||
mJarReader = do_CreateInstance(kZipReaderCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJarReader->Init(mJarFile);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJarReader->Open();
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mJarReader->GetInputStream(mJarEntry.get(),
|
||||
@ -205,7 +221,7 @@ nsJARChannel::Init(nsIURI *uri)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJARChannel::CreateJarInput()
|
||||
nsJARChannel::CreateJarInput(nsIZipReaderCache *jarCache)
|
||||
{
|
||||
// important to pass a clone of the file since the nsIFile impl is not
|
||||
// necessarily MT-safe
|
||||
@ -213,7 +229,7 @@ nsJARChannel::CreateJarInput()
|
||||
nsresult rv = mJarFile->Clone(getter_AddRefs(clonedFile));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mJarInput = new nsJARInputThunk(clonedFile, mJarEntry, gJarHandler->JarCache());
|
||||
mJarInput = new nsJARInputThunk(clonedFile, mJarEntry, jarCache);
|
||||
if (!mJarInput)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(mJarInput);
|
||||
@ -242,7 +258,7 @@ nsJARChannel::EnsureJarInput(PRBool blocking)
|
||||
}
|
||||
|
||||
if (mJarFile) {
|
||||
rv = CreateJarInput();
|
||||
rv = CreateJarInput(gJarHandler->JarCache());
|
||||
}
|
||||
else if (blocking) {
|
||||
NS_NOTREACHED("need sync downloader");
|
||||
@ -250,9 +266,11 @@ nsJARChannel::EnsureJarInput(PRBool blocking)
|
||||
}
|
||||
else {
|
||||
// kick off an async download of the base URI...
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader),
|
||||
mJarBaseURI, this, nsnull, PR_FALSE,
|
||||
mLoadGroup, mCallbacks, mLoadFlags);
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader), this);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = NS_OpenURI(mDownloader, nsnull, mJarBaseURI, nsnull,
|
||||
mLoadGroup, mCallbacks,
|
||||
mLoadFlags & ~LOAD_DOCUMENT_URI);
|
||||
}
|
||||
return rv;
|
||||
|
||||
@ -606,14 +624,13 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
|
||||
nsISupports *closure,
|
||||
nsresult status,
|
||||
nsIFile *file)
|
||||
nsresult status,
|
||||
nsIFile *file)
|
||||
{
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
mJarFile = file;
|
||||
|
||||
nsresult rv = CreateJarInput();
|
||||
nsresult rv = CreateJarInput(nsnull);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// create input stream pump
|
||||
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
|
||||
@ -628,7 +645,6 @@ nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
|
||||
OnStopRequest(nsnull, nsnull, status);
|
||||
}
|
||||
|
||||
mDownloader = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -665,6 +681,7 @@ nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
|
||||
mPump = 0;
|
||||
NS_IF_RELEASE(mJarInput);
|
||||
mIsPending = PR_FALSE;
|
||||
mDownloader = 0; // this may delete the underlying jar file
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIZipReader.h"
|
||||
#include "nsIDownloader.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIFile.h"
|
||||
@ -75,7 +76,7 @@ public:
|
||||
nsresult Init(nsIURI *uri);
|
||||
|
||||
private:
|
||||
nsresult CreateJarInput();
|
||||
nsresult CreateJarInput(nsIZipReaderCache *);
|
||||
nsresult EnsureJarInput(PRBool blocking);
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
@ -98,8 +99,8 @@ private:
|
||||
PRBool mIsPending;
|
||||
|
||||
nsJARInputThunk *mJarInput;
|
||||
nsCOMPtr<nsIStreamListener> mDownloader;
|
||||
nsCOMPtr<nsIInputStreamPump> mPump;
|
||||
nsCOMPtr<nsIDownloader> mDownloader;
|
||||
nsCOMPtr<nsIFile> mJarFile;
|
||||
nsCOMPtr<nsIURI> mJarBaseURI;
|
||||
nsCString mJarEntry;
|
||||
|
Loading…
Reference in New Issue
Block a user