зеркало из https://github.com/mozilla/gecko-dev.git
fixes bug 116365 (second attempt) "[RFE] Cache partial documents; automatically
issue byte range requests" r=gagan sr=mscott,rpotts,brendan a=asa
This commit is contained in:
Родитель
f5ef8ca045
Коммит
edab6546f5
|
@ -539,7 +539,11 @@ NS_IMETHODIMP nsMsgDBFolder::GetOfflineFileTransport(nsMsgKey msgKey, PRUint32 *
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = fts->CreateTransport(localStore, PR_RDWR | PR_CREATE_FILE, 0664, aFileChannel);
|
||||
rv = fts->CreateTransport(localStore,
|
||||
PR_RDWR | PR_CREATE_FILE,
|
||||
0664,
|
||||
PR_TRUE,
|
||||
aFileChannel);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
|
|
|
@ -234,7 +234,7 @@ nsresult nsMsgProtocol::OpenFileSocket(nsIURI * aURL, PRUint32 aStartPosition, P
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
//we are always using this file socket to read data from the mailbox.
|
||||
rv = fts->CreateTransport(file, PR_RDONLY,
|
||||
0664, getter_AddRefs(m_transport));
|
||||
0664, PR_TRUE, getter_AddRefs(m_transport));
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
|
||||
return rv;
|
||||
|
@ -880,7 +880,7 @@ nsresult nsMsgFilePostHelper::Init(nsIOutputStream * aOutStream, nsMsgAsyncWrite
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsITransport> transport;
|
||||
rv = fts->CreateTransport(aFileToPost, PR_RDONLY, 0664, getter_AddRefs(transport));
|
||||
rv = fts->CreateTransport(aFileToPost, PR_RDONLY, 0664, PR_TRUE, getter_AddRefs(transport));
|
||||
if (transport)
|
||||
{
|
||||
rv = transport->AsyncRead(this, nsnull, 0, PRUint32(-1), 0, getter_AddRefs(mPostFileRequest));
|
||||
|
|
|
@ -339,7 +339,7 @@ nsJARChannel::AsyncReadJARElement()
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsITransport> jarTransport;
|
||||
rv = fts->CreateTransportFromStreamIO(this, getter_AddRefs(jarTransport));
|
||||
rv = fts->CreateTransportFromStreamIO(this, PR_TRUE, getter_AddRefs(jarTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (mCallbacks) {
|
||||
|
|
|
@ -49,7 +49,8 @@ interface nsIFileTransportService : nsISupports
|
|||
{
|
||||
nsITransport createTransport(in nsIFile file,
|
||||
in long ioFlags,
|
||||
in long perm);
|
||||
in long perm,
|
||||
in boolean closeStreamWhenDone);
|
||||
|
||||
// This version can be used with an existing input stream to serve
|
||||
// as a data pump:
|
||||
|
@ -60,7 +61,8 @@ interface nsIFileTransportService : nsISupports
|
|||
in long contentLength,
|
||||
in boolean closeStreamWhenDone);
|
||||
|
||||
nsITransport createTransportFromStreamIO(in nsIStreamIO io);
|
||||
nsITransport createTransportFromStreamIO(in nsIStreamIO io,
|
||||
in boolean closeStreamWhenDone);
|
||||
|
||||
void dispatchRequest(in nsIRunnable runnable);
|
||||
void processPendingRequests();
|
||||
|
|
|
@ -124,6 +124,10 @@ nsFileIO::nsFileIO()
|
|||
nsFileIO::~nsFileIO()
|
||||
{
|
||||
(void)Close(NS_OK);
|
||||
if (mFD) {
|
||||
PR_Close(mFD);
|
||||
mFD = nsnull;
|
||||
}
|
||||
#ifdef PR_LOGGING
|
||||
if (mSpec) nsCRT::free(mSpec);
|
||||
#endif
|
||||
|
@ -185,11 +189,18 @@ nsFileIO::Open()
|
|||
|
||||
rv = localFile->OpenNSPRFileDesc(mIOFlags, mPerm, &mFD);
|
||||
if (NS_FAILED(rv)) {
|
||||
mFD = nsnull; // just in case
|
||||
#ifdef PR_LOGGING
|
||||
nsresult openError = rv;
|
||||
#endif
|
||||
// maybe we can't open this because it is a directory...
|
||||
PRBool isDir;
|
||||
rv = localFile->IsDirectory(&isDir);
|
||||
if (NS_SUCCEEDED(rv) && isDir) {
|
||||
return NS_OK;
|
||||
}
|
||||
PR_LOG(gFileIOLog, PR_LOG_DEBUG,
|
||||
("nsFileIO: OpenNSPRFileDesc failed [rv=%x]\n", openError));
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
@ -294,8 +305,10 @@ nsFileIO::GetInputStream(nsIInputStream * *aInputStream)
|
|||
return rv;
|
||||
|
||||
if (isDir) {
|
||||
if (mFD)
|
||||
if (mFD) {
|
||||
PR_Close(mFD);
|
||||
mFD = nsnull;
|
||||
}
|
||||
rv = nsDirectoryIndexStream::Create(mFile, aInputStream);
|
||||
PR_LOG(gFileIOLog, PR_LOG_DEBUG,
|
||||
("nsFileIO: opening local dir %s for input (%x)",
|
||||
|
@ -307,7 +320,7 @@ nsFileIO::GetInputStream(nsIInputStream * *aInputStream)
|
|||
if (fileIn == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(fileIn);
|
||||
rv = fileIn->InitWithFileDescriptor(mFD, mFile, PR_FALSE);
|
||||
rv = fileIn->InitWithFileDescriptor(mFD, this);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
#ifdef NS_NO_INPUT_BUFFERING
|
||||
*aInputStream = fileIn;
|
||||
|
@ -351,7 +364,7 @@ nsFileIO::GetOutputStream(nsIOutputStream * *aOutputStream)
|
|||
if (fileOut == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(fileOut);
|
||||
rv = fileOut->InitWithFileDescriptor(mFD, mFile);
|
||||
rv = fileOut->InitWithFileDescriptor(mFD, this);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIOutputStream> bufStr;
|
||||
#ifdef NS_NO_OUTPUT_BUFFERING
|
||||
|
@ -391,21 +404,39 @@ nsFileIO::GetName(nsACString &aName)
|
|||
|
||||
nsFileStream::nsFileStream()
|
||||
: mFD(nsnull)
|
||||
, mCloseFD(PR_TRUE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsFileStream::~nsFileStream()
|
||||
{
|
||||
if (mCloseFD)
|
||||
Close();
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileStream, nsISeekableStream)
|
||||
|
||||
nsresult
|
||||
nsFileStream::InitWithFileDescriptor(PRFileDesc* fd, nsISupports* parent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
|
||||
//
|
||||
// this file stream is dependent on its parent to keep the
|
||||
// file descriptor valid. an owning reference to the parent
|
||||
// prevents the file descriptor from going away prematurely.
|
||||
//
|
||||
mFD = fd;
|
||||
mCloseFD = PR_FALSE;
|
||||
mParent = parent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFileStream::Close()
|
||||
{
|
||||
if (mFD) {
|
||||
if (mCloseFD)
|
||||
PR_Close(mFD);
|
||||
mFD = nsnull;
|
||||
}
|
||||
|
@ -505,6 +536,8 @@ nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
|||
NS_IMETHODIMP
|
||||
nsFileInputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm, PRBool deleteOnClose)
|
||||
{
|
||||
NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -517,17 +550,6 @@ nsFileInputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm, PRBool del
|
|||
rv = localFile->OpenNSPRFileDesc(ioFlags, perm, &fd);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return InitWithFileDescriptor(fd, file, deleteOnClose);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFileInputStream::InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file, PRBool deleteOnClose)
|
||||
{
|
||||
NS_ASSERTION(mFD == nsnull, "already inited");
|
||||
if (mFD || !fd)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mLineBuffer = nsnull;
|
||||
mFD = fd;
|
||||
|
||||
if (deleteOnClose) {
|
||||
|
@ -609,6 +631,7 @@ nsFileInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = writer(this, closure, readBuf, 0, nBytes, _retval);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) ? nBytes == *_retval : PR_TRUE, "Didn't write all Data.");
|
||||
// XXX this assertion is invalid!
|
||||
}
|
||||
|
||||
nsMemory::Free(readBuf);
|
||||
|
@ -647,6 +670,8 @@ nsFileOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
|||
NS_IMETHODIMP
|
||||
nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm)
|
||||
{
|
||||
NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -654,20 +679,11 @@ nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm)
|
|||
ioFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
|
||||
if (perm <= 0)
|
||||
perm = 0664;
|
||||
|
||||
PRFileDesc* fd;
|
||||
rv = localFile->OpenNSPRFileDesc(ioFlags, perm, &fd);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return InitWithFileDescriptor(fd, file);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsFileOutputStream::InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file)
|
||||
{
|
||||
NS_ASSERTION(mFD == nsnull, "already inited");
|
||||
if (mFD || !fd)
|
||||
return NS_ERROR_FAILURE;
|
||||
mFD = fd;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -88,9 +88,13 @@ public:
|
|||
virtual ~nsFileStream();
|
||||
|
||||
nsresult Close();
|
||||
nsresult InitWithFileDescriptor(PRFileDesc* fd, nsISupports* parent);
|
||||
|
||||
protected:
|
||||
PRFileDesc* mFD;
|
||||
nsCOMPtr<nsISupports> mParent; // strong reference to parent nsFileIO,
|
||||
// which ensures mFD remains valid.
|
||||
PRBool mCloseFD;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -116,7 +120,7 @@ public:
|
|||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
nsresult InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file, PRBool deleteOnClose);
|
||||
|
||||
protected:
|
||||
nsLineBuffer *mLineBuffer;
|
||||
nsCOMPtr<nsIFile> mFileToDelete;
|
||||
|
@ -137,7 +141,6 @@ public:
|
|||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
nsresult InitWithFileDescriptor(PRFileDesc* fd, nsIFile* file);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -234,14 +234,18 @@ nsFileTransport::nsFileTransport()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsFileTransport::Init(nsFileTransportService *aService, nsIFile* file, PRInt32 ioFlags, PRInt32 perm)
|
||||
nsFileTransport::Init(nsFileTransportService *aService,
|
||||
nsIFile *file,
|
||||
PRInt32 ioFlags,
|
||||
PRInt32 perm,
|
||||
PRBool closeStreamWhenDone)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFileIO> io;
|
||||
rv = NS_NewFileIO(getter_AddRefs(io), file, ioFlags, perm);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return Init(aService, io);
|
||||
return Init(aService, io, closeStreamWhenDone);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -258,12 +262,13 @@ nsFileTransport::Init(nsFileTransportService *aService,
|
|||
rv = NS_NewInputStreamIO(getter_AddRefs(io), name, inStr,
|
||||
contentType, contentCharset, contentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mCloseStreamWhenDone = closeStreamWhenDone;
|
||||
return Init(aService, io);
|
||||
return Init(aService, io, closeStreamWhenDone);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFileTransport::Init(nsFileTransportService *aService, nsIStreamIO* io)
|
||||
nsFileTransport::Init(nsFileTransportService *aService,
|
||||
nsIStreamIO* io,
|
||||
PRBool closeStreamWhenDone)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (mLock == nsnull) {
|
||||
|
@ -275,6 +280,8 @@ nsFileTransport::Init(nsFileTransportService *aService, nsIStreamIO* io)
|
|||
rv = mStreamIO->GetName(mStreamName);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "GetName failed");
|
||||
|
||||
mCloseStreamWhenDone = closeStreamWhenDone;
|
||||
|
||||
NS_ADDREF(mService = aService);
|
||||
PR_AtomicIncrement(&mService->mTotalTransports);
|
||||
|
||||
|
|
|
@ -88,14 +88,17 @@ public:
|
|||
|
||||
nsresult Init(nsFileTransportService *aService, nsIFile* file,
|
||||
PRInt32 ioFlags,
|
||||
PRInt32 perm);
|
||||
PRInt32 perm,
|
||||
PRBool closeStreamWhenDone);
|
||||
nsresult Init(nsFileTransportService *aService, const nsACString &name,
|
||||
nsIInputStream *fromStream,
|
||||
const nsACString &contentType,
|
||||
const nsACString &contentCharset,
|
||||
PRInt32 contentLength,
|
||||
PRBool closeStreamWhenDone);
|
||||
nsresult Init(nsFileTransportService *aService, nsIStreamIO* io);
|
||||
nsresult Init(nsFileTransportService *aService,
|
||||
nsIStreamIO* io,
|
||||
PRBool closeStreamWhenDone);
|
||||
|
||||
void Process(nsIProgressEventSink *);
|
||||
void DoClose(void);
|
||||
|
|
|
@ -127,6 +127,7 @@ NS_IMETHODIMP
|
|||
nsFileTransportService::CreateTransport(nsIFile* file,
|
||||
PRInt32 ioFlags,
|
||||
PRInt32 perm,
|
||||
PRBool closeStreamWhenDone,
|
||||
nsITransport** result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -134,7 +135,7 @@ nsFileTransportService::CreateTransport(nsIFile* file,
|
|||
if (trans == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(trans);
|
||||
rv = trans->Init(this, file, ioFlags, perm);
|
||||
rv = trans->Init(this, file, ioFlags, perm, closeStreamWhenDone);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(trans);
|
||||
return rv;
|
||||
|
@ -170,6 +171,7 @@ nsFileTransportService::CreateTransportFromStream(const nsACString &name,
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsFileTransportService::CreateTransportFromStreamIO(nsIStreamIO *io,
|
||||
PRBool closeStreamWhenDone,
|
||||
nsITransport **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -177,7 +179,7 @@ nsFileTransportService::CreateTransportFromStreamIO(nsIStreamIO *io,
|
|||
if (trans == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(trans);
|
||||
rv = trans->Init(this, io);
|
||||
rv = trans->Init(this, io, closeStreamWhenDone);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(trans);
|
||||
return rv;
|
||||
|
|
|
@ -311,7 +311,8 @@ nsStreamIOChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
|
|||
do_GetService(kFileTransportServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = fts->CreateTransportFromStreamIO(mStreamIO, getter_AddRefs(mFileTransport));
|
||||
rv = fts->CreateTransportFromStreamIO(mStreamIO, PR_TRUE,
|
||||
getter_AddRefs(mFileTransport));
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
|
||||
|
|
|
@ -580,7 +580,7 @@ nsDiskCacheDevice::GetTransportForEntry(nsCacheEntry * entry,
|
|||
break;
|
||||
}
|
||||
|
||||
rv = gFileTransportService->CreateTransport(file, ioFlags, PR_IRUSR | PR_IWUSR, result);
|
||||
rv = gFileTransportService->CreateTransport(file, ioFlags, PR_IRUSR | PR_IWUSR, PR_FALSE, result);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,11 @@ nsXMLMIMEDataSource::Serialize() {
|
|||
do_GetService(kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
|
||||
rv = fts->CreateTransport(mFile, PR_WRONLY|PR_CREATE_FILE, PR_IRWXU, getter_AddRefs(transport)) ;
|
||||
rv = fts->CreateTransport(mFile,
|
||||
PR_WRONLY|PR_CREATE_FILE,
|
||||
PR_IRWXU,
|
||||
PR_TRUE,
|
||||
getter_AddRefs(transport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
|
@ -726,7 +730,11 @@ nsXMLMIMEDataSource::InitFromFile( nsIFile* aFile )
|
|||
do_GetService(kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
// Made second parameter 0 since I really don't know what it is used for
|
||||
rv = fts->CreateTransport(aFile, PR_RDONLY, PR_IRWXU, getter_AddRefs(transport)) ;
|
||||
rv = fts->CreateTransport(aFile,
|
||||
PR_RDONLY,
|
||||
PR_IRWXU,
|
||||
PR_TRUE,
|
||||
getter_AddRefs(transport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ nsFileChannel::EnsureTransport()
|
|||
do_GetService(kFileTransportServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = fts->CreateTransport(mFile, mIOFlags, mPerm,
|
||||
rv = fts->CreateTransport(mFile, mIOFlags, mPerm, PR_TRUE,
|
||||
getter_AddRefs(mFileTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ nsHttpChannel::nsHttpChannel()
|
|||
, mConnectionInfo(nsnull)
|
||||
, mLoadFlags(LOAD_NORMAL)
|
||||
, mStatus(NS_OK)
|
||||
, mLogicalOffset(0)
|
||||
, mCapabilities(0)
|
||||
, mReferrerType(REFERRER_NONE)
|
||||
, mCachedResponseHead(nsnull)
|
||||
|
@ -70,6 +71,7 @@ nsHttpChannel::nsHttpChannel()
|
|||
, mApplyConversion(PR_TRUE)
|
||||
, mFromCacheOnly(PR_FALSE)
|
||||
, mCachedContentIsValid(PR_FALSE)
|
||||
, mCachedContentIsPartial(PR_FALSE)
|
||||
, mResponseHeadersModified(PR_FALSE)
|
||||
, mCanceled(PR_FALSE)
|
||||
, mUploadStreamHasHeaders(PR_FALSE)
|
||||
|
@ -389,7 +391,7 @@ nsHttpChannel::SetupTransaction()
|
|||
if (mConnectionInfo->UsingSSL() || !mConnectionInfo->UsingHttpProxy()) {
|
||||
rv = mURI->GetPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// path may contain UTF-8 characters, so ensure that their escaped.
|
||||
// path may contain UTF-8 characters, so ensure that they're escaped.
|
||||
if (NS_EscapeURL(path.get(), path.Length(), esc_OnlyNonASCII, buf))
|
||||
requestURI = buf.get();
|
||||
else
|
||||
|
@ -489,10 +491,15 @@ nsHttpChannel::ProcessResponse()
|
|||
switch (httpStatus) {
|
||||
case 200:
|
||||
case 203:
|
||||
case 206:
|
||||
// these can normally be cached
|
||||
rv = ProcessNormal();
|
||||
break;
|
||||
case 206:
|
||||
if (mCachedContentIsPartial) // an internal byte range request...
|
||||
rv = ProcessPartialContent();
|
||||
else
|
||||
rv = ProcessNormal();
|
||||
break;
|
||||
case 300:
|
||||
case 301:
|
||||
case 302:
|
||||
|
@ -596,6 +603,160 @@ nsHttpChannel::ProcessNormal()
|
|||
return rv;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel <byte-range>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::SetupByteRangeRequest(PRUint32 partialLen)
|
||||
{
|
||||
// cached content has been found to be partial, add necessary request
|
||||
// headers to complete cache entry.
|
||||
|
||||
// use strongest validator available...
|
||||
const char *val = mCachedResponseHead->PeekHeader(nsHttp::ETag);
|
||||
if (!val)
|
||||
val = mCachedResponseHead->PeekHeader(nsHttp::Last_Modified);
|
||||
if (!val) {
|
||||
// if we hit this code it means mCachedResponseHead->IsResumable() is
|
||||
// either broken or not being called.
|
||||
NS_NOTREACHED("no cache validator");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
PR_snprintf(buf, sizeof(buf), "bytes=%u-", partialLen);
|
||||
|
||||
mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf));
|
||||
mRequestHead.SetHeader(nsHttp::If_Range, nsDependentCString(val));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::ProcessPartialContent()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// ok, we've just received a 206
|
||||
//
|
||||
// we need to stream whatever data is in the cache out first, and then
|
||||
// pick up whatever data is on the wire, writing it into the cache.
|
||||
|
||||
LOG(("nsHttpChannel::ProcessPartialContent [this=%x]\n", this));
|
||||
|
||||
NS_ENSURE_TRUE(mCachedResponseHead, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// suspend the current transaction (may still get an OnDataAvailable)
|
||||
rv = mTransaction->Suspend();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// merge any new headers with the cached response headers
|
||||
rv = mCachedResponseHead->UpdateHeaders(mResponseHead->Headers());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// update the cached response head
|
||||
nsCAutoString head;
|
||||
mCachedResponseHead->Flatten(head, PR_TRUE);
|
||||
rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// make the cached response be the current response
|
||||
delete mResponseHead;
|
||||
mResponseHead = mCachedResponseHead;
|
||||
mCachedResponseHead = 0;
|
||||
|
||||
rv = UpdateExpirationTime();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// the cached content is valid, although incomplete.
|
||||
mCachedContentIsValid = PR_TRUE;
|
||||
return ReadFromCache();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::BufferPartialContent(nsIInputStream *input, PRUint32 count)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
LOG(("nsHttpChannel::BufferPartialContent [this=%x count=%u]\n", this, count));
|
||||
|
||||
if (!mBufferOut) {
|
||||
LOG(("creating pipe...\n"));
|
||||
//
|
||||
// create a pipe for buffering network data (the size of this
|
||||
// pipe must be equal to or greater than the size of the pipe
|
||||
// used to proxy data from the socket transport thread).
|
||||
//
|
||||
rv = NS_NewPipe(getter_AddRefs(mBufferIn),
|
||||
getter_AddRefs(mBufferOut),
|
||||
NS_HTTP_SEGMENT_SIZE,
|
||||
NS_HTTP_BUFFER_SIZE,
|
||||
PR_TRUE,
|
||||
PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
PRUint32 bytesWritten = 0;
|
||||
rv = mBufferOut->WriteFrom(input, count, &bytesWritten);
|
||||
if (NS_FAILED(rv) || (bytesWritten != count)) {
|
||||
LOG(("writing to pipe failed [rv=%s bytes-written=%u]\n", rv, bytesWritten));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::OnDoneReadingPartialCacheEntry(PRBool *streamDone)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
LOG(("nsHttpChannel::OnDoneReadingPartialCacheEntry [this=%x]", this));
|
||||
|
||||
// by default, assume we would have streamed all data or failed...
|
||||
*streamDone = PR_TRUE;
|
||||
|
||||
// setup cache listener to append to cache entry
|
||||
PRUint32 size;
|
||||
rv = mCacheEntry->GetDataSize(&size);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = InstallCacheListener(size);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// process any buffered data
|
||||
if (mBufferIn) {
|
||||
PRUint32 avail;
|
||||
rv = mBufferIn->Available(&avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mListener->OnDataAvailable(this, mListenerContext, mBufferIn, size, avail);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// done with the pipe
|
||||
mBufferIn = 0;
|
||||
mBufferOut = 0;
|
||||
}
|
||||
|
||||
// need to track the logical offset of the data being sent to our listener
|
||||
mLogicalOffset = size;
|
||||
|
||||
// we're now completing the cached content, so we can clear this flag.
|
||||
// this puts us in the state of a regular download.
|
||||
mCachedContentIsPartial = PR_FALSE;
|
||||
|
||||
// resume the transaction if it exists, otherwise the pipe contained the
|
||||
// remaining part of the document and we've now streamed all of the data.
|
||||
if (mTransaction) {
|
||||
rv = mTransaction->Resume();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
*streamDone = PR_FALSE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel <cache>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -664,7 +825,10 @@ nsHttpChannel::OpenCacheEntry(PRBool *delayed)
|
|||
return NS_OK;
|
||||
}
|
||||
else if (mRequestHead.PeekHeader(nsHttp::Range)) {
|
||||
// we don't support caching for byte range requests
|
||||
// we don't support caching for byte range requests initiated
|
||||
// by our clients.
|
||||
// XXX perhaps we could munge their byte range into the cache
|
||||
// key to make caching sort'a work.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -850,18 +1014,24 @@ nsHttpChannel::CheckCache()
|
|||
}
|
||||
|
||||
// If the cached content-length is set and it does not match the data size
|
||||
// of the cached content, then refetch.
|
||||
PRInt32 contentLength = mCachedResponseHead->ContentLength();
|
||||
if (contentLength != -1) {
|
||||
// of the cached content, then the cached response is partial...
|
||||
// either we need to issue a byte range request or we need to refetch the
|
||||
// entire document.
|
||||
PRUint32 contentLength = (PRUint32) mCachedResponseHead->ContentLength();
|
||||
if (contentLength != PRUint32(-1)) {
|
||||
PRUint32 size;
|
||||
rv = mCacheEntry->GetDataSize(&size);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (size != (PRUint32) contentLength) {
|
||||
if (size != contentLength) {
|
||||
LOG(("Cached data size does not match the Content-Length header "
|
||||
"[content-length=%u size=%u]\n", contentLength, size));
|
||||
if ((size < contentLength) && mCachedResponseHead->IsResumable()) {
|
||||
// looks like a partial entry.
|
||||
// XXX must re-fetch until we learn how to do byte range requests.
|
||||
rv = SetupByteRangeRequest(size);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mCachedContentIsPartial = PR_TRUE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -1002,7 +1172,7 @@ nsHttpChannel::ReadFromCache()
|
|||
if (!mSecurityInfo)
|
||||
mCacheEntry->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
|
||||
|
||||
if (mCacheAccess & nsICache::ACCESS_WRITE) {
|
||||
if ((mCacheAccess & nsICache::ACCESS_WRITE) && !mCachedContentIsPartial) {
|
||||
// We have write access to the cache, but we don't need to go to the
|
||||
// server to validate at this time, so just mark the cache entry as
|
||||
// valid in order to allow others access to this cache entry.
|
||||
|
@ -1150,17 +1320,22 @@ nsHttpChannel::FinalizeCacheEntry()
|
|||
// Open an output stream to the cache entry and insert a listener tee into
|
||||
// the chain of response listeners.
|
||||
nsresult
|
||||
nsHttpChannel::InstallCacheListener()
|
||||
nsHttpChannel::InstallCacheListener(PRUint32 offset)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
LOG(("Preparing to write data into the cache [uri=%s]\n", mSpec.get()));
|
||||
|
||||
NS_ASSERTION(mCacheEntry, "no cache entry");
|
||||
NS_ASSERTION(mListener, "no listener");
|
||||
|
||||
if (!mCacheTransport) {
|
||||
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIOutputStream> out;
|
||||
rv = mCacheTransport->OpenOutputStream(0, PRUint32(-1), 0, getter_AddRefs(out));
|
||||
rv = mCacheTransport->OpenOutputStream(offset, PRUint32(-1), 0, getter_AddRefs(out));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX disk cache does not support overlapped i/o yet
|
||||
|
@ -2536,14 +2711,17 @@ nsHttpChannel::GetContentEncodings(nsISimpleEnumerator** aEncodings)
|
|||
NS_IMETHODIMP
|
||||
nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
||||
{
|
||||
if (!(mCanceled || NS_FAILED(mStatus))) {
|
||||
// capture the request's status, so our consumers will know ASAP of any
|
||||
// connection failures, etc - bug 93581
|
||||
request->GetStatus(&mStatus);
|
||||
}
|
||||
|
||||
LOG(("nsHttpChannel::OnStartRequest [this=%x request=%x status=%x]\n",
|
||||
this, request, mStatus));
|
||||
|
||||
if (mTransaction) {
|
||||
// don't enter this block if we're reading from the cache...
|
||||
if (NS_SUCCEEDED(mStatus) && !mCacheReadRequest && mTransaction) {
|
||||
// grab the security info from the connection object; the transaction
|
||||
// is guaranteed to own a reference to the connection.
|
||||
mSecurityInfo = mTransaction->SecurityInfo();
|
||||
|
@ -2578,6 +2756,23 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
|
|||
mPrevTransaction = nsnull;
|
||||
}
|
||||
|
||||
if (mCachedContentIsPartial && NS_SUCCEEDED(status)) {
|
||||
if (request == mTransaction) {
|
||||
// byte-range transaction finished before we got around to streaming it.
|
||||
NS_ASSERTION(mCacheReadRequest, "should be reading from cache right now");
|
||||
NS_RELEASE(mTransaction);
|
||||
mTransaction = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
if (request == mCacheReadRequest) {
|
||||
PRBool streamDone;
|
||||
status = OnDoneReadingPartialCacheEntry(&streamDone);
|
||||
if (NS_SUCCEEDED(status) && !streamDone)
|
||||
return status;
|
||||
// otherwise, fall through and fire OnStopRequest...
|
||||
}
|
||||
}
|
||||
|
||||
// if the request is for something we no longer reference, then simply
|
||||
// drop this event.
|
||||
if ((request != mTransaction) && (request != mCacheReadRequest))
|
||||
|
@ -2586,8 +2781,11 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
|
|||
mIsPending = PR_FALSE;
|
||||
mStatus = status;
|
||||
|
||||
// at this point, we're done with the transaction
|
||||
PRBool isPartial = PR_FALSE;
|
||||
if (mTransaction) {
|
||||
// find out if the transaction ran to completion...
|
||||
isPartial = !mTransaction->ResponseIsComplete();
|
||||
// at this point, we're done with the transaction
|
||||
NS_RELEASE(mTransaction);
|
||||
mTransaction = nsnull;
|
||||
}
|
||||
|
@ -2609,12 +2807,21 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
|
|||
}
|
||||
|
||||
if (mCacheEntry) {
|
||||
nsresult closeStatus = status;
|
||||
if (mCanceled) {
|
||||
// we don't want to discard the cache entry if canceled and
|
||||
// reading from the cache.
|
||||
if (mCanceled && (request == mCacheReadRequest))
|
||||
CloseCacheEntry(NS_OK);
|
||||
else
|
||||
CloseCacheEntry(status);
|
||||
if (request == mCacheReadRequest)
|
||||
closeStatus = NS_OK;
|
||||
// we also don't want to discard the cache entry if the
|
||||
// server supports byte range requests, because we could always
|
||||
// complete the download at a later time.
|
||||
else if (isPartial && mResponseHead && mResponseHead->IsResumable()) {
|
||||
LOG(("keeping partial response that is resumable!\n"));
|
||||
closeStatus = NS_OK;
|
||||
}
|
||||
}
|
||||
CloseCacheEntry(closeStatus);
|
||||
}
|
||||
|
||||
if (mLoadGroup)
|
||||
|
@ -2635,6 +2842,11 @@ nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
|
|||
LOG(("nsHttpChannel::OnDataAvailable [this=%x request=%x offset=%u count=%u]\n",
|
||||
this, request, offset, count));
|
||||
|
||||
if (mCachedContentIsPartial && (request == mTransaction)) {
|
||||
// XXX we can eliminate this buffer once bug 93055 is resolved.
|
||||
return BufferPartialContent(input, count);
|
||||
}
|
||||
|
||||
// if the request is for something we no longer reference, then simply
|
||||
// drop this event.
|
||||
if ((request != mTransaction) && (request != mCacheReadRequest)) {
|
||||
|
@ -2642,8 +2854,21 @@ nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
|
|||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
|
||||
if (mListener)
|
||||
return mListener->OnDataAvailable(this, mListenerContext, input, offset, count);
|
||||
if (mListener) {
|
||||
//
|
||||
// we have to manually keep the logical offset of the stream up-to-date.
|
||||
// we cannot depend soley on the offset provided, since we may have
|
||||
// already streamed some data from another source (see, for example,
|
||||
// OnDoneReadingPartialCacheEntry).
|
||||
//
|
||||
nsresult rv = mListener->OnDataAvailable(this,
|
||||
mListenerContext,
|
||||
input,
|
||||
mLogicalOffset,
|
||||
count);
|
||||
mLogicalOffset += count;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
|
|
|
@ -40,10 +40,12 @@
|
|||
#include "nsICacheListener.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsHttpConnection.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
class nsHttpTransaction;
|
||||
class nsHttpResponseHead;
|
||||
|
@ -106,7 +108,13 @@ private:
|
|||
nsresult InitCacheEntry();
|
||||
nsresult StoreAuthorizationMetaData();
|
||||
nsresult FinalizeCacheEntry();
|
||||
nsresult InstallCacheListener();
|
||||
nsresult InstallCacheListener(PRUint32 offset = 0);
|
||||
|
||||
// byte range request specific methods
|
||||
nsresult SetupByteRangeRequest(PRUint32 partialLen);
|
||||
nsresult ProcessPartialContent();
|
||||
nsresult BufferPartialContent(nsIInputStream *, PRUint32 count);
|
||||
nsresult OnDoneReadingPartialCacheEntry(PRBool *streamDone);
|
||||
|
||||
// auth specific methods
|
||||
nsresult GetCredentials(const char *challenges, PRBool proxyAuth, nsAFlatCString &creds);
|
||||
|
@ -149,6 +157,7 @@ private:
|
|||
|
||||
PRUint32 mLoadFlags;
|
||||
PRUint32 mStatus;
|
||||
PRUint32 mLogicalOffset;
|
||||
PRUint8 mCapabilities;
|
||||
PRUint8 mReferrerType;
|
||||
|
||||
|
@ -161,6 +170,10 @@ private:
|
|||
PRUint32 mPostID;
|
||||
PRUint32 mRequestTime;
|
||||
|
||||
// byte-range specific data
|
||||
nsCOMPtr<nsIInputStream> mBufferIn;
|
||||
nsCOMPtr<nsIOutputStream> mBufferOut;
|
||||
|
||||
// auth specific data
|
||||
nsXPIDLString mUser;
|
||||
nsXPIDLString mPass;
|
||||
|
@ -174,6 +187,7 @@ private:
|
|||
PRPackedBool mApplyConversion;
|
||||
PRPackedBool mFromCacheOnly;
|
||||
PRPackedBool mCachedContentIsValid;
|
||||
PRPackedBool mCachedContentIsPartial;
|
||||
PRPackedBool mResponseHeadersModified;
|
||||
PRPackedBool mCanceled;
|
||||
PRPackedBool mUploadStreamHasHeaders;
|
||||
|
|
|
@ -363,6 +363,17 @@ nsHttpResponseHead::MustValidateIfExpired()
|
|||
return val && PL_strcasestr(val, "must-revalidate");
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHttpResponseHead::IsResumable()
|
||||
{
|
||||
// even though some HTTP/1.0 servers may support byte range requests, we're not
|
||||
// going to bother with them, since those servers wouldn't understand If-Range.
|
||||
return mVersion >= NS_HTTP_VERSION_1_1 &&
|
||||
PeekHeader(nsHttp::Content_Length) &&
|
||||
(PeekHeader(nsHttp::ETag) || PeekHeader(nsHttp::Last_Modified)) &&
|
||||
PL_strcasestr(PeekHeader(nsHttp::Accept_Ranges), "bytes");
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHttpResponseHead::ExpiresInPast()
|
||||
{
|
||||
|
|
|
@ -87,6 +87,9 @@ public:
|
|||
PRBool MustValidate();
|
||||
PRBool MustValidateIfExpired();
|
||||
|
||||
// returns true if the server appears to support byte range requests.
|
||||
PRBool IsResumable();
|
||||
|
||||
// returns true if the Expires header has a value in the past relative to the
|
||||
// value of the Date header.
|
||||
PRBool ExpiresInPast();
|
||||
|
|
|
@ -95,6 +95,7 @@ nsHttpTransaction::nsHttpTransaction(nsIStreamListener *listener,
|
|||
, mCapabilities(caps)
|
||||
, mHaveStatusLine(PR_FALSE)
|
||||
, mHaveAllHeaders(PR_FALSE)
|
||||
, mResponseIsComplete(PR_FALSE)
|
||||
, mFiredOnStart(PR_FALSE)
|
||||
, mNoContent(PR_FALSE)
|
||||
, mPrematureEOF(PR_FALSE)
|
||||
|
@ -617,6 +618,7 @@ nsHttpTransaction::HandleContent(char *buf,
|
|||
// OnTransactionComplete is fired only once!
|
||||
PRInt32 priorVal = PR_AtomicSet(&mTransactionDone, 1);
|
||||
if (priorVal == 0) {
|
||||
mResponseIsComplete = PR_TRUE;
|
||||
// let the connection know that we are done with it; this should
|
||||
// result in OnStopTransaction being fired.
|
||||
return mConnection->OnTransactionComplete(this, NS_OK);
|
||||
|
|
|
@ -78,6 +78,9 @@ public:
|
|||
// will drop any reference to the response headers after this call.
|
||||
nsHttpResponseHead *TakeResponseHead();
|
||||
|
||||
// Called to find out if the transaction generated a complete response.
|
||||
PRBool ResponseIsComplete() { return mResponseIsComplete; }
|
||||
|
||||
// nsAHttpTransaction methods:
|
||||
void SetConnection(nsAHttpConnection *conn) { NS_IF_ADDREF(mConnection = conn); }
|
||||
void SetSecurityInfo(nsISupports *info) { mSecurityInfo = info; }
|
||||
|
@ -133,6 +136,7 @@ private:
|
|||
|
||||
PRPackedBool mHaveStatusLine;
|
||||
PRPackedBool mHaveAllHeaders;
|
||||
PRPackedBool mResponseIsComplete;
|
||||
PRPackedBool mFiredOnStart;
|
||||
PRPackedBool mNoContent; // expecting an empty entity body?
|
||||
PRPackedBool mPrematureEOF;
|
||||
|
|
|
@ -339,7 +339,7 @@ nsJARChannel::AsyncReadJARElement()
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsITransport> jarTransport;
|
||||
rv = fts->CreateTransportFromStreamIO(this, getter_AddRefs(jarTransport));
|
||||
rv = fts->CreateTransportFromStreamIO(this, PR_TRUE, getter_AddRefs(jarTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (mCallbacks) {
|
||||
|
|
|
@ -366,7 +366,7 @@ ParallelReadTest(char* dirName, nsIFileTransportService* fts)
|
|||
NS_ASSERTION(listener, "QI failed");
|
||||
|
||||
nsITransport* trans;
|
||||
rv = fts->CreateTransport(file, PR_RDONLY, 0, &trans);
|
||||
rv = fts->CreateTransport(file, PR_RDONLY, 0, PR_TRUE, &trans);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "create failed");
|
||||
nsCOMPtr<nsIRequest> request;
|
||||
rv = trans->AsyncRead(nsnull, listener, 0, -1, 0, getter_AddRefs(request));
|
||||
|
|
|
@ -204,7 +204,7 @@ TestAsyncRead(const char* fileName, PRUint32 offset, PRInt32 length)
|
|||
nsCOMPtr<nsILocalFile> file;
|
||||
rv = NS_NewLocalFile(fileName, PR_FALSE, getter_AddRefs(file));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fts->CreateTransport(file, PR_RDONLY, 0, &fileTrans);
|
||||
rv = fts->CreateTransport(file, PR_RDONLY, 0, PR_TRUE, &fileTrans);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
MyListener* listener = new MyListener();
|
||||
|
@ -260,7 +260,7 @@ TestAsyncWrite(const char* fileName, PRUint32 offset, PRInt32 length)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fts->CreateTransport(file,
|
||||
PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
|
||||
0664, &fileTrans);
|
||||
0664, PR_TRUE, &fileTrans);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
MyListener* listener = new MyListener();
|
||||
|
|
|
@ -133,7 +133,7 @@ TestSyncWrite(char* filename, PRUint32 startPosition, PRInt32 length)
|
|||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
nsCOMPtr<nsITransport> transport;
|
||||
rv = fts->CreateTransport(fs, PR_RDWR | PR_CREATE_FILE, 0664,
|
||||
rv = fts->CreateTransport(fs, PR_RDWR | PR_CREATE_FILE, 0664, PR_TRUE,
|
||||
getter_AddRefs(transport)) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
|
|
|
@ -1030,10 +1030,14 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel * aChannel)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsITransport> fileTransport;
|
||||
rv = fts->CreateTransport(mTempFile, PR_WRONLY | PR_CREATE_FILE, 0600, getter_AddRefs(fileTransport));
|
||||
rv = fts->CreateTransport(mTempFile,
|
||||
PR_WRONLY | PR_CREATE_FILE,
|
||||
0600,
|
||||
PR_TRUE,
|
||||
getter_AddRefs(fileTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = fileTransport->OpenOutputStream(0, -1, 0, getter_AddRefs(mOutStream));
|
||||
rv = fileTransport->OpenOutputStream(0, PRUint32(-1), 0, getter_AddRefs(mOutStream));
|
||||
|
||||
#ifdef XP_MAC
|
||||
nsXPIDLCString contentType;
|
||||
|
|
|
@ -168,6 +168,7 @@ nsStreamXferOp::Start( void ) {
|
|||
rv = fts->CreateTransport( mOutputFile,
|
||||
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
|
||||
0664,
|
||||
PR_TRUE,
|
||||
getter_AddRefs( mOutputTransport ) );
|
||||
|
||||
if ( NS_SUCCEEDED( rv ) ) {
|
||||
|
|
|
@ -777,6 +777,7 @@ nsXPInstallManager::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
|
|||
rv = fts->CreateTransport(mItem->mFile,
|
||||
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
|
||||
0664,
|
||||
PR_TRUE,
|
||||
getter_AddRefs( outTransport));
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
|
|
Загрузка…
Ссылка в новой задаче