Bug 396108 - Crash [@ PresShell::ResizeReflow] with iframes, binding, while onbeforecopy removing stuff, patch by Mathieu Fenniak, r=Olli.Pettay, sr=jst, a=jonas

This commit is contained in:
martijn.martijn@gmail.com 2007-09-29 10:56:04 -07:00
Родитель d8000edd01
Коммит 763317bf92
4 изменённых файлов: 68 добавлений и 159 удалений

Просмотреть файл

@ -1824,29 +1824,10 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
{
ForceCompositionEnd();
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the paste event.
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_PASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
// Did the event handler cause the editor to be destroyed?
// (ie. the input element was removed from the document)
// Don't proceed with paste.
if (mDidPreDestroy)
return NS_OK;
}
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
// Get Clipboard Service
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
@ -1959,26 +1940,9 @@ NS_IMETHODIMP nsHTMLEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPaste)
NS_ENSURE_ARG_POINTER(aCanPaste);
*aCanPaste = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforepaste event. If the event handler requests to prevent
// default behavior, set *aCanPaste = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFOREPASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanPaste = PR_TRUE;
return NS_OK;
}
}
nsresult rv = FireClipboardEvent(NS_BEFOREPASTE, aCanPaste);
if (NS_FAILED(rv) || *aCanPaste)
return rv;
// can't paste if readonly
if (!IsModifiable())

Просмотреть файл

@ -427,29 +427,10 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
{
ForceCompositionEnd();
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the paste event.
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_PASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
// Did the event handler cause the editor to be destroyed?
// (ie. the input element was removed from the document)
// Don't proceed with paste, as it will crash.
if (mDidPreDestroy)
return NS_OK;
}
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
// Get Clipboard Service
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
@ -483,26 +464,9 @@ NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPa
NS_ENSURE_ARG_POINTER(aCanPaste);
*aCanPaste = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforepaste event. If the event handler requests to prevent
// default behavior, set *aCanPaste = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFOREPASTE);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanPaste = PR_TRUE;
return NS_OK;
}
}
nsresult rv = FireClipboardEvent(NS_BEFOREPASTE, aCanPaste);
if (NS_FAILED(rv) || *aCanPaste)
return rv;
// can't paste if readonly
if (!IsModifiable())

Просмотреть файл

@ -1148,25 +1148,50 @@ nsresult nsPlaintextEditor::GetClipboardEventTarget(nsIDOMNode** aEventTarget)
return nsCopySupport::GetClipboardEventTarget(selection, aEventTarget);
}
NS_IMETHODIMP nsPlaintextEditor::Cut()
nsresult nsPlaintextEditor::FireClipboardEvent(PRUint32 msg,
PRBool* aPreventDefault)
{
*aPreventDefault = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the cut event.
// Unsafe to fire event during reflow (bug 396108)
PRBool isReflowing = PR_TRUE;
nsresult rv = ps->IsReflowLocked(&isReflowing);
if (NS_FAILED(rv) || isReflowing)
return NS_OK;
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_CUT);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
}
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
if (NS_FAILED(rv))
// On failure to get event target, just forget about it and don't fire.
return NS_OK;
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, msg);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
*aPreventDefault = PR_TRUE;
// Did the event handler cause the editor to be destroyed? (ie. the input
// element was removed from the document) Don't proceed with command,
// could crash, definitely does during paste.
if (mDidPreDestroy)
return NS_ERROR_NOT_INITIALIZED;
return NS_OK;
}
NS_IMETHODIMP nsPlaintextEditor::Cut()
{
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_CUT, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
@ -1177,6 +1202,8 @@ NS_IMETHODIMP nsPlaintextEditor::Cut()
if (NS_SUCCEEDED(selection->GetIsCollapsed(&isCollapsed)) && isCollapsed)
return NS_OK; // just return ok so no JS error is thrown
// ps should be guaranteed by FireClipboardEvent not failing
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
rv = ps->DoCopy();
if (NS_SUCCEEDED(rv))
rv = DeleteSelection(eNone);
@ -1188,26 +1215,9 @@ NS_IMETHODIMP nsPlaintextEditor::CanCut(PRBool *aCanCut)
NS_ENSURE_ARG_POINTER(aCanCut);
*aCanCut = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforecut event. If the event handler requests to prevent
// default behavior, set *aCanCut = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFORECUT);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanCut = PR_TRUE;
return NS_OK;
}
}
nsresult rv = FireClipboardEvent(NS_BEFORECUT, aCanCut);
if (NS_FAILED(rv) || *aCanCut)
return rv;
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));
@ -1223,26 +1233,13 @@ NS_IMETHODIMP nsPlaintextEditor::CanCut(PRBool *aCanCut)
NS_IMETHODIMP nsPlaintextEditor::Copy()
{
PRBool preventDefault;
nsresult rv = FireClipboardEvent(NS_COPY, &preventDefault);
if (NS_FAILED(rv) || preventDefault)
return rv;
// ps should be guaranteed by FireClipboardEvent not failing
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the copy event.
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_COPY);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault)
return NS_OK;
// the affect of the event handler closing the window here has been
// tested, it works without crashes.
}
return ps->DoCopy();
}
@ -1251,26 +1248,9 @@ NS_IMETHODIMP nsPlaintextEditor::CanCopy(PRBool *aCanCopy)
NS_ENSURE_ARG_POINTER(aCanCopy);
*aCanCopy = PR_FALSE;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps)
return NS_ERROR_NOT_INITIALIZED;
// Fire the beforecopy event. If the event handler requests to prevent
// default behavior, set *aCopyable = true. (IE-style behavior)
nsCOMPtr<nsIDOMNode> eventTarget;
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
// On failure to get event target, just forget about it and don't fire.
if (NS_SUCCEEDED(rv)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent evt(PR_TRUE, NS_BEFORECOPY);
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
nsnull, &status);
// if event handler return'd false (PreventDefault)
if (status == nsEventStatus_eConsumeNoDefault) {
*aCanCopy = PR_TRUE;
return NS_OK;
}
}
nsresult rv = FireClipboardEvent(NS_BEFORECOPY, aCanCopy);
if (NS_FAILED(rv) || *aCanCopy)
return rv;
nsCOMPtr<nsISelection> selection;
rv = GetSelection(getter_AddRefs(selection));

Просмотреть файл

@ -216,7 +216,8 @@ protected:
// Wrapper for nsCopySupport::GetClipboardEventTarget, finds target to fire
// [cut,copy,paste] and [beforecut,beforecopy,beforepaste] events at.
virtual nsresult GetClipboardEventTarget(nsIDOMNode** aEventTarget);
nsresult GetClipboardEventTarget(nsIDOMNode** aEventTarget);
nsresult FireClipboardEvent(PRUint32 msg, PRBool* aPreventDefault);
// Data members
protected: