Bug 1543315 - part 17: Mark PresShell::HandleDOMEventWithTarget() as MOZ_CAN_RUN_SCRIPT r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 09 May 2019 20:21:28 +0000
changeset 532155 e754d9ad197df615a1f71185f6201d956efc31b9
parent 532154 126a59b083f619859b308f023bc5c8df49686b3d
child 532156 c21f692a069302eca39bdb1342bc6acb9fa14a3b
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1543315
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1543315 - part 17: Mark PresShell::HandleDOMEventWithTarget() as MOZ_CAN_RUN_SCRIPT r=smaug Differential Revision: https://phabricator.services.mozilla.com/D30494
dom/base/Document.cpp
dom/base/Document.h
dom/base/nsGlobalWindowOuter.h
dom/events/EventStateManager.cpp
dom/events/EventStateManager.h
dom/html/HTMLButtonElement.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/ipc/BrowserChild.h
dom/ipc/ContentChild.h
dom/svg/SVGSVGElement.h
layout/base/PresShell.h
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsComboboxControlFrame.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsDragService.h
widget/gtk/nsDragService.h
widget/nsBaseDragService.h
widget/nsIDragService.idl
widget/windows/nsDragService.cpp
widget/windows/nsDragService.h
widget/windows/nsNativeDragTarget.cpp
widget/windows/nsNativeDragTarget.h
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -11046,17 +11046,17 @@ static void DispatchPointerLockError(Doc
 class PointerLockRequest final : public Runnable {
  public:
   PointerLockRequest(Element* aElement, bool aUserInputOrChromeCaller)
       : mozilla::Runnable("PointerLockRequest"),
         mElement(do_GetWeakReference(aElement)),
         mDocument(do_GetWeakReference(aElement->OwnerDoc())),
         mUserInputOrChromeCaller(aUserInputOrChromeCaller) {}
 
-  NS_IMETHOD Run() final;
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() final;
 
  private:
   nsWeakPtr mElement;
   nsWeakPtr mDocument;
   bool mUserInputOrChromeCaller;
 };
 
 static const char* GetPointerLockError(Element* aElement, Element* aCurrentLock,
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -1935,18 +1935,19 @@ class Document : public nsINode,
   /**
    * Handles any pending fullscreen in aDocument or its subdocuments.
    *
    * Returns whether there is any fullscreen request handled.
    */
   static bool HandlePendingFullscreenRequests(Document* aDocument);
 
   void RequestPointerLock(Element* aElement, CallerType);
-  bool SetPointerLock(Element* aElement, StyleCursorKind);
-
+  MOZ_CAN_RUN_SCRIPT bool SetPointerLock(Element* aElement, StyleCursorKind);
+
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   static void UnlockPointer(Document* aDoc = nullptr);
 
   // ScreenOrientation related APIs
 
   void SetCurrentOrientation(OrientationType aType, uint16_t aAngle) {
     mCurrentOrientationType = aType;
     mCurrentOrientationAngle = aAngle;
   }
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -320,17 +320,17 @@ class nsGlobalWindowOuter final : public
   void DispatchDOMWindowCreated();
 
   virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
                                bool aOriginalOpener) override;
 
   // Outer windows only.
   virtual void EnsureSizeAndPositionUpToDate() override;
 
-  virtual void EnterModalState() override;
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void EnterModalState() override;
   virtual void LeaveModalState() override;
 
   // Outer windows only.
   virtual bool CanClose() override;
   virtual void ForceClose() override;
 
   // Outer windows only.
   virtual bool DispatchCustomEvent(const nsAString& aEventName) override;
@@ -858,16 +858,17 @@ class nsGlobalWindowOuter final : public
   nsresult SetDocShellWidthAndHeight(int32_t width, int32_t height);
 
   static bool CanSetProperty(const char* aPrefName);
 
   static void MakeScriptDialogTitle(nsAString& aOutTitle,
                                     nsIPrincipal* aSubjectPrincipal);
 
   // Outer windows only.
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   bool CanMoveResizeWindows(mozilla::dom::CallerType aCallerType);
 
   // If aDoFlush is true, we'll flush our own layout; otherwise we'll try to
   // just flush our parent and only flush ourselves if we think we need to.
   // Outer windows only.
   mozilla::CSSPoint GetScrollXY(bool aDoFlush);
 
   int32_t GetScrollBoundaryOuter(mozilla::Side aSide);
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1991,17 +1991,17 @@ bool EventStateManager::DoDefaultDragSta
   uint32_t action = aDataTransfer->EffectAllowedInt();
   if (action == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
     action = nsIDragService::DRAGDROP_ACTION_COPY |
              nsIDragService::DRAGDROP_ACTION_MOVE |
              nsIDragService::DRAGDROP_ACTION_LINK;
 
   // get any custom drag image that was set
   int32_t imageX, imageY;
-  Element* dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
+  RefPtr<Element> dragImage = aDataTransfer->GetDragImage(&imageX, &imageY);
 
   nsCOMPtr<nsIArray> transArray = aDataTransfer->GetTransferables(dragTarget);
   if (!transArray) return false;
 
   // After this function returns, the DataTransfer will be cleared so it appears
   // empty to content. We need to pass a DataTransfer into the Drag Session, so
   // we need to make a copy.
   RefPtr<DataTransfer> dataTransfer;
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -1083,16 +1083,17 @@ class EventStateManager : public nsSuppo
    *
    * aDragEvent - the dragstart event
    * aDataTransfer - the data transfer that holds the data to be dragged
    * aDragTarget - the target of the drag
    * aSelection - the selection to be dragged
    * aPrincipal - the triggering principal of the drag, or null if it's from
    *              browser chrome or OS
    */
+  MOZ_CAN_RUN_SCRIPT
   bool DoDefaultDragStart(nsPresContext* aPresContext,
                           WidgetDragEvent* aDragEvent,
                           dom::DataTransfer* aDataTransfer,
                           nsIContent* aDragTarget, dom::Selection* aSelection,
                           nsIPrincipal* aPrincipal);
 
   bool IsTrackingDragGesture() const { return mGestureDownContent != nullptr; }
   /**
@@ -1268,17 +1269,18 @@ class EventStateManager : public nsSuppo
 
   // Functions used for click hold context menus
   nsCOMPtr<nsITimer> mClickHoldTimer;
   void CreateClickHoldTimer(nsPresContext* aPresContext, nsIFrame* aDownFrame,
                             WidgetGUIEvent* aMouseDownEvent);
   void KillClickHoldTimer();
   void FireContextClick();
 
-  static void SetPointerLock(nsIWidget* aWidget, nsIContent* aElement);
+  MOZ_CAN_RUN_SCRIPT static void SetPointerLock(nsIWidget* aWidget,
+                                                nsIContent* aElement);
   static void sClickHoldCallback(nsITimer* aTimer, void* aESM);
 };
 
 /**
  * This class is used while processing real user input. During this time, popups
  * are allowed. For mousedown events, mouse capturing is also permitted.
  */
 class AutoHandlingUserInputStatePusher {
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -46,16 +46,17 @@ class HTMLButtonElement final : public n
   NS_IMETHOD SaveState() override;
   bool RestoreState(PresState* aState) override;
   virtual bool IsDisabledForEvents(WidgetEvent* aEvent) override;
 
   virtual void FieldSetDisabledChanged(bool aNotify) override;
 
   // EventTarget
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
 
   // nsINode
   virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aGivenProto) override;
 
   // nsIContent
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -3853,17 +3853,17 @@ nsresult HTMLInputElement::PostHandleEve
                keyEvent->mKeyCode == NS_VK_RETURN) ||
               (aVisitor.mEvent->mMessage == eKeyUp &&
                keyEvent->mKeyCode == NS_VK_SPACE)) {
             switch (mType) {
               case NS_FORM_INPUT_CHECKBOX:
               case NS_FORM_INPUT_RADIO: {
                 // Checkbox and Radio try to submit on Enter press
                 if (keyEvent->mKeyCode != NS_VK_SPACE) {
-                  MaybeSubmitForm(aVisitor.mPresContext);
+                  MaybeSubmitForm(MOZ_KnownLive(aVisitor.mPresContext));
 
                   break;  // If we are submitting, do not send click event
                 }
                 // else fall through and treat Space like click...
                 MOZ_FALLTHROUGH;
               }
               case NS_FORM_INPUT_BUTTON:
               case NS_FORM_INPUT_RESET:
@@ -3930,17 +3930,17 @@ nsresult HTMLInputElement::PostHandleEve
            */
 
           if (aVisitor.mEvent->mMessage == eKeyPress &&
               keyEvent->mKeyCode == NS_VK_RETURN &&
               (IsSingleLineTextControl(false, mType) ||
                mType == NS_FORM_INPUT_NUMBER ||
                IsExperimentalMobileType(mType) || IsDateTimeInputType(mType))) {
             FireChangeEventIfNeeded();
-            rv = MaybeSubmitForm(aVisitor.mPresContext);
+            rv = MaybeSubmitForm(MOZ_KnownLive(aVisitor.mPresContext));
             NS_ENSURE_SUCCESS(rv, rv);
           }
 
           if (aVisitor.mEvent->mMessage == eKeyPress &&
               mType == NS_FORM_INPUT_RANGE && !keyEvent->IsAlt() &&
               !keyEvent->IsControl() && !keyEvent->IsMeta() &&
               (keyEvent->mKeyCode == NS_VK_LEFT ||
                keyEvent->mKeyCode == NS_VK_RIGHT ||
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -1012,17 +1012,17 @@ class HTMLInputElement final : public ns
 
   void RadioSetChecked(bool aNotify);
   void SetCheckedChanged(bool aCheckedChanged);
 
   /**
    * MaybeSubmitForm looks for a submit input or a single text control
    * and submits the form if either is present.
    */
-  nsresult MaybeSubmitForm(nsPresContext* aPresContext);
+  MOZ_CAN_RUN_SCRIPT nsresult MaybeSubmitForm(nsPresContext* aPresContext);
 
   /**
    * Update mFileList with the currently selected file.
    */
   void UpdateFileList();
 
   /**
    * Called after calling one of the SetFilesOrDirectories() functions.
--- a/dom/ipc/BrowserChild.h
+++ b/dom/ipc/BrowserChild.h
@@ -354,16 +354,17 @@ class BrowserChild final : public Browse
 
   mozilla::ipc::IPCResult RecvRealMouseButtonEvent(
       const mozilla::WidgetMouseEvent& aEvent, const ScrollableLayerGuid& aGuid,
       const uint64_t& aInputBlockId);
   mozilla::ipc::IPCResult RecvNormalPriorityRealMouseButtonEvent(
       const mozilla::WidgetMouseEvent& aEvent, const ScrollableLayerGuid& aGuid,
       const uint64_t& aInputBlockId);
 
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   mozilla::ipc::IPCResult RecvRealDragEvent(const WidgetDragEvent& aEvent,
                                             const uint32_t& aDragAction,
                                             const uint32_t& aDropEffect,
                                             nsIPrincipal* aPrincipal);
 
   mozilla::ipc::IPCResult RecvRealKeyEvent(
       const mozilla::WidgetKeyboardEvent& aEvent);
 
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -449,16 +449,17 @@ class ContentChild final : public PConte
                                                const uint32_t& aChangeType,
                                                const Maybe<URIParams>& aDomain);
 
   mozilla::ipc::IPCResult RecvShutdown();
 
   mozilla::ipc::IPCResult RecvInvokeDragSession(
       nsTArray<IPCDataTransfer>&& aTransfers, const uint32_t& aAction);
 
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   mozilla::ipc::IPCResult RecvEndDragSession(
       const bool& aDoneDrag, const bool& aUserCancelled,
       const mozilla::LayoutDeviceIntPoint& aEndDragPoint,
       const uint32_t& aKeyModifiers);
 
   mozilla::ipc::IPCResult RecvPush(const nsCString& aScope,
                                    const IPC::Principal& aPrincipal,
                                    const nsString& aMessageId);
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -97,17 +97,18 @@ class SVGSVGElement final : public SVGSV
 
   /**
    * For use by zoom controls to allow currentScale, currentTranslate.x and
    * currentTranslate.y to be set by a single operation that dispatches a
    * single SVGZoom event (instead of one SVGZoom and two SVGScroll events).
    *
    * XXX SVGZoomEvent is no more, is this needed?
    */
-  void SetCurrentScaleTranslate(float s, float x, float y);
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetCurrentScaleTranslate(float s, float x,
+                                                            float y);
 
   // nsIContent interface
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
   virtual bool IsEventAttributeNameInternal(nsAtom* aName) override;
 
   // nsINode methods:
   virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
 
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -649,26 +649,26 @@ class PresShell final : public nsStubDoc
     EventHandler eventHandler(*this);
     return eventHandler.HandleEventWithTarget(
         aEvent, aFrame, aContent, aEventStatus, aIsHandlingNativeEvent,
         aTargetContent, aOverrideClickTarget);
   }
 
   /**
    * Dispatch event to content only (NOT full processing)
-   * @note The caller must have a strong reference to the PresShell.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult HandleDOMEventWithTarget(nsIContent* aTargetContent,
                                     WidgetEvent* aEvent,
                                     nsEventStatus* aStatus);
 
   /**
    * Dispatch event to content only (NOT full processing)
-   * @note The caller must have a strong reference to the PresShell.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult HandleDOMEventWithTarget(nsIContent* aTargetContent,
                                     dom::Event* aEvent, nsEventStatus* aStatus);
 
   /**
    * Return whether or not the event is valid to be dispatched
    */
   bool CanDispatchEvent(const WidgetGUIEvent* aEvent = nullptr) const;
 
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -89,17 +89,17 @@ nsComboboxControlFrame::RedisplayTextEve
  */
 class nsComboButtonListener final : public nsIDOMEventListener {
  private:
   virtual ~nsComboButtonListener() {}
 
  public:
   NS_DECL_ISUPPORTS
 
-  NS_IMETHOD HandleEvent(dom::Event*) override {
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD HandleEvent(dom::Event*) override {
     mComboBox->ShowDropDown(!mComboBox->IsDroppedDown());
     return NS_OK;
   }
 
   explicit nsComboButtonListener(nsComboboxControlFrame* aCombobox) {
     mComboBox = aCombobox;
   }
 
@@ -310,17 +310,18 @@ void nsComboboxControlFrame::ShowPopup(b
   // fire a popup dom event if it is safe to do so
   RefPtr<mozilla::PresShell> presShell = PresContext()->GetPresShell();
   if (presShell && nsContentUtils::IsSafeToRunScript()) {
     nsEventStatus status = nsEventStatus_eIgnore;
     WidgetMouseEvent event(true,
                            aShowPopup ? eXULPopupShowing : eXULPopupHiding,
                            nullptr, WidgetMouseEvent::eReal);
 
-    presShell->HandleDOMEventWithTarget(mContent, &event, &status);
+    nsCOMPtr<nsIContent> content = mContent;
+    presShell->HandleDOMEventWithTarget(content, &event, &status);
   }
 }
 
 bool nsComboboxControlFrame::ShowList(bool aShowList) {
   nsView* view = mDropdownFrame->GetView();
   if (aShowList) {
     NS_ASSERTION(
         !view->HasWidget(),
@@ -490,17 +491,17 @@ nsPoint nsComboboxControlFrame::GetCSSTr
   }
   return translation;
 }
 
 class nsAsyncRollup : public Runnable {
  public:
   explicit nsAsyncRollup(nsComboboxControlFrame* aFrame)
       : mozilla::Runnable("nsAsyncRollup"), mFrame(aFrame) {}
-  NS_IMETHOD Run() override {
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() override {
     if (mFrame.IsAlive()) {
       static_cast<nsComboboxControlFrame*>(mFrame.GetFrame())->RollupFromList();
     }
     return NS_OK;
   }
   WeakFrame mFrame;
 };
 
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -81,16 +81,17 @@ class nsComboboxControlFrame final : pub
   virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
 
   virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
 
   virtual void Reflow(nsPresContext* aCX, ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus& aStatus) override;
 
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                mozilla::WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                 const nsDisplayListSet& aLists) override;
 
   void PaintFocus(DrawTarget& aDrawTarget, nsPoint aPt);
@@ -130,26 +131,20 @@ class nsComboboxControlFrame final : pub
    * @param aRepaint if true then force repaint (NOTE: we always force repaint
    *        currently)
    * @note This method might destroy |this|.
    */
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual void SetFocus(bool aOn, bool aRepaint) override;
 
   bool IsDroppedDown() { return mDroppedDown; }
-  /**
-   * @note This method might destroy |this|.
-   */
-  void ShowDropDown(bool aDoDropDown);
+  MOZ_CAN_RUN_SCRIPT void ShowDropDown(bool aDoDropDown);
   nsIFrame* GetDropDown();
   void SetDropDown(nsIFrame* aDropDownFrame);
-  /**
-   * @note This method might destroy |this|.
-   */
-  void RollupFromList();
+  MOZ_CAN_RUN_SCRIPT void RollupFromList();
 
   /**
    * Return the available space before and after this frame for
    * placing the drop-down list, and the current 2D translation.
    * Note that either or both can be less than or equal to zero,
    * if both are then the drop-down should be closed.
    */
   void GetAvailableDropdownSpace(mozilla::WritingMode aWM, nscoord* aBefore,
@@ -207,16 +202,17 @@ class nsComboboxControlFrame final : pub
       nsTArray<nsIWidget*>* aWidgetChain) override {
     return 0;
   }
 
   virtual nsIWidget* GetRollupWidget() override;
 
   // nsIStatefulFrame
   mozilla::UniquePtr<mozilla::PresState> SaveState() override;
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   NS_IMETHOD RestoreState(mozilla::PresState* aState) override;
   NS_IMETHOD GenerateStateKey(nsIContent* aContent,
                               mozilla::dom::Document* aDocument,
                               nsACString& aKey) override;
 
   static bool ToolkitHasNativePopup();
 
  protected:
@@ -256,25 +252,25 @@ class nsComboboxControlFrame final : pub
    private:
     nsComboboxControlFrame* mControlFrame;
   };
 
   /**
    * Show or hide the dropdown list.
    * @note This method might destroy |this|.
    */
-  void ShowPopup(bool aShowPopup);
+  MOZ_CAN_RUN_SCRIPT void ShowPopup(bool aShowPopup);
 
   /**
    * Show or hide the dropdown list.
    * @param aShowList true to show, false to hide the dropdown.
    * @note This method might destroy |this|.
    * @return false if this frame is destroyed, true if still alive.
    */
-  bool ShowList(bool aShowList);
+  MOZ_CAN_RUN_SCRIPT bool ShowList(bool aShowList);
   void CheckFireOnChange();
   void FireValueChangeEvent();
   nsresult RedisplayText();
   void HandleRedisplayTextEvent();
   void ActuallyDisplayText(bool aNotify);
 
  private:
   // If our total transform to the root frame of the root document is only a 2d
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -5245,31 +5245,32 @@ static gfx::IntPoint GetIntegerDeltaForE
   }
 
   nsCOMPtr<nsIDragSession> dragSession;
   mDragService->GetCurrentSession(getter_AddRefs(dragSession));
   if (dragSession) {
     if (aMessage == eDragOver) {
       // fire the drag event at the source. Just ignore whether it was
       // cancelled or not as there isn't actually a means to stop the drag
-      mDragService->FireDragEventAtSource(eDrag,
-                                          nsCocoaUtils::ModifiersForEvent([NSApp currentEvent]));
+      nsCOMPtr<nsIDragService> dragService = mDragService;
+      dragService->FireDragEventAtSource(eDrag,
+                                         nsCocoaUtils::ModifiersForEvent([NSApp currentEvent]));
       dragSession->SetCanDrop(false);
     } else if (aMessage == eDrop) {
       // We make the assumption that the dragOver handlers have correctly set
       // the |canDrop| property of the Drag Session.
       bool canDrop = false;
       if (!NS_SUCCEEDED(dragSession->GetCanDrop(&canDrop)) || !canDrop) {
         [self doDragAction:eDragExit sender:aSender];
 
         nsCOMPtr<nsINode> sourceNode;
         dragSession->GetSourceNode(getter_AddRefs(sourceNode));
         if (!sourceNode) {
-          mDragService->EndDragSession(false,
-                                       nsCocoaUtils::ModifiersForEvent([NSApp currentEvent]));
+          nsCOMPtr<nsIDragService> dragService = mDragService;
+          dragService->EndDragSession(false, nsCocoaUtils::ModifiersForEvent([NSApp currentEvent]));
         }
         return NSDragOperationNone;
       }
     }
 
     unsigned int modifierFlags = [[NSApp currentEvent] modifierFlags];
     uint32_t action = nsIDragService::DRAGDROP_ACTION_MOVE;
     // force copy = option, alias = cmd-option, default is move
@@ -5319,18 +5320,18 @@ static gfx::IntPoint GetIntegerDeltaForE
       case eDrop: {
         nsCOMPtr<nsINode> sourceNode;
         dragSession->GetSourceNode(getter_AddRefs(sourceNode));
         if (!sourceNode) {
           // We're leaving a window while doing a drag that was
           // initiated in a different app. End the drag session,
           // since we're done with it for now (until the user
           // drags back into mozilla).
-          mDragService->EndDragSession(false,
-                                       nsCocoaUtils::ModifiersForEvent([NSApp currentEvent]));
+          nsCOMPtr<nsIDragService> dragService = mDragService;
+          dragService->EndDragSession(false, nsCocoaUtils::ModifiersForEvent([NSApp currentEvent]));
         }
       }
       default:
         break;
     }
   }
 
   return NSDragOperationGeneric;
@@ -5406,17 +5407,17 @@ static gfx::IntPoint GetIntegerDeltaForE
 
   if (!mDragService) {
     CallGetService(kDragServiceContractID, &mDragService);
     NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!");
   }
 
   if (mDragService) {
     // set the dragend point from the current mouse location
-    nsDragService* dragService = static_cast<nsDragService*>(mDragService);
+    RefPtr<nsDragService> dragService = static_cast<nsDragService*>(mDragService);
     FlipCocoaScreenCoordinate(aPoint);
     dragService->SetDragEndPoint(gfx::IntPoint::Round(aPoint.x, aPoint.y));
 
     NSPoint pnt = [NSEvent mouseLocation];
     FlipCocoaScreenCoordinate(pnt);
     dragService->SetDragEndPoint(gfx::IntPoint::Round(pnt.x, pnt.y));
 
     // XXX: dropEffect should be updated per |aOperation|.
@@ -5429,17 +5430,17 @@ static gfx::IntPoint GetIntegerDeltaForE
     // All that said, NSDragOperationNone is still reliable.
     if (aOperation == NSDragOperationNone) {
       RefPtr<dom::DataTransfer> dataTransfer = dragService->GetDataTransfer();
       if (dataTransfer) {
         dataTransfer->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE);
       }
     }
 
-    mDragService->EndDragSession(true, nsCocoaUtils::ModifiersForEvent(currentEvent));
+    dragService->EndDragSession(true, nsCocoaUtils::ModifiersForEvent(currentEvent));
     NS_RELEASE(mDragService);
   }
 
   [globalDragPboard release];
   globalDragPboard = nil;
   [gLastDragMouseDownEvent release];
   gLastDragMouseDownEvent = nil;
 
--- a/widget/cocoa/nsDragService.h
+++ b/widget/cocoa/nsDragService.h
@@ -18,21 +18,21 @@ extern NSString* const kMozWildcardPboar
 extern NSString* const kMozCustomTypesPboardType;
 extern NSString* const kMozFileUrlsPboardType;
 
 class nsDragService : public nsBaseDragService {
  public:
   nsDragService();
 
   // nsBaseDragService
-  virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables,
-                                         const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
-                                         uint32_t aActionType) override;
+  MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
+      nsIArray* anArrayTransferables, const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
+      uint32_t aActionType) override;
   // nsIDragService
-  NS_IMETHOD EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) override;
+  MOZ_CAN_RUN_SCRIPT NS_IMETHOD EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) override;
   NS_IMETHOD UpdateDragImage(nsINode* aImage, int32_t aImageX, int32_t aImageY) override;
 
   // nsIDragSession
   NS_IMETHOD GetData(nsITransferable* aTransferable, uint32_t aItemIndex) override;
   NS_IMETHOD IsDataFlavorSupported(const char* aDataFlavor, bool* _retval) override;
   NS_IMETHOD GetNumDropItems(uint32_t* aNumItems) override;
 
   void DragMovedWithView(NSDraggingSession* aSession, NSPoint aPoint);
