Bug 1431246 - Create and update scrollbar markup in nsScrollbarFrame draft
authorTimothy Guan-tin Chien <timdream@gmail.com>
Mon, 09 Apr 2018 22:01:02 +0800
changeset 780853 70b7369b7b161c90e67669e74cdba29bc4357518
parent 779089 b4bc6b2401738b78fd47127a4c716bb9178e1a09
push id106143
push usertimdream@gmail.com
push dateThu, 12 Apr 2018 05:08:11 +0000
bugs1431246
milestone61.0a1
Bug 1431246 - Create and update scrollbar markup in nsScrollbarFrame nsScrollbarFrame::CopyAttributeValueToChildren() creates the children markup originally created by XBL. The attributes updated by XBL attribute inheritance is updated by nsScrollbarFrame::CopyAttributeValueToChildren(). This removes the XBL part of scrollbar implementation. MozReview-Commit-ID: FWi3HR2qkwF
layout/xul/nsScrollbarFrame.cpp
layout/xul/nsScrollbarFrame.h
layout/xul/test/test_bug159346.xul
layout/xul/test/test_bug703150.xul
toolkit/content/jar.mn
toolkit/content/widgets/scrollbar.xml
toolkit/themes/osx/global/nativescrollbars.css
toolkit/themes/windows/global/xulscrollbars.css
widget/tests/test_bug485118.xul
--- a/layout/xul/nsScrollbarFrame.cpp
+++ b/layout/xul/nsScrollbarFrame.cpp
@@ -9,16 +9,17 @@
 // Netscape Communications
 //
 // See documentation in associated header file
 //
 
 #include "nsScrollbarFrame.h"
 #include "nsSliderFrame.h"
 #include "nsScrollbarButtonFrame.h"
+#include "nsContentCreatorFunctions.h"
 #include "nsGkAtoms.h"
 #include "nsIScrollableFrame.h"
 #include "nsIScrollbarMediator.h"
 #include "mozilla/LookAndFeel.h"
 #include "nsThemeConstants.h"
 #include "nsIContent.h"
 #include "mozilla/dom/MutationEventBinding.h"
 
@@ -34,32 +35,43 @@ NS_NewScrollbarFrame(nsIPresShell* aPres
 {
   return new (aPresShell) nsScrollbarFrame(aStyle);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarFrame)
 
 NS_QUERYFRAME_HEAD(nsScrollbarFrame)
   NS_QUERYFRAME_ENTRY(nsScrollbarFrame)
+  NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
 
 void
 nsScrollbarFrame::Init(nsIContent*       aContent,
                        nsContainerFrame* aParent,
                        nsIFrame*         aPrevInFlow)
 {
   nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
 
   // We want to be a reflow root since we use reflows to move the
   // slider.  Any reflow inside the scrollbar frame will be a reflow to
   // move the slider and will thus not change anything outside of the
   // scrollbar or change the size of the scrollbar frame.
   AddStateBits(NS_FRAME_REFLOW_ROOT);
 }
 
+void nsScrollbarFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
+{
+  aPostDestroyData.AddAnonymousContent(mUpTopButton.forget());
+  aPostDestroyData.AddAnonymousContent(mDownTopButton.forget());
+  aPostDestroyData.AddAnonymousContent(mSlider.forget());
+  aPostDestroyData.AddAnonymousContent(mUpBottomButton.forget());
+  aPostDestroyData.AddAnonymousContent(mDownBottomButton.forget());
+  nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
+}
+
 void
 nsScrollbarFrame::Reflow(nsPresContext*          aPresContext,
                          ReflowOutput&     aDesiredSize,
                          const ReflowInput& aReflowInput,
                          nsReflowStatus&          aStatus)
 {
   MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
 
@@ -78,16 +90,19 @@ nsScrollbarFrame::Reflow(nsPresContext* 
 nsresult
 nsScrollbarFrame::AttributeChanged(int32_t aNameSpaceID,
                                    nsAtom* aAttribute,
                                    int32_t aModType)
 {
   nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
                                              aModType);
 
+  // Update value in our children
+  UpdateChildrenAttributeValue(aAttribute, true);
+
   // if the current position changes, notify any nsGfxScrollFrame
   // parent we may have
   if (aAttribute != nsGkAtoms::curpos)
     return rv;
 
   nsIScrollableFrame* scrollable = do_QueryFrame(GetParent());
   if (!scrollable)
     return rv;
@@ -286,8 +301,218 @@ nsScrollbarFrame::MoveToNewPosition()
           return curpos;
         }
       }
     }
   }
   content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
   return curpos;
 }
+
+nsresult
+nsScrollbarFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
+{
+  // <xul:scrollbarbutton sbattr="scrollbar-up-top" type="decrement" xbl:inherits="curpos,maxpos,disabled"/>
+  // <xul:scrollbarbutton sbattr="scrollbar-down-top" type="increment" xbl:inherits="curpos,maxpos,disabled"/>
+  // <xul:slider flex="1" xbl:inherits="disabled,curpos,maxpos,pageincrement,increment,orient">
+  //   <xul:thumb sbattr="scrollbar-thumb" xbl:inherits="orient,collapsed=disabled"
+  //              align="center" pack="center"/>
+  // </xul:slider>
+  // <xul:scrollbarbutton sbattr="scrollbar-up-bottom" type="decrement" xbl:inherits="curpos,maxpos,disabled"/>
+  // <xul:scrollbarbutton sbattr="scrollbar-down-bottom" type="increment" xbl:inherits="curpos,maxpos,disabled"/>
+
+  nsNodeInfoManager* nodeInfoManager = mContent->NodeInfo()->NodeInfoManager();
+
+  nsAutoString orient;
+  GetContent()->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient);
+
+  NS_TrustedNewXULElement(getter_AddRefs(mUpTopButton),
+    nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
+                                 kNameSpaceID_XUL,
+                                 nsINode::ELEMENT_NODE)
+  );
+  mUpTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
+                        NS_LITERAL_STRING("scrollbar-up-top"), false);
+  mUpTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
+                        NS_LITERAL_STRING("decrement"), false);
+
+  if (!aElements.AppendElement(mUpTopButton)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  NS_TrustedNewXULElement(getter_AddRefs(mDownTopButton),
+    nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
+                                 kNameSpaceID_XUL,
+                                 nsINode::ELEMENT_NODE)
+  );
+  mDownTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
+                          NS_LITERAL_STRING("scrollbar-down-top"), false);
+  mDownTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
+                          NS_LITERAL_STRING("increment"), false);
+
+  if (!aElements.AppendElement(mDownTopButton)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  NS_TrustedNewXULElement(getter_AddRefs(mSlider),
+    nodeInfoManager->GetNodeInfo(nsGkAtoms::slider, nullptr,
+                                 kNameSpaceID_XUL,
+                                 nsINode::ELEMENT_NODE)
+  );
+  mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false);
+  mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::flex,
+                   NS_LITERAL_STRING("1"), false);
+  mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::align,
+                   NS_LITERAL_STRING("center"), false);
+  mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::pack,
+                   NS_LITERAL_STRING("center"), false);
+
+  if (!aElements.AppendElement(mSlider)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  NS_TrustedNewXULElement(getter_AddRefs(mThumb),
+    nodeInfoManager->GetNodeInfo(nsGkAtoms::thumb, nullptr,
+                                 kNameSpaceID_XUL,
+                                 nsINode::ELEMENT_NODE)
+  );
+  mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
+                  NS_LITERAL_STRING("scrollbar-thumb"), false);
+  mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false);
+  mSlider->AppendChildTo(mThumb, false);
+
+  NS_TrustedNewXULElement(getter_AddRefs(mUpBottomButton),
+    nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
+                                 kNameSpaceID_XUL,
+                                 nsINode::ELEMENT_NODE)
+  );
+  mUpBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
+                           NS_LITERAL_STRING("decrement"), false);
+  mUpBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
+                           NS_LITERAL_STRING("scrollbar-up-bottom"), false);
+
+  if (!aElements.AppendElement(mUpBottomButton)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  NS_TrustedNewXULElement(getter_AddRefs(mDownBottomButton),
+    nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr,
+                                 kNameSpaceID_XUL,
+                                 nsINode::ELEMENT_NODE)
+  );
+  mDownBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr,
+                             NS_LITERAL_STRING("scrollbar-down-bottom"), false);
+  mDownBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
+                             NS_LITERAL_STRING("increment"), false);
+
+  if (!aElements.AppendElement(mDownBottomButton)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  UpdateChildrenAttributeValue(nsGkAtoms::curpos, false);
+  UpdateChildrenAttributeValue(nsGkAtoms::maxpos, false);
+  UpdateChildrenAttributeValue(nsGkAtoms::disabled, false);
+  UpdateChildrenAttributeValue(nsGkAtoms::pageincrement, false);
+  UpdateChildrenAttributeValue(nsGkAtoms::increment, false);
+
+  return NS_OK;
+}
+
+void
+nsScrollbarFrame::UpdateChildrenAttributeValue(nsAtom* aAttribute, bool aNotify)
+{
+  Element* el(GetContent()->AsElement());
+
+  nsAutoString value;
+  el->GetAttr(kNameSpaceID_None, aAttribute, value);
+
+  if (aAttribute == nsGkAtoms::curpos ||
+      aAttribute == nsGkAtoms::maxpos) {
+    if (mUpTopButton) {
+      mUpTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+    }
+    if (mDownTopButton) {
+      mDownTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+    }
+    if (mSlider) {
+      mSlider->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+    }
+    if (mUpBottomButton) {
+      mUpBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+    }
+    if (mDownBottomButton) {
+      mDownBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+    }
+  }
+  else if (aAttribute == nsGkAtoms::disabled) {
+    bool isDisabled = el->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
+    if (isDisabled) {
+      if (mUpTopButton) {
+        mUpTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+      }
+      if (mDownTopButton) {
+        mDownTopButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+      }
+      if (mSlider) {
+        mSlider->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+      }
+      if (mThumb) {
+        mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::collapsed, value, aNotify);
+      }
+      if (mUpBottomButton) {
+        mUpBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+      }
+      if (mDownBottomButton) {
+        mDownBottomButton->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+      }
+    } else {
+      if (mUpTopButton) {
+        mUpTopButton->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
+      }
+      if (mDownTopButton) {
+        mDownTopButton->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
+      }
+      if (mSlider) {
+        mSlider->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
+      }
+      if (mThumb) {
+        mThumb->UnsetAttr(kNameSpaceID_None, nsGkAtoms::collapsed, aNotify);
+      }
+      if (mUpBottomButton) {
+        mUpBottomButton->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
+      }
+      if (mDownBottomButton) {
+        mDownBottomButton->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
+      }
+    }
+  }
+  else if (aAttribute == nsGkAtoms::pageincrement ||
+           aAttribute == nsGkAtoms::increment) {
+    if (mSlider) {
+      mSlider->SetAttr(kNameSpaceID_None, aAttribute, value, aNotify);
+    }
+  }
+}
+
+void
+nsScrollbarFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
+                                           uint32_t aFilter)
+{
+  if (mUpTopButton) {
+    aElements.AppendElement(mUpTopButton);
+  }
+
+  if (mDownTopButton) {
+    aElements.AppendElement(mDownTopButton);
+  }
+
+  if (mSlider) {
+    aElements.AppendElement(mSlider);
+  }
+
+  if (mUpBottomButton) {
+    aElements.AppendElement(mUpBottomButton);
+  }
+
+  if (mDownBottomButton) {
+    aElements.AppendElement(mDownBottomButton);
+  }
+}
--- a/layout/xul/nsScrollbarFrame.h
+++ b/layout/xul/nsScrollbarFrame.h
@@ -7,31 +7,39 @@
 //
 // nsScrollbarFrame
 //
 
 #ifndef nsScrollbarFrame_h__
 #define nsScrollbarFrame_h__
 
 #include "mozilla/Attributes.h"
+#include "nsIAnonymousContentCreator.h"
 #include "nsBoxFrame.h"
 
 class nsIScrollbarMediator;
 
 nsIFrame* NS_NewScrollbarFrame(nsIPresShell* aPresShell,
                                mozilla::ComputedStyle* aStyle);
 
-class nsScrollbarFrame final : public nsBoxFrame
+class nsScrollbarFrame final : public nsBoxFrame,
+                               public nsIAnonymousContentCreator
 {
 public:
   explicit nsScrollbarFrame(ComputedStyle* aStyle)
     : nsBoxFrame(aStyle, kClassID)
     , mIncrement(0)
     , mSmoothScroll(false)
     , mScrollbarMediator(nullptr)
+    , mUpTopButton(nullptr)
+    , mDownTopButton(nullptr)
+    , mSlider(nullptr)
+    , mThumb(nullptr)
+    , mUpBottomButton(nullptr)
+    , mDownBottomButton(nullptr)
   {}
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS(nsScrollbarFrame)
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("ScrollbarFrame"), aResult);
@@ -55,16 +63,18 @@ public:
   NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
                         mozilla::WidgetGUIEvent* aEvent,
                         nsEventStatus* aEventStatus) override;
 
   NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
                            mozilla::WidgetGUIEvent* aEvent,
                            nsEventStatus* aEventStatus) override;
 
+  virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
+
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
   virtual void Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus) override;
@@ -96,17 +106,31 @@ public:
    * MoveToNewPosition() adds mIncrement to the current position and
    * updates the curpos attribute.
    * @returns The new position after clamping, in CSS Pixels
    * @note This method might destroy the frame, pres shell, and other objects.
    */
   int32_t MoveToNewPosition();
   int32_t GetIncrement() { return mIncrement; }
 
+  // nsIAnonymousContentCreator
+  virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
+  virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
+                                        uint32_t aFilter) override;
+
+  void UpdateChildrenAttributeValue(nsAtom* aAttribute, bool aNotify);
+
 protected:
   int32_t mIncrement; // Amount to scroll, in CSSPixels
   bool mSmoothScroll;
 
 private:
   nsCOMPtr<nsIContent> mScrollbarMediator;
+
+  nsCOMPtr<Element> mUpTopButton;
+  nsCOMPtr<Element> mDownTopButton;
+  nsCOMPtr<Element> mSlider;
+  nsCOMPtr<Element> mThumb;
+  nsCOMPtr<Element> mUpBottomButton;
+  nsCOMPtr<Element> mDownBottomButton;
 }; // class nsScrollbarFrame
 
 #endif
--- a/layout/xul/test/test_bug159346.xul
+++ b/layout/xul/test/test_bug159346.xul
@@ -12,44 +12,59 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
 <scrollbar id="scrollbar" curpos="0" maxpos="500"/>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
 var scrollbar = document.getElementById("scrollbar");
-var downButton =
-  document.getAnonymousElementByAttribute(scrollbar, "sbattr",
-                                          "scrollbar-down-bottom");
+
+var domWinUtils = SpecialPowers.DOMWindowUtils;
+  domWinUtils.loadSheetUsingURIString('data:text/css,@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); scrollbarbutton[type="increment"][sbattr="scrollbar-down-bottom"] { display: -moz-box; }', domWinUtils.AGENT_SHEET);
+
+function synthesizeMouseAtButton(aEvent) {
+  // Target at <scrollbarbutton sbattr="scrollbar-down-bottom">
+  var rect = SpecialPowers.unwrap(
+    SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)[4])
+      .getBoundingClientRect();
+    synthesizeMouseAtPoint(rect.x + rect.width / 2, rect.y + rect.height / 2, aEvent);
+}
+
+function synthesizeMouseOutsideScrollbar(aEvent) {
+  // Target at <scrollbarbutton sbattr="scrollbar-down-bottom">
+  var rect = SpecialPowers.unwrap(
+    SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)[4])
+      .getBoundingClientRect();
+    synthesizeMouseAtPoint(rect.x - 10, rect.y - 10, aEvent);
+}
 
 function init()
 {
-  downButton.style.display = "-moz-box";
   SimpleTest.executeSoon(doTest1);
 }
 
 function getCurrentPos()
 {
   return Number(scrollbar.getAttribute("curpos"));
 }
 
 function doTest1()
 {
   var lastPos = 0;
 
-  synthesizeMouseAtCenter(downButton, { type: "mousedown" });
+  synthesizeMouseAtButton({ type: "mousedown" });
   ok(getCurrentPos() > lastPos,
      "scrollbar didn't change curpos by mousedown #1");
   lastPos = getCurrentPos();
 
   setTimeout(function () {
     ok(getCurrentPos() > lastPos,
        "scrollbar didn't change curpos by auto repeat #1");
-    synthesizeMouseAtCenter(downButton, { type: "mouseup" });
+    synthesizeMouseAtButton({ type: "mouseup" });
     lastPos = getCurrentPos();
 
     setTimeout(function () {
       is(getCurrentPos(), lastPos,
          "scrollbar changed curpos after mouseup #1");
       SimpleTest.executeSoon(doTest2);
     }, 1000);
   }, 1000);
@@ -57,62 +72,62 @@ function doTest1()
 
 function doTest2()
 {
   SpecialPowers.setIntPref("ui.scrollbarButtonAutoRepeatBehavior", 0);
 
   scrollbar.setAttribute("curpos", 0);
   var lastPos = 0;
 
-  synthesizeMouseAtCenter(downButton, { type: "mousedown" });
+  synthesizeMouseAtButton({ type: "mousedown" });
   ok(getCurrentPos() > lastPos,
      "scrollbar didn't change curpos by mousedown #2");
   lastPos = getCurrentPos();
 
-  synthesizeMouse(downButton, -10, -10, { type: "mousemove" });
+  synthesizeMouseOutsideScrollbar({ type: "mousemove" });
   lastPos = getCurrentPos();
 
   setTimeout(function () {
     is(getCurrentPos(), lastPos,
        "scrollbar changed curpos by auto repeat when cursor is outside of scrollbar button #2");
-    synthesizeMouseAtCenter(downButton, { type: "mousemove" });
+    synthesizeMouseAtButton({ type: "mousemove" });
     lastPos = getCurrentPos();
 
     setTimeout(function () {
       ok(getCurrentPos() > lastPos,
          "scrollbar didn't change curpos by mousemove after cursor is back on the scrollbar button #2");
-      synthesizeMouseAtCenter(downButton, { type: "mouseup" });
+      synthesizeMouseAtButton({ type: "mouseup" });
       SimpleTest.executeSoon(doTest3);
     }, 1000);
   }, 1000);
 }
 
 function doTest3()
 {
   SpecialPowers.setIntPref("ui.scrollbarButtonAutoRepeatBehavior", 1);
 
   scrollbar.setAttribute("curpos", 0);
   var lastPos = 0;
 
-  synthesizeMouseAtCenter(downButton, { type: "mousedown" });
+  synthesizeMouseAtButton({ type: "mousedown" });
   ok(getCurrentPos() > lastPos,
      "scrollbar didn't change curpos by mousedown #3");
-  synthesizeMouse(downButton, -10, -10, { type: "mousemove" });
+  synthesizeMouseOutsideScrollbar({ type: "mousemove" });
   lastPos = getCurrentPos();
 
   setTimeout(function () {
     ok(getCurrentPos() > lastPos,
        "scrollbar didn't change curpos by auto repeat when cursor is outside of scrollbar button #3");
-    synthesizeMouseAtCenter(downButton, { type: "mousemove" });
+    synthesizeMouseAtButton({ type: "mousemove" });
     lastPos = getCurrentPos();
 
     setTimeout(function () {
       ok(getCurrentPos() > lastPos,
          "scrollbar didn't change curpos by mousemove after cursor is back on the scrollbar button #3");
-      synthesizeMouseAtCenter(downButton, { type: "mouseup" });
+      synthesizeMouseAtButton({ type: "mouseup" });
 
       SpecialPowers.clearUserPref("ui.scrollbarButtonAutoRepeatBehavior");
       SimpleTest.finish();
     }, 1000);
   }, 1000);
 }
 
 SimpleTest.waitForExplicitFinish();
--- a/layout/xul/test/test_bug703150.xul
+++ b/layout/xul/test/test_bug703150.xul
@@ -12,41 +12,45 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
 <scrollbar id="scrollbar" curpos="0" maxpos="500"/>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
 var scrollbar = document.getElementById("scrollbar");
-var scrollbarThumb =
-  document.getAnonymousElementByAttribute(scrollbar, "sbattr",
-                                          "scrollbar-thumb");
+
+function synthesizeMouseAtThumb(aEvent) {
+  var thumbRect = SpecialPowers.unwrap(
+    SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)[2])
+      .childNodes[0].getBoundingClientRect();
+    synthesizeMouseAtPoint(thumbRect.x + thumbRect.width / 2, thumbRect.y + thumbRect.height / 2, aEvent);
+}
 
 function doTest()
 {
   function mousedownHandler(aEvent)
   {
     aEvent.stopPropagation();
   }
   window.addEventListener("mousedown", mousedownHandler, true);
 
   // Wait for finishing reflow...
   SimpleTest.executeSoon(function () {
-    synthesizeMouseAtCenter(scrollbarThumb, { type: "mousedown" });
+    synthesizeMouseAtThumb({ type: "mousedown" });
 
     is(scrollbar.getAttribute("curpos"), "0",
        "scrollbar thumb has been moved already");
 
     synthesizeMouseAtCenter(scrollbar, { type: "mousemove" });
 
     ok(scrollbar.getAttribute("curpos") > 0,
        "scrollbar thumb hasn't been dragged");
 
-    synthesizeMouseAtCenter(scrollbarThumb, { type: "mouseup" });
+    synthesizeMouseAtThumb({ type: "mouseup" });
 
     window.removeEventListener("mousedown", mousedownHandler, true);
 
     SimpleTest.finish();
   });
 }
 
 SimpleTest.waitForExplicitFinish();
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -85,17 +85,16 @@ toolkit.jar:
    content/global/bindings/numberbox.xml       (widgets/numberbox.xml)
    content/global/bindings/popup.xml           (widgets/popup.xml)
    content/global/bindings/progressmeter.xml   (widgets/progressmeter.xml)
    content/global/bindings/radio.xml           (widgets/radio.xml)
    content/global/bindings/remote-browser.xml  (widgets/remote-browser.xml)
    content/global/bindings/resizer.xml         (widgets/resizer.xml)
    content/global/bindings/richlistbox.xml     (widgets/richlistbox.xml)
    content/global/bindings/scale.xml           (widgets/scale.xml)
-   content/global/bindings/scrollbar.xml       (widgets/scrollbar.xml)
    content/global/bindings/scrollbox.xml       (widgets/scrollbox.xml)
    content/global/bindings/spinner.js          (widgets/spinner.js)
    content/global/bindings/stringbundle.xml    (widgets/stringbundle.xml)
 *  content/global/bindings/tabbox.xml          (widgets/tabbox.xml)
    content/global/bindings/text.xml            (widgets/text.xml)
 *  content/global/bindings/textbox.xml         (widgets/textbox.xml)
    content/global/bindings/timekeeper.js       (widgets/timekeeper.js)
    content/global/bindings/timepicker.js       (widgets/timepicker.js)
deleted file mode 100644
--- a/toolkit/content/widgets/scrollbar.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<bindings id="scrollbarBindings"
-   xmlns="http://www.mozilla.org/xbl"
-   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-   xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <binding id="scrollbar" bindToUntrustedContent="true">
-    <content clickthrough="always">
-      <xul:scrollbarbutton sbattr="scrollbar-up-top" type="decrement" xbl:inherits="curpos,maxpos,disabled"/>
-      <xul:scrollbarbutton sbattr="scrollbar-down-top" type="increment" xbl:inherits="curpos,maxpos,disabled"/>
-      <xul:slider flex="1" xbl:inherits="disabled,curpos,maxpos,pageincrement,increment,orient">
-        <xul:thumb sbattr="scrollbar-thumb" xbl:inherits="orient,collapsed=disabled"
-                   align="center" pack="center"/>
-      </xul:slider>
-      <xul:scrollbarbutton sbattr="scrollbar-up-bottom" type="decrement" xbl:inherits="curpos,maxpos,disabled"/>
-      <xul:scrollbarbutton sbattr="scrollbar-down-bottom" type="increment" xbl:inherits="curpos,maxpos,disabled"/>
-    </content>
-  </binding>
-</bindings>
--- a/toolkit/themes/osx/global/nativescrollbars.css
+++ b/toolkit/themes/osx/global/nativescrollbars.css
@@ -2,17 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
 
 scrollbar {
   -moz-appearance: scrollbar;
-  -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#scrollbar);
   cursor: default;
   background-color: white;
 }
 
 scrollbar[root="true"] {
   position: relative;
   z-index: 2147483647; /* largest positive value of a signed 32-bit integer */
 }
@@ -77,12 +76,11 @@ scrollcorner {
   cursor: default;
   background-color: white;
 }
 
 /* ::::::::::::::::::::: MEDIA PRINT :::::::::::::::::::::: */
 @media print {
   html|div scrollbar {
     -moz-appearance: scrollbar;
-    -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#scrollbar);
     cursor: default;
   }
 }
--- a/toolkit/themes/windows/global/xulscrollbars.css
+++ b/toolkit/themes/windows/global/xulscrollbars.css
@@ -8,17 +8,16 @@
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml"); /* namespace for HTML elements */
 
 /* ::::: scrollbar ::::: */
 
 scrollbar {
   -moz-appearance: scrollbar-horizontal;
-  -moz-binding: url("chrome://global/content/bindings/scrollbar.xml#scrollbar");
   cursor: default;
 }
 
 @media all and (-moz-overlay-scrollbars) {
   scrollbar[root="true"] {
     position: relative;
     z-index: 2147483647; /* largest positive value of a signed 32-bit integer */
   }
--- a/widget/tests/test_bug485118.xul
+++ b/widget/tests/test_bug485118.xul
@@ -8,17 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <window title="Mozilla Bug 485118"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
 <body  xmlns="http://www.w3.org/1999/xhtml">
 <div id="content" style="display: none">
-  
+
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <hbox height="300">
   <vbox width="300">
     <scrollbar orient="horizontal"
@@ -49,17 +49,19 @@ https://bugzilla.mozilla.org/show_bug.cg
 <![CDATA[
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   ["horizontal", "vertical"].forEach(function (orient) {
     ["", "Small"].forEach(function (size) {
       var elem = document.getElementById(orient + size);
-      var thumbRect = document.getAnonymousElementByAttribute(elem, 'sbattr', 'scrollbar-thumb').getBoundingClientRect();
+      var thumbRect = SpecialPowers.unwrap(
+        SpecialPowers.InspectorUtils.getChildrenForNode(elem, true)[2])
+        .childNodes[0].getBoundingClientRect();
       var sizeToCheck = orient == "horizontal" ? "width" : "height";
       // var expectedSize = size == "Small" ? 19 : 26;
       var expectedSize = 26;
       is(thumbRect[sizeToCheck], expectedSize, size + " scrollbar has wrong minimum " + sizeToCheck);
     });
   });
   SimpleTest.finish();
 }