Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java |
| index 8f28b28f604729818750a98d2e19cd29886257b9..c57919ecd853cc3053dbcd7d45990d04beafc51d 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java |
| @@ -5,6 +5,7 @@ |
| package org.chromium.chrome.browser.contextualsearch; |
| import android.app.Activity; |
| +import android.content.Context; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.ViewTreeObserver; |
| @@ -48,10 +49,16 @@ import org.chromium.content_public.browser.LoadUrlParams; |
| import org.chromium.content_public.browser.NavigationEntry; |
| import org.chromium.content_public.browser.WebContentsObserver; |
| import org.chromium.content_public.common.TopControlsState; |
| +import org.chromium.ui.UiUtils; |
| import org.chromium.ui.base.WindowAndroid; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| +import java.util.ArrayList; |
| +import java.util.LinkedHashSet; |
| +import java.util.List; |
| +import java.util.Locale; |
| +import java.util.Set; |
| import javax.annotation.Nullable; |
| @@ -114,6 +121,9 @@ public class ContextualSearchManager extends ContextualSearchObservable |
| private boolean mIsShowingPromo; |
| private boolean mDidLogPromoOutcome; |
| + // Cached target languages for translation; |
| + private List<String> mTargetLanguages; |
|
pedro (no code reviews)
2015/11/03 19:36:19
Nit: Should it be static?
Donn Denman
2015/11/03 21:36:37
I wondered about that too, and concluded that it d
|
| + |
| /** |
| * Whether contextual search manager is currently promoting a tab. We should be ignoring hide |
| * requests when mIsPromotingTab is set to true. |
| @@ -290,13 +300,21 @@ public class ContextualSearchManager extends ContextualSearchObservable |
| } |
| /** |
| - * Sets the selection controller for testing purposes. |
| + * @return The selection controller, for testing purposes. |
| */ |
| @VisibleForTesting |
| ContextualSearchSelectionController getSelectionController() { |
| return mSelectionController; |
| } |
| + /** |
| + * @return The current search request, or {@code null} if there is none, for testing. |
| + */ |
| + @VisibleForTesting |
| + ContextualSearchRequest getRequest() { |
| + return mSearchRequest; |
| + } |
| + |
| @VisibleForTesting |
| boolean isSearchPanelShowing() { |
| return mSearchPanel.isShowing(); |
| @@ -476,10 +494,13 @@ public class ContextualSearchManager extends ContextualSearchObservable |
| mNetworkCommunicator.startSearchTermResolutionRequest( |
| mSelectionController.getSelectedText()); |
| didRequestSurroundings = true; |
| + // Cache the target languages in case they are needed for translation. |
| + if (mPolicy.isTranslationEnabled()) getTargetLanguages(); |
| } else { |
| boolean shouldPrefetch = mPolicy.shouldPrefetchSearchResult(isTap); |
| mSearchRequest = new ContextualSearchRequest(mSelectionController.getSelectedText(), |
| null, shouldPrefetch); |
| + // TODO(donnd): figure out a way to do translation on long-press selections. |
| mDidStartLoadingResolvedSearchRequest = false; |
| mSearchPanel.displaySearchTerm(mSelectionController.getSelectedText()); |
| if (shouldPrefetch) loadSearchUrl(); |
| @@ -675,20 +696,22 @@ public class ContextualSearchManager extends ContextualSearchObservable |
| * selection should be expanded by. |
| * @param selectionEndAdjust A positive number of characters that the end of the existing |
| * selection should be expanded by. |
| + * @param contextLanguage The language of the original search term, or an empty string. |
| */ |
| @CalledByNative |
| public void onSearchTermResolutionResponse(boolean isNetworkUnavailable, int responseCode, |
| final String searchTerm, final String displayText, final String alternateTerm, |
| - boolean doPreventPreload, int selectionStartAdjust, int selectionEndAdjust) { |
| + boolean doPreventPreload, int selectionStartAdjust, int selectionEndAdjust, |
| + final String contextLanguage) { |
| mNetworkCommunicator.handleSearchTermResolutionResponse(isNetworkUnavailable, responseCode, |
| searchTerm, displayText, alternateTerm, doPreventPreload, selectionStartAdjust, |
| - selectionEndAdjust); |
| + selectionEndAdjust, contextLanguage); |
| } |
| @Override |
| public void handleSearchTermResolutionResponse(boolean isNetworkUnavailable, int responseCode, |
| String searchTerm, String displayText, String alternateTerm, boolean doPreventPreload, |
| - int selectionStartAdjust, int selectionEndAdjust) { |
| + int selectionStartAdjust, int selectionEndAdjust, String contextLanguage) { |
| if (!mSearchPanel.isShowing()) return; |
| // Show an appropriate message for what to search for. |
| @@ -721,6 +744,14 @@ public class ContextualSearchManager extends ContextualSearchObservable |
| // appear in the user's history until the user views it). See crbug.com/406446. |
| boolean shouldPreload = !doPreventPreload && mPolicy.shouldPrefetchSearchResult(true); |
| mSearchRequest = new ContextualSearchRequest(searchTerm, alternateTerm, shouldPreload); |
| + // Trigger translation, if enabled. |
| + if (!contextLanguage.isEmpty() && mPolicy.isTranslationEnabled()) { |
| + List<String> targetLanguages = getTargetLanguages(); |
| + if (mPolicy.needsTranslation(contextLanguage, targetLanguages)) { |
| + mSearchRequest.forceTranslation( |
| + contextLanguage, mPolicy.bestTargetLanguage(targetLanguages)); |
| + } |
| + } |
| mDidStartLoadingResolvedSearchRequest = false; |
| if (mSearchPanel.isContentShowing()) { |
| mSearchRequest.setNormalPriority(); |
| @@ -769,6 +800,68 @@ public class ContextualSearchManager extends ContextualSearchObservable |
| } |
| // ============================================================================================ |
| + // Translation support |
| + // ============================================================================================ |
| + |
| + /** |
| + * Gets the list of target languages for the current user, with the first |
| + * item in the list being the user's primary language. |
| + * @return The {@link List} of languages the user understands with their primary language first. |
| + */ |
| + private List<String> getTargetLanguages() { |
| + // May be cached. |
| + if (mTargetLanguages != null) return mTargetLanguages; |
| + |
| + // Using LinkedHashSet keeps the entries both unique and ordered. |
| + Set<String> uniqueLanguages = new LinkedHashSet<String>(); |
| + |
| + // The primary language always comes first. |
| + uniqueLanguages.add( |
| + trimLocaleToLanguage(nativeGetTargetLanguage(mNativeContextualSearchManagerPtr))); |
| + |
| + // Next add languages the user knows how to type. |
| + Context context = mActivity.getApplicationContext(); |
| + List<String> locales = context != null |
| + ? new ArrayList<String>(UiUtils.getIMELocales(context)) |
| + : new ArrayList<String>(); |
| + for (int i = 0; i < locales.size(); i++) { |
| + uniqueLanguages.add(trimLocaleToLanguage(locales.get(i))); |
| + } |
| + |
| + // Add the accept languages last, since they are a weaker hint than presence of a keyboard. |
| + List<String> acceptLanguages = getAcceptLanguages(); |
| + for (int i = 0; i < acceptLanguages.size(); i++) { |
| + uniqueLanguages.add(trimLocaleToLanguage(acceptLanguages.get(i))); |
| + } |
| + mTargetLanguages = new ArrayList<String>(uniqueLanguages); |
| + return mTargetLanguages; |
| + } |
| + |
| + /** |
| + * Gets the list of accept languages for this user. |
| + * @return The {@link List} of languages the user understands or does not want translated. |
| + */ |
| + private List<String> getAcceptLanguages() { |
| + String acceptLanguages = nativeGetAcceptLanguages(mNativeContextualSearchManagerPtr); |
| + List<String> result = new ArrayList<String>(); |
| + for (String language : acceptLanguages.split(",")) { |
| + result.add(language); |
| + } |
| + return result; |
| + } |
| + |
| + /** |
| + * @return The given locale as a language code. |
| + */ |
| + private String trimLocaleToLanguage(String locale) { |
| + // TODO(donnd): use getScript or getLanguageTag (both API 21), or some other standard way to |
| + // strip the country, instead of hard-coding the two character language code. |
| + // TODO(donnd): Shouldn't getLanguage() do this? |
| + String trimmedLocale = locale.substring(0, 2); |
| + return new Locale(trimmedLocale).getLanguage(); |
| + } |
| + |
| + // ============================================================================================ |
| // OverlayContentDelegate |
| // ============================================================================================ |
| @@ -1194,4 +1287,6 @@ public class ContextualSearchManager extends ContextualSearchObservable |
| private native void nativeGatherSurroundingText(long nativeContextualSearchManager, |
| String selection, boolean useResolvedSearchTerm, ContentViewCore baseContentViewCore, |
| boolean maySendBasePageUrl); |
| + private native String nativeGetTargetLanguage(long nativeContextualSearchManager); |
| + private native String nativeGetAcceptLanguages(long nativeContextualSearchManager); |
| } |