From 8d3cbbd5d284351ee1402f4993ed60c27c2b38b6 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 12 Jan 2010 10:45:20 +1300 Subject: [PATCH] Bug 526394. Part 35: Prevent event dispatch and script execution during UpdateViewAfterScroll, even in the presence of malign Win32 reentrant APIs. r=mats --- layout/generic/nsGfxScrollFrame.cpp | 16 +++++++++++++- view/src/nsViewManager.cpp | 33 ++++++++++++++++------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 6cb4acc34ca..0424caf313d 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1687,7 +1687,21 @@ void nsGfxScrollFrameInner::ScrollVisual(nsIntPoint aPixDelta) nearestWidget->Scroll(aPixDelta, blitRects, configurations); AdjustViewsAndWidgets(mScrolledFrame, PR_TRUE); repaintRegion.MoveBy(-nearestWidgetOffset + offsetToDisplayRoot); - vm->UpdateViewAfterScroll(view, repaintRegion); + + { + // Block script execution. This suppresses event dispatching in + // PresShell::HandleEvent. We need to do this because Windows + // is evil and can dispatch WM_MOUSEACTIVATE messages during + // our call to ::UpdateWindow (in the presence of out-of-process + // plugins, it seems). We are not able to handle event dispatch + // here. + // No script runners should be added as we paint! + nsContentUtils::AddScriptBlockerAndPreventAddingRunners(); + vm->UpdateViewAfterScroll(view, repaintRegion); + nsContentUtils::RemoveScriptBlocker(); + // Nothing should run here on removing the blocker, since we + // prevented the addition of any script runners. + } nsIFrame* presContextRootFrame = presContext->FrameManager()->GetRootFrame(); if (nearestWidget == presContextRootFrame->GetWindow()) { diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 45616966634..84b7d9a85e6 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -861,25 +861,29 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, // Refresh the view if (IsRefreshEnabled()) { + nsRefPtr rootVM = RootViewManager(); + // If an ancestor widget was hidden and then shown, we could // have a delayed resize to handle. PRBool didResize = PR_FALSE; - for (nsViewManager *vm = this; vm; - vm = vm->mRootView->GetParent() - ? vm->mRootView->GetParent()->GetViewManager() - : nsnull) { - if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && - IsViewVisible(vm->mRootView)) { - vm->FlushDelayedResize(); + if (rootVM->mScrollCnt == 0) { + for (nsViewManager *vm = this; vm; + vm = vm->mRootView->GetParent() + ? vm->mRootView->GetParent()->GetViewManager() + : nsnull) { + if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && + IsViewVisible(vm->mRootView)) { + vm->FlushDelayedResize(); - // Paint later. - vm->UpdateView(vm->mRootView, NS_VMREFRESH_NO_SYNC); - didResize = PR_TRUE; + // Paint later. + vm->UpdateView(vm->mRootView, NS_VMREFRESH_NO_SYNC); + didResize = PR_TRUE; - // not sure if it's valid for us to claim that we - // ignored this, but we're going to do so anyway, since - // we didn't actually paint anything - *aStatus = nsEventStatus_eIgnore; + // not sure if it's valid for us to claim that we + // ignored this, but we're going to do so anyway, since + // we didn't actually paint anything + *aStatus = nsEventStatus_eIgnore; + } } } @@ -888,7 +892,6 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, // Notify view observers that we're about to paint. // Make sure to not send WillPaint notifications while scrolling. - nsRefPtr rootVM = RootViewManager(); nsCOMPtr widget; rootVM->GetRootWidget(getter_AddRefs(widget));