| 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 | |
| 289 // anymore. | |
| 290 unscheduleInvalidTapNotification(); | |
| 291 } | 260 } |
| 292 break; | 261 break; |
| 293 case SelectionEventType.SELECTION_HANDLES_CLEARED: | 262 case SelectionEventType.SELECTION_HANDLES_CLEARED: |
| 294 mHandler.handleSelectionDismissal(); | 263 mHandler.handleSelectionDismissal(); |
| 295 resetAllStates(); | 264 resetAllStates(); |
| 296 break; | 265 break; |
| 297 case SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED: | 266 case SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED: |
| 298 shouldHandleSelection = mShouldHandleSelectionModification; | 267 shouldHandleSelection = mShouldHandleSelectionModification; |
| 299 break; | 268 break; |
| 300 default: | 269 default: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 327 } | 296 } |
| 328 | 297 |
| 329 /** | 298 /** |
| 330 * Resets all internal state of this class, including the tap state. | 299 * Resets all internal state of this class, including the tap state. |
| 331 */ | 300 */ |
| 332 private void resetAllStates() { | 301 private void resetAllStates() { |
| 333 resetSelectionStates(); | 302 resetSelectionStates(); |
| 334 mLastTapState = null; | 303 mLastTapState = null; |
| 335 mLastScrollTimeNs = 0; | 304 mLastScrollTimeNs = 0; |
| 336 mIsContextMenuShown = false; | 305 mIsContextMenuShown = false; |
| 306 mTapTimeNanoseconds = 0; |
| 307 mDidExpandSelection = false; |
| 337 } | 308 } |
| 338 | 309 |
| 339 /** | 310 /** |
| 340 * Resets all of the internal state of this class that handles the selection
. | 311 * Resets all of the internal state of this class that handles the selection
. |
| 341 */ | 312 */ |
| 342 private void resetSelectionStates() { | 313 private void resetSelectionStates() { |
| 343 mSelectionType = SelectionType.UNDETERMINED; | 314 mSelectionType = SelectionType.UNDETERMINED; |
| 344 mSelectedText = null; | 315 mSelectedText = null; |
| 345 | 316 |
| 346 mWasTapGestureDetected = false; | 317 mWasTapGestureDetected = false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 357 /** | 328 /** |
| 358 * Handles an unhandled tap gesture. | 329 * Handles an unhandled tap gesture. |
| 359 * @param x The x coordinate in px. | 330 * @param x The x coordinate in px. |
| 360 * @param y The y coordinate in px. | 331 * @param y The y coordinate in px. |
| 361 */ | 332 */ |
| 362 void handleShowUnhandledTapUIIfNeeded(int x, int y) { | 333 void handleShowUnhandledTapUIIfNeeded(int x, int y) { |
| 363 mWasTapGestureDetected = false; | 334 mWasTapGestureDetected = false; |
| 364 // TODO(donnd): refactor to avoid needing a new handler API method as su
ggested by Pedro. | 335 // TODO(donnd): refactor to avoid needing a new handler API method as su
ggested by Pedro. |
| 365 if (mSelectionType != SelectionType.LONG_PRESS) { | 336 if (mSelectionType != SelectionType.LONG_PRESS) { |
| 366 mWasTapGestureDetected = true; | 337 mWasTapGestureDetected = true; |
| 367 long tapTimeNanoseconds = System.nanoTime(); | 338 mSelectionType = SelectionType.TAP; |
| 368 // TODO(donnd): add a policy method to get adjusted tap count. | 339 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; | 340 mX = x; |
| 382 mY = y; | 341 mY = y; |
| 383 boolean shouldSuppressTap = mTapHeuristics.shouldSuppressTap(); | 342 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 { | 343 } else { |
| 401 // Long press; reset last tap state. | 344 // Long press; reset last tap state. |
| 402 mLastTapState = null; | 345 mLastTapState = null; |
| 403 mHandler.handleInvalidTap(); | 346 mHandler.handleInvalidTap(); |
| 404 } | 347 } |
| 405 } | 348 } |
| 406 | 349 |
| 407 /** | 350 /** |
| 351 * Handles Tap suppression by making a callback to either the handler's #han
dleSuppressedTap() |
| 352 * or #handleNonSuppressedTap() after a possible delay. |
| 353 * This should be called when the context is fully built (by gathering surro
unding text |
| 354 * if needed, etc) but before showing any UX. |
| 355 */ |
| 356 void handleShouldSuppressTap() { |
| 357 int x = (int) mX; |
| 358 int y = (int) mY; |
| 359 |
| 360 // TODO(donnd): add a policy method to get adjusted tap count. |
| 361 ChromePreferenceManager prefs = ChromePreferenceManager.getInstance(); |
| 362 int adjustedTapsSinceOpen = prefs.getContextualSearchTapCount() |
| 363 - prefs.getContextualSearchTapQuickAnswerCount(); |
| 364 TapSuppressionHeuristics tapHeuristics = |
| 365 new TapSuppressionHeuristics(this, mLastTapState, x, y, adjusted
TapsSinceOpen); |
| 366 // TODO(donnd): Move to be called when the panel closes to work with sta
tes that change. |
| 367 tapHeuristics.logConditionState(); |
| 368 // Tell the manager what it needs in order to log metrics on whether the
tap would have |
| 369 // been suppressed if each of the heuristics were satisfied. |
| 370 mHandler.handleMetricsForWouldSuppressTap(tapHeuristics); |
| 371 |
| 372 boolean shouldSuppressTap = tapHeuristics.shouldSuppressTap(); |
| 373 if (mTapTimeNanoseconds != 0) { |
| 374 // Remember the tap state for subsequent tap evaluation. |
| 375 mLastTapState = |
| 376 new ContextualSearchTapState(x, y, mTapTimeNanoseconds, shou
ldSuppressTap); |
| 377 } else { |
| 378 mLastTapState = null; |
| 379 } |
| 380 |
| 381 if (shouldSuppressTap) { |
| 382 mHandler.handleSuppressedTap(); |
| 383 } else { |
| 384 mHandler.handleNonSuppressedTap(); |
| 385 } |
| 386 } |
| 387 |
| 388 /** |
| 408 * Gets the base page ContentViewCore. | 389 * Gets the base page ContentViewCore. |
| 409 * Deprecated, use getBaseWebContents instead. | 390 * Deprecated, use getBaseWebContents instead. |
| 410 * @return The Base Page's {@link ContentViewCore}, or {@code null} if there
is no current tab. | 391 * @return The Base Page's {@link ContentViewCore}, or {@code null} if there
is no current tab. |
| 411 */ | 392 */ |
| 412 @Deprecated | 393 @Deprecated |
| 413 ContentViewCore getBaseContentView() { | 394 ContentViewCore getBaseContentView() { |
| 414 Tab currentTab = mActivity.getActivityTab(); | 395 Tab currentTab = mActivity.getActivityTab(); |
| 415 return currentTab != null ? currentTab.getContentViewCore() : null; | 396 return currentTab != null ? currentTab.getContentViewCore() : null; |
| 416 } | 397 } |
| 417 | 398 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 430 } | 411 } |
| 431 | 412 |
| 432 /** | 413 /** |
| 433 * Expands the current selection by the specified amounts. | 414 * Expands the current selection by the specified amounts. |
| 434 * @param selectionStartAdjust The start offset adjustment of the selection
to use to highlight | 415 * @param selectionStartAdjust The start offset adjustment of the selection
to use to highlight |
| 435 * the search term. | 416 * the search term. |
| 436 * @param selectionEndAdjust The end offset adjustment of the selection to u
se to highlight | 417 * @param selectionEndAdjust The end offset adjustment of the selection to u
se to highlight |
| 437 * the search term. | 418 * the search term. |
| 438 */ | 419 */ |
| 439 void adjustSelection(int selectionStartAdjust, int selectionEndAdjust) { | 420 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 | |
| 442 | |
| 443 if (selectionStartAdjust == 0 && selectionEndAdjust == 0) return; | 421 if (selectionStartAdjust == 0 && selectionEndAdjust == 0) return; |
| 444 WebContents basePageWebContents = getBaseWebContents(); | 422 WebContents basePageWebContents = getBaseWebContents(); |
| 445 if (basePageWebContents != null) { | 423 if (basePageWebContents != null) { |
| 446 mDidExpandSelection = true; | 424 mDidExpandSelection = true; |
| 447 basePageWebContents.adjustSelectionByCharacterOffset( | 425 basePageWebContents.adjustSelectionByCharacterOffset( |
| 448 selectionStartAdjust, selectionEndAdjust); | 426 selectionStartAdjust, selectionEndAdjust); |
| 449 } | 427 } |
| 450 } | 428 } |
| 451 | 429 |
| 452 // =========================================================================
=================== | 430 // =========================================================================
=================== |
| 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 | 431 // Selection Modification |
| 487 // =========================================================================
=================== | 432 // =========================================================================
=================== |
| 488 | 433 |
| 489 /** | 434 /** |
| 490 * This method checks whether the selection modification should be handled.
This method | 435 * 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. | 436 * is needed to allow modifying selections that are occluded by the Panel. |
| 492 * See crbug.com/489461. | 437 * See crbug.com/489461. |
| 493 * | 438 * |
| 494 * @param reason The reason the panel is closing. | 439 * @param reason The reason the panel is closing. |
| 495 * @return Whether the selection modification should be handled. | 440 * @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. | 566 // Starts are inclusive and ends are non-inclusive for both GSAContext &
matcher. |
| 622 while (matcher.find()) { | 567 while (matcher.find()) { |
| 623 if (startOffset >= matcher.start() && endOffset <= matcher.end()) { | 568 if (startOffset >= matcher.start() && endOffset <= matcher.end()) { |
| 624 return true; | 569 return true; |
| 625 } | 570 } |
| 626 } | 571 } |
| 627 | 572 |
| 628 return false; | 573 return false; |
| 629 } | 574 } |
| 630 } | 575 } |
| OLD | NEW |