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;
}
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
nsTextEditorState::PrepareEditor(const nsAString *aValue)
{
@ -1168,12 +1188,14 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
bool shouldInitializeEditor = false;
nsCOMPtr<nsIEditor> 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

View File

@ -104,7 +104,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor)
mEditor = aEditor; // we hold a non-refcounted reference back to our editor
nsCOMPtr<nsISelection> 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

View File

@ -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<nsITextControlElement> 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<nsITextControlElement> 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;
}