Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Bug 703150 Cannot drag scrollbar thumb if stopPropagation() of moused…

…own event is called r+sr=smaug
  • Loading branch information...
commit fa69d0e55e01d096073bd7e8263fe8d8f01e284f 1 parent 7a17752
@masayuki-nakano masayuki-nakano authored
View
4 content/base/public/nsIAttribute.h
@@ -46,8 +46,8 @@ 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
{
View
4 content/base/public/nsIContent.h
@@ -75,8 +75,8 @@ enum nsLinkState {
// 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
View
2  content/base/public/nsIDOMFileReader.idl
@@ -41,7 +41,7 @@ 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]
View
4 content/base/public/nsIDocument.h
@@ -124,8 +124,8 @@ class Element;
} // 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)
View
5 content/base/public/nsINode.h
@@ -288,8 +288,8 @@ class nsMutationGuard {
// 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
@@ -728,6 +728,7 @@ class nsINode : public nsIDOMEventTarget,
*/
NS_DECL_NSIDOMEVENTTARGET
using nsIDOMEventTarget::AddEventListener;
+ using nsIDOMEventTarget::AddSystemEventListener;
/**
* Adds a mutation observer to be notified when this node, or any of its
View
4 content/base/public/nsIXMLHttpRequest.idl
@@ -53,7 +53,7 @@ interface nsIDOMBlob;
#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;
@@ -64,7 +64,7 @@ interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
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
};
View
24 content/base/src/nsGenericElement.cpp
@@ -1097,6 +1097,28 @@ nsINode::AddEventListener(const nsAString& aType,
}
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)
@@ -1108,6 +1130,8 @@ nsINode::RemoveEventListener(const nsAString& aType,
return NS_OK;
}
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsINode)
+
nsresult
nsINode::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
View
27 content/events/src/nsDOMEventTargetHelper.cpp
@@ -103,6 +103,8 @@ nsDOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
return NS_OK;
}
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsDOMEventTargetHelper)
+
NS_IMETHODIMP
nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,
@@ -131,6 +133,31 @@ nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
}
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;
View
22 content/events/src/nsEventListenerManager.h
@@ -318,4 +318,26 @@ class nsEventListenerManager
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__
View
28 dom/base/nsGlobalWindow.cpp
@@ -7376,6 +7376,8 @@ nsGlobalWindow::RemoveEventListener(const nsAString& aType,
return NS_OK;
}
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindow)
+
NS_IMETHODIMP
nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
{
@@ -7429,6 +7431,32 @@ nsGlobalWindow::AddEventListener(const nsAString& aType,
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)
{
View
4 dom/base/nsPIWindowRoot.h
@@ -50,8 +50,8 @@ 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
{
View
18 dom/base/nsWindowRoot.cpp
@@ -111,6 +111,8 @@ nsWindowRoot::RemoveEventListener(const nsAString& aType, nsIDOMEventListener* a
return NS_OK;
}
+NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsWindowRoot)
+
NS_IMETHODIMP
nsWindowRoot::DispatchEvent(nsIDOMEvent* aEvt, bool *aRetVal)
{
@@ -149,6 +151,22 @@ nsWindowRoot::AddEventListener(const nsAString& aType,
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)
{
View
2  dom/battery/nsIDOMBatteryManager.idl
@@ -38,7 +38,7 @@
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;
View
65 dom/interfaces/events/nsIDOMEventTarget.idl
@@ -69,7 +69,7 @@ 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
{
/**
@@ -106,6 +106,28 @@ interface nsIDOMEventTarget : nsISupports
[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,
@@ -122,6 +144,22 @@ interface nsIDOMEventTarget : nsISupports
{
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);
+ }
%}
/**
@@ -149,6 +187,15 @@ interface nsIDOMEventTarget : nsISupports
[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
@@ -278,4 +325,20 @@ 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; \
+}
+
%}
View
12 layout/xul/base/src/nsSliderFrame.cpp
@@ -54,6 +54,7 @@
#include "nsHTMLParts.h"
#include "nsIPresShell.h"
#include "nsCSSRendering.h"
+#include "nsEventListenerManager.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDocument.h"
@@ -974,11 +975,12 @@ nsSliderFrame::AddListener()
}
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
@@ -991,7 +993,7 @@ nsSliderFrame::RemoveListener()
return;
thumbFrame->GetContent()->
- RemoveEventListener(NS_LITERAL_STRING("mousedown"), mMediator, false);
+ RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), mMediator, false);
}
NS_IMETHODIMP
View
1  layout/xul/test/Makefile.in
@@ -55,6 +55,7 @@ _CHROME_FILES = \
test_bug372685.xul \
test_bug398982-1.xul \
test_bug398982-2.xul \
+ test_bug703150.xul \
$(NULL)
libs:: $(_TEST_FILES)
View
69 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>
Please sign in to comment.
Something went wrong with that request. Please try again.