| Index: chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlBar.java
|
| diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlBar.java
|
| deleted file mode 100644
|
| index 6696bc54eb4ff93e90d903c7cbcebc6d688675fe..0000000000000000000000000000000000000000
|
| --- a/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlBar.java
|
| +++ /dev/null
|
| @@ -1,1001 +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 android.content.ClipData;
|
| -import android.content.ClipboardManager;
|
| -import android.content.Context;
|
| -import android.content.res.ColorStateList;
|
| -import android.content.res.Resources;
|
| -import android.graphics.Canvas;
|
| -import android.graphics.Rect;
|
| -import android.os.SystemClock;
|
| -import android.text.Editable;
|
| -import android.text.Layout;
|
| -import android.text.Selection;
|
| -import android.text.Spanned;
|
| -import android.text.TextUtils;
|
| -import android.text.TextWatcher;
|
| -import android.util.AttributeSet;
|
| -import android.view.GestureDetector;
|
| -import android.view.KeyEvent;
|
| -import android.view.MotionEvent;
|
| -import android.view.View;
|
| -import android.view.accessibility.AccessibilityEvent;
|
| -import android.view.accessibility.AccessibilityManager;
|
| -import android.view.accessibility.AccessibilityNodeInfo;
|
| -import android.view.inputmethod.BaseInputConnection;
|
| -import android.view.inputmethod.EditorInfo;
|
| -import android.view.inputmethod.InputConnection;
|
| -import android.view.inputmethod.InputConnectionWrapper;
|
| -
|
| -import org.chromium.base.VisibleForTesting;
|
| -import org.chromium.chrome.R;
|
| -import org.chromium.chrome.browser.UrlUtilities;
|
| -import org.chromium.chrome.browser.omnibox.LocationBarLayout.OmniboxLivenessListener;
|
| -import org.chromium.chrome.browser.tab.ChromeTab;
|
| -import org.chromium.chrome.browser.widget.VerticallyFixedEditText;
|
| -import org.chromium.content.browser.ContentViewCore;
|
| -import org.chromium.ui.UiUtils;
|
| -
|
| -import java.net.MalformedURLException;
|
| -import java.net.URI;
|
| -import java.net.URISyntaxException;
|
| -import java.net.URL;
|
| -
|
| -/**
|
| - * The URL text entry view for the Omnibox.
|
| - */
|
| -public class UrlBar extends VerticallyFixedEditText {
|
| - private static final String TAG = "UrlBar";
|
| -
|
| - /** The contents of the URL that precede the path/query after being formatted. */
|
| - private String mFormattedUrlLocation;
|
| -
|
| - /** The contents of the URL that precede the path/query before formatting. */
|
| - private String mOriginalUrlLocation;
|
| -
|
| - /** Overrides the text announced during accessibility events. */
|
| - private String mAccessibilityTextOverride;
|
| -
|
| - private TextWatcher mLocationBarTextWatcher;
|
| -
|
| - private boolean mShowKeyboardOnWindowFocus;
|
| -
|
| - private boolean mFirstDrawComplete;
|
| -
|
| - /**
|
| - * The text direction of the URL or query: LAYOUT_DIRECTION_LOCALE, LAYOUT_DIRECTION_LTR, or
|
| - * LAYOUT_DIRECTION_RTL.
|
| - * */
|
| - private int mUrlDirection;
|
| -
|
| - private UrlBarDelegate mUrlBarDelegate;
|
| -
|
| - private UrlDirectionListener mUrlDirectionListener;
|
| -
|
| - private final AutocompleteSpan mAutocompleteSpan;
|
| -
|
| - /**
|
| - * The gesture detector is used to detect long presses. Long presses require special treatment
|
| - * because the URL bar has custom touch event handling. See: {@link #onTouchEvent}.
|
| - */
|
| - private final GestureDetector mGestureDetector;
|
| - private boolean mFocused;
|
| -
|
| - private final ColorStateList mDarkHintColor;
|
| - private final int mDarkDefaultTextColor;
|
| - private final int mDarkHighlightColor;
|
| -
|
| - private final int mLightHintColor;
|
| - private final int mLightDefaultTextColor;
|
| - private final int mLightHighlightColor;
|
| -
|
| - private Boolean mUseDarkColors;
|
| -
|
| - private AccessibilityManager mAccessibilityManager;
|
| - private boolean mDisableTextAccessibilityEvents;
|
| -
|
| - /**
|
| - * Whether default TextView scrolling should be disabled because autocomplete has been added.
|
| - * This allows the user entered text to be shown instead of the end of the autocomplete.
|
| - */
|
| - private boolean mDisableTextScrollingFromAutocomplete;
|
| -
|
| - private OmniboxLivenessListener mOmniboxLivenessListener;
|
| -
|
| - private long mFirstFocusTimeMs;
|
| -
|
| - private boolean mInBatchEditMode;
|
| - private boolean mSelectionChangedInBatchMode;
|
| -
|
| - /**
|
| - * Implement this to get updates when the direction of the text in the URL bar changes.
|
| - * E.g. If the user is typing a URL, then erases it and starts typing a query in Arabic,
|
| - * the direction will change from left-to-right to right-to-left.
|
| - */
|
| - interface UrlDirectionListener {
|
| - /**
|
| - * Called whenever the layout direction of the UrlBar changes.
|
| - * @param layoutDirection the new direction: android.view.View.LAYOUT_DIRECTION_LTR or
|
| - * android.view.View.LAYOUT_DIRECTION_RTL
|
| - */
|
| - public void onUrlDirectionChanged(int layoutDirection);
|
| - }
|
| -
|
| - /**
|
| - * Delegate used to communicate with the content side and the parent layout.
|
| - */
|
| - public interface UrlBarDelegate {
|
| - /**
|
| - * @return The current active {@link ChromeTab}.
|
| - */
|
| - ChromeTab getCurrentTab();
|
| -
|
| - /**
|
| - * Notify the linked {@link TextWatcher} to ignore any changes made in the UrlBar text.
|
| - * @param ignore Whether the changes should be ignored.
|
| - */
|
| - void setIgnoreURLBarModification(boolean ignore);
|
| -
|
| - /**
|
| - * Called at the beginning of the focus change event before the underlying TextView
|
| - * behavior is triggered.
|
| - * @param gainFocus Whether the URL is gaining focus or not.
|
| - */
|
| - void onUrlPreFocusChanged(boolean gainFocus);
|
| -
|
| - /**
|
| - * Called to notify that back key has been pressed while the focus in on the url bar.
|
| - */
|
| - void backKeyPressed();
|
| -
|
| - /**
|
| - * @return Whether original url is shown for preview page.
|
| - */
|
| - boolean showingOriginalUrlForPreview();
|
| -
|
| - /**
|
| - * @return Whether the light security theme should be used.
|
| - */
|
| - boolean shouldEmphasizeHttpsScheme();
|
| - }
|
| -
|
| - public UrlBar(Context context, AttributeSet attrs) {
|
| - super(context, attrs);
|
| -
|
| - Resources resources = getResources();
|
| -
|
| - mDarkDefaultTextColor = resources.getColor(R.color.url_emphasis_default_text);
|
| - mDarkHintColor = getHintTextColors();
|
| - mDarkHighlightColor = getHighlightColor();
|
| -
|
| - mLightDefaultTextColor = resources.getColor(R.color.url_emphasis_light_default_text);
|
| - mLightHintColor = resources.getColor(R.color.locationbar_light_hint_text);
|
| - mLightHighlightColor = resources.getColor(R.color.locationbar_light_selection_color);
|
| -
|
| - setUseDarkTextColors(true);
|
| -
|
| - mUrlDirection = LAYOUT_DIRECTION_LOCALE;
|
| - mAutocompleteSpan = new AutocompleteSpan();
|
| -
|
| - // The URL Bar is derived from an text edit class, and as such is focusable by
|
| - // default. This means that if it is created before the first draw of the UI it
|
| - // will (as the only focusable element of the UI) get focus on the first draw.
|
| - // We react to this by greying out the tab area and bringing up the keyboard,
|
| - // which we don't want to do at startup. Prevent this by disabling focus until
|
| - // the first draw.
|
| - setFocusable(false);
|
| - setFocusableInTouchMode(false);
|
| -
|
| - mGestureDetector = new GestureDetector(
|
| - getContext(), new GestureDetector.SimpleOnGestureListener() {
|
| - @Override
|
| - public void onLongPress(MotionEvent e) {
|
| - performLongClick();
|
| - }
|
| -
|
| - @Override
|
| - public boolean onSingleTapUp(MotionEvent e) {
|
| - requestFocus();
|
| - return true;
|
| - }
|
| - });
|
| - mGestureDetector.setOnDoubleTapListener(null);
|
| -
|
| - mAccessibilityManager =
|
| - (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
| - }
|
| -
|
| - /**
|
| - * Specifies whether the URL bar should use dark text colors or light colors.
|
| - * @param useDarkColors Whether the text colors should be dark (i.e. appropriate for use
|
| - * on a light background).
|
| - */
|
| - public void setUseDarkTextColors(boolean useDarkColors) {
|
| - if (mUseDarkColors != null && mUseDarkColors.booleanValue() == useDarkColors) return;
|
| -
|
| - mUseDarkColors = useDarkColors;
|
| - if (mUseDarkColors) {
|
| - setTextColor(mDarkDefaultTextColor);
|
| - setHighlightColor(mDarkHighlightColor);
|
| - } else {
|
| - setTextColor(mLightDefaultTextColor);
|
| - setHighlightColor(mLightHighlightColor);
|
| - }
|
| -
|
| - // Note: Setting the hint text color only takes effect if there is not text in the URL bar.
|
| - // To get around this, set the URL to empty before setting the hint color and revert
|
| - // back to the previous text after.
|
| - boolean hasNonEmptyText = false;
|
| - Editable text = getText();
|
| - if (!TextUtils.isEmpty(text)) {
|
| - setText("");
|
| - hasNonEmptyText = true;
|
| - }
|
| - if (useDarkColors) {
|
| - setHintTextColor(mDarkHintColor);
|
| - } else {
|
| - setHintTextColor(mLightHintColor);
|
| - }
|
| - if (hasNonEmptyText) setText(text);
|
| -
|
| - if (!hasFocus()) {
|
| - deEmphasizeUrl();
|
| - emphasizeUrl();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @return The search query text (non-null).
|
| - */
|
| - public String getQueryText() {
|
| - return getEditableText() != null ? getEditableText().toString() : "";
|
| - }
|
| -
|
| - /**
|
| - * @return Whether the current cursor position is at the end of the user typed text (i.e.
|
| - * at the beginning of the inline autocomplete text if present otherwise the very
|
| - * end of the current text).
|
| - */
|
| - public boolean isCursorAtEndOfTypedText() {
|
| - final int selectionStart = getSelectionStart();
|
| - final int selectionEnd = getSelectionEnd();
|
| -
|
| - int expectedSelectionStart = getText().getSpanStart(mAutocompleteSpan);
|
| - int expectedSelectionEnd = getText().length();
|
| - if (expectedSelectionStart < 0) {
|
| - expectedSelectionStart = expectedSelectionEnd;
|
| - }
|
| -
|
| - return selectionStart == expectedSelectionStart && selectionEnd == expectedSelectionEnd;
|
| - }
|
| -
|
| - /**
|
| - * @return Whether the URL is currently in batch edit mode triggered by an IME. No external
|
| - * text changes should be triggered while this is true.
|
| - */
|
| - public boolean isInBatchEditMode() {
|
| - return mInBatchEditMode;
|
| - }
|
| -
|
| - /**
|
| - * @return The user text without the autocomplete text.
|
| - */
|
| - public String getTextWithoutAutocomplete() {
|
| - int autoCompleteIndex = getText().getSpanStart(mAutocompleteSpan);
|
| - if (autoCompleteIndex < 0) {
|
| - return getQueryText();
|
| - } else {
|
| - return getQueryText().substring(0, autoCompleteIndex);
|
| - }
|
| - }
|
| -
|
| - /** @return Whether any autocomplete information is specified on the current text. */
|
| - @VisibleForTesting
|
| - protected boolean hasAutocomplete() {
|
| - return getText().getSpanStart(mAutocompleteSpan) >= 0
|
| - || mAutocompleteSpan.mAutocompleteText != null
|
| - || mAutocompleteSpan.mUserText != null;
|
| - }
|
| -
|
| - @Override
|
| - public void onBeginBatchEdit() {
|
| - super.onBeginBatchEdit();
|
| - mInBatchEditMode = true;
|
| - }
|
| -
|
| - @Override
|
| - public void onEndBatchEdit() {
|
| - super.onEndBatchEdit();
|
| - mInBatchEditMode = false;
|
| - if (mSelectionChangedInBatchMode) {
|
| - validateSelection(getSelectionStart(), getSelectionEnd());
|
| - mSelectionChangedInBatchMode = false;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - protected void onSelectionChanged(int selStart, int selEnd) {
|
| - if (!mInBatchEditMode) {
|
| - validateSelection(selStart, selEnd);
|
| - } else {
|
| - mSelectionChangedInBatchMode = true;
|
| - }
|
| - super.onSelectionChanged(selStart, selEnd);
|
| - }
|
| -
|
| - private void validateSelection(int selStart, int selEnd) {
|
| - int spanStart = getText().getSpanStart(mAutocompleteSpan);
|
| - int spanEnd = getText().getSpanEnd(mAutocompleteSpan);
|
| - if (spanStart >= 0 && (spanStart != selStart || spanEnd != selEnd)) {
|
| - // On selection changes, the autocomplete text has been accepted by the user or needs
|
| - // to be deleted below.
|
| - mAutocompleteSpan.clearSpan();
|
| -
|
| - // The autocomplete text will be deleted any time the selection occurs entirely before
|
| - // the start of the autocomplete text. This is required because certain keyboards will
|
| - // insert characters temporarily when starting a key entry gesture (whether it be
|
| - // swyping a word or long pressing to get a special character). When this temporary
|
| - // character appears, Chrome may decide to append some autocomplete, but the keyboard
|
| - // will then remove this temporary character only while leaving the autocomplete text
|
| - // alone. See crbug/273763 for more details.
|
| - if (selEnd <= spanStart) getText().delete(spanStart, getText().length());
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
|
| - mFocused = focused;
|
| - mUrlBarDelegate.onUrlPreFocusChanged(focused);
|
| - if (!focused) mAutocompleteSpan.clearSpan();
|
| - super.onFocusChanged(focused, direction, previouslyFocusedRect);
|
| -
|
| - if (focused && mFirstFocusTimeMs == 0) {
|
| - mFirstFocusTimeMs = SystemClock.elapsedRealtime();
|
| - if (mOmniboxLivenessListener != null) mOmniboxLivenessListener.onOmniboxFocused();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @return The elapsed realtime timestamp in ms of the first time the url bar was focused,
|
| - * 0 if never.
|
| - */
|
| - public long getFirstFocusTime() {
|
| - return mFirstFocusTimeMs;
|
| - }
|
| -
|
| - @Override
|
| - protected void onWindowVisibilityChanged(int visibility) {
|
| - super.onWindowVisibilityChanged(visibility);
|
| - if (visibility == View.GONE && isFocused()) mShowKeyboardOnWindowFocus = true;
|
| - }
|
| -
|
| - @Override
|
| - public void onWindowFocusChanged(boolean hasWindowFocus) {
|
| - super.onWindowFocusChanged(hasWindowFocus);
|
| - if (hasWindowFocus) {
|
| - if (mShowKeyboardOnWindowFocus && isFocused()) {
|
| - // Without the call to post(..), the keyboard was not getting shown when the
|
| - // window regained focus despite this being the final call in the view system
|
| - // flow.
|
| - post(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - UiUtils.showKeyboard(UrlBar.this);
|
| - }
|
| - });
|
| - }
|
| - mShowKeyboardOnWindowFocus = false;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public View focusSearch(int direction) {
|
| - if (direction == View.FOCUS_BACKWARD
|
| - && mUrlBarDelegate.getCurrentTab().getView() != null) {
|
| - return mUrlBarDelegate.getCurrentTab().getView();
|
| - } else {
|
| - return super.focusSearch(direction);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
| - if (keyCode == KeyEvent.KEYCODE_BACK) {
|
| - if (event.getAction() == KeyEvent.ACTION_DOWN
|
| - && event.getRepeatCount() == 0) {
|
| - // Tell the framework to start tracking this event.
|
| - getKeyDispatcherState().startTracking(event, this);
|
| - return true;
|
| - } else if (event.getAction() == KeyEvent.ACTION_UP) {
|
| - getKeyDispatcherState().handleUpEvent(event);
|
| - if (event.isTracking() && !event.isCanceled()) {
|
| - mUrlBarDelegate.backKeyPressed();
|
| - return true;
|
| - }
|
| - }
|
| - }
|
| - return super.onKeyPreIme(keyCode, event);
|
| - }
|
| -
|
| - @Override
|
| - public boolean onTouchEvent(MotionEvent event) {
|
| - ChromeTab currentTab = mUrlBarDelegate.getCurrentTab();
|
| - if (currentTab != null
|
| - && currentTab.getBackgroundContentViewHelper() != null
|
| - && mUrlBarDelegate.showingOriginalUrlForPreview()) {
|
| - // When we are showing preview, we treat click on UrlBar as an event to force swapping
|
| - // of content views.
|
| - currentTab.getBackgroundContentViewHelper().forceSwappingContentViews();
|
| - }
|
| -
|
| - if (!mFocused) {
|
| - mGestureDetector.onTouchEvent(event);
|
| - return true;
|
| - }
|
| -
|
| - if (event.getAction() == MotionEvent.ACTION_DOWN && currentTab != null) {
|
| - // Make sure to hide the current ContentView ActionBar.
|
| - ContentViewCore viewCore = currentTab.getContentViewCore();
|
| - if (viewCore != null) viewCore.hideSelectActionMode();
|
| - }
|
| -
|
| - return super.onTouchEvent(event);
|
| - }
|
| -
|
| - @Override
|
| - public boolean bringPointIntoView(int offset) {
|
| - if (mDisableTextScrollingFromAutocomplete) return false;
|
| - return super.bringPointIntoView(offset);
|
| - }
|
| -
|
| - @Override
|
| - public boolean onPreDraw() {
|
| - boolean retVal = super.onPreDraw();
|
| - if (mDisableTextScrollingFromAutocomplete) {
|
| - // super.onPreDraw will put the selection at the end of the text selection, but
|
| - // in the case of autocomplete we want the last typed character to be shown, which
|
| - // is the start of selection.
|
| - mDisableTextScrollingFromAutocomplete = false;
|
| - bringPointIntoView(getSelectionStart());
|
| - retVal = true;
|
| - }
|
| - return retVal;
|
| - }
|
| -
|
| - @Override
|
| - public void onDraw(Canvas canvas) {
|
| - super.onDraw(canvas);
|
| -
|
| - if (!mFirstDrawComplete) {
|
| - mFirstDrawComplete = true;
|
| -
|
| - // We have now avoided the first draw problem (see the comment in
|
| - // the constructor) so we want to make the URL bar focusable so that
|
| - // touches etc. activate it.
|
| - setFocusable(true);
|
| - setFocusableInTouchMode(true);
|
| -
|
| - // The URL bar will now react correctly to a focus change event
|
| - if (mOmniboxLivenessListener != null) mOmniboxLivenessListener.onOmniboxInteractive();
|
| - }
|
| -
|
| - // Notify listeners if the URL's direction has changed.
|
| - updateUrlDirection();
|
| - }
|
| -
|
| - /**
|
| - * If the direction of the URL has changed, update mUrlDirection and notify the
|
| - * UrlDirectionListeners.
|
| - */
|
| - private void updateUrlDirection() {
|
| - Layout layout = getLayout();
|
| - if (layout == null) return;
|
| -
|
| - int urlDirection;
|
| - if (length() == 0) {
|
| - urlDirection = LAYOUT_DIRECTION_LOCALE;
|
| - } else if (layout.getParagraphDirection(0) == Layout.DIR_LEFT_TO_RIGHT) {
|
| - urlDirection = LAYOUT_DIRECTION_LTR;
|
| - } else {
|
| - urlDirection = LAYOUT_DIRECTION_RTL;
|
| - }
|
| -
|
| - if (urlDirection != mUrlDirection) {
|
| - mUrlDirection = urlDirection;
|
| - if (mUrlDirectionListener != null) {
|
| - mUrlDirectionListener.onUrlDirectionChanged(urlDirection);
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @return The text direction of the URL, e.g. LAYOUT_DIRECTION_LTR.
|
| - */
|
| - public int getUrlDirection() {
|
| - return mUrlDirection;
|
| - }
|
| -
|
| - /**
|
| - * Sets the listener for changes in the url bar's layout direction. Also calls
|
| - * onUrlDirectionChanged() immediately on the listener.
|
| - *
|
| - * @param listener The UrlDirectionListener to receive callbacks when the url direction changes,
|
| - * or null to unregister any previously registered listener.
|
| - */
|
| - public void setUrlDirectionListener(UrlDirectionListener listener) {
|
| - mUrlDirectionListener = listener;
|
| - if (mUrlDirectionListener != null) {
|
| - mUrlDirectionListener.onUrlDirectionChanged(mUrlDirection);
|
| - }
|
| - }
|
| -
|
| - void setLocationBarTextWatcher(TextWatcher locationBarTextWatcher) {
|
| - mLocationBarTextWatcher = locationBarTextWatcher;
|
| - }
|
| -
|
| - /**
|
| - * Set the url delegate to handle communication from the {@link UrlBar} to the rest of the UI.
|
| - * @param delegate The {@link UrlBarDelegate} to be used.
|
| - */
|
| - public void setDelegate(UrlBarDelegate delegate) {
|
| - mUrlBarDelegate = delegate;
|
| - }
|
| -
|
| - /**
|
| - * Set {@link OmniboxLivenessListener} to be used for receiving interaction related messages
|
| - * during startup.
|
| - * @param listener The listener to use for sending the messages.
|
| - */
|
| - @VisibleForTesting
|
| - public void setOmniboxLivenessListener(OmniboxLivenessListener listener) {
|
| - mOmniboxLivenessListener = listener;
|
| - }
|
| -
|
| - /**
|
| - * Signal {@link OmniboxLivenessListener} that the omnibox is completely operational now.
|
| - */
|
| - @VisibleForTesting
|
| - public void onOmniboxFullyFunctional() {
|
| - if (mOmniboxLivenessListener != null) mOmniboxLivenessListener.onOmniboxFullyFunctional();
|
| - }
|
| -
|
| - @Override
|
| - public boolean onTextContextMenuItem(int id) {
|
| - if (id == android.R.id.paste) {
|
| - ClipboardManager clipboard = (ClipboardManager) getContext()
|
| - .getSystemService(Context.CLIPBOARD_SERVICE);
|
| - ClipData clipData = clipboard.getPrimaryClip();
|
| - if (clipData != null) {
|
| - StringBuilder builder = new StringBuilder();
|
| - for (int i = 0; i < clipData.getItemCount(); i++) {
|
| - builder.append(clipData.getItemAt(i).coerceToText(getContext()));
|
| - }
|
| - String pasteString = OmniboxViewUtil.sanitizeTextForPaste(builder.toString());
|
| -
|
| - int min = 0;
|
| - int max = getText().length();
|
| -
|
| - if (isFocused()) {
|
| - final int selStart = getSelectionStart();
|
| - final int selEnd = getSelectionEnd();
|
| -
|
| - min = Math.max(0, Math.min(selStart, selEnd));
|
| - max = Math.max(0, Math.max(selStart, selEnd));
|
| - }
|
| -
|
| - Selection.setSelection(getText(), max);
|
| - getText().replace(min, max, pasteString);
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - if (mOriginalUrlLocation == null || mFormattedUrlLocation == null) {
|
| - return super.onTextContextMenuItem(id);
|
| - }
|
| -
|
| - int selectedStartIndex = getSelectionStart();
|
| - int selectedEndIndex = getSelectionEnd();
|
| -
|
| - // If we are copying/cutting the full previously formatted URL, reset the URL
|
| - // text before initiating the TextViews handling of the context menu.
|
| - String currentText = getText().toString();
|
| - if (selectedStartIndex == 0
|
| - && (id == android.R.id.cut || id == android.R.id.copy)
|
| - && currentText.startsWith(mFormattedUrlLocation)
|
| - && selectedEndIndex >= mFormattedUrlLocation.length()) {
|
| - String newText = mOriginalUrlLocation
|
| - + currentText.substring(mFormattedUrlLocation.length());
|
| - selectedEndIndex = selectedEndIndex - mFormattedUrlLocation.length()
|
| - + mOriginalUrlLocation.length();
|
| - mUrlBarDelegate.setIgnoreURLBarModification(true);
|
| - setText(newText);
|
| - setSelection(0, selectedEndIndex);
|
| - boolean retVal = super.onTextContextMenuItem(id);
|
| - if (getText().toString().equals(newText)) {
|
| - setText(currentText);
|
| - setSelection(getText().length());
|
| - }
|
| - mUrlBarDelegate.setIgnoreURLBarModification(false);
|
| - return retVal;
|
| - }
|
| - return super.onTextContextMenuItem(id);
|
| - }
|
| -
|
| - /**
|
| - * Sets the text content of the URL bar.
|
| - *
|
| - * @param url The original URL (or generic text) that can be used for copy/cut/paste.
|
| - * @param formattedUrl Formatted URL for user display. Null if there isn't one.
|
| - * @return Whether the visible text has changed.
|
| - */
|
| - public boolean setUrl(String url, String formattedUrl) {
|
| - if (!TextUtils.isEmpty(formattedUrl)) {
|
| - try {
|
| - URL javaUrl = new URL(url);
|
| - mFormattedUrlLocation =
|
| - getUrlContentsPrePath(formattedUrl, javaUrl.getHost());
|
| - mOriginalUrlLocation =
|
| - getUrlContentsPrePath(url, javaUrl.getHost());
|
| - } catch (MalformedURLException mue) {
|
| - mOriginalUrlLocation = null;
|
| - mFormattedUrlLocation = null;
|
| - }
|
| - } else {
|
| - mOriginalUrlLocation = null;
|
| - mFormattedUrlLocation = null;
|
| - formattedUrl = url;
|
| - }
|
| -
|
| - Editable previousText = getEditableText();
|
| - setText(formattedUrl);
|
| -
|
| - if (!isFocused()) scrollToTLD();
|
| -
|
| - return !TextUtils.equals(previousText, getEditableText());
|
| - }
|
| -
|
| - /**
|
| - * Autocompletes the text on the url bar and selects the text that was not entered by the
|
| - * user. Using append() instead of setText() to preserve the soft-keyboard layout.
|
| - * @param userText user The text entered by the user.
|
| - * @param inlineAutocompleteText The suggested autocompletion for the user's text.
|
| - */
|
| - public void setAutocompleteText(CharSequence userText, CharSequence inlineAutocompleteText) {
|
| - boolean emptyAutocomplete = TextUtils.isEmpty(inlineAutocompleteText);
|
| -
|
| - if (!emptyAutocomplete) mDisableTextScrollingFromAutocomplete = true;
|
| -
|
| - int autocompleteIndex = userText.length();
|
| -
|
| - String previousText = getQueryText();
|
| - CharSequence newText = TextUtils.concat(userText, inlineAutocompleteText);
|
| -
|
| - mUrlBarDelegate.setIgnoreURLBarModification(true);
|
| - mDisableTextAccessibilityEvents = true;
|
| -
|
| - if (!TextUtils.equals(previousText, newText)) {
|
| - // The previous text may also have included autocomplete text, so we only
|
| - // append the new autocomplete text that has changed.
|
| - if (TextUtils.indexOf(newText, previousText) == 0) {
|
| - append(newText.subSequence(previousText.length(), newText.length()));
|
| - } else {
|
| - setUrl(newText.toString(), null);
|
| - }
|
| - }
|
| -
|
| - if (getSelectionStart() != autocompleteIndex
|
| - || getSelectionEnd() != getText().length()) {
|
| - setSelection(autocompleteIndex, getText().length());
|
| -
|
| - if (inlineAutocompleteText.length() != 0) {
|
| - // Sending a TYPE_VIEW_TEXT_SELECTION_CHANGED accessibility event causes the
|
| - // previous TYPE_VIEW_TEXT_CHANGED event to be swallowed. As a result the user
|
| - // hears the autocomplete text but *not* the text they typed. Instead we send a
|
| - // TYPE_ANNOUNCEMENT event, which doesn't swallow the text-changed event.
|
| - announceForAccessibility(inlineAutocompleteText);
|
| - }
|
| - }
|
| -
|
| - if (emptyAutocomplete) {
|
| - mAutocompleteSpan.clearSpan();
|
| - } else {
|
| - mAutocompleteSpan.setSpan(userText, inlineAutocompleteText);
|
| - }
|
| -
|
| - mUrlBarDelegate.setIgnoreURLBarModification(false);
|
| - mDisableTextAccessibilityEvents = false;
|
| - }
|
| -
|
| - /**
|
| - * Overrides the text announced when focusing on the field for accessibility. This value will
|
| - * be cleared automatically when the text content changes for this view.
|
| - * @param accessibilityOverride The text to be announced instead of the current text value
|
| - * (or null if the text content should be read).
|
| - */
|
| - public void setAccessibilityTextOverride(String accessibilityOverride) {
|
| - mAccessibilityTextOverride = accessibilityOverride;
|
| - }
|
| -
|
| - private void scrollToTLD() {
|
| - Editable url = getText();
|
| - if (url == null || url.length() < 1) return;
|
| - String urlString = url.toString();
|
| - URL javaUrl;
|
| - try {
|
| - javaUrl = new URL(urlString);
|
| - } catch (MalformedURLException mue) {
|
| - return;
|
| - }
|
| - String host = javaUrl.getHost();
|
| - if (host == null || host.isEmpty()) return;
|
| - int hostStart = urlString.indexOf(host);
|
| - int hostEnd = hostStart + host.length();
|
| - setSelection(hostEnd);
|
| - }
|
| -
|
| - @Override
|
| - public void setText(CharSequence text, BufferType type) {
|
| - mDisableTextScrollingFromAutocomplete = false;
|
| -
|
| - // Avoid setting the same text to the URL bar as it will mess up the scroll/cursor
|
| - // position.
|
| - // Setting the text is also quite expensive, so only do it when the text has changed
|
| - // (since we apply spans when the URL is not focused, we only optimize this when the
|
| - // URL is being edited).
|
| - if (!TextUtils.equals(getEditableText(), text)) {
|
| - super.setText(text, type);
|
| - mAccessibilityTextOverride = null;
|
| - }
|
| -
|
| - // Verify the autocomplete is still valid after the text change.
|
| - if (mAutocompleteSpan != null
|
| - && mAutocompleteSpan.mUserText != null
|
| - && mAutocompleteSpan.mAutocompleteText != null) {
|
| - if (getText().getSpanStart(mAutocompleteSpan) < 0) {
|
| - mAutocompleteSpan.clearSpan();
|
| - } else {
|
| - Editable editableText = getEditableText();
|
| - CharSequence previousUserText = mAutocompleteSpan.mUserText;
|
| - CharSequence previousAutocompleteText = mAutocompleteSpan.mAutocompleteText;
|
| - if (editableText.length()
|
| - < (previousUserText.length() + previousAutocompleteText.length())) {
|
| - mAutocompleteSpan.clearSpan();
|
| - } else if (TextUtils.indexOf(getText(), previousUserText) != 0
|
| - || TextUtils.indexOf(getText(), previousAutocompleteText)
|
| - != previousUserText.length()) {
|
| - mAutocompleteSpan.clearSpan();
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Returns the portion of the URL that precedes the path/query section of the URL.
|
| - *
|
| - * @param url The url to be used to find the preceding portion.
|
| - * @param host The host to be located in the URL to determine the location of the path.
|
| - * @return The URL contents that precede the path (or the passed in URL if the host is
|
| - * not found).
|
| - */
|
| - private static String getUrlContentsPrePath(String url, String host) {
|
| - String urlPrePath = url;
|
| - int hostIndex = url.indexOf(host);
|
| - if (hostIndex >= 0) {
|
| - int pathIndex = url.indexOf('/', hostIndex);
|
| - if (pathIndex > 0) {
|
| - urlPrePath = url.substring(0, pathIndex);
|
| - } else {
|
| - urlPrePath = url;
|
| - }
|
| - }
|
| - return urlPrePath;
|
| - }
|
| -
|
| - @Override
|
| - public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
|
| - if (mDisableTextAccessibilityEvents) {
|
| - if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
|
| - || event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
|
| - return;
|
| - }
|
| - }
|
| - super.sendAccessibilityEventUnchecked(event);
|
| - }
|
| -
|
| - @Override
|
| - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
| - super.onInitializeAccessibilityNodeInfo(info);
|
| -
|
| - if (mAccessibilityTextOverride != null) {
|
| - info.setText(mAccessibilityTextOverride);
|
| - }
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - InputConnectionWrapper mInputConnection = new InputConnectionWrapper(null, true) {
|
| - private final char[] mTempSelectionChar = new char[1];
|
| -
|
| - @Override
|
| - public boolean commitText(CharSequence text, int newCursorPosition) {
|
| - Editable currentText = getText();
|
| - if (currentText == null) return super.commitText(text, newCursorPosition);
|
| -
|
| - int selectionStart = Selection.getSelectionStart(currentText);
|
| - int selectionEnd = Selection.getSelectionEnd(currentText);
|
| - int autocompleteIndex = currentText.getSpanStart(mAutocompleteSpan);
|
| - // If the text being committed is a single character that matches the next character
|
| - // in the selection (assumed to be the autocomplete text), we only move the text
|
| - // selection instead clearing the autocomplete text causing flickering as the
|
| - // autocomplete text will appear once the next suggestions are received.
|
| - //
|
| - // To be confident that the selection is an autocomplete, we ensure the selection
|
| - // is at least one character and the end of the selection is the end of the
|
| - // currently entered text.
|
| - if (newCursorPosition == 1 && selectionStart > 0 && selectionStart != selectionEnd
|
| - && selectionEnd >= currentText.length()
|
| - && autocompleteIndex == selectionStart
|
| - && text.length() == 1) {
|
| - currentText.getChars(selectionStart, selectionStart + 1, mTempSelectionChar, 0);
|
| - if (mTempSelectionChar[0] == text.charAt(0)) {
|
| -
|
| - // Since the text isn't changing, TalkBack won't read out the typed characters.
|
| - // To work around this, explicitly send an accessibility event. crbug.com/416595
|
| - if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()) {
|
| - AccessibilityEvent event = AccessibilityEvent.obtain(
|
| - AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
|
| - event.setFromIndex(selectionStart);
|
| - event.setRemovedCount(0);
|
| - event.setAddedCount(1);
|
| - event.setBeforeText(currentText.toString().substring(0, selectionStart));
|
| - sendAccessibilityEventUnchecked(event);
|
| - }
|
| -
|
| - if (mLocationBarTextWatcher != null) {
|
| - mLocationBarTextWatcher.beforeTextChanged(currentText, 0, 0, 0);
|
| - }
|
| - setAutocompleteText(
|
| - currentText.subSequence(0, selectionStart + 1),
|
| - currentText.subSequence(selectionStart + 1, selectionEnd));
|
| - if (mLocationBarTextWatcher != null) {
|
| - mLocationBarTextWatcher.afterTextChanged(currentText);
|
| - }
|
| - return true;
|
| - }
|
| - }
|
| - return super.commitText(text, newCursorPosition);
|
| - }
|
| -
|
| - @Override
|
| - public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
| - Editable currentText = getText();
|
| - int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan);
|
| - if (autoCompleteSpanStart >= 0) {
|
| - int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText);
|
| -
|
| - // On certain device/keyboard combinations, the composing regions are specified
|
| - // with a noticeable delay after the initial character is typed, and in certain
|
| - // circumstances it does not check that the current state of the text matches the
|
| - // expectations of it's composing region.
|
| - // For example, you can be typing:
|
| - // chrome://f
|
| - // Chrome will autocomplete to:
|
| - // chrome://f[lags]
|
| - // And after the autocomplete has been set, the keyboard will set the composing
|
| - // region to the last character and it assumes it is 'f' as it was the last
|
| - // character the keyboard sent. If we commit this composition, the text will
|
| - // look like:
|
| - // chrome://flag[f]
|
| - // And if we use the autocomplete clearing logic below, it will look like:
|
| - // chrome://f[f]
|
| - // To work around this, we see if the composition matches all the characters prior
|
| - // to the autocomplete and just readjust the composing region to be that subset.
|
| - //
|
| - // See crbug.com/366732
|
| - if (composingEnd == currentText.length()
|
| - && autoCompleteSpanStart >= text.length()
|
| - && TextUtils.equals(
|
| - currentText.subSequence(
|
| - autoCompleteSpanStart - text.length(),
|
| - autoCompleteSpanStart),
|
| - text)) {
|
| - setComposingRegion(
|
| - autoCompleteSpanStart - text.length(), autoCompleteSpanStart);
|
| - }
|
| -
|
| - // Once composing text is being modified, the autocomplete text has been accepted
|
| - // or has to be deleted.
|
| - mAutocompleteSpan.clearSpan();
|
| - Selection.setSelection(currentText, autoCompleteSpanStart);
|
| - currentText.delete(autoCompleteSpanStart, currentText.length());
|
| - }
|
| - return super.setComposingText(text, newCursorPosition);
|
| - }
|
| - };
|
| -
|
| - @Override
|
| - public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
| - mInputConnection.setTarget(super.onCreateInputConnection(outAttrs));
|
| - return mInputConnection;
|
| - }
|
| -
|
| - /**
|
| - * Emphasize the TLD and second domain of the URL.
|
| - */
|
| - public void emphasizeUrl() {
|
| - Editable url = getText();
|
| - if (OmniboxUrlEmphasizer.hasEmphasisSpans(url) || hasFocus()) {
|
| - return;
|
| - }
|
| -
|
| - if (url.length() < 1) {
|
| - return;
|
| - }
|
| -
|
| - if (mUrlBarDelegate.showingOriginalUrlForPreview()) {
|
| - // We will make the whole url as greyed out(Tailing url color). This is the UI
|
| - // treatment we show to indicate that we are showing original url for preview page.
|
| - OmniboxUrlEmphasizer.greyOutUrl(url, getResources(), mUseDarkColors);
|
| - return;
|
| - }
|
| -
|
| - // We retrieve the domain and registry from the full URL (the url bar shows a simplified
|
| - // version of the URL).
|
| - ChromeTab currentTab = mUrlBarDelegate.getCurrentTab();
|
| - if (currentTab == null || currentTab.getProfile() == null) return;
|
| -
|
| - boolean isInternalPage = false;
|
| - try {
|
| - String tabUrl = currentTab.getUrl();
|
| - isInternalPage = UrlUtilities.isInternalScheme(new URI(tabUrl));
|
| - } catch (URISyntaxException e) {
|
| - // Ignore as this only is for applying color
|
| - }
|
| -
|
| - OmniboxUrlEmphasizer.emphasizeUrl(url, getResources(), currentTab.getProfile(),
|
| - currentTab.getSecurityLevel(), isInternalPage,
|
| - mUseDarkColors, mUrlBarDelegate.shouldEmphasizeHttpsScheme());
|
| - }
|
| -
|
| - /**
|
| - * Reset the modifications done to emphasize the TLD and second domain of the URL.
|
| - */
|
| - public void deEmphasizeUrl() {
|
| - OmniboxUrlEmphasizer.deEmphasizeUrl(getText());
|
| - }
|
| -
|
| - /**
|
| - * Simple span used for tracking the current autocomplete state.
|
| - */
|
| - private class AutocompleteSpan {
|
| - private CharSequence mUserText;
|
| - private CharSequence mAutocompleteText;
|
| -
|
| - /**
|
| - * Adds the span to the current text.
|
| - * @param userText The user entered text.
|
| - * @param autocompleteText The autocomplete text being appended.
|
| - */
|
| - public void setSpan(CharSequence userText, CharSequence autocompleteText) {
|
| - Editable text = getText();
|
| - text.removeSpan(this);
|
| - mAutocompleteText = autocompleteText;
|
| - mUserText = userText;
|
| - text.setSpan(
|
| - this,
|
| - userText.length(),
|
| - text.length(),
|
| - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
| - }
|
| -
|
| - /** Removes this span from the current text and clears the internal state. */
|
| - public void clearSpan() {
|
| - getText().removeSpan(this);
|
| - mAutocompleteText = null;
|
| - mUserText = null;
|
| - }
|
| - }
|
| -}
|
|
|