Bug 1543315 - part 15: Mark PresShell::ScrollFrameRectIntoView() as MOZ_CAN_RUN_SCRIPT r=smaug

Unfortunately, `EventChainVisitor` does not grab the `nsPresContext` with
`RefPtr` by itself.  Therefore, there is no guarantee of the lifetime without
checking the origin when its subclasses are instantiated.  This patch changes
it and subclasses to `MOZ_STACK_CLASS` since only `EventDispatcher::Dispatch()`
creates them in the stack with given `nsPresContext`.  Additionally, it's
already been marked as MOZ_CAN_RUN_SCRIPT_BOUNDARY`.  Therefore, the
`nsPresContext` instance has already been guaranteed its lifetime by the
caller.  For making this fact stronger, this patch marks their constructors
as `MOZ_CAN_RUN_SCRIPT`.  Therefore, nobody can create those instances without
guaranteeing the lifetime of `nsPresContext` and `dom::Event`.  Note that
it may look like that `mPresContext` of `EventChainPostVisitor` is not
guaranteed.  However, `EventChainPreVisitor` which gives `nsPresContext` to it
is also a stack only class.  So, it won't be deleted before
`EventChainPostVisitor` instance.

Differential Revision: https://phabricator.services.mozilla.com/D30010

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2019-05-06 13:57:46 +00:00
Родитель 4fd67bb3f1
Коммит 780b285e68
19 изменённых файлов: 71 добавлений и 41 удалений

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

@ -198,7 +198,7 @@ class nsAutoScrollTimer final : public nsITimerCallback, public nsINamed {
return NS_OK;
}
NS_IMETHOD Notify(nsITimer* timer) override {
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Notify(nsITimer* timer) override {
if (mSelection && mPresContext) {
AutoWeakFrame frame =
mContent ? mPresContext->GetPrimaryFrameFor(mContent) : nullptr;
@ -216,7 +216,8 @@ class nsAutoScrollTimer final : public nsITimerCallback, public nsINamed {
}
NS_ASSERTION(frame->PresContext() == mPresContext, "document mismatch?");
mSelection->DoAutoScroll(frame, pt);
RefPtr<Selection> selection = mSelection;
selection->DoAutoScroll(frame, pt);
}
return NS_OK;
}
@ -3044,7 +3045,7 @@ nsresult Selection::ScrollIntoView(SelectionRegion aRegion,
return NS_OK;
}
PresShell* presShell = mFrameSelection->GetPresShell();
RefPtr<PresShell> presShell = mFrameSelection->GetPresShell();
if (!presShell || !presShell->GetDocument()) {
return NS_OK;
}

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

@ -153,6 +153,7 @@ class Selection final : public nsSupportsWeakReference,
// Otherwise, if SCROLL_DO_FLUSH is also in aFlags, then this method will
// flush layout and you MUST hold a strong ref on 'this' for the duration
// of this call. This might destroy arbitrary layout objects.
MOZ_CAN_RUN_SCRIPT_BOUNDARY
nsresult ScrollIntoView(SelectionRegion aRegion,
ScrollAxis aVertical = ScrollAxis(),
ScrollAxis aHorizontal = ScrollAxis(),
@ -209,7 +210,7 @@ class Selection final : public nsSupportsWeakReference,
NS_IMETHOD Repaint(nsPresContext* aPresContext);
// Note: StartAutoScrollTimer might destroy arbitrary frames etc.
MOZ_CAN_RUN_SCRIPT
nsresult StartAutoScrollTimer(nsIFrame* aFrame, const nsPoint& aPoint,
uint32_t aDelay);
@ -377,7 +378,7 @@ class Selection final : public nsSupportsWeakReference,
bool aAllowAdjacent,
nsTArray<RefPtr<nsRange>>& aReturn,
mozilla::ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void ScrollIntoView(int16_t aRegion, bool aIsSynchronous,
WhereToScroll aVPercent, WhereToScroll aHPercent,
mozilla::ErrorResult& aRv);
@ -587,8 +588,7 @@ class Selection final : public nsSupportsWeakReference,
private:
friend class ::nsAutoScrollTimer;
// Note: DoAutoScroll might destroy arbitrary frames etc.
nsresult DoAutoScroll(nsIFrame* aFrame, nsPoint aPoint);
MOZ_CAN_RUN_SCRIPT nsresult DoAutoScroll(nsIFrame* aFrame, nsPoint aPoint);
// We are not allowed to be in nodes whose root is not our document
bool HasSameRoot(nsINode& aNode);

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

@ -893,8 +893,9 @@ nsresult EventDispatcher::Dispatch(nsISupports* aTarget,
// Create visitor object and start event dispatching.
// GetEventTargetParent for the original target.
nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
nsCOMPtr<EventTarget> targetForPreVisitor = aEvent->mTarget;
EventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
isInAnon, aEvent->mTarget);
isInAnon, targetForPreVisitor);
targetEtci->GetEventTargetParent(preVisitor);
if (!preVisitor.mCanHandle) {

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

@ -50,8 +50,11 @@ class EventTarget;
* is called right after calling event listener for the current event target.
*/
class EventChainVisitor {
class MOZ_STACK_CLASS EventChainVisitor {
public:
// For making creators of this class instances guarantee the lifetime of
// aPresContext, this needs to be marked as MOZ_CAN_RUN_SCRIPT.
MOZ_CAN_RUN_SCRIPT
EventChainVisitor(nsPresContext* aPresContext, WidgetEvent* aEvent,
dom::Event* aDOMEvent,
nsEventStatus aEventStatus = nsEventStatus_eIgnore)
@ -63,6 +66,9 @@ class EventChainVisitor {
/**
* The prescontext, possibly nullptr.
* Note that the lifetime of mPresContext is guaranteed by the creators so
* that you can use this with MOZ_KnownLive() when you set argument
* of can-run-script methods to this.
*/
nsPresContext* const mPresContext;
@ -106,8 +112,9 @@ class EventChainVisitor {
nsCOMPtr<nsISupports> mItemData;
};
class EventChainPreVisitor : public EventChainVisitor {
class MOZ_STACK_CLASS EventChainPreVisitor final : public EventChainVisitor {
public:
MOZ_CAN_RUN_SCRIPT
EventChainPreVisitor(nsPresContext* aPresContext, WidgetEvent* aEvent,
dom::Event* aDOMEvent, nsEventStatus aEventStatus,
bool aIsInAnon,
@ -292,10 +299,16 @@ class EventChainPreVisitor : public EventChainVisitor {
dom::EventTarget* mTargetInKnownToBeHandledScope;
};
class EventChainPostVisitor : public mozilla::EventChainVisitor {
class MOZ_STACK_CLASS EventChainPostVisitor final
: public mozilla::EventChainVisitor {
public:
// Note that for making guarantee the lifetime of mPresContext and mDOMEvent,
// creators should guarantee that aOther won't be deleted while the instance
// of this class is alive.
MOZ_CAN_RUN_SCRIPT
explicit EventChainPostVisitor(EventChainVisitor& aOther)
: EventChainVisitor(aOther.mPresContext, aOther.mEvent, aOther.mDOMEvent,
: EventChainVisitor(MOZ_KnownLive(aOther.mPresContext), aOther.mEvent,
MOZ_KnownLive(aOther.mDOMEvent),
aOther.mEventStatus) {}
};

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

@ -4033,7 +4033,8 @@ class MOZ_STACK_CLASS ESMEventCB : public EventDispatchingCallback {
if (aVisitor.mPresContext) {
nsIFrame* frame = aVisitor.mPresContext->GetPrimaryFrameFor(mTarget);
if (frame) {
frame->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent->AsGUIEvent(),
frame->HandleEvent(MOZ_KnownLive(aVisitor.mPresContext),
aVisitor.mEvent->AsGUIEvent(),
&aVisitor.mEventStatus);
}
}
@ -4734,7 +4735,9 @@ void EventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
}
// Finally dispatch the event to the frame
if (aTargetFrame) aTargetFrame->HandleEvent(aPresContext, &event, &status);
if (aTargetFrame) {
aTargetFrame->HandleEvent(aPresContext, &event, &status);
}
}
void EventStateManager::UpdateDragDataTransfer(WidgetDragEvent* dragEvent) {

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

@ -212,6 +212,7 @@ class AccessibleCaretManager {
// Start the selection scroll timer if the caret is being dragged out of
// the scroll port.
MOZ_CAN_RUN_SCRIPT
void StartSelectionAutoScrollTimer(const nsPoint& aPoint) const;
void StopSelectionAutoScrollTimer() const;

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

@ -501,7 +501,8 @@ class MOZ_STACK_CLASS nsPresShellEventCB : public EventDispatchingCallback {
frame = mPresShell->GetRootFrame();
}
if (frame) {
frame->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent->AsGUIEvent(),
frame->HandleEvent(MOZ_KnownLive(aVisitor.mPresContext),
aVisitor.mEvent->AsGUIEvent(),
&aVisitor.mEventStatus);
}
}

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

@ -559,6 +559,7 @@ class PresShell final : public nsStubDocumentObserver,
* view.
* @return true if any scrolling happened, false if no scrolling happened
*/
MOZ_CAN_RUN_SCRIPT
bool ScrollFrameRectIntoView(nsIFrame* aFrame, const nsRect& aRect,
ScrollAxis aVertical, ScrollAxis aHorizontal,
ScrollFlags aScrollFlags);

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

@ -1812,7 +1812,8 @@ void nsListControlFrame::ScrollToFrame(dom::HTMLOptionElement& aOptElement) {
// otherwise we find the content's frame and scroll to it
nsIFrame* childFrame = aOptElement.GetPrimaryFrame();
if (childFrame) {
PresShell()->ScrollFrameRectIntoView(
RefPtr<mozilla::PresShell> presShell = PresShell();
presShell->ScrollFrameRectIntoView(
childFrame, nsRect(nsPoint(0, 0), childFrame->GetSize()), ScrollAxis(),
ScrollAxis(),
ScrollFlags::ScrollOverflowHidden |

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

@ -76,6 +76,7 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot,
@ -98,6 +99,7 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
// nsIFormControlFrame
virtual nsresult SetFormProperty(nsAtom* aName,
const nsAString& aValue) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
virtual void SetFocus(bool aOn = true, bool aRepaint = false) override;
virtual mozilla::ScrollStyles GetScrollStyles() const override;
@ -122,7 +124,7 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
void CaptureMouseEvents(bool aGrabMouseEvents);
nscoord GetBSizeOfARow();
uint32_t GetNumberOfOptions();
void AboutToDropDown();
MOZ_CAN_RUN_SCRIPT_BOUNDARY void AboutToDropDown();
/**
* @note This method might destroy the frame, pres shell and other objects.
@ -140,19 +142,22 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
* Makes aIndex the selected option of a combobox list.
* @note This method might destroy the frame, pres shell and other objects.
*/
void ComboboxFinish(int32_t aIndex);
void OnContentReset();
MOZ_CAN_RUN_SCRIPT_BOUNDARY void ComboboxFinish(int32_t aIndex);
MOZ_CAN_RUN_SCRIPT_BOUNDARY void OnContentReset();
// nsISelectControlFrame
NS_IMETHOD AddOption(int32_t index) override;
NS_IMETHOD RemoveOption(int32_t index) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
NS_IMETHOD DoneAddingChildren(bool aIsDone) override;
/**
* Gets the content (an option) by index and then set it as
* being selected or not selected.
*/
MOZ_CAN_RUN_SCRIPT_BOUNDARY
NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
NS_IMETHOD_(void)
OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) override;
@ -160,10 +165,13 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
* Mouse event listeners.
* @note These methods might destroy the frame, pres shell and other objects.
*/
MOZ_CAN_RUN_SCRIPT
nsresult MouseDown(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT
nsresult MouseUp(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT
nsresult MouseMove(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT
nsresult DragMove(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT
nsresult KeyDown(mozilla::dom::Event* aKeyEvent);
@ -288,14 +296,9 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
mozilla::dom::HTMLSelectElement* aSelect,
mozilla::dom::HTMLOptionElement* aOption);
/**
* @note This method might destroy the frame, pres shell and other objects.
*/
void ScrollToFrame(HTMLOptionElement& aOptElement);
/**
* @note This method might destroy the frame, pres shell and other objects.
*/
void ScrollToIndex(int32_t anIndex);
MOZ_CAN_RUN_SCRIPT void ScrollToFrame(HTMLOptionElement& aOptElement);
MOZ_CAN_RUN_SCRIPT void ScrollToIndex(int32_t anIndex);
/**
* When the user clicks on the comboboxframe to show the dropdown
@ -322,7 +325,7 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
* Resets the select back to it's original default values;
* those values as determined by the original HTML
*/
virtual void ResetList(bool aAllowScrolling);
MOZ_CAN_RUN_SCRIPT void ResetList(bool aAllowScrolling);
explicit nsListControlFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext);
@ -364,19 +367,14 @@ class nsListControlFrame final : public nsHTMLScrollFrame,
bool SetOptionsSelectedFromFrame(int32_t aStartIndex, int32_t aEndIndex,
bool aValue, bool aClearAll);
bool ToggleOptionSelectedFromFrame(int32_t aIndex);
/**
* @note This method might destroy the frame, pres shell and other objects.
*/
MOZ_CAN_RUN_SCRIPT
bool SingleSelection(int32_t aClickedIndex, bool aDoToggle);
bool ExtendedSelection(int32_t aStartIndex, int32_t aEndIndex,
bool aClearAll);
/**
* @note This method might destroy the frame, pres shell and other objects.
*/
MOZ_CAN_RUN_SCRIPT
bool PerformSelection(int32_t aClickedIndex, bool aIsShift, bool aIsControl);
/**
* @note This method might destroy the frame, pres shell and other objects.
*/
MOZ_CAN_RUN_SCRIPT
bool HandleListSelection(mozilla::dom::Event* aDOMEvent,
int32_t selectedIndex);
void InitSelectionRange(int32_t aClickedIndex);

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

@ -172,6 +172,7 @@ class nsFrame : public nsBox {
const nsFrameList& GetChildList(ChildListID aListID) const override;
void GetChildLists(nsTArray<ChildList>* aLists) const override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
@ -399,6 +400,7 @@ class nsFrame : public nsBox {
nsEventStatus* aEventStatus,
bool aControlHeld);
MOZ_CAN_RUN_SCRIPT
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus);

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

@ -1189,7 +1189,8 @@ nsresult nsFrameSelection::StartAutoScrollTimer(nsIFrame* aFrame,
return NS_ERROR_NULL_POINTER;
}
return mDomSelections[index]->StartAutoScrollTimer(aFrame, aPoint, aDelay);
RefPtr<Selection> selection = mDomSelections[index];
return selection->StartAutoScrollTimer(aFrame, aPoint, aDelay);
}
void nsFrameSelection::StopAutoScrollTimer() {

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

@ -367,7 +367,7 @@ class nsFrameSelection final {
*
* @param aDelay is the timer's interval.
*/
/*unsafe*/
MOZ_CAN_RUN_SCRIPT
nsresult StartAutoScrollTimer(nsIFrame* aFrame, const nsPoint& aPoint,
uint32_t aDelay);

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

@ -1812,7 +1812,8 @@ nsIScrollableFrame* nsMenuPopupFrame::GetScrollFrame(nsIFrame* aStart) {
void nsMenuPopupFrame::EnsureMenuItemIsVisible(nsMenuFrame* aMenuItem) {
if (aMenuItem) {
aMenuItem->PresShell()->ScrollFrameRectIntoView(
RefPtr<mozilla::PresShell> presShell = aMenuItem->PresShell();
presShell->ScrollFrameRectIntoView(
aMenuItem, nsRect(nsPoint(0, 0), aMenuItem->GetRect().Size()),
ScrollAxis(), ScrollAxis(),
ScrollFlags::ScrollOverflowHidden |

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

@ -178,6 +178,7 @@ class nsMenuPopupFrame final : public nsBoxFrame,
// nsMenuParent interface
virtual nsMenuFrame* GetCurrentMenuItem() override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem) override;
virtual void CurrentMenuIsBeingDestroyed() override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
@ -254,6 +255,7 @@ class nsMenuPopupFrame final : public nsBoxFrame,
virtual void UpdateWidgetProperties() override;
// layout, position and display the popup as needed
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
nsIFrame* aAnchor, bool aSizedToPopup);
@ -347,7 +349,7 @@ class nsMenuPopupFrame final : public nsBoxFrame,
}
#endif
void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);
MOZ_CAN_RUN_SCRIPT void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);
void ChangeByPage(bool aIsUp);

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

@ -59,6 +59,7 @@ class nsScrollbarButtonFrame final : public nsButtonBoxFrame {
return NS_OK;
}
MOZ_CAN_RUN_SCRIPT
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override {

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

@ -61,6 +61,7 @@ class nsScrollbarFrame final : public nsBoxFrame,
nsEventStatus* aEventStatus,
bool aControlHeld) override;
MOZ_CAN_RUN_SCRIPT
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;

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

@ -116,6 +116,7 @@ class nsSliderFrame final : public nsBoxFrame {
return NS_OK;
}
MOZ_CAN_RUN_SCRIPT
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override {

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

@ -55,6 +55,7 @@ class nsSplitterFrame final : public nsBoxFrame {
nsEventStatus* aEventStatus,
bool aControlHeld) override;
MOZ_CAN_RUN_SCRIPT
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;