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

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java

Issue 1206673003: Merge java_staging/src into java/src. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 6 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_staging/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
deleted file mode 100644
index 65f204b1c01fcf97622292a33633b1f1ef441cc8..0000000000000000000000000000000000000000
--- a/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ /dev/null
@@ -1,2422 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.omnibox;
-
-import static org.chromium.chrome.browser.toolbar.ToolbarPhone.URL_FOCUS_CHANGE_ANIMATION_DURATION_MS;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.speech.RecognizerIntent;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.Selection;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-import android.view.ActionMode;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.view.inputmethod.BaseInputConnection;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.ListView;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.CollectionUtil;
-import org.chromium.base.CommandLine;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ContextualMenuBar;
-import org.chromium.chrome.browser.ContextualMenuBar.ActionBarDelegate;
-import org.chromium.chrome.browser.CustomSelectionActionModeCallback;
-import org.chromium.chrome.browser.Tab;
-import org.chromium.chrome.browser.WebsiteSettingsPopup;
-import org.chromium.chrome.browser.WindowDelegate;
-import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper;
-import org.chromium.chrome.browser.document.BrandColorUtils;
-import org.chromium.chrome.browser.dom_distiller.DomDistillerServiceFactory;
-import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils;
-import org.chromium.chrome.browser.ntp.NativePageFactory;
-import org.chromium.chrome.browser.ntp.NewTabPage;
-import org.chromium.chrome.browser.ntp.NewTabPage.FakeboxDelegate;
-import org.chromium.chrome.browser.ntp.NewTabPageUma;
-import org.chromium.chrome.browser.omnibox.AutocompleteController.OnSuggestionsReceivedListener;
-import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxResultItem;
-import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxSuggestionDelegate;
-import org.chromium.chrome.browser.omnibox.OmniboxSuggestion.Type;
-import org.chromium.chrome.browser.omnibox.VoiceSuggestionProvider.VoiceResult;
-import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader;
-import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.search_engines.TemplateUrlService;
-import org.chromium.chrome.browser.ssl.ConnectionSecurityLevel;
-import org.chromium.chrome.browser.tab.BackgroundContentViewHelper;
-import org.chromium.chrome.browser.tab.ChromeTab;
-import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
-import org.chromium.chrome.browser.toolbar.ToolbarPhone;
-import org.chromium.chrome.browser.util.FeatureUtilities;
-import org.chromium.chrome.browser.util.KeyNavigationUtil;
-import org.chromium.chrome.browser.util.ViewUtils;
-import org.chromium.chrome.browser.widget.TintedImageButton;
-import org.chromium.components.dom_distiller.core.DomDistillerService;
-import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
-import org.chromium.content.browser.ContentViewCore;
-import org.chromium.content.browser.accessibility.BrowserAccessibilityManager;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.ui.UiUtils;
-import org.chromium.ui.base.DeviceFormFactor;
-import org.chromium.ui.base.PageTransition;
-import org.chromium.ui.base.WindowAndroid;
-import org.chromium.ui.interpolators.BakedBezierInterpolator;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * This class represents the location bar where the user types in URLs and
- * search terms.
- */
-public class LocationBarLayout extends FrameLayout implements OnClickListener,
- OnSuggestionsReceivedListener, LocationBar, FakeboxDelegate,
- WindowAndroid.IntentCallback {
-
- // Delay triggering the omnibox results upon key press to allow the location bar to repaint
- // with the new characters.
- private static final long OMNIBOX_SUGGESTION_START_DELAY_MS = 30;
-
- private static final int OMNIBOX_CONTAINER_BACKGROUND_FADE_MS = 250;
-
- // The minimum confidence threshold that will result in navigating directly to a voice search
- // response (as opposed to treating it like a typed string in the Omnibox).
- private static final float VOICE_SEARCH_CONFIDENCE_NAVIGATE_THRESHOLD = 0.9f;
-
- private static final int CONTENT_OVERLAY_COLOR = Color.argb(166, 0, 0, 0);
- private static final int OMNIBOX_RESULTS_BG_COLOR = Color.rgb(245, 245, 246);
- private static final int OMNIBOX_INCOGNITO_RESULTS_BG_COLOR = Color.rgb(50, 50, 50);
-
- /**
- * URI schemes that ContentView can handle.
- *
- * Copied from UrlUtilities.java. UrlUtilities uses a URI to check for schemes, which
- * is more strict than Uri and causes the path stripping to fail.
- *
- * The following additions have been made: "chrome", "ftp".
- */
- private static final HashSet<String> ACCEPTED_SCHEMES = CollectionUtil.newHashSet(
- "about", "data", "file", "ftp", "http", "https", "inline", "javascript", "chrome");
- private static final HashSet<String> UNSUPPORTED_SCHEMES_TO_SPLIT =
- CollectionUtil.newHashSet("file", "javascript", "data");
-
- protected ImageView mNavigationButton;
- protected ImageButton mSecurityButton;
- protected TintedImageButton mDeleteButton;
- protected TintedImageButton mMicButton;
- protected UrlBar mUrlBar;
- protected UrlContainer mUrlContainer;
- private ContextualMenuBar mContextualMenuBar = null;
-
- private AutocompleteController mAutocomplete;
-
- private ToolbarDataProvider mToolbarDataProvider;
- private UrlFocusChangeListener mUrlFocusChangeListener;
-
- private boolean mNativeInitialized;
-
- private final List<Runnable> mDeferredNativeRunnables = new ArrayList<Runnable>();
-
- // The type of the navigation button currently showing.
- private NavigationButtonType mNavigationButtonType;
-
- // The type of the security icon currently active.
- private int mSecurityIconType;
-
- private final OmniboxResultsAdapter mSuggestionListAdapter;
- private OmniboxSuggestionsList mSuggestionList;
-
- private final List<OmniboxResultItem> mSuggestionItems;
-
- /**
- * The text shown in the URL bar (user text + inline autocomplete) after the most recent set of
- * omnibox suggestions was received. When the user presses enter in the omnibox, this value is
- * compared to the URL bar text to determine whether the first suggestion is still valid.
- */
- private String mUrlTextAfterSuggestionsReceived;
-
- // Set to true when the URL bar text is modified programmatically. Initially set
- // to true until the old state has been loaded.
- private boolean mIgnoreURLBarModification = true;
- private boolean mIgnoreOmniboxItemSelection = true;
-
- private boolean mLastUrlEditWasDelete = false;
-
- // True if we are showing the search query instead of the url.
- private boolean mQueryInTheOmnibox = false;
-
- private String mOriginalUrl = "";
-
- private WindowAndroid mWindowAndroid;
- private WindowDelegate mWindowDelegate;
-
- private Runnable mRequestSuggestions;
-
- private ViewGroup mOmniboxResultsContainer;
- private ObjectAnimator mFadeInOmniboxBackgroundAnimator;
- private ObjectAnimator mFadeOutOmniboxBackgroundAnimator;
- private Animator mOmniboxBackgroundAnimator;
-
- private boolean mSuggestionsShown;
- private boolean mUrlHasFocus;
- private boolean mUrlFocusedFromFakebox;
- private boolean mHasRecordedUrlFocusSource;
-
- // Set to true when the user has started typing new input in the omnibox, set to false
- // when the omnibox loses focus or becomes empty.
- private boolean mHasStartedNewOmniboxEditSession;
- // The timestamp (using SystemClock.elapsedRealtime()) at the point when the user started
- // modifying the omnibox with new input.
- private long mNewOmniboxEditSessionTimestamp = -1;
-
- private boolean mSecurityButtonShown;
-
- private AnimatorSet mLocationBarIconActiveAnimator;
- private AnimatorSet mSecurityButtonShowAnimator;
- private AnimatorSet mNavigationIconShowAnimator;
-
- private TextWatcher mTextWatcher;
-
- private OmniboxPrerender mOmniboxPrerender;
-
- private View mFocusedTabView;
- private int mFocusedTabImportantForAccessibilityState;
- private BrowserAccessibilityManager mFocusedTabAccessibilityManager;
-
- // True if we are showing original url for preview page. This is will be true when there is a
- // background page loaded in background content view.
- private boolean mShowingOriginalUrlForPreview;
-
- private boolean mSuggestionModalShown;
- private boolean mUseDarkColors;
-
- // True if the user has just selected a suggestion from the suggestion list. This suppresses
- // the recording of the dismissal of the suggestion list. (The list is only considered to have
- // been dismissed if the user didn't choose one of the suggestions shown.) This signal is used
- // instead of a parameter to hideSuggestions because that method is often called from multiple
- // code paths in a not necessarily obvious or even deterministic order.
- private boolean mSuggestionSelectionInProgress;
-
- private CustomSelectionActionModeCallback mDefaultActionModeCallbackForTextEdit;
-
- private Runnable mShowSuggestions;
-
- /**
- * Listener for receiving the messages related with interacting with the omnibox during startup.
- */
- public interface OmniboxLivenessListener {
- /**
- * Called after the first draw when the omnibox can receive touch events.
- */
- void onOmniboxInteractive();
-
- /**
- * Called when the native libraries are loaded and listeners with native components
- * have been initialized.
- */
- void onOmniboxFullyFunctional();
-
- /**
- * Called when the omnibox is focused.
- */
- void onOmniboxFocused();
- }
-
- /**
- * Class to handle text changes in the URL bar, ensuring that the appropriate
- * buttons are displayed as the text changes, and requesting suggestions.
- */
- private final class UrlBarTextWatcher implements TextWatcher {
- @Override
- public void afterTextChanged(final Editable editableText) {
- updateDeleteButtonVisibility();
- updateNavigationButton();
-
- if (mIgnoreURLBarModification) return;
-
- if (!mHasStartedNewOmniboxEditSession && mNativeInitialized) {
- RecordUserAction.record("MobileFirstEditInOmnibox");
- mAutocomplete.resetSession();
- mHasStartedNewOmniboxEditSession = true;
- mNewOmniboxEditSessionTimestamp = SystemClock.elapsedRealtime();
- }
-
- if (!isInTouchMode() && mSuggestionList != null) {
- mSuggestionList.setSelection(0);
- }
-
- stopAutocomplete(false);
- if (TextUtils.isEmpty(mUrlBar.getTextWithoutAutocomplete())) {
- hideSuggestions();
- startZeroSuggest();
- } else {
- assert mRequestSuggestions == null : "Multiple omnibox requests in flight.";
- mRequestSuggestions = new Runnable() {
- @Override
- public void run() {
- String textWithoutAutocomplete = mUrlBar.getTextWithoutAutocomplete();
-
- boolean preventAutocomplete = !shouldAutocomplete()
- || (editableText != null && Selection.getSelectionEnd(editableText)
- != editableText.length());
- mRequestSuggestions = null;
- if (getCurrentTab() == null) return;
- mAutocomplete.start(
- getCurrentTab().getProfile(),
- getCurrentTab().getUrl(),
- textWithoutAutocomplete, preventAutocomplete);
- }
- };
- if (mNativeInitialized) {
- postDelayed(mRequestSuggestions, OMNIBOX_SUGGESTION_START_DELAY_MS);
- } else {
- mDeferredNativeRunnables.add(mRequestSuggestions);
- }
- }
-
- // Occasionally, was seeing the selection in the URL not being cleared during
- // very rapid editing. This is here to hopefully force a selection reset during
- // deletes.
- if (mLastUrlEditWasDelete) mUrlBar.setSelection(mUrlBar.getSelectionStart());
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- cancelPendingAutocompleteStart();
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- // We need to determine whether the text change was triggered by a delete (so we
- // don't autocomplete of the entered text in that case). With soft-keyboard, there
- // is no way to know that the delete button was pressed, so we track text removal
- // changes.
- mLastUrlEditWasDelete = (count == 0);
- }
- }
-
- /**
- * Class to handle input from a hardware keyboard when the focus is on the URL bar. In
- * particular, handle navigating the suggestions list from the keyboard.
- */
- private final class UrlBarKeyListener implements OnKeyListener {
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (KeyNavigationUtil.isGoDown(event)
- && mSuggestionList != null
- && mSuggestionList.isShown()) {
- int suggestionCount = mSuggestionListAdapter.getCount();
- if (mSuggestionList.getSelectedItemPosition() < suggestionCount - 1) {
- if (suggestionCount > 0) mIgnoreOmniboxItemSelection = false;
- } else {
- // Do not pass down events when the last item is already selected as it will
- // dismiss the suggestion list.
- return true;
- }
-
- if (mSuggestionList.getSelectedItemPosition()
- == ListView.INVALID_POSITION) {
- // When clearing the selection after a text change, state is not reset
- // correctly so hitting down again will cause it to start from the previous
- // selection point. We still have to send the key down event to let the list
- // view items take focus, but then we select the first item explicitly.
- boolean result = mSuggestionList.onKeyDown(keyCode, event);
- mSuggestionList.setSelection(0);
- return result;
- } else {
- return mSuggestionList.onKeyDown(keyCode, event);
- }
- } else if (KeyNavigationUtil.isGoUp(event)
- && mSuggestionList != null
- && mSuggestionList.isShown()) {
- if (mSuggestionList.getSelectedItemPosition() != 0
- && mSuggestionListAdapter.getCount() > 0) {
- mIgnoreOmniboxItemSelection = false;
- }
- return mSuggestionList.onKeyDown(keyCode, event);
- } else if (KeyNavigationUtil.isGoRight(event)
- && mSuggestionList != null
- && mSuggestionList.isShown()
- && mSuggestionList.getSelectedItemPosition()
- != ListView.INVALID_POSITION) {
- OmniboxResultItem selectedItem =
- (OmniboxResultItem) mSuggestionListAdapter.getItem(
- mSuggestionList.getSelectedItemPosition());
- // Set the UrlBar text to empty, so that it will trigger a text change when we
- // set the text to the suggestion again.
- setUrlBarText(null, null, "");
- mUrlBar.setText(selectedItem.getSuggestion().getFillIntoEdit());
- mSuggestionList.setSelection(0);
- mUrlBar.setSelection(mUrlBar.getText().length());
- return true;
- } else if (KeyNavigationUtil.isEnter(event)
- && LocationBarLayout.this.getVisibility() == VISIBLE) {
- UiUtils.hideKeyboard(mUrlBar);
- mSuggestionSelectionInProgress = true;
- final String urlText = mUrlBar.getQueryText();
- if (mNativeInitialized) {
- findMatchAndLoadUrl(urlText);
- } else {
- mDeferredNativeRunnables.add(new Runnable() {
- @Override
- public void run() {
- findMatchAndLoadUrl(urlText);
- }
- });
- }
- return true;
- }
-
- return false;
- }
-
- private void findMatchAndLoadUrl(String urlText) {
- int suggestionMatchPosition;
- OmniboxSuggestion suggestionMatch;
-
- if (mSuggestionList != null
- && mSuggestionList.isShown()
- && mSuggestionList.getSelectedItemPosition()
- != ListView.INVALID_POSITION) {
- // Bluetooth keyboard case: the user highlighted a suggestion with the arrow
- // keys, then pressed enter.
- suggestionMatchPosition = mSuggestionList.getSelectedItemPosition();
- OmniboxResultItem selectedItem =
- (OmniboxResultItem) mSuggestionListAdapter.getItem(suggestionMatchPosition);
- suggestionMatch = selectedItem.getSuggestion();
- } else if (!mSuggestionItems.isEmpty()
- && urlText.equals(mUrlTextAfterSuggestionsReceived)) {
- // Common case: the user typed something, received suggestions, then pressed enter.
- suggestionMatch = mSuggestionItems.get(0).getSuggestion();
- suggestionMatchPosition = 0;
- } else {
- // Less common case: there are no valid omnibox suggestions. This can happen if the
- // user tapped the URL bar to dismiss the suggestions, then pressed enter. This can
- // also happen if the user presses enter before any suggestions have been received
- // from the autocomplete controller.
- suggestionMatch = mAutocomplete.classify(urlText);
- suggestionMatchPosition = 0;
-
- // If urlText couldn't be classified, bail.
- if (suggestionMatch == null) return;
- }
-
- String suggestionMatchUrl = updateSuggestionUrlIfNeeded(suggestionMatch,
- suggestionMatchPosition);
-
- // It's important to use the page transition from the suggestion or we might end
- // up saving generated URLs as typed URLs, which would then pollute the subsequent
- // omnibox results.
- loadUrlFromOmniboxMatch(suggestionMatchUrl, suggestionMatch.getTransition(),
- suggestionMatchPosition, suggestionMatch.getType());
- }
- }
-
- /**
- * Specifies the types of buttons shown to signify different types of navigation elements.
- */
- protected enum NavigationButtonType {
- PAGE,
- MAGNIFIER,
- EMPTY,
- }
-
- /**
- * @param outRect Populated with a {@link Rect} that represents the {@link Tab} specific content
- * of this {@link LocationBar}.
- */
- public void getContentRect(Rect outRect) {
- outRect.set(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(),
- getHeight() - getPaddingBottom());
- }
-
- /**
- * A widget for showing a list of omnibox suggestions.
- */
- @VisibleForTesting
- public class OmniboxSuggestionsList extends ListView {
- private final int mSuggestionHeight;
- private final int mSuggestionAnswerHeight;
- private final View mAnchorView;
-
- private final int[] mTempPosition = new int[2];
- private final Rect mTempRect = new Rect();
-
- private final int mBackgroundVerticalPadding;
-
- private float mMaxRequiredWidth;
- private float mMaxMatchContentsWidth;
-
- /**
- * Constructs a new list designed for containing omnibox suggestions.
- * @param context Context used for contained views.
- */
- public OmniboxSuggestionsList(Context context) {
- super(context, null, android.R.attr.dropDownListViewStyle);
- setDivider(null);
- setFocusable(true);
- setFocusableInTouchMode(true);
-
- mSuggestionHeight = context.getResources().getDimensionPixelOffset(
- R.dimen.omnibox_suggestion_height);
- mSuggestionAnswerHeight = context.getResources().getDimensionPixelOffset(
- R.dimen.omnibox_suggestion_answer_height);
-
- int paddingTop = context.getResources().getDimensionPixelOffset(
- R.dimen.omnibox_suggestion_list_padding_top);
- int paddingBottom = context.getResources().getDimensionPixelOffset(
- R.dimen.omnibox_suggestion_list_padding_bottom);
- ApiCompatibilityUtils.setPaddingRelative(this, 0, paddingTop, 0, paddingBottom);
-
- Drawable background = getSuggestionPopupBackground();
- setBackground(background);
- background.getPadding(mTempRect);
-
- mBackgroundVerticalPadding =
- mTempRect.top + mTempRect.bottom + getPaddingTop() + getPaddingBottom();
-
- mAnchorView = LocationBarLayout.this.getRootView().findViewById(R.id.toolbar);
- }
-
- private void show() {
- updateLayoutParams();
- if (getVisibility() != VISIBLE) {
- mIgnoreOmniboxItemSelection = true; // Reset to default value.
- setVisibility(VISIBLE);
- if (getSelectedItemPosition() != 0) setSelection(0);
- }
- updateSuggestionsLayoutDirection(mUrlBar.getUrlDirection());
- }
-
- /**
- * Invalidates all of the suggestion views in the list. Only applicable when this
- * is visible.
- */
- public void invalidateSuggestionViews() {
- if (!isShown()) return;
- ListView suggestionsList = mSuggestionList;
- for (int i = 0; i < suggestionsList.getChildCount(); i++) {
- if (suggestionsList.getChildAt(i) instanceof SuggestionView) {
- suggestionsList.getChildAt(i).postInvalidateOnAnimation();
- }
- }
- }
-
- /**
- * Updates the maximum widths required to render the suggestions.
- * This is needed for infinite suggestions where we try to vertically align the leading
- * ellipsis.
- */
- public void resetMaxTextWidths() {
- mMaxRequiredWidth = 0;
- mMaxMatchContentsWidth = 0;
- }
-
- /**
- * Updates the max text width values for the suggestions.
- * @param requiredWidth a new required width.
- * @param matchContentsWidth a new match contents width.
- */
- public void updateMaxTextWidths(float requiredWidth, float matchContentsWidth) {
- mMaxRequiredWidth = Math.max(mMaxRequiredWidth, requiredWidth);
- mMaxMatchContentsWidth = Math.max(mMaxMatchContentsWidth, matchContentsWidth);
- }
-
- /**
- * @return max required width for the suggestions.
- */
- public float getMaxRequiredWidth() {
- return mMaxRequiredWidth;
- }
-
- /**
- * @return max match contents width for the suggestions.
- */
- public float getMaxMatchContentsWidth() {
- return mMaxMatchContentsWidth;
- }
-
- private void updateLayoutParams() {
- boolean updateLayout = false;
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams();
- if (layoutParams == null) {
- layoutParams = new FrameLayout.LayoutParams(0, 0);
- setLayoutParams(layoutParams);
- }
-
- // Compare the relative positions of the anchor view to the list parent view to
- // determine the offset to apply to the suggestions list. By using layout positioning,
- // this avoids issues where getLocationInWindow can be inaccurate on certain devices.
- View contentView =
- LocationBarLayout.this.getRootView().findViewById(android.R.id.content);
- ViewUtils.getRelativeLayoutPosition(contentView, mAnchorView, mTempPosition);
- int anchorX = mTempPosition[0];
- int anchorY = mTempPosition[1];
-
- ViewUtils.getRelativeLayoutPosition(contentView, (View) getParent(), mTempPosition);
- int parentY = mTempPosition[1];
-
- int anchorBottomRelativeToContent = anchorY + mAnchorView.getMeasuredHeight();
- int desiredTopMargin = anchorBottomRelativeToContent - parentY;
- if (layoutParams.topMargin != desiredTopMargin) {
- layoutParams.topMargin = desiredTopMargin;
- updateLayout = true;
- }
-
- int contentLeft = contentView.getLeft();
- int anchorLeftRelativeToContent = anchorX - contentLeft;
- if (layoutParams.leftMargin != anchorLeftRelativeToContent) {
- layoutParams.leftMargin = anchorLeftRelativeToContent;
- updateLayout = true;
- }
-
- getWindowDelegate().getWindowVisibleDisplayFrame(mTempRect);
- int decorHeight = getWindowDelegate().getDecorViewHeight();
- int availableViewportHeight = Math.min(mTempRect.height(), decorHeight);
- int availableListHeight = availableViewportHeight - anchorBottomRelativeToContent;
- int desiredHeight = Math.min(availableListHeight, getIdealHeight());
- if (layoutParams.height != desiredHeight) {
- layoutParams.height = desiredHeight;
- updateLayout = true;
- }
-
- int desiredWidth = getDesiredWidth();
- if (layoutParams.width != desiredWidth) {
- layoutParams.width = desiredWidth;
- updateLayout = true;
- }
-
- if (updateLayout) requestLayout();
- }
-
- private int getIdealHeight() {
- int idealListSize = mBackgroundVerticalPadding;
- for (int i = 0; i < mSuggestionItems.size(); i++) {
- OmniboxResultItem item = mSuggestionItems.get(i);
- if (!TextUtils.isEmpty(item.getSuggestion().getAnswerContents())) {
- idealListSize += mSuggestionAnswerHeight;
- } else {
- idealListSize += mSuggestionHeight;
- }
- }
- return idealListSize;
- }
-
- private int getDesiredWidth() {
- return mAnchorView.getWidth();
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
- if (!hasWindowFocus && !mSuggestionModalShown) hideSuggestions();
- }
-
- @Override
- protected void layoutChildren() {
- super.layoutChildren();
- // In ICS, the selected view is not marked as selected despite calling setSelection(0),
- // so we bootstrap this after the children have been laid out.
- if (!isInTouchMode() && getSelectedView() != null) {
- getSelectedView().setSelected(true);
- }
- }
- }
-
- public LocationBarLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- LayoutInflater.from(context).inflate(R.layout.location_bar, this, true);
- mNavigationButton = (ImageView) findViewById(R.id.navigation_button);
- assert mNavigationButton != null : "Missing navigation type view.";
- mNavigationButtonType = DeviceFormFactor.isTablet(context)
- ? NavigationButtonType.PAGE : NavigationButtonType.EMPTY;
-
- mSecurityButton = (ImageButton) findViewById(R.id.security_button);
- mSecurityIconType = ConnectionSecurityLevel.NONE;
-
- mDeleteButton = (TintedImageButton) findViewById(R.id.delete_button);
-
- mUrlBar = (UrlBar) findViewById(R.id.url_bar);
- // The HTC Sense IME will attempt to autocomplete words in the Omnibox when Prediction is
- // enabled. We want to disable this feature and rely on the Omnibox's implementation.
- // Their IME does not respect ~TYPE_TEXT_FLAG_AUTO_COMPLETE nor any of the other InputType
- // options I tried, but setting the filter variation prevents it. Sadly, it also removes
- // the .com button, but the prediction was buggy as it would autocomplete words even when
- // typing at the beginning of the omnibox text when other content was present (messing up
- // what was previously there). See bug: http://b/issue?id=6200071
- String defaultIme = Settings.Secure.getString(getContext().getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD);
- if (defaultIme != null && defaultIme.contains("com.htc.android.htcime")) {
- mUrlBar.setInputType(mUrlBar.getInputType() | InputType.TYPE_TEXT_VARIATION_FILTER);
- }
- mUrlBar.setDelegate(this);
-
- mUrlContainer = (UrlContainer) findViewById(R.id.url_container);
-
- mSuggestionItems = new ArrayList<OmniboxResultItem>();
- mSuggestionListAdapter = new OmniboxResultsAdapter(getContext(), this, mSuggestionItems);
-
- mMicButton = (TintedImageButton) findViewById(R.id.mic_button);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mUrlBar.setCursorVisible(false);
- mNavigationButton.setVisibility(VISIBLE);
- mSecurityButton.setVisibility(INVISIBLE);
-
- setLayoutTransition(null);
-
- AnimatorListenerAdapter iconChangeAnimatorListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (animation == mSecurityButtonShowAnimator) {
- mNavigationButton.setVisibility(INVISIBLE);
- } else if (animation == mNavigationIconShowAnimator) {
- mSecurityButton.setVisibility(INVISIBLE);
- }
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- if (animation == mSecurityButtonShowAnimator) {
- mSecurityButton.setVisibility(VISIBLE);
- } else if (animation == mNavigationIconShowAnimator) {
- mNavigationButton.setVisibility(VISIBLE);
- }
- }
- };
-
- mSecurityButtonShowAnimator = new AnimatorSet();
- mSecurityButtonShowAnimator.playTogether(
- ObjectAnimator.ofFloat(mNavigationButton, ALPHA, 0),
- ObjectAnimator.ofFloat(mSecurityButton, ALPHA, 1));
- mSecurityButtonShowAnimator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS);
- mSecurityButtonShowAnimator.addListener(iconChangeAnimatorListener);
-
- mNavigationIconShowAnimator = new AnimatorSet();
- mNavigationIconShowAnimator.playTogether(
- ObjectAnimator.ofFloat(mNavigationButton, ALPHA, 1),
- ObjectAnimator.ofFloat(mSecurityButton, ALPHA, 0));
- mNavigationIconShowAnimator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS);
- mNavigationIconShowAnimator.addListener(iconChangeAnimatorListener);
-
- mUrlBar.setOnKeyListener(new UrlBarKeyListener());
-
- mTextWatcher = new UrlBarTextWatcher();
- mUrlBar.setLocationBarTextWatcher(mTextWatcher);
-
- // mLocationBar's direction is tied to this UrlBar's text direction. Icons inside the
- // location bar, e.g. lock, refresh, X, should be reversed if UrlBar's text is RTL.
- mUrlBar.setUrlDirectionListener(new UrlBar.UrlDirectionListener() {
- @Override
- public void onUrlDirectionChanged(int layoutDirection) {
- ApiCompatibilityUtils.setLayoutDirection(LocationBarLayout.this, layoutDirection);
- updateSuggestionsLayoutDirection(layoutDirection);
- }
- });
-
- mUrlBar.setSelectAllOnFocus(true);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- updateLayoutParams();
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- private void updateSuggestionsLayoutDirection(int layoutDirection) {
- if (mSuggestionList != null && mSuggestionList.isShown()) {
- ListView listView = mSuggestionList;
- ApiCompatibilityUtils.setLayoutDirection(listView, layoutDirection);
- for (int i = 0; i < listView.getChildCount(); i++) {
- ApiCompatibilityUtils.setLayoutDirection(listView.getChildAt(i),
- layoutDirection);
- }
- }
- }
-
- @Override
- public void initializeControls(WindowDelegate windowDelegate,
- ActionBarDelegate actionBarDelegate, WindowAndroid windowAndroid) {
- mWindowDelegate = windowDelegate;
-
- mContextualMenuBar = new ContextualMenuBar(getContext(), actionBarDelegate);
- mContextualMenuBar.setCustomSelectionActionModeCallback(
- new CustomSelectionActionModeCallback() {
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- boolean retVal = super.onCreateActionMode(mode, menu);
- mode.getMenuInflater().inflate(R.menu.textselectionmenu, menu);
- return retVal;
- }
-
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- if (item.getItemId() == R.id.copy_url) {
- ClipboardManager clipboard =
- (ClipboardManager) getContext().getSystemService(
- Context.CLIPBOARD_SERVICE);
- ClipData clip = ClipData.newPlainText("url", mOriginalUrl);
- clipboard.setPrimaryClip(clip);
- mode.finish();
- return true;
- } else {
- return super.onActionItemClicked(mode, item);
- }
- }
- });
-
- mWindowAndroid = windowAndroid;
- mMicButton.setOnClickListener(this);
- }
-
- /**
- * @return The WindowDelegate for the LocationBar. This should be used for all Window related
- * state queries.
- */
- protected WindowDelegate getWindowDelegate() {
- return mWindowDelegate;
- }
-
- /**
- * Handles native dependent initialization for this class.
- */
- @Override
- public void onNativeLibraryReady() {
- mNativeInitialized = true;
-
- mSecurityButton.setOnClickListener(this);
- mNavigationButton.setOnClickListener(this);
- updateMicButtonState();
- mDeleteButton.setOnClickListener(this);
-
- mAutocomplete = new AutocompleteController(this);
-
- mOmniboxPrerender = new OmniboxPrerender();
-
- for (Runnable deferredRunnable : mDeferredNativeRunnables) {
- post(deferredRunnable);
- }
- mDeferredNativeRunnables.clear();
-
- mUrlBar.onOmniboxFullyFunctional();
-
- updateCustomSelectionActionModeCallback();
- updateVisualsForState();
- }
-
- /**
- * @return Whether or not to animate icon changes.
- */
- protected boolean shouldAnimateIconChanges() {
- return mUrlHasFocus;
- }
-
- /**
- * Sets the autocomplete controller for the location bar.
- *
- * @param controller The controller that will handle autocomplete/omnibox suggestions.
- * @note Only used for testing.
- */
- @VisibleForTesting
- public void setAutocompleteController(AutocompleteController controller) {
- mAutocomplete = controller;
- }
-
- /**
- * Updates the profile used for generating autocomplete suggestions.
- * @param profile The profile to be used.
- */
- @Override
- public void setAutocompleteProfile(Profile profile) {
- // This will only be called once at least one tab exists, and the tab model is told to
- // update its state. During Chrome initialization the tab model update happens after the
- // call to onNativeLibraryReady, so this assert will not fire.
- assert mNativeInitialized :
- "Setting Autocomplete Profile before native side initialized";
- mAutocomplete.setProfile(profile);
- mOmniboxPrerender.initializeForProfile(profile);
- }
-
- private void changeLocationBarIcon(boolean showSecurityButton) {
- if (mLocationBarIconActiveAnimator != null && mLocationBarIconActiveAnimator.isRunning()) {
- mLocationBarIconActiveAnimator.cancel();
- }
- View viewToBeShown = showSecurityButton ? mSecurityButton : mNavigationButton;
- if (viewToBeShown.getVisibility() == VISIBLE && viewToBeShown.getAlpha() == 1) {
- return;
- }
- if (showSecurityButton) {
- mLocationBarIconActiveAnimator = mSecurityButtonShowAnimator;
- } else {
- mLocationBarIconActiveAnimator = mNavigationIconShowAnimator;
- }
- if (shouldAnimateIconChanges()) {
- mLocationBarIconActiveAnimator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS);
- } else {
- mLocationBarIconActiveAnimator.setDuration(0);
- }
- mLocationBarIconActiveAnimator.start();
- }
-
- @Override
- public void onUrlPreFocusChanged(boolean gainFocus) {
- if (mToolbarDataProvider == null || mToolbarDataProvider.getTab() == null) return;
-
- if (!mQueryInTheOmnibox
- && FeatureUtilities.isDocumentMode(getContext())
- && !TextUtils.isEmpty(mUrlBar.getText())) {
- mUrlBar.setUrl(mToolbarDataProvider.getTab().getUrl(), null);
- }
- }
-
- @Override
- public void setUrlBarFocus(boolean shouldBeFocused) {
- if (shouldBeFocused) {
- mUrlBar.requestFocus();
- } else {
- mUrlBar.clearFocus();
- }
- }
-
- @Override
- public long getFirstUrlBarFocusTime() {
- return mUrlBar.getFirstFocusTime();
- }
-
- /**
- * @return Whether the URL focus change is taking place, e.g. a focus animation is running on
- * a phone device.
- */
- protected boolean isUrlFocusChangeInProgress() {
- return false;
- }
-
- /**
- * Triggered when the URL input field has gained or lost focus.
- * @param hasFocus Whether the URL field has gained focus.
- */
- public void onUrlFocusChange(boolean hasFocus) {
- mUrlHasFocus = hasFocus;
- updateFocusSource(hasFocus);
- updateDeleteButtonVisibility();
- Tab currentTab = getCurrentTab();
- if (hasFocus) {
- mUrlBar.deEmphasizeUrl();
- } else {
- hideSuggestions();
-
- // Focus change caused by a close-tab may result in an invalid current tab.
- if (currentTab != null) {
- setUrlToPageUrl();
- emphasizeUrl();
- }
- }
-
- if (getToolbarDataProvider().isUsingBrandColor()) {
- updateVisualsForState();
- if (mUrlHasFocus) mUrlBar.selectAll();
- }
-
- if (mUrlFocusChangeListener != null) mUrlFocusChangeListener.onUrlFocusChange(hasFocus);
- changeLocationBarIcon(
- (!DeviceFormFactor.isTablet(getContext()) || !hasFocus) && isSecurityButtonShown());
- mUrlBar.setCursorVisible(hasFocus);
- if (mQueryInTheOmnibox) mUrlBar.setSelection(mUrlBar.getSelectionEnd());
-
- updateOmniboxResultsContainer();
- if (hasFocus) updateOmniboxResultsContainerBackground(true);
-
- if (hasFocus && currentTab != null && !currentTab.isIncognito()) {
- if (mNativeInitialized
- && TemplateUrlService.getInstance().isDefaultSearchEngineGoogle()) {
- GeolocationHeader.primeLocationForGeoHeader(getContext());
- } else {
- mDeferredNativeRunnables.add(new Runnable() {
- @Override
- public void run() {
- if (TemplateUrlService.getInstance().isDefaultSearchEngineGoogle()) {
- GeolocationHeader.primeLocationForGeoHeader(getContext());
- }
- }
- });
- }
- }
-
- if (mNativeInitialized) {
- startZeroSuggest();
- } else {
- mDeferredNativeRunnables.add(new Runnable() {
- @Override
- public void run() {
- if (TextUtils.isEmpty(mUrlBar.getQueryText())) {
- startZeroSuggest();
- }
- }
- });
- }
-
- // Add and remove text watcher from the URL bar with focus, so that it's
- // not called when we modify the displayed information on focus.
- if (hasFocus) {
- mUrlBar.addTextChangedListener(mTextWatcher);
- } else {
- mUrlBar.removeTextChangedListener(mTextWatcher);
- }
-
- if (!hasFocus) {
- mHasStartedNewOmniboxEditSession = false;
- mNewOmniboxEditSessionTimestamp = -1;
- }
- }
-
- /**
- * Make a zero suggest request if native is loaded, the URL bar has focus, and the
- * current tab is not incognito.
- */
- private void startZeroSuggest() {
- // Reset "edited" state in the omnibox if zero suggest is triggered -- new edits
- // now count as a new session.
- mHasStartedNewOmniboxEditSession = false;
- mNewOmniboxEditSessionTimestamp = -1;
- Tab currentTab = getCurrentTab();
- if (mNativeInitialized
- && mUrlHasFocus
- && currentTab != null
- && !currentTab.isIncognito()) {
- mAutocomplete.startZeroSuggest(currentTab.getProfile(), mUrlBar.getQueryText(),
- currentTab.getUrl(), mQueryInTheOmnibox, mUrlFocusedFromFakebox);
- }
- }
-
- @Override
- public void setDefaultTextEditActionModeCallback(CustomSelectionActionModeCallback callback) {
- mDefaultActionModeCallbackForTextEdit = callback;
- }
-
- /**
- * If query in the omnibox, sets UrlBar's ActionModeCallback to show copy url button. Else,
- * it is set to the default one.
- */
- private void updateCustomSelectionActionModeCallback() {
- if (mQueryInTheOmnibox) {
- mUrlBar.setCustomSelectionActionModeCallback(
- mContextualMenuBar.getCustomSelectionActionModeCallback());
- } else {
- mUrlBar.setCustomSelectionActionModeCallback(mDefaultActionModeCallbackForTextEdit);
- }
- }
-
- @Override
- public void requestUrlFocusFromFakebox(String pastedText) {
- mUrlFocusedFromFakebox = true;
- mUrlBar.requestFocus();
-
- if (pastedText != null) {
- // This must be happen after requestUrlFocus(), which changes the selection.
- mUrlBar.setUrl(pastedText, null);
- mUrlBar.setSelection(mUrlBar.getText().length());
- }
- }
-
- /**
- * Sets the toolbar that owns this LocationBar.
- */
- @Override
- public void setToolbarDataProvider(ToolbarDataProvider toolbarDataProvider) {
- mToolbarDataProvider = toolbarDataProvider;
-
- mUrlBar.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, final boolean hasFocus) {
- onUrlFocusChange(hasFocus);
- }
- });
- }
-
- @Override
- public void setMenuButtonHelper(AppMenuButtonHelper helper) { }
-
- @Override
- public View getMenuAnchor() {
- return null;
- }
-
- /**
- * Sets the URL focus change listner that will be notified when the URL gains or loses focus.
- * @param listener The listener to be registered.
- */
- @Override
- public void setUrlFocusChangeListener(UrlFocusChangeListener listener) {
- mUrlFocusChangeListener = listener;
- }
-
- /**
- * @return The toolbar data provider.
- */
- @VisibleForTesting
- protected ToolbarDataProvider getToolbarDataProvider() {
- return mToolbarDataProvider;
- }
-
- private static NavigationButtonType suggestionTypeToNavigationButtonType(
- OmniboxSuggestion.Type suggestionType) {
- switch (suggestionType) {
- case NAVSUGGEST:
- case HISTORY_URL:
- case URL_WHAT_YOU_TYPED:
- case HISTORY_TITLE:
- case HISTORY_BODY:
- case HISTORY_KEYWORD:
- return NavigationButtonType.PAGE;
- case SEARCH_WHAT_YOU_TYPED:
- case SEARCH_HISTORY:
- case SEARCH_SUGGEST:
- case SEARCH_SUGGEST_ENTITY:
- case SEARCH_SUGGEST_TAIL:
- case SEARCH_SUGGEST_PERSONALIZED:
- case SEARCH_SUGGEST_PROFILE:
- case VOICE_SUGGEST:
- case SEARCH_OTHER_ENGINE:
- case OPEN_HISTORY_PAGE:
- return NavigationButtonType.MAGNIFIER;
- default:
- assert false;
- return NavigationButtonType.MAGNIFIER;
- }
- }
-
- // Updates the navigation button based on the URL string
- private void updateNavigationButton() {
- boolean isTablet = DeviceFormFactor.isTablet(getContext());
- NavigationButtonType type = NavigationButtonType.EMPTY;
- if (isTablet && !mSuggestionItems.isEmpty()) {
- // If there are suggestions showing, show the icon for the default suggestion.
- type = suggestionTypeToNavigationButtonType(
- mSuggestionItems.get(0).getSuggestion().getType());
- } else if (mQueryInTheOmnibox) {
- type = NavigationButtonType.MAGNIFIER;
- } else if (isTablet) {
- type = NavigationButtonType.PAGE;
- }
-
- if (type != mNavigationButtonType) setNavigationButtonType(type);
- }
-
- /**
- * @return Whether the query is shown in the omnibox instead of the url.
- */
- public boolean showingQueryInTheOmnibox() {
- return mQueryInTheOmnibox;
- }
-
- /**
- * @return Whether original url is shown for preview page.
- */
- @Override
- public boolean showingOriginalUrlForPreview() {
- return mShowingOriginalUrlForPreview;
- }
-
- private int getSecurityLevel() {
- if (getCurrentTab() == null) return ConnectionSecurityLevel.NONE;
- return getCurrentTab().getSecurityLevel();
- }
-
- /**
- * Determines the icon that should be displayed for the current security level.
- * @param securityLevel The security level for which the resource will be returned.
- * @param usingLightTheme Whether light themed security assets should be used.
- * @return The resource ID of the icon that should be displayed, 0 if no icon should show.
- */
- public static int getSecurityIconResource(int securityLevel, boolean usingLightTheme) {
- switch (securityLevel) {
- case ConnectionSecurityLevel.NONE:
- return 0;
- case ConnectionSecurityLevel.SECURITY_WARNING:
- return R.drawable.omnibox_https_warning;
- case ConnectionSecurityLevel.SECURITY_ERROR:
- return R.drawable.omnibox_https_invalid;
- case ConnectionSecurityLevel.SECURE:
- case ConnectionSecurityLevel.EV_SECURE:
- return usingLightTheme
- ? R.drawable.omnibox_https_valid_light : R.drawable.omnibox_https_valid;
- default:
- assert false;
- }
- return 0;
- }
-
- /**
- * Updates the security icon displayed in the LocationBar.
- */
- @Override
- public void updateSecurityIcon(int securityLevel) {
- if (showingOriginalUrlForPreview()) {
- securityLevel = ConnectionSecurityLevel.NONE;
- }
- if (mQueryInTheOmnibox) {
- if (securityLevel == ConnectionSecurityLevel.SECURE
- || securityLevel == ConnectionSecurityLevel.EV_SECURE) {
- securityLevel = ConnectionSecurityLevel.NONE;
- } else if (securityLevel == ConnectionSecurityLevel.SECURITY_WARNING
- || securityLevel == ConnectionSecurityLevel.SECURITY_ERROR) {
- setUrlToPageUrl();
- }
- }
-
- // ImageView#setImageResource is no-op if given resource is the current one.
- mSecurityButton.setImageResource(
- getSecurityIconResource(securityLevel, !shouldEmphasizeHttpsScheme()));
-
- if (mSecurityIconType == securityLevel) return;
- mSecurityIconType = securityLevel;
-
- if (securityLevel == ConnectionSecurityLevel.NONE) {
- updateSecurityButton(false);
- } else {
- updateSecurityButton(true);
- // Since we emphasize the schema of the URL based on the security type, we need to
- // refresh the emphasis.
- mUrlBar.deEmphasizeUrl();
- }
- emphasizeUrl();
- }
-
- private void emphasizeUrl() {
- if (!mQueryInTheOmnibox) mUrlBar.emphasizeUrl();
- }
-
- @Override
- public boolean shouldEmphasizeHttpsScheme() {
- int securityLevel = getSecurityLevel();
- if (securityLevel == ConnectionSecurityLevel.SECURITY_ERROR
- || securityLevel == ConnectionSecurityLevel.SECURITY_WARNING
- || securityLevel == ConnectionSecurityLevel.SECURITY_POLICY_WARNING) {
- return true;
- }
- if (getToolbarDataProvider().isUsingBrandColor()) return false;
- if (getToolbarDataProvider().isIncognito()) return false;
- return true;
- }
-
- /**
- * Updates the display of the security button.
- * @param enabled Whether the security button should be displayed.
- */
- private void updateSecurityButton(boolean enabled) {
- changeLocationBarIcon(enabled
- && (!DeviceFormFactor.isTablet(getContext()) || !mUrlHasFocus));
- mSecurityButtonShown = enabled;
- updateLocationBarIconContainerVisibility();
- }
-
- /**
- * @return Whether the security button is currently being displayed.
- */
- @VisibleForTesting
- public boolean isSecurityButtonShown() {
- return mSecurityButtonShown;
- }
-
- /**
- * Sets the type of the current navigation type and updates the UI to match it.
- * @param buttonType The type of navigation button to be shown.
- */
- private void setNavigationButtonType(NavigationButtonType buttonType) {
- switch (buttonType) {
- case PAGE:
- Drawable page = ApiCompatibilityUtils.getDrawable(
- getResources(), R.drawable.ic_omnibox_page);
- page.setColorFilter(mUseDarkColors
- ? getResources().getColor(R.color.light_normal_color)
- : Color.WHITE, PorterDuff.Mode.SRC_IN);
- mNavigationButton.setImageDrawable(page);
- break;
- case MAGNIFIER:
- mNavigationButton.setImageResource(R.drawable.ic_omnibox_magnifier);
- break;
- case EMPTY:
- mNavigationButton.setImageResource(0);
- break;
- default:
- assert false;
- }
-
- if (mNavigationButton.getVisibility() != VISIBLE) {
- mNavigationButton.setVisibility(VISIBLE);
- }
- mNavigationButtonType = buttonType;
- updateLocationBarIconContainerVisibility();
- }
-
- /**
- * Update the visibility of the location bar icon container based on the state of the
- * security and navigation icons.
- */
- protected void updateLocationBarIconContainerVisibility() {
- boolean showContainer =
- mSecurityButtonShown || mNavigationButtonType != NavigationButtonType.EMPTY;
- findViewById(R.id.location_bar_icon).setVisibility(showContainer ? VISIBLE : GONE);
- }
-
- private boolean isStoredArticle(String url) {
- DomDistillerService domDistillerService =
- DomDistillerServiceFactory.getForProfile(Profile.getLastUsedProfile());
- String entryIdFromUrl = DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id");
- if (TextUtils.isEmpty(entryIdFromUrl)) return false;
- return domDistillerService.hasEntry(entryIdFromUrl);
- }
-
- /**
- * Updates the layout params for the location bar start aligned views.
- */
- protected void updateLayoutParams() {
- int startMargin = 0;
- int urlContainerChildIndex = -1;
- for (int i = 0; i < getChildCount(); i++) {
- View childView = getChildAt(i);
- if (childView.getVisibility() != GONE) {
- LayoutParams childLayoutParams = (LayoutParams) childView.getLayoutParams();
- if (ApiCompatibilityUtils.getMarginStart(childLayoutParams) != startMargin) {
- ApiCompatibilityUtils.setMarginStart(childLayoutParams, startMargin);
- childView.setLayoutParams(childLayoutParams);
- }
- if (childView == mUrlContainer) {
- urlContainerChildIndex = i;
- break;
- }
- int widthMeasureSpec;
- int heightMeasureSpec;
- if (childLayoutParams.width == LayoutParams.WRAP_CONTENT) {
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- getMeasuredWidth(), MeasureSpec.AT_MOST);
- } else if (childLayoutParams.width == LayoutParams.MATCH_PARENT) {
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- getMeasuredWidth(), MeasureSpec.EXACTLY);
- } else {
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- childLayoutParams.width, MeasureSpec.EXACTLY);
- }
- if (childLayoutParams.height == LayoutParams.WRAP_CONTENT) {
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- getMeasuredHeight(), MeasureSpec.AT_MOST);
- } else if (childLayoutParams.height == LayoutParams.MATCH_PARENT) {
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- getMeasuredHeight(), MeasureSpec.EXACTLY);
- } else {
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- childLayoutParams.height, MeasureSpec.EXACTLY);
- }
- childView.measure(widthMeasureSpec, heightMeasureSpec);
- startMargin += childView.getMeasuredWidth();
- }
- }
-
- assert urlContainerChildIndex != -1;
- int urlContainerMarginEnd = 0;
- for (int i = urlContainerChildIndex + 1; i < getChildCount(); i++) {
- View childView = getChildAt(i);
- if (childView.getVisibility() != GONE) {
- LayoutParams childLayoutParams = (LayoutParams) childView.getLayoutParams();
- urlContainerMarginEnd = Math.max(urlContainerMarginEnd,
- childLayoutParams.width
- + ApiCompatibilityUtils.getMarginStart(childLayoutParams)
- + ApiCompatibilityUtils.getMarginEnd(childLayoutParams));
- }
- }
- LayoutParams urlLayoutParams = (LayoutParams) mUrlContainer.getLayoutParams();
- if (ApiCompatibilityUtils.getMarginEnd(urlLayoutParams) != urlContainerMarginEnd) {
- ApiCompatibilityUtils.setMarginEnd(urlLayoutParams, urlContainerMarginEnd);
- mUrlContainer.setLayoutParams(urlLayoutParams);
- }
- }
-
- /**
- * @return Whether the delete button should be shown.
- */
- protected boolean shouldShowDeleteButton() {
- // Show the delete button at the endon the right when the bar has focus and has some text.
- return mUrlBar.hasFocus() && !TextUtils.isEmpty(mUrlBar.getText());
- }
-
- /**
- * Updates the display of the delete URL content button.
- */
- protected void updateDeleteButtonVisibility() {
- }
-
- /**
- * @return The suggestion list popup containing the omnibox results (or
- * null if it has not yet been created).
- */
- @VisibleForTesting
- public OmniboxSuggestionsList getSuggestionList() {
- return mSuggestionList;
- }
-
- /**
- * Initiates the mSuggestionListPopup. Done on demand to not slow down
- * the initial inflation of the location bar.
- */
- private void initSuggestionList() {
- // Only called from onSuggestionsReceived(), which is a callback from a listener set up by
- // onNativeLibraryReady(), so this assert is safe.
- assert mNativeInitialized : "Trying to initialize suggestions list before native init";
- if (mSuggestionList != null) return;
-
- OnLayoutChangeListener suggestionListResizer = new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- // On ICS, this update does not take affect unless it is posted to the end of the
- // current message queue.
- post(new Runnable() {
- @Override
- public void run() {
- if (mSuggestionList.isShown()) mSuggestionList.updateLayoutParams();
- }
- });
- }
- };
- getRootView().findViewById(R.id.control_container)
- .addOnLayoutChangeListener(suggestionListResizer);
-
- mSuggestionList = new OmniboxSuggestionsList(getContext());
- mOmniboxResultsContainer.addView(mSuggestionList);
- mSuggestionList.setAdapter(mSuggestionListAdapter);
- mSuggestionList.setClipToPadding(false);
- mSuggestionListAdapter.setSuggestionDelegate(new OmniboxSuggestionDelegate() {
- @Override
- public void onSelection(OmniboxSuggestion suggestion, int position) {
- mSuggestionSelectionInProgress = true;
- String suggestionMatchUrl = updateSuggestionUrlIfNeeded(suggestion, position);
- loadUrlFromOmniboxMatch(suggestionMatchUrl, suggestion.getTransition(), position,
- suggestion.getType());
- hideSuggestions();
- UiUtils.hideKeyboard(mUrlBar);
- }
-
- @Override
- public void onRefineSuggestion(OmniboxSuggestion suggestion) {
- stopAutocomplete(false);
- mUrlBar.setUrl(suggestion.getFillIntoEdit(), null);
- mUrlBar.setSelection(mUrlBar.getText().length());
- RecordUserAction.record("MobileOmniboxRefineSuggestion");
- }
-
- @Override
- public void onSetUrlToSuggestion(OmniboxSuggestion suggestion) {
- if (mIgnoreOmniboxItemSelection) return;
- setUrlBarText(null, null, suggestion.getFillIntoEdit());
- mUrlBar.setSelection(mUrlBar.getText().length());
- mIgnoreOmniboxItemSelection = true;
- }
-
- @Override
- public void onDeleteSuggestion(int position) {
- if (mAutocomplete != null) mAutocomplete.deleteSuggestion(position);
- }
-
- @Override
- public void onGestureDown() {
- stopAutocomplete(false);
- }
-
- @Override
- public void onShowModal() {
- mSuggestionModalShown = true;
- }
-
- @Override
- public void onHideModal() {
- mSuggestionModalShown = false;
- }
-
- @Override
- public void onTextWidthsUpdated(float requiredWidth, float matchContentsWidth) {
- mSuggestionList.updateMaxTextWidths(requiredWidth, matchContentsWidth);
- }
-
- @Override
- public float getMaxRequiredWidth() {
- return mSuggestionList.getMaxRequiredWidth();
- }
-
- @Override
- public float getMaxMatchContentsWidth() {
- return mSuggestionList.getMaxMatchContentsWidth();
- }
- });
- }
-
- /**
- * @return The view that the suggestion popup should be anchored below.
- */
- protected View getSuggestionPopupAnchorView() {
- return this;
- }
-
- /**
- * @return The background for the omnibox suggestions popup.
- */
- protected Drawable getSuggestionPopupBackground() {
- if (mToolbarDataProvider.isIncognito()) {
- return new ColorDrawable(OMNIBOX_INCOGNITO_RESULTS_BG_COLOR);
- } else {
- return new ColorDrawable(OMNIBOX_RESULTS_BG_COLOR);
- }
- }
-
- /**
- * Handles showing/hiding the suggestions list.
- * @param visible Whether the suggestions list should be visible.
- */
- protected void setSuggestionsListVisibility(final boolean visible) {
- mSuggestionsShown = visible;
- if (mSuggestionList != null) {
- final boolean isShowing = mSuggestionList.isShown();
- if (visible && !isShowing) {
- mSuggestionList.show();
- } else if (!visible && isShowing) {
- mSuggestionList.setVisibility(GONE);
- }
- }
- updateOmniboxResultsContainer();
- }
-
- /**
- * Updates the URL we will navigate to from suggestion, if needed. This will update the search
- * URL to be of the corpus type if query in the omnibox is displayed and update aqs= parameter
- * on regular web search URLs.
- *
- * @param suggestion The chosen omnibox suggestion.
- * @param selectedIndex The index of the chosen omnibox suggestion.
- * @return The url to navigate to.
- */
- private String updateSuggestionUrlIfNeeded(OmniboxSuggestion suggestion, int selectedIndex) {
- // Only called once we have suggestions, and don't have a listener though which we can
- // receive suggestions until the native side is ready, so this is safe
- assert mNativeInitialized
- : "updateSuggestionUrlIfNeeded called before native initialization";
-
- String updatedUrl = null;
- // Only replace URL queries for corpus search refinements, this does not work well
- // for regular web searches.
- // TODO(mariakhomenko): improve efficiency by just checking whether corpus exists.
- if (mQueryInTheOmnibox && !suggestion.isUrlSuggestion()
- && !TextUtils.isEmpty(mToolbarDataProvider.getCorpusChipText())) {
- String query = suggestion.getFillIntoEdit();
- Tab currentTab = getCurrentTab();
- if (currentTab != null && !TextUtils.isEmpty(currentTab.getUrl())
- && !TextUtils.isEmpty(query)) {
- updatedUrl = TemplateUrlService.getInstance().replaceSearchTermsInUrl(
- query, currentTab.getUrl());
- }
- } else if (suggestion.getType() != Type.VOICE_SUGGEST) {
- // TODO(mariakhomenko): Ideally we want to update match destination URL with new aqs
- // for query in the omnibox and voice suggestions, but it's currently difficult to do.
- long elapsedTimeSinceInputChange = mNewOmniboxEditSessionTimestamp > 0
- ? (SystemClock.elapsedRealtime() - mNewOmniboxEditSessionTimestamp) : -1;
- updatedUrl = mAutocomplete.updateMatchDestinationUrlWithQueryFormulationTime(
- selectedIndex, elapsedTimeSinceInputChange);
- }
-
- return updatedUrl == null ? suggestion.getUrl() : updatedUrl;
- }
-
- private void clearSuggestions(boolean notifyChange) {
- mSuggestionItems.clear();
- // Make sure to notify the adapter. If the ListView becomes out of sync
- // with its adapter and it has not been notified, it will throw an
- // exception when some UI events are propagated.
- if (notifyChange) mSuggestionListAdapter.notifyDataSetChanged();
- }
-
- /**
- * Hides the omnibox suggestion popup.
- *
- * <p>
- * Signals the autocomplete controller to stop generating omnibox suggestions.
- *
- * @see AutocompleteController#stop(boolean)
- */
- @Override
- public void hideSuggestions() {
- if (mAutocomplete == null) return;
-
- if (mShowSuggestions != null) removeCallbacks(mShowSuggestions);
-
- recordSuggestionsDismissed();
-
- stopAutocomplete(true);
-
- setSuggestionsListVisibility(false);
- clearSuggestions(true);
- updateNavigationButton();
-
- mSuggestionSelectionInProgress = false;
- }
-
- /**
- * Records a UMA action indicating that the user dismissed the suggestion list (e.g. pressed
- * the back button or the 'x' button in the Omnibox). If there was an answer shown its type
- * is recorded.
- *
- * The action is not recorded if mSelectionInProgress is true. This allows us to avoid
- * recording the action in the case where the user is selecting a suggestion which is not
- * considered a dismissal.
- */
- private void recordSuggestionsDismissed() {
- if (mSuggestionSelectionInProgress || mSuggestionItems.size() == 0) return;
-
- int answerTypeShown = 0;
- for (int i = 0; i < mSuggestionItems.size(); i++) {
- OmniboxSuggestion suggestion = mSuggestionItems.get(i).getSuggestion();
- if (suggestion.hasAnswer()) {
- try {
- answerTypeShown = Integer.parseInt(suggestion.getAnswerType());
- } catch (NumberFormatException e) {
- Log.e(getClass().getSimpleName(),
- "Answer type in dismissed suggestions is not an int: "
- + suggestion.getAnswerType());
- }
- break;
- }
- }
- RecordHistogram.recordSparseSlowlyHistogram(
- "Omnibox.SuggestionsDismissed.AnswerType", answerTypeShown);
- }
-
- /**
- * Signals the autocomplete controller to stop generating omnibox suggestions and cancels the
- * queued task to start the autocomplete controller, if any.
- *
- * @param clear Whether to clear the most recent autocomplete results.
- */
- private void stopAutocomplete(boolean clear) {
- if (mAutocomplete != null) mAutocomplete.stop(clear);
- cancelPendingAutocompleteStart();
- }
-
- /**
- * Cancels the queued task to start the autocomplete controller, if any.
- */
- private void cancelPendingAutocompleteStart() {
- if (mRequestSuggestions != null) {
- // There is a request for suggestions either waiting for the native side
- // to start, or on the message queue. Remove it from wherever it is.
- if (!mDeferredNativeRunnables.remove(mRequestSuggestions)) {
- removeCallbacks(mRequestSuggestions);
- }
- mRequestSuggestions = null;
- }
- }
-
- @Override
- protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
- // Don't restore the state of the location bar, it can lead to all kind of bad states with
- // the popup.
- // When we restore tabs, we focus the selected tab so the URL of the page shows.
- }
-
- /**
- * Performs a search query on the current {@link ChromeTab}. This calls
- * {@link TemplateUrlService#getUrlForSearchQuery(String)} to get a url based on {@code query}
- * and loads that url in the current {@link ChromeTab}.
- * @param query The {@link String} that represents the text query that should be searched for.
- */
- @VisibleForTesting
- public void performSearchQueryForTest(String query) {
- if (TextUtils.isEmpty(query)) return;
-
- String queryUrl = TemplateUrlService.getInstance().getUrlForSearchQuery(query);
-
- if (!TextUtils.isEmpty(queryUrl)) {
- loadUrl(queryUrl, PageTransition.GENERATED);
- } else {
- setSearchQuery(query);
- }
- }
-
- /**
- * Sets the query string in the omnibox (ensuring the URL bar has focus and triggering
- * autocomplete for the specified query) as if the user typed it.
- *
- * @param query The query to be set in the omnibox.
- */
- public void setSearchQuery(final String query) {
- if (TextUtils.isEmpty(query)) return;
-
- if (!mNativeInitialized) {
- mDeferredNativeRunnables.add(new Runnable() {
- @Override
- public void run() {
- setSearchQuery(query);
- }
- });
- return;
- }
-
- setUrlBarText(null, null, query);
- mUrlBar.setSelection(0, mUrlBar.getText().length());
- mUrlBar.requestFocus();
- stopAutocomplete(false);
- if (getCurrentTab() != null) {
- mAutocomplete.start(
- getCurrentTab().getProfile(), getCurrentTab().getUrl(), query, false);
- }
- post(new Runnable() {
- @Override
- public void run() {
- UiUtils.showKeyboard(mUrlBar);
- }
- });
- }
-
- /**
- * Whether {@code v} is a location icon which can be clicked to show the
- * origin info dialog.
- */
- private boolean isLocationIcon(View v) {
- return v == mSecurityButton || v == mNavigationButton;
- }
-
- @Override
- public void onClick(View v) {
- if (v == mDeleteButton) {
- if (!TextUtils.isEmpty(mUrlBar.getQueryText())) {
- setUrlBarText(null, null, "");
- hideSuggestions();
- }
-
- startZeroSuggest();
- return;
- } else if (!mUrlHasFocus && isLocationIcon(v)) {
- Tab currentTab = getCurrentTab();
- if (currentTab != null && currentTab.getWebContents() != null) {
- WebsiteSettingsPopup.show(getContext(), currentTab.getProfile(),
- currentTab.getWebContents());
- }
- } else if (v == mMicButton) {
- RecordUserAction.record("MobileOmniboxVoiceSearch");
- startVoiceRecognition();
- }
- }
-
- /**
- * Whether we want to be showing inline autocomplete results. We don't want to show them as the
- * user deletes input. Also if there is a composition (e.g. while using the Japanese IME),
- * we must not autocomplete or we'll destroy the composition.
- * @return Whether we want to be showing inline autocomplete results.
- */
- private boolean shouldAutocomplete() {
- if (mLastUrlEditWasDelete) return false;
- Editable text = mUrlBar.getText();
-
- return mUrlBar.isCursorAtEndOfTypedText()
- && !mUrlBar.isInBatchEditMode()
- && BaseInputConnection.getComposingSpanEnd(text)
- == BaseInputConnection.getComposingSpanStart(text);
- }
-
- @Override
- public void onSuggestionsReceived(List<OmniboxSuggestion> newSuggestions,
- String inlineAutocompleteText) {
- // This is a callback from a listener that is set up by onNativeLibraryReady,
- // so can only be called once the native side is set up.
- assert mNativeInitialized : "Suggestions received before native side intialialized";
-
- if (getCurrentTab() == null) {
- // If the current tab is not available, drop the suggestions and hide the autocomplete.
- hideSuggestions();
- return;
- }
-
- String userText = mUrlBar.getTextWithoutAutocomplete();
- mUrlTextAfterSuggestionsReceived = userText + inlineAutocompleteText;
-
- boolean itemsChanged = false;
- boolean itemCountChanged = false;
- // If the length of the incoming suggestions matches that of those currently being shown,
- // replace them inline to allow transient entries to retain their proper highlighting.
- if (mSuggestionItems.size() == newSuggestions.size()) {
- for (int index = 0; index < newSuggestions.size(); index++) {
- OmniboxResultItem suggestionItem = mSuggestionItems.get(index);
- OmniboxSuggestion suggestion = suggestionItem.getSuggestion();
- OmniboxSuggestion newSuggestion = newSuggestions.get(index);
- // Determine whether the suggestions have changed. If not, save some time by not
- // redrawing the suggestions UI.
- if (suggestion.equals(newSuggestion)
- && suggestion.getType() != OmniboxSuggestion.Type.SEARCH_SUGGEST_TAIL) {
- if (suggestionItem.getMatchedQuery().equals(userText)) {
- continue;
- } else if (!suggestion.getDisplayText().startsWith(userText)
- && !suggestion.getUrl().contains(userText)) {
- continue;
- }
- }
- mSuggestionItems.set(index, new OmniboxResultItem(newSuggestion, userText));
- itemsChanged = true;
- }
- } else {
- itemsChanged = true;
- itemCountChanged = true;
- clearSuggestions(false);
- for (int i = 0; i < newSuggestions.size(); i++) {
- mSuggestionItems.add(new OmniboxResultItem(newSuggestions.get(i), userText));
- }
- }
-
- if (mSuggestionItems.isEmpty()) {
- if (mSuggestionsShown) hideSuggestions();
- return;
- }
-
- if (shouldAutocomplete()) {
- mUrlBar.setAutocompleteText(userText, inlineAutocompleteText);
- }
-
- // Show the suggestion list.
- initSuggestionList(); // It may not have been initialized yet.
- mSuggestionList.resetMaxTextWidths();
-
- if (itemsChanged) mSuggestionListAdapter.notifySuggestionsChanged();
-
- if (mUrlBar.hasFocus()) {
- final boolean updateLayoutParams = itemCountChanged;
- mShowSuggestions = new Runnable() {
- @Override
- public void run() {
- setSuggestionsListVisibility(true);
- if (updateLayoutParams) {
- mSuggestionList.updateLayoutParams();
- }
- mShowSuggestions = null;
- }
- };
- if (!isUrlFocusChangeInProgress()) {
- mShowSuggestions.run();
- } else {
- postDelayed(mShowSuggestions, ToolbarPhone.URL_FOCUS_CHANGE_ANIMATION_DURATION_MS);
- }
- }
-
- // Update the navigation button to show the default suggestion's icon.
- updateNavigationButton();
-
- if (!CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_INSTANT)
- && PrivacyPreferencesManager.getInstance(getContext()).shouldPrerender()) {
- mOmniboxPrerender.prerenderMaybe(
- userText,
- getOriginalUrl(),
- mAutocomplete.getCurrentNativeAutocompleteResult(),
- getCurrentTab().getProfile(),
- getCurrentTab());
- }
- }
-
- @Override
- public void backKeyPressed() {
- hideSuggestions();
- UiUtils.hideKeyboard(mUrlBar);
- // Revert the URL to match the current page.
- setUrlToPageUrl();
- // Focus the page.
- Tab currentTab = getCurrentTab();
- if (currentTab != null) currentTab.requestFocus();
- }
-
- /**
- * @return Returns the original url of the page.
- */
- public String getOriginalUrl() {
- return mOriginalUrl;
- }
-
- /**
- * Given the URL display text, this will remove any path portion contained within.
- * @param displayText The text to strip the path from.
- * @return A pair where the first item is the text without any path content (if the path was
- * successfully found), and the second item is the path content (or null if no path
- * was found or parsing the path failed).
- * @see ToolbarDataProvider#getText()
- */
- // TODO(tedchoc): Move this logic into the original display text calculation.
- @VisibleForTesting
- public static Pair<String, String> splitPathFromUrlDisplayText(String displayText) {
- int pathSearchOffset = 0;
- Uri uri = Uri.parse(displayText);
- String scheme = uri.getScheme();
- if (!TextUtils.isEmpty(scheme)) {
- if (UNSUPPORTED_SCHEMES_TO_SPLIT.contains(scheme)) {
- return Pair.create(displayText, null);
- } else if (ACCEPTED_SCHEMES.contains(scheme)) {
- for (pathSearchOffset = scheme.length();
- pathSearchOffset < displayText.length();
- pathSearchOffset++) {
- char c = displayText.charAt(pathSearchOffset);
- if (c != ':' && c != '/') break;
- }
- }
- }
- int pathOffset = -1;
- if (pathSearchOffset < displayText.length()) {
- pathOffset = displayText.indexOf('/', pathSearchOffset);
- }
- if (pathOffset != -1) {
- String prePathText = displayText.substring(0, pathOffset);
- // If the '/' is the last character and the beginning of the path, then just drop
- // the path entirely.
- String pathText = pathOffset == displayText.length() - 1
- ? null : displayText.substring(pathOffset);
- return Pair.create(prePathText, pathText);
- }
- return Pair.create(displayText, null);
- }
-
- /**
- * Sets the displayed URL to be the URL of the page currently showing.
- *
- * <p>The URL is converted to the most user friendly format (removing HTTP:// for example).
- *
- * <p>If the current tab is null, the URL text will be cleared.
- */
- @Override
- public void setUrlToPageUrl() {
- // If the URL is currently focused, do not replace the text they have entered with the URL.
- // Once they stop editing the URL, the current tab's URL will automatically be filled in.
- if (mUrlBar.hasFocus()) return;
-
- mQueryInTheOmnibox = false;
-
- if (getCurrentTab() == null) {
- setUrlBarText(null, null, "");
- return;
- }
-
- // Profile may be null if switching to a tab that has not yet been initialized.
- Profile profile = getCurrentTab().getProfile();
- if (profile != null) mOmniboxPrerender.clear(profile);
-
- String url = getCurrentTab().getUrl().trim();
- mOriginalUrl = url;
-
- if (NativePageFactory.isNativePageUrl(url, getCurrentTab().isIncognito())) {
- // Don't show anything for Chrome URLs.
- setUrlBarText("", null, null);
- return;
- }
-
- // Background view has similar case as snapshot.
- BackgroundContentViewHelper backgroundViewHelper =
- getCurrentTab().getBackgroundContentViewHelper();
- boolean hasPendingBackgroundPage =
- backgroundViewHelper != null && backgroundViewHelper.hasPendingBackgroundPage();
- boolean isTransitioningFromPreviewPageToOriginal =
- showingOriginalUrlForPreview() && !hasPendingBackgroundPage;
- mShowingOriginalUrlForPreview = hasPendingBackgroundPage;
-
- boolean showingQuery = false;
- String displayText = mToolbarDataProvider.getText();
- int securityLevel = getSecurityLevel();
- if (securityLevel != ConnectionSecurityLevel.SECURITY_ERROR
- && !TextUtils.isEmpty(displayText) && mToolbarDataProvider.wouldReplaceURL()) {
- url = displayText.trim();
- showingQuery = true;
- mQueryInTheOmnibox = true;
- }
- String path = null;
- if (!showingQuery && FeatureUtilities.isDocumentMode(getContext())) {
- Pair<String, String> urlText = splitPathFromUrlDisplayText(displayText);
- displayText = urlText.first;
- path = urlText.second;
- }
-
- if (DomDistillerUrlUtils.isDistilledPage(url)) {
- if (isStoredArticle(url)) {
- DomDistillerService domDistillerService =
- DomDistillerServiceFactory.getForProfile(profile);
- String originalUrl = domDistillerService.getUrlForEntry(
- DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id"));
- displayText =
- DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl);
- } else if (DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url) != null) {
- String originalUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url);
- displayText =
- DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl);
- }
- }
-
- if (setUrlBarText(displayText, path, url) || isTransitioningFromPreviewPageToOriginal) {
- mUrlBar.deEmphasizeUrl();
- emphasizeUrl();
- }
- if (showingQuery) {
- updateNavigationButton();
- }
- updateCustomSelectionActionModeCallback();
- }
-
- /**
- * Changes the text on the url bar
- * @param displayText The text (URL or search terms) for user display.
- * @param trailingText The trailing text (path portion of the URL) to be displayed separately.
- * @param text The original text (URL or search terms) for copy/cut.
- * @return Whether the URL was changed as a result of this call.
- */
- private boolean setUrlBarText(String displayText, String trailingText, String text) {
- mIgnoreURLBarModification = true;
- boolean urlChanged = mUrlContainer.setUrlText(displayText, trailingText, text);
- mIgnoreURLBarModification = false;
- return urlChanged;
- }
-
- /**
- * Sets whether modifications to the URL bar should be ignored.
- */
- @Override
- public void setIgnoreURLBarModification(boolean value) {
- mIgnoreURLBarModification = value;
- }
-
- private void loadUrlFromOmniboxMatch(String url, int transition, int matchPosition,
- OmniboxSuggestion.Type type) {
- // loadUrl modifies AutocompleteController's state clearing the native
- // AutocompleteResults needed by onSuggestionsSelected. Therefore,
- // loadUrl should should be invoked last.
- Tab currentTab = getCurrentTab();
- String currentPageUrl = currentTab != null ? currentTab.getUrl() : "";
- WebContents webContents = currentTab != null ? currentTab.getWebContents() : null;
- long elapsedTimeSinceModified = mNewOmniboxEditSessionTimestamp > 0
- ? (SystemClock.elapsedRealtime() - mNewOmniboxEditSessionTimestamp) : -1;
- mAutocomplete.onSuggestionSelected(matchPosition, type, currentPageUrl,
- mQueryInTheOmnibox, mUrlFocusedFromFakebox, elapsedTimeSinceModified,
- webContents);
- loadUrl(url, transition);
- }
-
- private void loadUrl(String url, int transition) {
- Tab currentTab = getCurrentTab();
-
- // The code of the rest of this class ensures that this can't be called until the native
- // side is initialized
- assert mNativeInitialized : "Loading URL before native side initialized";
-
- if (currentTab != null
- && (currentTab.isNativePage() || NewTabPage.isNTPUrl(currentTab.getUrl()))) {
- NewTabPageUma.recordOmniboxNavigation(url, transition);
- // Passing in an empty string should not do anything unless the user is at the NTP.
- // Since the NTP has no url, pressing enter while clicking on the URL bar should refresh
- // the page as it does when you click and press enter on any other site.
- if (url.isEmpty()) url = currentTab.getUrl();
- }
-
- // Loads the |url| in the current ContentView and gives focus to the ContentView.
- if (currentTab != null && !url.isEmpty()) {
- LoadUrlParams loadUrlParams = new LoadUrlParams(url);
- loadUrlParams.setVerbatimHeaders(
- GeolocationHeader.getGeoHeader(getContext(), url, currentTab.isIncognito()));
- loadUrlParams.setTransitionType(transition | PageTransition.FROM_ADDRESS_BAR);
- currentTab.loadUrl(loadUrlParams);
-
- setUrlToPageUrl();
- RecordUserAction.record("MobileOmniboxSearch");
- RecordUserAction.record("MobileTabClobbered");
- } else {
- setUrlToPageUrl();
- }
-
- if (currentTab != null) currentTab.requestFocus();
-
- // Prevent any upcoming omnibox suggestions from showing. We have to do this after we load
- // the URL as this will hide the suggestions and trigger a cancel of the prerendered page.
- stopAutocomplete(true);
- }
-
- /**
- * Update the location bar visuals based on a loading state change.
- * @param updateUrl Whether to update the URL as a result of the this call.
- */
- @Override
- public void updateLoadingState(boolean updateUrl) {
- if (updateUrl) setUrlToPageUrl();
- updateNavigationButton();
- updateSecurityIcon(getSecurityLevel());
- }
-
- /**
- * @return The ChromeTab currently showing.
- */
- @Override
- public ChromeTab getCurrentTab() {
- if (mToolbarDataProvider == null) return null;
- return ChromeTab.fromTab(mToolbarDataProvider.getTab());
- }
-
- private ContentViewCore getContentViewCore() {
- Tab currentTab = getCurrentTab();
- return currentTab != null ? currentTab.getContentViewCore() : null;
- }
-
- private void updateOmniboxResultsContainer() {
- if (mSuggestionsShown || mUrlHasFocus) {
- if (mOmniboxResultsContainer == null) {
- ViewStub overlayStub =
- (ViewStub) getRootView().findViewById(R.id.omnibox_results_container_stub);
- mOmniboxResultsContainer = (ViewGroup) overlayStub.inflate();
- mOmniboxResultsContainer.setBackgroundColor(CONTENT_OVERLAY_COLOR);
- // Prevent touch events from propagating down to the chrome view.
- mOmniboxResultsContainer.setOnTouchListener(new OnTouchListener() {
- @Override
- @SuppressLint("ClickableViewAccessibility")
- public boolean onTouch(View v, MotionEvent event) {
- int action = event.getActionMasked();
- if (action == MotionEvent.ACTION_CANCEL
- || action == MotionEvent.ACTION_UP) {
- mUrlBar.clearFocus();
- updateOmniboxResultsContainerBackground(false);
- }
- return true;
- }
- });
- }
- updateOmniboxResultsContainerVisibility(true);
- } else if (mOmniboxResultsContainer != null) {
- updateOmniboxResultsContainerBackground(false);
- }
- }
-
- private void updateOmniboxResultsContainerVisibility(boolean visible) {
- boolean currentlyVisible = mOmniboxResultsContainer.getVisibility() == VISIBLE;
- if (currentlyVisible == visible) {
- // This early return is necessary. Otherwise, calling
- // updateOmniboxResultsContainerVisibility(true) twice in a row will update
- // mFocusedTabImportantForAccessibilityState incorrectly and cause
- // mFocusedTabView to be stuck in IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS mode.
- // http://crbug.com/445560
- return;
- }
-
- if (visible) {
- mOmniboxResultsContainer.setVisibility(VISIBLE);
-
- if (getContentViewCore() != null) {
- mFocusedTabAccessibilityManager =
- getContentViewCore().getBrowserAccessibilityManager();
- if (mFocusedTabAccessibilityManager != null) {
- mFocusedTabAccessibilityManager.setVisible(false);
- }
- }
-
- if (getCurrentTab() != null && getCurrentTab().getView() != null) {
- mFocusedTabView = getCurrentTab().getView();
- mFocusedTabImportantForAccessibilityState =
- mFocusedTabView.getImportantForAccessibility();
- mFocusedTabView.setImportantForAccessibility(
- IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
- }
- } else {
- mOmniboxResultsContainer.setVisibility(INVISIBLE);
-
- if (mFocusedTabAccessibilityManager != null) {
- mFocusedTabAccessibilityManager.setVisible(true);
- mFocusedTabAccessibilityManager = null;
- }
-
- if (mFocusedTabView != null) {
- mFocusedTabView.setImportantForAccessibility(
- mFocusedTabImportantForAccessibilityState);
- mFocusedTabView = null;
- }
- }
- }
-
- /**
- * Set the background of the omnibox results container.
- * @param visible Whether the background should be made visible.
- */
- private void updateOmniboxResultsContainerBackground(boolean visible) {
- if (getToolbarDataProvider() == null) return;
-
- NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
- boolean locationBarShownInNTP = ntp != null && ntp.isLocationBarShownInNTP();
- if (visible) {
- if (locationBarShownInNTP) {
- mOmniboxResultsContainer.getBackground().setAlpha(0);
- } else {
- fadeInOmniboxResultsContainerBackground();
- }
- } else {
- if (locationBarShownInNTP) {
- updateOmniboxResultsContainerVisibility(false);
- } else {
- fadeOutOmniboxResultsContainerBackground();
- }
- }
- }
-
- /**
- * Trigger a fade in of the omnibox results background.
- */
- protected void fadeInOmniboxResultsContainerBackground() {
- if (mFadeInOmniboxBackgroundAnimator == null) {
- mFadeInOmniboxBackgroundAnimator = ObjectAnimator.ofInt(
- getRootView().findViewById(R.id.omnibox_results_container).getBackground(),
- "alpha", 0, 255);
- mFadeInOmniboxBackgroundAnimator.setDuration(OMNIBOX_CONTAINER_BACKGROUND_FADE_MS);
- mFadeInOmniboxBackgroundAnimator.setInterpolator(
- BakedBezierInterpolator.FADE_IN_CURVE);
- }
- runOmniboxResultsFadeAnimation(mFadeInOmniboxBackgroundAnimator);
- }
-
- private void fadeOutOmniboxResultsContainerBackground() {
- if (mFadeOutOmniboxBackgroundAnimator == null) {
- mFadeOutOmniboxBackgroundAnimator = ObjectAnimator.ofInt(
- getRootView().findViewById(R.id.omnibox_results_container).getBackground(),
- "alpha", 255, 0);
- mFadeOutOmniboxBackgroundAnimator.setDuration(OMNIBOX_CONTAINER_BACKGROUND_FADE_MS);
- mFadeOutOmniboxBackgroundAnimator.setInterpolator(
- BakedBezierInterpolator.FADE_OUT_CURVE);
- mFadeOutOmniboxBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
- private boolean mIsCancelled;
-
- @Override
- public void onAnimationStart(Animator animation) {
- mIsCancelled = false;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mIsCancelled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mIsCancelled) return;
- updateOmniboxResultsContainerVisibility(false);
- }
- });
- }
- runOmniboxResultsFadeAnimation(mFadeOutOmniboxBackgroundAnimator);
- }
-
- private void runOmniboxResultsFadeAnimation(Animator fadeAnimation) {
- if (mOmniboxBackgroundAnimator == fadeAnimation
- && mOmniboxBackgroundAnimator.isRunning()) {
- return;
- } else if (mOmniboxBackgroundAnimator != null) {
- mOmniboxBackgroundAnimator.cancel();
- }
- mOmniboxBackgroundAnimator = fadeAnimation;
- mOmniboxBackgroundAnimator.start();
- }
-
- /**
- * @return Whether voice search is supported in the current browser configuration.
- */
- protected boolean isVoiceSearchEnabled() {
- return mToolbarDataProvider != null && !mToolbarDataProvider.isIncognito()
- && FeatureUtilities.isRecognitionIntentPresent(getContext(), true);
- }
-
- @Override
- protected void onWindowVisibilityChanged(int visibility) {
- super.onWindowVisibilityChanged(visibility);
- if (visibility == View.VISIBLE) updateMicButtonState();
- }
-
- /**
- * Call to notify the location bar that the state of the voice search microphone button may
- * need to be updated.
- */
- @Override
- public void updateMicButtonState() {
- mMicButton.setVisibility(isVoiceSearchEnabled() ? View.VISIBLE : View.GONE);
- }
-
- /**
- * Call to force the UI to update the state of various buttons based on whether or not the
- * current tab is incognito.
- */
- @Override
- public void updateVisualsForState() {
- if (updateUseDarkColors() || getToolbarDataProvider().isUsingBrandColor()) {
- updateSecurityIcon(getSecurityLevel());
- }
- ColorStateList colorStateList = getResources().getColorStateList(mUseDarkColors
- ? R.color.dark_mode_tint : R.color.light_mode_tint);
- mMicButton.setTint(colorStateList);
- mDeleteButton.setTint(colorStateList);
-
- setNavigationButtonType(mNavigationButtonType);
- mUrlContainer.setUseDarkTextColors(mUseDarkColors);
-
- if (mSuggestionList != null) {
- mSuggestionList.setBackground(getSuggestionPopupBackground());
- }
- mSuggestionListAdapter.setUseDarkColors(mUseDarkColors);
- }
-
- /**
- * Checks the current specs and updates {@link LocationBar#mUseDarkColors} if necessary.
- * @return Whether {@link LocationBar#mUseDarkColors} has been updated.
- */
- private boolean updateUseDarkColors() {
- Tab tab = getCurrentTab();
- boolean brandColorNeedsLightText = false;
- if (getToolbarDataProvider().isUsingBrandColor() && !mUrlHasFocus) {
- int currentPrimaryColor = getToolbarDataProvider().getPrimaryColor();
- brandColorNeedsLightText =
- BrandColorUtils.shouldUseLightDrawablesForToolbar(currentPrimaryColor);
- }
-
- boolean useDarkColors = tab == null || !(tab.isIncognito() || brandColorNeedsLightText);
- boolean hasChanged = useDarkColors != mUseDarkColors;
- mUseDarkColors = useDarkColors;
-
- return hasChanged;
- }
-
- /**
- * Triggers a voice recognition intent to allow the user to specify a search query.
- */
- @Override
- public void startVoiceRecognition() {
- Activity activity = mWindowAndroid.getActivity().get();
- if (activity == null) return;
-
- Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
- intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
- RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
- intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
- activity.getComponentName().flattenToString());
- intent.putExtra(RecognizerIntent.EXTRA_WEB_SEARCH_ONLY, true);
-
- if (mWindowAndroid.showCancelableIntent(intent, this, R.string.voice_search_error) < 0) {
- // Requery whether or not the recognition intent can be handled.
- FeatureUtilities.isRecognitionIntentPresent(activity, false);
- updateMicButtonState();
- }
- }
-
- // WindowAndroid.IntentCallback implementation:
- @Override
- public void onIntentCompleted(WindowAndroid window, int resultCode,
- ContentResolver contentResolver, Intent data) {
- if (resultCode != Activity.RESULT_OK) return;
- if (data.getExtras() == null) return;
-
- VoiceResult topResult = mAutocomplete.onVoiceResults(data.getExtras());
- if (topResult == null) return;
-
- String topResultQuery = topResult.getMatch();
- if (TextUtils.isEmpty(topResultQuery)) return;
-
- if (topResult.getConfidence() < VOICE_SEARCH_CONFIDENCE_NAVIGATE_THRESHOLD) {
- setSearchQuery(topResultQuery);
- return;
- }
-
- String url = AutocompleteController.nativeQualifyPartialURLQuery(topResultQuery);
- if (url == null) {
- url = TemplateUrlService.getInstance().getUrlForVoiceSearchQuery(
- topResultQuery);
- }
- loadUrl(url, PageTransition.TYPED);
- }
-
- /**
- * Tracks how the URL bar was focused (i.e. from the omnibox or the fakebox) and records a UMA
- * stat for this. Should be called whenever the URL bar gains or loses focus.
- * @param hasFocus Whether the URL bar now has focus.
- */
- private void updateFocusSource(boolean hasFocus) {
- if (!hasFocus) {
- mUrlFocusedFromFakebox = false;
- mHasRecordedUrlFocusSource = false;
- return;
- }
-
- // Record UMA event for how the URL bar was focused.
- assert !mHasRecordedUrlFocusSource;
- if (mHasRecordedUrlFocusSource) return;
-
- Tab currentTab = getCurrentTab();
- if (currentTab == null) return;
-
- String url = currentTab.getUrl();
- if (mUrlFocusedFromFakebox) {
- RecordUserAction.record("MobileFocusedFakeboxOnNtp");
- } else {
- if (currentTab.isNativePage() && NewTabPage.isNTPUrl(url)) {
- RecordUserAction.record("MobileFocusedOmniboxOnNtp");
- } else {
- RecordUserAction.record("MobileFocusedOmniboxNotOnNtp");
- }
- }
- mHasRecordedUrlFocusSource = true;
- }
-
- @Override
- public void onTabLoadingNTP(NewTabPage ntp) {
- ntp.setFakeboxDelegate(this);
- }
-
- @Override
- public View getContainerView() {
- return this;
- }
-
- @Override
- public void setTitleToPageTitle() { }
-}

Powered by Google App Engine
This is Rietveld 408576698