зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d8000edd01
Коммит
763317bf92
|
@ -1824,29 +1824,10 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
|
||||||
{
|
{
|
||||||
ForceCompositionEnd();
|
ForceCompositionEnd();
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
PRBool preventDefault;
|
||||||
if (!ps)
|
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
if (NS_FAILED(rv) || preventDefault)
|
||||||
|
return rv;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Clipboard Service
|
// Get Clipboard Service
|
||||||
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
|
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);
|
NS_ENSURE_ARG_POINTER(aCanPaste);
|
||||||
*aCanPaste = PR_FALSE;
|
*aCanPaste = PR_FALSE;
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
nsresult rv = FireClipboardEvent(NS_BEFOREPASTE, aCanPaste);
|
||||||
if (!ps)
|
if (NS_FAILED(rv) || *aCanPaste)
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
return rv;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't paste if readonly
|
// can't paste if readonly
|
||||||
if (!IsModifiable())
|
if (!IsModifiable())
|
||||||
|
|
|
@ -427,29 +427,10 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
|
||||||
{
|
{
|
||||||
ForceCompositionEnd();
|
ForceCompositionEnd();
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
PRBool preventDefault;
|
||||||
if (!ps)
|
nsresult rv = FireClipboardEvent(NS_PASTE, &preventDefault);
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
if (NS_FAILED(rv) || preventDefault)
|
||||||
|
return rv;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Clipboard Service
|
// Get Clipboard Service
|
||||||
nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
|
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);
|
NS_ENSURE_ARG_POINTER(aCanPaste);
|
||||||
*aCanPaste = PR_FALSE;
|
*aCanPaste = PR_FALSE;
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
nsresult rv = FireClipboardEvent(NS_BEFOREPASTE, aCanPaste);
|
||||||
if (!ps)
|
if (NS_FAILED(rv) || *aCanPaste)
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
return rv;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't paste if readonly
|
// can't paste if readonly
|
||||||
if (!IsModifiable())
|
if (!IsModifiable())
|
||||||
|
|
|
@ -1148,25 +1148,50 @@ nsresult nsPlaintextEditor::GetClipboardEventTarget(nsIDOMNode** aEventTarget)
|
||||||
return nsCopySupport::GetClipboardEventTarget(selection, 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);
|
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||||
if (!ps)
|
if (!ps)
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
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;
|
nsCOMPtr<nsIDOMNode> eventTarget;
|
||||||
nsresult rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
|
rv = GetClipboardEventTarget(getter_AddRefs(eventTarget));
|
||||||
// On failure to get event target, just forget about it and don't fire.
|
if (NS_FAILED(rv))
|
||||||
if (NS_SUCCEEDED(rv)) {
|
// On failure to get event target, just forget about it and don't fire.
|
||||||
nsEventStatus status = nsEventStatus_eIgnore;
|
return NS_OK;
|
||||||
nsEvent evt(PR_TRUE, NS_CUT);
|
|
||||||
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
nsnull, &status);
|
nsEvent evt(PR_TRUE, msg);
|
||||||
// if event handler return'd false (PreventDefault)
|
nsEventDispatcher::Dispatch(eventTarget, ps->GetPresContext(), &evt,
|
||||||
if (status == nsEventStatus_eConsumeNoDefault)
|
nsnull, &status);
|
||||||
return NS_OK;
|
// 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;
|
nsCOMPtr<nsISelection> selection;
|
||||||
rv = GetSelection(getter_AddRefs(selection));
|
rv = GetSelection(getter_AddRefs(selection));
|
||||||
|
@ -1177,6 +1202,8 @@ NS_IMETHODIMP nsPlaintextEditor::Cut()
|
||||||
if (NS_SUCCEEDED(selection->GetIsCollapsed(&isCollapsed)) && isCollapsed)
|
if (NS_SUCCEEDED(selection->GetIsCollapsed(&isCollapsed)) && isCollapsed)
|
||||||
return NS_OK; // just return ok so no JS error is thrown
|
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();
|
rv = ps->DoCopy();
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
rv = DeleteSelection(eNone);
|
rv = DeleteSelection(eNone);
|
||||||
|
@ -1188,26 +1215,9 @@ NS_IMETHODIMP nsPlaintextEditor::CanCut(PRBool *aCanCut)
|
||||||
NS_ENSURE_ARG_POINTER(aCanCut);
|
NS_ENSURE_ARG_POINTER(aCanCut);
|
||||||
*aCanCut = PR_FALSE;
|
*aCanCut = PR_FALSE;
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
nsresult rv = FireClipboardEvent(NS_BEFORECUT, aCanCut);
|
||||||
if (!ps)
|
if (NS_FAILED(rv) || *aCanCut)
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
return rv;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISelection> selection;
|
nsCOMPtr<nsISelection> selection;
|
||||||
rv = GetSelection(getter_AddRefs(selection));
|
rv = GetSelection(getter_AddRefs(selection));
|
||||||
|
@ -1223,26 +1233,13 @@ NS_IMETHODIMP nsPlaintextEditor::CanCut(PRBool *aCanCut)
|
||||||
|
|
||||||
NS_IMETHODIMP nsPlaintextEditor::Copy()
|
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);
|
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();
|
return ps->DoCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1251,26 +1248,9 @@ NS_IMETHODIMP nsPlaintextEditor::CanCopy(PRBool *aCanCopy)
|
||||||
NS_ENSURE_ARG_POINTER(aCanCopy);
|
NS_ENSURE_ARG_POINTER(aCanCopy);
|
||||||
*aCanCopy = PR_FALSE;
|
*aCanCopy = PR_FALSE;
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
nsresult rv = FireClipboardEvent(NS_BEFORECOPY, aCanCopy);
|
||||||
if (!ps)
|
if (NS_FAILED(rv) || *aCanCopy)
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
return rv;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISelection> selection;
|
nsCOMPtr<nsISelection> selection;
|
||||||
rv = GetSelection(getter_AddRefs(selection));
|
rv = GetSelection(getter_AddRefs(selection));
|
||||||
|
|
|
@ -216,7 +216,8 @@ protected:
|
||||||
|
|
||||||
// Wrapper for nsCopySupport::GetClipboardEventTarget, finds target to fire
|
// Wrapper for nsCopySupport::GetClipboardEventTarget, finds target to fire
|
||||||
// [cut,copy,paste] and [beforecut,beforecopy,beforepaste] events at.
|
// [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
|
// Data members
|
||||||
protected:
|
protected:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче