Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: chrome/browser/ui/omnibox/omnibox_edit_model.cc

Issue 232023004: Ensures the autocomplete_controller input is saved and restored when changing tabs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed broken browser test. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" 5 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.h" 12 #include "base/prefs/pref_service.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/app/chrome_command_ids.h" 17 #include "chrome/app/chrome_command_ids.h"
18 #include "chrome/browser/autocomplete/autocomplete_classifier.h" 18 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
19 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" 19 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
20 #include "chrome/browser/autocomplete/autocomplete_input.h"
21 #include "chrome/browser/autocomplete/autocomplete_provider.h" 20 #include "chrome/browser/autocomplete/autocomplete_provider.h"
22 #include "chrome/browser/autocomplete/extension_app_provider.h" 21 #include "chrome/browser/autocomplete/extension_app_provider.h"
23 #include "chrome/browser/autocomplete/history_url_provider.h" 22 #include "chrome/browser/autocomplete/history_url_provider.h"
24 #include "chrome/browser/autocomplete/keyword_provider.h" 23 #include "chrome/browser/autocomplete/keyword_provider.h"
25 #include "chrome/browser/autocomplete/search_provider.h" 24 #include "chrome/browser/autocomplete/search_provider.h"
26 #include "chrome/browser/bookmarks/bookmark_stats.h" 25 #include "chrome/browser/bookmarks/bookmark_stats.h"
27 #include "chrome/browser/chrome_notification_types.h" 26 #include "chrome/browser/chrome_notification_types.h"
28 #include "chrome/browser/command_updater.h" 27 #include "chrome/browser/command_updater.h"
29 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h" 28 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
30 #include "chrome/browser/favicon/favicon_tab_helper.h" 29 #include "chrome/browser/favicon/favicon_tab_helper.h"
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 167
169 // OmniboxEditModel::State ---------------------------------------------------- 168 // OmniboxEditModel::State ----------------------------------------------------
170 169
171 OmniboxEditModel::State::State(bool user_input_in_progress, 170 OmniboxEditModel::State::State(bool user_input_in_progress,
172 const base::string16& user_text, 171 const base::string16& user_text,
173 const base::string16& gray_text, 172 const base::string16& gray_text,
174 const base::string16& keyword, 173 const base::string16& keyword,
175 bool is_keyword_hint, 174 bool is_keyword_hint,
176 bool url_replacement_enabled, 175 bool url_replacement_enabled,
177 OmniboxFocusState focus_state, 176 OmniboxFocusState focus_state,
178 FocusSource focus_source) 177 FocusSource focus_source,
178 const AutocompleteInput& autocomplete_input)
179 : user_input_in_progress(user_input_in_progress), 179 : user_input_in_progress(user_input_in_progress),
180 user_text(user_text), 180 user_text(user_text),
181 gray_text(gray_text), 181 gray_text(gray_text),
182 keyword(keyword), 182 keyword(keyword),
183 is_keyword_hint(is_keyword_hint), 183 is_keyword_hint(is_keyword_hint),
184 url_replacement_enabled(url_replacement_enabled), 184 url_replacement_enabled(url_replacement_enabled),
185 focus_state(focus_state), 185 focus_state(focus_state),
186 focus_source(focus_source) { 186 focus_source(focus_source),
187 autocomplete_input(autocomplete_input) {
187 } 188 }
188 189
189 OmniboxEditModel::State::~State() { 190 OmniboxEditModel::State::~State() {
190 } 191 }
191 192
192 193
193 // OmniboxEditModel ----------------------------------------------------------- 194 // OmniboxEditModel -----------------------------------------------------------
194 195
195 OmniboxEditModel::OmniboxEditModel(OmniboxView* view, 196 OmniboxEditModel::OmniboxEditModel(OmniboxView* view,
196 OmniboxEditController* controller, 197 OmniboxEditController* controller,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 InternalSetUserText(user_text); 234 InternalSetUserText(user_text);
234 } 235 }
235 } 236 }
236 237
237 UMA_HISTOGRAM_BOOLEAN("Omnibox.SaveStateForTabSwitch.UserInputInProgress", 238 UMA_HISTOGRAM_BOOLEAN("Omnibox.SaveStateForTabSwitch.UserInputInProgress",
238 user_input_in_progress_); 239 user_input_in_progress_);
239 return State( 240 return State(
240 user_input_in_progress_, user_text_, view_->GetGrayTextAutocompletion(), 241 user_input_in_progress_, user_text_, view_->GetGrayTextAutocompletion(),
241 keyword_, is_keyword_hint_, 242 keyword_, is_keyword_hint_,
242 controller_->GetToolbarModel()->url_replacement_enabled(), 243 controller_->GetToolbarModel()->url_replacement_enabled(),
243 focus_state_, focus_source_); 244 focus_state_, focus_source_, input_);
244 } 245 }
245 246
246 void OmniboxEditModel::RestoreState(const State* state) { 247 void OmniboxEditModel::RestoreState(const State* state) {
247 // We need to update the permanent text correctly and revert the view 248 // We need to update the permanent text correctly and revert the view
248 // regardless of whether there is saved state. 249 // regardless of whether there is saved state.
249 controller_->GetToolbarModel()->set_url_replacement_enabled( 250 controller_->GetToolbarModel()->set_url_replacement_enabled(
250 !state || state->url_replacement_enabled); 251 !state || state->url_replacement_enabled);
251 permanent_text_ = controller_->GetToolbarModel()->GetText(); 252 permanent_text_ = controller_->GetToolbarModel()->GetText();
252 // Don't muck with the search term replacement state, as we've just set it 253 // Don't muck with the search term replacement state, as we've just set it
253 // correctly. 254 // correctly.
254 view_->RevertWithoutResettingSearchTermReplacement(); 255 view_->RevertWithoutResettingSearchTermReplacement();
256 // Restore the autocomplete controller's input, or clear it if this is a new
257 // tab.
258 input_ = state ? state->autocomplete_input : AutocompleteInput();
255 if (!state) 259 if (!state)
256 return; 260 return;
257 261
258 SetFocusState(state->focus_state, OMNIBOX_FOCUS_CHANGE_TAB_SWITCH); 262 SetFocusState(state->focus_state, OMNIBOX_FOCUS_CHANGE_TAB_SWITCH);
259 focus_source_ = state->focus_source; 263 focus_source_ = state->focus_source;
260 // Restore any user editing. 264 // Restore any user editing.
261 if (state->user_input_in_progress) { 265 if (state->user_input_in_progress) {
262 // NOTE: Be sure and set keyword-related state BEFORE invoking 266 // NOTE: Be sure and set keyword-related state BEFORE invoking
263 // DisplayTextFromUserText(), as its result depends upon this state. 267 // DisplayTextFromUserText(), as its result depends upon this state.
264 keyword_ = state->keyword; 268 keyword_ = state->keyword;
265 is_keyword_hint_ = state->is_keyword_hint; 269 is_keyword_hint_ = state->is_keyword_hint;
266 view_->SetUserText(state->user_text, 270 view_->SetUserText(state->user_text,
267 DisplayTextFromUserText(state->user_text), false); 271 DisplayTextFromUserText(state->user_text), false);
268 view_->SetGrayTextAutocompletion(state->gray_text); 272 view_->SetGrayTextAutocompletion(state->gray_text);
269 } 273 }
270 } 274 }
271 275
272 AutocompleteMatch OmniboxEditModel::CurrentMatch( 276 AutocompleteMatch OmniboxEditModel::CurrentMatch(
273 GURL* alternate_nav_url) const { 277 GURL* alternate_nav_url) const {
274 // If we have a valid match use it. Otherwise get one for the current text. 278 // If we have a valid match use it. Otherwise get one for the current text.
275 AutocompleteMatch match = omnibox_controller_->current_match(); 279 AutocompleteMatch match = omnibox_controller_->current_match();
276 280
277 if (!match.destination_url.is_valid()) { 281 if (!match.destination_url.is_valid()) {
278 GetInfoForCurrentText(&match, alternate_nav_url); 282 GetInfoForCurrentText(&match, alternate_nav_url);
279 } else if (alternate_nav_url) { 283 } else if (alternate_nav_url) {
280 *alternate_nav_url = AutocompleteResult::ComputeAlternateNavUrl( 284 *alternate_nav_url = AutocompleteResult::ComputeAlternateNavUrl(
281 autocomplete_controller()->input(), match); 285 input_, match);
282 } 286 }
283 return match; 287 return match;
284 } 288 }
285 289
286 bool OmniboxEditModel::UpdatePermanentText() { 290 bool OmniboxEditModel::UpdatePermanentText() {
287 SearchProvider* search_provider = 291 SearchProvider* search_provider =
288 autocomplete_controller()->search_provider(); 292 autocomplete_controller()->search_provider();
289 if (search_provider && delegate_->CurrentPageExists()) 293 if (search_provider && delegate_->CurrentPageExists())
290 search_provider->set_current_page_url(delegate_->GetURL()); 294 search_provider->set_current_page_url(delegate_->GetURL());
291 295
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 view_->SetWindowTextAndCaretPos(permanent_text_, 534 view_->SetWindowTextAndCaretPos(permanent_text_,
531 has_focus() ? permanent_text_.length() : 0, 535 has_focus() ? permanent_text_.length() : 0,
532 false, true); 536 false, true);
533 AutocompleteActionPredictor* action_predictor = 537 AutocompleteActionPredictor* action_predictor =
534 predictors::AutocompleteActionPredictorFactory::GetForProfile(profile_); 538 predictors::AutocompleteActionPredictorFactory::GetForProfile(profile_);
535 action_predictor->ClearTransitionalMatches(); 539 action_predictor->ClearTransitionalMatches();
536 } 540 }
537 541
538 void OmniboxEditModel::StartAutocomplete( 542 void OmniboxEditModel::StartAutocomplete(
539 bool has_selected_text, 543 bool has_selected_text,
540 bool prevent_inline_autocomplete) const { 544 bool prevent_inline_autocomplete) {
541 size_t cursor_position; 545 size_t cursor_position;
542 if (inline_autocomplete_text_.empty()) { 546 if (inline_autocomplete_text_.empty()) {
543 // Cursor position is equivalent to the current selection's end. 547 // Cursor position is equivalent to the current selection's end.
544 size_t start; 548 size_t start;
545 view_->GetSelectionBounds(&start, &cursor_position); 549 view_->GetSelectionBounds(&start, &cursor_position);
546 // Adjust cursor position taking into account possible keyword in the user 550 // Adjust cursor position taking into account possible keyword in the user
547 // text. We rely on DisplayTextFromUserText() method which is consistent 551 // text. We rely on DisplayTextFromUserText() method which is consistent
548 // with keyword extraction done in KeywordProvider/SearchProvider. 552 // with keyword extraction done in KeywordProvider/SearchProvider.
549 const size_t cursor_offset = 553 const size_t cursor_offset =
550 user_text_.length() - DisplayTextFromUserText(user_text_).length(); 554 user_text_.length() - DisplayTextFromUserText(user_text_).length();
551 cursor_position += cursor_offset; 555 cursor_position += cursor_offset;
552 } else { 556 } else {
553 // There are some cases where StartAutocomplete() may be called 557 // There are some cases where StartAutocomplete() may be called
554 // with non-empty |inline_autocomplete_text_|. In such cases, we cannot 558 // with non-empty |inline_autocomplete_text_|. In such cases, we cannot
555 // use the current selection, because it could result with the cursor 559 // use the current selection, because it could result with the cursor
556 // position past the last character from the user text. Instead, 560 // position past the last character from the user text. Instead,
557 // we assume that the cursor is simply at the end of input. 561 // we assume that the cursor is simply at the end of input.
558 // One example is when user presses Ctrl key while having a highlighted 562 // One example is when user presses Ctrl key while having a highlighted
559 // inline autocomplete text. 563 // inline autocomplete text.
560 // TODO: Rethink how we are going to handle this case to avoid 564 // TODO: Rethink how we are going to handle this case to avoid
561 // inconsistent behavior when user presses Ctrl key. 565 // inconsistent behavior when user presses Ctrl key.
562 // See http://crbug.com/165961 and http://crbug.com/165968 for more details. 566 // See http://crbug.com/165961 and http://crbug.com/165968 for more details.
563 cursor_position = user_text_.length(); 567 cursor_position = user_text_.length();
564 } 568 }
565 569
566 GURL current_url = 570 GURL current_url =
567 (delegate_->CurrentPageExists() && view_->IsIndicatingQueryRefinement()) ? 571 (delegate_->CurrentPageExists() && view_->IsIndicatingQueryRefinement()) ?
568 delegate_->GetURL() : GURL(); 572 delegate_->GetURL() : GURL();
569 bool keyword_is_selected = KeywordIsSelected(); 573 bool keyword_is_selected = KeywordIsSelected();
570 omnibox_controller_->StartAutocomplete( 574 input_ = AutocompleteInput(
571 user_text_, 575 user_text_,
572 cursor_position, 576 cursor_position,
577 base::string16(),
573 current_url, 578 current_url,
574 ClassifyPage(), 579 ClassifyPage(),
575 prevent_inline_autocomplete || just_deleted_text_ || 580 prevent_inline_autocomplete || just_deleted_text_ ||
576 (has_selected_text && inline_autocomplete_text_.empty()) || 581 (has_selected_text && inline_autocomplete_text_.empty()) ||
577 (paste_state_ != NONE), 582 (paste_state_ != NONE),
578 keyword_is_selected, 583 keyword_is_selected,
579 keyword_is_selected || allow_exact_keyword_match_); 584 keyword_is_selected || allow_exact_keyword_match_,
585 true);
586
587 omnibox_controller_->StartAutocomplete(input_);
580 } 588 }
581 589
582 void OmniboxEditModel::StopAutocomplete() { 590 void OmniboxEditModel::StopAutocomplete() {
583 autocomplete_controller()->Stop(true); 591 autocomplete_controller()->Stop(true);
584 } 592 }
585 593
586 bool OmniboxEditModel::CanPasteAndGo(const base::string16& text) const { 594 bool OmniboxEditModel::CanPasteAndGo(const base::string16& text) const {
587 if (!view_->command_updater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) 595 if (!view_->command_updater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL))
588 return false; 596 return false;
589 597
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 if (control_key_state_ == DOWN_WITHOUT_CHANGE && !KeywordIsSelected() && 631 if (control_key_state_ == DOWN_WITHOUT_CHANGE && !KeywordIsSelected() &&
624 autocomplete_controller()->history_url_provider()) { 632 autocomplete_controller()->history_url_provider()) {
625 // Generate a new AutocompleteInput, copying the latest one but using "com" 633 // Generate a new AutocompleteInput, copying the latest one but using "com"
626 // as the desired TLD. Then use this autocomplete input to generate a 634 // as the desired TLD. Then use this autocomplete input to generate a
627 // URL_WHAT_YOU_TYPED AutocompleteMatch. Note that using the most recent 635 // URL_WHAT_YOU_TYPED AutocompleteMatch. Note that using the most recent
628 // input instead of the currently visible text means we'll ignore any 636 // input instead of the currently visible text means we'll ignore any
629 // visible inline autocompletion: if a user types "foo" and is autocompleted 637 // visible inline autocompletion: if a user types "foo" and is autocompleted
630 // to "foodnetwork.com", ctrl-enter will navigate to "foo.com", not 638 // to "foodnetwork.com", ctrl-enter will navigate to "foo.com", not
631 // "foodnetwork.com". At the time of writing, this behavior matches 639 // "foodnetwork.com". At the time of writing, this behavior matches
632 // Internet Explorer, but not Firefox. 640 // Internet Explorer, but not Firefox.
633 const AutocompleteInput& old_input = autocomplete_controller()->input(); 641 input_ = AutocompleteInput(
634 AutocompleteInput input(
635 has_temporary_text_ ? 642 has_temporary_text_ ?
636 UserTextFromDisplayText(view_->GetText()) : old_input.text(), 643 UserTextFromDisplayText(view_->GetText()) : input_.text(),
637 old_input.cursor_position(), base::ASCIIToUTF16("com"), 644 input_.cursor_position(), base::ASCIIToUTF16("com"),
638 GURL(), old_input.current_page_classification(), 645 GURL(), input_.current_page_classification(),
639 old_input.prevent_inline_autocomplete(), old_input.prefer_keyword(), 646 input_.prevent_inline_autocomplete(), input_.prefer_keyword(),
640 old_input.allow_exact_keyword_match(), 647 input_.allow_exact_keyword_match(),
641 old_input.want_asynchronous_matches()); 648 input_.want_asynchronous_matches());
642 AutocompleteMatch url_match( 649 AutocompleteMatch url_match(
643 autocomplete_controller()->history_url_provider()->SuggestExactInput( 650 autocomplete_controller()->history_url_provider()->SuggestExactInput(
644 input.text(), input.canonicalized_url(), false)); 651 input_.text(), input_.canonicalized_url(), false));
652
645 653
646 if (url_match.destination_url.is_valid()) { 654 if (url_match.destination_url.is_valid()) {
647 // We have a valid URL, we use this newly generated AutocompleteMatch. 655 // We have a valid URL, we use this newly generated AutocompleteMatch.
648 match = url_match; 656 match = url_match;
649 alternate_nav_url = GURL(); 657 alternate_nav_url = GURL();
650 } 658 }
651 } 659 }
652 660
653 if (!match.destination_url.is_valid()) 661 if (!match.destination_url.is_valid())
654 return; 662 return;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST)) { 724 (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST)) {
717 elapsed_time_since_user_first_modified_omnibox = 725 elapsed_time_since_user_first_modified_omnibox =
718 base::TimeDelta::FromMilliseconds(-1); 726 base::TimeDelta::FromMilliseconds(-1);
719 elapsed_time_since_last_change_to_default_match = 727 elapsed_time_since_last_change_to_default_match =
720 base::TimeDelta::FromMilliseconds(-1); 728 base::TimeDelta::FromMilliseconds(-1);
721 } 729 }
722 DCHECK_NE(OmniboxPopupModel::kNoMatch, index); 730 DCHECK_NE(OmniboxPopupModel::kNoMatch, index);
723 OmniboxLog log( 731 OmniboxLog log(
724 input_text, 732 input_text,
725 just_deleted_text_, 733 just_deleted_text_,
726 autocomplete_controller()->input().type(), 734 input_.type(),
727 index, 735 index,
728 -1, // don't yet know tab ID; set later if appropriate 736 -1, // don't yet know tab ID; set later if appropriate
729 ClassifyPage(), 737 ClassifyPage(),
730 elapsed_time_since_user_first_modified_omnibox, 738 elapsed_time_since_user_first_modified_omnibox,
731 match.inline_autocompletion.length(), 739 match.inline_autocompletion.length(),
732 elapsed_time_since_last_change_to_default_match, 740 elapsed_time_since_last_change_to_default_match,
733 result()); 741 result());
734 742
735 DCHECK(user_input_in_progress_ || (match.provider && 743 DCHECK(user_input_in_progress_ || (match.provider &&
736 (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST))) 744 (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST)))
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after
1443 // Update state and notify view if the omnibox has focus and the caret 1451 // Update state and notify view if the omnibox has focus and the caret
1444 // visibility changed. 1452 // visibility changed.
1445 const bool was_caret_visible = is_caret_visible(); 1453 const bool was_caret_visible = is_caret_visible();
1446 focus_state_ = state; 1454 focus_state_ = state;
1447 if (focus_state_ != OMNIBOX_FOCUS_NONE && 1455 if (focus_state_ != OMNIBOX_FOCUS_NONE &&
1448 is_caret_visible() != was_caret_visible) 1456 is_caret_visible() != was_caret_visible)
1449 view_->ApplyCaretVisibility(); 1457 view_->ApplyCaretVisibility();
1450 1458
1451 delegate_->OnFocusChanged(focus_state_, reason); 1459 delegate_->OnFocusChanged(focus_state_, reason);
1452 } 1460 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/omnibox/omnibox_edit_model.h ('k') | chrome/browser/ui/omnibox/omnibox_view_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698