/** Handles an unhandled tap gesture. */
 void handleShowUnhandledTapUIIfNeeded(int x, int y) {
   mWasTapGestureDetected = false;
   if (mSelectionType != SelectionType.LONG_PRESS && shouldHandleTap(x, y)) {
     mX = x;
     mY = y;
     mWasLastTapValid = true;
     mWasTapGestureDetected = true;
     // TODO(donnd): Find a better way to determine that a navigation will be triggered
     // by the tap, or merge with other time-consuming actions like gathering surrounding
     // text or detecting page mutations.
     new Handler()
         .postDelayed(
             new Runnable() {
               @Override
               public void run() {
                 mHandler.handleValidTap();
               }
             },
             TAP_NAVIGATION_DETECTION_DELAY);
   }
   if (!mWasTapGestureDetected) {
     mWasLastTapValid = false;
     mHandler.handleInvalidTap();
   }
 }
  /**
   * Handles a change in the current Selection.
   *
   * @param selection The selection portion of the context.
   */
  void handleSelectionChanged(String selection) {
    if (mDidExpandSelection) {
      mSelectedText = selection;
      mDidExpandSelection = false;
      return;
    }

    if (selection == null || selection.isEmpty()) {
      scheduleInvalidTapNotification();
      // When the user taps on the page it will place the caret in that position, which
      // will trigger a onSelectionChanged event with an empty string.
      if (mSelectionType == SelectionType.TAP) {
        // Since we mostly ignore a selection that's empty, we only need to partially reset.
        resetSelectionStates();
        return;
      }
    }
    if (!selection.isEmpty()) {
      unscheduleInvalidTapNotification();
    }

    mSelectedText = selection;

    if (mWasTapGestureDetected) {
      mSelectionType = SelectionType.TAP;
      handleSelection(selection, mSelectionType);
      mWasTapGestureDetected = false;
    } else {
      mHandler.handleSelectionModification(selection, isValidSelection(selection), mX, mY);
    }
  }
  /**
   * Handles a notification that a selection event took place.
   *
   * @param eventType The type of event that took place.
   * @param posXPix The x coordinate of the selection start handle.
   * @param posYPix The y coordinate of the selection start handle.
   */
  void handleSelectionEvent(int eventType, float posXPix, float posYPix) {
    boolean shouldHandleSelection = false;
    switch (eventType) {
      case SelectionEventType.SELECTION_HANDLES_SHOWN:
        mWasTapGestureDetected = false;
        mSelectionType = SelectionType.LONG_PRESS;
        shouldHandleSelection = true;
        // Since we're showing pins, we don't care if the previous tap was invalid anymore.
        unscheduleInvalidTapNotification();
        break;
      case SelectionEventType.SELECTION_HANDLES_CLEARED:
        mHandler.handleSelectionDismissal();
        resetAllStates();
        break;
      case SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED:
        shouldHandleSelection = mShouldHandleSelectionModification;
        break;
      case SelectionEventType.SELECTION_ESTABLISHED:
        mIsSelectionEstablished = true;
        break;
      case SelectionEventType.SELECTION_DISSOLVED:
        mIsSelectionEstablished = false;
        break;
      default:
    }

    if (shouldHandleSelection) {
      ContentViewCore baseContentView = getBaseContentView();
      if (baseContentView != null) {
        String selection = baseContentView.getSelectedText();
        if (selection != null) {
          mX = posXPix;
          mY = posYPix;
          mSelectedText = selection;
          handleSelection(selection, SelectionType.LONG_PRESS);
        }
      }
    }
  }
 /** Notify's the system that tap gesture has been completed. */
 private void onInvalidTapDetectionTimeout() {
   mHandler.handleInvalidTap();
   mIsWaitingForInvalidTapDetection = false;
 }
 /**
  * Re-enables selection modification handling and invokes
  * ContextualSearchSelectionHandler.handleSelection().
  *
  * @param selection The text that was selected.
  * @param type The type of selection made by the user.
  */
 private void handleSelection(String selection, SelectionType type) {
   mShouldHandleSelectionModification = true;
   mHandler.handleSelection(selection, isValidSelection(selection), type, mX, mY);
 }