--- a/widget/gtk/nsDragService.h
+++ b/widget/gtk/nsDragService.h
@@ -53,27 +53,28 @@ class nsDragService final : public nsBas
  public:
   nsDragService();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIOBSERVER
 
   // nsBaseDragService
-  virtual nsresult InvokeDragSessionImpl(
+  MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
       nsIArray* anArrayTransferables,
       const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
       uint32_t aActionType) override;
   // nsIDragService
-  NS_IMETHOD InvokeDragSession(nsINode* aDOMNode, nsIPrincipal* aPrincipal,
-                               nsIArray* anArrayTransferables,
-                               uint32_t aActionType,
-                               nsContentPolicyType aContentPolicyType) override;
+  MOZ_CAN_RUN_SCRIPT NS_IMETHOD
+  InvokeDragSession(nsINode* aDOMNode, nsIPrincipal* aPrincipal,
+                    nsIArray* anArrayTransferables, uint32_t aActionType,
+                    nsContentPolicyType aContentPolicyType) override;
   NS_IMETHOD StartDragSession() override;
-  NS_IMETHOD EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) override;
+  MOZ_CAN_RUN_SCRIPT NS_IMETHOD EndDragSession(bool aDoneDrag,
+                                               uint32_t aKeyModifiers) override;
 
   // nsIDragSession
   NS_IMETHOD SetCanDrop(bool aCanDrop) override;
   NS_IMETHOD GetCanDrop(bool* aCanDrop) override;
   NS_IMETHOD GetNumDropItems(uint32_t* aNumItems) override;
   NS_IMETHOD GetData(nsITransferable* aTransferable,
                      uint32_t aItemIndex) override;
   NS_IMETHOD IsDataFlavorSupported(const char* aDataFlavor,
@@ -206,20 +207,20 @@ class nsDragService final : public nsBas
                       const mozilla::LayoutDeviceIntRect& dragRect);
 
   gboolean Schedule(DragTask aTask, nsWindow* aWindow,
                     GdkDragContext* aDragContext,
                     nsWaylandDragContext* aPendingWaylandDragContext,
                     mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime);
 
   // Callback for g_idle_add_full() to run mScheduledTask.
