Add use counter when touch-action isn't used when preventDefault'd.
Keep track of the lack of usage of touch-action on pages.
BUG=639227
TBR=isherman@chromium.org
Review-Url: https://codereview.chromium.org/2475443004
Cr-Commit-Position: refs/heads/master@{#431618}
diff --git a/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.cpp b/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.cpp
index 28676fbd..8afeeeb 100644
--- a/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.cpp
+++ b/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.cpp
@@ -7,12 +7,13 @@
namespace blink {
AddEventListenerOptionsResolved::AddEventListenerOptionsResolved()
- : m_passiveForcedForDocumentTarget(false) {}
+ : m_passiveForcedForDocumentTarget(false), m_passiveSpecified(false) {}
AddEventListenerOptionsResolved::AddEventListenerOptionsResolved(
const AddEventListenerOptions& options)
: AddEventListenerOptions(options),
- m_passiveForcedForDocumentTarget(false) {}
+ m_passiveForcedForDocumentTarget(false),
+ m_passiveSpecified(false) {}
AddEventListenerOptionsResolved::~AddEventListenerOptionsResolved() {}
diff --git a/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.h b/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.h
index 26cbef2..fde5ae7 100644
--- a/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.h
+++ b/third_party/WebKit/Source/core/events/AddEventListenerOptionsResolved.h
@@ -29,10 +29,16 @@
return m_passiveForcedForDocumentTarget;
}
+ // Set whether passive was specified when the options were
+ // created by callee.
+ void setPassiveSpecified(bool specified) { m_passiveSpecified = specified; }
+ bool passiveSpecified() const { return m_passiveSpecified; }
+
DECLARE_VIRTUAL_TRACE();
private:
bool m_passiveForcedForDocumentTarget;
+ bool m_passiveSpecified;
};
} // namespace blink
diff --git a/third_party/WebKit/Source/core/events/Event.cpp b/third_party/WebKit/Source/core/events/Event.cpp
index 5adbdb9..68487d5 100644
--- a/third_party/WebKit/Source/core/events/Event.cpp
+++ b/third_party/WebKit/Source/core/events/Event.cpp
@@ -92,7 +92,7 @@
m_wasInitialized(true),
m_isTrusted(false),
m_preventDefaultCalledOnUncancelableEvent(false),
- m_handlingPassive(PassiveMode::NotPassive),
+ m_handlingPassive(PassiveMode::NotPassiveDefault),
m_eventPhase(0),
m_currentTarget(nullptr),
m_platformTimeStamp(platformTimeStamp) {}
@@ -219,7 +219,8 @@
}
void Event::preventDefault() {
- if (m_handlingPassive != PassiveMode::NotPassive) {
+ if (m_handlingPassive != PassiveMode::NotPassive &&
+ m_handlingPassive != PassiveMode::NotPassiveDefault) {
m_preventDefaultCalledDuringPassive = true;
const LocalDOMWindow* window =
@@ -228,9 +229,11 @@
const char* devToolsMsg = nullptr;
switch (m_handlingPassive) {
case PassiveMode::NotPassive:
+ case PassiveMode::NotPassiveDefault:
NOTREACHED();
break;
case PassiveMode::Passive:
+ case PassiveMode::PassiveDefault:
devToolsMsg =
"Unable to preventDefault inside passive event listener "
"invocation.";
diff --git a/third_party/WebKit/Source/core/events/Event.h b/third_party/WebKit/Source/core/events/Event.h
index d1c8fdda..e2074dd 100644
--- a/third_party/WebKit/Source/core/events/Event.h
+++ b/third_party/WebKit/Source/core/events/Event.h
@@ -84,9 +84,17 @@
};
enum class PassiveMode {
+ // Not passive, default initialized.
+ NotPassiveDefault,
+ // Not passive, explicitly specified.
NotPassive,
+ // Passive, explicitly specified.
Passive,
+ // Passive, not explicitly specified and forced due to document level
+ // listener.
PassiveForcedDocumentLevel,
+ // Passive, default initialized.
+ PassiveDefault,
};
static Event* create() { return new Event; }
diff --git a/third_party/WebKit/Source/core/events/EventTarget.cpp b/third_party/WebKit/Source/core/events/EventTarget.cpp
index 329f68d..13346d6 100644
--- a/third_party/WebKit/Source/core/events/EventTarget.cpp
+++ b/third_party/WebKit/Source/core/events/EventTarget.cpp
@@ -69,11 +69,16 @@
Event::PassiveMode eventPassiveMode(
const RegisteredEventListener& eventListener) {
- if (!eventListener.passive())
- return Event::PassiveMode::NotPassive;
+ if (!eventListener.passive()) {
+ if (eventListener.passiveSpecified())
+ return Event::PassiveMode::NotPassive;
+ return Event::PassiveMode::NotPassiveDefault;
+ }
if (eventListener.passiveForcedForDocumentTarget())
return Event::PassiveMode::PassiveForcedDocumentLevel;
- return Event::PassiveMode::Passive;
+ if (eventListener.passiveSpecified())
+ return Event::PassiveMode::Passive;
+ return Event::PassiveMode::PassiveDefault;
}
Settings* windowSettings(LocalDOMWindow* executingWindow) {
@@ -192,6 +197,8 @@
void EventTarget::setDefaultAddEventListenerOptions(
const AtomicString& eventType,
AddEventListenerOptionsResolved& options) {
+ options.setPassiveSpecified(options.hasPassive());
+
if (!isScrollBlockingEvent(eventType)) {
if (!options.hasPassive())
options.setPassive(false);
diff --git a/third_party/WebKit/Source/core/events/RegisteredEventListener.h b/third_party/WebKit/Source/core/events/RegisteredEventListener.h
index 948f5850..0d73bf8 100644
--- a/third_party/WebKit/Source/core/events/RegisteredEventListener.h
+++ b/third_party/WebKit/Source/core/events/RegisteredEventListener.h
@@ -40,7 +40,8 @@
m_passive(false),
m_once(false),
m_blockedEventWarningEmitted(false),
- m_passiveForcedForDocumentTarget(false) {}
+ m_passiveForcedForDocumentTarget(false),
+ m_passiveSpecified(false) {}
RegisteredEventListener(EventListener* listener,
const AddEventListenerOptionsResolved& options)
@@ -50,7 +51,8 @@
m_once(options.once()),
m_blockedEventWarningEmitted(false),
m_passiveForcedForDocumentTarget(
- options.passiveForcedForDocumentTarget()) {}
+ options.passiveForcedForDocumentTarget()),
+ m_passiveSpecified(options.passiveSpecified()) {}
DEFINE_INLINE_TRACE() { visitor->trace(m_listener); }
@@ -60,6 +62,7 @@
result.setPassive(m_passive);
result.setPassiveForcedForDocumentTarget(m_passiveForcedForDocumentTarget);
result.setOnce(m_once);
+ result.setPassiveSpecified(m_passiveSpecified);
return result;
}
@@ -81,6 +84,8 @@
return m_passiveForcedForDocumentTarget;
}
+ bool passiveSpecified() const { return m_passiveSpecified; }
+
void setBlockedEventWarningEmitted() { m_blockedEventWarningEmitted = true; }
bool matches(const EventListener* listener,
@@ -107,6 +112,7 @@
unsigned m_once : 1;
unsigned m_blockedEventWarningEmitted : 1;
unsigned m_passiveForcedForDocumentTarget : 1;
+ unsigned m_passiveSpecified : 1;
};
} // namespace blink
diff --git a/third_party/WebKit/Source/core/events/TouchEvent.cpp b/third_party/WebKit/Source/core/events/TouchEvent.cpp
index 9821312..b4df5135 100644
--- a/third_party/WebKit/Source/core/events/TouchEvent.cpp
+++ b/third_party/WebKit/Source/core/events/TouchEvent.cpp
@@ -210,7 +210,8 @@
bool cancelable,
bool causesScrollingIfUncanceled,
bool firstTouchMoveOrStart,
- double platformTimeStamp)
+ double platformTimeStamp,
+ TouchAction currentTouchAction)
// Pass a sourceCapabilities including the ability to fire touchevents when
// creating this touchevent, which is always created from input device
// capabilities from EventHandler.
@@ -228,7 +229,8 @@
m_changedTouches(changedTouches),
m_causesScrollingIfUncanceled(causesScrollingIfUncanceled),
m_firstTouchMoveOrStart(firstTouchMoveOrStart),
- m_defaultPreventedBeforeCurrentTarget(false) {}
+ m_defaultPreventedBeforeCurrentTarget(false),
+ m_currentTouchAction(currentTouchAction) {}
TouchEvent::TouchEvent(const AtomicString& type,
const TouchEventInit& initializer)
@@ -265,6 +267,24 @@
"because scrolling is in progress and "
"cannot be interrupted."));
}
+
+ if ((type() == EventTypeNames::touchstart ||
+ type() == EventTypeNames::touchmove) &&
+ view() && view()->frame() && m_currentTouchAction == TouchActionAuto) {
+ switch (handlingPassive()) {
+ case PassiveMode::NotPassiveDefault:
+ UseCounter::count(view()->frame(),
+ UseCounter::TouchEventPreventedNoTouchAction);
+ break;
+ case PassiveMode::PassiveForcedDocumentLevel:
+ UseCounter::count(
+ view()->frame(),
+ UseCounter::TouchEventPreventedForcedDocumentPassiveNoTouchAction);
+ break;
+ default:
+ break;
+ }
+ }
}
void TouchEvent::doneDispatchingEventAtCurrentTarget() {
diff --git a/third_party/WebKit/Source/core/events/TouchEvent.h b/third_party/WebKit/Source/core/events/TouchEvent.h
index 530ae237..307663c0 100644
--- a/third_party/WebKit/Source/core/events/TouchEvent.h
+++ b/third_party/WebKit/Source/core/events/TouchEvent.h
@@ -53,10 +53,12 @@
bool cancelable,
bool causesScrollingIfUncanceled,
bool firstTouchMoveOrStart,
- double platformTimeStamp) {
+ double platformTimeStamp,
+ TouchAction currentTouchAction) {
return new TouchEvent(touches, targetTouches, changedTouches, type, view,
modifiers, cancelable, causesScrollingIfUncanceled,
- firstTouchMoveOrStart, platformTimeStamp);
+ firstTouchMoveOrStart, platformTimeStamp,
+ currentTouchAction);
}
static TouchEvent* create(const AtomicString& type,
@@ -103,7 +105,8 @@
bool cancelable,
bool causesScrollingIfUncanceled,
bool firstTouchMoveOrStart,
- double platformTimeStamp);
+ double platformTimeStamp,
+ TouchAction currentTouchAction);
TouchEvent(const AtomicString&, const TouchEventInit&);
Member<TouchList> m_touches;
@@ -112,6 +115,10 @@
bool m_causesScrollingIfUncanceled;
bool m_firstTouchMoveOrStart;
bool m_defaultPreventedBeforeCurrentTarget;
+
+ // The current effective touch action computed before each
+ // touchstart event is generated. It is used for UMA histograms.
+ TouchAction m_currentTouchAction;
};
class TouchEventDispatchMediator final : public EventDispatchMediator {
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 31dce80a..589fff3 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1387,6 +1387,8 @@
HTMLMediaElementPreloadForcedMetadata = 1679,
GenericSensorStart = 1680,
GenericSensorStop = 1681,
+ TouchEventPreventedNoTouchAction = 1682,
+ TouchEventPreventedForcedDocumentPassiveNoTouchAction = 1683,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/input/TouchEventManager.cpp b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
index 69c4190..6880e9f 100644
--- a/third_party/WebKit/Source/core/input/TouchEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
@@ -94,6 +94,7 @@
m_regionForTouchID.clear();
m_touchPressed = false;
m_currentEvent = PlatformEvent::NoType;
+ m_currentTouchAction = TouchActionAuto;
}
DEFINE_TRACE(TouchEventManager) {
@@ -167,6 +168,7 @@
if (allTouchesReleased) {
m_touchSequenceDocument.clear();
+ m_currentTouchAction = TouchActionAuto;
}
WebInputEventResult eventResult = WebInputEventResult::NotHandled;
@@ -182,13 +184,14 @@
static_cast<PlatformTouchPoint::TouchState>(state)));
for (const auto& eventTarget : changedTouches[state].m_targets) {
EventTarget* touchEventTarget = eventTarget;
- TouchEvent* touchEvent = TouchEvent::create(
- touches, touchesByTarget.get(touchEventTarget),
- changedTouches[state].m_touches.get(), eventName,
- touchEventTarget->toNode()->document().domWindow(),
- event.getModifiers(), event.cancelable(),
- event.causesScrollingIfUncanceled(),
- event.touchStartOrFirstTouchMove(), event.timestamp());
+ TouchEvent* touchEvent =
+ TouchEvent::create(touches, touchesByTarget.get(touchEventTarget),
+ changedTouches[state].m_touches.get(), eventName,
+ touchEventTarget->toNode()->document().domWindow(),
+ event.getModifiers(), event.cancelable(),
+ event.causesScrollingIfUncanceled(),
+ event.touchStartOrFirstTouchMove(),
+ event.timestamp(), m_currentTouchAction);
DispatchEventResult domDispatchResult =
touchEventTarget->dispatchEvent(touchEvent);
@@ -333,8 +336,13 @@
TouchAction effectiveTouchAction =
TouchActionUtil::computeEffectiveTouchAction(*touchInfo.touchNode);
- if (effectiveTouchAction != TouchActionAuto)
+ if (effectiveTouchAction != TouchActionAuto) {
m_frame->page()->chromeClient().setTouchAction(effectiveTouchAction);
+
+ // Combine the current touch action sequence with the touch action
+ // for the current finger press.
+ m_currentTouchAction &= effectiveTouchAction;
+ }
}
}
}
diff --git a/third_party/WebKit/Source/core/input/TouchEventManager.h b/third_party/WebKit/Source/core/input/TouchEventManager.h
index e6c7d5e8..7504490 100644
--- a/third_party/WebKit/Source/core/input/TouchEventManager.h
+++ b/third_party/WebKit/Source/core/input/TouchEventManager.h
@@ -96,6 +96,10 @@
bool m_touchPressed;
// The touch event currently being handled or NoType if none.
PlatformEvent::EventType m_currentEvent;
+
+ // The current touch action, computed on each touch start and is
+ // a union of all touches. Reset when all touches are released.
+ TouchAction m_currentTouchAction;
};
} // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
index 85a2341..b2b2af8 100644
--- a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
@@ -149,7 +149,7 @@
touchList->append(touch0);
TouchEvent* touchEvent = TouchEvent::create(
touchList, touchList, touchList, EventTypeNames::touchstart, domWindow,
- PlatformEvent::NoModifiers, false, false, true, 0);
+ PlatformEvent::NoModifiers, false, false, true, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
ASSERT_EQ(1u, webTouchBuilder.touchesLength);
@@ -174,7 +174,7 @@
touchList->append(touch0);
TouchEvent* touchEvent = TouchEvent::create(
touchList, touchList, touchList, EventTypeNames::touchstart, domWindow,
- PlatformEvent::NoModifiers, true, false, true, 0);
+ PlatformEvent::NoModifiers, true, false, true, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
EXPECT_EQ(WebInputEvent::Blocking, webTouchBuilder.dispatchType);
@@ -187,10 +187,10 @@
activeTouchList->append(touch0);
activeTouchList->append(touch1);
movedTouchList->append(touch0);
- TouchEvent* touchEvent =
- TouchEvent::create(activeTouchList, activeTouchList, movedTouchList,
- EventTypeNames::touchmove, domWindow,
- PlatformEvent::NoModifiers, false, false, true, 0);
+ TouchEvent* touchEvent = TouchEvent::create(
+ activeTouchList, activeTouchList, movedTouchList,
+ EventTypeNames::touchmove, domWindow, PlatformEvent::NoModifiers, false,
+ false, true, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
ASSERT_EQ(2u, webTouchBuilder.touchesLength);
@@ -209,10 +209,10 @@
activeTouchList->append(touch0);
activeTouchList->append(touch1);
movedTouchList->append(touch1);
- TouchEvent* touchEvent =
- TouchEvent::create(activeTouchList, activeTouchList, movedTouchList,
- EventTypeNames::touchmove, domWindow,
- PlatformEvent::NoModifiers, false, false, true, 0);
+ TouchEvent* touchEvent = TouchEvent::create(
+ activeTouchList, activeTouchList, movedTouchList,
+ EventTypeNames::touchmove, domWindow, PlatformEvent::NoModifiers, false,
+ false, true, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
ASSERT_EQ(2u, webTouchBuilder.touchesLength);
@@ -230,10 +230,10 @@
TouchList* releasedTouchList = TouchList::create();
activeTouchList->append(touch0);
releasedTouchList->append(touch1);
- TouchEvent* touchEvent =
- TouchEvent::create(activeTouchList, activeTouchList, releasedTouchList,
- EventTypeNames::touchend, domWindow,
- PlatformEvent::NoModifiers, false, false, false, 0);
+ TouchEvent* touchEvent = TouchEvent::create(
+ activeTouchList, activeTouchList, releasedTouchList,
+ EventTypeNames::touchend, domWindow, PlatformEvent::NoModifiers, false,
+ false, false, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
ASSERT_EQ(2u, webTouchBuilder.touchesLength);
@@ -251,10 +251,10 @@
TouchList* cancelledTouchList = TouchList::create();
cancelledTouchList->append(touch0);
cancelledTouchList->append(touch1);
- TouchEvent* touchEvent =
- TouchEvent::create(activeTouchList, activeTouchList, cancelledTouchList,
- EventTypeNames::touchcancel, domWindow,
- PlatformEvent::NoModifiers, false, false, false, 0);
+ TouchEvent* touchEvent = TouchEvent::create(
+ activeTouchList, activeTouchList, cancelledTouchList,
+ EventTypeNames::touchcancel, domWindow, PlatformEvent::NoModifiers,
+ false, false, false, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
ASSERT_EQ(2u, webTouchBuilder.touchesLength);
@@ -281,7 +281,7 @@
}
TouchEvent* touchEvent = TouchEvent::create(
touchList, touchList, touchList, EventTypeNames::touchstart, domWindow,
- PlatformEvent::NoModifiers, false, false, true, 0);
+ PlatformEvent::NoModifiers, false, false, true, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
ASSERT_EQ(static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap),
@@ -559,7 +559,7 @@
touchList->append(touch);
TouchEvent* touchEvent = TouchEvent::create(
touchList, touchList, touchList, EventTypeNames::touchmove, domWindow,
- PlatformEvent::NoModifiers, false, false, true, 0);
+ PlatformEvent::NoModifiers, false, false, true, 0, TouchActionAuto);
WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
ASSERT_EQ(1u, webTouchBuilder.touchesLength);
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index ac05428..271542f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -85706,6 +85706,9 @@
<int value="1679" label="HTMLMediaElementPreloadForcedMetadata"/>
<int value="1680" label="GenericSensorStart"/>
<int value="1681" label="GenericSensorStop"/>
+ <int value="1682" label="TouchEventPreventedNoTouchAction"/>
+ <int value="1683"
+ label="TouchEventPreventedForcedDocumentPassiveNoTouchAction"/>
</enum>
<enum name="FetchRequestMode" type="int">