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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java

Issue 2348443002: Revert of [TTS] Gather surrounding text on Tap before any UX. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 3 months 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 | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/action/ResolvedSearchAction.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 package org.chromium.chrome.browser.contextualsearch; 5 package org.chromium.chrome.browser.contextualsearch;
6 6
7 import android.os.Handler; 7 import android.os.Handler;
8 8
9 import org.chromium.base.VisibleForTesting; 9 import org.chromium.base.VisibleForTesting;
10 import org.chromium.chrome.browser.ChromeActivity; 10 import org.chromium.chrome.browser.ChromeActivity;
11 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; 11 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
12 import org.chromium.chrome.browser.contextualsearch.ContextualSearchBlacklist.Bl acklistReason; 12 import org.chromium.chrome.browser.contextualsearch.ContextualSearchBlacklist.Bl acklistReason;
13 import org.chromium.chrome.browser.contextualsearch.action.ResolvedSearchAction;
14 import org.chromium.chrome.browser.contextualsearch.action.SearchAction;
15 import org.chromium.chrome.browser.contextualsearch.action.SearchActionListener;
16 import org.chromium.chrome.browser.contextualsearch.gesture.SearchGestureHost;
17 import org.chromium.chrome.browser.preferences.ChromePreferenceManager; 13 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
18 import org.chromium.chrome.browser.tab.Tab; 14 import org.chromium.chrome.browser.tab.Tab;
19 import org.chromium.content.browser.ContentViewCore; 15 import org.chromium.content.browser.ContentViewCore;
20 import org.chromium.content_public.browser.GestureStateListener; 16 import org.chromium.content_public.browser.GestureStateListener;
21 import org.chromium.content_public.browser.WebContents;
22 import org.chromium.ui.touch_selection.SelectionEventType; 17 import org.chromium.ui.touch_selection.SelectionEventType;
23 18
24 import java.util.regex.Matcher; 19 import java.util.regex.Matcher;
25 import java.util.regex.Pattern; 20 import java.util.regex.Pattern;
26 21
27 /** 22 /**
28 * Controls selection gesture interaction for Contextual Search. 23 * Controls selection gesture interaction for Contextual Search.
29 */ 24 */
30 public class ContextualSearchSelectionController implements SearchGestureHost { 25 public class ContextualSearchSelectionController {
26
31 /** 27 /**
32 * The type of selection made by the user. 28 * The type of selection made by the user.
33 */ 29 */
34 public enum SelectionType { 30 public enum SelectionType {
35 UNDETERMINED, 31 UNDETERMINED,
36 TAP, 32 TAP,
37 LONG_PRESS 33 LONG_PRESS
38 } 34 }
39 35
40 // The number of milliseconds to wait for a selection change after a tap bef ore considering 36 // The number of milliseconds to wait for a selection change after a tap bef ore considering
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 private boolean mShouldHandleSelectionModification; 72 private boolean mShouldHandleSelectionModification;
77 private boolean mDidExpandSelection; 73 private boolean mDidExpandSelection;
78 74
79 // Position of the selection. 75 // Position of the selection.
80 private float mX; 76 private float mX;
81 private float mY; 77 private float mY;
82 78
83 // The time of the most last scroll activity, or 0 if none. 79 // The time of the most last scroll activity, or 0 if none.
84 private long mLastScrollTimeNs; 80 private long mLastScrollTimeNs;
85 81
86 // When the last tap gesture happened.
87 private long mTapTimeNanoseconds;
88
89 // Tracks whether a Context Menu has just been shown and the UX has been dis missed. 82 // Tracks whether a Context Menu has just been shown and the UX has been dis missed.
90 // The selection may be unreliable until the next reset. See crbug.com/6284 36. 83 // The selection may be unreliable until the next reset. See crbug.com/6284 36.
91 private boolean mIsContextMenuShown; 84 private boolean mIsContextMenuShown;
92 85
93 // Set to true when we have identified that a pending tap has not been handl ed by Blink.
94 private boolean mHasIdentifiedUnhandledTap;
95
96 // The current Search action.
97 private SearchAction mSearchAction;
98
99 private class ContextualSearchGestureStateListener extends GestureStateListe ner { 86 private class ContextualSearchGestureStateListener extends GestureStateListe ner {
100 @Override 87 @Override
101 public void onScrollStarted(int scrollOffsetY, int scrollExtentY) { 88 public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {
102 mHandler.handleScroll(); 89 mHandler.handleScroll();
103 } 90 }
104 91
105 @Override 92 @Override
106 public void onScrollEnded(int scrollOffsetY, int scrollExtentY) { 93 public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {
107 mLastScrollTimeNs = System.nanoTime(); 94 mLastScrollTimeNs = System.nanoTime();
108 } 95 }
(...skipping 10 matching lines...) Expand all
119 // notification in this case. 106 // notification in this case.
120 // See crbug.com/444114. 107 // See crbug.com/444114.
121 @Override 108 @Override
122 public void onSingleTap(boolean consumed, int x, int y) { 109 public void onSingleTap(boolean consumed, int x, int y) {
123 // We may be notified that a tap has happened even when the system c onsumed the event. 110 // We may be notified that a tap has happened even when the system c onsumed the event.
124 // This is being used to support tapping on an existing selection to show the selection 111 // This is being used to support tapping on an existing selection to show the selection
125 // handles. We should process this tap unless we have already shown the selection 112 // handles. We should process this tap unless we have already shown the selection
126 // handles (have a long-press selection) and the tap was consumed. 113 // handles (have a long-press selection) and the tap was consumed.
127 if (!(consumed && mSelectionType == SelectionType.LONG_PRESS)) { 114 if (!(consumed && mSelectionType == SelectionType.LONG_PRESS)) {
128 scheduleInvalidTapNotification(); 115 scheduleInvalidTapNotification();
129
130 if (mHasIdentifiedUnhandledTap) createSearchAction();
131 } 116 }
132 } 117 }
133 } 118 }
134 119
135 /** 120 /**
136 * Constructs a new Selection controller for the given activity. Callbacks will be issued 121 * Constructs a new Selection controller for the given activity. Callbacks will be issued
137 * through the given selection handler. 122 * through the given selection handler.
138 * @param activity The {@link ChromeActivity} to control. 123 * @param activity The {@link ChromeActivity} to control.
139 * @param handler The handler for callbacks. 124 * @param handler The handler for callbacks.
140 */ 125 */
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 } 319 }
335 320
336 /** 321 /**
337 * Re-enables selection modification handling and invokes 322 * Re-enables selection modification handling and invokes
338 * ContextualSearchSelectionHandler.handleSelection(). 323 * ContextualSearchSelectionHandler.handleSelection().
339 * @param selection The text that was selected. 324 * @param selection The text that was selected.
340 * @param type The type of selection made by the user. 325 * @param type The type of selection made by the user.
341 */ 326 */
342 private void handleSelection(String selection, SelectionType type) { 327 private void handleSelection(String selection, SelectionType type) {
343 mShouldHandleSelectionModification = true; 328 mShouldHandleSelectionModification = true;
344 destroySearchAction();
345 boolean isValidSelection = validateSelectionSuppression(selection); 329 boolean isValidSelection = validateSelectionSuppression(selection);
346 mHandler.handleSelection(selection, isValidSelection, type, mX, mY); 330 mHandler.handleSelection(selection, isValidSelection, type, mX, mY);
347 } 331 }
348 332
349 /** 333 /**
350 * Resets all internal state of this class, including the tap state. 334 * Resets all internal state of this class, including the tap state.
351 */ 335 */
352 private void resetAllStates() { 336 private void resetAllStates() {
353 resetSelectionStates(); 337 resetSelectionStates();
354 mLastTapState = null; 338 mLastTapState = null;
355 mLastScrollTimeNs = 0; 339 mLastScrollTimeNs = 0;
356 mIsContextMenuShown = false; 340 mIsContextMenuShown = false;
357 mHasIdentifiedUnhandledTap = false;
358 mTapTimeNanoseconds = 0;
359 } 341 }
360 342
361 /** 343 /**
362 * Resets all of the internal state of this class that handles the selection . 344 * Resets all of the internal state of this class that handles the selection .
363 */ 345 */
364 private void resetSelectionStates() { 346 private void resetSelectionStates() {
365 mSelectionType = SelectionType.UNDETERMINED; 347 mSelectionType = SelectionType.UNDETERMINED;
366 mSelectedText = null; 348 mSelectedText = null;
367 349
368 mWasTapGestureDetected = false; 350 mWasTapGestureDetected = false;
369 } 351 }
370 352
371 /** 353 /**
372 * Should be called when a new Tab is selected. 354 * Should be called when a new Tab is selected.
373 * Resets all of the internal state of this class. 355 * Resets all of the internal state of this class.
374 */ 356 */
375 void onTabSelected() { 357 void onTabSelected() {
376 resetAllStates(); 358 resetAllStates();
377 } 359 }
378 360
379 /** 361 /**
380 * Handles an unhandled tap gesture. 362 * Handles an unhandled tap gesture.
381 * @param x The x coordinate.
382 * @param y The y coordinate.
383 */ 363 */
384 void handleShowUnhandledTapUIIfNeeded(int x, int y) { 364 void handleShowUnhandledTapUIIfNeeded(int x, int y) {
385 mWasTapGestureDetected = false; 365 mWasTapGestureDetected = false;
386 // TODO(donnd): shouldn't we check == TAP here instead of LONG_PRESS? 366 // TODO(donnd): shouldn't we check == TAP here instead of LONG_PRESS?
387 // TODO(donnd): refactor to avoid needing a new handler API method as su ggested by Pedro. 367 // TODO(donnd): refactor to avoid needing a new handler API method as su ggested by Pedro.
388 if (mSelectionType != SelectionType.LONG_PRESS) { 368 if (mSelectionType != SelectionType.LONG_PRESS) {
389 mWasTapGestureDetected = true; 369 mWasTapGestureDetected = true;
390 mTapTimeNanoseconds = System.nanoTime(); 370 long tapTimeNanoseconds = System.nanoTime();
391 371 // TODO(donnd): add a policy method to get adjusted tap count.
392 // NOTE(donnd): We first acknowledge that a unhandled tap was identi fied, but 372 ChromePreferenceManager prefs = ChromePreferenceManager.getInstance( mActivity);
393 // we don't do anything now. Instead we'll wait for the onSingleTap( ) event to fire, 373 int adjustedTapsSinceOpen = prefs.getContextualSearchTapCount()
394 // and only do something when an unhandled tap was identified. onSin gleTap() will 374 - prefs.getContextualSearchTapQuickAnswerCount();
395 // always get fired, as opposed to showUnhandledTapUIIfNeeded(). 375 TapSuppressionHeuristics tapHeuristics =
396 mHasIdentifiedUnhandledTap = true; 376 new TapSuppressionHeuristics(this, mLastTapState, x, y, adju stedTapsSinceOpen);
397 377 // TODO(donnd): Move to be called when the panel closes to work with states that change.
378 tapHeuristics.logConditionState();
379 // Tell the manager what it needs in order to log metrics on whether the tap would have
380 // been suppressed if each of the heuristics were satisfied.
381 mHandler.handleMetricsForWouldSuppressTap(tapHeuristics);
398 mX = x; 382 mX = x;
399 mY = y; 383 mY = y;
384 boolean shouldSuppressTap = tapHeuristics.shouldSuppressTap();
385 if (shouldSuppressTap) {
386 mHandler.handleSuppressedTap();
387 } else {
388 // TODO(donnd): Find a better way to determine that a navigation will be triggered
389 // by the tap, or merge with other time-consuming actions like g athering surrounding
390 // text or detecting page mutations.
391 new Handler().postDelayed(new Runnable() {
392 @Override
393 public void run() {
394 mHandler.handleValidTap();
395 }
396 }, TAP_NAVIGATION_DETECTION_DELAY);
397 }
398 // Remember the tap state for subsequent tap evaluation.
399 mLastTapState =
400 new ContextualSearchTapState(x, y, tapTimeNanoseconds, shoul dSuppressTap);
400 } else { 401 } else {
401 // Long press; reset last tap state. 402 // Long press; reset last tap state.
402 mLastTapState = null; 403 mLastTapState = null;
403 mHandler.handleInvalidTap(); 404 mHandler.handleInvalidTap();
404 } 405 }
405 } 406 }
406 407
407 /** 408 /**
408 * Processes a {@link SearchAction}.
409 * This should be called when the associated {@code SearchAction} has built its context (by
410 * gathering surrounding text if needed, etc) but before showing any UX.
411 * @param searchAction The {@link SearchAction} for this Tap gesture.
412 * @param x The x coordinate.
413 * @param y The y coordinate.
414 */
415 void processSearchAction(SearchAction searchAction, int x, int y) {
416 // TODO(donnd): consider using the supplied searchAction, or remove if u sed from native!
417 // TODO(donnd): add a policy method to get adjusted tap count.
418 ChromePreferenceManager prefs = ChromePreferenceManager.getInstance(mAct ivity);
419 int adjustedTapsSinceOpen = prefs.getContextualSearchTapCount()
420 - prefs.getContextualSearchTapQuickAnswerCount();
421 TapSuppressionHeuristics tapHeuristics =
422 new TapSuppressionHeuristics(this, mLastTapState, x, y, adjusted TapsSinceOpen);
423 // TODO(donnd): Move to be called when the panel closes to work with sta tes that change.
424 tapHeuristics.logConditionState();
425 // Tell the manager what it needs in order to log metrics on whether the tap would have
426 // been suppressed if each of the heuristics were satisfied.
427 mHandler.handleMetricsForWouldSuppressTap(tapHeuristics);
428
429 boolean shouldSuppressTap = tapHeuristics.shouldSuppressTap();
430 if (shouldSuppressTap) {
431 mHandler.handleSuppressedTap();
432 } else {
433 // TODO(donnd): Find a better way to determine that a navigation wil l be triggered
434 // by the tap, or merge with other time-consuming actions like gathe ring surrounding
435 // text or detecting page mutations.
436 new Handler().postDelayed(new Runnable() {
437 @Override
438 public void run() {
439 mHandler.handleValidTap();
440 }
441 }, TAP_NAVIGATION_DETECTION_DELAY);
442 }
443 if (mTapTimeNanoseconds == 0) throw new RuntimeException("Tap time not s et!");
444 // Remember the tap state for subsequent tap evaluation.
445 mLastTapState = new ContextualSearchTapState(x, y, mTapTimeNanoseconds, shouldSuppressTap);
446 }
447
448 /**
449 * Creates the current {@link SearchAction}.
450 */
451 void createSearchAction() {
452 destroySearchAction();
453 mSearchAction = new ResolvedSearchAction(new SearchActionListener() {
454
455 @Override
456 protected void onContextReady(SearchAction action) {
457 processSearchAction(action, (int) mX, (int) mY);
458 }
459 }, this);
460
461 mSearchAction.extractContext();
462 }
463
464 /**
465 * Destroys the current {@link SearchAction}.
466 */
467 private void destroySearchAction() {
468 if (mSearchAction == null) return;
469
470 mSearchAction.destroyAction();
471 mSearchAction = null;
472 }
473
474 // ========================================================================= ===================
475 // SearchGestureHost
476 // ========================================================================= ===================
477
478 @Override
479 public WebContents getTabWebContents() {
480 Tab currentTab = mActivity.getActivityTab();
481 return currentTab != null ? currentTab.getWebContents() : null;
482 }
483
484 @Override
485 public void dismissGesture() {
486 destroySearchAction();
487 }
488
489 // ========================================================================= ===================
490 // Utilities
491 // ========================================================================= ===================
492
493 /**
494 * @return The Base Page's {@link ContentViewCore}, or {@code null} if there is no current tab. 409 * @return The Base Page's {@link ContentViewCore}, or {@code null} if there is no current tab.
495 */ 410 */
496 ContentViewCore getBaseContentView() { 411 ContentViewCore getBaseContentView() {
497 // TODO(donnd): switch to using WebContents over ContentViewCore.
498 Tab currentTab = mActivity.getActivityTab(); 412 Tab currentTab = mActivity.getActivityTab();
499 return currentTab != null ? currentTab.getContentViewCore() : null; 413 return currentTab != null ? currentTab.getContentViewCore() : null;
500 } 414 }
501 415
502 /** 416 /**
503 * Expands the current selection by the specified amounts. 417 * Expands the current selection by the specified amounts.
504 * @param selectionStartAdjust The start offset adjustment of the selection to use to highlight 418 * @param selectionStartAdjust The start offset adjustment of the selection to use to highlight
505 * the search term. 419 * the search term.
506 * @param selectionEndAdjust The end offset adjustment of the selection to u se to highlight 420 * @param selectionEndAdjust The end offset adjustment of the selection to u se to highlight
507 * the search term. 421 * the search term.
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 // Starts are inclusive and ends are non-inclusive for both GSAContext & matcher. 597 // Starts are inclusive and ends are non-inclusive for both GSAContext & matcher.
684 while (matcher.find()) { 598 while (matcher.find()) {
685 if (startOffset >= matcher.start() && endOffset <= matcher.end()) { 599 if (startOffset >= matcher.start() && endOffset <= matcher.end()) {
686 return true; 600 return true;
687 } 601 }
688 } 602 }
689 603
690 return false; 604 return false;
691 } 605 }
692 } 606 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/action/ResolvedSearchAction.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698