Bug 779572: Properly protect state in AsyncPanZoomController with a monitor r=cjones

This commit is contained in:
Doug Sherk 2012-08-07 18:51:13 -07:00
parent 4a69c27626
commit 763a1114a3
2 changed files with 36 additions and 11 deletions

View File

@ -243,12 +243,15 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
ScheduleComposite();
// Fall through.
case FLING:
CancelAnimation();
{
MonitorAutoLock monitor(mMonitor);
CancelAnimation();
}
// Fall through.
case NOTHING:
mX.StartTouch(xPos);
mY.StartTouch(yPos);
mState = TOUCHING;
SetState(TOUCHING);
break;
case TOUCHING:
case PANNING:
@ -320,7 +323,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
return nsEventStatus_eIgnore;
case TOUCHING:
mState = NOTHING;
SetState(NOTHING);
return nsEventStatus_eIgnore;
case PANNING:
@ -329,10 +332,10 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
ScheduleComposite();
RequestContentRepaint();
}
mState = FLING;
SetState(FLING);
return nsEventStatus_eConsumeNoDefault;
case PINCHING:
mState = NOTHING;
SetState(NOTHING);
// Scale gesture listener should have handled this.
NS_WARNING("Gesture listener should have handled pinching in OnTouchEnd.");
return nsEventStatus_eIgnore;
@ -342,12 +345,12 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
}
nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEvent) {
mState = NOTHING;
SetState(NOTHING);
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) {
mState = PINCHING;
SetState(PINCHING);
mLastZoomFocus = aEvent.mFocusPoint;
return nsEventStatus_eConsumeNoDefault;
@ -449,7 +452,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
}
nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent) {
mState = PANNING;
SetState(PANNING);
mX.StartTouch(aEvent.mFocusPoint.x);
mY.StartTouch(aEvent.mFocusPoint.y);
{
@ -517,7 +520,7 @@ void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
mX.StartTouch(touch.mScreenPoint.x);
mY.StartTouch(touch.mScreenPoint.y);
mState = PANNING;
SetState(PANNING);
if (angle < AXIS_LOCK_ANGLE || angle > (M_PI - AXIS_LOCK_ANGLE)) {
mY.LockPanning();
@ -925,11 +928,11 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
gfx::Rect zoomToRect(gfx::Rect(aRect.x, aRect.y, aRect.width, aRect.height));
gfx::Rect cssPageRect = mFrameMetrics.mCSSContentRect;
SetState(ANIMATING_ZOOM);
{
MonitorAutoLock mon(mMonitor);
mState = ANIMATING_ZOOM;
nsIntRect viewport = mFrameMetrics.mViewport;
// If the rect is empty, treat it as a request to zoom out to the full page
@ -995,5 +998,10 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
}
}
void AsyncPanZoomController::SetState(PanZoomState aState) {
MonitorAutoLock monitor(mMonitor);
mState = aState;
}
}
}

View File

@ -296,6 +296,8 @@ protected:
* Cancels any currently running animation. Note that all this does is set the
* state of the AsyncPanZoomController back to NOTHING, but it is the
* animation's responsibility to check this before advancing.
*
* *** The monitor must be held while calling this.
*/
void CancelAnimation();
@ -398,6 +400,13 @@ private:
CONTENT_PAINTING_AND_PAINT_PENDING
};
/**
* Helper to set the current state. Holds the monitor before actually setting
* it. If the monitor is already held by the current thread, it is safe to
* instead use: |mState = NEWSTATE;|
*/
void SetState(PanZoomState aState);
nsRefPtr<CompositorParent> mCompositorParent;
nsRefPtr<GeckoContentController> mGeckoContentController;
nsRefPtr<GestureEventListener> mGestureEventListener;
@ -428,6 +437,10 @@ private:
AxisX mX;
AxisY mY;
// Protects |mFrameMetrics|, |mLastContentPaintMetrics| and |mState|. Before
// manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the monitor
// should be held. When setting |mState|, either the SetState() function can
// be used, or the monitor can be held and then |mState| updated.
Monitor mMonitor;
// The last time the compositor has sampled the content transform for this
@ -443,7 +456,11 @@ private:
// Stores the previous focus point if there is a pinch gesture happening. Used
// to allow panning by moving multiple fingers (thus moving the focus point).
nsIntPoint mLastZoomFocus;
// Stores the state of panning and zooming this frame. This is protected by
// |mMonitor|; that is, it should be held whenever this is updated.
PanZoomState mState;
int mDPI;
// Stores the current paint status of the frame that we're managing. Repaints