From efe22ceaf9f10e1b6346b07f2eff07a47f96343e Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Sat, 20 Oct 2012 21:48:34 +0300 Subject: [PATCH] Bug 802985, PreDestroy editor, r=ehsan --- .../html/content/src/nsTextEditorState.cpp | 24 +++++- editor/libeditor/text/nsTextEditRules.cpp | 2 +- layout/forms/nsTextControlFrame.cpp | 79 ++++++++++--------- 3 files changed, 66 insertions(+), 39 deletions(-) diff --git a/content/html/content/src/nsTextEditorState.cpp b/content/html/content/src/nsTextEditorState.cpp index 5181d7cf882..b2afb2e63a3 100644 --- a/content/html/content/src/nsTextEditorState.cpp +++ b/content/html/content/src/nsTextEditorState.cpp @@ -1122,6 +1122,26 @@ nsTextEditorState::BindToFrame(nsTextControlFrame* aFrame) return NS_OK; } +struct PreDestroyer +{ + void Init(nsIEditor* aEditor) + { + mNewEditor = aEditor; + } + ~PreDestroyer() + { + if (mNewEditor) { + mNewEditor->PreDestroy(true); + } + } + void Swap(nsCOMPtr& aEditor) + { + return mNewEditor.swap(aEditor); + } +private: + nsCOMPtr mNewEditor; +}; + nsresult nsTextEditorState::PrepareEditor(const nsAString *aValue) { @@ -1168,12 +1188,14 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue) bool shouldInitializeEditor = false; nsCOMPtr newEditor; // the editor that we might create nsresult rv = NS_OK; + PreDestroyer preDestroyer; if (!mEditor) { shouldInitializeEditor = true; // Create an editor newEditor = do_CreateInstance(kTextEditorCID, &rv); NS_ENSURE_SUCCESS(rv, rv); + preDestroyer.Init(newEditor); // Make sure we clear out the non-breaking space before we initialize the editor rv = mBoundFrame->UpdateValueDisplay(false, true); @@ -1302,7 +1324,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue) if (shouldInitializeEditor) { // Hold on to the newly created editor - mEditor = newEditor; + preDestroyer.Swap(mEditor); } // If we have a default value, insert it under the div we created diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index bda1d0f4230..0d7ba3a22e5 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -104,7 +104,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor) mEditor = aEditor; // we hold a non-refcounted reference back to our editor nsCOMPtr selection; mEditor->GetSelection(getter_AddRefs(selection)); - NS_ASSERTION(selection, "editor cannot get selection"); + NS_WARN_IF_FALSE(selection, "editor cannot get selection"); // Put in a magic br if needed. This method handles null selection, // which should never happen anyway diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index c5d823939de..bdc3747402e 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -296,50 +296,53 @@ nsTextControlFrame::EnsureEditorInitialized() // Make sure that editor init doesn't do things that would kill us off // (especially off the script blockers it'll create for its DOM mutations). - nsAutoScriptBlocker scriptBlocker; + { + nsAutoScriptBlocker scriptBlocker; - // Time to mess with our security context... See comments in GetValue() - // for why this is needed. - nsCxPusher pusher; - pusher.PushNull(); + // Time to mess with our security context... See comments in GetValue() + // for why this is needed. + nsCxPusher pusher; + pusher.PushNull(); - // Make sure that we try to focus the content even if the method fails - class EnsureSetFocus { - public: - explicit EnsureSetFocus(nsTextControlFrame* aFrame) - : mFrame(aFrame) {} - ~EnsureSetFocus() { - if (nsContentUtils::IsFocusedContent(mFrame->GetContent())) - mFrame->SetFocus(true, false); - } - private: - nsTextControlFrame *mFrame; - }; - EnsureSetFocus makeSureSetFocusHappens(this); + // Make sure that we try to focus the content even if the method fails + class EnsureSetFocus { + public: + explicit EnsureSetFocus(nsTextControlFrame* aFrame) + : mFrame(aFrame) {} + ~EnsureSetFocus() { + if (nsContentUtils::IsFocusedContent(mFrame->GetContent())) + mFrame->SetFocus(true, false); + } + private: + nsTextControlFrame *mFrame; + }; + EnsureSetFocus makeSureSetFocusHappens(this); #ifdef DEBUG - // Make sure we are not being called again until we're finished. - // If reentrancy happens, just pretend that we don't have an editor. - const EditorInitializerEntryTracker tracker(*this); - NS_ASSERTION(!tracker.EnteredMoreThanOnce(), - "EnsureEditorInitialized has been called while a previous call was in progress"); + // Make sure we are not being called again until we're finished. + // If reentrancy happens, just pretend that we don't have an editor. + const EditorInitializerEntryTracker tracker(*this); + NS_ASSERTION(!tracker.EnteredMoreThanOnce(), + "EnsureEditorInitialized has been called while a previous call was in progress"); #endif - // Create an editor for the frame, if one doesn't already exist - nsCOMPtr txtCtrl = do_QueryInterface(GetContent()); - NS_ASSERTION(txtCtrl, "Content not a text control element"); - nsresult rv = txtCtrl->CreateEditor(); - NS_ENSURE_SUCCESS(rv, rv); + // Create an editor for the frame, if one doesn't already exist + nsCOMPtr txtCtrl = do_QueryInterface(GetContent()); + NS_ASSERTION(txtCtrl, "Content not a text control element"); + nsresult rv = txtCtrl->CreateEditor(); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_STATE(weakFrame.IsAlive()); - // Turn on mUseEditor so that subsequent calls will use the - // editor. - mUseEditor = true; + // Turn on mUseEditor so that subsequent calls will use the + // editor. + mUseEditor = true; - // Set the selection to the beginning of the text field. - if (weakFrame.IsAlive()) { - SetSelectionEndPoints(0, 0); + // Set the selection to the beginning of the text field. + if (weakFrame.IsAlive()) { + SetSelectionEndPoints(0, 0); + } } - + NS_ENSURE_STATE(weakFrame.IsAlive()); return NS_OK; } @@ -1089,8 +1092,10 @@ nsTextControlFrame::GetSelectionRange(int32_t* aSelectionStart, return NS_OK; } - nsContentUtils::GetSelectionInTextControl(typedSel, - GetRootNodeAndInitializeEditor(), *aSelectionStart, *aSelectionEnd); + mozilla::dom::Element* root = GetRootNodeAndInitializeEditor(); + NS_ENSURE_STATE(root); + nsContentUtils::GetSelectionInTextControl(typedSel, root, + *aSelectionStart, *aSelectionEnd); return NS_OK; }