зеркало из https://github.com/mozilla/gecko-dev.git
Bug 688208 - Guard against accessing destroyed object [r=mfinkle]
The nsWindow for Android often dispatches events but doesn't check for window destruction afterwards. Ensure that necessary destruction checks and kungFuDeathGrips are in place to avoid accessing a destroyed object.
This commit is contained in:
Родитель
a71ec3750f
Коммит
28e52ff018
|
@ -273,6 +273,8 @@ nsWindow::Create(nsIWidget *aParent,
|
|||
NS_IMETHODIMP
|
||||
nsWindow::Destroy(void)
|
||||
{
|
||||
nsBaseWidget::mOnDestroyCalled = true;
|
||||
|
||||
for (PRUint32 i = 0; i < mChildren.Length(); ++i) {
|
||||
// why do we still have children?
|
||||
ALOG("### Warning: Destroying window %p and reparenting child %p to null!", (void*)this, (void*)mChildren[i]);
|
||||
|
@ -639,7 +641,10 @@ nsWindow::BringToFront()
|
|||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
|
||||
nsWindow *oldTop = nsnull;
|
||||
nsWindow *newTop = this;
|
||||
if (!gTopLevelWindows.IsEmpty())
|
||||
oldTop = gTopLevelWindows[0];
|
||||
|
||||
|
@ -651,11 +656,20 @@ nsWindow::BringToFront()
|
|||
DispatchEvent(&event);
|
||||
}
|
||||
|
||||
nsGUIEvent event(true, NS_ACTIVATE, this);
|
||||
if (Destroyed()) {
|
||||
// somehow the deactivate event handler destroyed this window.
|
||||
// try to recover by grabbing the next window in line and activating
|
||||
// that instead
|
||||
if (gTopLevelWindows.IsEmpty())
|
||||
return;
|
||||
newTop = gTopLevelWindows[0];
|
||||
}
|
||||
|
||||
nsGUIEvent event(true, NS_ACTIVATE, newTop);
|
||||
DispatchEvent(&event);
|
||||
|
||||
// force a window resize
|
||||
nsAppShell::gAppShell->ResendLastResizeEvent(this);
|
||||
nsAppShell::gAppShell->ResendLastResizeEvent(newTop);
|
||||
RedrawAll();
|
||||
}
|
||||
|
||||
|
@ -985,6 +999,7 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
|
|||
if (!mIsVisible)
|
||||
return false;
|
||||
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
nsEventStatus status;
|
||||
nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height);
|
||||
|
||||
|
@ -1247,6 +1262,7 @@ nsWindow::OnSizeChanged(const gfxIntSize& aSize)
|
|||
|
||||
ALOG("nsWindow: %p OnSizeChanged [%d %d]", (void*)this, w, h);
|
||||
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
nsSizeEvent event(true, NS_SIZE, this);
|
||||
InitEvent(event);
|
||||
|
||||
|
@ -1321,6 +1337,7 @@ nsWindow::OnMotionEvent(AndroidGeckoEvent *ae)
|
|||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
nsIntPoint pt(ae->P0());
|
||||
nsIntPoint offset = WidgetToScreenOffset();
|
||||
|
||||
|
@ -1353,6 +1370,8 @@ send_again:
|
|||
// XXX add the double-click handling logic here
|
||||
|
||||
DispatchEvent(&event);
|
||||
if (Destroyed())
|
||||
return;
|
||||
|
||||
if (msg == NS_MOUSE_BUTTON_DOWN) {
|
||||
msg = NS_MOUSE_MOVE;
|
||||
|
@ -1402,7 +1421,10 @@ void nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae)
|
|||
}
|
||||
|
||||
if (!mGestureFinished) {
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
DispatchGestureEvent(msg, 0, pinchDelta, refPoint, ae->Time());
|
||||
if (Destroyed())
|
||||
return;
|
||||
|
||||
// If the cumulative pinch delta goes past the threshold, treat this
|
||||
// as a pinch only, and not a swipe.
|
||||
|
@ -1429,6 +1451,8 @@ void nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae)
|
|||
// Finish the pinch gesture, then fire the swipe event:
|
||||
msg = NS_SIMPLE_GESTURE_MAGNIFY;
|
||||
DispatchGestureEvent(msg, 0, pinchDist - mStartDist, refPoint, ae->Time());
|
||||
if (Destroyed())
|
||||
return;
|
||||
msg = NS_SIMPLE_GESTURE_SWIPE;
|
||||
DispatchGestureEvent(msg, direction, 0, refPoint, ae->Time());
|
||||
|
||||
|
@ -1631,6 +1655,7 @@ nsWindow::InitKeyEvent(nsKeyEvent& event, AndroidGeckoEvent& key)
|
|||
void
|
||||
nsWindow::HandleSpecialKey(AndroidGeckoEvent *ae)
|
||||
{
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
nsCOMPtr<nsIAtom> command;
|
||||
bool isDown = ae->Action() == AndroidKeyEvent::ACTION_DOWN;
|
||||
bool isLongPress = !!(ae->Flags() & AndroidKeyEvent::FLAG_LONG_PRESS);
|
||||
|
@ -1692,6 +1717,7 @@ nsWindow::HandleSpecialKey(AndroidGeckoEvent *ae)
|
|||
void
|
||||
nsWindow::OnKeyEvent(AndroidGeckoEvent *ae)
|
||||
{
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
PRUint32 msg;
|
||||
switch (ae->Action()) {
|
||||
case AndroidKeyEvent::ACTION_DOWN:
|
||||
|
@ -1734,6 +1760,8 @@ nsWindow::OnKeyEvent(AndroidGeckoEvent *ae)
|
|||
InitKeyEvent(event, *ae);
|
||||
DispatchEvent(&event, status);
|
||||
|
||||
if (Destroyed())
|
||||
return;
|
||||
if (!firePress)
|
||||
return;
|
||||
|
||||
|
@ -1781,6 +1809,7 @@ nsWindow::OnIMEAddRange(AndroidGeckoEvent *ae)
|
|||
void
|
||||
nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
|
||||
{
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
switch (ae->Action()) {
|
||||
case AndroidGeckoEvent::IME_COMPOSITION_END:
|
||||
{
|
||||
|
@ -1826,9 +1855,8 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
|
|||
compositionUpdate.data = event.theText;
|
||||
mIMELastDispatchedComposingText = event.theText;
|
||||
DispatchEvent(&compositionUpdate);
|
||||
// XXX We must check whether this widget is destroyed or not
|
||||
// before dispatching next event. However, Android's
|
||||
// nsWindow has never checked it...
|
||||
if (Destroyed())
|
||||
return;
|
||||
}
|
||||
|
||||
ALOGIME("IME: IME_SET_TEXT: l=%u, r=%u",
|
||||
|
@ -1949,6 +1977,8 @@ nsWindow::ResetInputState()
|
|||
|
||||
// Cancel composition on Gecko side
|
||||
if (mIMEComposing) {
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
|
||||
nsTextEvent textEvent(true, NS_TEXT_TEXT, this);
|
||||
InitEvent(textEvent, nsnull);
|
||||
textEvent.theText = mIMEComposingText;
|
||||
|
@ -2003,6 +2033,8 @@ nsWindow::CancelIMEComposition()
|
|||
|
||||
// Cancel composition on Gecko side
|
||||
if (mIMEComposing) {
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
|
||||
nsTextEvent textEvent(true, NS_TEXT_TEXT, this);
|
||||
InitEvent(textEvent, nsnull);
|
||||
DispatchEvent(&textEvent);
|
||||
|
@ -2043,6 +2075,7 @@ nsWindow::OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd)
|
|||
// The more efficient way would have been passing the substring from index
|
||||
// aStart to index aNewEnd
|
||||
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
nsQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, this);
|
||||
InitEvent(event, nsnull);
|
||||
event.InitForQueryTextContent(0, PR_UINT32_MAX);
|
||||
|
@ -2063,6 +2096,7 @@ nsWindow::OnIMESelectionChange(void)
|
|||
{
|
||||
ALOGIME("IME: OnIMESelectionChange");
|
||||
|
||||
nsRefPtr<nsWindow> kungFuDeathGrip(this);
|
||||
nsQueryContentEvent event(true, NS_QUERY_SELECTED_TEXT, this);
|
||||
InitEvent(event, nsnull);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче