Bug 703150 Cannot drag scrollbar thumb if stopPropagation() of mousedown event is called r+sr=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 25 Nov 2011 10:09:58 +0900
changeset 80756 b8cf3f10e4d3
parent 80755 a31b251053fb
child 80757 a4492c6d02b0
push id21527
push usermlamouri@mozilla.com
push date2011-11-25 09:53 +0000
treeherdermozilla-central@655742c3b022 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs703150
milestone11.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 703150 Cannot drag scrollbar thumb if stopPropagation() of mousedown event is called r+sr=smaug
content/base/public/nsIAttribute.h
content/base/public/nsIContent.h
content/base/public/nsIDOMFileReader.idl
content/base/public/nsIDocument.h
content/base/public/nsINode.h
content/base/public/nsIXMLHttpRequest.idl
content/base/src/nsGenericElement.cpp
content/events/src/nsDOMEventTargetHelper.cpp
content/events/src/nsEventListenerManager.h
dom/base/nsGlobalWindow.cpp
dom/base/nsPIWindowRoot.h
dom/base/nsWindowRoot.cpp
dom/battery/nsIDOMBatteryManager.idl
dom/interfaces/events/nsIDOMEventTarget.idl
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/test/Makefile.in
layout/xul/test/test_bug703150.xul
--- a/content/base/public/nsIAttribute.h
+++ b/content/base/public/nsIAttribute.h
@@ -41,18 +41,18 @@
 #define nsIAttribute_h___
 
 #include "nsINode.h"
 
 class nsDOMAttributeMap;
 class nsIContent;
 
 #define NS_IATTRIBUTE_IID  \
-{ 0xf809b623, 0x5b1e, 0x4121, \
-  { 0xb8, 0x9d, 0x19, 0x24, 0x7b, 0x70, 0x77, 0x08 } }
+{ 0x536167ae, 0x8a9c, 0x4712, \
+  { 0x8b, 0x61, 0x3, 0x43, 0xf6, 0xbc, 0x64, 0x75 } }
 
 class nsIAttribute : public nsINode
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IATTRIBUTE_IID)
 
   virtual void SetMap(nsDOMAttributeMap *aMap) = 0;
   
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -70,18 +70,18 @@ enum nsLinkState {
   eLinkState_Unknown    = 0,
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID \
-{ 0xb651e0a7, 0x1471, 0x49cc, \
-  { 0xb4, 0xe1, 0xc2, 0xca, 0x01, 0xfe, 0xb7, 0x80 } }
+{ 0x3128b3a0, 0xb609, 0x44e3, \
+  { 0xad, 0x91, 0xdc, 0xf1, 0x4a, 0x3f, 0xf6, 0xa0 } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
 #ifdef MOZILLA_INTERNAL_API
--- a/content/base/public/nsIDOMFileReader.idl
+++ b/content/base/public/nsIDOMFileReader.idl
@@ -36,17 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
 interface nsIDOMBlob;
 interface nsIDOMFileError;
 
-[scriptable, builtinclass, uuid(fc316500-87c4-411e-ab75-dd62468f4174)]
+[scriptable, builtinclass, uuid(d158de26-904e-4731-b42c-8b3a4d172703)]
 interface nsIDOMFileReader : nsIDOMEventTarget
 {
   [implicit_jscontext]
   void readAsArrayBuffer(in nsIDOMBlob filedata);
   void readAsBinaryString(in nsIDOMBlob filedata);
   void readAsText(in nsIDOMBlob filedata, [optional] in DOMString encoding);
   void readAsDataURL(in nsIDOMBlob file);
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -119,18 +119,18 @@ class Loader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
-{ 0x184e0a3c, 0x1899, 0x417d, \
-  { 0xbf, 0xf4, 0x5a, 0x15, 0xe6, 0xe8, 0xaa, 0x94 } }
+{ 0x3b78f6, 0x6dc5, 0x44c6, \
+  { 0xbc, 0x28, 0x60, 0x2a, 0xb2, 0x4f, 0xfb, 0x7b } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -283,18 +283,18 @@ private:
 // Categories of node properties
 // 0 is global.
 #define DOM_USER_DATA         1
 #define DOM_USER_DATA_HANDLER 2
 #define SMIL_MAPPED_ATTR_ANIMVAL 3
 
 // IID for the nsINode interface
 #define NS_INODE_IID \
-{ 0x20d16be2, 0x3c58, 0x4099, \
-  { 0xbf, 0xa6, 0xd0, 0xe7, 0x6b, 0xb1, 0x3d, 0xc5 } }
+{ 0xd026d280, 0x5b25, 0x41c0, \
+  { 0x92, 0xcf, 0x6, 0xf6, 0xf, 0xb, 0x9a, 0xfe } }
 
 /**
  * An internal interface that abstracts some DOMNode-related parts that both
  * nsIContent and nsIDocument share.  An instance of this interface has a list
  * of nsIContent children and provides access to them.
  */
 class nsINode : public nsIDOMEventTarget,
                 public nsWrapperCache
@@ -723,16 +723,17 @@ public:
     return mParent && mParent->IsElement() ? mParent : nsnull;
   }
 
   /**
    * See nsIDOMEventTarget
    */
   NS_DECL_NSIDOMEVENTTARGET
   using nsIDOMEventTarget::AddEventListener;
+  using nsIDOMEventTarget::AddSystemEventListener;
 
   /**
    * Adds a mutation observer to be notified when this node, or any of its
    * descendants, are modified. The node will hold a weak reference to the
    * observer, which means that it is the responsibility of the observer to
    * remove itself in case it dies before the node.  If an observer is added
    * while observers are being notified, it may also be notified.  In general,
    * adding observers while inside a notification is not a good idea.  An
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -48,28 +48,28 @@ interface nsPIDOMWindow;
 interface nsIInputStream;
 interface nsIDOMBlob;
 
 %{C++
 // for jsval
 #include "jsapi.h"
 %}
 
-[scriptable, builtinclass, uuid(dea238a1-240f-45f4-9f07-7769bc69eb76)]
+[scriptable, builtinclass, uuid(e2b59e48-3655-4429-a94c-b4332c346ba2)]
 interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
   // event handler attributes
   attribute nsIDOMEventListener onabort;
   attribute nsIDOMEventListener onerror;
   attribute nsIDOMEventListener onload;
   attribute nsIDOMEventListener onloadstart;
   attribute nsIDOMEventListener onprogress;
   attribute nsIDOMEventListener onloadend;
 };
 
-[scriptable, builtinclass, uuid(09ff3682-7759-4441-a765-f70e1a1fabcf)]
+[scriptable, builtinclass, uuid(db9357fc-edf7-42b2-aab2-c24ab19ece20)]
 interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
   // for future use
 };
 
 /**
  * Mozilla's XMLHttpRequest is modelled after Microsoft's IXMLHttpRequest
  * object. The goal has been to make Mozilla's version match Microsoft's
  * version as closely as possible, but there are bound to be some differences.
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1092,27 +1092,51 @@ nsINode::AddEventListener(const nsAStrin
   nsEventListenerManager* listener_manager = GetListenerManager(true);
   NS_ENSURE_STATE(listener_manager);
   listener_manager->AddEventListener(aType, aListener, aUseCapture,
                                      aWantsUntrusted);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsINode::AddSystemEventListener(const nsAString& aType,
+                                nsIDOMEventListener *aListener,
+                                bool aUseCapture,
+                                bool aWantsUntrusted,
+                                PRUint8 aOptionalArgc)
+{
+  NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
+               "Won't check if this is chrome, you want to set "
+               "aWantsUntrusted to false or make the aWantsUntrusted "
+               "explicit by making aOptionalArgc non-zero.");
+
+  if (!aWantsUntrusted &&
+      (aOptionalArgc < 2 &&
+       !nsContentUtils::IsChromeDoc(OwnerDoc()))) {
+    aWantsUntrusted = true;
+  }
+
+  return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
+                                   aWantsUntrusted);
+}
+
+NS_IMETHODIMP
 nsINode::RemoveEventListener(const nsAString& aType,
                              nsIDOMEventListener* aListener,
                              bool aUseCapture)
 {
   nsEventListenerManager* elm = GetListenerManager(false);
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
   return NS_OK;
 }
 
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsINode)
+
 nsresult
 nsINode::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   // This is only here so that we can use the NS_DECL_NSIDOMTARGET macro
   NS_ABORT();
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -98,16 +98,18 @@ nsDOMEventTargetHelper::RemoveEventListe
   nsEventListenerManager* elm = GetListenerManager(false);
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
 
   return NS_OK;
 }
 
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsDOMEventTargetHelper)
+
 NS_IMETHODIMP
 nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
                                          nsIDOMEventListener *aListener,
                                          bool aUseCapture,
                                          bool aWantsUntrusted,
                                          PRUint8 aOptionalArgc)
 {
   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
@@ -126,16 +128,41 @@ nsDOMEventTargetHelper::AddEventListener
 
   nsEventListenerManager* elm = GetListenerManager(true);
   NS_ENSURE_STATE(elm);
   elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMEventTargetHelper::AddSystemEventListener(const nsAString& aType,
+                                               nsIDOMEventListener *aListener,
+                                               bool aUseCapture,
+                                               bool aWantsUntrusted,
+                                               PRUint8 aOptionalArgc)
+{
+  NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
+               "Won't check if this is chrome, you want to set "
+               "aWantsUntrusted to false or make the aWantsUntrusted "
+               "explicit by making aOptionalArgc non-zero.");
+
+  if (aOptionalArgc < 2) {
+    nsresult rv;
+    nsIScriptContext* context = GetContextForEventHandlers(&rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsIDocument> doc =
+      nsContentUtils::GetDocumentFromScriptContext(context);
+    aWantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc);
+  }
+
+  return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
+                                   aWantsUntrusted);
+}
+
+NS_IMETHODIMP
 nsDOMEventTargetHelper::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
 {
   nsEventStatus status = nsEventStatus_eIgnore;
   nsresult rv =
     nsEventDispatcher::DispatchDOMEvent(this, nsnull, aEvent, nsnull, &status);
 
   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
   return rv;
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -313,9 +313,31 @@ protected:
 
   static PRUint32                           mInstanceCount;
   static jsid                               sAddListenerID;
 
   friend class nsEventTargetChainItem;
   static PRUint32                           sCreatedCount;
 };
 
+/**
+ * NS_AddSystemEventListener() is a helper function for implementing
+ * nsIDOMEventTarget::AddSystemEventListener().
+ */
+inline nsresult
+NS_AddSystemEventListener(nsIDOMEventTarget* aTarget,
+                          const nsAString& aType,
+                          nsIDOMEventListener *aListener,
+                          bool aUseCapture,
+                          bool aWantsUntrusted)
+{
+  nsEventListenerManager* listenerManager = aTarget->GetListenerManager(true);
+  NS_ENSURE_STATE(listenerManager);
+  PRUint32 flags = NS_EVENT_FLAG_SYSTEM_EVENT;
+  flags |= aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
+  if (aWantsUntrusted) {
+    flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
+  }
+  listenerManager->AddEventListenerByType(aListener, aType, flags);
+  return NS_OK;
+}
+
 #endif // nsEventListenerManager_h__
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7371,16 +7371,18 @@ nsGlobalWindow::RemoveEventListener(cons
 {
   nsRefPtr<nsEventListenerManager> elm = GetListenerManager(false);
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
   return NS_OK;
 }
 
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindow)
+
 NS_IMETHODIMP
 nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
 {
   FORWARD_TO_INNER(DispatchEvent, (aEvent, aRetVal), NS_OK);
 
   if (!mDoc) {
     return NS_ERROR_FAILURE;
   }
@@ -7424,16 +7426,42 @@ nsGlobalWindow::AddEventListener(const n
   }
 
   nsEventListenerManager* manager = GetListenerManager(true);
   NS_ENSURE_STATE(manager);
   manager->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsGlobalWindow::AddSystemEventListener(const nsAString& aType,
+                                       nsIDOMEventListener *aListener,
+                                       bool aUseCapture,
+                                       bool aWantsUntrusted,
+                                       PRUint8 aOptionalArgc)
+{
+  NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
+               "Won't check if this is chrome, you want to set "
+               "aWantsUntrusted to false or make the aWantsUntrusted "
+               "explicit by making optional_argc non-zero.");
+
+  if (IsOuterWindow() && mInnerWindow &&
+      !nsContentUtils::CanCallerAccess(mInnerWindow)) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  if (!aWantsUntrusted &&
+      (aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
+    aWantsUntrusted = true;
+  }
+
+  return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
+                                   aWantsUntrusted);
+}
+
 nsEventListenerManager*
 nsGlobalWindow::GetListenerManager(bool aCreateIfNotFound)
 {
   FORWARD_TO_INNER_CREATE(GetListenerManager, (aCreateIfNotFound), nsnull);
 
   if (!mListenerManager && aCreateIfNotFound) {
     mListenerManager =
       new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
--- a/dom/base/nsPIWindowRoot.h
+++ b/dom/base/nsPIWindowRoot.h
@@ -45,18 +45,18 @@
 
 class nsPIDOMWindow;
 class nsIControllers;
 class nsIController;
 struct JSContext;
 
 // 426C1B56-E38A-435E-B291-BE1557F2A0A2
 #define NS_IWINDOWROOT_IID \
-{ 0x426c1b56, 0xe38a, 0x435e, \
-  { 0xb2, 0x91, 0xbe, 0x15, 0x57, 0xf2, 0xa0, 0xa2 } }
+{ 0xc89780f2, 0x8905, 0x417f, \
+  { 0xa6, 0x62, 0xf6, 0xc, 0xa6, 0xd7, 0xc, 0x91 } }
 
 class nsPIWindowRoot : public nsIDOMEventTarget
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWINDOWROOT_IID)
 
   virtual nsPIDOMWindow* GetWindow()=0;
 
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -106,16 +106,18 @@ nsWindowRoot::RemoveEventListener(const 
 {
   nsRefPtr<nsEventListenerManager> elm = GetListenerManager(false);
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
   return NS_OK;
 }
 
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsWindowRoot)
+
 NS_IMETHODIMP
 nsWindowRoot::DispatchEvent(nsIDOMEvent* aEvt, bool *aRetVal)
 {
   nsEventStatus status = nsEventStatus_eIgnore;
   nsresult rv =  nsEventDispatcher::DispatchDOMEvent(
     static_cast<nsIDOMEventTarget*>(this), nsnull, aEvt, nsnull, &status);
   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
   return rv;
@@ -144,16 +146,32 @@ nsWindowRoot::AddEventListener(const nsA
                "explicit by making optional_argc non-zero.");
 
   nsEventListenerManager* elm = GetListenerManager(true);
   NS_ENSURE_STATE(elm);
   elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsWindowRoot::AddSystemEventListener(const nsAString& aType,
+                                     nsIDOMEventListener *aListener,
+                                     bool aUseCapture,
+                                     bool aWantsUntrusted,
+                                     PRUint8 aOptionalArgc)
+{
+  NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
+               "Won't check if this is chrome, you want to set "
+               "aWantsUntrusted to false or make the aWantsUntrusted "
+               "explicit by making optional_argc non-zero.");
+
+  return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
+                                   aWantsUntrusted);
+}
+
 nsEventListenerManager*
 nsWindowRoot::GetListenerManager(bool aCreateIfNotFound)
 {
   if (!mListenerManager && aCreateIfNotFound) {
     mListenerManager =
       new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
   }
 
--- a/dom/battery/nsIDOMBatteryManager.idl
+++ b/dom/battery/nsIDOMBatteryManager.idl
@@ -33,17 +33,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
 
-[scriptable, function, uuid(98b6237b-9654-43de-97e0-acf4b091b4e7)]
+[scriptable, function, uuid(41e88f87-42cb-4db1-8724-f5456a16c410)]
 interface nsIDOMMozBatteryManager : nsIDOMEventTarget
 {
   readonly attribute double     level;
   readonly attribute boolean    charging;
   readonly attribute double     dischargingTime;
   readonly attribute double     chargingTime;
 
   attribute nsIDOMEventListener onlevelchange;
--- a/dom/interfaces/events/nsIDOMEventTarget.idl
+++ b/dom/interfaces/events/nsIDOMEventTarget.idl
@@ -64,17 +64,17 @@ class nsEventListenerManager;
 [ptr] native nsEventStatusPtr(nsEventStatus);
 [ptr] native JSContextPtr(JSContext);
 [ptr] native nsEventListenerManagerPtr(nsEventListenerManager);
 
 interface nsIScriptContext;
 interface nsIDOMEventListener;
 interface nsIDOMEvent;
 
-[scriptable, builtinclass, uuid(1797d5a4-b12a-428d-9eef-a0e13839728c)]
+[scriptable, builtinclass, uuid(8e375931-298d-4d0a-9cb4-5668f0cdc5a8)]
 interface nsIDOMEventTarget : nsISupports
 {
   /**
    * This method allows the registration of event listeners on the event target.
    * If an EventListener is added to an EventTarget while it is processing an
    * event, it will not be triggered by the current actions but may be 
    * triggered during a later stage of event flow, such as the bubbling phase.
    * 
@@ -101,32 +101,70 @@ interface nsIDOMEventTarget : nsISupport
    *                         listener will receive events whether or not
    *                         they're trusted
    */
   [optional_argc] void addEventListener(in DOMString type,
                                         in nsIDOMEventListener listener,
                                         [optional] in boolean useCapture,
                                         [optional] in boolean wantsUntrusted);
 
+  /**
+   * addSystemEventListener() adds an event listener of aType to the system
+   * group.  Typically, core code should use system group for listening to
+   * content (i.e., non-chrome) element's events.  If core code uses
+   * nsIDOMEventTarget::AddEventListener for a content node, it means
+   * that the listener cannot listen the event when web content calls
+   * stopPropagation() of the event.
+   *
+   * @param aType            An event name you're going to handle.
+   * @param aListener        An event listener.
+   * @param aUseCapture      TRUE if you want to listen the event in capturing
+   *                         phase.  Otherwise, FALSE.
+   * @param aWantsUntrusted  TRUE if you want to handle untrusted events.
+   *                         Otherwise, FALSE.
+   * @return                 NS_OK if succeed.  Otherwise, NS_ERROR_*.
+   */
+  [noscript, optional_argc] void addSystemEventListener(
+                                   in DOMString type,
+                                   in nsIDOMEventListener listener,
+                                   [optional] in boolean aUseCapture,
+                                   [optional] in boolean aWantsUntrusted);
+
 %{C++
   // non-virtual so it won't affect the vtable
   nsresult AddEventListener(const nsAString& aType,
                             nsIDOMEventListener* aListener,
                             bool aUseCapture)
   {
     return AddEventListener(aType, aListener, aUseCapture, PR_FALSE, 1);
   }
   // non-virtual so it won't affect the vtable
   nsresult AddEventListener(const nsAString& aType,
                             nsIDOMEventListener* aListener,
                             bool aUseCapture,
                             bool aWantsUntrusted)
   {
     return AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, 2);
   }
+  // non-virtual so it won't affect the vtable
+  nsresult AddSystemEventListener(const nsAString& aType,
+                                  nsIDOMEventListener* aListener,
+                                  bool aUseCapture)
+  {
+    return AddSystemEventListener(aType, aListener, aUseCapture, PR_FALSE, 1);
+  }
+  // non-virtual so it won't affect the vtable
+  nsresult AddSystemEventListener(const nsAString& aType,
+                                  nsIDOMEventListener* aListener,
+                                  bool aUseCapture,
+                                  bool aWantsUntrusted)
+  {
+    return AddSystemEventListener(aType, aListener, aUseCapture,
+                                  aWantsUntrusted, 2);
+  }
 %}
 
   /**
    * This method allows the removal of event listeners from the event 
    * target. If an EventListener is removed from an EventTarget while it 
    * is processing an event, it will not be triggered by the current actions. 
    * EventListeners can never be invoked after being removed.
    * Calling removeEventListener with arguments which do not identify any 
@@ -144,16 +182,25 @@ interface nsIDOMEventTarget : nsISupport
    *                     not affect a non-capturing version of the same 
    *                     listener, and vice versa.
    */
   void                     removeEventListener(in DOMString type,
                                                in nsIDOMEventListener listener,
                                                [optional] in boolean useCapture);
 
   /**
+   * removeSystemEventListener() should be used if you have used
+   * addSystemEventListener().
+   */
+  [noscript] void          removeSystemEventListener(
+                             in DOMString type,
+                             in nsIDOMEventListener listener,
+                             [optional] in boolean aUseCapture);
+
+  /**
    * This method allows the dispatch of events into the implementations 
    * event model. Events dispatched in this manner will have the same 
    * capturing and bubbling behavior as events dispatched directly by the 
    * implementation. The target of the event is the EventTarget on which 
    * dispatchEvent is called.
    *
    * @param   evt Specifies the event type, behavior, and contextual 
    *              information to be used in processing the event.
@@ -273,9 +320,25 @@ interface nsIDOMEventTarget : nsISupport
 typedef nsIDOMEventTarget nsPIDOMEventTarget;
 
 #define NS_IMPL_DOMTARGET_DEFAULTS(_class) \
 nsPIDOMEventTarget* _class::GetTargetForDOMEvent() { return this; } \
 nsPIDOMEventTarget* _class::GetTargetForEventTargetChain() { return this; } \
 nsresult _class::WillHandleEvent(nsEventChainPostVisitor& aVisitor) { return NS_OK; } \
 JSContext* _class::GetJSContextForEventHandlers() { return nsnull; }
 
+#define NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(aClass) \
+NS_IMETHODIMP \
+aClass::RemoveSystemEventListener(const nsAString& aType, \
+                                  nsIDOMEventListener *aListener, \
+                                  bool aUseCapture) \
+{ \
+  nsEventListenerManager* listenerManager = GetListenerManager(false); \
+  if (!listenerManager) { \
+    return NS_OK; \
+  } \
+  PRUint32 flags = NS_EVENT_FLAG_SYSTEM_EVENT; \
+  flags |= aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; \
+  listenerManager->RemoveEventListenerByType(aListener, aType, flags); \
+  return NS_OK; \
+}
+
 %}
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -49,16 +49,17 @@
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsCOMPtr.h"
 #include "nsINameSpaceManager.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLParts.h"
 #include "nsIPresShell.h"
 #include "nsCSSRendering.h"
+#include "nsEventListenerManager.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDocument.h"
 #include "nsScrollbarButtonFrame.h"
 #include "nsISliderListener.h"
 #include "nsIScrollbarMediator.h"
 #include "nsScrollbarFrame.h"
 #include "nsRepeatService.h"
@@ -969,34 +970,35 @@ nsSliderFrame::isDraggingThumb()
 void
 nsSliderFrame::AddListener()
 {
   if (!mMediator) {
     mMediator = new nsSliderMediator(this);
   }
 
   nsIFrame* thumbFrame = mFrames.FirstChild();
-  if (thumbFrame) {
-    thumbFrame->GetContent()->
-      AddEventListener(NS_LITERAL_STRING("mousedown"), mMediator, false,
-                       false);
+  if (!thumbFrame) {
+    return;
   }
+  thumbFrame->GetContent()->
+    AddSystemEventListener(NS_LITERAL_STRING("mousedown"), mMediator,
+                           false, false);
 }
 
 void
 nsSliderFrame::RemoveListener()
 {
   NS_ASSERTION(mMediator, "No listener was ever added!!");
 
   nsIFrame* thumbFrame = mFrames.FirstChild();
   if (!thumbFrame)
     return;
 
   thumbFrame->GetContent()->
-    RemoveEventListener(NS_LITERAL_STRING("mousedown"), mMediator, false);
+    RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), mMediator, false);
 }
 
 NS_IMETHODIMP
 nsSliderFrame::HandlePress(nsPresContext* aPresContext,
                            nsGUIEvent*     aEvent,
                            nsEventStatus*  aEventStatus)
 {
 #ifdef XP_MACOSX
--- a/layout/xul/test/Makefile.in
+++ b/layout/xul/test/Makefile.in
@@ -50,15 +50,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug563416.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_bug159346.xul \
 		test_bug372685.xul \
 		test_bug398982-1.xul \
 		test_bug398982-2.xul \
+		test_bug703150.xul \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/layout/xul/test/test_bug703150.xul
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        xmlns:html="http://www.w3.org/1999/xhtml"
+        title="Test for Bug 703150">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=703150
+-->
+
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <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 doTest()
+{
+  function mousedownHandler(aEvent)
+  {
+    aEvent.stopPropagation();
+  }
+  window.addEventListener("mousedown", mousedownHandler, true);
+
+  // Wait for finishing reflow...
+  SimpleTest.executeSoon(function () {
+    synthesizeMouseAtCenter(scrollbarThumb, { 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" });
+
+    window.removeEventListener("mousedown", mousedownHandler, true);
+
+    SimpleTest.finish();
+  });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+]]>
+</script>
+
+<body  id="html_body" xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=703150">Mozilla Bug 703150</a>
+<p id="display"></p>
+
+<pre id="test">
+</pre>
+<script>
+addLoadEvent(doTest);
+</script>
+</body>
+
+
+</window>