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 // This file defines the interface class OmniboxView. Each toolkit will 6 // implement the edit view differently, so that code is inherently platform 7 // specific. However, the OmniboxEditModel needs to do some communication with 8 // the view. Since the model is shared between platforms, we need to define an 9 // interface that all view implementations will share. 10 11 #ifndef COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_VIEW_H_ 12 #define COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_VIEW_H_ 13 14 #include <stddef.h> 15 16 #include <memory> 17 #include <string> 18 19 #include "base/gtest_prod_util.h" 20 #include "base/strings/string16.h" 21 #include "base/strings/string_util.h" 22 #include "base/strings/utf_string_conversions.h" 23 #include "components/omnibox/browser/autocomplete_match.h" 24 #include "components/omnibox/browser/omnibox_client.h" 25 #include "third_party/skia/include/core/SkColor.h" 26 #include "ui/base/models/image_model.h" 27 #include "ui/base/window_open_disposition.h" 28 #include "ui/gfx/image/image_skia.h" 29 #include "ui/gfx/native_widget_types.h" 30 #include "ui/gfx/range/range.h" 31 32 class GURL; 33 class OmniboxEditController; 34 class OmniboxViewMacTest; 35 class OmniboxEditModel; 36 37 class OmniboxView { 38 public: 39 using IconFetchedCallback = base::OnceCallback<void(const gfx::Image& icon)>; 40 41 // Represents the changes between two State objects. This is used by the 42 // model to determine how its internal state should be updated after the view 43 // state changes. See OmniboxEditModel::OnAfterPossibleChange(). 44 struct StateChanges { 45 // |old_text| and |new_text| are not owned. 46 const base::string16* old_text; 47 const base::string16* new_text; 48 size_t new_sel_start; 49 size_t new_sel_end; 50 bool selection_differs; 51 bool text_differs; 52 bool keyword_differs; 53 bool just_deleted_text; 54 }; 55 56 virtual ~OmniboxView(); 57 OmniboxView(const OmniboxView&) = delete; 58 OmniboxView& operator=(const OmniboxView&) = delete; 59 60 // Used by the automation system for getting at the model from the view. model()61 OmniboxEditModel* model() { return model_.get(); } model()62 const OmniboxEditModel* model() const { return model_.get(); } 63 64 // Called when any relevant state changes other than changing tabs. 65 virtual void Update() = 0; 66 67 // Asks the browser to load the specified match, using the supplied 68 // disposition. |alternate_nav_url|, if non-empty, contains the 69 // alternate navigation URL for for this match. See comments on 70 // AutocompleteResult::GetAlternateNavURL(). 71 // 72 // |pasted_text| should only be set if this call is due to a 73 // Paste-And-Go/Search action. 74 // 75 // |selected_line| is passed to SendOpenNotification(); see comments there. 76 // 77 // This may close the popup. 78 virtual void OpenMatch(const AutocompleteMatch& match, 79 WindowOpenDisposition disposition, 80 const GURL& alternate_nav_url, 81 const base::string16& pasted_text, 82 size_t selected_line, 83 base::TimeTicks match_selection_timestamp); 84 85 // Returns the current text of the edit control, which could be the 86 // "temporary" text set by the popup, the "permanent" text set by the 87 // browser, or just whatever the user has currently typed. 88 virtual base::string16 GetText() const = 0; 89 90 // |true| if the user is in the process of editing the field, or if 91 // the field is empty. 92 bool IsEditingOrEmpty() const; 93 94 // Returns the icon to display as the location icon. If a favicon is 95 // available, |on_icon_fetched| may be called later asynchronously. 96 ui::ImageModel GetIcon(int dip_size, 97 SkColor color, 98 IconFetchedCallback on_icon_fetched) const; 99 100 // The user text is the text the user has manually keyed in. When present, 101 // this is shown in preference to the permanent text; hitting escape will 102 // revert to the permanent text. 103 void SetUserText(const base::string16& text); 104 virtual void SetUserText(const base::string16& text, 105 bool update_popup); 106 107 // Sets the window text and the caret position. |notify_text_changed| is true 108 // if the model should be notified of the change. If rich autocompletion is 109 // enabled, |additional_text| is displayed in a non-editable views::Label 110 // adjacent to the omnibox. 111 virtual void SetWindowTextAndCaretPos(const base::string16& text, 112 size_t caret_pos, 113 bool update_popup, 114 bool notify_text_changed) = 0; 115 116 // Sets the caret position. Removes any selection. Clamps the requested caret 117 // position to the length of the current text. 118 virtual void SetCaretPos(size_t caret_pos) = 0; 119 120 // Sets the omnibox adjacent additional text label in the location bar view. 121 virtual void SetAdditionalText(const base::string16& text) = 0; 122 123 // Transitions the user into keyword mode with their default search provider, 124 // preserving and selecting the user's text if they already typed in a query. 125 virtual void EnterKeywordModeForDefaultSearchProvider() = 0; 126 127 // Returns true if all text is selected. Returns false if there is no text. 128 virtual bool IsSelectAll() const = 0; 129 130 // Fills |start| and |end| with the indexes of the current selection's bounds. 131 // It is not guaranteed that |*start < *end|, as the selection can be 132 // directed. If there is no selection, |start| and |end| will both be equal 133 // to the current cursor position. 134 virtual void GetSelectionBounds(size_t* start, size_t* end) const = 0; 135 136 // Returns the sum of all selections' lengths. This is used to detect when 137 // the user has deleted text, and therefore, their input should not be 138 // autocompleted. 139 virtual size_t GetAllSelectionsLength() const = 0; 140 141 // Selects all the text in the edit. Use this in place of SetSelAll() to 142 // avoid selecting the "phantom newline" at the end of the edit. 143 virtual void SelectAll(bool reversed) = 0; 144 145 // Reverts the edit and popup back to their unedited state (permanent text 146 // showing, popup closed, no user input in progress). 147 virtual void RevertAll(); 148 149 // Updates the autocomplete popup and other state after the text has been 150 // changed by the user. 151 virtual void UpdatePopup() = 0; 152 153 // Closes the autocomplete popup, if it's open. The name |ClosePopup| 154 // conflicts with the OSX class override as that has a base class that also 155 // defines a method with that name. 156 virtual void CloseOmniboxPopup(); 157 158 // Sets the focus to the omnibox. |is_user_initiated| is true when the user 159 // explicitly focused the omnibox, and false when the omnibox was 160 // automatically focused (like for browser startup or NTP load). 161 virtual void SetFocus(bool is_user_initiated) = 0; 162 163 // Shows or hides the caret based on whether the model's is_caret_visible() is 164 // true. 165 virtual void ApplyCaretVisibility() = 0; 166 167 // Updates the accessibility state by enunciating any on-focus text. SetAccessibilityLabel(const base::string16 & display_text,const AutocompleteMatch & match,bool notify_text_changed)168 virtual void SetAccessibilityLabel(const base::string16& display_text, 169 const AutocompleteMatch& match, 170 bool notify_text_changed) {} 171 172 // Called when the temporary text in the model may have changed. 173 // |display_text| is the new text to show; |match_type| is the type of the 174 // match the new text came from. |save_original_selection| is true when there 175 // wasn't previously a temporary text and thus we need to save off the user's 176 // existing selection. |notify_text_changed| is true if the model should be 177 // notified of the change. 178 virtual void OnTemporaryTextMaybeChanged(const base::string16& display_text, 179 const AutocompleteMatch& match, 180 bool save_original_selection, 181 bool notify_text_changed) = 0; 182 183 // Called when the inline autocomplete text in the model may have changed. 184 // |display_text| is the new text to show. |selection| indicates the 185 // autocompleted portions which should be selected. |user_text_length| is the 186 // length of the user input portion of the text (not including the 187 // autocompletion). 188 virtual void OnInlineAutocompleteTextMaybeChanged( 189 const base::string16& display_text, 190 std::vector<gfx::Range> selections, 191 size_t user_text_length) = 0; 192 193 // Called when the inline autocomplete text in the model has been cleared. 194 virtual void OnInlineAutocompleteTextCleared() = 0; 195 196 // Called when the temporary text has been reverted by the user. This will 197 // reset the user's original selection. 198 virtual void OnRevertTemporaryText(const base::string16& display_text, 199 const AutocompleteMatch& match) = 0; 200 201 // Checkpoints the current edit state before an operation that might trigger 202 // a new autocomplete run to open or modify the popup. Call this before 203 // user-initiated edit actions that trigger autocomplete, but *not* for 204 // automatic changes to the textfield that should not affect autocomplete. 205 virtual void OnBeforePossibleChange() = 0; 206 // OnAfterPossibleChange() returns true if there was a change that caused it 207 // to call UpdatePopup(). If |allow_keyword_ui_change| is false, we 208 // prevent alterations to the keyword UI state (enabled vs. disabled). 209 virtual bool OnAfterPossibleChange(bool allow_keyword_ui_change) = 0; 210 211 // Returns the gfx::NativeView of the edit view. 212 virtual gfx::NativeView GetNativeView() const = 0; 213 214 // Gets the relative window for the pop up window of OmniboxPopupView. The pop 215 // up window will be shown under the relative window. When an IME is attached 216 // to the rich edit control, the IME window is the relative window. Otherwise, 217 // the top-most window is the relative window. 218 virtual gfx::NativeView GetRelativeWindowForPopup() const = 0; 219 220 // Returns true if the user is composing something in an IME. 221 virtual bool IsImeComposing() const = 0; 222 223 // Returns true if we know for sure that an IME is showing a popup window, 224 // which may overlap the omnibox's popup window. 225 virtual bool IsImeShowingPopup() const; 226 227 // Display a virtual keyboard or alternate input view if enabled. 228 virtual void ShowVirtualKeyboardIfEnabled(); 229 230 // Hides a virtual keyboard or alternate input view if enabled. 231 virtual void HideImeIfNeeded(); 232 233 // Returns true if the view is displaying UI that indicates that query 234 // refinement will take place when the user selects the current match. For 235 // search matches, this will cause the omnibox to search over the existing 236 // corpus (e.g. Images) rather than start a new Web search. This method will 237 // only ever return true on mobile ports. 238 virtual bool IsIndicatingQueryRefinement() const; 239 240 // Returns |text| with any leading javascript schemas stripped. 241 static base::string16 StripJavascriptSchemas(const base::string16& text); 242 243 // Automatically collapses internal whitespace as follows: 244 // * Leading and trailing whitespace are often copied accidentally and rarely 245 // affect behavior, so they are stripped. If this collapses the whole 246 // string, returns a space, since pasting nothing feels broken. 247 // * Internal whitespace sequences not containing CR/LF may be integral to the 248 // meaning of the string and are preserved exactly. The presence of any of 249 // these also suggests the input is more likely a search than a navigation, 250 // which affects the next bullet. 251 // * Internal whitespace sequences containing CR/LF have likely been split 252 // across lines by terminals, email programs, etc., and are collapsed. If 253 // there are any internal non-CR/LF whitespace sequences, the input is more 254 // likely search data (e.g. street addresses), so collapse these to a single 255 // space. If not, the input might be a navigation (e.g. a line-broken URL), 256 // so collapse these away entirely. 257 // 258 // Finally, calls StripJavascriptSchemas() on the resulting string. 259 static base::string16 SanitizeTextForPaste(const base::string16& text); 260 261 protected: 262 // Tracks important state that may change between OnBeforePossibleChange() and 263 // OnAfterPossibleChange(). 264 struct State { 265 base::string16 text; 266 base::string16 keyword; 267 bool is_keyword_selected; 268 size_t sel_start; 269 size_t sel_end; 270 size_t all_sel_length; 271 272 State(); 273 State(const State& state); 274 }; 275 276 OmniboxView(OmniboxEditController* controller, 277 std::unique_ptr<OmniboxClient> client); 278 279 // Fills |state| with the current text state. 280 void GetState(State* state); 281 282 // Returns the delta between |before| and |after|. 283 StateChanges GetStateChanges(const State& before, 284 const State& after); 285 286 // Internally invoked whenever the text changes in some way. 287 virtual void TextChanged(); 288 289 // Return the number of characters in the current buffer. The name 290 // |GetTextLength| can't be used as the Windows override of this class 291 // inherits from a class that defines a method with that name. 292 virtual int GetOmniboxTextLength() const = 0; 293 294 // Try to parse the current text as a URL and colorize the components. 295 virtual void EmphasizeURLComponents() = 0; 296 controller()297 OmniboxEditController* controller() { return controller_; } controller()298 const OmniboxEditController* controller() const { return controller_; } 299 300 // Marks part (or, if |range| is invalid, all) of the current text as 301 // emphasized or de-emphasized, by changing its color. 302 virtual void SetEmphasis(bool emphasize, const gfx::Range& range) = 0; 303 304 // Sets the color and strikethrough state for |range|, which represents the 305 // current scheme, based on the current security state. Schemes are displayed 306 // in different ways for different security levels. 307 virtual void UpdateSchemeStyle(const gfx::Range& range) = 0; 308 309 // Parses |display_text|, then invokes SetEmphasis() and UpdateSchemeStyle() 310 // appropriately. If the text is a query string, there is no scheme, and 311 // everything is emphasized equally, whereas for URLs the scheme may be styled 312 // based on the current security state, with parts of the URL de-emphasized to 313 // draw attention to whatever best represents the "identity" of the current 314 // URL. 315 void UpdateTextStyle(const base::string16& display_text, 316 const bool text_is_url, 317 const AutocompleteSchemeClassifier& classifier); 318 319 private: 320 friend class OmniboxViewMacTest; 321 friend class TestOmniboxView; 322 323 // |model_| can be NULL in tests. 324 std::unique_ptr<OmniboxEditModel> model_; 325 OmniboxEditController* controller_; 326 }; 327 328 #endif // COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_VIEW_H_ 329