Chromium Code Reviews| OLD | NEW |
|---|---|
| 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; | |
| 8 import android.text.TextUtils; | 7 import android.text.TextUtils; |
| 9 | 8 |
| 10 import org.chromium.base.VisibleForTesting; | 9 import org.chromium.base.VisibleForTesting; |
| 11 import org.chromium.chrome.browser.ChromeActivity; | 10 import org.chromium.chrome.browser.ChromeActivity; |
| 12 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; | 11 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; |
| 13 import org.chromium.chrome.browser.contextualsearch.ContextualSearchBlacklist.Bl acklistReason; | 12 import org.chromium.chrome.browser.contextualsearch.ContextualSearchBlacklist.Bl acklistReason; |
| 14 import org.chromium.chrome.browser.preferences.ChromePreferenceManager; | 13 import org.chromium.chrome.browser.preferences.ChromePreferenceManager; |
| 15 import org.chromium.chrome.browser.tab.Tab; | 14 import org.chromium.chrome.browser.tab.Tab; |
| 16 import org.chromium.content.browser.ContentViewCore; | 15 import org.chromium.content.browser.ContentViewCore; |
| 17 import org.chromium.content_public.browser.GestureStateListener; | 16 import org.chromium.content_public.browser.GestureStateListener; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 28 | 27 |
| 29 /** | 28 /** |
| 30 * The type of selection made by the user. | 29 * The type of selection made by the user. |
| 31 */ | 30 */ |
| 32 public enum SelectionType { | 31 public enum SelectionType { |
| 33 UNDETERMINED, | 32 UNDETERMINED, |
| 34 TAP, | 33 TAP, |
| 35 LONG_PRESS | 34 LONG_PRESS |
| 36 } | 35 } |
| 37 | 36 |
| 38 // The number of milliseconds to wait for a selection change after a tap bef ore considering | |
| 39 // the tap invalid. This can't be too small or the subsequent taps may not have established | |
| 40 // a new selection in time. This is because selectWordAroundCaret doesn't a lways select. | |
| 41 // TODO(donnd): Fix in Blink, crbug.com/435778. | |
| 42 private static final int INVALID_IF_NO_SELECTION_CHANGE_AFTER_TAP_MS = 50; | |
| 43 | |
| 44 // The default navigation-detection-delay in milliseconds. | |
| 45 private static final int TAP_NAVIGATION_DETECTION_DELAY = 16; | |
| 46 | |
| 47 private static final String CONTAINS_WORD_PATTERN = "(\\w|\\p{L}|\\p{N})+"; | 37 private static final String CONTAINS_WORD_PATTERN = "(\\w|\\p{L}|\\p{N})+"; |
| 48 // A URL is: | 38 // A URL is: |
| 49 // 1: scheme:// | 39 // 1: scheme:// |
| 50 // 1+: any word char, _ or - | 40 // 1+: any word char, _ or - |
| 51 // 1+: . followed by 1+ of any word char, _ or - | 41 // 1+: . followed by 1+ of any word char, _ or - |
| 52 // 0-1: 0+ of any word char or .,@?^=%&:/~#- followed by any word char or @?^-%&/~+#- | 42 // 0-1: 0+ of any word char or .,@?^=%&:/~#- followed by any word char or @?^-%&/~+#- |
| 53 // TODO(twellington): expand accepted schemes? | 43 // TODO(twellington): expand accepted schemes? |
| 54 private static final Pattern URL_PATTERN = Pattern.compile("((http|https|fil e|ftp|ssh)://)" | 44 private static final Pattern URL_PATTERN = Pattern.compile("((http|https|fil e|ftp|ssh)://)" |
| 55 + "([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+# -])?"); | 45 + "([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+# -])?"); |
| 56 | 46 |
| 57 // Max selection length must be limited or the entire request URL can go pas t the 2K limit. | 47 // Max selection length must be limited or the entire request URL can go pas t the 2K limit. |
| 58 private static final int MAX_SELECTION_LENGTH = 100; | 48 private static final int MAX_SELECTION_LENGTH = 100; |
| 59 | 49 |
| 60 private final ChromeActivity mActivity; | 50 private final ChromeActivity mActivity; |
| 61 private final ContextualSearchSelectionHandler mHandler; | 51 private final ContextualSearchSelectionHandler mHandler; |
| 62 private final Runnable mHandleInvalidTapRunnable; | |
| 63 private final Handler mRunnableHandler; | |
| 64 private final float mPxToDp; | 52 private final float mPxToDp; |
| 65 private final Pattern mContainsWordPattern; | 53 private final Pattern mContainsWordPattern; |
| 66 | 54 |
| 67 private String mSelectedText; | 55 private String mSelectedText; |
| 68 private SelectionType mSelectionType; | 56 private SelectionType mSelectionType; |
| 69 private boolean mWasTapGestureDetected; | 57 private boolean mWasTapGestureDetected; |
| 70 // Reflects whether the last tap was valid and whether we still have a tap-b ased selection. | 58 // Reflects whether the last tap was valid and whether we still have a tap-b ased selection. |
| 71 private ContextualSearchTapState mLastTapState; | 59 private ContextualSearchTapState mLastTapState; |
| 72 private TapSuppressionHeuristics mTapHeuristics; | |
| 73 private boolean mIsWaitingForInvalidTapDetection; | 60 private boolean mIsWaitingForInvalidTapDetection; |
| 74 private boolean mShouldHandleSelectionModification; | 61 private boolean mShouldHandleSelectionModification; |
| 75 private boolean mDidExpandSelection; | 62 private boolean mDidExpandSelection; |
| 76 | 63 |
| 77 // Position of the selection. | 64 // Position of the selection. |
| 78 private float mX; | 65 private float mX; |
| 79 private float mY; | 66 private float mY; |
| 80 | 67 |
| 81 // The time of the most last scroll activity, or 0 if none. | 68 // The time of the most last scroll activity, or 0 if none. |
| 82 private long mLastScrollTimeNs; | 69 private long mLastScrollTimeNs; |
| 83 | 70 |
| 71 // When the last tap gesture happened. | |
| 72 private long mTapTimeNanoseconds; | |
| 73 | |
| 84 // Tracks whether a Context Menu has just been shown and the UX has been dis missed. | 74 // Tracks whether a Context Menu has just been shown and the UX has been dis missed. |
| 85 // The selection may be unreliable until the next reset. See crbug.com/6284 36. | 75 // The selection may be unreliable until the next reset. See crbug.com/6284 36. |
| 86 private boolean mIsContextMenuShown; | 76 private boolean mIsContextMenuShown; |
| 87 | 77 |
| 88 private class ContextualSearchGestureStateListener extends GestureStateListe ner { | 78 private class ContextualSearchGestureStateListener extends GestureStateListe ner { |
| 89 @Override | 79 @Override |
| 90 public void onScrollStarted(int scrollOffsetY, int scrollExtentY) { | 80 public void onScrollStarted(int scrollOffsetY, int scrollExtentY) { |
| 91 mHandler.handleScroll(); | 81 mHandler.handleScroll(); |
| 92 } | 82 } |
| 93 | 83 |
| 94 @Override | 84 @Override |
| 95 public void onScrollEnded(int scrollOffsetY, int scrollExtentY) { | 85 public void onScrollEnded(int scrollOffsetY, int scrollExtentY) { |
| 96 mLastScrollTimeNs = System.nanoTime(); | 86 mLastScrollTimeNs = System.nanoTime(); |
| 97 } | 87 } |
| 98 | 88 |
| 99 @Override | 89 @Override |
| 100 public void onScrollUpdateGestureConsumed() { | 90 public void onScrollUpdateGestureConsumed() { |
| 101 // The onScrollEnded notification is unreliable, so mark time during scroll updates too. | 91 // The onScrollEnded notification is unreliable, so mark time during scroll updates too. |
| 102 // See crbug.com/600863. | 92 // See crbug.com/600863. |
| 103 mLastScrollTimeNs = System.nanoTime(); | 93 mLastScrollTimeNs = System.nanoTime(); |
| 104 } | 94 } |
| 105 | 95 |
| 106 // TODO(donnd): Remove this once we get notification of the selection ch anging | 96 // TODO(donnd): Remove this once we get notification of the selection ch anging |
| 107 // after a tap-select gets a subsequent tap nearby. Currently there's n o | 97 // after a tap-select gets a subsequent tap nearby. Currently there's n o |
| 108 // notification in this case. | 98 // notification in this case. |
| 109 // See crbug.com/444114. | 99 // See crbug.com/444114. |
| 110 @Override | 100 @Override |
| 111 public void onSingleTap(boolean consumed) { | 101 public void onSingleTap(boolean consumed) { |
| 112 // We may be notified that a tap has happened even when the system c onsumed the event. | 102 // TODO(donnd): remove completely! |
| 113 // This is being used to support tapping on an existing selection to show the selection | |
| 114 // handles. We should process this tap unless we have already shown the selection | |
| 115 // handles (have a long-press selection) and the tap was consumed. | |
| 116 if (!(consumed && mSelectionType == SelectionType.LONG_PRESS)) { | |
| 117 scheduleInvalidTapNotification(); | |
| 118 } | |
| 119 } | 103 } |
| 120 } | 104 } |
| 121 | 105 |
| 122 /** | 106 /** |
| 123 * Constructs a new Selection controller for the given activity. Callbacks will be issued | 107 * Constructs a new Selection controller for the given activity. Callbacks will be issued |
| 124 * through the given selection handler. | 108 * through the given selection handler. |
| 125 * @param activity The {@link ChromeActivity} to control. | 109 * @param activity The {@link ChromeActivity} to control. |
| 126 * @param handler The handler for callbacks. | 110 * @param handler The handler for callbacks. |
| 127 */ | 111 */ |
| 128 public ContextualSearchSelectionController(ChromeActivity activity, | 112 public ContextualSearchSelectionController(ChromeActivity activity, |
| 129 ContextualSearchSelectionHandler handler) { | 113 ContextualSearchSelectionHandler handler) { |
| 130 mActivity = activity; | 114 mActivity = activity; |
| 131 mHandler = handler; | 115 mHandler = handler; |
| 132 mPxToDp = 1.f / mActivity.getResources().getDisplayMetrics().density; | 116 mPxToDp = 1.f / mActivity.getResources().getDisplayMetrics().density; |
| 133 | |
| 134 mRunnableHandler = new Handler(); | |
| 135 mHandleInvalidTapRunnable = new Runnable() { | |
| 136 @Override | |
| 137 public void run() { | |
| 138 onInvalidTapDetectionTimeout(); | |
| 139 } | |
| 140 }; | |
| 141 | |
| 142 mContainsWordPattern = Pattern.compile(CONTAINS_WORD_PATTERN); | 117 mContainsWordPattern = Pattern.compile(CONTAINS_WORD_PATTERN); |
| 143 } | 118 } |
| 144 | 119 |
| 145 /** | 120 /** |
| 146 * Notifies that the base page has started loading a page. | 121 * Notifies that the base page has started loading a page. |
| 147 */ | 122 */ |
| 148 void onBasePageLoadStarted() { | 123 void onBasePageLoadStarted() { |
| 149 resetAllStates(); | 124 resetAllStates(); |
| 150 } | 125 } |
| 151 | 126 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 * @param selection The selection portion of the context. | 214 * @param selection The selection portion of the context. |
| 240 */ | 215 */ |
| 241 void handleSelectionChanged(String selection) { | 216 void handleSelectionChanged(String selection) { |
| 242 if (mDidExpandSelection) { | 217 if (mDidExpandSelection) { |
| 243 mSelectedText = selection; | 218 mSelectedText = selection; |
| 244 mDidExpandSelection = false; | 219 mDidExpandSelection = false; |
| 245 return; | 220 return; |
| 246 } | 221 } |
| 247 | 222 |
| 248 if (selection == null || selection.isEmpty()) { | 223 if (selection == null || selection.isEmpty()) { |
| 249 scheduleInvalidTapNotification(); | 224 mHandler.handleSelectionCleared(); |
| 250 // When the user taps on the page it will place the caret in that po sition, which | 225 // When the user taps on the page it will place the caret in that po sition, which |
| 251 // will trigger a onSelectionChanged event with an empty string. | 226 // will trigger a onSelectionChanged event with an empty string. |
| 252 if (mSelectionType == SelectionType.TAP) { | 227 if (mSelectionType == SelectionType.TAP) { |
| 253 // Since we mostly ignore a selection that's empty, we only need to partially reset. | 228 // Since we mostly ignore a selection that's empty, we only need to partially reset. |
| 254 resetSelectionStates(); | 229 resetSelectionStates(); |
| 255 return; | 230 return; |
| 256 } | 231 } |
| 257 } | 232 } |
| 258 if (!selection.isEmpty()) { | |
| 259 unscheduleInvalidTapNotification(); | |
| 260 } | |
| 261 | 233 |
| 262 mSelectedText = selection; | 234 mSelectedText = selection; |
| 263 | 235 |
| 264 if (mWasTapGestureDetected) { | 236 if (mWasTapGestureDetected) { |
| 265 mSelectionType = SelectionType.TAP; | 237 assert mSelectionType == SelectionType.TAP; |
| 266 handleSelection(selection, mSelectionType); | 238 handleSelection(selection, mSelectionType); |
| 267 mWasTapGestureDetected = false; | 239 mWasTapGestureDetected = false; |
| 268 } else { | 240 } else { |
| 269 boolean isValidSelection = validateSelectionSuppression(selection); | 241 boolean isValidSelection = validateSelectionSuppression(selection); |
| 270 mHandler.handleSelectionModification(selection, isValidSelection, mX , mY); | 242 mHandler.handleSelectionModification(selection, isValidSelection, mX , mY); |
| 271 } | 243 } |
| 272 } | 244 } |
| 273 | 245 |
| 274 /** | 246 /** |
| 275 * Handles a notification that a selection event took place. | 247 * Handles a notification that a selection event took place. |
| 276 * @param eventType The type of event that took place. | 248 * @param eventType The type of event that took place. |
| 277 * @param posXPix The x coordinate of the selection start handle. | 249 * @param posXPix The x coordinate of the selection start handle. |
| 278 * @param posYPix The y coordinate of the selection start handle. | 250 * @param posYPix The y coordinate of the selection start handle. |
| 279 */ | 251 */ |
| 280 void handleSelectionEvent(int eventType, float posXPix, float posYPix) { | 252 void handleSelectionEvent(int eventType, float posXPix, float posYPix) { |
| 281 boolean shouldHandleSelection = false; | 253 boolean shouldHandleSelection = false; |
| 282 switch (eventType) { | 254 switch (eventType) { |
| 283 case SelectionEventType.SELECTION_HANDLES_SHOWN: | 255 case SelectionEventType.SELECTION_HANDLES_SHOWN: |
| 284 if (!mIsContextMenuShown) { | 256 if (!mIsContextMenuShown) { |
| 285 mWasTapGestureDetected = false; | 257 mWasTapGestureDetected = false; |
| 286 mSelectionType = SelectionType.LONG_PRESS; | 258 mSelectionType = SelectionType.LONG_PRESS; |
| 287 shouldHandleSelection = true; | 259 shouldHandleSelection = true; |
| 288 // Since we're showing pins, we don't care if the previous t ap was invalid | 260 // Since we're showing pins, we don't care if the previous t ap was invalid |
| 289 // anymore. | 261 // anymore. |
|
Theresa
2017/04/25 17:30:42
Can we remove this comment too?
Donn Denman
2017/04/25 22:35:38
Done.
| |
| 290 unscheduleInvalidTapNotification(); | |
| 291 } | 262 } |
| 292 break; | 263 break; |
| 293 case SelectionEventType.SELECTION_HANDLES_CLEARED: | 264 case SelectionEventType.SELECTION_HANDLES_CLEARED: |
| 294 mHandler.handleSelectionDismissal(); | 265 mHandler.handleSelectionDismissal(); |
| 295 resetAllStates(); | 266 resetAllStates(); |
| 296 break; | 267 break; |
| 297 case SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED: | 268 case SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED: |
| 298 shouldHandleSelection = mShouldHandleSelectionModification; | 269 shouldHandleSelection = mShouldHandleSelectionModification; |
| 299 break; | 270 break; |
| 300 default: | 271 default: |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 327 } | 298 } |
| 328 | 299 |
| 329 /** | 300 /** |
| 330 * Resets all internal state of this class, including the tap state. | 301 * Resets all internal state of this class, including the tap state. |
| 331 */ | 302 */ |
| 332 private void resetAllStates() { | 303 private void resetAllStates() { |
| 333 resetSelectionStates(); | 304 resetSelectionStates(); |
| 334 mLastTapState = null; | 305 mLastTapState = null; |
| 335 mLastScrollTimeNs = 0; | 306 mLastScrollTimeNs = 0; |
| 336 mIsContextMenuShown = false; | 307 mIsContextMenuShown = false; |
| 308 mTapTimeNanoseconds = 0; | |
| 309 mDidExpandSelection = false; | |
| 337 } | 310 } |
| 338 | 311 |
| 339 /** | 312 /** |
| 340 * Resets all of the internal state of this class that handles the selection . | 313 * Resets all of the internal state of this class that handles the selection . |
| 341 */ | 314 */ |
| 342 private void resetSelectionStates() { | 315 private void resetSelectionStates() { |
| 343 mSelectionType = SelectionType.UNDETERMINED; | 316 mSelectionType = SelectionType.UNDETERMINED; |
| 344 mSelectedText = null; | 317 mSelectedText = null; |
| 345 | 318 |
| 346 mWasTapGestureDetected = false; | 319 mWasTapGestureDetected = false; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 357 /** | 330 /** |
| 358 * Handles an unhandled tap gesture. | 331 * Handles an unhandled tap gesture. |
| 359 * @param x The x coordinate in px. | 332 * @param x The x coordinate in px. |
| 360 * @param y The y coordinate in px. | 333 * @param y The y coordinate in px. |
| 361 */ | 334 */ |
| 362 void handleShowUnhandledTapUIIfNeeded(int x, int y) { | 335 void handleShowUnhandledTapUIIfNeeded(int x, int y) { |
| 363 mWasTapGestureDetected = false; | 336 mWasTapGestureDetected = false; |
| 364 // TODO(donnd): refactor to avoid needing a new handler API method as su ggested by Pedro. | 337 // TODO(donnd): refactor to avoid needing a new handler API method as su ggested by Pedro. |
| 365 if (mSelectionType != SelectionType.LONG_PRESS) { | 338 if (mSelectionType != SelectionType.LONG_PRESS) { |
| 366 mWasTapGestureDetected = true; | 339 mWasTapGestureDetected = true; |
| 367 long tapTimeNanoseconds = System.nanoTime(); | 340 mSelectionType = SelectionType.TAP; |
| 368 // TODO(donnd): add a policy method to get adjusted tap count. | 341 mTapTimeNanoseconds = System.nanoTime(); |
| 369 ChromePreferenceManager prefs = ChromePreferenceManager.getInstance( ); | |
| 370 int adjustedTapsSinceOpen = prefs.getContextualSearchTapCount() | |
| 371 - prefs.getContextualSearchTapQuickAnswerCount(); | |
| 372 // Explicitly destroy the old heuristics so native code can dispose data. | |
| 373 if (mTapHeuristics != null) mTapHeuristics.destroy(); | |
| 374 mTapHeuristics = | |
| 375 new TapSuppressionHeuristics(this, mLastTapState, x, y, adju stedTapsSinceOpen); | |
| 376 // TODO(donnd): Move to be called when the panel closes to work with states that change. | |
| 377 mTapHeuristics.logConditionState(); | |
| 378 // Tell the manager what it needs in order to log metrics on whether the tap would have | |
| 379 // been suppressed if each of the heuristics were satisfied. | |
| 380 mHandler.handleMetricsForWouldSuppressTap(mTapHeuristics); | |
| 381 mX = x; | 342 mX = x; |
| 382 mY = y; | 343 mY = y; |
| 383 boolean shouldSuppressTap = mTapHeuristics.shouldSuppressTap(); | 344 mHandler.handleValidTap(); |
| 384 if (shouldSuppressTap) { | |
| 385 mHandler.handleSuppressedTap(); | |
| 386 } else { | |
| 387 // TODO(donnd): Find a better way to determine that a navigation will be triggered | |
| 388 // by the tap, or merge with other time-consuming actions like g athering surrounding | |
| 389 // text or detecting page mutations. | |
| 390 new Handler().postDelayed(new Runnable() { | |
| 391 @Override | |
| 392 public void run() { | |
| 393 mHandler.handleValidTap(); | |
| 394 } | |
| 395 }, TAP_NAVIGATION_DETECTION_DELAY); | |
| 396 } | |
| 397 // Remember the tap state for subsequent tap evaluation. | |
| 398 mLastTapState = | |
| 399 new ContextualSearchTapState(x, y, tapTimeNanoseconds, shoul dSuppressTap); | |
| 400 } else { | 345 } else { |
| 401 // Long press; reset last tap state. | 346 // Long press; reset last tap state. |
| 402 mLastTapState = null; | 347 mLastTapState = null; |
| 403 mHandler.handleInvalidTap(); | 348 mHandler.handleInvalidTap(); |
| 404 } | 349 } |
| 405 } | 350 } |
| 406 | 351 |
| 407 /** | 352 /** |
| 353 * Handles Tap suppression by making a callback to either the handler's hand leSuppressedTap or | |
|
Theresa
2017/04/25 17:30:42
nit: #handleSuppressedTap() or #handleNonSuppresse
Donn Denman
2017/04/25 22:35:37
Done.
| |
| 354 * handleNonSuppressedTap after a possible delay. | |
| 355 * This should be called when the context is fully build (by gathering surro unding text | |
|
Theresa
2017/04/25 17:30:42
nit: s/build/built
Donn Denman
2017/04/25 22:35:38
Done.
| |
| 356 * if needed, etc) but before showing any UX. | |
| 357 */ | |
| 358 void handleShouldSuppressTap() { | |
| 359 int x = (int) mX; | |
| 360 int y = (int) mY; | |
| 361 | |
| 362 // TODO(donnd): add a policy method to get adjusted tap count. | |
| 363 ChromePreferenceManager prefs = ChromePreferenceManager.getInstance(); | |
| 364 int adjustedTapsSinceOpen = prefs.getContextualSearchTapCount() | |
| 365 - prefs.getContextualSearchTapQuickAnswerCount(); | |
| 366 TapSuppressionHeuristics tapHeuristics = | |
| 367 new TapSuppressionHeuristics(this, mLastTapState, x, y, adjusted TapsSinceOpen); | |
| 368 // TODO(donnd): Move to be called when the panel closes to work with sta tes that change. | |
| 369 tapHeuristics.logConditionState(); | |
| 370 // Tell the manager what it needs in order to log metrics on whether the tap would have | |
| 371 // been suppressed if each of the heuristics were satisfied. | |
| 372 mHandler.handleMetricsForWouldSuppressTap(tapHeuristics); | |
| 373 | |
| 374 boolean shouldSuppressTap = tapHeuristics.shouldSuppressTap(); | |
| 375 if (mTapTimeNanoseconds != 0) { | |
| 376 // Remember the tap state for subsequent tap evaluation. | |
| 377 mLastTapState = | |
| 378 new ContextualSearchTapState(x, y, mTapTimeNanoseconds, shou ldSuppressTap); | |
| 379 } else { | |
| 380 mLastTapState = null; | |
| 381 } | |
| 382 | |
| 383 if (shouldSuppressTap) { | |
| 384 mHandler.handleSuppressedTap(); | |
| 385 } else { | |
| 386 mHandler.handleNonSuppressedTap(); | |
| 387 } | |
| 388 } | |
| 389 | |
| 390 /** | |
| 408 * Gets the base page ContentViewCore. | 391 * Gets the base page ContentViewCore. |
| 409 * Deprecated, use getBaseWebContents instead. | 392 * Deprecated, use getBaseWebContents instead. |
| 410 * @return The Base Page's {@link ContentViewCore}, or {@code null} if there is no current tab. | 393 * @return The Base Page's {@link ContentViewCore}, or {@code null} if there is no current tab. |
| 411 */ | 394 */ |
| 412 @Deprecated | 395 @Deprecated |
| 413 ContentViewCore getBaseContentView() { | 396 ContentViewCore getBaseContentView() { |
| 414 Tab currentTab = mActivity.getActivityTab(); | 397 Tab currentTab = mActivity.getActivityTab(); |
| 415 return currentTab != null ? currentTab.getContentViewCore() : null; | 398 return currentTab != null ? currentTab.getContentViewCore() : null; |
| 416 } | 399 } |
| 417 | 400 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 430 } | 413 } |
| 431 | 414 |
| 432 /** | 415 /** |
| 433 * Expands the current selection by the specified amounts. | 416 * Expands the current selection by the specified amounts. |
| 434 * @param selectionStartAdjust The start offset adjustment of the selection to use to highlight | 417 * @param selectionStartAdjust The start offset adjustment of the selection to use to highlight |
| 435 * the search term. | 418 * the search term. |
| 436 * @param selectionEndAdjust The end offset adjustment of the selection to u se to highlight | 419 * @param selectionEndAdjust The end offset adjustment of the selection to u se to highlight |
| 437 * the search term. | 420 * the search term. |
| 438 */ | 421 */ |
| 439 void adjustSelection(int selectionStartAdjust, int selectionEndAdjust) { | 422 void adjustSelection(int selectionStartAdjust, int selectionEndAdjust) { |
| 440 // TODO(donnd): add code to verify that the selection is still valid bef ore changing it. | |
| 441 // crbug.com/508354 | |
|
Theresa
2017/04/25 17:30:42
Why is this TODO no longer neeeded?
Donn Denman
2017/04/25 22:35:37
Added a check in handleSearchTermResolutionRespons
| |
| 442 | |
| 443 if (selectionStartAdjust == 0 && selectionEndAdjust == 0) return; | 423 if (selectionStartAdjust == 0 && selectionEndAdjust == 0) return; |
| 444 WebContents basePageWebContents = getBaseWebContents(); | 424 WebContents basePageWebContents = getBaseWebContents(); |
| 445 if (basePageWebContents != null) { | 425 if (basePageWebContents != null) { |
| 446 mDidExpandSelection = true; | 426 mDidExpandSelection = true; |
| 447 basePageWebContents.adjustSelectionByCharacterOffset( | 427 basePageWebContents.adjustSelectionByCharacterOffset( |
| 448 selectionStartAdjust, selectionEndAdjust); | 428 selectionStartAdjust, selectionEndAdjust); |
| 449 } | 429 } |
| 450 } | 430 } |
| 451 | 431 |
| 452 // ========================================================================= =================== | 432 // ========================================================================= =================== |
| 453 // Invalid Tap Notification | |
| 454 // ========================================================================= =================== | |
| 455 | |
| 456 /** | |
| 457 * Schedules a notification to check if the tap was invalid. | |
| 458 * When we call selectWordAroundCaret it selects nothing in cases where the tap was invalid. | |
| 459 * We have no way to know other than scheduling a notification to check late r. | |
| 460 * This allows us to hide the bar when there's no selection. | |
| 461 */ | |
| 462 private void scheduleInvalidTapNotification() { | |
| 463 // TODO(donnd): Fix selectWordAroundCaret to we can tell if it selects, instead | |
| 464 // of using a timer here! See crbug.com/435778. | |
| 465 mRunnableHandler.postDelayed(mHandleInvalidTapRunnable, | |
| 466 INVALID_IF_NO_SELECTION_CHANGE_AFTER_TAP_MS); | |
| 467 } | |
| 468 | |
| 469 /** | |
| 470 * Un-schedules all pending notifications to check if a tap was invalid. | |
| 471 */ | |
| 472 private void unscheduleInvalidTapNotification() { | |
| 473 mRunnableHandler.removeCallbacks(mHandleInvalidTapRunnable); | |
| 474 mIsWaitingForInvalidTapDetection = true; | |
| 475 } | |
| 476 | |
| 477 /** | |
| 478 * Notify's the system that tap gesture has been completed. | |
| 479 */ | |
| 480 private void onInvalidTapDetectionTimeout() { | |
| 481 mHandler.handleInvalidTap(); | |
| 482 mIsWaitingForInvalidTapDetection = false; | |
| 483 } | |
| 484 | |
| 485 // ========================================================================= =================== | |
| 486 // Selection Modification | 433 // Selection Modification |
| 487 // ========================================================================= =================== | 434 // ========================================================================= =================== |
| 488 | 435 |
| 489 /** | 436 /** |
| 490 * This method checks whether the selection modification should be handled. This method | 437 * This method checks whether the selection modification should be handled. This method |
| 491 * is needed to allow modifying selections that are occluded by the Panel. | 438 * is needed to allow modifying selections that are occluded by the Panel. |
| 492 * See crbug.com/489461. | 439 * See crbug.com/489461. |
| 493 * | 440 * |
| 494 * @param reason The reason the panel is closing. | 441 * @param reason The reason the panel is closing. |
| 495 * @return Whether the selection modification should be handled. | 442 * @return Whether the selection modification should be handled. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 // Starts are inclusive and ends are non-inclusive for both GSAContext & matcher. | 568 // Starts are inclusive and ends are non-inclusive for both GSAContext & matcher. |
| 622 while (matcher.find()) { | 569 while (matcher.find()) { |
| 623 if (startOffset >= matcher.start() && endOffset <= matcher.end()) { | 570 if (startOffset >= matcher.start() && endOffset <= matcher.end()) { |
| 624 return true; | 571 return true; |
| 625 } | 572 } |
| 626 } | 573 } |
| 627 | 574 |
| 628 return false; | 575 return false; |
| 629 } | 576 } |
| 630 } | 577 } |
| OLD | NEW |