2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
*
|
2012-05-21 04:12:37 -07:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "nsJAR.h"
|
|
|
|
#include "nsJARChannel.h"
|
|
|
|
#include "nsJARProtocolHandler.h"
|
|
|
|
#include "nsMimeTypes.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsEscape.h"
|
2007-11-26 21:32:23 -08:00
|
|
|
#include "nsIPrefService.h"
|
|
|
|
#include "nsIPrefBranch.h"
|
2009-03-10 14:58:00 -07:00
|
|
|
#include "nsIViewSourceChannel.h"
|
2009-02-19 12:25:18 -08:00
|
|
|
#include "nsChannelProperties.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
#include "nsIPrincipal.h"
|
|
|
|
#include "nsIFileURL.h"
|
|
|
|
|
2011-06-11 19:30:15 -07:00
|
|
|
#include "mozilla/Preferences.h"
|
|
|
|
|
|
|
|
using namespace mozilla;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
|
|
|
|
|
|
|
|
// the entry for a directory will either be empty (in the case of the
|
|
|
|
// top-level directory) or will end with a slash
|
|
|
|
#define ENTRY_IS_DIRECTORY(_entry) \
|
|
|
|
((_entry).IsEmpty() || '/' == (_entry).Last())
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#if defined(PR_LOGGING)
|
|
|
|
//
|
|
|
|
// set NSPR_LOG_MODULES=nsJarProtocol:5
|
|
|
|
//
|
2012-07-30 07:20:58 -07:00
|
|
|
static PRLogModuleInfo *gJarProtocolLog = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define LOG(args) PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, args)
|
|
|
|
#define LOG_ENABLED() PR_LOG_TEST(gJarProtocolLog, 4)
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsJARInputThunk
|
|
|
|
//
|
|
|
|
// this class allows us to do some extra work on the stream transport thread.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class nsJARInputThunk : public nsIInputStream
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIINPUTSTREAM
|
|
|
|
|
2010-09-08 20:38:34 -07:00
|
|
|
nsJARInputThunk(nsIZipReader *zipReader,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIURI* fullJarURI,
|
|
|
|
const nsACString &jarEntry,
|
|
|
|
nsIZipReaderCache *jarCache)
|
|
|
|
: mJarCache(jarCache)
|
2010-09-08 20:38:34 -07:00
|
|
|
, mJarReader(zipReader)
|
2007-03-22 10:30:00 -07:00
|
|
|
, mJarEntry(jarEntry)
|
|
|
|
, mContentLength(-1)
|
|
|
|
{
|
2009-03-01 17:06:55 -08:00
|
|
|
if (fullJarURI) {
|
2010-07-11 05:49:52 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
nsresult rv =
|
|
|
|
#endif
|
|
|
|
fullJarURI->GetAsciiSpec(mJarDirSpec);
|
2009-03-01 17:06:55 -08:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "this shouldn't fail");
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~nsJARInputThunk()
|
|
|
|
{
|
|
|
|
if (!mJarCache && mJarReader)
|
|
|
|
mJarReader->Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetJarReader(nsIZipReader **result)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*result = mJarReader);
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t GetContentLength()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
return mContentLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult EnsureJarStream();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
nsCOMPtr<nsIZipReaderCache> mJarCache;
|
|
|
|
nsCOMPtr<nsIZipReader> mJarReader;
|
2009-03-01 17:06:55 -08:00
|
|
|
nsCString mJarDirSpec;
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIInputStream> mJarStream;
|
|
|
|
nsCString mJarEntry;
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t mContentLength;
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputThunk, nsIInputStream)
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsJARInputThunk::EnsureJarStream()
|
|
|
|
{
|
|
|
|
if (mJarStream)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
if (ENTRY_IS_DIRECTORY(mJarEntry)) {
|
|
|
|
// A directory stream also needs the Spec of the FullJarURI
|
|
|
|
// because is included in the stream data itself.
|
|
|
|
|
2009-03-01 17:06:55 -08:00
|
|
|
NS_ENSURE_STATE(!mJarDirSpec.IsEmpty());
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-03-01 17:06:55 -08:00
|
|
|
rv = mJarReader->GetInputStreamWithSpec(mJarDirSpec,
|
2011-09-28 16:14:45 -07:00
|
|
|
mJarEntry,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(mJarStream));
|
|
|
|
}
|
|
|
|
else {
|
2011-09-28 16:14:45 -07:00
|
|
|
rv = mJarReader->GetInputStream(mJarEntry,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(mJarStream));
|
|
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
// convert to the proper result if the entry wasn't found
|
|
|
|
// so that error pages work
|
|
|
|
if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
|
|
|
|
rv = NS_ERROR_FILE_NOT_FOUND;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ask the JarStream for the content length
|
2012-08-22 08:56:38 -07:00
|
|
|
uint64_t avail;
|
|
|
|
rv = mJarStream->Available((uint64_t *) &avail);
|
2009-10-04 10:20:45 -07:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
mContentLength = avail < PR_INT32_MAX ? (int32_t) avail : -1;
|
2012-08-10 19:44:11 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARInputThunk::Close()
|
|
|
|
{
|
|
|
|
if (mJarStream)
|
|
|
|
return mJarStream->Close();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsJARInputThunk::Available(uint64_t *avail)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsresult rv = EnsureJarStream();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return mJarStream->Available(avail);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsJARInputThunk::Read(char *buf, uint32_t count, uint32_t *countRead)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsresult rv = EnsureJarStream();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return mJarStream->Read(buf, count, countRead);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARInputThunk::ReadSegments(nsWriteSegmentFun writer, void *closure,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t count, uint32_t *countRead)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// stream transport does only calls Read()
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsJARInputThunk::IsNonBlocking(bool *nonBlocking)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-10-17 07:59:28 -07:00
|
|
|
*nonBlocking = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2009-02-19 12:25:18 -08:00
|
|
|
// nsJARChannel
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsJARChannel::nsJARChannel()
|
2012-08-27 16:34:30 -07:00
|
|
|
: mOpened(false)
|
|
|
|
, mAppURI(nullptr)
|
2012-07-11 08:38:36 -07:00
|
|
|
, mContentLength(-1)
|
2007-03-22 10:30:00 -07:00
|
|
|
, mLoadFlags(LOAD_NORMAL)
|
|
|
|
, mStatus(NS_OK)
|
2011-10-17 07:59:28 -07:00
|
|
|
, mIsPending(false)
|
|
|
|
, mIsUnsafe(true)
|
2012-07-30 07:20:58 -07:00
|
|
|
, mJarInput(nullptr)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
#if defined(PR_LOGGING)
|
|
|
|
if (!gJarProtocolLog)
|
|
|
|
gJarProtocolLog = PR_NewLogModule("nsJarProtocol");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// hold an owning reference to the jar handler
|
|
|
|
NS_ADDREF(gJarHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsJARChannel::~nsJARChannel()
|
|
|
|
{
|
|
|
|
// with the exception of certain error cases mJarInput will already be null.
|
|
|
|
NS_IF_RELEASE(mJarInput);
|
|
|
|
|
|
|
|
// release owning reference to the jar handler
|
|
|
|
nsJARProtocolHandler *handler = gJarHandler;
|
|
|
|
NS_RELEASE(handler); // NULL parameter
|
|
|
|
}
|
|
|
|
|
2009-02-19 12:25:18 -08:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED6(nsJARChannel,
|
|
|
|
nsHashPropertyBag,
|
|
|
|
nsIRequest,
|
|
|
|
nsIChannel,
|
|
|
|
nsIStreamListener,
|
|
|
|
nsIRequestObserver,
|
|
|
|
nsIDownloadObserver,
|
|
|
|
nsIJARChannel)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsJARChannel::Init(nsIURI *uri)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2009-02-19 12:25:18 -08:00
|
|
|
rv = nsHashPropertyBag::Init();
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
mJarURI = do_QueryInterface(uri, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2008-10-15 13:05:23 -07:00
|
|
|
mOriginalURI = mJarURI;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Prevent loading jar:javascript URIs (see bug 290982).
|
|
|
|
nsCOMPtr<nsIURI> innerURI;
|
|
|
|
rv = mJarURI->GetJARFile(getter_AddRefs(innerURI));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool isJS;
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = innerURI->SchemeIs("javascript", &isJS);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
if (isJS) {
|
|
|
|
NS_WARNING("blocking jar:javascript:");
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(PR_LOGGING)
|
|
|
|
mJarURI->GetSpec(mSpec);
|
|
|
|
#endif
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsJARChannel::CreateJarInput(nsIZipReaderCache *jarCache)
|
|
|
|
{
|
|
|
|
// important to pass a clone of the file since the nsIFile impl is not
|
|
|
|
// necessarily MT-safe
|
|
|
|
nsCOMPtr<nsIFile> clonedFile;
|
|
|
|
nsresult rv = mJarFile->Clone(getter_AddRefs(clonedFile));
|
2010-09-08 20:38:34 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-09-08 20:38:34 -07:00
|
|
|
nsCOMPtr<nsIZipReader> reader;
|
|
|
|
if (jarCache) {
|
|
|
|
if (mInnerJarEntry.IsEmpty())
|
|
|
|
rv = jarCache->GetZip(mJarFile, getter_AddRefs(reader));
|
|
|
|
else
|
2011-09-28 16:14:45 -07:00
|
|
|
rv = jarCache->GetInnerZip(mJarFile, mInnerJarEntry,
|
2010-09-08 20:38:34 -07:00
|
|
|
getter_AddRefs(reader));
|
|
|
|
} else {
|
|
|
|
// create an uncached jar reader
|
|
|
|
nsCOMPtr<nsIZipReader> outerReader = do_CreateInstance(kZipReaderCID, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
rv = outerReader->Open(mJarFile);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (mInnerJarEntry.IsEmpty())
|
|
|
|
reader = outerReader;
|
|
|
|
else {
|
|
|
|
reader = do_CreateInstance(kZipReaderCID, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2011-09-28 16:14:45 -07:00
|
|
|
rv = reader->OpenInner(outerReader, mInnerJarEntry);
|
2010-09-08 20:38:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
mJarInput = new nsJARInputThunk(reader, mJarURI, mJarEntry, jarCache);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mJarInput)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(mJarInput);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2011-09-28 23:19:26 -07:00
|
|
|
nsJARChannel::EnsureJarInput(bool blocking)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
LOG(("nsJARChannel::EnsureJarInput [this=%x %s]\n", this, mSpec.get()));
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
|
|
|
|
rv = mJarURI->GetJARFile(getter_AddRefs(mJarBaseURI));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = mJarURI->GetJAREntry(mJarEntry);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
// The name of the JAR entry must not contain URL-escaped characters:
|
|
|
|
// we're moving from URL domain to a filename domain here. nsStandardURL
|
|
|
|
// does basic escaping by default, which breaks reading zipped files which
|
|
|
|
// have e.g. spaces in their filenames.
|
|
|
|
NS_UnescapeURL(mJarEntry);
|
|
|
|
|
|
|
|
// try to get a nsIFile directly from the url, which will often succeed.
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mJarBaseURI);
|
|
|
|
if (fileURL)
|
|
|
|
fileURL->GetFile(getter_AddRefs(mJarFile));
|
|
|
|
}
|
2010-09-08 20:38:34 -07:00
|
|
|
// try to handle a nested jar
|
|
|
|
if (!mJarFile) {
|
|
|
|
nsCOMPtr<nsIJARURI> jarURI = do_QueryInterface(mJarBaseURI);
|
|
|
|
if (jarURI) {
|
|
|
|
nsCOMPtr<nsIFileURL> fileURL;
|
|
|
|
nsCOMPtr<nsIURI> innerJarURI;
|
|
|
|
rv = jarURI->GetJARFile(getter_AddRefs(innerJarURI));
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
fileURL = do_QueryInterface(innerJarURI);
|
|
|
|
if (fileURL) {
|
|
|
|
fileURL->GetFile(getter_AddRefs(mJarFile));
|
|
|
|
jarURI->GetJAREntry(mInnerJarEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (mJarFile) {
|
2011-10-17 07:59:28 -07:00
|
|
|
mIsUnsafe = false;
|
2007-11-26 21:32:23 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// NOTE: we do not need to deal with mSecurityInfo here,
|
|
|
|
// because we're loading from a local file
|
|
|
|
rv = CreateJarInput(gJarHandler->JarCache());
|
|
|
|
}
|
|
|
|
else if (blocking) {
|
|
|
|
NS_NOTREACHED("need sync downloader");
|
|
|
|
rv = NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// kick off an async download of the base URI...
|
|
|
|
rv = NS_NewDownloader(getter_AddRefs(mDownloader), this);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
2012-07-30 07:20:58 -07:00
|
|
|
rv = NS_OpenURI(mDownloader, nullptr, mJarBaseURI, nullptr,
|
2007-03-22 10:30:00 -07:00
|
|
|
mLoadGroup, mCallbacks,
|
2007-11-26 21:32:23 -08:00
|
|
|
mLoadFlags & ~(LOAD_DOCUMENT_URI | LOAD_CALL_CONTENT_SNIFFERS));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsIRequest
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetName(nsACString &result)
|
|
|
|
{
|
|
|
|
return mJarURI->GetSpec(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsJARChannel::IsPending(bool *result)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
*result = mIsPending;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetStatus(nsresult *status)
|
|
|
|
{
|
|
|
|
if (mPump && NS_SUCCEEDED(mStatus))
|
|
|
|
mPump->GetStatus(status);
|
|
|
|
else
|
|
|
|
*status = mStatus;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::Cancel(nsresult status)
|
|
|
|
{
|
|
|
|
mStatus = status;
|
|
|
|
if (mPump)
|
|
|
|
return mPump->Cancel(status);
|
|
|
|
|
|
|
|
NS_ASSERTION(!mIsPending, "need to implement cancel when downloading");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::Suspend()
|
|
|
|
{
|
|
|
|
if (mPump)
|
|
|
|
return mPump->Suspend();
|
|
|
|
|
|
|
|
NS_ASSERTION(!mIsPending, "need to implement suspend when downloading");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::Resume()
|
|
|
|
{
|
|
|
|
if (mPump)
|
|
|
|
return mPump->Resume();
|
|
|
|
|
|
|
|
NS_ASSERTION(!mIsPending, "need to implement resume when downloading");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
|
|
|
|
{
|
|
|
|
*aLoadFlags = mLoadFlags;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
|
|
|
|
{
|
|
|
|
mLoadFlags = aLoadFlags;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
|
|
|
|
{
|
|
|
|
mLoadGroup = aLoadGroup;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsIChannel
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetOriginalURI(nsIURI **aURI)
|
|
|
|
{
|
2008-10-15 13:05:23 -07:00
|
|
|
*aURI = mOriginalURI;
|
|
|
|
NS_ADDREF(*aURI);
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetOriginalURI(nsIURI *aURI)
|
|
|
|
{
|
2008-10-15 13:05:23 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aURI);
|
2007-03-22 10:30:00 -07:00
|
|
|
mOriginalURI = aURI;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetURI(nsIURI **aURI)
|
|
|
|
{
|
2012-07-11 08:38:36 -07:00
|
|
|
if (mAppURI) {
|
|
|
|
NS_IF_ADDREF(*aURI = mAppURI);
|
|
|
|
} else {
|
|
|
|
NS_IF_ADDREF(*aURI = mJarURI);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetOwner(nsISupports **result)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (mOwner) {
|
|
|
|
NS_ADDREF(*result = mOwner);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mJarInput) {
|
2012-07-30 07:20:58 -07:00
|
|
|
*result = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- Verify signature, if one is present, and set owner accordingly
|
|
|
|
nsCOMPtr<nsIZipReader> jarReader;
|
|
|
|
mJarInput->GetJarReader(getter_AddRefs(jarReader));
|
|
|
|
if (!jarReader)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrincipal> cert;
|
2011-09-28 16:14:45 -07:00
|
|
|
rv = jarReader->GetCertificatePrincipal(mJarEntry, getter_AddRefs(cert));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
if (cert) {
|
|
|
|
nsCAutoString certFingerprint;
|
|
|
|
rv = cert->GetFingerprint(certFingerprint);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCAutoString subjectName;
|
|
|
|
rv = cert->GetSubjectName(subjectName);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCAutoString prettyName;
|
|
|
|
rv = cert->GetPrettyName(prettyName);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> certificate;
|
|
|
|
rv = cert->GetCertificate(getter_AddRefs(certificate));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
|
|
|
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = secMan->GetCertificatePrincipal(certFingerprint, subjectName,
|
|
|
|
prettyName, certificate,
|
|
|
|
mJarBaseURI,
|
|
|
|
getter_AddRefs(cert));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
mOwner = do_QueryInterface(cert, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
NS_ADDREF(*result = mOwner);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetOwner(nsISupports *aOwner)
|
|
|
|
{
|
|
|
|
mOwner = aOwner;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aCallbacks = mCallbacks);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
|
|
|
|
{
|
|
|
|
mCallbacks = aCallbacks;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetSecurityInfo(nsISupports **aSecurityInfo)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aSecurityInfo, "Null out param");
|
|
|
|
NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetContentType(nsACString &result)
|
|
|
|
{
|
2012-08-27 16:34:30 -07:00
|
|
|
// If the Jar file has not been open yet,
|
|
|
|
// We return application/x-unknown-content-type
|
|
|
|
if (!mOpened) {
|
|
|
|
result.Assign(UNKNOWN_CONTENT_TYPE);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mContentType.IsEmpty()) {
|
2012-08-27 16:34:30 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//
|
|
|
|
// generate content type and set it
|
|
|
|
//
|
2012-07-30 07:20:58 -07:00
|
|
|
const char *ext = nullptr, *fileName = mJarEntry.get();
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t len = mJarEntry.Length();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// check if we're displaying a directory
|
|
|
|
// mJarEntry will be empty if we're trying to display
|
|
|
|
// the topmost directory in a zip, e.g. jar:foo.zip!/
|
|
|
|
if (ENTRY_IS_DIRECTORY(mJarEntry)) {
|
|
|
|
mContentType.AssignLiteral(APPLICATION_HTTP_INDEX_FORMAT);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// not a directory, take a guess by its extension
|
2012-08-22 08:56:38 -07:00
|
|
|
for (int32_t i = len-1; i >= 0; i--) {
|
2007-03-22 10:30:00 -07:00
|
|
|
if (fileName[i] == '.') {
|
|
|
|
ext = &fileName[i + 1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ext) {
|
|
|
|
nsIMIMEService *mimeServ = gJarHandler->MimeService();
|
|
|
|
if (mimeServ)
|
|
|
|
mimeServ->GetTypeFromExtension(nsDependentCString(ext), mContentType);
|
|
|
|
}
|
|
|
|
if (mContentType.IsEmpty())
|
|
|
|
mContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result = mContentType;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetContentType(const nsACString &aContentType)
|
|
|
|
{
|
|
|
|
// If someone gives us a type hint we should just use that type instead of
|
|
|
|
// doing our guessing. So we don't care when this is being called.
|
|
|
|
|
|
|
|
// mContentCharset is unchanged if not parsed
|
|
|
|
NS_ParseContentType(aContentType, mContentType, mContentCharset);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetContentCharset(nsACString &aContentCharset)
|
|
|
|
{
|
|
|
|
// If someone gives us a charset hint we should just use that charset.
|
|
|
|
// So we don't care when this is being called.
|
|
|
|
aContentCharset = mContentCharset;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetContentCharset(const nsACString &aContentCharset)
|
|
|
|
{
|
|
|
|
mContentCharset = aContentCharset;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-09 15:41:04 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsJARChannel::GetContentDisposition(uint32_t *aContentDisposition)
|
2011-09-09 15:41:04 -07:00
|
|
|
{
|
|
|
|
if (mContentDispositionHeader.IsEmpty())
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
|
|
*aContentDisposition = mContentDisposition;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
|
|
|
|
{
|
|
|
|
if (mContentDispositionHeader.IsEmpty())
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
|
|
aContentDispositionHeader = mContentDispositionHeader;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsJARChannel::GetContentLength(int32_t *result)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// if content length is unknown, query mJarInput...
|
|
|
|
if (mContentLength < 0 && mJarInput)
|
|
|
|
mContentLength = mJarInput->GetContentLength();
|
|
|
|
|
|
|
|
*result = mContentLength;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsJARChannel::SetContentLength(int32_t aContentLength)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// XXX does this really make any sense at all?
|
|
|
|
mContentLength = aContentLength;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::Open(nsIInputStream **stream)
|
|
|
|
{
|
|
|
|
LOG(("nsJARChannel::Open [this=%x]\n", this));
|
|
|
|
|
|
|
|
NS_ENSURE_TRUE(!mJarInput, NS_ERROR_IN_PROGRESS);
|
|
|
|
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
mJarFile = nullptr;
|
2011-10-17 07:59:28 -07:00
|
|
|
mIsUnsafe = true;
|
2007-11-26 21:32:23 -08:00
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
nsresult rv = EnsureJarInput(true);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
if (!mJarInput)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
// force load the jar file now so GetContentLength will return a
|
|
|
|
// meaningful value once we return.
|
2009-08-26 09:38:25 -07:00
|
|
|
rv = mJarInput->EnsureJarStream();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_ADDREF(*stream = mJarInput);
|
2012-08-27 16:34:30 -07:00
|
|
|
|
|
|
|
mOpened = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
|
|
|
|
{
|
|
|
|
LOG(("nsJARChannel::AsyncOpen [this=%x]\n", this));
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(listener);
|
|
|
|
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
mJarFile = nullptr;
|
2011-10-17 07:59:28 -07:00
|
|
|
mIsUnsafe = true;
|
2007-11-26 21:32:23 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Initialize mProgressSink
|
|
|
|
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
nsresult rv = EnsureJarInput(false);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2009-03-05 04:27:48 -08:00
|
|
|
// These variables must only be set if we're going to trigger an
|
|
|
|
// OnStartRequest, either from AsyncRead or OnDownloadComplete.
|
|
|
|
mListener = listener;
|
|
|
|
mListenerContext = ctx;
|
2011-10-17 07:59:28 -07:00
|
|
|
mIsPending = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mJarInput) {
|
2009-03-05 04:27:48 -08:00
|
|
|
// create input stream pump and call AsyncRead as a block
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
|
2009-03-05 04:27:48 -08:00
|
|
|
if (NS_SUCCEEDED(rv))
|
2012-07-30 07:20:58 -07:00
|
|
|
rv = mPump->AsyncRead(this, nullptr);
|
2009-03-05 04:27:48 -08:00
|
|
|
|
|
|
|
// If we failed to create the pump or initiate the AsyncRead,
|
|
|
|
// then we need to clear these variables.
|
|
|
|
if (NS_FAILED(rv)) {
|
2011-10-17 07:59:28 -07:00
|
|
|
mIsPending = false;
|
2012-07-30 07:20:58 -07:00
|
|
|
mListenerContext = nullptr;
|
|
|
|
mListener = nullptr;
|
2009-03-05 04:27:48 -08:00
|
|
|
return rv;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mLoadGroup)
|
2012-07-30 07:20:58 -07:00
|
|
|
mLoadGroup->AddRequest(this, nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-08-27 16:34:30 -07:00
|
|
|
mOpened = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-11-26 21:32:23 -08:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsIJARChannel
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsJARChannel::GetIsUnsafe(bool *isUnsafe)
|
2007-11-26 21:32:23 -08:00
|
|
|
{
|
|
|
|
*isUnsafe = mIsUnsafe;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-11 08:38:36 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::SetAppURI(nsIURI *aURI) {
|
|
|
|
NS_ENSURE_ARG_POINTER(aURI);
|
|
|
|
|
|
|
|
nsCAutoString scheme;
|
|
|
|
aURI->GetScheme(scheme);
|
|
|
|
if (!scheme.EqualsLiteral("app")) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
mAppURI = aURI;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsIDownloadObserver
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
|
|
|
|
nsIRequest *request,
|
|
|
|
nsISupports *context,
|
|
|
|
nsresult status,
|
|
|
|
nsIFile *file)
|
|
|
|
{
|
2007-11-26 20:35:00 -08:00
|
|
|
nsresult rv;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
|
2007-11-26 20:35:00 -08:00
|
|
|
if (channel) {
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t loadFlags;
|
2007-11-26 20:35:00 -08:00
|
|
|
channel->GetLoadFlags(&loadFlags);
|
|
|
|
if (loadFlags & LOAD_REPLACE) {
|
|
|
|
mLoadFlags |= LOAD_REPLACE;
|
|
|
|
|
|
|
|
if (!mOriginalURI) {
|
|
|
|
SetOriginalURI(mJarURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> innerURI;
|
|
|
|
rv = channel->GetURI(getter_AddRefs(innerURI));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsCOMPtr<nsIJARURI> newURI;
|
|
|
|
rv = mJarURI->CloneWithJARFile(innerURI,
|
|
|
|
getter_AddRefs(newURI));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
mJarURI = newURI;
|
|
|
|
}
|
|
|
|
}
|
2007-12-13 14:34:13 -08:00
|
|
|
if (NS_SUCCEEDED(status)) {
|
|
|
|
status = rv;
|
|
|
|
}
|
2007-11-26 20:35:00 -08:00
|
|
|
}
|
2007-12-13 14:34:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(status) && channel) {
|
|
|
|
// Grab the security info from our base channel
|
|
|
|
channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
|
2007-11-26 21:32:23 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
|
|
|
if (httpChannel) {
|
|
|
|
// We only want to run scripts if the server really intended to
|
|
|
|
// send us a JAR file. Check the server-supplied content type for
|
|
|
|
// a JAR type.
|
2011-09-09 15:41:04 -07:00
|
|
|
nsCAutoString header;
|
2007-11-26 21:32:23 -08:00
|
|
|
httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
|
|
|
|
header);
|
|
|
|
nsCAutoString contentType;
|
|
|
|
nsCAutoString charset;
|
|
|
|
NS_ParseContentType(header, contentType, charset);
|
2009-03-10 14:58:00 -07:00
|
|
|
nsCAutoString channelContentType;
|
|
|
|
channel->GetContentType(channelContentType);
|
|
|
|
mIsUnsafe = !(contentType.Equals(channelContentType) &&
|
|
|
|
(contentType.EqualsLiteral("application/java-archive") ||
|
|
|
|
contentType.EqualsLiteral("application/x-jar")));
|
2007-11-26 21:32:23 -08:00
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIJARChannel> innerJARChannel(do_QueryInterface(channel));
|
|
|
|
if (innerJARChannel) {
|
2011-09-28 23:19:26 -07:00
|
|
|
bool unsafe;
|
2007-11-26 21:32:23 -08:00
|
|
|
innerJARChannel->GetIsUnsafe(&unsafe);
|
|
|
|
mIsUnsafe = unsafe;
|
|
|
|
}
|
|
|
|
}
|
2011-09-09 15:41:04 -07:00
|
|
|
|
|
|
|
channel->GetContentDispositionHeader(mContentDispositionHeader);
|
|
|
|
mContentDisposition = NS_GetContentDispositionFromHeader(mContentDispositionHeader, this);
|
2007-11-26 21:32:23 -08:00
|
|
|
}
|
|
|
|
|
2011-06-11 19:30:15 -07:00
|
|
|
if (NS_SUCCEEDED(status) && mIsUnsafe &&
|
2011-09-28 23:19:26 -07:00
|
|
|
!Preferences::GetBool("network.jar.open-unsafe-types", false)) {
|
2011-06-11 19:30:15 -07:00
|
|
|
status = NS_ERROR_UNSAFE_CONTENT_TYPE;
|
2007-11-26 20:35:00 -08:00
|
|
|
}
|
|
|
|
|
2009-03-10 14:58:00 -07:00
|
|
|
if (NS_SUCCEEDED(status)) {
|
|
|
|
// Refuse to unpack view-source: jars even if open-unsafe-types is set.
|
|
|
|
nsCOMPtr<nsIViewSourceChannel> viewSource = do_QueryInterface(channel);
|
|
|
|
if (viewSource) {
|
|
|
|
status = NS_ERROR_UNSAFE_CONTENT_TYPE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_SUCCEEDED(status)) {
|
|
|
|
mJarFile = file;
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
rv = CreateJarInput(nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// create input stream pump
|
|
|
|
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
2012-07-30 07:20:58 -07:00
|
|
|
rv = mPump->AsyncRead(this, nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
status = rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(status)) {
|
2007-11-26 21:32:23 -08:00
|
|
|
mStatus = status;
|
2012-07-30 07:20:58 -07:00
|
|
|
OnStartRequest(nullptr, nullptr);
|
|
|
|
OnStopRequest(nullptr, nullptr, status);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsIStreamListener
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::OnStartRequest(nsIRequest *req, nsISupports *ctx)
|
|
|
|
{
|
|
|
|
LOG(("nsJARChannel::OnStartRequest [this=%x %s]\n", this, mSpec.get()));
|
|
|
|
|
|
|
|
return mListener->OnStartRequest(this, mListenerContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
|
|
|
|
{
|
|
|
|
LOG(("nsJARChannel::OnStopRequest [this=%x %s status=%x]\n",
|
|
|
|
this, mSpec.get(), status));
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(mStatus))
|
|
|
|
mStatus = status;
|
|
|
|
|
|
|
|
if (mListener) {
|
|
|
|
mListener->OnStopRequest(this, mListenerContext, status);
|
|
|
|
mListener = 0;
|
|
|
|
mListenerContext = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mLoadGroup)
|
2012-07-30 07:20:58 -07:00
|
|
|
mLoadGroup->RemoveRequest(this, nullptr, status);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
mPump = 0;
|
|
|
|
NS_IF_RELEASE(mJarInput);
|
2011-10-17 07:59:28 -07:00
|
|
|
mIsPending = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
mDownloader = 0; // this may delete the underlying jar file
|
|
|
|
|
|
|
|
// Drop notification callbacks to prevent cycles.
|
|
|
|
mCallbacks = 0;
|
|
|
|
mProgressSink = 0;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsJARChannel::OnDataAvailable(nsIRequest *req, nsISupports *ctx,
|
|
|
|
nsIInputStream *stream,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t offset, uint32_t count)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
#if defined(PR_LOGGING)
|
|
|
|
LOG(("nsJARChannel::OnDataAvailable [this=%x %s]\n", this, mSpec.get()));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
rv = mListener->OnDataAvailable(this, mListenerContext, stream, offset, count);
|
|
|
|
|
|
|
|
// simply report progress here instead of hooking ourselves up as a
|
|
|
|
// nsITransportEventSink implementation.
|
2010-08-30 13:20:39 -07:00
|
|
|
// XXX do the 64-bit stuff for real
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND))
|
2012-08-22 08:56:38 -07:00
|
|
|
mProgressSink->OnProgress(this, nullptr, uint64_t(offset + count),
|
|
|
|
uint64_t(mContentLength));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return rv; // let the pump cancel on failure
|
|
|
|
}
|