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