Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 OmniboxEditModel::State::~State() { | 113 OmniboxEditModel::State::~State() { |
| 114 } | 114 } |
| 115 | 115 |
| 116 /////////////////////////////////////////////////////////////////////////////// | 116 /////////////////////////////////////////////////////////////////////////////// |
| 117 // OmniboxEditModel | 117 // OmniboxEditModel |
| 118 | 118 |
| 119 OmniboxEditModel::OmniboxEditModel(OmniboxView* view, | 119 OmniboxEditModel::OmniboxEditModel(OmniboxView* view, |
| 120 OmniboxEditController* controller, | 120 OmniboxEditController* controller, |
| 121 Profile* profile) | 121 Profile* profile) |
| 122 : view_(view), | 122 : view_(view), |
| 123 popup_(NULL), | |
| 124 controller_(controller), | 123 controller_(controller), |
| 125 focus_state_(OMNIBOX_FOCUS_NONE), | 124 focus_state_(OMNIBOX_FOCUS_NONE), |
| 126 user_input_in_progress_(false), | 125 user_input_in_progress_(false), |
| 127 just_deleted_text_(false), | 126 just_deleted_text_(false), |
| 128 has_temporary_text_(false), | 127 has_temporary_text_(false), |
| 129 is_temporary_text_set_by_instant_(false), | 128 is_temporary_text_set_by_instant_(false), |
| 130 is_instant_temporary_text_a_search_query_(false), | 129 is_instant_temporary_text_a_search_query_(false), |
| 131 paste_state_(NONE), | 130 paste_state_(NONE), |
| 132 control_key_state_(UP), | 131 control_key_state_(UP), |
| 133 is_keyword_hint_(false), | 132 is_keyword_hint_(false), |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 | 225 |
| 227 void OmniboxEditModel::FinalizeInstantQuery(const string16& input_text, | 226 void OmniboxEditModel::FinalizeInstantQuery(const string16& input_text, |
| 228 const InstantSuggestion& suggestion, | 227 const InstantSuggestion& suggestion, |
| 229 bool skip_inline_autocomplete) { | 228 bool skip_inline_autocomplete) { |
| 230 if (skip_inline_autocomplete) { | 229 if (skip_inline_autocomplete) { |
| 231 const string16 final_text = input_text + suggestion.text; | 230 const string16 final_text = input_text + suggestion.text; |
| 232 view_->OnBeforePossibleChange(); | 231 view_->OnBeforePossibleChange(); |
| 233 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, | 232 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, |
| 234 false); | 233 false); |
| 235 view_->OnAfterPossibleChange(); | 234 view_->OnAfterPossibleChange(); |
| 236 } else if (popup_->IsOpen()) { | 235 } else if (popup_model()->IsOpen()) { |
| 237 SearchProvider* search_provider = | 236 SearchProvider* search_provider = |
| 238 autocomplete_controller()->search_provider(); | 237 autocomplete_controller()->search_provider(); |
| 239 // There may be no providers during testing; guard against that. | 238 // There may be no providers during testing; guard against that. |
| 240 if (search_provider) | 239 if (search_provider) |
| 241 search_provider->FinalizeInstantQuery(input_text, suggestion); | 240 search_provider->FinalizeInstantQuery(input_text, suggestion); |
| 242 } | 241 } |
| 243 } | 242 } |
| 244 | 243 |
| 245 void OmniboxEditModel::SetInstantSuggestion( | 244 void OmniboxEditModel::SetInstantSuggestion( |
| 246 const InstantSuggestion& suggestion) { | 245 const InstantSuggestion& suggestion) { |
| 247 switch (suggestion.behavior) { | 246 switch (suggestion.behavior) { |
| 248 case INSTANT_COMPLETE_NOW: | 247 case INSTANT_COMPLETE_NOW: |
| 249 view_->SetInstantSuggestion(string16()); | 248 view_->SetInstantSuggestion(string16()); |
| 250 if (!suggestion.text.empty()) | 249 if (!suggestion.text.empty()) |
| 251 FinalizeInstantQuery(view_->GetText(), suggestion, false); | 250 FinalizeInstantQuery(view_->GetText(), suggestion, false); |
| 252 break; | 251 break; |
| 253 | 252 |
| 254 case INSTANT_COMPLETE_NEVER: { | 253 case INSTANT_COMPLETE_NEVER: { |
| 255 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type); | 254 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type); |
| 256 view_->SetInstantSuggestion(suggestion.text); | 255 view_->SetInstantSuggestion(suggestion.text); |
| 257 autocomplete_controller()->search_provider()->ClearInstantSuggestion(); | 256 SearchProvider* search_provider = |
| 257 autocomplete_controller()->search_provider(); | |
| 258 if (search_provider) | |
| 259 search_provider->ClearInstantSuggestion(); | |
| 258 break; | 260 break; |
| 259 } | 261 } |
| 260 | 262 |
| 261 case INSTANT_COMPLETE_REPLACE: { | 263 case INSTANT_COMPLETE_REPLACE: { |
| 262 const bool save_original_selection = !has_temporary_text_; | 264 const bool save_original_selection = !has_temporary_text_; |
| 263 view_->SetInstantSuggestion(string16()); | 265 view_->SetInstantSuggestion(string16()); |
| 264 has_temporary_text_ = true; | 266 has_temporary_text_ = true; |
| 265 is_temporary_text_set_by_instant_ = true; | 267 is_temporary_text_set_by_instant_ = true; |
| 266 is_instant_temporary_text_a_search_query_ = | 268 is_instant_temporary_text_a_search_query_ = |
| 267 suggestion.type == INSTANT_SUGGESTION_SEARCH; | 269 suggestion.type == INSTANT_SUGGESTION_SEARCH; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 // has been closed or on return from a sleep state. | 337 // has been closed or on return from a sleep state. |
| 336 // (http://crbug.com/105689) | 338 // (http://crbug.com/105689) |
| 337 if (!delegate_->CurrentPageExists()) | 339 if (!delegate_->CurrentPageExists()) |
| 338 break; | 340 break; |
| 339 // Ask for prerendering if the destination URL is different than the | 341 // Ask for prerendering if the destination URL is different than the |
| 340 // current URL. | 342 // current URL. |
| 341 if (current_match.destination_url != PermanentURL()) | 343 if (current_match.destination_url != PermanentURL()) |
| 342 delegate_->DoPrerender(current_match); | 344 delegate_->DoPrerender(current_match); |
| 343 break; | 345 break; |
| 344 case AutocompleteActionPredictor::ACTION_PRECONNECT: | 346 case AutocompleteActionPredictor::ACTION_PRECONNECT: |
| 345 DoPreconnect(current_match); | 347 omnibox_controller_->DoPreconnect(current_match); |
| 346 break; | 348 break; |
| 347 case AutocompleteActionPredictor::ACTION_NONE: | 349 case AutocompleteActionPredictor::ACTION_NONE: |
| 348 break; | 350 break; |
| 349 } | 351 } |
| 350 | 352 |
| 351 controller_->OnChanged(); | 353 controller_->OnChanged(); |
| 352 } | 354 } |
| 353 | 355 |
| 354 void OmniboxEditModel::GetDataForURLExport(GURL* url, | 356 void OmniboxEditModel::GetDataForURLExport(GURL* url, |
| 355 string16* title, | 357 string16* title, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 374 #endif | 376 #endif |
| 375 | 377 |
| 376 // The value of input.prevent_inline_autocomplete() is determined by the | 378 // The value of input.prevent_inline_autocomplete() is determined by the |
| 377 // following conditions: | 379 // following conditions: |
| 378 // 1. If the caret is at the end of the text. | 380 // 1. If the caret is at the end of the text. |
| 379 // 2. If it's in IME composition mode. | 381 // 2. If it's in IME composition mode. |
| 380 // We send the caret position to Instant (so it can determine #1 itself), and | 382 // We send the caret position to Instant (so it can determine #1 itself), and |
| 381 // we use a separated widget for displaying the Instant suggest (so it doesn't | 383 // we use a separated widget for displaying the Instant suggest (so it doesn't |
| 382 // interfere with #2). So, we don't need to care about the value of | 384 // interfere with #2). So, we don't need to care about the value of |
| 383 // input.prevent_inline_autocomplete() here. | 385 // input.prevent_inline_autocomplete() here. |
| 384 return view_->DeleteAtEndPressed() || popup_->selected_line() != 0 || | 386 return view_->DeleteAtEndPressed() || popup_model()->selected_line() != 0 || |
| 385 just_deleted_text_; | 387 just_deleted_text_; |
| 386 } | 388 } |
| 387 | 389 |
| 388 bool OmniboxEditModel::CurrentTextIsURL() const { | 390 bool OmniboxEditModel::CurrentTextIsURL() const { |
| 389 if (view_->toolbar_model()->GetSearchTermsType() != | 391 if (view_->toolbar_model()->GetSearchTermsType() != |
| 390 ToolbarModel::NO_SEARCH_TERMS) | 392 ToolbarModel::NO_SEARCH_TERMS) |
| 391 return false; | 393 return false; |
| 392 | 394 |
| 393 // If current text is not composed of replaced search terms and | 395 // If current text is not composed of replaced search terms and |
| 394 // !user_input_in_progress_, then permanent text is showing and should be a | 396 // !user_input_in_progress_, then permanent text is showing and should be a |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 false, true); | 489 false, true); |
| 488 AutocompleteActionPredictor* action_predictor = | 490 AutocompleteActionPredictor* action_predictor = |
| 489 AutocompleteActionPredictorFactory::GetForProfile(profile_); | 491 AutocompleteActionPredictorFactory::GetForProfile(profile_); |
| 490 if (action_predictor) | 492 if (action_predictor) |
| 491 action_predictor->ClearTransitionalMatches(); | 493 action_predictor->ClearTransitionalMatches(); |
| 492 } | 494 } |
| 493 | 495 |
| 494 void OmniboxEditModel::StartAutocomplete( | 496 void OmniboxEditModel::StartAutocomplete( |
| 495 bool has_selected_text, | 497 bool has_selected_text, |
| 496 bool prevent_inline_autocomplete) const { | 498 bool prevent_inline_autocomplete) const { |
| 497 ClearPopupKeywordMode(); | 499 omnibox_controller_->ClearPopupKeywordMode(); |
| 498 | 500 |
| 499 bool keyword_is_selected = KeywordIsSelected(); | 501 bool keyword_is_selected = KeywordIsSelected(); |
| 500 popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch); | 502 popup_model()->SetHoveredLine(OmniboxPopupModel::kNoMatch); |
| 501 | 503 |
| 502 size_t cursor_position; | 504 size_t cursor_position; |
| 503 if (inline_autocomplete_text_.empty()) { | 505 if (inline_autocomplete_text_.empty()) { |
| 504 // Cursor position is equivalent to the current selection's end. | 506 // Cursor position is equivalent to the current selection's end. |
| 505 size_t start; | 507 size_t start; |
| 506 view_->GetSelectionBounds(&start, &cursor_position); | 508 view_->GetSelectionBounds(&start, &cursor_position); |
| 507 // Adjust cursor position taking into account possible keyword in the user | 509 // Adjust cursor position taking into account possible keyword in the user |
| 508 // text. We rely on DisplayTextFromUserText() method which is consistent | 510 // text. We rely on DisplayTextFromUserText() method which is consistent |
| 509 // with keyword extraction done in KeywordProvider/SearchProvider. | 511 // with keyword extraction done in KeywordProvider/SearchProvider. |
| 510 const size_t cursor_offset = | 512 const size_t cursor_offset = |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 632 view_->OpenMatch(match, disposition, alternate_nav_url, | 634 view_->OpenMatch(match, disposition, alternate_nav_url, |
| 633 OmniboxPopupModel::kNoMatch); | 635 OmniboxPopupModel::kNoMatch); |
| 634 } | 636 } |
| 635 | 637 |
| 636 void OmniboxEditModel::OpenMatch(const AutocompleteMatch& match, | 638 void OmniboxEditModel::OpenMatch(const AutocompleteMatch& match, |
| 637 WindowOpenDisposition disposition, | 639 WindowOpenDisposition disposition, |
| 638 const GURL& alternate_nav_url, | 640 const GURL& alternate_nav_url, |
| 639 size_t index) { | 641 size_t index) { |
| 640 // We only care about cases where there is a selection (i.e. the popup is | 642 // We only care about cases where there is a selection (i.e. the popup is |
| 641 // open). | 643 // open). |
| 642 if (popup_->IsOpen()) { | 644 if (popup_model()->IsOpen()) { |
| 643 const base::TimeTicks& now(base::TimeTicks::Now()); | 645 const base::TimeTicks& now(base::TimeTicks::Now()); |
| 644 // TODO(sreeram): Handle is_temporary_text_set_by_instant_ correctly. | 646 // TODO(sreeram): Handle is_temporary_text_set_by_instant_ correctly. |
| 645 AutocompleteLog log( | 647 AutocompleteLog log( |
| 646 autocomplete_controller()->input().text(), | 648 autocomplete_controller()->input().text(), |
| 647 just_deleted_text_, | 649 just_deleted_text_, |
| 648 autocomplete_controller()->input().type(), | 650 autocomplete_controller()->input().type(), |
| 649 popup_->selected_line(), | 651 popup_model()->selected_line(), |
| 650 -1, // don't yet know tab ID; set later if appropriate | 652 -1, // don't yet know tab ID; set later if appropriate |
| 651 delegate_->CurrentPageExists() ? ClassifyPage(delegate_->GetURL()) : | 653 delegate_->CurrentPageExists() ? ClassifyPage(delegate_->GetURL()) : |
| 652 metrics::OmniboxEventProto_PageClassification_OTHER, | 654 metrics::OmniboxEventProto_PageClassification_OTHER, |
| 653 now - time_user_first_modified_omnibox_, | 655 now - time_user_first_modified_omnibox_, |
| 654 string16::npos, // completed_length; possibly set later | 656 string16::npos, // completed_length; possibly set later |
| 655 now - autocomplete_controller()->last_time_default_match_changed(), | 657 now - autocomplete_controller()->last_time_default_match_changed(), |
| 656 result()); | 658 result()); |
| 657 DCHECK(user_input_in_progress_ || | 659 DCHECK(user_input_in_progress_ || |
| 658 match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST) | 660 match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST) |
| 659 << "We didn't get here through the expected series of calls. " | 661 << "We didn't get here through the expected series of calls. " |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 if (match.starred) | 760 if (match.starred) |
| 759 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX); | 761 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX); |
| 760 } | 762 } |
| 761 | 763 |
| 762 bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) { | 764 bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) { |
| 763 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 765 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
| 764 | 766 |
| 765 autocomplete_controller()->Stop(false); | 767 autocomplete_controller()->Stop(false); |
| 766 is_keyword_hint_ = false; | 768 is_keyword_hint_ = false; |
| 767 | 769 |
| 768 if (popup_->IsOpen()) | 770 if (popup_model()->IsOpen()) |
| 769 popup_->SetSelectedLineState(OmniboxPopupModel::KEYWORD); | 771 popup_model()->SetSelectedLineState(OmniboxPopupModel::KEYWORD); |
| 770 else | 772 else |
| 771 StartAutocomplete(false, true); | 773 StartAutocomplete(false, true); |
| 772 | 774 |
| 773 // Ensure the current selection is saved before showing keyword mode | 775 // Ensure the current selection is saved before showing keyword mode |
| 774 // so that moving to another line and then reverting the text will restore | 776 // so that moving to another line and then reverting the text will restore |
| 775 // the current state properly. | 777 // the current state properly. |
| 776 bool save_original_selection = !has_temporary_text_; | 778 bool save_original_selection = !has_temporary_text_; |
| 777 has_temporary_text_ = true; | 779 has_temporary_text_ = true; |
| 778 is_temporary_text_set_by_instant_ = false; | 780 is_temporary_text_set_by_instant_ = false; |
| 779 is_instant_temporary_text_a_search_query_ = false; | 781 is_instant_temporary_text_a_search_query_ = false; |
| 780 view_->OnTemporaryTextMaybeChanged( | 782 view_->OnTemporaryTextMaybeChanged( |
| 781 DisplayTextFromUserText(CurrentMatch().fill_into_edit), | 783 DisplayTextFromUserText(CurrentMatch().fill_into_edit), |
| 782 save_original_selection, true); | 784 save_original_selection, true); |
| 783 | 785 |
| 784 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); | 786 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); |
| 785 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method, | 787 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method, |
| 786 ENTERED_KEYWORD_MODE_NUM_ITEMS); | 788 ENTERED_KEYWORD_MODE_NUM_ITEMS); |
| 787 | 789 |
| 788 return true; | 790 return true; |
| 789 } | 791 } |
| 790 | 792 |
| 793 void OmniboxEditModel::AcceptTemporaryTextAsUserText() { | |
| 794 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); | |
| 795 has_temporary_text_ = false; | |
| 796 is_temporary_text_set_by_instant_ = false; | |
| 797 OnPopupBoundsChanged(gfx::Rect()); | |
| 798 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); | |
| 799 } | |
| 800 | |
| 791 void OmniboxEditModel::ClearKeyword(const string16& visible_text) { | 801 void OmniboxEditModel::ClearKeyword(const string16& visible_text) { |
| 792 autocomplete_controller()->Stop(false); | 802 autocomplete_controller()->Stop(false); |
| 793 ClearPopupKeywordMode(); | 803 omnibox_controller_->ClearPopupKeywordMode(); |
| 794 | 804 |
| 795 const string16 window_text(keyword_ + visible_text); | 805 const string16 window_text(keyword_ + visible_text); |
| 796 | 806 |
| 797 // Only reset the result if the edit text has changed since the | 807 // Only reset the result if the edit text has changed since the |
| 798 // keyword was accepted, or if the popup is closed. | 808 // keyword was accepted, or if the popup is closed. |
| 799 if (just_deleted_text_ || !visible_text.empty() || !popup_->IsOpen()) { | 809 if (just_deleted_text_ || !visible_text.empty() || !popup_model()->IsOpen()) { |
| 800 view_->OnBeforePossibleChange(); | 810 view_->OnBeforePossibleChange(); |
| 801 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), | 811 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
| 802 false, false); | 812 false, false); |
| 803 keyword_.clear(); | 813 keyword_.clear(); |
| 804 is_keyword_hint_ = false; | 814 is_keyword_hint_ = false; |
| 805 view_->OnAfterPossibleChange(); | 815 view_->OnAfterPossibleChange(); |
| 806 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this | 816 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
| 807 // since the edit contents have actually grown | 817 // since the edit contents have actually grown |
| 808 // longer. | 818 // longer. |
| 809 } else { | 819 } else { |
| 810 is_keyword_hint_ = true; | 820 is_keyword_hint_ = true; |
| 811 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), | 821 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
| 812 false, true); | 822 false, true); |
| 813 } | 823 } |
| 814 } | 824 } |
| 815 | 825 |
| 816 const AutocompleteResult& OmniboxEditModel::result() const { | |
| 817 return autocomplete_controller()->result(); | |
| 818 } | |
| 819 | |
| 820 void OmniboxEditModel::OnSetFocus(bool control_down) { | 826 void OmniboxEditModel::OnSetFocus(bool control_down) { |
| 821 // If the omnibox lost focus while the caret was hidden and then regained | 827 // If the omnibox lost focus while the caret was hidden and then regained |
| 822 // focus, OnSetFocus() is called and should restore visibility. Note that | 828 // focus, OnSetFocus() is called and should restore visibility. Note that |
| 823 // focus can be regained without an accompanying call to | 829 // focus can be regained without an accompanying call to |
| 824 // OmniboxView::SetFocus(), e.g. by tabbing in. | 830 // OmniboxView::SetFocus(), e.g. by tabbing in. |
| 825 SetFocusState(OMNIBOX_FOCUS_VISIBLE, OMNIBOX_FOCUS_CHANGE_EXPLICIT); | 831 SetFocusState(OMNIBOX_FOCUS_VISIBLE, OMNIBOX_FOCUS_CHANGE_EXPLICIT); |
| 826 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; | 832 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; |
| 827 | 833 |
| 828 if (delegate_->CurrentPageExists()) { | 834 if (delegate_->CurrentPageExists()) { |
| 829 // TODO(jered): We may want to merge this into Start() and just call that | 835 // TODO(jered): We may want to merge this into Start() and just call that |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 911 ControlKeyState old_state = control_key_state_; | 917 ControlKeyState old_state = control_key_state_; |
| 912 control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP; | 918 control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP; |
| 913 if ((control_key_state_ == DOWN_WITHOUT_CHANGE) && has_temporary_text_) { | 919 if ((control_key_state_ == DOWN_WITHOUT_CHANGE) && has_temporary_text_) { |
| 914 // Arrowing down and then hitting control accepts the temporary text as | 920 // Arrowing down and then hitting control accepts the temporary text as |
| 915 // the input text. | 921 // the input text. |
| 916 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); | 922 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); |
| 917 has_temporary_text_ = false; | 923 has_temporary_text_ = false; |
| 918 is_temporary_text_set_by_instant_ = false; | 924 is_temporary_text_set_by_instant_ = false; |
| 919 is_instant_temporary_text_a_search_query_ = false; | 925 is_instant_temporary_text_a_search_query_ = false; |
| 920 } | 926 } |
| 921 if ((old_state != DOWN_WITH_CHANGE) && popup_->IsOpen()) { | 927 if ((old_state != DOWN_WITH_CHANGE) && popup_model()->IsOpen()) { |
| 922 // Autocomplete history provider results may change, so refresh the | 928 // Autocomplete history provider results may change, so refresh the |
| 923 // popup. This will force user_input_in_progress_ to true, but if the | 929 // popup. This will force user_input_in_progress_ to true, but if the |
| 924 // popup is open, that should have already been the case. | 930 // popup is open, that should have already been the case. |
| 925 view_->UpdatePopup(); | 931 view_->UpdatePopup(); |
| 926 } | 932 } |
| 927 } | 933 } |
| 928 } | 934 } |
| 929 | 935 |
| 930 void OmniboxEditModel::OnUpOrDownKeyPressed(int count) { | 936 void OmniboxEditModel::OnUpOrDownKeyPressed(int count) { |
| 931 // NOTE: This purposefully doesn't trigger any code that resets paste_state_. | 937 // NOTE: This purposefully doesn't trigger any code that resets paste_state_. |
| 932 if (!popup_->IsOpen()) { | 938 if (!popup_model()->IsOpen()) { |
| 933 if (!query_in_progress()) { | 939 if (!query_in_progress()) { |
| 934 // The popup is neither open nor working on a query already. So, start an | 940 // The popup is neither open nor working on a query already. So, start an |
| 935 // autocomplete query for the current text. This also sets | 941 // autocomplete query for the current text. This also sets |
| 936 // user_input_in_progress_ to true, which we want: if the user has started | 942 // user_input_in_progress_ to true, which we want: if the user has started |
| 937 // to interact with the popup, changing the permanent_text_ shouldn't | 943 // to interact with the popup, changing the permanent_text_ shouldn't |
| 938 // change the displayed text. | 944 // change the displayed text. |
| 939 // Note: This does not force the popup to open immediately. | 945 // Note: This does not force the popup to open immediately. |
| 940 // TODO(pkasting): We should, in fact, force this particular query to open | 946 // TODO(pkasting): We should, in fact, force this particular query to open |
| 941 // the popup immediately. | 947 // the popup immediately. |
| 942 if (!user_input_in_progress_) | 948 if (!user_input_in_progress_) |
| 943 InternalSetUserText(permanent_text_); | 949 InternalSetUserText(permanent_text_); |
| 944 view_->UpdatePopup(); | 950 view_->UpdatePopup(); |
| 945 } else { | 951 } else { |
| 946 // TODO(pkasting): The popup is working on a query but is not open. We | 952 // TODO(pkasting): The popup is working on a query but is not open. We |
| 947 // should force it to open immediately. | 953 // should force it to open immediately. |
| 948 } | 954 } |
| 949 } else { | 955 } else { |
| 950 InstantController* instant = controller_->GetInstant(); | 956 InstantController* instant = controller_->GetInstant(); |
| 951 if (instant && instant->OnUpOrDownKeyPressed(count)) { | 957 if (instant && instant->OnUpOrDownKeyPressed(count)) { |
| 952 // If Instant handles the key press, it's showing a list of suggestions | 958 // If Instant handles the key press, it's showing a list of suggestions |
| 953 // that it's stepping through. In that case, our popup model is | 959 // that it's stepping through. In that case, our popup model is |
| 954 // irrelevant, so don't process the key press ourselves. However, do stop | 960 // irrelevant, so don't process the key press ourselves. However, do stop |
| 955 // the autocomplete system from changing the results. | 961 // the autocomplete system from changing the results. |
| 956 autocomplete_controller()->Stop(false); | 962 autocomplete_controller()->Stop(false); |
| 957 } else { | 963 } else { |
| 958 // The popup is open, so the user should be able to interact with it | 964 // The popup is open, so the user should be able to interact with it |
| 959 // normally. | 965 // normally. |
| 960 popup_->Move(count); | 966 popup_model()->Move(count); |
| 961 } | 967 } |
| 962 } | 968 } |
| 963 } | 969 } |
| 964 | 970 |
| 965 void OmniboxEditModel::OnPopupDataChanged( | 971 void OmniboxEditModel::OnPopupDataChanged( |
| 966 const string16& text, | 972 const string16& text, |
| 967 GURL* destination_for_temporary_text_change, | 973 GURL* destination_for_temporary_text_change, |
| 968 const string16& keyword, | 974 const string16& keyword, |
| 969 bool is_keyword_hint) { | 975 bool is_keyword_hint) { |
| 976 DLOG(ERROR) << "A"; | |
|
Mathieu
2013/05/03 19:09:02
remove
beaudoin
2013/05/04 03:06:51
/facepalm. :)
Done.
| |
| 970 // Update keyword/hint-related local state. | 977 // Update keyword/hint-related local state. |
| 971 bool keyword_state_changed = (keyword_ != keyword) || | 978 bool keyword_state_changed = (keyword_ != keyword) || |
| 972 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); | 979 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); |
| 973 if (keyword_state_changed) { | 980 if (keyword_state_changed) { |
| 974 keyword_ = keyword; | 981 keyword_ = keyword; |
| 975 is_keyword_hint_ = is_keyword_hint; | 982 is_keyword_hint_ = is_keyword_hint; |
| 976 | 983 |
| 977 // |is_keyword_hint_| should always be false if |keyword_| is empty. | 984 // |is_keyword_hint_| should always be false if |keyword_| is empty. |
| 978 DCHECK(!keyword_.empty() || !is_keyword_hint_); | 985 DCHECK(!keyword_.empty() || !is_keyword_hint_); |
| 979 } | 986 } |
| 980 | 987 |
| 988 DLOG(ERROR) << "B"; | |
| 981 // Handle changes to temporary text. | 989 // Handle changes to temporary text. |
| 982 if (destination_for_temporary_text_change != NULL) { | 990 if (destination_for_temporary_text_change != NULL) { |
| 983 const bool save_original_selection = !has_temporary_text_; | 991 const bool save_original_selection = !has_temporary_text_; |
| 984 if (save_original_selection) { | 992 if (save_original_selection) { |
| 985 // Save the original selection and URL so it can be reverted later. | 993 // Save the original selection and URL so it can be reverted later. |
| 986 has_temporary_text_ = true; | 994 has_temporary_text_ = true; |
| 987 is_temporary_text_set_by_instant_ = false; | 995 is_temporary_text_set_by_instant_ = false; |
| 988 is_instant_temporary_text_a_search_query_ = false; | 996 is_instant_temporary_text_a_search_query_ = false; |
| 989 original_url_ = *destination_for_temporary_text_change; | 997 original_url_ = *destination_for_temporary_text_change; |
| 990 inline_autocomplete_text_.clear(); | 998 inline_autocomplete_text_.clear(); |
| 991 } | 999 } |
| 1000 DLOG(ERROR) << "C"; | |
| 992 if (control_key_state_ == DOWN_WITHOUT_CHANGE) { | 1001 if (control_key_state_ == DOWN_WITHOUT_CHANGE) { |
| 993 // Arrowing around the popup cancels control-enter. | 1002 // Arrowing around the popup cancels control-enter. |
| 994 control_key_state_ = DOWN_WITH_CHANGE; | 1003 control_key_state_ = DOWN_WITH_CHANGE; |
| 995 // Now things are a bit screwy: the desired_tld has changed, but if we | 1004 // Now things are a bit screwy: the desired_tld has changed, but if we |
| 996 // update the popup, the new order of entries won't match the old, so the | 1005 // update the popup, the new order of entries won't match the old, so the |
| 997 // user's selection gets screwy; and if we don't update the popup, and the | 1006 // user's selection gets screwy; and if we don't update the popup, and the |
| 998 // user reverts, then the selected item will be as if control is still | 1007 // user reverts, then the selected item will be as if control is still |
| 999 // pressed, even though maybe it isn't any more. There is no obvious | 1008 // pressed, even though maybe it isn't any more. There is no obvious |
| 1000 // right answer here :( | 1009 // right answer here :( |
| 1001 } | 1010 } |
| 1011 DLOG(ERROR) << "D"; | |
| 1002 view_->OnTemporaryTextMaybeChanged(DisplayTextFromUserText(text), | 1012 view_->OnTemporaryTextMaybeChanged(DisplayTextFromUserText(text), |
| 1003 save_original_selection, true); | 1013 save_original_selection, true); |
| 1004 return; | 1014 return; |
| 1005 } | 1015 } |
| 1016 DLOG(ERROR) << "E: " << keyword_state_changed; | |
| 1006 | 1017 |
| 1007 bool call_controller_onchanged = true; | 1018 bool call_controller_onchanged = true; |
| 1008 inline_autocomplete_text_ = text; | 1019 inline_autocomplete_text_ = text; |
| 1009 | 1020 |
| 1010 if (keyword_state_changed && KeywordIsSelected()) { | 1021 if (keyword_state_changed && KeywordIsSelected()) { |
| 1011 // If we reach here, the user most likely entered keyword mode by inserting | 1022 // If we reach here, the user most likely entered keyword mode by inserting |
| 1012 // a space between a keyword name and a search string (as pressing space or | 1023 // a space between a keyword name and a search string (as pressing space or |
| 1013 // tab after the keyword name alone would have been be handled in | 1024 // tab after the keyword name alone would have been be handled in |
| 1014 // MaybeAcceptKeywordBySpace() by calling AcceptKeyword(), which won't reach | 1025 // MaybeAcceptKeywordBySpace() by calling AcceptKeyword(), which won't reach |
| 1015 // here). In this case, we don't want to call | 1026 // here). In this case, we don't want to call |
| 1016 // OnInlineAutocompleteTextMaybeChanged() as normal, because that will | 1027 // OnInlineAutocompleteTextMaybeChanged() as normal, because that will |
| 1017 // correctly change the text (to the search string alone) but move the caret | 1028 // correctly change the text (to the search string alone) but move the caret |
| 1018 // to the end of the string; instead we want the caret at the start of the | 1029 // to the end of the string; instead we want the caret at the start of the |
| 1019 // search string since that's where it was in the original input. So we set | 1030 // search string since that's where it was in the original input. So we set |
| 1020 // the text and caret position directly. | 1031 // the text and caret position directly. |
| 1021 // | 1032 // |
| 1022 // It may also be possible to reach here if we're reverting from having | 1033 // It may also be possible to reach here if we're reverting from having |
| 1023 // temporary text back to a default match that's a keyword search, but in | 1034 // temporary text back to a default match that's a keyword search, but in |
| 1024 // that case the RevertTemporaryText() call below will reset the caret or | 1035 // that case the RevertTemporaryText() call below will reset the caret or |
| 1025 // selection correctly so the caret positioning we do here won't matter. | 1036 // selection correctly so the caret positioning we do here won't matter. |
| 1037 DLOG(ERROR) << "F"; | |
| 1026 view_->SetWindowTextAndCaretPos(DisplayTextFromUserText(user_text_), 0, | 1038 view_->SetWindowTextAndCaretPos(DisplayTextFromUserText(user_text_), 0, |
| 1027 false, false); | 1039 false, false); |
| 1028 } else if (view_->OnInlineAutocompleteTextMaybeChanged( | 1040 } else if (view_->OnInlineAutocompleteTextMaybeChanged( |
| 1029 DisplayTextFromUserText(user_text_ + inline_autocomplete_text_), | 1041 DisplayTextFromUserText(user_text_ + inline_autocomplete_text_), |
| 1030 DisplayTextFromUserText(user_text_).length())) { | 1042 DisplayTextFromUserText(user_text_).length())) { |
| 1043 DLOG(ERROR) << "G"; | |
| 1031 call_controller_onchanged = false; | 1044 call_controller_onchanged = false; |
| 1032 } | 1045 } |
| 1033 | 1046 |
| 1034 // If |has_temporary_text_| is true, then we previously had a manual selection | 1047 // If |has_temporary_text_| is true, then we previously had a manual selection |
| 1035 // but now don't (or |destination_for_temporary_text_change| would have been | 1048 // but now don't (or |destination_for_temporary_text_change| would have been |
| 1036 // non-NULL). This can happen when deleting the selected item in the popup. | 1049 // non-NULL). This can happen when deleting the selected item in the popup. |
| 1037 // In this case, we've already reverted the popup to the default match, so we | 1050 // In this case, we've already reverted the popup to the default match, so we |
| 1038 // need to revert ourselves as well. | 1051 // need to revert ourselves as well. |
| 1052 DLOG(ERROR) << "H"; | |
| 1039 if (has_temporary_text_) { | 1053 if (has_temporary_text_) { |
| 1040 RevertTemporaryText(false); | 1054 RevertTemporaryText(false); |
| 1041 call_controller_onchanged = false; | 1055 call_controller_onchanged = false; |
| 1042 } | 1056 } |
| 1043 | 1057 |
| 1058 DLOG(ERROR) << "I"; | |
| 1044 // We need to invoke OnChanged in case the destination url changed (as could | 1059 // We need to invoke OnChanged in case the destination url changed (as could |
| 1045 // happen when control is toggled). | 1060 // happen when control is toggled). |
| 1046 if (call_controller_onchanged) | 1061 if (call_controller_onchanged) |
| 1047 OnChanged(); | 1062 OnChanged(); |
| 1048 } | 1063 } |
| 1049 | 1064 |
| 1050 bool OmniboxEditModel::OnAfterPossibleChange(const string16& old_text, | 1065 bool OmniboxEditModel::OnAfterPossibleChange(const string16& old_text, |
| 1051 const string16& new_text, | 1066 const string16& new_text, |
| 1052 size_t selection_start, | 1067 size_t selection_start, |
| 1053 size_t selection_end, | 1068 size_t selection_end, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1071 // Modifying the selection counts as accepting the autocompleted text. | 1086 // Modifying the selection counts as accepting the autocompleted text. |
| 1072 const bool user_text_changed = | 1087 const bool user_text_changed = |
| 1073 text_differs || (selection_differs && !inline_autocomplete_text_.empty()); | 1088 text_differs || (selection_differs && !inline_autocomplete_text_.empty()); |
| 1074 | 1089 |
| 1075 // If something has changed while the control key is down, prevent | 1090 // If something has changed while the control key is down, prevent |
| 1076 // "ctrl-enter" until the control key is released. When we do this, we need | 1091 // "ctrl-enter" until the control key is released. When we do this, we need |
| 1077 // to update the popup if it's open, since the desired_tld will have changed. | 1092 // to update the popup if it's open, since the desired_tld will have changed. |
| 1078 if ((text_differs || selection_differs) && | 1093 if ((text_differs || selection_differs) && |
| 1079 (control_key_state_ == DOWN_WITHOUT_CHANGE)) { | 1094 (control_key_state_ == DOWN_WITHOUT_CHANGE)) { |
| 1080 control_key_state_ = DOWN_WITH_CHANGE; | 1095 control_key_state_ = DOWN_WITH_CHANGE; |
| 1081 if (!text_differs && !popup_->IsOpen()) | 1096 if (!text_differs && !popup_model()->IsOpen()) |
| 1082 return false; // Don't open the popup for no reason. | 1097 return false; // Don't open the popup for no reason. |
| 1083 } else if (!user_text_changed) { | 1098 } else if (!user_text_changed) { |
| 1084 return false; | 1099 return false; |
| 1085 } | 1100 } |
| 1086 | 1101 |
| 1087 // If the user text has not changed, we do not want to change the model's | 1102 // If the user text has not changed, we do not want to change the model's |
| 1088 // state associated with the text. Otherwise, we can get surprising behavior | 1103 // state associated with the text. Otherwise, we can get surprising behavior |
| 1089 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 | 1104 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 |
| 1090 if (user_text_changed) { | 1105 if (user_text_changed) { |
| 1091 InternalSetUserText(UserTextFromDisplayText(new_text)); | 1106 InternalSetUserText(UserTextFromDisplayText(new_text)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1143 MaybeAcceptKeywordBySpace(user_text_)); | 1158 MaybeAcceptKeywordBySpace(user_text_)); |
| 1144 } | 1159 } |
| 1145 | 1160 |
| 1146 void OmniboxEditModel::OnPopupBoundsChanged(const gfx::Rect& bounds) { | 1161 void OmniboxEditModel::OnPopupBoundsChanged(const gfx::Rect& bounds) { |
| 1147 InstantController* instant = controller_->GetInstant(); | 1162 InstantController* instant = controller_->GetInstant(); |
| 1148 if (instant) | 1163 if (instant) |
| 1149 instant->SetPopupBounds(bounds); | 1164 instant->SetPopupBounds(bounds); |
| 1150 } | 1165 } |
| 1151 | 1166 |
| 1152 void OmniboxEditModel::OnResultChanged(bool default_match_changed) { | 1167 void OmniboxEditModel::OnResultChanged(bool default_match_changed) { |
| 1153 const bool was_open = popup_->IsOpen(); | |
| 1154 if (default_match_changed) { | |
| 1155 string16 inline_autocomplete_text; | |
| 1156 string16 keyword; | |
| 1157 bool is_keyword_hint = false; | |
| 1158 const AutocompleteResult& result = this->result(); | |
| 1159 const AutocompleteResult::const_iterator match(result.default_match()); | |
| 1160 if (match != result.end()) { | |
| 1161 if ((match->inline_autocomplete_offset != string16::npos) && | |
| 1162 (match->inline_autocomplete_offset < | |
| 1163 match->fill_into_edit.length())) { | |
| 1164 inline_autocomplete_text = | |
| 1165 match->fill_into_edit.substr(match->inline_autocomplete_offset); | |
| 1166 } | |
| 1167 | |
| 1168 if (!prerender::IsOmniboxEnabled(profile_)) | |
| 1169 DoPreconnect(*match); | |
| 1170 | |
| 1171 // We could prefetch the alternate nav URL, if any, but because there | |
| 1172 // can be many of these as a user types an initial series of characters, | |
| 1173 // the OS DNS cache could suffer eviction problems for minimal gain. | |
| 1174 | |
| 1175 match->GetKeywordUIState(profile_, &keyword, &is_keyword_hint); | |
| 1176 } | |
| 1177 | |
| 1178 popup_->OnResultChanged(); | |
| 1179 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, | |
| 1180 is_keyword_hint); | |
| 1181 } else { | |
| 1182 popup_->OnResultChanged(); | |
| 1183 } | |
| 1184 | |
| 1185 if (popup_->IsOpen()) { | |
| 1186 OnPopupBoundsChanged(popup_->view()->GetTargetBounds()); | |
| 1187 | |
| 1188 InstantController* instant = controller_->GetInstant(); | |
| 1189 if (instant && !in_revert_) { | |
| 1190 instant->HandleAutocompleteResults( | |
| 1191 *autocomplete_controller()->providers()); | |
| 1192 } | |
| 1193 } else if (was_open) { | |
| 1194 // Accepts the temporary text as the user text, because it makes little | |
| 1195 // sense to have temporary text when the popup is closed. | |
| 1196 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); | |
| 1197 has_temporary_text_ = false; | |
| 1198 is_temporary_text_set_by_instant_ = false; | |
| 1199 is_instant_temporary_text_a_search_query_ = false; | |
| 1200 OnPopupBoundsChanged(gfx::Rect()); | |
| 1201 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_); | |
| 1202 } | |
| 1203 } | 1168 } |
| 1204 | 1169 |
| 1205 bool OmniboxEditModel::query_in_progress() const { | 1170 bool OmniboxEditModel::query_in_progress() const { |
| 1206 return !autocomplete_controller()->done(); | 1171 return !autocomplete_controller()->done(); |
| 1207 } | 1172 } |
| 1208 | 1173 |
| 1209 void OmniboxEditModel::InternalSetUserText(const string16& text) { | 1174 void OmniboxEditModel::InternalSetUserText(const string16& text) { |
| 1210 user_text_ = text; | 1175 user_text_ = text; |
| 1211 just_deleted_text_ = false; | 1176 just_deleted_text_ = false; |
| 1212 inline_autocomplete_text_.clear(); | 1177 inline_autocomplete_text_.clear(); |
| 1213 } | 1178 } |
| 1214 | 1179 |
| 1215 bool OmniboxEditModel::KeywordIsSelected() const { | 1180 bool OmniboxEditModel::KeywordIsSelected() const { |
| 1216 return !is_keyword_hint_ && !keyword_.empty(); | 1181 return !is_keyword_hint_ && !keyword_.empty(); |
| 1217 } | 1182 } |
| 1218 | 1183 |
| 1219 void OmniboxEditModel::ClearPopupKeywordMode() const { | |
| 1220 if (popup_->IsOpen() && | |
| 1221 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) | |
| 1222 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); | |
| 1223 } | |
| 1224 | |
| 1225 string16 OmniboxEditModel::DisplayTextFromUserText(const string16& text) const { | 1184 string16 OmniboxEditModel::DisplayTextFromUserText(const string16& text) const { |
| 1226 return KeywordIsSelected() ? | 1185 return KeywordIsSelected() ? |
| 1227 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; | 1186 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; |
| 1228 } | 1187 } |
| 1229 | 1188 |
| 1230 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const { | 1189 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const { |
| 1231 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; | 1190 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; |
| 1232 } | 1191 } |
| 1233 | 1192 |
| 1234 void OmniboxEditModel::InfoForCurrentSelection(AutocompleteMatch* match, | |
| 1235 GURL* alternate_nav_url) const { | |
| 1236 DCHECK(match != NULL); | |
| 1237 const AutocompleteResult& result = this->result(); | |
| 1238 if (!autocomplete_controller()->done()) { | |
| 1239 // It's technically possible for |result| to be empty if no provider returns | |
| 1240 // a synchronous result but the query has not completed synchronously; | |
| 1241 // pratically, however, that should never actually happen. | |
| 1242 if (result.empty()) | |
| 1243 return; | |
| 1244 // The user cannot have manually selected a match, or the query would have | |
| 1245 // stopped. So the default match must be the desired selection. | |
| 1246 *match = *result.default_match(); | |
| 1247 } else { | |
| 1248 CHECK(popup_->IsOpen()); | |
| 1249 // If there are no results, the popup should be closed (so we should have | |
| 1250 // failed the CHECK above), and URLsForDefaultMatch() should have been | |
| 1251 // called instead. | |
| 1252 CHECK(!result.empty()); | |
| 1253 CHECK(popup_->selected_line() < result.size()); | |
| 1254 *match = result.match_at(popup_->selected_line()); | |
| 1255 } | |
| 1256 if (alternate_nav_url && popup_->manually_selected_match().empty()) | |
| 1257 *alternate_nav_url = result.alternate_nav_url(); | |
| 1258 } | |
| 1259 | |
| 1260 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match, | 1193 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match, |
| 1261 GURL* alternate_nav_url) const { | 1194 GURL* alternate_nav_url) const { |
| 1262 // If there's temporary text and it has been set by Instant, we won't find it | 1195 // If there's temporary text and it has been set by Instant, we won't find it |
| 1263 // in the popup model, so create the match based on the type Instant told us | 1196 // in the popup model, so classify the text anew. |
| 1264 // (SWYT for queries and UWYT for URLs). We do this instead of classifying the | 1197 if ((popup_model()->IsOpen() || query_in_progress()) && |
| 1265 // text ourselves because the text may look like a URL, but Instant may expect | 1198 !is_temporary_text_set_by_instant_) { |
| 1266 // it to be a search (e.g.: a query for "amazon.com"). | |
| 1267 if (is_temporary_text_set_by_instant_) { | |
| 1268 const string16& text = view_->GetText(); | |
| 1269 AutocompleteInput input(text, string16::npos, string16(), GURL(), false, | |
| 1270 false, false, AutocompleteInput::BEST_MATCH); | |
| 1271 // Only the destination_url and the transition of the match will be be used | |
| 1272 // (to either navigate to the URL or let Instant commit its preview). The | |
| 1273 // match won't be used for logging, displaying in the dropdown, etc. So, | |
| 1274 // it's okay to pass in mostly bogus params (such as relevance = 0). | |
| 1275 // TODO(sreeram): Always using NO_SUGGESTIONS_AVAILABLE is wrong when | |
| 1276 // Instant is using the local fallback overlay. Fix. | |
| 1277 if (is_instant_temporary_text_a_search_query_) { | |
| 1278 const TemplateURL* default_provider = | |
| 1279 TemplateURLServiceFactory::GetForProfile(profile_)-> | |
| 1280 GetDefaultSearchProvider(); | |
| 1281 if (default_provider && default_provider->SupportsReplacement()) { | |
| 1282 *match = SearchProvider::CreateSearchSuggestion(profile_, | |
| 1283 autocomplete_controller()->search_provider(), input, text, text, 0, | |
| 1284 AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, | |
| 1285 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, false, | |
| 1286 default_provider->keyword()); | |
| 1287 } else { | |
| 1288 // Can't create a new search match. Leave |match| as is, with an | |
| 1289 // invalid destination_url. This shouldn't ever happen. For example, | |
| 1290 // even if a group policy update in the midst of interacting with | |
| 1291 // Instant leaves us without a valid search provider, Instant should've | |
| 1292 // observed the update and reset |is_temporary_text_set_by_instant_|, | |
| 1293 // so we still shouldn't get here. However, as protection against the | |
| 1294 // unknowns and Instant regressions, we simply return an invalid match | |
| 1295 // instead of crashing (hence no DCHECK). | |
| 1296 } | |
| 1297 } else { | |
| 1298 *match = HistoryURLProvider::SuggestExactInput( | |
| 1299 autocomplete_controller()->history_url_provider(), input, false); | |
| 1300 } | |
| 1301 } else if (popup_->IsOpen() || query_in_progress()) { | |
| 1302 InfoForCurrentSelection(match, alternate_nav_url); | 1199 InfoForCurrentSelection(match, alternate_nav_url); |
| 1303 } else { | 1200 } else { |
| 1304 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify( | 1201 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify( |
| 1305 UserTextFromDisplayText(view_->GetText()), KeywordIsSelected(), true, | 1202 UserTextFromDisplayText(view_->GetText()), KeywordIsSelected(), true, |
| 1306 match, alternate_nav_url); | 1203 match, alternate_nav_url); |
| 1307 } | 1204 } |
| 1308 } | 1205 } |
| 1309 | 1206 |
| 1310 void OmniboxEditModel::RevertTemporaryText(bool revert_popup) { | 1207 void OmniboxEditModel::RevertTemporaryText(bool revert_popup) { |
| 1311 // The user typed something, then selected a different item. Restore the | 1208 // The user typed something, then selected a different item. Restore the |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1329 // The two "false" arguments make sure that our shenanigans don't cause any | 1226 // The two "false" arguments make sure that our shenanigans don't cause any |
| 1330 // previously saved selection to be erased nor OnChanged() to be called. | 1227 // previously saved selection to be erased nor OnChanged() to be called. |
| 1331 view_->OnTemporaryTextMaybeChanged(user_text_ + inline_autocomplete_text_, | 1228 view_->OnTemporaryTextMaybeChanged(user_text_ + inline_autocomplete_text_, |
| 1332 false, false); | 1229 false, false); |
| 1333 AutocompleteResult::const_iterator match(result().default_match()); | 1230 AutocompleteResult::const_iterator match(result().default_match()); |
| 1334 instant->OnCancel(match != result().end() ? *match : AutocompleteMatch(), | 1231 instant->OnCancel(match != result().end() ? *match : AutocompleteMatch(), |
| 1335 user_text_, | 1232 user_text_, |
| 1336 user_text_ + inline_autocomplete_text_); | 1233 user_text_ + inline_autocomplete_text_); |
| 1337 } | 1234 } |
| 1338 if (revert_popup) | 1235 if (revert_popup) |
| 1339 popup_->ResetToDefaultMatch(); | 1236 popup_model()->ResetToDefaultMatch(); |
| 1340 view_->OnRevertTemporaryText(); | 1237 view_->OnRevertTemporaryText(); |
| 1341 } | 1238 } |
| 1342 | 1239 |
| 1343 bool OmniboxEditModel::MaybeAcceptKeywordBySpace(const string16& new_text) { | 1240 bool OmniboxEditModel::MaybeAcceptKeywordBySpace(const string16& new_text) { |
| 1344 size_t keyword_length = new_text.length() - 1; | 1241 size_t keyword_length = new_text.length() - 1; |
| 1345 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && | 1242 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && |
| 1346 inline_autocomplete_text_.empty() && | 1243 inline_autocomplete_text_.empty() && |
| 1347 (keyword_.length() == keyword_length) && | 1244 (keyword_.length() == keyword_length) && |
| 1348 IsSpaceCharForAcceptingKeyword(new_text[keyword_length]) && | 1245 IsSpaceCharForAcceptingKeyword(new_text[keyword_length]) && |
| 1349 !new_text.compare(0, keyword_length, keyword_, 0, keyword_length) && | 1246 !new_text.compare(0, keyword_length, keyword_, 0, keyword_length) && |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1400 // Remove "?" if we're in forced query mode. | 1297 // Remove "?" if we're in forced query mode. |
| 1401 AutocompleteInput::RemoveForcedQueryStringIfNecessary( | 1298 AutocompleteInput::RemoveForcedQueryStringIfNecessary( |
| 1402 autocomplete_controller()->input().type(), &user_text); | 1299 autocomplete_controller()->input().type(), &user_text); |
| 1403 AutocompleteInput::RemoveForcedQueryStringIfNecessary( | 1300 AutocompleteInput::RemoveForcedQueryStringIfNecessary( |
| 1404 autocomplete_controller()->input().type(), &full_text); | 1301 autocomplete_controller()->input().type(), &full_text); |
| 1405 | 1302 |
| 1406 size_t start, end; | 1303 size_t start, end; |
| 1407 view_->GetSelectionBounds(&start, &end); | 1304 view_->GetSelectionBounds(&start, &end); |
| 1408 | 1305 |
| 1409 return instant->Update(match, user_text, full_text, start, end, | 1306 return instant->Update(match, user_text, full_text, start, end, |
| 1410 UseVerbatimInstant(), user_input_in_progress_, popup_->IsOpen(), | 1307 UseVerbatimInstant(), user_input_in_progress_, popup_model()->IsOpen(), |
| 1411 in_escape_handler_, KeywordIsSelected()); | 1308 in_escape_handler_, KeywordIsSelected()); |
| 1412 } | 1309 } |
| 1413 | 1310 |
| 1414 void OmniboxEditModel::DoPreconnect(const AutocompleteMatch& match) { | |
| 1415 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { | |
| 1416 // Warm up DNS Prefetch cache, or preconnect to a search service. | |
| 1417 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, | |
| 1418 AutocompleteMatch::NUM_TYPES); | |
| 1419 if (profile_->GetNetworkPredictor()) { | |
| 1420 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( | |
| 1421 match.destination_url, | |
| 1422 AutocompleteActionPredictor::IsPreconnectable(match)); | |
| 1423 } | |
| 1424 // We could prefetch the alternate nav URL, if any, but because there | |
| 1425 // can be many of these as a user types an initial series of characters, | |
| 1426 // the OS DNS cache could suffer eviction problems for minimal gain. | |
| 1427 } | |
| 1428 } | |
| 1429 | |
| 1430 // static | 1311 // static |
| 1431 bool OmniboxEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 1312 bool OmniboxEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
| 1432 switch (c) { | 1313 switch (c) { |
| 1433 case 0x0020: // Space | 1314 case 0x0020: // Space |
| 1434 case 0x3000: // Ideographic Space | 1315 case 0x3000: // Ideographic Space |
| 1435 return true; | 1316 return true; |
| 1436 default: | 1317 default: |
| 1437 return false; | 1318 return false; |
| 1438 } | 1319 } |
| 1439 } | 1320 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1471 instant->OmniboxFocusChanged(state, reason, NULL); | 1352 instant->OmniboxFocusChanged(state, reason, NULL); |
| 1472 | 1353 |
| 1473 // Update state and notify view if the omnibox has focus and the caret | 1354 // Update state and notify view if the omnibox has focus and the caret |
| 1474 // visibility changed. | 1355 // visibility changed. |
| 1475 const bool was_caret_visible = is_caret_visible(); | 1356 const bool was_caret_visible = is_caret_visible(); |
| 1476 focus_state_ = state; | 1357 focus_state_ = state; |
| 1477 if (focus_state_ != OMNIBOX_FOCUS_NONE && | 1358 if (focus_state_ != OMNIBOX_FOCUS_NONE && |
| 1478 is_caret_visible() != was_caret_visible) | 1359 is_caret_visible() != was_caret_visible) |
| 1479 view_->ApplyCaretVisibility(); | 1360 view_->ApplyCaretVisibility(); |
| 1480 } | 1361 } |
| OLD | NEW |