зеркало из https://github.com/mozilla/gecko-dev.git
fixes bug 97528 "1200 urls created on startup about:blank" (take 2)
r=dp, sr=brendan
This commit is contained in:
Родитель
051c211df1
Коммит
819e81b079
|
@ -270,16 +270,20 @@ NS_IMETHODIMP
|
|||
nsJARChannel::AsyncOpen(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mUserContext = ctxt;
|
||||
mUserListener = listener;
|
||||
mSynchronousRead = PR_FALSE;
|
||||
|
||||
if (mLoadGroup) {
|
||||
rv = mLoadGroup->AddRequest(this, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
mSynchronousRead = PR_FALSE;
|
||||
return EnsureJARFileAvailable();
|
||||
rv = EnsureJARFileAvailable();
|
||||
if (NS_FAILED(rv) && mLoadGroup)
|
||||
mLoadGroup->RemoveRequest(this, nsnull, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -288,30 +292,43 @@ nsJARChannel::EnsureJARFileAvailable()
|
|||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: EnsureJARFileAvailable %s", (const char*)jarURLStr));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: EnsureJARFileAvailable %s", (const char*)jarURLStr));
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = mURI->GetJARFile(getter_AddRefs(mJARBaseURI));
|
||||
if (NS_FAILED(rv)) goto error;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mURI->GetJAREntry(&mJAREntry);
|
||||
if (NS_FAILED(rv)) goto error;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader),
|
||||
mJARBaseURI, this, nsnull, mSynchronousRead,
|
||||
mLoadGroup, mCallbacks, mLoadFlags);
|
||||
// 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(mDownloadedJARFile));
|
||||
}
|
||||
|
||||
// if DownloadComplete() was called early, need to release the reference.
|
||||
if (mSynchronousRead && mSynchronousInputStream)
|
||||
mDownloader = null_nsCOMPtr();
|
||||
if (mDownloadedJARFile) {
|
||||
// after successfully downloading the jar file to the cache,
|
||||
// start the extraction process:
|
||||
if (mSynchronousRead)
|
||||
rv = OpenJARElement();
|
||||
else
|
||||
rv = AsyncReadJARElement();
|
||||
}
|
||||
else {
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader),
|
||||
mJARBaseURI, this, nsnull, mSynchronousRead,
|
||||
mLoadGroup, mCallbacks, mLoadFlags);
|
||||
|
||||
error:
|
||||
if (NS_FAILED(rv) && mLoadGroup) {
|
||||
nsresult rv2 = mLoadGroup->RemoveRequest(this, nsnull, NS_OK);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv2), "RemoveChannel failed");
|
||||
// if DownloadComplete() was called early, need to release the reference.
|
||||
if (mSynchronousRead && mSynchronousInputStream)
|
||||
mDownloader = 0;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -340,10 +357,12 @@ nsJARChannel::AsyncReadJARElement()
|
|||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: AsyncRead jar entry %s", (const char*)jarURLStr));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: AsyncRead jar entry %s", (const char*)jarURLStr));
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = jarTransport->AsyncRead(this, nsnull, 0, PRUint32(-1), 0,
|
||||
|
@ -566,13 +585,15 @@ nsJARChannel::OnStopRequest(nsIRequest* jarExtractionTransport, nsISupports* con
|
|||
{
|
||||
nsresult rv;
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar extraction complete %s status=%x",
|
||||
(const char*)jarURLStr, aStatus));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar extraction complete %s status=%x",
|
||||
(const char*)jarURLStr, aStatus));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -656,10 +677,12 @@ NS_IMETHODIMP
|
|||
nsJARChannel::GetInputStream(nsIInputStream* *aInputStream)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: GetInputStream jar entry %s", (const char*)jarURLStr));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: GetInputStream jar entry %s", (const char*)jarURLStr));
|
||||
}
|
||||
#endif
|
||||
NS_ENSURE_TRUE(mJAR, NS_ERROR_NULL_POINTER);
|
||||
return mJAR->GetInputStream(mJAREntry, aInputStream);
|
||||
|
|
|
@ -270,16 +270,20 @@ NS_IMETHODIMP
|
|||
nsJARChannel::AsyncOpen(nsIStreamListener* listener, nsISupports* ctxt)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mUserContext = ctxt;
|
||||
mUserListener = listener;
|
||||
mSynchronousRead = PR_FALSE;
|
||||
|
||||
if (mLoadGroup) {
|
||||
rv = mLoadGroup->AddRequest(this, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
mSynchronousRead = PR_FALSE;
|
||||
return EnsureJARFileAvailable();
|
||||
rv = EnsureJARFileAvailable();
|
||||
if (NS_FAILED(rv) && mLoadGroup)
|
||||
mLoadGroup->RemoveRequest(this, nsnull, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -288,30 +292,43 @@ nsJARChannel::EnsureJARFileAvailable()
|
|||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: EnsureJARFileAvailable %s", (const char*)jarURLStr));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: EnsureJARFileAvailable %s", (const char*)jarURLStr));
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = mURI->GetJARFile(getter_AddRefs(mJARBaseURI));
|
||||
if (NS_FAILED(rv)) goto error;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mURI->GetJAREntry(&mJAREntry);
|
||||
if (NS_FAILED(rv)) goto error;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader),
|
||||
mJARBaseURI, this, nsnull, mSynchronousRead,
|
||||
mLoadGroup, mCallbacks, mLoadFlags);
|
||||
// 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(mDownloadedJARFile));
|
||||
}
|
||||
|
||||
// if DownloadComplete() was called early, need to release the reference.
|
||||
if (mSynchronousRead && mSynchronousInputStream)
|
||||
mDownloader = null_nsCOMPtr();
|
||||
if (mDownloadedJARFile) {
|
||||
// after successfully downloading the jar file to the cache,
|
||||
// start the extraction process:
|
||||
if (mSynchronousRead)
|
||||
rv = OpenJARElement();
|
||||
else
|
||||
rv = AsyncReadJARElement();
|
||||
}
|
||||
else {
|
||||
rv = NS_NewDownloader(getter_AddRefs(mDownloader),
|
||||
mJARBaseURI, this, nsnull, mSynchronousRead,
|
||||
mLoadGroup, mCallbacks, mLoadFlags);
|
||||
|
||||
error:
|
||||
if (NS_FAILED(rv) && mLoadGroup) {
|
||||
nsresult rv2 = mLoadGroup->RemoveRequest(this, nsnull, NS_OK);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv2), "RemoveChannel failed");
|
||||
// if DownloadComplete() was called early, need to release the reference.
|
||||
if (mSynchronousRead && mSynchronousInputStream)
|
||||
mDownloader = 0;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -340,10 +357,12 @@ nsJARChannel::AsyncReadJARElement()
|
|||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: AsyncRead jar entry %s", (const char*)jarURLStr));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: AsyncRead jar entry %s", (const char*)jarURLStr));
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = jarTransport->AsyncRead(this, nsnull, 0, PRUint32(-1), 0,
|
||||
|
@ -566,13 +585,15 @@ nsJARChannel::OnStopRequest(nsIRequest* jarExtractionTransport, nsISupports* con
|
|||
{
|
||||
nsresult rv;
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar extraction complete %s status=%x",
|
||||
(const char*)jarURLStr, aStatus));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
nsXPIDLCString jarURLStr;
|
||||
rv = mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: jar extraction complete %s status=%x",
|
||||
(const char*)jarURLStr, aStatus));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -656,10 +677,12 @@ NS_IMETHODIMP
|
|||
nsJARChannel::GetInputStream(nsIInputStream* *aInputStream)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: GetInputStream jar entry %s", (const char*)jarURLStr));
|
||||
if (PR_LOG_TEST(gJarProtocolLog, PR_LOG_DEBUG)) {
|
||||
nsXPIDLCString jarURLStr;
|
||||
mURI->GetSpec(getter_Copies(jarURLStr));
|
||||
PR_LOG(gJarProtocolLog, PR_LOG_DEBUG,
|
||||
("nsJarProtocol: GetInputStream jar entry %s", (const char*)jarURLStr));
|
||||
}
|
||||
#endif
|
||||
NS_ENSURE_TRUE(mJAR, NS_ERROR_NULL_POINTER);
|
||||
return mJAR->GetInputStream(mJAREntry, aInputStream);
|
||||
|
|
|
@ -75,4 +75,9 @@ interface nsIResProtocolHandler : nsIProtocolHandler
|
|||
* Returns true if substitutions are already defined for the specified root.
|
||||
*/
|
||||
boolean hasSubstitutions(in string root);
|
||||
|
||||
/**
|
||||
* Resolution utility function.
|
||||
*/
|
||||
string resolveURI(in nsIURI resourceURI);
|
||||
};
|
||||
|
|
|
@ -31,7 +31,6 @@ LIBRARY_NAME = nkres_s
|
|||
REQUIRES = xpcom string exthandler mimetype
|
||||
|
||||
CPPSRCS = \
|
||||
nsResChannel.cpp \
|
||||
nsResProtocolHandler.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
@ -41,6 +40,10 @@ EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
|
|||
# static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(DEPTH)/netwerk/base/src \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
|
|
|
@ -28,10 +28,13 @@ LIBRARY_NAME=nkres_s
|
|||
LCFLAGS = -DWIN32_LEAN_AND_MEAN -D_IMPL_NS_NET
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsResChannel.obj \
|
||||
.\$(OBJDIR)\nsResProtocolHandler.obj \
|
||||
$(NULL)
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\netwerk\base\src \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
|
|
|
@ -1,651 +0,0 @@
|
|||
/* -*- 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.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsResChannel.h"
|
||||
#include "nsCRT.h"
|
||||
#include "netCore.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIFileTransportService.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsMimeTypes.h"
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
//
|
||||
// Log module for nsResChannel logging...
|
||||
//
|
||||
// To enable logging (see prlog.h for full details):
|
||||
//
|
||||
// set NSPR_LOG_MODULES=nsResChannel:5
|
||||
// set NSPR_LOG_FILE=nspr.log
|
||||
//
|
||||
// this enables PR_LOG_DEBUG level information and places all output in
|
||||
// the file nspr.log
|
||||
PRLogModuleInfo* gResChannelLog = nsnull;
|
||||
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsResChannel::nsResChannel()
|
||||
: mLoadFlags(nsIResChannel::LOAD_NORMAL),
|
||||
mState(QUIESCENT),
|
||||
mStatus(NS_OK)
|
||||
#ifdef DEBUG
|
||||
,mInitiator(nsnull)
|
||||
#endif
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
#if defined(PR_LOGGING)
|
||||
//
|
||||
// Initialize the global PRLogModule for socket transport logging
|
||||
// if necessary...
|
||||
//
|
||||
if (nsnull == gResChannelLog) {
|
||||
gResChannelLog = PR_NewLogModule("nsResChannel");
|
||||
}
|
||||
#endif /* PR_LOGGING */
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResChannel::Init(nsIResProtocolHandler* handler, nsIURI* uri)
|
||||
{
|
||||
mHandler = handler;
|
||||
mResourceURI = uri;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsResChannel::~nsResChannel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsResChannel)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsResChannel)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsResChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIResChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIFileChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIResChannel)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIRequest, nsIResChannel)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIChannel, nsIResChannel)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
|
||||
NS_METHOD
|
||||
nsResChannel::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
|
||||
{
|
||||
nsResChannel* rc = new nsResChannel();
|
||||
if (rc == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(rc);
|
||||
nsresult rv = rc->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(rc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsResChannel::Substitutions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
nsResChannel::Substitutions::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
nsResChannel* channel = GET_SUBSTITUTIONS_CHANNEL(this);
|
||||
|
||||
if (mSubstitutions)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
char* root;
|
||||
rv = channel->mResourceURI->GetHost(&root);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// XXX don't pass null to GetSubstitutions!
|
||||
const char* strRoot = root ? root : "";
|
||||
rv = channel->mHandler->GetSubstitutions(strRoot,
|
||||
getter_AddRefs(mSubstitutions));
|
||||
nsCRT::free(root);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResChannel::Substitutions::Next(char* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsResChannel* channel = GET_SUBSTITUTIONS_CHANNEL(this);
|
||||
|
||||
nsCOMPtr<nsIURI> substURI;
|
||||
rv = mSubstitutions->GetElementAt(mCurrentIndex++, getter_AddRefs(substURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (substURI == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
char* path = nsnull;
|
||||
rv = channel->mResourceURI->GetPath(&path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX this path[0] check is a hack -- it seems to me that GetPath
|
||||
// shouldn't include the leading slash:
|
||||
char* aResolvedURI;
|
||||
rv = substURI->Resolve(path[0] == '/' ? path+1 : path, &aResolvedURI);
|
||||
nsCRT::free(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*result = aResolvedURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIRequest methods:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetName(PRUnichar* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString urlStr;
|
||||
rv = mResourceURI->GetSpec(getter_Copies(urlStr));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsString name;
|
||||
name.AppendWithConversion(urlStr);
|
||||
*result = name.ToNewUnicode();
|
||||
return *result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::IsPending(PRBool *result)
|
||||
{
|
||||
if (mResolvedChannel)
|
||||
return mResolvedChannel->IsPending(result);
|
||||
*result = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetStatus(nsresult *status)
|
||||
{
|
||||
*status = mStatus;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::Cancel(nsresult status)
|
||||
{
|
||||
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mInitiator == PR_CurrentThread(),
|
||||
"wrong thread calling this routine");
|
||||
#endif
|
||||
nsresult rv = NS_OK;
|
||||
if (mResolvedChannel) {
|
||||
rv = mResolvedChannel->Cancel(status);
|
||||
}
|
||||
mStatus = status;
|
||||
mResolvedChannel = nsnull; // remove the resolution
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::Suspend()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mInitiator == PR_CurrentThread(),
|
||||
"wrong thread calling this routine");
|
||||
#endif
|
||||
if (mResolvedChannel)
|
||||
return mResolvedChannel->Suspend();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::Resume()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mInitiator == PR_CurrentThread(),
|
||||
"wrong thread calling this routine");
|
||||
#endif
|
||||
if (mResolvedChannel)
|
||||
return mResolvedChannel->Resume();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIChannel methods:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetOriginalURI(nsIURI* *aURI)
|
||||
{
|
||||
*aURI = mOriginalURI ? mOriginalURI : mResourceURI;
|
||||
NS_ADDREF(*aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::SetOriginalURI(nsIURI* aURI)
|
||||
{
|
||||
mOriginalURI = aURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetURI(nsIURI* *aURI)
|
||||
{
|
||||
if (mResolvedChannel) {
|
||||
return mResolvedChannel->GetURI(aURI);
|
||||
}
|
||||
*aURI = mResourceURI;
|
||||
NS_ADDREF(*aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResChannel::EnsureNextResolvedChannel()
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString resolvedURI;
|
||||
|
||||
nsCOMPtr<nsIIOService> serv(do_GetService(kIOServiceCID, &rv));
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = mSubstitutions.Next(getter_Copies(resolvedURI));
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = serv->NewChannel(resolvedURI, nsnull,
|
||||
getter_AddRefs(mResolvedChannel));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = NS_OK; // returning NS_OK lets us try again
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (mOriginalURI) {
|
||||
rv = mResolvedChannel->SetOriginalURI(mOriginalURI);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
if (mLoadGroup) {
|
||||
rv = mResolvedChannel->SetLoadGroup(mLoadGroup);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
if (mLoadFlags != nsIResChannel::LOAD_NORMAL) {
|
||||
rv = mResolvedChannel->SetLoadFlags(mLoadFlags);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
if (mCallbacks) {
|
||||
rv = mResolvedChannel->SetNotificationCallbacks(mCallbacks);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
#if defined(PR_LOGGING)
|
||||
nsXPIDLCString resURI;
|
||||
(void)mResourceURI->GetSpec(getter_Copies(resURI));
|
||||
PR_LOG(gResChannelLog, PR_LOG_DEBUG,
|
||||
("nsResChannel: resolving %s ",
|
||||
(const char*)resURI));
|
||||
PR_LOG(gResChannelLog, PR_LOG_DEBUG,
|
||||
(" to %s => status %x\n",
|
||||
(const char*)resolvedURI, rv));
|
||||
#endif /* PR_LOGGING */
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::Open(nsIInputStream **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (mResolvedChannel)
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
|
||||
rv = mSubstitutions.Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
do {
|
||||
rv = EnsureNextResolvedChannel();
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
if (mResolvedChannel)
|
||||
rv = mResolvedChannel->Open(result);
|
||||
} while (NS_FAILED(rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXX What does OpenOutputStream mean for a res "channel"
|
||||
#if 0
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::OpenOutputStream(PRUint32 transferOffset, PRUint32 transferCount, nsIOutputStream **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (mResolvedChannel)
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
|
||||
rv = mSubstitutions.Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
do {
|
||||
rv = EnsureNextResolvedChannel();
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
if (mResolvedChannel)
|
||||
rv = mResolvedChannel->OpenOutputStream(transferOffset, transferCount, result);
|
||||
} while (NS_FAILED(rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mInitiator == nsnull || mInitiator == PR_CurrentThread(),
|
||||
"wrong thread calling this routine");
|
||||
mInitiator = PR_CurrentThread();
|
||||
#endif
|
||||
|
||||
switch (mState) {
|
||||
case QUIESCENT:
|
||||
if (mResolvedChannel)
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
|
||||
// first time through
|
||||
rv = mSubstitutions.Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// fall through
|
||||
mState = ASYNC_READ;
|
||||
|
||||
case ASYNC_READ:
|
||||
break;
|
||||
|
||||
default:
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
}
|
||||
NS_ASSERTION(mState == ASYNC_READ, "wrong state");
|
||||
|
||||
mUserContext = ctxt;
|
||||
mUserObserver = listener; // cast back to nsIStreamListener later
|
||||
|
||||
do {
|
||||
rv = EnsureNextResolvedChannel();
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
if (mResolvedChannel)
|
||||
rv = mResolvedChannel->AsyncOpen(this, nsnull);
|
||||
// Later, this AsyncRead will call back our OnStopRequest
|
||||
// method. The action resumes there...
|
||||
} while (NS_FAILED(rv));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
(void)EndRequest(rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetLoadFlags(PRUint32 *aLoadFlags)
|
||||
{
|
||||
*aLoadFlags = mLoadFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::SetLoadFlags(PRUint32 aLoadFlags)
|
||||
{
|
||||
mLoadFlags = aLoadFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetContentType(char * *aContentType)
|
||||
{
|
||||
if (mResolvedChannel)
|
||||
return mResolvedChannel->GetContentType(aContentType);
|
||||
|
||||
// if we have not created a mResolvedChannel, use the mime service
|
||||
nsCOMPtr<nsIMIMEService> MIMEService (do_GetService(NS_MIMESERVICE_CONTRACTID));
|
||||
if (!MIMEService) return NS_ERROR_FAILURE;
|
||||
return MIMEService->GetTypeFromURI(mResourceURI, aContentType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::SetContentType(const char *aContentType)
|
||||
{
|
||||
if (mResolvedChannel)
|
||||
return mResolvedChannel->SetContentType(aContentType);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetContentLength(PRInt32 *aContentLength)
|
||||
{
|
||||
if (mResolvedChannel)
|
||||
return mResolvedChannel->GetContentLength(aContentLength);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::SetContentLength(PRInt32 aContentLength)
|
||||
{
|
||||
NS_NOTREACHED("nsResChannel::SetContentLength");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
*aLoadGroup = mLoadGroup;
|
||||
NS_IF_ADDREF(*aLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
mLoadGroup = aLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetOwner(nsISupports* *aOwner)
|
||||
{
|
||||
*aOwner = mOwner.get();
|
||||
NS_IF_ADDREF(*aOwner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
mOwner = aOwner;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
||||
{
|
||||
*aNotificationCallbacks = mCallbacks.get();
|
||||
NS_IF_ADDREF(*aNotificationCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
mCallbacks = aNotificationCallbacks;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
|
||||
{
|
||||
NS_NOTREACHED("nsResChannel::GetSecurityInfo");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIStreamListener methods:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::OnStartRequest(nsIRequest* request, nsISupports* context)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mInitiator == PR_CurrentThread(),
|
||||
"wrong thread calling this routine");
|
||||
#endif
|
||||
NS_ASSERTION(mUserObserver, "No observer...");
|
||||
return mUserObserver->OnStartRequest(NS_STATIC_CAST(nsIResChannel*, this), mUserContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::OnStopRequest(nsIRequest* request, nsISupports* context,
|
||||
nsresult aStatus)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mInitiator == PR_CurrentThread(),
|
||||
"wrong thread calling this routine");
|
||||
#endif
|
||||
if (NS_FAILED(aStatus) && aStatus != NS_BINDING_ABORTED) {
|
||||
nsCOMPtr<nsIRequest> dummyRequest;
|
||||
|
||||
// if we failed to process this channel, then try the next one:
|
||||
switch (mState) {
|
||||
case ASYNC_READ:
|
||||
return AsyncOpen(GetUserListener(), mUserContext);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return EndRequest(aStatus);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResChannel::EndRequest(nsresult aStatus)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = mUserObserver->OnStopRequest(NS_STATIC_CAST(nsIResChannel*, this),
|
||||
mUserContext, aStatus);
|
||||
#if 0 // we don't add the resource channel to the group (although maybe we should)
|
||||
if (mLoadGroup) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoadGroup->RemoveChannel(this, context, notif);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Release the reference to the consumer stream listener...
|
||||
mUserObserver = 0;
|
||||
mUserContext = 0;
|
||||
mResolvedChannel = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResChannel::OnDataAvailable(nsIRequest* request, nsISupports* context,
|
||||
nsIInputStream *aIStream, PRUint32 aSourceOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mInitiator == PR_CurrentThread(),
|
||||
"wrong thread calling this routine");
|
||||
#endif
|
||||
return GetUserListener()->OnDataAvailable(NS_STATIC_CAST(nsIResChannel*, this),
|
||||
mUserContext, aIStream,
|
||||
aSourceOffset, aLength);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/* void init (in nsIFile file, in long ioFlags, in long perm); */
|
||||
NS_IMETHODIMP nsResChannel::Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIFile file; */
|
||||
NS_IMETHODIMP nsResChannel::GetFile(nsIFile * *result)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = mSubstitutions.Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
do {
|
||||
rv = EnsureNextResolvedChannel();
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
if (mResolvedChannel) {
|
||||
nsCOMPtr<nsIFileChannel> fc(do_QueryInterface(mResolvedChannel));
|
||||
if (fc) {
|
||||
rv = fc->GetFile(getter_AddRefs(file));
|
||||
if (file) {
|
||||
PRBool exists;
|
||||
rv = file->Exists(&exists);
|
||||
if (NS_SUCCEEDED(rv) && exists) {
|
||||
*result = file;
|
||||
NS_ADDREF(*result);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (NS_FAILED(rv));
|
||||
|
||||
*result = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* attribute long ioFlags; */
|
||||
NS_IMETHODIMP nsResChannel::GetIoFlags(PRInt32 *aIoFlags)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
NS_IMETHODIMP nsResChannel::SetIoFlags(PRInt32 aIoFlags)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* attribute long permissions; */
|
||||
NS_IMETHODIMP nsResChannel::GetPermissions(PRInt32 *aPermissions)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
NS_IMETHODIMP nsResChannel::SetPermissions(PRInt32 aPermissions)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
/* -*- 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.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsResChannel_h__
|
||||
#define nsResChannel_h__
|
||||
|
||||
#include "nsIResChannel.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamProvider.h"
|
||||
#include "nsIResProtocolHandler.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoLock.h"
|
||||
#ifdef DEBUG
|
||||
#include "prthread.h"
|
||||
#endif
|
||||
|
||||
class nsResChannel : public nsIResChannel,
|
||||
public nsIFileChannel,
|
||||
public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUEST
|
||||
NS_DECL_NSICHANNEL
|
||||
NS_DECL_NSIFILECHANNEL
|
||||
NS_DECL_NSIRESCHANNEL
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
nsResChannel();
|
||||
virtual ~nsResChannel();
|
||||
|
||||
// Define a Create method to be used with a factory:
|
||||
static NS_METHOD
|
||||
Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult);
|
||||
|
||||
nsresult Init(nsIResProtocolHandler* handler, nsIURI* uri);
|
||||
|
||||
protected:
|
||||
class Substitutions {
|
||||
public:
|
||||
Substitutions() : mCurrentIndex(0) {}
|
||||
~Substitutions() {}
|
||||
|
||||
nsresult Init();
|
||||
nsresult Next(char* *result);
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mResourceURI;
|
||||
nsCOMPtr<nsISupportsArray> mSubstitutions;
|
||||
PRUint32 mCurrentIndex;
|
||||
};
|
||||
friend class Substitutions;
|
||||
|
||||
#define GET_SUBSTITUTIONS_CHANNEL(_this) \
|
||||
((nsResChannel*)((char*)(_this) - offsetof(nsResChannel, mSubstitutions)))
|
||||
|
||||
enum State {
|
||||
QUIESCENT,
|
||||
ASYNC_READ,
|
||||
ASYNC_WRITE
|
||||
};
|
||||
|
||||
nsIStreamListener* GetUserListener() {
|
||||
// this method doesn't addref the listener
|
||||
NS_ASSERTION(mState == ASYNC_READ, "wrong state");
|
||||
// this cast is safe because we set mUserObserver in AsyncRead
|
||||
nsIRequestObserver* obs = mUserObserver;
|
||||
nsIStreamListener* listener = NS_STATIC_CAST(nsIStreamListener*, obs);
|
||||
return listener;
|
||||
}
|
||||
|
||||
nsIStreamProvider* GetUserProvider() {
|
||||
// this method doesn't addref the provider
|
||||
NS_ASSERTION(mState == ASYNC_WRITE, "wrong state");
|
||||
// this cast is safe because we set mUserObserver in AsyncWrite
|
||||
nsIRequestObserver* obs = mUserObserver;
|
||||
nsIStreamProvider* provider = NS_STATIC_CAST(nsIStreamProvider*, obs);
|
||||
return provider;
|
||||
}
|
||||
|
||||
nsresult EnsureNextResolvedChannel();
|
||||
nsresult EndRequest(nsresult aStatus);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCOMPtr<nsIURI> mResourceURI;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
PRUint32 mLoadFlags;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
|
||||
nsCOMPtr<nsIResProtocolHandler> mHandler;
|
||||
nsCOMPtr<nsIChannel> mResolvedChannel;
|
||||
State mState;
|
||||
Substitutions mSubstitutions;
|
||||
nsCOMPtr<nsIRequestObserver> mUserObserver;
|
||||
nsCOMPtr<nsISupports> mUserContext;
|
||||
nsresult mStatus;
|
||||
#ifdef DEBUG
|
||||
PRThread* mInitiator;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // nsResChannel_h__
|
|
@ -19,6 +19,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsResProtocolHandler.h"
|
||||
|
@ -26,25 +27,65 @@
|
|||
#include "nsIURL.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsResChannel.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "prenv.h"
|
||||
#include "prmem.h"
|
||||
#include "prprf.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsResURL : overrides nsStdURL::GetFile to provide nsIFile resolution
|
||||
|
||||
#include "nsStdURL.h"
|
||||
|
||||
class nsResURL : public nsStdURL
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD GetFile(nsIFile **);
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResURL::GetFile(nsIFile **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_TRUE(nsResProtocolHandler::get(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsXPIDLCString spec;
|
||||
rv = nsResProtocolHandler::get()->ResolveURI(this, getter_Copies(spec));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsILocalFile> localFile =
|
||||
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = localFile->SetURL(spec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return CallQueryInterface(localFile, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsResProtocolHandler *nsResProtocolHandler::mGlobalInstance = nsnull;
|
||||
|
||||
nsResProtocolHandler::nsResProtocolHandler()
|
||||
: mLock(nsnull), mSubstitutions(32)
|
||||
: mSubstitutions(32)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
NS_ASSERTION(!mGlobalInstance, "res handler already created!");
|
||||
mGlobalInstance = this;
|
||||
}
|
||||
|
||||
nsResProtocolHandler::~nsResProtocolHandler()
|
||||
{
|
||||
mGlobalInstance = nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -55,14 +96,8 @@ nsResProtocolHandler::SetSpecialDir(const char* rootName, const char* sysDir)
|
|||
rv = NS_GetSpecialDirectory(sysDir, getter_AddRefs(file));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIFileURL> fileURL(do_CreateInstance(kStandardURLCID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = fileURL->SetFile(file);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsXPIDLCString spec;
|
||||
rv = fileURL->GetSpec(getter_Copies(spec));
|
||||
rv = file->GetURL(getter_Copies(spec));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return AppendSubstitution(rootName, spec);
|
||||
|
@ -73,9 +108,8 @@ nsResProtocolHandler::Init()
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
mLock = PR_NewLock();
|
||||
if (mLock == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mIOService = do_GetIOService(&rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// set up initial mappings
|
||||
rv = SetSpecialDir("ProgramDir", NS_OS_CURRENT_PROCESS_DIR);
|
||||
|
@ -121,12 +155,6 @@ nsResProtocolHandler::Init()
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsResProtocolHandler::~nsResProtocolHandler()
|
||||
{
|
||||
if (mLock)
|
||||
PR_DestroyLock(mLock);
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsResProtocolHandler, nsIResProtocolHandler, nsIProtocolHandler, nsISupportsWeakReference)
|
||||
|
||||
NS_METHOD
|
||||
|
@ -179,23 +207,16 @@ nsResProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI,
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIURI> url(do_CreateInstance(kStandardURLCID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsResURL *resURL;
|
||||
NS_NEWXPCOM(resURL, nsResURL);
|
||||
if (!resURL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(resURL);
|
||||
|
||||
if (aBaseURI) {
|
||||
nsXPIDLCString aResolvedURI;
|
||||
rv = aBaseURI->Resolve(aSpec, getter_Copies(aResolvedURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = url->SetSpec(aResolvedURI);
|
||||
} else {
|
||||
rv = url->SetSpec((char*)aSpec);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*result = url;
|
||||
NS_ADDREF(*result);
|
||||
rv = resURL->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aBaseURI);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = CallQueryInterface(resURL, result);
|
||||
NS_RELEASE(resURL);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -203,19 +224,15 @@ NS_IMETHODIMP
|
|||
nsResProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsResChannel* channel;
|
||||
rv = nsResChannel::Create(nsnull, NS_GET_IID(nsIResChannel), (void**)&channel);
|
||||
nsXPIDLCString spec;
|
||||
|
||||
rv = ResolveURI(uri, getter_Copies(spec));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = channel->Init(this, uri);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(channel);
|
||||
return rv;
|
||||
}
|
||||
rv = mIOService->NewChannel(spec, nsnull, result);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*result = (nsIChannel*)(nsIResChannel*)channel;
|
||||
return NS_OK;
|
||||
return (*result)->SetOriginalURI(uri);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -231,12 +248,9 @@ NS_IMETHODIMP
|
|||
nsResProtocolHandler::PrependSubstitution(const char *root, const char *urlStr)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCOMPtr<nsIIOService> ioServ = do_GetIOService(&rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = ioServ->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
rv = mIOService->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCStringKey key(root);
|
||||
|
@ -268,12 +282,9 @@ NS_IMETHODIMP
|
|||
nsResProtocolHandler::AppendSubstitution(const char *root, const char *urlStr)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCOMPtr<nsIIOService> ioServ = do_GetIOService(&rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = ioServ->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
rv = mIOService->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCStringKey key(root);
|
||||
|
@ -324,12 +335,9 @@ NS_IMETHODIMP
|
|||
nsResProtocolHandler::RemoveSubstitution(const char *root, const char *urlStr)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCOMPtr<nsIIOService> ioServ = do_GetIOService(&rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = ioServ->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
rv = mIOService->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCStringKey key(root);
|
||||
|
@ -361,7 +369,6 @@ NS_IMETHODIMP
|
|||
nsResProtocolHandler::GetSubstitutions(const char *root, nsISupportsArray* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCStringKey key(root);
|
||||
nsISupportsArray* strings = (nsISupportsArray*)mSubstitutions.Get(&key);
|
||||
|
@ -382,4 +389,35 @@ nsResProtocolHandler::HasSubstitutions(const char *root, PRBool *result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::ResolveURI(nsIURI *uri, char **result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString host, path;
|
||||
|
||||
rv = uri->GetHost(getter_Copies(host));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = uri->GetPath(getter_Copies(path));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> substitutions;
|
||||
rv = GetSubstitutions(host.get() ?
|
||||
host.get() : "", getter_AddRefs(substitutions));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// always use the first substitution
|
||||
nsCOMPtr<nsIURI> substURI;
|
||||
substitutions->GetElementAt(0, getter_AddRefs(substURI));
|
||||
if (!substURI) return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
rv = substURI->Resolve(path[0] == '/' ? path+1 : path, result);
|
||||
#if 0
|
||||
nsXPIDLCString spec;
|
||||
uri->GetSpec(getter_Copies(spec));
|
||||
printf("%s\n -> %s\n", spec.get(), *result);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
*/
|
||||
|
||||
#ifndef nsResProtocolHandler_h___
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include "nsIResProtocolHandler.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsResProtocolHandler : public nsIResProtocolHandler, public nsSupportsWeakReference
|
||||
|
@ -45,9 +47,13 @@ public:
|
|||
nsresult Init();
|
||||
nsresult SetSpecialDir(const char* rootName, const char* specialDir);
|
||||
|
||||
protected:
|
||||
PRLock* mLock;
|
||||
nsSupportsHashtable mSubstitutions;
|
||||
static nsResProtocolHandler *get() { return mGlobalInstance; }
|
||||
|
||||
private:
|
||||
static nsResProtocolHandler *mGlobalInstance;
|
||||
|
||||
nsSupportsHashtable mSubstitutions;
|
||||
nsCOMPtr<nsIIOService> mIOService;
|
||||
};
|
||||
|
||||
#endif /* nsResProtocolHandler_h___ */
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/* -*- 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.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsResProtocolHandler.h"
|
||||
|
||||
static nsModuleComponentInfo gResComponents[] = {
|
||||
{ "The Resource Protocol Handler",
|
||||
NS_RESPROTOCOLHANDLER_CID,
|
||||
NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "resource",
|
||||
nsResProtocolHandler::Create
|
||||
}
|
||||
2};
|
||||
|
||||
NS_IMPL_NSGETMODULE(res, gResComponents)
|
Загрузка…
Ссылка в новой задаче