Bug 985988, event handlers should update preventDefault flag similar way to event.preventDefault(), r=masayuki
--- a/dom/events/Event.h
+++ b/dom/events/Event.h
@@ -199,36 +199,41 @@ public:
aRv = InitEvent(aType, aBubbles, aCancelable);
}
EventTarget* GetOriginalTarget() const;
EventTarget* GetExplicitOriginalTarget() const;
bool GetPreventDefault() const;
+ /**
+ * @param aCalledByDefaultHandler Should be true when this is called by
+ * C++ or Chrome. Otherwise, e.g., called
+ * by a call of Event.preventDefault() in
+ * content script, false.
+ */
+ void PreventDefaultInternal(bool aCalledByDefaultHandler);
+
+ bool IsMainThreadEvent()
+ {
+ return mIsMainThreadEvent;
+ }
+
protected:
// Internal helper functions
void SetEventType(const nsAString& aEventTypeArg);
already_AddRefed<nsIContent> GetTargetFromFrame();
/**
* IsChrome() returns true if aCx is chrome context or the event is created
* in chrome's thread. Otherwise, false.
*/
bool IsChrome(JSContext* aCx) const;
- /**
- * @param aCalledByDefaultHandler Should be true when this is called by
- * C++ or Chrome. Otherwise, e.g., called
- * by a call of Event.preventDefault() in
- * content script, false.
- */
- void PreventDefaultInternal(bool aCalledByDefaultHandler);
-
mozilla::WidgetEvent* mEvent;
nsRefPtr<nsPresContext> mPresContext;
nsCOMPtr<EventTarget> mExplicitOriginalTarget;
nsCOMPtr<nsPIDOMWindow> mOwner; // nsPIDOMWindow for now.
bool mEventIsInternal;
bool mPrivateDataDuplicated;
bool mIsMainThreadEvent;
};
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -125,16 +125,17 @@ FINAL_LIBRARY = 'gklayout'
LOCAL_INCLUDES += [
'/content/base/src',
'/content/html/content/src',
'/content/xml/content/src',
'/content/xul/content/src',
'/dom/base',
'/dom/settings',
'/dom/src/storage',
+ '/dom/workers',
'/js/xpconnect/wrappers',
'/layout/generic',
'/layout/xul',
'/layout/xul/tree/',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
LOCAL_INCLUDES += [
--- a/dom/events/nsJSEventListener.cpp
+++ b/dom/events/nsJSEventListener.cpp
@@ -12,16 +12,17 @@
#include "nsIXPConnect.h"
#include "nsIMutableArray.h"
#include "nsVariant.h"
#include "nsIDOMBeforeUnloadEvent.h"
#include "nsGkAtoms.h"
#include "xpcpublic.h"
#include "nsJSEnvironment.h"
#include "nsDOMJSUtils.h"
+#include "WorkerPrivate.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/Likely.h"
#include "mozilla/dom/ErrorEvent.h"
#include "mozilla/dom/UnionTypes.h"
#ifdef DEBUG
#include "nspr.h" // PR_fprintf
@@ -149,18 +150,29 @@ nsJSEventListener::IsBlackForCC()
}
return false;
}
nsresult
nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
nsCOMPtr<EventTarget> target = do_QueryInterface(mTarget);
- if (!target || !mHandler.HasEventHandler())
+ if (!target || !mHandler.HasEventHandler() ||
+ !GetHandler().Ptr()->CallbackPreserveColor()) {
return NS_ERROR_FAILURE;
+ }
+
+ Event* event = aEvent->InternalDOMEvent();
+ bool isMainThread = event->IsMainThreadEvent();
+ bool isChromeHandler =
+ isMainThread ?
+ nsContentUtils::GetObjectPrincipal(
+ GetHandler().Ptr()->CallbackPreserveColor()) ==
+ nsContentUtils::GetSystemPrincipal() :
+ mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
if (mHandler.Type() == nsEventHandler::eOnError) {
MOZ_ASSERT_IF(mEventName, mEventName == nsGkAtoms::onerror);
nsString errorMsg, file;
EventOrString msgOrEvent;
Optional<nsAString> fileName;
Optional<uint32_t> lineNumber;
@@ -194,17 +206,17 @@ nsJSEventListener::HandleEvent(nsIDOMEve
ErrorResult rv;
bool handled = handler->Call(mTarget, msgOrEvent, fileName, lineNumber,
columnNumber, error, rv);
if (rv.Failed()) {
return rv.ErrorCode();
}
if (handled) {
- aEvent->PreventDefault();
+ event->PreventDefaultInternal(isChromeHandler);
}
return NS_OK;
}
if (mHandler.Type() == nsEventHandler::eOnBeforeUnload) {
MOZ_ASSERT(mEventName == nsGkAtoms::onbeforeunload);
nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handler =
@@ -215,17 +227,17 @@ nsJSEventListener::HandleEvent(nsIDOMEve
if (rv.Failed()) {
return rv.ErrorCode();
}
nsCOMPtr<nsIDOMBeforeUnloadEvent> beforeUnload = do_QueryInterface(aEvent);
NS_ENSURE_STATE(beforeUnload);
if (!DOMStringIsNull(retval)) {
- aEvent->PreventDefault();
+ event->PreventDefaultInternal(isChromeHandler);
nsAutoString text;
beforeUnload->GetReturnValue(text);
// Set the text in the beforeUnload event as long as it wasn't
// already set (through event.returnValue, which takes
// precedence over a value returned from a JS function in IE)
if (text.IsEmpty()) {
@@ -246,17 +258,17 @@ nsJSEventListener::HandleEvent(nsIDOMEve
}
// If the handler returned false and its sense is not reversed,
// or the handler returned true and its sense is reversed from
// the usual (false means cancel), then prevent default.
if (retval.isBoolean() &&
retval.toBoolean() == (mEventName == nsGkAtoms::onerror ||
mEventName == nsGkAtoms::onmouseover)) {
- aEvent->PreventDefault();
+ event->PreventDefaultInternal(isChromeHandler);
}
return NS_OK;
}
/*
* Factory functions
*/
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -147,8 +147,9 @@ skip-if = buildapp == 'b2g' # b2g(drag e
skip-if = toolkit == 'android' #TIMED_OUT
[test_eventctors.html]
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
[test_focus_disabled.html]
[test_messageEvent.html]
[test_moz_mouse_pixel_scroll_event.html]
[test_wheel_default_action.html]
skip-if = buildapp == 'b2g' || e10s
+[test_bug985988.html]
new file mode 100644
--- /dev/null
+++ b/dom/events/test/test_bug985988.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=985988
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 985988</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 985988 **/
+
+ function handler() {
+ return false;
+ }
+
+ function reversedHandler() {
+ return true;
+ }
+
+ function test() {
+ var t = document.getElementById("testtarget");
+
+ t.onclick = handler;
+ var e = new MouseEvent("click", {cancelable: true});
+ t.dispatchEvent(e);
+ ok(e.defaultPrevented, "Should have prevented default handling.");
+
+ t.onclick = reversedHandler;
+ e = new MouseEvent("click", {cancelable: true});
+ t.dispatchEvent(e);
+ ok(!e.defaultPrevented, "Shouldn't have prevented default handling.");
+
+ // mouseover has reversed meaning for handler return value.
+ t.onmouseover = reversedHandler;
+ e = new MouseEvent("mouseover", {cancelable: true});
+ t.dispatchEvent(e);
+ ok(e.defaultPrevented, "Should have prevented default handling.");
+
+ t.onmouseover = handler;
+ e = new MouseEvent("mouseover", {cancelable: true});
+ t.dispatchEvent(e);
+ ok(!e.defaultPrevented, "Shouldn't have prevented default handling.");
+
+ // error has reversed meaning for handler return value.
+ t.onerror = reversedHandler;
+ e = new ErrorEvent("error", {cancelable: true});
+ t.dispatchEvent(e);
+ ok(e.defaultPrevented, "Should have prevented default handling.");
+
+ t.onerror = handler;
+ e = new MouseEvent("error", {cancelable: true});
+ t.dispatchEvent(e);
+ ok(!e.defaultPrevented, "Shouldn't have prevented default handling.");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(test);
+
+ </script>
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=985988">Mozilla Bug 985988</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<a href="#" id="testtarget">test target</a>
+<pre id="test">
+</pre>
+</body>
+</html>