From 6cbc21aa58455974b21cb3a16a06864902f8d158 Mon Sep 17 00:00:00 2001 From: Stone Shih Date: Mon, 10 Jul 2017 16:42:01 +0800 Subject: [PATCH] Bug 1355497: Ignore preventDefault on pointerdown by WebExtensions. r=smaug. Prevent default on pointerdown will stop firing the subsequent mouse events. Ignore the case that preventDefault by WebExtensions to avoid breaking some websites. MozReview-Commit-ID: 9ztW1WfEg9a --- .../content/test/webextensions/browser.ini | 1 + .../browser_permissions_pointerevent.js | 48 +++++++++++++++++++ dom/events/Event.cpp | 10 ++-- dom/events/Event.h | 3 +- widget/BasicEvents.h | 10 ++-- widget/WidgetEventImpl.cpp | 25 ++++++++++ 6 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 browser/base/content/test/webextensions/browser_permissions_pointerevent.js diff --git a/browser/base/content/test/webextensions/browser.ini b/browser/base/content/test/webextensions/browser.ini index 6041aad6b425..3dd213ffe8a2 100644 --- a/browser/base/content/test/webextensions/browser.ini +++ b/browser/base/content/test/webextensions/browser.ini @@ -27,6 +27,7 @@ support-files = [browser_permissions_mozAddonManager.js] [browser_permissions_optional.js] skip-if = !e10s +[browser_permissions_pointerevent.js] [browser_permissions_unsigned.js] skip-if = require_signing [browser_update_checkForUpdates.js] diff --git a/browser/base/content/test/webextensions/browser_permissions_pointerevent.js b/browser/base/content/test/webextensions/browser_permissions_pointerevent.js new file mode 100644 index 000000000000..b2bd376f8e76 --- /dev/null +++ b/browser/base/content/test/webextensions/browser_permissions_pointerevent.js @@ -0,0 +1,48 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +add_task(async function test_pointerevent() { + async function contentScript() { + document.addEventListener("pointerdown", async (e) => { + browser.test.assertTrue(true, "Should receive pointerdown"); + e.preventDefault(); + }); + + document.addEventListener("mousedown", (e) => { + browser.test.assertTrue(true, "Should receive mousedown"); + }); + + document.addEventListener("mouseup", (e) => { + browser.test.assertTrue(true, "Should receive mouseup"); + }); + + document.addEventListener("pointerup", (e) => { + browser.test.assertTrue(true, "Should receive pointerup"); + browser.test.sendMessage("done"); + }); + browser.test.sendMessage("pageReady"); + } + + let extension = ExtensionTestUtils.loadExtension({ + background() { + browser.test.sendMessage("ready", browser.runtime.getURL("page.html")); + }, + files: { + "page.html": ``, + "page.js": contentScript, + }, + }); + await extension.startup(); + await new Promise(resolve => { + SpecialPowers.pushPrefEnv({"set": [["dom.w3c_pointer_events.enabled", true]]}, resolve); + }); + let url = await extension.awaitMessage("ready"); + await BrowserTestUtils.withNewTab({gBrowser, url}, async browser => { + await extension.awaitMessage("pageReady"); + await BrowserTestUtils.synthesizeMouseAtCenter("html", {type: "mousedown", button: 0}, browser); + await BrowserTestUtils.synthesizeMouseAtCenter("html", {type: "mouseup", button: 0}, browser); + await extension.awaitMessage("done"); + }); + await extension.unload(); +}); diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp index 3fb19a6e1ee1..0d1285929de4 100644 --- a/dom/events/Event.cpp +++ b/dom/events/Event.cpp @@ -484,11 +484,15 @@ Event::PreventDefault(JSContext* aCx, CallerType aCallerType) // Then, JS in content mey be call preventDefault() // even in the event is in system event group. Therefore, don't refer // mInSystemGroup here. - PreventDefaultInternal(aCallerType == CallerType::System); + nsIPrincipal* principal = mIsMainThreadEvent ? + nsContentUtils::SubjectPrincipal(aCx) : nullptr; + + PreventDefaultInternal(aCallerType == CallerType::System, principal); } void -Event::PreventDefaultInternal(bool aCalledByDefaultHandler) +Event::PreventDefaultInternal(bool aCalledByDefaultHandler, + nsIPrincipal* aPrincipal) { if (!mEvent->mFlags.mCancelable) { return; @@ -507,7 +511,7 @@ Event::PreventDefaultInternal(bool aCalledByDefaultHandler) return; } - mEvent->PreventDefault(aCalledByDefaultHandler); + mEvent->PreventDefault(aCalledByDefaultHandler, aPrincipal); if (!IsTrusted()) { return; diff --git a/dom/events/Event.h b/dom/events/Event.h index fcecfe84ba63..718bc9f3604f 100644 --- a/dom/events/Event.h +++ b/dom/events/Event.h @@ -244,7 +244,8 @@ public: * by a call of Event.preventDefault() in * content script, false. */ - void PreventDefaultInternal(bool aCalledByDefaultHandler); + void PreventDefaultInternal(bool aCalledByDefaultHandler, + nsIPrincipal* aPrincipal = nullptr); bool IsMainThreadEvent() { diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h index 98faae8c96c4..81fee189e10c 100644 --- a/widget/BasicEvents.h +++ b/widget/BasicEvents.h @@ -613,13 +613,9 @@ public: */ void StopPropagation() { mFlags.StopPropagation(); } void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); } - void PreventDefault(bool aCalledByDefaultHandler = true) - { - // Legacy mouse events shouldn't be prevented on ePointerDown by default - // handlers. - MOZ_RELEASE_ASSERT(!aCalledByDefaultHandler || mMessage != ePointerDown); - mFlags.PreventDefault(aCalledByDefaultHandler); - } + void PreventDefault(bool aCalledByDefaultHandler = true, + nsIPrincipal* aPrincipal = nullptr); + void PreventDefaultBeforeDispatch() { mFlags.PreventDefaultBeforeDispatch(); } bool DefaultPrevented() const { return mFlags.DefaultPrevented(); } bool DefaultPreventedByContent() const diff --git a/widget/WidgetEventImpl.cpp b/widget/WidgetEventImpl.cpp index 03d15f5e90e2..c8549fda90c1 100644 --- a/widget/WidgetEventImpl.cpp +++ b/widget/WidgetEventImpl.cpp @@ -13,6 +13,7 @@ #include "mozilla/Preferences.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" +#include "nsContentUtils.h" #include "nsIContent.h" #include "nsIDOMEventTarget.h" #include "nsPrintfCString.h" @@ -515,6 +516,30 @@ WidgetEvent::GetOriginalDOMEventTarget() const return GetDOMEventTarget(); } +void +WidgetEvent::PreventDefault(bool aCalledByDefaultHandler, + nsIPrincipal* aPrincipal) +{ + if (mMessage == ePointerDown) { + if (aCalledByDefaultHandler) { + // Shouldn't prevent default on pointerdown by default handlers to stop + // firing legacy mouse events. Use MOZ_ASSERT to catch incorrect usages + // in debug builds. + MOZ_ASSERT(false); + return; + } + if (aPrincipal) { + nsAutoString addonId; + Unused << NS_WARN_IF(NS_FAILED(aPrincipal->GetAddonId(addonId))); + if (!addonId.IsEmpty()) { + // Ignore the case that it's called by a web extension. + return; + } + } + } + mFlags.PreventDefault(aCalledByDefaultHandler); +} + /****************************************************************************** * mozilla::WidgetInputEvent ******************************************************************************/