Make sure to catch error messages returned by nsCompontentManagerImpl::CreateInstance when creating a dtd ( CNavDTD ). This fixes a shutdown crash. r=timeless, sr=heikki, a=asa

This commit is contained in:
harishd@netscape.com
2002-12-06 01:54:39 +00:00
parent 43b4d667ac
commit c0bdd46a84
8 changed files with 204 additions and 156 deletions

View File

@@ -123,22 +123,9 @@ public:
CSharedParserObjects()
:mDTDDeque(0),
mHasViewSourceDTD(PR_FALSE),
mHasXMLDTD(PR_FALSE)
mHasXMLDTD(PR_FALSE)
{
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
nsIDTD* theDTD;
NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
// please handle allocation failure
NS_ASSERTION(theDTD, "Failed to create DTD");
mDTDDeque.Push(theDTD);
mHasViewSourceDTD=PR_FALSE;
mHasXMLDTD=PR_FALSE;
// do nothing.
}
~CSharedParserObjects() {
@@ -146,17 +133,31 @@ public:
mDTDDeque.ForEach(theDeallocator); //release all the DTD's
}
void RegisterDTD(nsIDTD* aDTD){
if(aDTD) {
NS_ADDREF(aDTD);
CDTDFinder theFinder(aDTD);
if(!mDTDDeque.FirstThat(theFinder)) {
nsIDTD* theDTD;
aDTD->CreateNewInstance(&theDTD);
mDTDDeque.Push(theDTD);
}
NS_RELEASE(aDTD);
nsresult Init() {
//Note: To cut down on startup time/overhead, we defer the construction of non-html DTD's.
nsIDTD* theDTD = 0;
nsresult rv = NS_NewNavHTMLDTD(&theDTD); //do this as a default HTML DTD...
NS_ASSERTION(theDTD, "Failed to create DTD");
NS_ENSURE_SUCCESS(rv, rv);
mDTDDeque.Push(theDTD);
mHasViewSourceDTD = PR_FALSE;
mHasXMLDTD = PR_FALSE;
return NS_OK;
}
nsresult RegisterDTD(nsIDTD* aDTD) {
NS_ENSURE_ARG_POINTER(aDTD);
nsCOMPtr<nsIDTD> dtd(aDTD);
CDTDFinder theFinder(dtd);
if (!mDTDDeque.FirstThat(theFinder)) {
nsIDTD* theDTD;
nsresult rv = dtd->CreateNewInstance(&theDTD);
NS_ENSURE_SUCCESS(rv, rv);
mDTDDeque.Push(theDTD);
}
return NS_OK;
}
nsDeque mDTDDeque;
@@ -262,11 +263,16 @@ static CSharedParserObjects* gSharedParserObjects=0;
//-------------------------------------------------------------------------
CSharedParserObjects& GetSharedObjects() {
nsresult
GetSharedObjects(CSharedParserObjects** aSharedParserObjects) {
if (!gSharedParserObjects) {
gSharedParserObjects = new CSharedParserObjects();
NS_ENSURE_TRUE(gSharedParserObjects, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = gSharedParserObjects->Init();
NS_ENSURE_SUCCESS(rv, rv);
}
return *gSharedParserObjects;
*aSharedParserObjects = gSharedParserObjects;
return NS_OK;
}
/**
@@ -551,9 +557,12 @@ nsIContentSink* nsParser::GetContentSink(void){
* @param aDTD is the object to be registered.
* @return nothing.
*/
void nsParser::RegisterDTD(nsIDTD* aDTD){
CSharedParserObjects& theShare=GetSharedObjects();
theShare.RegisterDTD(aDTD);
nsresult
nsParser::RegisterDTD(nsIDTD* aDTD){
CSharedParserObjects* sharedObjects;
nsresult rv = GetSharedObjects(&sharedObjects);
NS_ENSURE_SUCCESS(rv, rv);
return sharedObjects->RegisterDTD(aDTD);
}
/**
@@ -1130,59 +1139,72 @@ void DetermineParseMode(const nsString& aBuffer,
* @return
*/
static
PRBool FindSuitableDTD(CParserContext& aParserContext,
const nsString& aBuffer)
nsresult
FindSuitableDTD(CParserContext& aParserContext,
const nsString& aBuffer,
PRBool* aReturn)
{
*aReturn = PR_FALSE;
//Let's start by trying the defaultDTD, if one exists...
if(aParserContext.mDTD)
if(aParserContext.mDTD->CanParse(aParserContext,aBuffer,0))
return PR_TRUE;
CSharedParserObjects& gSharedObjects=GetSharedObjects();
CSharedParserObjects* sharedObjects;
nsresult rv = GetSharedObjects(&sharedObjects);
NS_ENSURE_SUCCESS(rv, rv);
aParserContext.mAutoDetectStatus=eUnknownDetect;
PRInt32 theDTDIndex=0;
nsIDTD* theBestDTD=0;
nsIDTD* theDTD=0;
PRBool thePrimaryFound=PR_FALSE;
aParserContext.mAutoDetectStatus = eUnknownDetect;
PRInt32 theDTDIndex = 0;
nsIDTD* theBestDTD = 0;
nsIDTD* theDTD = 0;
PRBool thePrimaryFound = PR_FALSE;
while((theDTDIndex<=gSharedObjects.mDTDDeque.GetSize()) && (aParserContext.mAutoDetectStatus!=ePrimaryDetect)){
theDTD=(nsIDTD*)gSharedObjects.mDTDDeque.ObjectAt(theDTDIndex++);
if(theDTD) {
while ((theDTDIndex <= sharedObjects->mDTDDeque.GetSize()) &&
(aParserContext.mAutoDetectStatus != ePrimaryDetect)){
theDTD = NS_STATIC_CAST(nsIDTD*, sharedObjects->mDTDDeque.ObjectAt(theDTDIndex++));
if (theDTD) {
// Store detect status in temp ( theResult ) to avoid bugs such as
// 36233, 36754, 36491, 36323. Basically, we should avoid calling DTD's
// WillBuildModel() multiple times, i.e., we shouldn't leave auto-detect-status
// unknown.
eAutoDetectResult theResult=theDTD->CanParse(aParserContext,aBuffer,0);
if(eValidDetect==theResult){
aParserContext.mAutoDetectStatus=eValidDetect;
theBestDTD=theDTD;
eAutoDetectResult theResult = theDTD->CanParse(aParserContext,aBuffer,0);
if (eValidDetect == theResult){
aParserContext.mAutoDetectStatus = eValidDetect;
theBestDTD = theDTD;
}
else if(ePrimaryDetect==theResult) {
theBestDTD=theDTD;
thePrimaryFound=PR_TRUE;
aParserContext.mAutoDetectStatus=ePrimaryDetect;
else if (ePrimaryDetect == theResult) {
theBestDTD = theDTD;
thePrimaryFound = PR_TRUE;
aParserContext.mAutoDetectStatus = ePrimaryDetect;
}
}
if((theDTDIndex==gSharedObjects.mDTDDeque.GetSize()) && (!thePrimaryFound)) {
if(!gSharedObjects.mHasXMLDTD) {
NS_NewExpatDriver(&theDTD); //do this to view XML files...
gSharedObjects.mDTDDeque.Push(theDTD);
gSharedObjects.mHasXMLDTD=PR_TRUE;
if (theDTDIndex == sharedObjects->mDTDDeque.GetSize() && !thePrimaryFound) {
if (!sharedObjects->mHasXMLDTD) {
rv = NS_NewExpatDriver(&theDTD); //do this to view XML files...
NS_ENSURE_SUCCESS(rv, rv);
sharedObjects->mDTDDeque.Push(theDTD);
sharedObjects->mHasXMLDTD = PR_TRUE;
}
else if(!gSharedObjects.mHasViewSourceDTD) {
NS_NewViewSourceHTML(&theDTD); //do this so all non-html files can be viewed...
gSharedObjects.mDTDDeque.Push(theDTD);
gSharedObjects.mHasViewSourceDTD=PR_TRUE;
else if (!sharedObjects->mHasViewSourceDTD) {
rv = NS_NewViewSourceHTML(&theDTD); //do this so all non-html files can be viewed...
NS_ENSURE_SUCCESS(rv, rv);
sharedObjects->mDTDDeque.Push(theDTD);
sharedObjects->mHasViewSourceDTD = PR_TRUE;
}
}
}
if(theBestDTD) {
theBestDTD->CreateNewInstance(&aParserContext.mDTD);
return PR_TRUE;
rv = theBestDTD->CreateNewInstance(&aParserContext.mDTD);
NS_ENSURE_SUCCESS(rv, rv);
*aReturn = PR_TRUE;
}
return PR_FALSE;
return rv;
}
NS_IMETHODIMP
@@ -1214,7 +1236,8 @@ nsParser::CancelParsingEvents() {
* can delay until the last moment the resolution of
* which DTD to use (unless of course we're assigned one).
*/
nsresult nsParser::WillBuildModel(nsString& aFilename)
nsresult
nsParser::WillBuildModel(nsString& aFilename)
{
if (!mParserContext)
return kInvalidParserContext;
@@ -1230,9 +1253,12 @@ nsresult nsParser::WillBuildModel(nsString& aFilename)
eDTDMode_autodetect == mParserContext->mDTDMode)
DetermineParseMode(theBuffer, mParserContext->mDTDMode,
mParserContext->mDocType, mParserContext->mMimeType);
PRBool found;
nsresult rv = FindSuitableDTD(*mParserContext,theBuffer, &found);
NS_ENSURE_SUCCESS(rv, rv);
if (!FindSuitableDTD(*mParserContext,theBuffer))
return NS_OK;
if (!found)
return rv;
nsITokenizer* tokenizer;
mParserContext->GetTokenizer(mParserContext->mDTD->GetType(), tokenizer);
@@ -1715,7 +1741,7 @@ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk, PRBo
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: nsParser::ResumeParse(), this=%p\n", this));
MOZ_TIMER_START(mParseTime);
result=WillBuildModel(mParserContext->mScanner->GetFilename());
result = WillBuildModel(mParserContext->mScanner->GetFilename());
if (NS_FAILED(result)) {
mFlags &= ~NS_PARSER_FLAG_CAN_TOKENIZE;
return result;