Bug 1481923 - Make nsContentUtils::SendMouseEvent return the information where preventDefault() was called. r=masayuki

On a long press touch event we fire a contextmenu event and if the contextmenu
is opening, we fire a touchcancel event. Unfortunately we had been checking
the return value, nsEventStatus, from nsIWidget::DispatchInputEvent via
nsContentUtils::SendMouseEvent to tell whether the context menu is opening or
not. So, we unintentionally fire the touchcancel event if the context menu is
NOT going to be opened because of preventDefault() in a contextmenu event
listener in the content itself.

NOTE: The oparator<< for the new PreventDefaultResult enum will be used in
APZ logging code.

[1] https://searchfox.org/mozilla-central/rev/95c41d54c3fd65d51976d5188842a69b459a7589/mobile/android/actors/ContentDelegateChild.jsm#100

Differential Revision: https://phabricator.services.mozilla.com/D115963
This commit is contained in:
Hiroyuki Ikezoe 2021-06-01 05:47:29 +00:00
Родитель 1ba472c91b
Коммит aafeee2434
4 изменённых файлов: 53 добавлений и 9 удалений

Просмотреть файл

@ -8196,7 +8196,7 @@ nsresult nsContentUtils::SendMouseEvent(
int32_t aButton, int32_t aButtons, int32_t aClickCount, int32_t aModifiers,
bool aIgnoreRootScrollFrame, float aPressure,
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
bool* aPreventDefault, bool aIsDOMEventSynthesized,
PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized,
bool aIsWidgetEventSynthesized) {
nsPoint offset;
nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
@ -8278,7 +8278,15 @@ nsresult nsContentUtils::SendMouseEvent(
NS_ENSURE_SUCCESS(rv, rv);
}
if (aPreventDefault) {
*aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
if (status == nsEventStatus_eConsumeNoDefault) {
if (event.mFlags.mDefaultPreventedByContent) {
*aPreventDefault = PreventDefaultResult::ByContent;
} else {
*aPreventDefault = PreventDefaultResult::ByChrome;
}
} else {
*aPreventDefault = PreventDefaultResult::No;
}
}
return NS_OK;
@ -10602,3 +10610,21 @@ nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL,
}
return spec;
}
namespace mozilla {
std::ostream& operator<<(std::ostream& aOut,
const PreventDefaultResult aPreventDefaultResult) {
switch (aPreventDefaultResult) {
case PreventDefaultResult::No:
aOut << "unhandled";
break;
case PreventDefaultResult::ByContent:
aOut << "handled-by-content";
break;
case PreventDefaultResult::ByChrome:
aOut << "handled-by-chrome";
break;
}
return aOut;
}
} // namespace mozilla

Просмотреть файл

@ -245,6 +245,10 @@ struct EventNameMapping {
bool mMaybeSpecialSVGorSMILEvent;
};
namespace mozilla {
enum class PreventDefaultResult : uint8_t { No, ByContent, ByChrome };
}
class nsContentUtils {
friend class nsAutoScriptBlockerSuppressNodeRemoved;
typedef mozilla::dom::Element Element;
@ -2916,8 +2920,8 @@ class nsContentUtils {
float aY, int32_t aButton, int32_t aButtons, int32_t aClickCount,
int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure,
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
bool* aPreventDefault, bool aIsDOMEventSynthesized,
bool aIsWidgetEventSynthesized);
mozilla::PreventDefaultResult* aPreventDefault,
bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized);
static void FirePageShowEventForFrameLoaderSwap(
nsIDocShellTreeItem* aItem,
@ -3492,6 +3496,12 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) {
}
}
namespace mozilla {
std::ostream& operator<<(
std::ostream& aOut,
const mozilla::PreventDefaultResult aPreventDefaultResult);
} // namespace mozilla
class MOZ_RAII nsAutoScriptBlocker {
public:
explicit nsAutoScriptBlocker() { nsContentUtils::AddScriptBlocker(); }

Просмотреть файл

@ -725,10 +725,17 @@ nsDOMWindowUtils::SendMouseEventCommon(
bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized,
bool aIsWidgetEventSynthesized, int32_t aButtons) {
RefPtr<PresShell> presShell = GetPresShell();
return nsContentUtils::SendMouseEvent(
PreventDefaultResult preventDefaultResult;
nsresult rv = nsContentUtils::SendMouseEvent(
presShell, aType, aX, aY, aButton, aButtons, aClickCount, aModifiers,
aIgnoreRootScrollFrame, aPressure, aInputSourceArg, aPointerId, aToWindow,
aPreventDefault, aIsDOMEventSynthesized, aIsWidgetEventSynthesized);
&preventDefaultResult, aIsDOMEventSynthesized, aIsWidgetEventSynthesized);
if (aPreventDefault) {
*aPreventDefault = preventDefaultResult != PreventDefaultResult::No;
}
return rv;
}
NS_IMETHODIMP

Просмотреть файл

@ -551,13 +551,14 @@ bool APZCCallbackHelper::DispatchMouseEvent(
unsigned short aInputSourceArg, uint32_t aPointerId) {
NS_ENSURE_TRUE(aPresShell, true);
bool defaultPrevented = false;
PreventDefaultResult preventDefaultResult;
nsContentUtils::SendMouseEvent(
aPresShell, aType, aPoint.x, aPoint.y, aButton,
nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED, aClickCount, aModifiers,
/* aIgnoreRootScrollFrame = */ false, 0, aInputSourceArg, aPointerId,
false, &defaultPrevented, false, /* aIsWidgetEventSynthesized = */ false);
return defaultPrevented;
false, &preventDefaultResult, false,
/* aIsWidgetEventSynthesized = */ false);
return preventDefaultResult != PreventDefaultResult::No;
}
void APZCCallbackHelper::FireSingleTapEvent(const LayoutDevicePoint& aPoint,