1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_
6 #define CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <set>
12 #include <string>
13 
14 #include "base/gtest_prod_util.h"
15 #include "base/macros.h"
16 #include "base/scoped_observer.h"
17 #include "build/build_config.h"
18 #include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h"
19 #include "components/omnibox/browser/omnibox_view.h"
20 #include "components/prefs/pref_change_registrar.h"
21 #include "components/search_engines/template_url_service.h"
22 #include "components/search_engines/template_url_service_observer.h"
23 #include "content/public/browser/web_contents_observer.h"
24 #include "third_party/skia/include/core/SkColor.h"
25 #include "ui/base/window_open_disposition.h"
26 #include "ui/compositor/compositor.h"
27 #include "ui/compositor/compositor_observer.h"
28 #include "ui/gfx/animation/multi_animation.h"
29 #include "ui/gfx/range/range.h"
30 #include "ui/views/animation/animation_delegate_views.h"
31 #include "ui/views/controls/textfield/textfield.h"
32 #include "ui/views/controls/textfield/textfield_controller.h"
33 
34 #if defined(OS_CHROMEOS)
35 #include "ui/base/ime/chromeos/input_method_manager.h"
36 #endif
37 
38 class LocationBarView;
39 class OmniboxClient;
40 class OmniboxPopupContentsView;
41 
42 namespace content {
43 struct FocusedNodeDetails;
44 class WebContents;
45 }  // namespace content
46 
47 namespace gfx {
48 class RenderText;
49 }  // namespace gfx
50 
51 namespace ui {
52 class OSExchangeData;
53 }  // namespace ui
54 
55 // Views-implementation of OmniboxView.
56 class OmniboxViewViews : public OmniboxView,
57                          public views::Textfield,
58 #if defined(OS_CHROMEOS)
59                          public chromeos::input_method::InputMethodManager::
60                              CandidateWindowObserver,
61 #endif
62                          public views::TextfieldController,
63                          public ui::CompositorObserver,
64                          public TemplateURLServiceObserver,
65                          public content::WebContentsObserver {
66  public:
67   // The internal view class name.
68   static const char kViewClassName[];
69 
70   // Max width of the gradient mask used to smooth ElideAnimation edges.
71   static const int kSmoothingGradientMaxWidth = 15;
72 
73   OmniboxViewViews(OmniboxEditController* controller,
74                    std::unique_ptr<OmniboxClient> client,
75                    bool popup_window_mode,
76                    LocationBarView* location_bar,
77                    const gfx::FontList& font_list);
78   ~OmniboxViewViews() override;
79 
80   // Initialize, create the underlying views, etc.
81   void Init();
82 
83   // Exposes the RenderText for tests.
84 #if defined(UNIT_TEST)
GetRenderText()85   gfx::RenderText* GetRenderText() {
86     return views::Textfield::GetRenderText();
87   }
88 #endif
89 
90   // For use when switching tabs, this saves the current state onto the tab so
91   // that it can be restored during a later call to Update().
92   void SaveStateToTab(content::WebContents* tab);
93 
94   // Called when the window's active tab changes.
95   void OnTabChanged(content::WebContents* web_contents);
96 
97   // Called to clear the saved state for |web_contents|.
98   void ResetTabState(content::WebContents* web_contents);
99 
100   // Installs the placeholder text with the name of the current default search
101   // provider. For example, if Google is the default search provider, this shows
102   // "Search Google or type a URL" when the Omnibox is empty and unfocused.
103   void InstallPlaceholderText();
104 
105   // Indicates if the cursor is at one end of the input. Requires that both
106   // ends of the selection reside there.
107   bool SelectionAtBeginning() const;
108   bool SelectionAtEnd() const;
109 
110   // Returns the width in pixels needed to display the current text. The
111   // returned value includes margins.
112   int GetTextWidth() const;
113   // Returns the width in pixels needed to display the current text unelided.
114   int GetUnelidedTextWidth() const;
115 
116   // Returns the omnibox's width in pixels.
117   int GetWidth() const;
118 
119   // OmniboxView:
120   void EmphasizeURLComponents() override;
121   void Update() override;
122   base::string16 GetText() const override;
123   using OmniboxView::SetUserText;
124   void SetUserText(const base::string16& text,
125                    bool update_popup) override;
126   void SetWindowTextAndCaretPos(const base::string16& text,
127                                 size_t caret_pos,
128                                 bool update_popup,
129                                 bool notify_text_changed) override;
130   void SetAdditionalText(const base::string16& additional_text) override;
131   void EnterKeywordModeForDefaultSearchProvider() override;
132   bool IsSelectAll() const override;
133   void GetSelectionBounds(base::string16::size_type* start,
134                           base::string16::size_type* end) const override;
135   size_t GetAllSelectionsLength() const override;
136   void SelectAll(bool reversed) override;
137   void RevertAll() override;
138   void SetFocus(bool is_user_initiated) override;
139   bool IsImeComposing() const override;
140   gfx::NativeView GetRelativeWindowForPopup() const override;
141   bool IsImeShowingPopup() const override;
142 
143   // views::Textfield:
144   gfx::Size GetMinimumSize() const override;
145   bool OnMousePressed(const ui::MouseEvent& event) override;
146   bool OnMouseDragged(const ui::MouseEvent& event) override;
147   void OnMouseReleased(const ui::MouseEvent& event) override;
148   void OnPaint(gfx::Canvas* canvas) override;
149   void ExecuteCommand(int command_id, int event_flags) override;
150   ui::TextInputType GetTextInputType() const override;
151   void AddedToWidget() override;
152   void RemovedFromWidget() override;
153   base::string16 GetLabelForCommandId(int command_id) const override;
154   bool IsCommandIdEnabled(int command_id) const override;
155 
156   // content::WebContentsObserver:
157   void DidStartNavigation(content::NavigationHandle* navigation) override;
158   void DidFinishNavigation(content::NavigationHandle* navigation) override;
159   void DidGetUserInteraction(const blink::WebInputEvent& event) override;
160   void OnFocusChangedInPage(content::FocusedNodeDetails* details) override;
161 
162   // For testing only.
GetPopupContentsViewForTesting()163   OmniboxPopupContentsView* GetPopupContentsViewForTesting() const {
164     return popup_view_.get();
165   }
166 
167  protected:
168   // Animates the URL to a given range of text, which could be a substring or
169   // superstring of what's currently displayed. An elision animation hides the
170   // path (and optionally subdomains) by narrowing the bounds of each side of
171   // the URL while also shifting the text to remain aligned with the leading
172   // edge of the display area. While the bounds change, the text being elided
173   // can be simultaneously faded to transparent to make the transition smoother.
174   // An unelision animation is the reverse.
175   //
176   // Animation is used for elision when the elision is in response to a user
177   // interaction and we want to draw attention to where the URL is going and how
178   // it can be retrieved. Depending on field trial configurations, this could be
179   // after the user interacts with the page (where we want to hide the full URL
180   // but hint that it can be brought back by interacting with the omnibox),
181   // and/or when the user hovers over the omnibox. In contrast,
182   // ElideToSimplifiedDomain() and UnelideFromSimplifiedDomain() instantly
183   // elide/unelide and are used when we want to elide/unelide without drawing
184   // the user's attention (for example, on a same-document navigation where we
185   // want the URL to remain simplified if it was simplified before the
186   // navigation).
187   //
188   // This class is declared here for testing.
189   class ElideAnimation : public views::AnimationDelegateViews {
190    public:
191     ElideAnimation(OmniboxViewViews* view, gfx::RenderText* render_text);
192     ~ElideAnimation() override;
193 
194     // Begin the elision animation targeting |elide_to_bounds|, after a delay of
195     // |delay_ms|. |ranges_surrounding_simplified_domain| should contain 1 or 2
196     // ranges surrounding the simplified domain part, they should be in order
197     // (i.e. the range on the left should be the first element). If only one
198     // element is set, it will be assumed we are only eliding from the left
199     // side. Those ranges will be faded from |starting_color| to
200     // |ending_color|.
201     void Start(
202         const gfx::Range& elide_to_bounds,
203         uint32_t delay_ms,
204         const std::vector<gfx::Range>& ranges_surrounding_simplified_domain,
205         SkColor starting_color,
206         SkColor ending_color);
207 
208     void Stop();
209 
210     // Returns true if the animation is currently running.
211     bool IsAnimating();
212 
213     // Returns the bounds to which the animation is eliding, as passed in to
214     // Start().
215     const gfx::Range& GetElideToBounds() const;
216 
217     // Returns the current color applied to each of the ranges in
218     // |ranges_surrounding_simplified_domain| passed in to Start(), if the
219     // animation is running or has completed running.
220     // Returns gfx::kPlaceholderColor if the animation has not starting
221     // running yet.
222     SkColor GetCurrentColor() const;
223 
224     gfx::MultiAnimation* GetAnimationForTesting();
225 
GetCurrentOffsetForTesting()226     int GetCurrentOffsetForTesting() { return current_offset_; }
227 
228     // views::AnimationDelegateViews:
229     void AnimationProgressed(const gfx::Animation* animation) override;
230 
231    private:
232     // Non-owning pointers. |view_| and |render_text_| must always outlive this
233     // class.
234     OmniboxViewViews* view_;
235     gfx::RenderText* render_text_;
236 
237     // The target bounds passed in to Start().
238     gfx::Range elide_to_bounds_;
239     // The desired end state: the display rect that we are eliding or uneliding
240     // to.
241     gfx::Rect elide_to_rect_;
242     // The starting display rect from which we are eliding or uneliding.
243     gfx::Rect elide_from_rect_;
244     // The display rect surrounding the simplified domain.
245     gfx::Rect simplified_domain_bounds_;
246     // The starting and ending display offsets for |render_text_|.
247     int starting_display_offset_ = 0;
248     int ending_display_offset_ = 0;
249 
250     // The current offset, exposed for testing.
251     int current_offset_;
252 
253     // Holds the ranges surrounding the simplified domain part. As the animation
254     // runs, each range fades from |starting_color_| to |ending_color_|.
255     std::vector<gfx::Range> ranges_surrounding_simplified_domain_;
256     SkColor starting_color_;
257     SkColor ending_color_;
258 
259     // The underlying animation. We use a MultiAnimation to implement the
260     // |delay_ms| delay passed into Start(). When this delay is nonzero, the
261     // first part of the animation is a zero tween of |delay_ms| length.
262     std::unique_ptr<gfx::MultiAnimation> animation_;
263   };
264 
265   ElideAnimation* GetHoverElideOrUnelideAnimationForTesting();
266   ElideAnimation* GetElideAfterInteractionAnimationForTesting();
267 
268   // views::Textfield:
269   void OnThemeChanged() override;
270   bool IsDropCursorForInsertion() const override;
271 
272   // Applies the given |color| to |range|. This is a wrapper method around
273   // Textfield::ApplyColor that tests can override.
274   virtual void ApplyColor(SkColor color, const gfx::Range& range);
275 
276  private:
277   FRIEND_TEST_ALL_PREFIXES(
278       OmniboxViewViewsTest,
279       RendererInitiatedFocusPreservesCursorWhenStartingFocused);
280   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExit);
281   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExitIDN);
282   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, PrivateRegistry);
283   FRIEND_TEST_ALL_PREFIXES(
284       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
285       BrowserInitiatedNavigation);
286   FRIEND_TEST_ALL_PREFIXES(
287       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
288       UserInteractionAndHover);
289   FRIEND_TEST_ALL_PREFIXES(
290       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
291       MouseClick);
292   FRIEND_TEST_ALL_PREFIXES(
293       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
294       FocusingEditableNode);
295   FRIEND_TEST_ALL_PREFIXES(
296       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
297       BoundsChanged);
298   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, BoundsChanged);
299   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverHistogram);
300   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
301                            CancellingAnimationDoesNotCrash);
302   FRIEND_TEST_ALL_PREFIXES(
303       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
304       SchemeAndTrivialSubdomainElision);
305   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
306                            SimplifiedDomainElisionWithNarrowOmnibox);
307   FRIEND_TEST_ALL_PREFIXES(
308       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
309       SimplifiedDomainElisionWithNarrowOmnibox);
310   FRIEND_TEST_ALL_PREFIXES(
311       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
312       HideOnInteractionAfterFocusAndBlur);
313   FRIEND_TEST_ALL_PREFIXES(
314       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
315       URLPositionWithHideOnInteraction);
316   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, AfterBlur);
317   FRIEND_TEST_ALL_PREFIXES(
318       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
319       PathChangeDuringAnimation);
320   FRIEND_TEST_ALL_PREFIXES(
321       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
322       VerticalAndHorizontalPosition);
323   FRIEND_TEST_ALL_PREFIXES(
324       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
325       NoStaleGradientMask);
326   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest, ModifierKeys);
327   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
328                            ErrorPageNavigation);
329   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
330                            SameDocNavigations);
331   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
332                            SameDocNavigationDuringAnimation);
333   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest, GradientMask);
334   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
335                            GradientMaskResetAfterStop);
336   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
337                            UserInteractionDuringAnimation);
338   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
339                            SubframeNavigations);
340   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
341                            AlwaysShowFullURLs);
342   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsHideOnInteractionTest,
343                            AlwaysShowFullURLs);
344   FRIEND_TEST_ALL_PREFIXES(
345       OmniboxViewViewsRevealOnHoverAndMaybeHideOnInteractionTest,
346       UnsetAlwaysShowFullURLs);
347   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest,
348                            RegistrableDomainRepeated);
349   FRIEND_TEST_ALL_PREFIXES(
350       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
351       TabChangeWhenNotEligibleForEliding);
352   FRIEND_TEST_ALL_PREFIXES(OmniboxPopupContentsViewTest,
353                            EmitAccessibilityEvents);
354   // TODO(tommycli): Remove the rest of these friends after porting these
355   // browser tests to unit tests.
356   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, CloseOmniboxPopupOnTextDrag);
357   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, FriendlyAccessibleLabel);
358   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, DoNotNavigateOnDrop);
359   FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest,
360                            ElideAnimationDoesntStartIfNoVisibleChange);
361 
362   enum class UnelisionGesture {
363     HOME_KEY_PRESSED,
364     MOUSE_RELEASE,
365     OTHER,
366   };
367 
368   // Update the field with |text| and set the selection. |ranges| should not be
369   // empty; even text with no selections must have at least 1 empty range in
370   // |ranges| to indicate the cursor position.
371   void SetTextAndSelectedRanges(const base::string16& text,
372                                 const std::vector<gfx::Range>& ranges);
373 
374   void SetSelectedRanges(const std::vector<gfx::Range>& ranges);
375 
376   // Returns the selected text.
377   base::string16 GetSelectedText() const;
378 
379   // Paste text from the clipboard into the omnibox.
380   // Textfields implementation of Paste() pastes the contents of the clipboard
381   // as is. We want to strip whitespace and other things (see GetClipboardText()
382   // for details). The function invokes OnBefore/AfterPossibleChange() as
383   // necessary.
384   void OnOmniboxPaste();
385 
386   // Handle keyword hint tab-to-search and tabbing through dropdown results.
387   bool HandleEarlyTabActions(const ui::KeyEvent& event);
388 
389   void ClearAccessibilityLabel();
390 
391   void SetAccessibilityLabel(const base::string16& display_text,
392                              const AutocompleteMatch& match,
393                              bool notify_text_changed) override;
394 
395   // Returns true if the user text was updated with the full URL (without
396   // steady-state elisions).  |gesture| is the user gesture causing unelision.
397   bool UnapplySteadyStateElisions(UnelisionGesture gesture);
398 
399 #if defined(OS_MAC)
400   void AnnounceFriendlySuggestionText();
401 #endif
402 
403   // OmniboxView:
404   void SetCaretPos(size_t caret_pos) override;
405   void UpdatePopup() override;
406   void ApplyCaretVisibility() override;
407   void OnTemporaryTextMaybeChanged(const base::string16& display_text,
408                                    const AutocompleteMatch& match,
409                                    bool save_original_selection,
410                                    bool notify_text_changed) override;
411   void OnInlineAutocompleteTextMaybeChanged(const base::string16& display_text,
412                                             std::vector<gfx::Range> selections,
413                                             size_t user_text_length) override;
414   void OnInlineAutocompleteTextCleared() override;
415   void OnRevertTemporaryText(const base::string16& display_text,
416                              const AutocompleteMatch& match) override;
417   void OnBeforePossibleChange() override;
418   bool OnAfterPossibleChange(bool allow_keyword_ui_change) override;
419   gfx::NativeView GetNativeView() const override;
420   void ShowVirtualKeyboardIfEnabled() override;
421   void HideImeIfNeeded() override;
422   int GetOmniboxTextLength() const override;
423   void SetEmphasis(bool emphasize, const gfx::Range& range) override;
424   void UpdateSchemeStyle(const gfx::Range& range) override;
425 
426   // views::View
427   void OnMouseMoved(const ui::MouseEvent& event) override;
428   void OnMouseExited(const ui::MouseEvent& event) override;
429 
430   // views::Textfield:
431   bool IsItemForCommandIdDynamic(int command_id) const override;
432   const char* GetClassName() const override;
433   void OnGestureEvent(ui::GestureEvent* event) override;
434   void AboutToRequestFocusFromTabTraversal(bool reverse) override;
435   bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
436   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
437   bool HandleAccessibleAction(const ui::AXActionData& action_data) override;
438   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
439   void OnFocus() override;
440   void OnBlur() override;
441   base::string16 GetSelectionClipboardText() const override;
442   void DoInsertChar(base::char16 ch) override;
443   bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
444   void ExecuteTextEditCommand(ui::TextEditCommand command) override;
445   bool ShouldShowPlaceholderText() const override;
446 
447   // chromeos::input_method::InputMethodManager::CandidateWindowObserver:
448 #if defined(OS_CHROMEOS)
449   void CandidateWindowOpened(
450       chromeos::input_method::InputMethodManager* manager) override;
451   void CandidateWindowClosed(
452       chromeos::input_method::InputMethodManager* manager) override;
453 #endif
454 
455   // views::TextfieldController:
456   void ContentsChanged(views::Textfield* sender,
457                        const base::string16& new_contents) override;
458   bool HandleKeyEvent(views::Textfield* sender,
459                       const ui::KeyEvent& key_event) override;
460   void OnBeforeUserAction(views::Textfield* sender) override;
461   void OnAfterUserAction(views::Textfield* sender) override;
462   void OnAfterCutOrCopy(ui::ClipboardBuffer clipboard_buffer) override;
463   void OnWriteDragData(ui::OSExchangeData* data) override;
464   void OnGetDragOperationsForTextfield(int* drag_operations) override;
465   void AppendDropFormats(
466       int* formats,
467       std::set<ui::ClipboardFormatType>* format_types) override;
468   int OnDrop(const ui::OSExchangeData& data) override;
469   void UpdateContextMenu(ui::SimpleMenuModel* menu_contents) override;
470 
471   // ui::SimpleMenuModel::Delegate:
472   bool IsCommandIdChecked(int id) const override;
473 
474   // ui::CompositorObserver:
475   void OnCompositingDidCommit(ui::Compositor* compositor) override;
476   void OnCompositingStarted(ui::Compositor* compositor,
477                             base::TimeTicks start_time) override;
478   void OnCompositingEnded(ui::Compositor* compositor) override;
479   void OnCompositingShuttingDown(ui::Compositor* compositor) override;
480 
481   // TemplateURLServiceObserver:
482   void OnTemplateURLServiceChanged() override;
483 
484   // Returns the gfx::Range of the simplified domain of the current URL, if
485   // there is one. The simplified domain could be either the registrable domain
486   // (if OmniboxFieldTrial::ElideToRegistrableDomain() is enabled) or the full
487   // hostname. |ranges_surrounding_simplified_domain| is an optional output
488   // parameter; if non-null, it will be populated with the ranges that do not
489   // contain the simplified domain.
490   gfx::Range GetSimplifiedDomainBounds(
491       std::vector<gfx::Range>* ranges_surrounding_simplified_domain);
492 
493   // Returns true if the currently displayed URL is eligible for elision to a
494   // simplified domain. This takes into account the omnibox's current state
495   // (e.g. the URL shouldn't be elided if the user is currently editing it) as
496   // well as properties of the current text (e.g. extension URLs or non-URLs
497   // shouldn't be elided because they may not have simplified domains; localhost
498   // URLs shouldn't be elided because they are used in development workflows
499   // where the full URL is useful).
500   //
501   // This method does NOT take field trials into account or the "Always show
502   // full URLs" option. Calling code should check field trial state and
503   // model()->ShouldPreventElision() if applicable.
504   bool IsURLEligibleForSimplifiedDomainEliding();
505 
506   // When certain field trials are enabled, the URL is shown on page load
507   // and elided to a simplified domain when the user interacts with the page.
508   // This method resets back to the on-page-load state. That is, it unhides the
509   // URL (if currently hidden) and resets state so that the URL will show until
510   // user interaction. This is used on navigation and blur, when the URL should
511   // be shown but hidden on next user interaction.
512   void ResetToHideOnInteraction();
513 
514   // Called when the "Always show full URLs" preference is toggled. Updates the
515   // state to elide to a simplified domain on user interaction and/or reveal the
516   // URL on hover, depending on field trial configuration.
517   //
518   // When the preference changes, we immediately elide/unelide instead of
519   // animating. Animating might look a little nicer, but this should be a
520   // relatively rare event so it's simpler to just immediately update the
521   // display.
522   void OnShouldPreventElisionChanged();
523 
524   // Elides the URL to a simplified version of the domain with an animation.
525   // This should be called when a user interaction with the web contents
526   // triggers elision. Does nothing if the relevant field trial is disabled or
527   // the URL is not eligible for eliding.
528   void MaybeElideURLWithAnimationFromInteraction();
529 
530   // The methods below elide to or unelide from a simplified version of the URL.
531   // Callers should ensure that the URL is valid before calling.
532   //
533   // These methods do not animate, but rather immediately elide/unelide. These
534   // methods are used when we don't want to draw the user's attention to the URL
535   // simplification -- for example, if the URL is already simplified and the
536   // user performs a same-document navigation, we want to keep the URL
537   // simplified without it appearing to be a change from the user's perspective.
538 
539   // Elides the URL to a simplified version of the domain. This will be the
540   // registrable domain if OmniboxFieldTrial::ShouldElideToRegistrableDomain()
541   // is true; otherwise it is the hostname with trivial subdomains ("www.")
542   // elided. The scheme, path, and other components of the URL are hidden.
543   void ElideURL();
544   // Show the full URL, including scheme, all subdomains, and path.
545   void ShowFullURL();
546   // Shows the full URL and then elides http/https schemes and the
547   // "www." subdomain (if present) by setting the display rect to the width of
548   // the remaining URL and then setting the display offset to scroll the scheme
549   // and trivial subdomain offscreen.
550   void ShowFullURLWithoutSchemeAndTrivialSubdomain();
551 
552   // Parses GetText() as a URL, trims trivial subdomains from it (if any and if
553   // applicable), and returns the result.
554   url::Component GetHostComponentAfterTrivialSubdomain();
555 
556   // When true, the location bar view is read only and also is has a slightly
557   // different presentation (smaller font size). This is used for popups.
558   bool popup_window_mode_;
559 
560   std::unique_ptr<OmniboxPopupContentsView> popup_view_;
561 
562   // Animations are used to elide/unelide the path (and subdomains, if
563   // OmniboxFieldTrial::ShouldElideToRegistrableDomain() is true) under some
564   // field trial settings. These animations are created at different times
565   // depending on the field trial configuration, so don't assume they are
566   // non-null.
567   //
568   // These animations are used by different field trials as described below.
569 
570   // This animation is used to unelide or elide the URL
571   // when the mouse hovers or exits the omnibox. The URL will unelide to the
572   // full URL or a partially elided version (with scheme and trivial subdomains
573   // elided) depending on whether the user has interacted with the page yet
574   // (when reveal-on-interaction is enabled).
575   std::unique_ptr<ElideAnimation> hover_elide_or_unelide_animation_;
576   // When ShouldHidePathQueryRefOnInteraction() is enabled, when a
577   // navigation finishes, we unelide the URL if it was a full cross-document
578   // navigation. Once the user interacts with the page, we create and run
579   // |elide_after_web_contents_interaction_animation_| to elide the URL. After
580   // the first user interaction,
581   // |elide_after_web_contents_interaction_animation_| doesn't run again until
582   // it's re-created after the next navigation. There are 2 separate animations
583   // (one for after-interaction and one hovering) so that the state of the
584   // after-interaction animation can be queried to know when the user has or has
585   // not already interacted with the page.
586   std::unique_ptr<ElideAnimation>
587       elide_after_web_contents_interaction_animation_;
588 
589   // If set, rectangles will be drawn as gradient masks over the omnibox text.
590   // Used to smooth color transition when an ElideAnimation is animating.
591   gfx::Rect elide_animation_smoothing_rect_left_;
592   gfx::Rect elide_animation_smoothing_rect_right_;
593 
594   // The time that the mouse begins hovering over the omnibox, used for
595   // recording metrics related to simplified domain field trials. Set in
596   // OnMouseMoved() and cleared when the mouse exits the hover.
597   base::Time hover_start_time_;
598   // A histogram is recorded for each continuous hover over the omnibox, ended
599   // by either focusing or exiting the mouse. This is set to true if the
600   // histogram was recorded due to the omnibox being focused, so that it won't
601   // be recorded again for the same continuous hover when the mouse exits.
602   bool recorded_hover_on_focus_ = false;
603   base::Clock* clock_;
604 
605   // Selection persisted across temporary text changes, like popup suggestions.
606   std::vector<gfx::Range> saved_temporary_selection_;
607 
608   // Holds the user's selection across focus changes.  There is only a saved
609   // selection if this range IsValid().
610   std::vector<gfx::Range> saved_selection_for_focus_change_;
611 
612   // Tracking state before and after a possible change.
613   State state_before_change_;
614   bool ime_composing_before_change_ = false;
615 
616   // |location_bar_view_| can be NULL in tests.
617   LocationBarView* location_bar_view_;
618 
619 #if defined(OS_CHROMEOS)
620   // True if the IME candidate window is open. When this is true, we want to
621   // avoid showing the popup. So far, the candidate window is detected only
622   // on Chrome OS.
623   bool ime_candidate_window_open_ = false;
624 #endif
625 
626   // True if any mouse button is currently depressed.
627   bool is_mouse_pressed_ = false;
628 
629   // Applies a minimum threshold to drag events after unelision. Because the
630   // text shifts after unelision, we don't want unintentional mouse drags to
631   // change the selection.
632   bool filter_drag_events_for_unelision_ = false;
633 
634   // Should we select all the text when we see the mouse button get released?
635   // We select in response to a click that focuses the omnibox, but we defer
636   // until release, setting this variable back to false if we saw a drag, to
637   // allow the user to select just a portion of the text.
638   bool select_all_on_mouse_release_ = false;
639 
640   // Indicates if we want to select all text in the omnibox when we get a
641   // GESTURE_TAP. We want to select all only when the textfield is not in focus
642   // and gets a tap. So we use this variable to remember focus state before tap.
643   bool select_all_on_gesture_tap_ = false;
644 
645   // Whether the user should be notified if the clipboard is restricted.
646   bool show_rejection_ui_if_any_ = false;
647 
648   // Keep track of the word that would be selected if URL is unelided between
649   // a single and double click. This is an edge case where the elided URL is
650   // selected. On the double click, unelision is performed in between the first
651   // and second clicks. This results in both the wrong word to be selected and
652   // the wrong selection length. For example, if example.com is shown and you
653   // try to double click on the "x", it unelides to https://example.com after
654   // the first click, resulting in "https" being selected.
655   size_t next_double_click_selection_len_ = 0;
656   size_t next_double_click_selection_offset_ = 0;
657 
658   // The time of the first character insert operation that has not yet been
659   // painted. Used to measure omnibox responsiveness with a histogram.
660   base::TimeTicks insert_char_time_;
661 
662   // The state machine for logging the Omnibox.CharTypedToRepaintLatency
663   // histogram.
664   enum {
665     NOT_ACTIVE,           // Not currently tracking a char typed event.
666     CHAR_TYPED,           // Character was typed.
667     ON_PAINT_CALLED,      // Character was typed and OnPaint() called.
668     COMPOSITING_COMMIT,   // Compositing was committed after OnPaint().
669     COMPOSITING_STARTED,  // Compositing was started.
670   } latency_histogram_state_;
671 
672   // The currently selected match, if any, with additional labelling text
673   // such as the document title and the type of search, for example:
674   // "Google https://google.com location from bookmark", or
675   // "cats are liquid search suggestion".
676   base::string16 friendly_suggestion_text_;
677 
678   // The number of added labelling characters before editable text begins.
679   // For example,  "Google https://google.com location from history",
680   // this is set to 7 (the length of "Google ").
681   int friendly_suggestion_text_prefix_length_;
682 
683   ScopedObserver<ui::Compositor, ui::CompositorObserver>
684       scoped_compositor_observer_{this};
685   ScopedObserver<TemplateURLService, TemplateURLServiceObserver>
686       scoped_template_url_service_observer_{this};
687 
688   // Send tab to self submenu.
689   std::unique_ptr<send_tab_to_self::SendTabToSelfSubMenuModel>
690       send_tab_to_self_sub_menu_model_;
691 
692   PrefChangeRegistrar pref_change_registrar_;
693 
694   base::WeakPtrFactory<OmniboxViewViews> weak_factory_{this};
695 
696   DISALLOW_COPY_AND_ASSIGN(OmniboxViewViews);
697 };
698 
699 #endif  // CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_VIEW_VIEWS_H_
700