-  static gboolean TaskDispatchCallback(gpointer data);
-  gboolean RunScheduledTask();
+  MOZ_CAN_RUN_SCRIPT static gboolean TaskDispatchCallback(gpointer data);
+  MOZ_CAN_RUN_SCRIPT gboolean RunScheduledTask();
   void UpdateDragAction();
-  void DispatchMotionEvents();
+  MOZ_CAN_RUN_SCRIPT void DispatchMotionEvents();
   void ReplyToDragMotion(GdkDragContext* aDragContext);
 #ifdef MOZ_WAYLAND
   void ReplyToDragMotion(nsWaylandDragContext* aDragContext);
 #endif
   gboolean DispatchDropEvent();
   static uint32_t GetCurrentModifiers();
 };
 
--- a/widget/nsBaseDragService.h
+++ b/widget/nsBaseDragService.h
@@ -72,17 +72,17 @@ class nsBaseDragService : public nsIDrag
  protected:
   virtual ~nsBaseDragService();
 
   /**
    * Called from nsBaseDragService to initiate a platform drag from a source
    * in this process.  This is expected to ensure that StartDragSession() and
    * EndDragSession() get called if the platform drag is successfully invoked.
    */
-  virtual nsresult InvokeDragSessionImpl(
+  MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
       nsIArray* aTransferableArray,
       const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
       uint32_t aActionType) = 0;
 
   /**
    * Draw the drag image, if any, to a surface and return it. The drag image
    * is constructed from mImage if specified, or aDOMNode if mImage is null.
    *
--- a/widget/nsIDragService.idl
+++ b/widget/nsIDragService.idl
@@ -45,16 +45,17 @@ interface nsIDragService : nsISupports
     * @param  aPrincipal - the triggering principal of the drag, or null if
     *                      it's from browser chrome or OS
     * @param  aTransferables - an array of transferables to be dragged
     * @param  aActionType - specified which of copy/move/link are allowed
     * @param  aContentPolicyType - the contentPolicyType that will be
     *           passed to the loadInfo when creating a new channel
     *           (defaults to TYPE_OTHER)
     */
