gecko-dev/netwerk/cache/mgr/nsCacheEntryChannel.cpp

230 строки
5.9 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsCacheManager.h"
#include "nsCacheEntryChannel.h"
#include "nsIOutputStream.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsMemory.h"
nsCacheEntryChannel::nsCacheEntryChannel(
nsCachedNetData* aCacheEntry,
nsIChannel* aChannel,
nsILoadGroup* aLoadGroup):
nsChannelProxy(aChannel),
mCacheEntry(aCacheEntry),
mLoadGroup(aLoadGroup),
mLoadAttributes(0)
{
NS_ASSERTION(aCacheEntry->mChannelCount < 0xFF, "Overflowed channel counter");
mCacheEntry->mChannelCount++;
NS_INIT_REFCNT();
}
nsCacheEntryChannel::~nsCacheEntryChannel()
{
mCacheEntry->mChannelCount--;
}
NS_IMPL_THREADSAFE_ISUPPORTS3(nsCacheEntryChannel,
nsISupports,
nsIChannel,
nsIRequest)
// A proxy for nsIOutputStream
class CacheOutputStream : public nsIOutputStream {
public:
CacheOutputStream(nsIOutputStream *aOutputStream,
nsCachedNetData *aCacheEntry):
mOutputStream(aOutputStream),
mCacheEntry(aCacheEntry),
mStartTime(PR_IntervalNow())
{ NS_INIT_REFCNT(); }
virtual ~CacheOutputStream() {
mCacheEntry->NoteDownloadTime(mStartTime, PR_IntervalNow());
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
}
NS_DECL_ISUPPORTS
NS_IMETHOD Close() {
return mOutputStream->Close();
}
NS_IMETHOD Flush() { return mOutputStream->Flush(); }
NS_IMETHOD
Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes) {
nsresult rv;
*aActualBytes = 0;
rv = mOutputStream->Write(aBuf, aCount, aActualBytes);
mCacheEntry->mLogicalLength += *aActualBytes;
if (NS_FAILED(rv)) return rv;
nsCacheManager::LimitCacheSize();
return rv;
}
protected:
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsCachedNetData> mCacheEntry;
// Time at which stream was opened
PRIntervalTime mStartTime;
};
NS_IMPL_THREADSAFE_ISUPPORTS1(CacheOutputStream, nsIOutputStream)
NS_IMETHODIMP
nsCacheEntryChannel::GetTransferOffset(PRUint32 *aStartPosition)
{
return mChannel->GetTransferOffset(aStartPosition);
}
NS_IMETHODIMP
nsCacheEntryChannel::SetTransferOffset(PRUint32 aStartPosition)
{
mCacheEntry->mLogicalLength = aStartPosition;
return mChannel->SetTransferOffset(aStartPosition);
}
NS_IMETHODIMP
nsCacheEntryChannel::GetTransferCount(PRInt32 *aReadCount)
{
return mChannel->GetTransferCount(aReadCount);
}
NS_IMETHODIMP
nsCacheEntryChannel::SetTransferCount(PRInt32 aReadCount)
{
return mChannel->SetTransferCount(aReadCount);
}
NS_IMETHODIMP
nsCacheEntryChannel::OpenOutputStream(nsIOutputStream* *aOutputStream)
{
nsresult rv;
nsCOMPtr<nsIOutputStream> baseOutputStream;
rv = mChannel->OpenOutputStream(getter_AddRefs(baseOutputStream));
if (NS_FAILED(rv)) return rv;
mCacheEntry->NoteAccess();
mCacheEntry->NoteUpdate();
*aOutputStream = new CacheOutputStream(baseOutputStream, mCacheEntry);
if (!*aOutputStream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aOutputStream);
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::OpenInputStream(nsIInputStream* *aInputStream)
{
mCacheEntry->NoteAccess();
return mChannel->OpenInputStream(aInputStream);
}
NS_IMETHODIMP
nsCacheEntryChannel::AsyncRead(nsIStreamListener *aListener, nsISupports *aContext)
{
nsresult rv;
NS_ENSURE_ARG(aListener);
mCacheEntry->NoteAccess();
if (mLoadGroup) {
mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
}
rv = mChannel->AsyncRead(aListener, aContext);
return rv;
}
// No async writes allowed to the cache yet
NS_IMETHODIMP
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream,
nsIStreamObserver *aObserver,
nsISupports *aContext)
{
NS_NOTREACHED("nsCacheEntryChannel::AsyncWrite");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
NS_IMETHODIMP
nsCacheEntryChannel::GetURI(nsIURI * *aURI)
{
char* spec;
nsresult rv;
rv = mCacheEntry->GetUriSpec(&spec);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewURI(spec, nsnull, aURI);
nsMemory::Free(spec);
return rv;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetOriginalURI(nsIURI * *aURI)
{
// FIXME - should return original URI passed into NewChannel() ?
NS_NOTREACHED("nsCacheEntryChannel::GetOriginalURI");
return NS_ERROR_NOT_IMPLEMENTED;
}