Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: third_party/WebKit/Source/core/input/TouchEventManager.cpp

Issue 2414273003: Remove UserGesture on touch scrolls (Closed)
Patch Set: Improve comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/input/TouchEventManager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/input/TouchEventManager.h" 5 #include "core/input/TouchEventManager.h"
6 6
7 #include "core/dom/Document.h" 7 #include "core/dom/Document.h"
8 #include "core/dom/DocumentUserGestureToken.h"
9 #include "core/events/TouchEvent.h" 8 #include "core/events/TouchEvent.h"
10 #include "core/frame/Deprecation.h" 9 #include "core/frame/Deprecation.h"
11 #include "core/frame/EventHandlerRegistry.h" 10 #include "core/frame/EventHandlerRegistry.h"
12 #include "core/frame/FrameHost.h" 11 #include "core/frame/FrameHost.h"
13 #include "core/frame/FrameView.h" 12 #include "core/frame/FrameView.h"
14 #include "core/html/HTMLCanvasElement.h" 13 #include "core/html/HTMLCanvasElement.h"
15 #include "core/input/EventHandlingUtil.h" 14 #include "core/input/EventHandlingUtil.h"
16 #include "core/input/TouchActionUtil.h" 15 #include "core/input/TouchActionUtil.h"
17 #include "core/layout/HitTestCanvasResult.h" 16 #include "core/layout/HitTestCanvasResult.h"
18 #include "core/page/ChromeClient.h" 17 #include "core/page/ChromeClient.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 }; 83 };
85 84
86 } // namespace 85 } // namespace
87 86
88 TouchEventManager::TouchEventManager(LocalFrame* frame) : m_frame(frame) { 87 TouchEventManager::TouchEventManager(LocalFrame* frame) : m_frame(frame) {
89 clear(); 88 clear();
90 } 89 }
91 90
92 void TouchEventManager::clear() { 91 void TouchEventManager::clear() {
93 m_touchSequenceDocument.clear(); 92 m_touchSequenceDocument.clear();
94 m_touchSequenceUserGestureToken.clear();
95 m_targetForTouchID.clear(); 93 m_targetForTouchID.clear();
96 m_regionForTouchID.clear(); 94 m_regionForTouchID.clear();
97 m_touchPressed = false; 95 m_touchPressed = false;
98 m_touchScrollStarted = false;
99 m_currentEvent = PlatformEvent::NoType; 96 m_currentEvent = PlatformEvent::NoType;
100 } 97 }
101 98
102 DEFINE_TRACE(TouchEventManager) { 99 DEFINE_TRACE(TouchEventManager) {
103 visitor->trace(m_frame); 100 visitor->trace(m_frame);
104 visitor->trace(m_touchSequenceDocument); 101 visitor->trace(m_touchSequenceDocument);
105 visitor->trace(m_targetForTouchID); 102 visitor->trace(m_targetForTouchID);
106 } 103 }
107 104
108 WebInputEventResult TouchEventManager::dispatchTouchEvents( 105 WebInputEventResult TouchEventManager::dispatchTouchEvents(
109 const PlatformTouchEvent& event, 106 const PlatformTouchEvent& event,
110 const HeapVector<TouchInfo>& touchInfos, 107 const HeapVector<TouchInfo>& touchInfos,
111 bool allTouchesReleased) { 108 bool allTouchesReleased) {
112 // Build up the lists to use for the |touches|, |targetTouches| and 109 // Build up the lists to use for the |touches|, |targetTouches| and
113 // |changedTouches| attributes in the JS event. See 110 // |changedTouches| attributes in the JS event. See
114 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these 111 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
115 // lists fit together. 112 // lists fit together.
116 113
117 // Holds the complete set of touches on the screen. 114 // Holds the complete set of touches on the screen.
118 TouchList* touches = TouchList::create(); 115 TouchList* touches = TouchList::create();
119 116
120 // A different view on the 'touches' list above, filtered and grouped by 117 // A different view on the 'touches' list above, filtered and grouped by
121 // event target. Used for the |targetTouches| list in the JS event. 118 // event target. Used for the |targetTouches| list in the JS event.
122 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; 119 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>;
123 TargetTouchesHeapMap touchesByTarget; 120 TargetTouchesHeapMap touchesByTarget;
124 121
125 // Array of touches per state, used to assemble the |changedTouches| list. 122 // Array of touches per state, used to assemble the |changedTouches| list.
126 ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd]; 123 ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd];
127 124
128 for (unsigned i = 0; i < touchInfos.size(); ++i) { 125 for (auto touchInfo : touchInfos) {
129 const TouchInfo& touchInfo = touchInfos[i];
130 const PlatformTouchPoint& point = touchInfo.point; 126 const PlatformTouchPoint& point = touchInfo.point;
131 PlatformTouchPoint::TouchState pointState = point.state(); 127 PlatformTouchPoint::TouchState pointState = point.state();
132 128
133 Touch* touch = Touch::create( 129 Touch* touch = Touch::create(
134 touchInfo.targetFrame.get(), touchInfo.touchNode.get(), point.id(), 130 touchInfo.targetFrame.get(), touchInfo.touchNode.get(), point.id(),
135 point.screenPos(), touchInfo.contentPoint, touchInfo.adjustedRadius, 131 point.screenPos(), touchInfo.contentPoint, touchInfo.adjustedRadius,
136 point.rotationAngle(), point.force(), touchInfo.region); 132 point.rotationAngle(), point.force(), touchInfo.region);
137 133
138 // Ensure this target's touch list exists, even if it ends up empty, so 134 // Ensure this target's touch list exists, even if it ends up empty, so
139 // it can always be passed to TouchEvent::Create below. 135 // it can always be passed to TouchEvent::Create below.
(...skipping 24 matching lines...) Expand all
164 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd); 160 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
165 if (!changedTouches[pointState].m_touches) 161 if (!changedTouches[pointState].m_touches)
166 changedTouches[pointState].m_touches = TouchList::create(); 162 changedTouches[pointState].m_touches = TouchList::create();
167 changedTouches[pointState].m_touches->append(touch); 163 changedTouches[pointState].m_touches->append(touch);
168 changedTouches[pointState].m_targets.add(touchInfo.touchNode); 164 changedTouches[pointState].m_targets.add(touchInfo.touchNode);
169 } 165 }
170 } 166 }
171 167
172 if (allTouchesReleased) { 168 if (allTouchesReleased) {
173 m_touchSequenceDocument.clear(); 169 m_touchSequenceDocument.clear();
174 m_touchSequenceUserGestureToken.clear();
175 } 170 }
176 171
177 WebInputEventResult eventResult = WebInputEventResult::NotHandled; 172 WebInputEventResult eventResult = WebInputEventResult::NotHandled;
178 173
179 // Now iterate through the |changedTouches| list and |m_targets| within it, 174 // Now iterate through the |changedTouches| list and |m_targets| within it,
180 // sending TouchEvents to the targets as required. 175 // sending TouchEvents to the targets as required.
181 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; 176 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd;
182 ++state) { 177 ++state) {
183 if (!changedTouches[state].m_touches) 178 if (!changedTouches[state].m_touches)
184 continue; 179 continue;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 ? HandledTouches 254 ? HandledTouches
260 : UnhandledTouches); 255 : UnhandledTouches);
261 } 256 }
262 } 257 }
263 eventResult = EventHandlingUtil::mergeEventResult( 258 eventResult = EventHandlingUtil::mergeEventResult(
264 eventResult, 259 eventResult,
265 EventHandlingUtil::toWebInputEventResult(domDispatchResult)); 260 EventHandlingUtil::toWebInputEventResult(domDispatchResult));
266 } 261 }
267 } 262 }
268 263
269 if (allTouchesReleased)
270 m_touchScrollStarted = false;
271
272 return eventResult; 264 return eventResult;
273 } 265 }
274 266
275 void TouchEventManager::updateTargetAndRegionMapsForTouchStarts( 267 void TouchEventManager::updateTargetAndRegionMapsForTouchStarts(
276 HeapVector<TouchInfo>& touchInfos) { 268 HeapVector<TouchInfo>& touchInfos) {
277 for (auto& touchInfo : touchInfos) { 269 for (auto& touchInfo : touchInfos) {
278 // Touch events implicitly capture to the touched node, and don't change 270 // Touch events implicitly capture to the touched node, and don't change
279 // active/hover states themselves (Gesture events do). So we only need 271 // active/hover states themselves (Gesture events do). So we only need
280 // to hit-test on touchstart and when the target could be different than 272 // to hit-test on touchstart and when the target could be different than
281 // the corresponding pointer event target. 273 // the corresponding pointer event target.
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 point.state() != PlatformTouchPoint::TouchCancelled) 418 point.state() != PlatformTouchPoint::TouchCancelled)
427 allTouchesReleased = false; 419 allTouchesReleased = false;
428 } 420 }
429 if (newTouchSequence) { 421 if (newTouchSequence) {
430 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should 422 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should
431 // have cleared the active document when we saw the last release. But we 423 // have cleared the active document when we saw the last release. But we
432 // have some tests that violate this, ClusterFuzz could trigger it, and 424 // have some tests that violate this, ClusterFuzz could trigger it, and
433 // there may be cases where the browser doesn't reliably release all 425 // there may be cases where the browser doesn't reliably release all
434 // touches. http://crbug.com/345372 tracks this. 426 // touches. http://crbug.com/345372 tracks this.
435 m_touchSequenceDocument.clear(); 427 m_touchSequenceDocument.clear();
436 m_touchSequenceUserGestureToken.clear();
437 } 428 }
438 429
439 ASSERT(m_frame->view()); 430 ASSERT(m_frame->view());
440 if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || 431 if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() ||
441 !m_touchSequenceDocument->frame()->view())) { 432 !m_touchSequenceDocument->frame()->view())) {
442 // If the active touch document has no frame or view, it's probably being 433 // If the active touch document has no frame or view, it's probably being
443 // destroyed so we can't dispatch events. 434 // destroyed so we can't dispatch events.
444 return false; 435 return false;
445 } 436 }
446 437
447 updateTargetAndRegionMapsForTouchStarts(touchInfos); 438 updateTargetAndRegionMapsForTouchStarts(touchInfos);
448 439
449 m_touchPressed = !allTouchesReleased; 440 m_touchPressed = !allTouchesReleased;
450 441
451 // If there's no document receiving touch events, or no handlers on the 442 // If there's no document receiving touch events, or no handlers on the
452 // document set to receive the events, then we can skip all the rest of 443 // document set to receive the events, then we can skip all the rest of
453 // this work. 444 // this work.
454 if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || 445 if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() ||
455 !hasTouchHandlers( 446 !hasTouchHandlers(
456 m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || 447 m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) ||
457 !m_touchSequenceDocument->frame()) { 448 !m_touchSequenceDocument->frame()) {
458 if (allTouchesReleased) { 449 if (allTouchesReleased) {
459 m_touchSequenceDocument.clear(); 450 m_touchSequenceDocument.clear();
460 m_touchSequenceUserGestureToken.clear();
461 } 451 }
462 return false; 452 return false;
463 } 453 }
464 454
465 setAllPropertiesOfTouchInfos(touchInfos); 455 setAllPropertiesOfTouchInfos(touchInfos);
466 456
467 return true; 457 return true;
468 } 458 }
469 459
470 // TODO(rbyers): Replace with AutoReset as base/WTF unification permits. 460 // TODO(rbyers): Replace with AutoReset as base/WTF unification permits.
(...skipping 22 matching lines...) Expand all
493 if (!reHitTestTouchPointsIfNeeded(event, touchInfos)) 483 if (!reHitTestTouchPointsIfNeeded(event, touchInfos))
494 return WebInputEventResult::NotHandled; 484 return WebInputEventResult::NotHandled;
495 485
496 bool allTouchesReleased = true; 486 bool allTouchesReleased = true;
497 for (const auto& point : event.touchPoints()) { 487 for (const auto& point : event.touchPoints()) {
498 if (point.state() != PlatformTouchPoint::TouchReleased && 488 if (point.state() != PlatformTouchPoint::TouchReleased &&
499 point.state() != PlatformTouchPoint::TouchCancelled) 489 point.state() != PlatformTouchPoint::TouchCancelled)
500 allTouchesReleased = false; 490 allTouchesReleased = false;
501 } 491 }
502 492
503 // Whether a touch should be considered a "user gesture" or not is a tricky
504 // question.
505 // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZu7 nvOg/edit#
506
507 // The touchend corresponding to a tap is always a user gesture.
508 bool isTap =
509 event.touchPoints().size() == 1 &&
510 event.touchPoints()[0].state() == PlatformTouchPoint::TouchReleased &&
511 !event.causesScrollingIfUncanceled();
512
513 // For now, disallow dragging as a user gesture when the events are being sent
514 // to a cross-origin iframe (crbug.com/582140).
515 bool isSameOrigin = false;
516 if (m_touchSequenceDocument && m_touchSequenceDocument->frame()) {
517 SecurityOrigin* securityOrigin = m_touchSequenceDocument->frame()
518 ->securityContext()
519 ->getSecurityOrigin();
520 Frame* top = m_frame->tree().top();
521 if (top &&
522 securityOrigin->canAccess(top->securityContext()->getSecurityOrigin()))
523 isSameOrigin = true;
524 }
525
526 std::unique_ptr<UserGestureIndicator> gestureIndicator;
527 if (isTap || isSameOrigin) {
528 gestureIndicator = wrapUnique(new UserGestureIndicator(
529 m_touchSequenceUserGestureToken
530 ? m_touchSequenceUserGestureToken.release()
531 : DocumentUserGestureToken::create(m_touchSequenceDocument)));
532
533 m_touchSequenceUserGestureToken = UserGestureIndicator::currentToken();
534 // These are cases we'd like to migrate to not hold a user gesture.
535 if (event.type() == PlatformEvent::TouchStart ||
536 event.type() == PlatformEvent::TouchMove ||
537 (event.type() == PlatformEvent::TouchEnd && m_touchScrollStarted)) {
538 // Collect metrics in userGestureUtilized().
539 m_touchSequenceUserGestureToken->setUserGestureUtilizedCallback(this);
540 }
541 }
542
543 return dispatchTouchEvents(event, touchInfos, allTouchesReleased); 493 return dispatchTouchEvents(event, touchInfos, allTouchesReleased);
544 } 494 }
545 495
546 bool TouchEventManager::isAnyTouchActive() const { 496 bool TouchEventManager::isAnyTouchActive() const {
547 return m_touchPressed; 497 return m_touchPressed;
548 } 498 }
549 499
550 void TouchEventManager::userGestureUtilized() {
551 // This is invoked for UserGestureIndicators created in
552 // TouchEventManger::handleTouchEvent which perhaps represent touch actions
553 // which shouldn't be considered a user-gesture. Trigger a UseCounter based
554 // on the touch event that's currently being dispatched.
555 UseCounter::Feature feature;
556
557 switch (m_currentEvent) {
558 case PlatformEvent::TouchStart:
559 feature = UseCounter::TouchStartUserGestureUtilized;
560 break;
561 case PlatformEvent::TouchMove:
562 feature = UseCounter::TouchMoveUserGestureUtilized;
563 break;
564 case PlatformEvent::TouchEnd:
565 feature = UseCounter::TouchEndDuringScrollUserGestureUtilized;
566 break;
567 default:
568 NOTREACHED();
569 return;
570 }
571 Deprecation::countDeprecation(m_frame, feature);
572 }
573
574 } // namespace blink 500 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/input/TouchEventManager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698