Bug 339434: Crash trying to spellcheck in a closed window. Patch by pkasting@google.com. r=brettw, sr=bzbarsky

git-svn-id: svn://10.0.0.236/trunk@203331 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
pamg.bugs%gmail.com 2006-07-21 01:15:57 +00:00
parent 5f7ca2b6d9
commit 22934e7775
3 changed files with 72 additions and 50 deletions

View File

@ -155,6 +155,7 @@ nsEditor::nsEditor()
, mInIMEMode(PR_FALSE)
, mIsIMEComposing(PR_FALSE)
, mShouldTxnSetSelection(PR_TRUE)
, mDidPreDestroy(PR_FALSE)
, mActionListeners(nsnull)
, mEditorObservers(nsnull)
, mDocDirtyState(-1)
@ -216,9 +217,6 @@ nsEditor::~nsEditor()
delete mEditorObservers; // no need to release observers; we didn't addref them
mEditorObservers = 0;
if (mInlineSpellChecker)
mInlineSpellChecker->Cleanup();
if (mActionListeners)
{
PRInt32 i;
@ -455,11 +453,21 @@ nsEditor::RemoveEventListeners()
NS_IMETHODIMP
nsEditor::PreDestroy()
{
// tell our listeners that the doc is going away
NotifyDocumentListeners(eDocumentToBeDestroyed);
if (!mDidPreDestroy) {
// Let spellchecker clean up its observers etc.
if (mInlineSpellChecker) {
mInlineSpellChecker->Cleanup();
mInlineSpellChecker = nsnull;
}
// Unregister event listeners
RemoveEventListeners();
// tell our listeners that the doc is going away
NotifyDocumentListeners(eDocumentToBeDestroyed);
// Unregister event listeners
RemoveEventListeners();
mDidPreDestroy = PR_TRUE;
}
return NS_OK;
}
@ -1258,17 +1266,27 @@ NS_IMETHODIMP nsEditor::GetInlineSpellChecker(PRBool autoCreate,
nsIInlineSpellChecker ** aInlineSpellChecker)
{
NS_ENSURE_ARG_POINTER(aInlineSpellChecker);
nsresult rv;
if (mDidPreDestroy) {
// Don't allow people to get or create the spell checker once the editor
// is going away.
*aInlineSpellChecker = nsnull;
return autoCreate ? NS_ERROR_NOT_AVAILABLE : NS_OK;
}
if (!mInlineSpellChecker && autoCreate) {
nsresult rv;
mInlineSpellChecker = do_CreateInstance(MOZ_INLINESPELLCHECKER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = mInlineSpellChecker->Init(this);
if (NS_FAILED(rv))
mInlineSpellChecker = nsnull;
NS_ENSURE_SUCCESS(rv, rv);
}
NS_IF_ADDREF(*aInlineSpellChecker = mInlineSpellChecker);
NS_IF_ADDREF(*aInlineSpellChecker = mInlineSpellChecker);
return NS_OK;
}

View File

@ -607,7 +607,8 @@ protected:
// This is different from mInIMEMode. see Bug 98434.
PRPackedBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
// various listeners
PRPackedBool mDidPreDestroy; // whether PreDestroy has been called
// various listeners
nsVoidArray* mActionListeners; // listens to all low level actions on the doc
nsVoidArray* mEditorObservers; // just notify once per high level change
nsCOMPtr<nsISupportsArray> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc)

View File

@ -130,7 +130,21 @@ mozInlineSpellChecker::Init(nsIEditor *aEditor)
nsresult mozInlineSpellChecker::Cleanup()
{
return UnregisterEventListeners();
mNumWordsInSpellSelection = 0;
nsCOMPtr<nsISelection> spellCheckSelection;
nsresult rv = GetSpellCheckSelection(getter_AddRefs(spellCheckSelection));
if (NS_FAILED(rv)) {
// Ensure we still unregister event listeners (but return a failure code)
UnregisterEventListeners();
} else {
spellCheckSelection->RemoveAllRanges();
rv = UnregisterEventListeners();
}
mSpellCheck = nsnull;
return rv;
}
// mozInlineSpellChecker::CanEnableInlineSpellChecking
@ -231,54 +245,43 @@ mozInlineSpellChecker::GetEnableRealTimeSpell(PRBool* aEnabled)
NS_IMETHODIMP
mozInlineSpellChecker::SetEnableRealTimeSpell(PRBool aEnabled)
{
nsresult res = NS_OK;
if (!aEnabled) {
return Cleanup();
}
if (aEnabled) {
if (!mSpellCheck) {
nsCOMPtr<nsIEditorSpellCheck> spellchecker = do_CreateInstance("@mozilla.org/editor/editorspellchecker;1", &res);
if (NS_SUCCEEDED(res) && spellchecker)
{
nsCOMPtr<nsITextServicesFilter> filter = do_CreateInstance("@mozilla.org/editor/txtsrvfiltermail;1", &res);
spellchecker->SetFilter(filter);
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
res = spellchecker->InitSpellChecker(editor, PR_FALSE);
NS_ENSURE_SUCCESS(res, res);
if (!mSpellCheck) {
nsresult res = NS_OK;
nsCOMPtr<nsIEditorSpellCheck> spellchecker = do_CreateInstance("@mozilla.org/editor/editorspellchecker;1", &res);
if (NS_SUCCEEDED(res) && spellchecker)
{
nsCOMPtr<nsITextServicesFilter> filter = do_CreateInstance("@mozilla.org/editor/txtsrvfiltermail;1", &res);
spellchecker->SetFilter(filter);
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
res = spellchecker->InitSpellChecker(editor, PR_FALSE);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsITextServicesDocument> tsDoc = do_CreateInstance("@mozilla.org/textservices/textservicesdocument;1", &res);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsITextServicesDocument> tsDoc = do_CreateInstance("@mozilla.org/textservices/textservicesdocument;1", &res);
NS_ENSURE_SUCCESS(res, res);
res = tsDoc->SetFilter(filter);
NS_ENSURE_SUCCESS(res, res);
res = tsDoc->SetFilter(filter);
NS_ENSURE_SUCCESS(res, res);
res = tsDoc->InitWithEditor(editor);
NS_ENSURE_SUCCESS(res, res);
res = tsDoc->InitWithEditor(editor);
NS_ENSURE_SUCCESS(res, res);
mTextServicesDocument = tsDoc;
mSpellCheck = spellchecker;
mTextServicesDocument = tsDoc;
mSpellCheck = spellchecker;
// spell checking is enabled, register our event listeners to track navigation
RegisterEventListeners();
}
// spell checking is enabled, register our event listeners to track navigation
RegisterEventListeners();
}
// spellcheck the current contents. SpellCheckRange doesn't supply a created
// range to DoSpellCheck, which in our case is the entire range. But this
// optimization doesn't matter because there is nothing in the spellcheck
// selection when starting, which triggers a better optimization.
res = SpellCheckRange(nsnull);
}
else
{
nsCOMPtr<nsISelection> spellCheckSelection;
res = GetSpellCheckSelection(getter_AddRefs(spellCheckSelection));
NS_ENSURE_SUCCESS(res, res);
spellCheckSelection->RemoveAllRanges();
mNumWordsInSpellSelection = 0;
UnregisterEventListeners();
mSpellCheck = nsnull;
}
return res;
// spellcheck the current contents. SpellCheckRange doesn't supply a created
// range to DoSpellCheck, which in our case is the entire range. But this
// optimization doesn't matter because there is nothing in the spellcheck
// selection when starting, which triggers a better optimization.
return SpellCheckRange(nsnull);
}
// mozInlineSpellChecker::SpellCheckAfterEditorChange