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

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java

Issue 2906763002: [TTS] Add some initial signals for Tap in content. (Closed)
Patch Set: Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
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 5d80817b268f82afdf521f8da31c4176b6902342..9ed354309497ac4474c036ed8379b1f7f9ad1329 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,6 +4,7 @@
package org.chromium.chrome.browser.contextualsearch;
+import android.annotation.SuppressLint;
import android.text.TextUtils;
import org.chromium.base.annotations.CalledByNative;
@@ -17,7 +18,10 @@ import javax.annotation.Nullable;
* or changed.
*/
public abstract class ContextualSearchContext {
- static final int INVALID_SELECTION_OFFSET = -1;
+ static final int INVALID_OFFSET = -1;
+
+ // non-visible word-break marker present in German Wikipedia pages.
+ static final int SOFT_HYPHEN = 173;
// Pointer to the native instance of this class.
private long mNativePointer;
@@ -30,8 +34,12 @@ public abstract class ContextualSearchContext {
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;
+ private int mSelectionStartOffset = INVALID_OFFSET;
+ private int mSelectionEndOffset = INVALID_OFFSET;
+
+ // The start and end offsets of an initial Tap gesture within the text content.
+ private int mTapStartOffset = INVALID_OFFSET;
+ private int mTapEndOffset = INVALID_OFFSET;
// The initial word selected by a Tap, or null.
private String mInitialSelectedWord;
@@ -39,6 +47,11 @@ public abstract class ContextualSearchContext {
// The original encoding of the base page.
private String mEncoding;
+ // The tapped word as analyzed internally before selection takes place, or {@code null} if no
+ // analysis has been done yet.
+ private String mTappedWord;
+ private int mTappedWordStartOffset = INVALID_OFFSET;
+
/**
* Constructs a context that tracks the selection and some amount of page content.
*/
@@ -85,6 +98,11 @@ public abstract class ContextualSearchContext {
mSurroundingText = surroundingText;
mSelectionStartOffset = startOffset;
mSelectionEndOffset = endOffset;
+ if (startOffset == endOffset && mTapStartOffset == INVALID_OFFSET
+ && mTapEndOffset == INVALID_OFFSET) {
+ mTapStartOffset = startOffset;
+ mTapEndOffset = endOffset;
+ }
// Notify of an initial selection if it's not empty.
if (endOffset > startOffset) onSelectionChanged();
}
@@ -99,7 +117,7 @@ public abstract class ContextualSearchContext {
/**
* @return The offset into the surrounding text of the start of the selection, or
- * {@link #INVALID_SELECTION_OFFSET} if not yet established.
+ * {@link #INVALID_OFFSET} if not yet established.
*/
int getSelectionStartOffset() {
return mSelectionStartOffset;
@@ -107,7 +125,7 @@ public abstract class ContextualSearchContext {
/**
* @return The offset into the surrounding text of the end of the selection, or
- * {@link #INVALID_SELECTION_OFFSET} if not yet established.
+ * {@link #INVALID_OFFSET} if not yet established.
*/
int getSelectionEndOffset() {
return mSelectionEndOffset;
@@ -143,9 +161,7 @@ public abstract class ContextualSearchContext {
* @return Whether this context can Resolve the Search Term.
*/
boolean canResolve() {
- return mHasSetResolveProperties && mSelectionStartOffset != INVALID_SELECTION_OFFSET
- && mSelectionEndOffset != INVALID_SELECTION_OFFSET
- && mSelectionEndOffset > mSelectionStartOffset;
+ return mHasSetResolveProperties && haveValidSelection();
}
/**
@@ -173,7 +189,107 @@ public abstract class ContextualSearchContext {
*/
abstract void onSelectionChanged();
- // TODO(donnd): Add a test for this class!
+ // ============================================================================================
+ // Content Analysis.
+ // ============================================================================================
+
+ /**
+ * @return Whether we have valid Surrounding text and initial Tap offset.
+ */
+ private boolean haveValidTappedText() {
+ return !TextUtils.isEmpty(mSurroundingText) && mTapStartOffset != INVALID_OFFSET
+ && mTapEndOffset != INVALID_OFFSET && mTapEndOffset <= mSurroundingText.length();
+ }
+
+ /**
+ * @return Whether we have a valid selection.
+ */
+ private boolean haveValidSelection() {
+ if (!haveValidTappedText()) return false;
+
+ return mSelectionStartOffset != INVALID_OFFSET && mSelectionEndOffset != INVALID_OFFSET
+ && mSelectionStartOffset < mSelectionEndOffset
+ && mSelectionEndOffset < mSurroundingText.length();
+ }
+
+ /**
+ * @return The tapped word, or {@code null} if the tapped word cannot be identified by the
+ * current parsing capability.
+ */
+ String getTappedWord() {
+ if (mTappedWord != null) return mTappedWord;
+
+ assert haveValidTappedText();
+ int wordStartOffset = findWordStartOffset(mSurroundingText, mTapStartOffset);
+ int wordEndOffset = findWordEndOffset(mSurroundingText, mTapEndOffset);
+ if (wordStartOffset == INVALID_OFFSET || wordEndOffset == INVALID_OFFSET) return null;
+
+ mTappedWord = mSurroundingText.substring(wordStartOffset, wordEndOffset);
+ mTappedWordStartOffset = wordStartOffset;
+ return mTappedWord;
+ }
+
+ /**
+ * @return The offset of the tap within the tapped word, or {@code -1} if the tapped word cannot
+ * be identified by the current parsing capability.
+ */
+ int getTappedWordOffset() {
+ getTappedWord();
+ if (mTappedWordStartOffset != INVALID_OFFSET && mTapStartOffset == mTapEndOffset) {
+ return mTapStartOffset - mTappedWordStartOffset;
+ }
+
+ return INVALID_OFFSET;
+ }
+
+ /**
+ * @return The start of the word that contains the given initial offset, within {@code text}.
+ */
+ private int findWordStartOffset(String text, int initial) {
+ // Scan before, aborting if we hit any CJKN letter.
+ for (int offset = initial - 1; offset >= 0; offset--) {
+ if (isIdeographicAtIndex(text, offset)) return INVALID_OFFSET;
+
+ if (isWordBreakAtIndex(text, offset)) {
+ // The start of the word is after this word break.
+ return offset + 1;
+ }
+ }
+ return INVALID_OFFSET;
+ }
+
+ /**
+ * @return The end of the word that contains the given initial offset, within {@code text}.
+ */
+ private int findWordEndOffset(String text, int initial) {
+ // Scan after, aborting if we hit any CJKN letter.
+ for (int offset = initial; offset <= text.length(); offset++) {
+ if (isIdeographicAtIndex(text, offset)) return INVALID_OFFSET;
+
+ if (isWordBreakAtIndex(text, offset)) {
+ // The end of the word is the offset of this word break.
+ return offset;
+ }
+ }
+ return INVALID_OFFSET;
+ }
+
+ /**
+ * @return Whether the character at the given index in the text is "Ideographic", which means
+ * we probably won't see reliable word breaks.
+ */
+ @SuppressLint("NewApi")
+ private boolean isIdeographicAtIndex(String text, int index) {
+ return Character.isIdeographic(text.charAt(index));
+ }
+
+ /**
+ * @return Whether the character at the given index is a word-break.
+ */
+ private boolean isWordBreakAtIndex(String text, int index) {
+ return !Character.isLetterOrDigit(text.charAt(index))
+ && text.codePointAt(index) != SOFT_HYPHEN;
+ }
// ============================================================================================
// Native callback support.

Powered by Google App Engine
This is Rietveld 408576698