| Index: chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
|
| index b1ac520fc8828c0d12afd85e0946fc5e3038a2a8..0f56a3639b7c9bdc60cbc83e4cf677e5f9c6005c 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
|
| @@ -4,45 +4,61 @@
|
|
|
| package org.chromium.chrome.browser.contextualsearch;
|
|
|
| +import android.text.TextUtils;
|
| +
|
| +import org.chromium.base.Log;
|
| import org.chromium.base.annotations.CalledByNative;
|
|
|
| +import javax.annotation.Nullable;
|
| +
|
| /**
|
| * Provides a context in which to search, and links to the native ContextualSearchContext.
|
| * Includes the selection, selection offsets, surrounding page content, etc.
|
| + * Requires an override of #onSelectionChanged to call when a non-empty selection is established
|
| + * or changed.
|
| */
|
| -public class ContextualSearchContext {
|
| - // The initial selection that established this context, or null.
|
| - private final String mSelection;
|
| +public abstract class ContextualSearchContext {
|
| + static final int INVALID_SELECTION_OFFSET = -1;
|
| + private static final String TAG = "ContextualSearch";
|
|
|
| // Pointer to the native instance of this class.
|
| private long mNativePointer;
|
|
|
| - // Whether this context can Resolve a Search Term.
|
| - private boolean mCanResolve;
|
| + // Whether this context has had the required properties set so it can Resolve a Search Term.
|
| + private boolean mHasSetResolveProperties;
|
| +
|
| + // A shortened version of the actual text content surrounding the selection, or null if not yet
|
| + // established.
|
| + private String mSurroundingText;
|
| +
|
| + // The start and end offsets of the selection within the text content.
|
| + private int mSelectionStartOffset = INVALID_SELECTION_OFFSET;
|
| + private int mSelectionEndOffset = INVALID_SELECTION_OFFSET;
|
| +
|
| + // The initial word selected by a Tap, or null.
|
| + private String mInitialSelectedWord;
|
| +
|
| + // The original encoding of the base page.
|
| + private String mEncoding;
|
|
|
| /**
|
| - * Constructs a context that cannot resolve a search term and has a small amount of
|
| - * page content.
|
| + * Constructs a context that tracks the selection and some amount of page content.
|
| */
|
| ContextualSearchContext() {
|
| mNativePointer = nativeInit();
|
| - mSelection = null;
|
| - mCanResolve = false;
|
| + mHasSetResolveProperties = false;
|
| }
|
|
|
| /**
|
| - * Constructs a context that can resolve a search term and has a large amount of
|
| + * Updates a context to be able to resolve a search term and have a large amount of
|
| * page content.
|
| - * @param selection The current selection.
|
| * @param homeCountry The country where the user usually resides, or an empty string if not
|
| * known.
|
| * @param maySendBasePageUrl Whether policy allows sending the base-page URL to the server.
|
| */
|
| - ContextualSearchContext(String selection, String homeCountry, boolean maySendBasePageUrl) {
|
| - mNativePointer = nativeInit();
|
| - mSelection = selection;
|
| - mCanResolve = true;
|
| - nativeSetResolveProperties(getNativePointer(), selection, homeCountry, maySendBasePageUrl);
|
| + void setResolveProperties(String homeCountry, boolean maySendBasePageUrl) {
|
| + mHasSetResolveProperties = true;
|
| + nativeSetResolveProperties(getNativePointer(), homeCountry, maySendBasePageUrl);
|
| }
|
|
|
| /**
|
| @@ -53,23 +69,153 @@ public class ContextualSearchContext {
|
| assert mNativePointer != 0;
|
| nativeDestroy(mNativePointer);
|
| mNativePointer = 0;
|
| +
|
| + // Also zero out private data that may be sizable.
|
| + mSurroundingText = null;
|
| + }
|
| +
|
| + /**
|
| + * Sets the surrounding text and selection offsets.
|
| + * @param encoding The original encoding of the base page.
|
| + * @param surroundingText The text from the base page surrounding the selection.
|
| + * @param startOffset The offset of start the selection.
|
| + * @param endOffset The offset of the end of the selection
|
| + */
|
| + void setSurroundingText(
|
| + String encoding, String surroundingText, int startOffset, int endOffset) {
|
| + mEncoding = encoding;
|
| + mSurroundingText = surroundingText;
|
| + mSelectionStartOffset = startOffset;
|
| + mSelectionEndOffset = endOffset;
|
| + // Notify of an initial selection if it's not empty.
|
| + if (endOffset > startOffset) onSelectionChanged();
|
| }
|
|
|
| /**
|
| - * @return the original selection.
|
| + * @return The text that surrounds the selection, or {@code null} if none yet known.
|
| */
|
| - String getSelection() {
|
| - return mSelection;
|
| + @Nullable
|
| + String getSurroundingText() {
|
| + return mSurroundingText;
|
| }
|
|
|
| /**
|
| - * @return Whether this context can "Resolve" the Search Term or is just used for a
|
| - * non-resolving Tap gesture or a Long-press gesture.
|
| + * @return The offset into the surrounding text of the start of the selection, or
|
| + * {@link #INVALID_SELECTION_OFFSET} if not yet established.
|
| + */
|
| + int getSelectionStartOffset() {
|
| + return mSelectionStartOffset;
|
| + }
|
| +
|
| + /**
|
| + * @return The offset into the surrounding text of the end of the selection, or
|
| + * {@link #INVALID_SELECTION_OFFSET} if not yet established.
|
| + */
|
| + int getSelectionEndOffset() {
|
| + return mSelectionEndOffset;
|
| + }
|
| +
|
| + /**
|
| + * @return The original encoding of the base page.
|
| + */
|
| + String getEncoding() {
|
| + return mEncoding;
|
| + }
|
| +
|
| + /**
|
| + * @return The initial word selected by a Tap.
|
| + */
|
| + String getInitialSelectedWord() {
|
| + return mInitialSelectedWord;
|
| + }
|
| +
|
| + /**
|
| + * @return The text content that follows the selection (one side of the surrounding text).
|
| + */
|
| + String getTextContentFollowingSelection() {
|
| + if (mSurroundingText != null && mSelectionEndOffset > 0
|
| + && mSelectionEndOffset <= mSurroundingText.length()) {
|
| + return mSurroundingText.substring(mSelectionEndOffset);
|
| + } else {
|
| + return "";
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @return Whether this context can Resolve the Search Term.
|
| */
|
| boolean canResolve() {
|
| - return mCanResolve;
|
| + return mHasSetResolveProperties && mSelectionStartOffset != INVALID_SELECTION_OFFSET
|
| + && mSelectionEndOffset != INVALID_SELECTION_OFFSET
|
| + && mSelectionEndOffset > mSelectionStartOffset;
|
| }
|
|
|
| + /**
|
| + * Notifies of an adjustment that has been applied to the start and end of the selection.
|
| + * @param startAdjust A signed value indicating the direction of the adjustment to the start of
|
| + * the selection (typically a negative value when the selection expands).
|
| + * @param endAdjust A signed value indicating the direction of the adjustment to the end of
|
| + * the selection (typically a positive value when the selection expands).
|
| + */
|
| + void onSelectionAdjusted(int startAdjust, int endAdjust) {
|
| + makeSelectionAdjustments(startAdjust, endAdjust);
|
| + }
|
| +
|
| + /**
|
| + * Update the context based on the given selection.
|
| + * TODO(donnd): This method of finding the adjustment to the selection is unreliable!
|
| + * TODO(donnd): Replace by getting the selection adjustment directly from
|
| + * {@link #onSelectionAdjusted} which is called by SelectWordAroundCaretAck
|
| + * (since it knows how the selection was actually adjusted).
|
| + * This method can be removed once SelectWordAroundCaretAck is in place.
|
| + * See crbug.com/435778 for details.
|
| + * @param selection The new selection.
|
| + */
|
| + void updateContextFromSelection(String selection) {
|
| + mInitialSelectedWord = selection;
|
| + if (mSelectionStartOffset == INVALID_SELECTION_OFFSET
|
| + || mSelectionEndOffset == INVALID_SELECTION_OFFSET
|
| + || TextUtils.isEmpty(mSurroundingText) || TextUtils.isEmpty(selection)) {
|
| + return;
|
| + }
|
| +
|
| + int selectionLength = selection.length();
|
| + for (int i = 0; i <= selectionLength; i++) {
|
| + int possibleStart = mSelectionStartOffset - i;
|
| + int possibleEnd = possibleStart + selectionLength;
|
| + if (possibleStart >= 0 && possibleEnd <= mSurroundingText.length()
|
| + && selection.equals(mSurroundingText.substring(possibleStart, possibleEnd))) {
|
| + makeSelectionAdjustments(-i, selectionLength - i);
|
| + return;
|
| + }
|
| + }
|
| +
|
| + Log.w(TAG, "Warning, unable to update context from the selection!");
|
| + }
|
| +
|
| + /**
|
| + * Makes adjustments to the selection offsets.
|
| + * @param startAdjust A signed value indicating the direction of the adjustment to the start of
|
| + * the selection (typically a negative value when the selection expands).
|
| + * @param endAdjust A signed value indicating the direction of the adjustment to the end of
|
| + * the selection (typically a positive value when the selection expands).
|
| + */
|
| + private void makeSelectionAdjustments(int startAdjust, int endAdjust) {
|
| + nativeAdjustSelection(getNativePointer(), startAdjust, endAdjust);
|
| + // Fully track the selection as it changes.
|
| + mSelectionStartOffset += startAdjust;
|
| + mSelectionEndOffset += endAdjust;
|
| + // Notify of changes.
|
| + onSelectionChanged();
|
| + }
|
| +
|
| + /**
|
| + * Notifies this instance that the selection has been changed.
|
| + */
|
| + abstract void onSelectionChanged();
|
| +
|
| + // TODO(donnd): Add a test for this class!
|
| +
|
| // ============================================================================================
|
| // Native callback support.
|
| // ============================================================================================
|
| @@ -85,6 +231,8 @@ public class ContextualSearchContext {
|
| // ============================================================================================
|
| private native long nativeInit();
|
| private native void nativeDestroy(long nativeContextualSearchContext);
|
| - private native void nativeSetResolveProperties(long nativeContextualSearchContext,
|
| - String selection, String homeCountry, boolean maySendBasePageUrl);
|
| + private native void nativeSetResolveProperties(
|
| + long nativeContextualSearchContext, String homeCountry, boolean maySendBasePageUrl);
|
| + private native void nativeAdjustSelection(
|
| + long nativeContextualSearchContext, int startAdjust, int endAdjust);
|
| }
|
|
|