blob: 28070f75224bf68c0bac2d2eeea5dd8ac46ad24e [file] [log] [blame]
// Copyright (c) 2012 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.
#ifndef CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_
#define CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_
#include <stddef.h>
#include <memory>
#include <set>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/scoped_observation.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h"
#include "components/omnibox/browser/omnibox_view.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/search_engines/template_url_service.h"
#include "components/search_engines/template_url_service_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/window_open_disposition.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/gfx/animation/multi_animation.h"
#include "ui/gfx/range/range.h"
#include "ui/views/animation/animation_delegate_views.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/metadata/metadata_header_macros.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ui/base/ime/chromeos/input_method_manager.h"
#endif
class LocationBarView;
class OmniboxClient;
class OmniboxPopupContentsView;
namespace content {
struct FocusedNodeDetails;
class WebContents;
} // namespace content
namespace gfx {
class RenderText;
} // namespace gfx
namespace ui {
class OSExchangeData;
} // namespace ui
// Views-implementation of OmniboxView.
class OmniboxViewViews : public OmniboxView,
public views::Textfield,
#if BUILDFLAG(IS_CHROMEOS_ASH)
public chromeos::input_method::InputMethodManager::
CandidateWindowObserver,
#endif
public views::TextfieldController,
public ui::CompositorObserver,
public TemplateURLServiceObserver,
public content::WebContentsObserver {
public:
METADATA_HEADER(OmniboxViewViews);
// Max width of the gradient mask used to smooth ElideAnimation edges.
static const int kSmoothingGradientMaxWidth = 15;
OmniboxViewViews(OmniboxEditController* controller,
std::unique_ptr<OmniboxClient> client,
bool popup_window_mode,
LocationBarView* location_bar,
const gfx::FontList& font_list);
OmniboxViewViews(const OmniboxViewViews&) = delete;
OmniboxViewViews& operator=(const OmniboxViewViews&) = delete;
~OmniboxViewViews() override;
// Initialize, create the underlying views, etc.
void Init();
// Exposes the RenderText for tests.
#if defined(UNIT_TEST)
gfx::RenderText* GetRenderText() {
return views::Textfield::GetRenderText();
}
#endif
// For use when switching tabs, this saves the current state onto the tab so
// that it can be restored during a later call to Update().
void SaveStateToTab(content::WebContents* tab);
// Called when the window's active tab changes.
void OnTabChanged(content::WebContents* web_contents);
// Called to clear the saved state for |web_contents|.
void ResetTabState(content::WebContents* web_contents);
// Installs the placeholder text with the name of the current default search
// provider. For example, if Google is the default search provider, this shows
// "Search Google or type a URL" when the Omnibox is empty and unfocused.
void InstallPlaceholderText();
// Indicates if the cursor is at the end of the input. Requires that both
// ends of the selection reside there.
bool GetSelectionAtEnd() const;
// Returns the width in pixels needed to display the current text. The
// returned value includes margins.
int GetTextWidth() const;
// Returns the width in pixels needed to display the current text unelided.
int GetUnelidedTextWidth() const;
// Returns the omnibox's width in pixels.
int GetWidth() const;
// OmniboxView:
void EmphasizeURLComponents() override;
void Update() override;
std::u16string GetText() const override;
using OmniboxView::SetUserText;
void SetUserText(const std::u16string& text, bool update_popup) override;
void SetWindowTextAndCaretPos(const std::u16string& text,
size_t caret_pos,
bool update_popup,
bool notify_text_changed) override;
void SetAdditionalText(const std::u16string& additional_text) override;
void EnterKeywordModeForDefaultSearchProvider() override;
bool IsSelectAll() const override;
void GetSelectionBounds(std::u16string::size_type* start,
std::u16string::size_type* end) const override;
size_t GetAllSelectionsLength() const override;
void SelectAll(bool reversed) override;
void RevertAll() override;
void SetFocus(bool is_user_initiated) override;
bool IsImeComposing() const override;
gfx::NativeView GetRelativeWindowForPopup() const override;
bool IsImeShowingPopup() const override;
// views::Textfield:
gfx::Size GetMinimumSize() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnPaint(gfx::Canvas* canvas) override;
void ExecuteCommand(int command_id, int event_flags) override;
void OnInputMethodChanged() override;
void AddedToWidget() override;
void RemovedFromWidget() override;
std::u16string GetLabelForCommandId(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override;
// content::WebContentsObserver:
void DidStartNavigation(content::NavigationHandle* navigation) override;
void DidFinishNavigation(content::NavigationHandle* navigation) override;
void DidGetUserInteraction(const blink::WebInputEvent& event) override;
void OnFocusChangedInPage(content::FocusedNodeDetails* details) override;
// For testing only.
OmniboxPopupContentsView* GetPopupContentsViewForTesting() const {
return popup_view_.get();
}
protected:
// Animates the URL to a given range of text, which could be a substring or
// superstring of what's currently displayed. An elision animation hides the
// path (and optionally subdomains) by narrowing the bounds of each side of
// the URL while also shifting the text to remain aligned with the leading
// edge of the display area. While the bounds change, the text being elided
// can be simultaneously faded to transparent to make the transition smoother.
// An unelision animation is the reverse.
//
// Animation is used for elision when the elision is in response to a user
// interaction and we want to draw attention to where the URL is going and how
// it can be retrieved. Depending on field trial configurations, this could be
// after the user interacts with the page (where we want to hide the full URL
// but hint that it can be brought back by interacting with the omnibox),
// and/or when the user hovers over the omnibox. In contrast,
// ElideToSimplifiedDomain() and UnelideFromSimplifiedDomain() instantly
// elide/unelide and are used when we want to elide/unelide without drawing
// the user's attention (for example, on a same-document navigation where we
// want the URL to remain simplified if it was simplified before the
// navigation).
//
// This class is declared here for testing.
class ElideAnimation : public views::AnimationDelegateViews {
public:
ElideAnimation(OmniboxViewViews* view, gfx::RenderText* render_text);
~ElideAnimation() override;
// Begin the elision animation targeting |elide_to_bounds|, after a delay of
// |delay_ms|. |ranges_surrounding_simplified_domain| should contain 1 or 2
// ranges surrounding the simplified domain part, they should be in order
// (i.e. the range on the left should be the first element). If only one
// element is set, it will be assumed we are only eliding from the left
// side. Those ranges will be faded from |starting_color| to
// |ending_color|.
void Start(
const gfx::Range& elide_to_bounds,
uint32_t delay_ms,
const std::vector<gfx::Range>& ranges_surrounding_simplified_domain,
SkColor starting_color,
SkColor ending_color);
void Stop();
// Returns true if the animation is currently running.
bool IsAnimating();
// Returns the bounds to which the animation is eliding, as passed in to
// Start().
const gfx::Range& GetElideToBounds() const;
// Returns the current color applied to each of the ranges in
// |ranges_surrounding_simplified_domain| passed in to Start(), if the
// animation is running or has completed running.
// Returns gfx::kPlaceholderColor if the animation has not starting
// running yet.
SkColor GetCurrentColor() const;
gfx::MultiAnimation* GetAnimationForTesting();
int GetCurrentOffsetForTesting() { return current_offset_; }
// views::AnimationDelegateViews:
void AnimationProgressed(const gfx::Animation* animation) override;
private:
// Non-owning pointers. |view_| and |render_text_| must always outlive this
// class.
OmniboxViewViews* view_;
gfx::RenderText* render_text_;
// The target bounds passed in to Start().
gfx::Range elide_to_bounds_;
// The desired end state: the display rect that we are eliding or uneliding
// to.
gfx::Rect elide_to_rect_;
// The starting display rect from which we are eliding or uneliding.
gfx::Rect elide_from_rect_;
// The display rect surrounding the simplified domain.
gfx::Rect simplified_domain_bounds_;
// The starting and ending display offsets for |render_text_|.
int starting_display_offset_ = 0;
int ending_display_offset_ = 0;
// The current offset, exposed for testing.
int current_offset_;
// Holds the ranges surrounding the simplified domain part. As the animation
// runs, each range fades from |starting_color_| to |ending_color_|.
std::vector<gfx::Range> ranges_surrounding_simplified_domain_;
SkColor starting_color_;
SkColor ending_color_;
// The underlying animation. We use a MultiAnimation to implement the
// |delay_ms| delay passed into Start(). When this delay is nonzero, the
// first part of the animation is a zero tween of |delay_ms| length.
std::unique_ptr<gfx::MultiAnimation> animation_;
};
ElideAnimation* GetHoverElideOrUnelideAnimationForTesting();
ElideAnimation* GetElideAfterInteractionAnimationForTesting();
// views::Textfield:
void OnThemeChanged() override;
bool IsDropCursorForInsertion() const override;
// Applies the given |color| to |range|. This is a wrapper method around
// Textfield::ApplyColor that tests can override.
virtual void ApplyColor(SkColor color, const gfx::Range& range);
private:
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsTest,
RendererInitiatedFocusPreservesCursorWhenStartingFocused);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExit);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExitIDN);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, PrivateRegistry);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
BrowserInitiatedNavigation);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
UserInteractionAndHover);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
MouseClick);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
FocusingEditableNode);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
BoundsChanged);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, BoundsChanged);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverHistogram);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
CancellingAnimationDoesNotCrash);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
SchemeAndTrivialSubdomainElision);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
SimplifiedDomainElisionWithNarrowOmnibox);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
SimplifiedDomainElisionWithNarrowOmnibox);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
HideOnInteractionAfterFocusAndBlur);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
URLPositionWithHideOnInteraction);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, AfterBlur);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
PathChangeDuringAnimation);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
VerticalAndHorizontalPosition);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
NoStaleGradientMask);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest, ModifierKeys);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
ErrorPageNavigation);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
SameDocNavigations);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
SameDocNavigationDuringAnimation);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest, GradientMask);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
GradientMaskResetAfterStop);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
UserInteractionDuringAnimation);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
SubframeNavigations);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
AlwaysShowFullURLs);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
AlwaysShowFullURLs);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsRevealOnHoverAndMaybeHideOnInteractionTest,
UnsetAlwaysShowFullURLs);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
RegistrableDomainRepeated);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
TabChangeWhenNotEligibleForEliding);
FRIEND_TEST_ALL_PREFIXES(OmniboxPopupContentsViewTest,
EmitAccessibilityEvents);
// TODO(tommycli): Remove the rest of these friends after porting these
// browser tests to unit tests.
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, CloseOmniboxPopupOnTextDrag);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, FriendlyAccessibleLabel);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, DoNotNavigateOnDrop);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest,
ElideAnimationDoesntStartIfNoVisibleChange);
enum class UnelisionGesture {
HOME_KEY_PRESSED,
MOUSE_RELEASE,
OTHER,
};
// Update the field with |text| and set the selection. |ranges| should not be
// empty; even text with no selections must have at least 1 empty range in
// |ranges| to indicate the cursor position.
void SetTextAndSelectedRanges(const std::u16string& text,
const std::vector<gfx::Range>& ranges);
void SetSelectedRanges(const std::vector<gfx::Range>& ranges);
// Returns the selected text.
std::u16string GetSelectedText() const;
// Paste text from the clipboard into the omnibox.
// Textfields implementation of Paste() pastes the contents of the clipboard
// as is. We want to strip whitespace and other things (see GetClipboardText()
// for details). The function invokes OnBefore/AfterPossibleChange() as
// necessary.
void OnOmniboxPaste();
// Handle keyword hint tab-to-search and tabbing through dropdown results.
bool HandleEarlyTabActions(const ui::KeyEvent& event);
void ClearAccessibilityLabel();
void SetAccessibilityLabel(const std::u16string& display_text,
const AutocompleteMatch& match,
bool notify_text_changed) override;
// Returns true if the user text was updated with the full URL (without
// steady-state elisions). |gesture| is the user gesture causing unelision.
bool UnapplySteadyStateElisions(UnelisionGesture gesture);
#if defined(OS_MAC)
void AnnounceFriendlySuggestionText();
#endif
// OmniboxView:
void SetCaretPos(size_t caret_pos) override;
void UpdatePopup() override;
void ApplyCaretVisibility() override;
void OnTemporaryTextMaybeChanged(const std::u16string& display_text,
const AutocompleteMatch& match,
bool save_original_selection,
bool notify_text_changed) override;
void OnInlineAutocompleteTextMaybeChanged(const std::u16string& display_text,
std::vector<gfx::Range> selections,
size_t user_text_length) override;
void OnInlineAutocompleteTextCleared() override;
void OnRevertTemporaryText(const std::u16string& display_text,
const AutocompleteMatch& match) override;
void OnBeforePossibleChange() override;
bool OnAfterPossibleChange(bool allow_keyword_ui_change) override;
gfx::NativeView GetNativeView() const override;
void ShowVirtualKeyboardIfEnabled() override;
void HideImeIfNeeded() override;
int GetOmniboxTextLength() const override;
void SetEmphasis(bool emphasize, const gfx::Range& range) override;
void UpdateSchemeStyle(const gfx::Range& range) override;
// views::View
void OnMouseMoved(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
// views::Textfield:
bool IsItemForCommandIdDynamic(int command_id) const override;
void OnGestureEvent(ui::GestureEvent* event) override;
void AboutToRequestFocusFromTabTraversal(bool reverse) override;
bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
bool HandleAccessibleAction(const ui::AXActionData& action_data) override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void OnFocus() override;
void OnBlur() override;
std::u16string GetSelectionClipboardText() const override;
void DoInsertChar(char16_t ch) override;
bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
void ExecuteTextEditCommand(ui::TextEditCommand command) override;
bool ShouldShowPlaceholderText() const override;
// chromeos::input_method::InputMethodManager::CandidateWindowObserver:
#if BUILDFLAG(IS_CHROMEOS_ASH)
void CandidateWindowOpened(
chromeos::input_method::InputMethodManager* manager) override;
void CandidateWindowClosed(
chromeos::input_method::InputMethodManager* manager) override;
#endif
// views::TextfieldController:
void ContentsChanged(views::Textfield* sender,
const std::u16string& new_contents) override;
bool HandleKeyEvent(views::Textfield* sender,
const ui::KeyEvent& key_event) override;
void OnBeforeUserAction(views::Textfield* sender) override;
void OnAfterUserAction(views::Textfield* sender) override;
void OnAfterCutOrCopy(ui::ClipboardBuffer clipboard_buffer) override;
void OnWriteDragData(ui::OSExchangeData* data) override;
void OnGetDragOperationsForTextfield(int* drag_operations) override;
void AppendDropFormats(
int* formats,
std::set<ui::ClipboardFormatType>* format_types) override;
ui::mojom::DragOperation OnDrop(const ui::OSExchangeData& data) override;
void UpdateContextMenu(ui::SimpleMenuModel* menu_contents) override;
// ui::SimpleMenuModel::Delegate:
bool IsCommandIdChecked(int id) const override;
// ui::CompositorObserver:
void OnCompositingDidCommit(ui::Compositor* compositor) override;
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override;
void OnCompositingEnded(ui::Compositor* compositor) override;
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
// TemplateURLServiceObserver:
void OnTemplateURLServiceChanged() override;
// Permits launch of the external protocol handler after user actions in
// the omnibox. The handler needs to be informed that omnibox input should
// always be considered "user gesture-triggered", lest it always return BLOCK.
void PermitExternalProtocolHandler();
// Returns the gfx::Range of the simplified domain of the current URL, if
// there is one. The simplified domain could be either the registrable domain
// (if OmniboxFieldTrial::ElideToRegistrableDomain() is enabled) or the full
// hostname. |ranges_surrounding_simplified_domain| is an optional output
// parameter; if non-null, it will be populated with the ranges that do not
// contain the simplified domain.
gfx::Range GetSimplifiedDomainBounds(
std::vector<gfx::Range>* ranges_surrounding_simplified_domain);
// Returns true if the currently displayed URL is eligible for elision to a
// simplified domain. This takes into account the omnibox's current state
// (e.g. the URL shouldn't be elided if the user is currently editing it) as
// well as properties of the current text (e.g. extension URLs or non-URLs
// shouldn't be elided because they may not have simplified domains; localhost
// URLs shouldn't be elided because they are used in development workflows
// where the full URL is useful).
//
// This method does NOT take field trials into account or the "Always show
// full URLs" option. Calling code should check field trial state and
// model()->ShouldPreventElision() if applicable.
bool GetURLEligibleForSimplifiedDomainEliding() const;
// When certain field trials are enabled, the URL is shown on page load
// and elided to a simplified domain when the user interacts with the page.
// This method resets back to the on-page-load state. That is, it unhides the
// URL (if currently hidden) and resets state so that the URL will show until
// user interaction. This is used on navigation and blur, when the URL should
// be shown but hidden on next user interaction.
void ResetToHideOnInteraction();
// Called when the "Always show full URLs" preference is toggled. Updates the
// state to elide to a simplified domain on user interaction and/or reveal the
// URL on hover, depending on field trial configuration.
//
// When the preference changes, we immediately elide/unelide instead of
// animating. Animating might look a little nicer, but this should be a
// relatively rare event so it's simpler to just immediately update the
// display.
void OnShouldPreventElisionChanged();
// Elides the URL to a simplified version of the domain with an animation.
// This should be called when a user interaction with the web contents
// triggers elision. Does nothing if the relevant field trial is disabled or
// the URL is not eligible for eliding.
void MaybeElideURLWithAnimationFromInteraction();
// The methods below elide to or unelide from a simplified version of the URL.
// Callers should ensure that the URL is valid before calling.
//
// These methods do not animate, but rather immediately elide/unelide. These
// methods are used when we don't want to draw the user's attention to the URL
// simplification -- for example, if the URL is already simplified and the
// user performs a same-document navigation, we want to keep the URL
// simplified without it appearing to be a change from the user's perspective.
// Elides the URL to a simplified version of the domain. This will be the
// registrable domain if OmniboxFieldTrial::ShouldElideToRegistrableDomain()
// is true; otherwise it is the hostname with trivial subdomains ("www.")
// elided. The scheme, path, and other components of the URL are hidden.
void ElideURL();
// Show the full URL, including scheme, all subdomains, and path.
void ShowFullURL();
// Shows the full URL and then elides http/https schemes and the
// "www." subdomain (if present) by setting the display rect to the width of
// the remaining URL and then setting the display offset to scroll the scheme
// and trivial subdomain offscreen.
void ShowFullURLWithoutSchemeAndTrivialSubdomain();
// Parses GetText() as a URL, trims trivial subdomains from it (if any and if
// applicable), and returns the result.
url::Component GetHostComponentAfterTrivialSubdomain() const;
// When true, the location bar view is read only and also is has a slightly
// different presentation (smaller font size). This is used for popups.
bool popup_window_mode_;
std::unique_ptr<OmniboxPopupContentsView> popup_view_;
// Animations are used to elide/unelide the path (and subdomains, if
// OmniboxFieldTrial::ShouldElideToRegistrableDomain() is true) under some
// field trial settings. These animations are created at different times
// depending on the field trial configuration, so don't assume they are
// non-null.
//
// These animations are used by different field trials as described below.
// This animation is used to unelide or elide the URL
// when the mouse hovers or exits the omnibox. The URL will unelide to the
// full URL or a partially elided version (with scheme and trivial subdomains
// elided) depending on whether the user has interacted with the page yet
// (when reveal-on-interaction is enabled).
std::unique_ptr<ElideAnimation> hover_elide_or_unelide_animation_;
// When ShouldHidePathQueryRefOnInteraction() is enabled, when a
// navigation finishes, we unelide the URL if it was a full cross-document
// navigation. Once the user interacts with the page, we create and run
// |elide_after_web_contents_interaction_animation_| to elide the URL. After
// the first user interaction,
// |elide_after_web_contents_interaction_animation_| doesn't run again until
// it's re-created after the next navigation. There are 2 separate animations
// (one for after-interaction and one hovering) so that the state of the
// after-interaction animation can be queried to know when the user has or has
// not already interacted with the page.
std::unique_ptr<ElideAnimation>
elide_after_web_contents_interaction_animation_;
// If set, rectangles will be drawn as gradient masks over the omnibox text.
// Used to smooth color transition when an ElideAnimation is animating.
gfx::Rect elide_animation_smoothing_rect_left_;
gfx::Rect elide_animation_smoothing_rect_right_;
// The time that the mouse begins hovering over the omnibox, used for
// recording metrics related to simplified domain field trials. Set in
// OnMouseMoved() and cleared when the mouse exits the hover.
base::Time hover_start_time_;
// A histogram is recorded for each continuous hover over the omnibox, ended
// by either focusing or exiting the mouse. This is set to true if the
// histogram was recorded due to the omnibox being focused, so that it won't
// be recorded again for the same continuous hover when the mouse exits.
bool recorded_hover_on_focus_ = false;
base::Clock* clock_;
// Selection persisted across temporary text changes, like popup suggestions.
std::vector<gfx::Range> saved_temporary_selection_;
// Holds the user's selection across focus changes. There is only a saved
// selection if this range IsValid().
std::vector<gfx::Range> saved_selection_for_focus_change_;
// Tracking state before and after a possible change.
State state_before_change_;
bool ime_composing_before_change_ = false;
// |location_bar_view_| can be NULL in tests.
LocationBarView* location_bar_view_;
#if BUILDFLAG(IS_CHROMEOS_ASH)
// True if the IME candidate window is open. When this is true, we want to
// avoid showing the popup. So far, the candidate window is detected only
// on Chrome OS.
bool ime_candidate_window_open_ = false;
#endif
// True if any mouse button is currently depressed.
bool is_mouse_pressed_ = false;
// Applies a minimum threshold to drag events after unelision. Because the
// text shifts after unelision, we don't want unintentional mouse drags to
// change the selection.
bool filter_drag_events_for_unelision_ = false;
// Should we select all the text when we see the mouse button get released?
// We select in response to a click that focuses the omnibox, but we defer
// until release, setting this variable back to false if we saw a drag, to
// allow the user to select just a portion of the text.
bool select_all_on_mouse_release_ = false;
// Indicates if we want to select all text in the omnibox when we get a
// GESTURE_TAP. We want to select all only when the textfield is not in focus
// and gets a tap. So we use this variable to remember focus state before tap.
bool select_all_on_gesture_tap_ = false;
// Whether the user should be notified if the clipboard is restricted.
bool show_rejection_ui_if_any_ = false;
// Keep track of the word that would be selected if URL is unelided between
// a single and double click. This is an edge case where the elided URL is
// selected. On the double click, unelision is performed in between the first
// and second clicks. This results in both the wrong word to be selected and
// the wrong selection length. For example, if example.com is shown and you
// try to double click on the "x", it unelides to https://example.com after
// the first click, resulting in "https" being selected.
size_t next_double_click_selection_len_ = 0;
size_t next_double_click_selection_offset_ = 0;
// The time of the first character insert operation that has not yet been
// painted. Used to measure omnibox responsiveness with a histogram.
base::TimeTicks insert_char_time_;
// The state machine for logging the Omnibox.CharTypedToRepaintLatency
// histogram.
enum {
NOT_ACTIVE, // Not currently tracking a char typed event.
CHAR_TYPED, // Character was typed.
ON_PAINT_CALLED, // Character was typed and OnPaint() called.
COMPOSITING_COMMIT, // Compositing was committed after OnPaint().
COMPOSITING_STARTED, // Compositing was started.
} latency_histogram_state_;
// The currently selected match, if any, with additional labelling text
// such as the document title and the type of search, for example:
// "Google https://google.com location from bookmark", or
// "cats are liquid search suggestion".
std::u16string friendly_suggestion_text_;
// The number of added labelling characters before editable text begins.
// For example, "Google https://google.com location from history",
// this is set to 7 (the length of "Google ").
int friendly_suggestion_text_prefix_length_;
base::ScopedObservation<ui::Compositor, ui::CompositorObserver>
scoped_compositor_observation_{this};
base::ScopedObservation<TemplateURLService, TemplateURLServiceObserver>
scoped_template_url_service_observation_{this};
// Send tab to self submenu.
std::unique_ptr<send_tab_to_self::SendTabToSelfSubMenuModel>
send_tab_to_self_sub_menu_model_;
PrefChangeRegistrar pref_change_registrar_;
base::WeakPtrFactory<OmniboxViewViews> weak_factory_{this};
};
#endif // CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_