Bug 802985, PreDestroy editor, r=ehsan

This commit is contained in:
Olli Pettay 2012-10-20 21:48:34 +03:00
parent e86cd8818c
commit efe22ceaf9
3 changed files with 66 additions and 39 deletions

View File

@ -1122,6 +1122,26 @@ nsTextEditorState::BindToFrame(nsTextControlFrame* aFrame)
return NS_OK; return NS_OK;
} }
struct PreDestroyer
{
void Init(nsIEditor* aEditor)
{
mNewEditor = aEditor;
}
~PreDestroyer()
{
if (mNewEditor) {
mNewEditor->PreDestroy(true);
}
}
void Swap(nsCOMPtr<nsIEditor>& aEditor)
{
return mNewEditor.swap(aEditor);
}
private:
nsCOMPtr<nsIEditor> mNewEditor;
};
nsresult nsresult
nsTextEditorState::PrepareEditor(const nsAString *aValue) nsTextEditorState::PrepareEditor(const nsAString *aValue)
{ {
@ -1168,12 +1188,14 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
bool shouldInitializeEditor = false; bool shouldInitializeEditor = false;
nsCOMPtr<nsIEditor> newEditor; // the editor that we might create nsCOMPtr<nsIEditor> newEditor; // the editor that we might create
nsresult rv = NS_OK; nsresult rv = NS_OK;
PreDestroyer preDestroyer;
if (!mEditor) { if (!mEditor) {
shouldInitializeEditor = true; shouldInitializeEditor = true;
// Create an editor // Create an editor
newEditor = do_CreateInstance(kTextEditorCID, &rv); newEditor = do_CreateInstance(kTextEditorCID, &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
preDestroyer.Init(newEditor);
// Make sure we clear out the non-breaking space before we initialize the editor // Make sure we clear out the non-breaking space before we initialize the editor
rv = mBoundFrame->UpdateValueDisplay(false, true); rv = mBoundFrame->UpdateValueDisplay(false, true);
@ -1302,7 +1324,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
if (shouldInitializeEditor) { if (shouldInitializeEditor) {
// Hold on to the newly created editor // 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 // If we have a default value, insert it under the div we created

View File

@ -104,7 +104,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor)
mEditor = aEditor; // we hold a non-refcounted reference back to our editor mEditor = aEditor; // we hold a non-refcounted reference back to our editor
nsCOMPtr<nsISelection> selection; nsCOMPtr<nsISelection> selection;
mEditor->GetSelection(getter_AddRefs(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, // Put in a magic br if needed. This method handles null selection,
// which should never happen anyway // which should never happen anyway

View File

@ -296,50 +296,53 @@ nsTextControlFrame::EnsureEditorInitialized()
// Make sure that editor init doesn't do things that would kill us off // 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). // (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() // Time to mess with our security context... See comments in GetValue()
// for why this is needed. // for why this is needed.
nsCxPusher pusher; nsCxPusher pusher;
pusher.PushNull(); pusher.PushNull();
// Make sure that we try to focus the content even if the method fails // Make sure that we try to focus the content even if the method fails
class EnsureSetFocus { class EnsureSetFocus {
public: public:
explicit EnsureSetFocus(nsTextControlFrame* aFrame) explicit EnsureSetFocus(nsTextControlFrame* aFrame)
: mFrame(aFrame) {} : mFrame(aFrame) {}
~EnsureSetFocus() { ~EnsureSetFocus() {
if (nsContentUtils::IsFocusedContent(mFrame->GetContent())) if (nsContentUtils::IsFocusedContent(mFrame->GetContent()))
mFrame->SetFocus(true, false); mFrame->SetFocus(true, false);
} }
private: private:
nsTextControlFrame *mFrame; nsTextControlFrame *mFrame;
}; };
EnsureSetFocus makeSureSetFocusHappens(this); EnsureSetFocus makeSureSetFocusHappens(this);
#ifdef DEBUG #ifdef DEBUG
// Make sure we are not being called again until we're finished. // Make sure we are not being called again until we're finished.
// If reentrancy happens, just pretend that we don't have an editor. // If reentrancy happens, just pretend that we don't have an editor.
const EditorInitializerEntryTracker tracker(*this); const EditorInitializerEntryTracker tracker(*this);
NS_ASSERTION(!tracker.EnteredMoreThanOnce(), NS_ASSERTION(!tracker.EnteredMoreThanOnce(),
"EnsureEditorInitialized has been called while a previous call was in progress"); "EnsureEditorInitialized has been called while a previous call was in progress");
#endif #endif
// Create an editor for the frame, if one doesn't already exist // Create an editor for the frame, if one doesn't already exist
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
NS_ASSERTION(txtCtrl, "Content not a text control element"); NS_ASSERTION(txtCtrl, "Content not a text control element");
nsresult rv = txtCtrl->CreateEditor(); nsresult rv = txtCtrl->CreateEditor();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(weakFrame.IsAlive());
// Turn on mUseEditor so that subsequent calls will use the // Turn on mUseEditor so that subsequent calls will use the
// editor. // editor.
mUseEditor = true; mUseEditor = true;
// Set the selection to the beginning of the text field. // Set the selection to the beginning of the text field.
if (weakFrame.IsAlive()) { if (weakFrame.IsAlive()) {
SetSelectionEndPoints(0, 0); SetSelectionEndPoints(0, 0);
}
} }
NS_ENSURE_STATE(weakFrame.IsAlive());
return NS_OK; return NS_OK;
} }
@ -1089,8 +1092,10 @@ nsTextControlFrame::GetSelectionRange(int32_t* aSelectionStart,
return NS_OK; return NS_OK;
} }
nsContentUtils::GetSelectionInTextControl(typedSel, mozilla::dom::Element* root = GetRootNodeAndInitializeEditor();
GetRootNodeAndInitializeEditor(), *aSelectionStart, *aSelectionEnd); NS_ENSURE_STATE(root);
nsContentUtils::GetSelectionInTextControl(typedSel, root,
*aSelectionStart, *aSelectionEnd);
return NS_OK; return NS_OK;
} }