+  [can_run_script]
   void invokeDragSession (in Node aDOMNode,
                           in nsIPrincipal aPrincipal,
                           in nsIArray aTransferables,
                           in unsigned long aActionType,
                           [optional] in nsContentPolicyType aContentPolicyType);
 
   /**
    * Starts a modal drag session using an image. The first four arguments are
@@ -78,17 +79,17 @@ interface nsIDragService : nsISupports
    * a document, it will be rendered at its displayed size, othewise, it will be
    * rendered at its real size. For other types of elements, the element is
    * rendered into an offscreen buffer in the same manner as it is currently
    * displayed. The document selection is hidden while drawing.
    *
    * The aDragEvent must be supplied as the current screen coordinates of the
    * event are needed to calculate the image location.
    */
-  [noscript]
+  [noscript, can_run_script]
   void invokeDragSessionWithImage(in Node aDOMNode,
                                   in nsIPrincipal aPrincipal,
                                   in nsIArray aTransferableArray,
                                   in unsigned long aActionType,
                                   in Node aImage,
                                   in long aImageX,
                                   in long aImageY,
                                   in DragEvent aDragEvent,
@@ -96,16 +97,17 @@ interface nsIDragService : nsISupports
 
   /**
    * Start a modal drag session using the selection as the drag image.
    * The aDragEvent must be supplied as the current screen coordinates of the
    * event are needed to calculate the image location.
    *
    * Note: This method is deprecated for non-native code.
    */
+  [can_run_script]
   void invokeDragSessionWithSelection(in Selection aSelection,
                                       in nsIPrincipal aPrincipal,
                                       in nsIArray aTransferableArray,
                                       in unsigned long aActionType,
                                       in DragEvent aDragEvent,
                                       in DataTransferPtr aDataTransfer);
 
   /**
@@ -121,29 +123,32 @@ interface nsIDragService : nsISupports
 
   /**
     * Tells the Drag Service to end a drag session. This is called when
     * an external drag occurs
     *
     * If aDoneDrag is true, the drag has finished, otherwise the drag has
     * just left the window.
     */
+  [can_run_script]
   void endDragSession(in boolean aDoneDrag,
                       [optional] in unsigned long aKeyModifiers);
 
   /**
    * Fire a drag event at the source of the drag
    */
-  [noscript] void fireDragEventAtSource(in EventMessage aEventMessage,
-                                        in unsigned long aKeyModifiers);
+  [noscript, can_run_script]
+  void fireDragEventAtSource(in EventMessage aEventMessage,
+                             in unsigned long aKeyModifiers);
 
   /**
    * Increase/decrease dragging suppress level by one.
    * If level is greater than one, dragging is disabled.
    */
+  [can_run_script]
   void suppress();
   void unsuppress();
 
   /**
     * aX and aY are in LayoutDevice pixels.
     */
   [noscript] void dragMoved(in long aX, in long aY);
 
--- a/widget/windows/nsDragService.cpp
+++ b/widget/windows/nsDragService.cpp
@@ -246,19 +246,18 @@ static bool LayoutDevicePointToCSSPoint(
   CSSIntPoint screenOriginCSS;
   screen->GetRectDisplayPix(&screenOriginCSS.x, &screenOriginCSS.y, &w, &h);
 
   aCSSPos = (aDevPos - screenOriginDev) * devToCSSScale + screenOriginCSS;
   return true;
 }
 
 //-------------------------------------------------------------------------
-NS_IMETHODIMP
-nsDragService::StartInvokingDragSession(IDataObject* aDataObj,
-                                        uint32_t aActionType) {
+nsresult nsDragService::StartInvokingDragSession(IDataObject* aDataObj,
+                                                 uint32_t aActionType) {
   // To do the drag we need to create an object that
   // implements the IDataObject interface (for OLE)
   RefPtr<nsNativeDragSource> nativeDragSrc =
       new nsNativeDragSource(mDataTransfer);
 
   // Now figure out what the native drag effect should be
   DWORD winDropRes;
   DWORD effects = DROPEFFECT_SCROLL;
--- a/widget/windows/nsDragService.h
+++ b/widget/windows/nsDragService.h
@@ -18,34 +18,35 @@ class nsDataObjCollection;
  */
 
 class nsDragService : public nsBaseDragService {
  public:
   nsDragService();
   virtual ~nsDragService();
 
   // nsBaseDragService
-  virtual nsresult InvokeDragSessionImpl(
+  MOZ_CAN_RUN_SCRIPT virtual nsresult InvokeDragSessionImpl(
       nsIArray* anArrayTransferables,
       const mozilla::Maybe<mozilla::CSSIntRegion>& aRegion,
       uint32_t aActionType);
 
   // nsIDragSession
   NS_IMETHOD GetData(nsITransferable* aTransferable, uint32_t anItem) override;
   NS_IMETHOD GetNumDropItems(uint32_t* aNumItems) override;
   NS_IMETHOD IsDataFlavorSupported(const char* aDataFlavor,
                                    bool* _retval) override;
-  NS_IMETHOD EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) override;
+  MOZ_CAN_RUN_SCRIPT NS_IMETHOD EndDragSession(bool aDoneDrag,
+                                               uint32_t aKeyModifiers) override;
   NS_IMETHOD UpdateDragImage(nsINode* aImage, int32_t aImageX,
                              int32_t aImageY) override;
 
   // native impl.
   NS_IMETHOD SetIDataObject(IDataObject* aDataObj);
-  NS_IMETHOD StartInvokingDragSession(IDataObject* aDataObj,
-                                      uint32_t aActionType);
+  MOZ_CAN_RUN_SCRIPT nsresult StartInvokingDragSession(IDataObject* aDataObj,
+                                                       uint32_t aActionType);
 
   // A drop occurred within the application vs. outside of it.
   void SetDroppedLocal();
 
   IDataObject* GetDataObject() { return mDataObject; }
 
  protected:
   nsDataObjCollection* GetDataObjCollection(IDataObject* aDataObj);
--- a/widget/windows/nsNativeDragTarget.cpp
+++ b/widget/windows/nsNativeDragTarget.cpp
@@ -322,17 +322,18 @@ nsNativeDragTarget::DragOver(DWORD grfKe
       GetDropTargetHelper()->DragEnter(mHWnd, dragService->GetDataObject(), &pt,
                                        *pdwEffect);
     }
     POINT pt = {ptl.x, ptl.y};
     GetDropTargetHelper()->DragOver(&pt, *pdwEffect);
   }
 
   ModifierKeyState modifierKeyState;
-  mDragService->FireDragEventAtSource(eDrag, modifierKeyState.GetModifiers());
+  nsCOMPtr<nsIDragService> dragService = mDragService;
+  dragService->FireDragEventAtSource(eDrag, modifierKeyState.GetModifiers());
   // Now process the native drag state and then dispatch the event
   ProcessDrag(eDragOver, grfKeyState, ptl, pdwEffect);
 
   this->Release();
 
   return S_OK;
 }
 
@@ -358,17 +359,18 @@ nsNativeDragTarget::DragLeave() {
     currentDragSession->GetSourceNode(getter_AddRefs(sourceNode));
 
     if (!sourceNode) {
       // We're leaving a window while doing a drag that was
       // initiated in a different app. End the drag session, since
       // we're done with it for now (until the user drags back into
       // mozilla).
       ModifierKeyState modifierKeyState;
-      mDragService->EndDragSession(false, modifierKeyState.GetModifiers());
+      nsCOMPtr<nsIDragService> dragService = mDragService;
+      dragService->EndDragSession(false, modifierKeyState.GetModifiers());
     }
   }
 
   // release the ref that was taken in DragEnter
   NS_ASSERTION(mTookOwnRef, "want to release own ref, but not taken!");
   if (mTookOwnRef) {
     this->Release();
     mTookOwnRef = false;
@@ -380,17 +382,18 @@ nsNativeDragTarget::DragLeave() {
 void nsNativeDragTarget::DragCancel() {
   // Cancel the drag session if we did DragEnter.
   if (mTookOwnRef) {
     if (GetDropTargetHelper()) {
       GetDropTargetHelper()->DragLeave();
     }
     if (mDragService) {
       ModifierKeyState modifierKeyState;
-      mDragService->EndDragSession(false, modifierKeyState.GetModifiers());
+      nsCOMPtr<nsIDragService> dragService = mDragService;
+      dragService->EndDragSession(false, modifierKeyState.GetModifiers());
     }
     this->Release();  // matching the AddRef in DragEnter
     mTookOwnRef = false;
   }
 }
 
 STDMETHODIMP
 nsNativeDragTarget::Drop(LPDATAOBJECT pData, DWORD grfKeyState, POINTL aPT,
--- a/widget/windows/nsNativeDragTarget.h
+++ b/widget/windows/nsNativeDragTarget.h
@@ -43,34 +43,37 @@ class nsNativeDragTarget final : public 
   // in grfKeyState, and the coordinates specified by point. This is
   // called by OLE when a drag enters this object's window (as registered
   // by Initialize).
   STDMETHODIMP DragEnter(LPDATAOBJECT pSource, DWORD grfKeyState, POINTL point,
                          DWORD* pEffect);
 
   // Similar to DragEnter except it is called frequently while the drag
   // is over this object's window.
-  STDMETHODIMP DragOver(DWORD grfKeyState, POINTL point, DWORD* pEffect);
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY STDMETHODIMP DragOver(DWORD grfKeyState,
+                                                    POINTL point,
+                                                    DWORD* pEffect);
 
   // Release the drag-drop source and put internal state back to the point
   // before the call to DragEnter. This is called when the drag leaves
   // without a drop occurring.
-  STDMETHODIMP DragLeave();
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY STDMETHODIMP DragLeave();
 
   // If point is within our region of interest and pSource's data supports
   // one of our formats, get the data and set pEffect according to
   // grfKeyState (DROPEFFECT_MOVE if the control key was not pressed,
   // DROPEFFECT_COPY if the control key was pressed). Otherwise return
   // E_FAIL.
-  STDMETHODIMP Drop(LPDATAOBJECT pSource, DWORD grfKeyState, POINTL point,
-                    DWORD* pEffect);
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY STDMETHODIMP Drop(LPDATAOBJECT pSource,
+                                                DWORD grfKeyState, POINTL point,
+                                                DWORD* pEffect);
   /**
    * Cancel the current drag session, if any.
    */
-  void DragCancel();
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY void DragCancel();
 
   static void DragImageChanged() { gDragImageChanged = true; }
 
  protected:
   void GetGeckoDragAction(DWORD grfKeyState, LPDWORD pdwEffect,
                           uint32_t* aGeckoAction);
   void ProcessDrag(mozilla::EventMessage aEventMessage, DWORD grfKeyState,
                    POINTL pt, DWORD* pdwEffect);