Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_controller.h" | 5 #include "chrome/browser/ui/omnibox/omnibox_controller.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | 8 #include "chrome/browser/autocomplete/autocomplete_classifier.h" |
| 9 #include "chrome/browser/autocomplete/autocomplete_match.h" | 9 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 10 #include "chrome/browser/autocomplete/search_provider.h" | 10 #include "chrome/browser/autocomplete/search_provider.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 #include "extensions/common/constants.h" | 23 #include "extensions/common/constants.h" |
| 24 #include "ui/gfx/rect.h" | 24 #include "ui/gfx/rect.h" |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // Returns the AutocompleteMatch that the InstantController should prefetch, if | 28 // Returns the AutocompleteMatch that the InstantController should prefetch, if |
| 29 // any. | 29 // any. |
| 30 // | 30 // |
| 31 // The SearchProvider may mark some suggestions to be prefetched based on | 31 // The SearchProvider may mark some suggestions to be prefetched based on |
| 32 // instructions from the suggest server. If such a match ranks sufficiently | 32 // instructions from the suggest server. If such a match ranks sufficiently |
| 33 // highly, we'll return it. | 33 // highly or if kAllowPrefetchNonDefaultMatch field trial is enabled, we'll |
| 34 // return it. | |
| 34 // | 35 // |
| 35 // We only care about matches that are the default or the very first entry in | 36 // If the kAllowPrefetchNonDefaultMatch field trial is enabled we return the |
| 36 // the dropdown (which can happen for non-default matches only if we're hiding | 37 // prefetch suggestion even if it is not the default match. Otherwise we only |
| 37 // a top verbatim match) or the second entry in the dropdown (which can happen | 38 // care about matches that are the default or the very first entry in the |
| 38 // for non-default matches when a top verbatim match is shown); for other | 39 // dropdown (which can happen for non-default matches only if we're hiding a top |
| 39 // matches, we think the likelihood of the user selecting them is low enough | 40 // verbatim match) or the second entry in the dropdown (which can happen for |
| 40 // that prefetching isn't worth doing. | 41 // non-default matches when a top verbatim match is shown); for other matches, |
| 42 // we think the likelihood of the user selecting them is low enough that | |
| 43 // prefetching isn't worth doing. | |
| 41 const AutocompleteMatch* GetMatchToPrefetch(const AutocompleteResult& result) { | 44 const AutocompleteMatch* GetMatchToPrefetch(const AutocompleteResult& result) { |
| 42 // If the default match should be prefetched, do that. | 45 if (chrome::ShouldAllowPrefetchNonDefaultMatch()) { |
| 43 const AutocompleteResult::const_iterator default_match( | 46 const AutocompleteResult::const_iterator prefetch_match = std::find_if( |
| 44 result.default_match()); | 47 result.begin(), result.end(), SearchProvider::ShouldPrefetch); |
| 45 if ((default_match != result.end()) && | 48 return prefetch_match != result.end() ? &(*prefetch_match) : NULL; |
| 46 SearchProvider::ShouldPrefetch(*default_match)) | 49 } else { |
|
Peter Kasting
2014/06/19 23:03:09
Nit: No else after return.
sidharthms
2014/06/20 00:30:49
Done.
| |
| 47 return &(*default_match); | 50 // If the default match should be prefetched, do that. |
| 51 const AutocompleteResult::const_iterator default_match( | |
| 52 result.default_match()); | |
| 53 if ((default_match != result.end()) && | |
| 54 SearchProvider::ShouldPrefetch(*default_match)) | |
| 55 return &(*default_match); | |
| 48 | 56 |
| 49 // Otherwise, if the top match is a verbatim match and the very next match is | 57 // Otherwise, if the top match is a verbatim match and the very next match |
| 50 // prefetchable, fetch that. | 58 // is prefetchable, fetch that. |
| 51 if ((result.ShouldHideTopMatch() || | 59 if ((result.ShouldHideTopMatch() || |
| 52 result.TopMatchIsStandaloneVerbatimMatch()) && | 60 result.TopMatchIsStandaloneVerbatimMatch()) && |
| 53 (result.size() > 1) && | 61 (result.size() > 1) && |
| 54 SearchProvider::ShouldPrefetch(result.match_at(1))) | 62 SearchProvider::ShouldPrefetch(result.match_at(1))) |
| 55 return &result.match_at(1); | 63 return &result.match_at(1); |
| 56 | 64 |
| 57 return NULL; | 65 return NULL; |
| 66 } | |
| 58 } | 67 } |
| 59 | 68 |
| 60 } // namespace | 69 } // namespace |
| 61 | 70 |
| 62 OmniboxController::OmniboxController(OmniboxEditModel* omnibox_edit_model, | 71 OmniboxController::OmniboxController(OmniboxEditModel* omnibox_edit_model, |
| 63 Profile* profile) | 72 Profile* profile) |
| 64 : omnibox_edit_model_(omnibox_edit_model), | 73 : omnibox_edit_model_(omnibox_edit_model), |
| 65 profile_(profile), | 74 profile_(profile), |
| 66 popup_(NULL), | 75 popup_(NULL), |
| 67 autocomplete_controller_(new AutocompleteController(profile, this, | 76 autocomplete_controller_(new AutocompleteController(profile, this, |
| 68 AutocompleteClassifier::kDefaultOmniboxProviders)) { | 77 AutocompleteClassifier::kDefaultOmniboxProviders)) { |
| 69 } | 78 } |
| 70 | 79 |
| 71 OmniboxController::~OmniboxController() { | 80 OmniboxController::~OmniboxController() { |
| 72 } | 81 } |
| 73 | 82 |
| 74 void OmniboxController::StartAutocomplete( | 83 void OmniboxController::StartAutocomplete( |
| 75 const AutocompleteInput& input) const { | 84 const AutocompleteInput& input) const { |
| 76 ClearPopupKeywordMode(); | 85 ClearPopupKeywordMode(); |
| 77 popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch); | 86 popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch); |
| 78 | 87 |
| 79 // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as | 88 // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as |
| 80 // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it. | 89 // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it. |
| 81 autocomplete_controller_->Start(input); | 90 autocomplete_controller_->Start(input); |
| 82 } | 91 } |
| 83 | 92 |
| 84 void OmniboxController::OnResultChanged(bool default_match_changed) { | 93 void OmniboxController::OnResultChanged(bool default_match_changed) { |
| 85 const bool was_open = popup_->IsOpen(); | 94 const bool was_open = popup_->IsOpen(); |
| 95 const AutocompleteResult& result = this->result(); | |
|
Peter Kasting
2014/06/19 23:03:09
Nit: I think it would be better to remove this and
sidharthms
2014/06/20 00:30:49
Done.
| |
| 86 if (default_match_changed) { | 96 if (default_match_changed) { |
| 87 // The default match has changed, we need to let the OmniboxEditModel know | 97 // The default match has changed, we need to let the OmniboxEditModel know |
| 88 // about new inline autocomplete text (blue highlight). | 98 // about new inline autocomplete text (blue highlight). |
| 89 const AutocompleteResult& result = this->result(); | |
| 90 const AutocompleteResult::const_iterator match(result.default_match()); | 99 const AutocompleteResult::const_iterator match(result.default_match()); |
| 91 if (match != result.end()) { | 100 if (match != result.end()) { |
| 92 current_match_ = *match; | 101 current_match_ = *match; |
| 93 if (!prerender::IsOmniboxEnabled(profile_)) | 102 if (!prerender::IsOmniboxEnabled(profile_)) |
| 94 DoPreconnect(*match); | 103 DoPreconnect(*match); |
| 95 omnibox_edit_model_->OnCurrentMatchChanged(); | 104 omnibox_edit_model_->OnCurrentMatchChanged(); |
| 96 | |
| 97 if (chrome::IsInstantExtendedAPIEnabled()) { | |
| 98 InstantSuggestion prefetch_suggestion; | |
| 99 const AutocompleteMatch* match_to_prefetch = GetMatchToPrefetch(result); | |
| 100 if (match_to_prefetch) { | |
| 101 prefetch_suggestion.text = match_to_prefetch->contents; | |
| 102 prefetch_suggestion.metadata = | |
| 103 SearchProvider::GetSuggestMetadata(*match_to_prefetch); | |
| 104 } | |
| 105 // Send the prefetch suggestion unconditionally to the InstantPage. If | |
| 106 // there is no suggestion to prefetch, we need to send a blank query to | |
| 107 // clear the prefetched results. | |
| 108 omnibox_edit_model_->SetSuggestionToPrefetch(prefetch_suggestion); | |
| 109 } | |
| 110 } else { | 105 } else { |
| 111 InvalidateCurrentMatch(); | 106 InvalidateCurrentMatch(); |
| 112 popup_->OnResultChanged(); | 107 popup_->OnResultChanged(); |
| 113 omnibox_edit_model_->OnPopupDataChanged(base::string16(), NULL, | 108 omnibox_edit_model_->OnPopupDataChanged(base::string16(), NULL, |
| 114 base::string16(), false); | 109 base::string16(), false); |
| 115 } | 110 } |
| 116 } else { | 111 } else { |
| 117 popup_->OnResultChanged(); | 112 popup_->OnResultChanged(); |
| 118 } | 113 } |
| 119 | 114 |
| 120 if (!popup_->IsOpen() && was_open) { | 115 if (!popup_->IsOpen() && was_open) { |
| 121 // Accept the temporary text as the user text, because it makes little sense | 116 // Accept the temporary text as the user text, because it makes little sense |
| 122 // to have temporary text when the popup is closed. | 117 // to have temporary text when the popup is closed. |
| 123 omnibox_edit_model_->AcceptTemporaryTextAsUserText(); | 118 omnibox_edit_model_->AcceptTemporaryTextAsUserText(); |
| 124 } | 119 } |
| 120 | |
| 121 if (!chrome::IsInstantExtendedAPIEnabled()) | |
|
Peter Kasting
2014/06/19 23:03:08
Nit: Why not include this in the next conditional
sidharthms
2014/06/20 00:30:49
Done.
| |
| 122 return; | |
| 123 if ((default_match_changed && result.default_match() != result.end()) || | |
| 124 (chrome::ShouldAllowPrefetchNonDefaultMatch() && !result.empty())) { | |
| 125 InstantSuggestion prefetch_suggestion; | |
| 126 const AutocompleteMatch* match_to_prefetch = GetMatchToPrefetch(result); | |
| 127 if (match_to_prefetch) { | |
| 128 prefetch_suggestion.text = match_to_prefetch->contents; | |
| 129 prefetch_suggestion.metadata = | |
| 130 SearchProvider::GetSuggestMetadata(*match_to_prefetch); | |
| 131 } | |
| 132 // Send the prefetch suggestion unconditionally to the InstantPage. If | |
| 133 // there is no suggestion to prefetch, we need to send a blank query to | |
| 134 // clear the prefetched results. | |
| 135 omnibox_edit_model_->SetSuggestionToPrefetch(prefetch_suggestion); | |
| 136 } | |
| 125 } | 137 } |
| 126 | 138 |
| 127 void OmniboxController::InvalidateCurrentMatch() { | 139 void OmniboxController::InvalidateCurrentMatch() { |
| 128 current_match_ = AutocompleteMatch(); | 140 current_match_ = AutocompleteMatch(); |
| 129 } | 141 } |
| 130 | 142 |
| 131 void OmniboxController::ClearPopupKeywordMode() const { | 143 void OmniboxController::ClearPopupKeywordMode() const { |
| 132 if (popup_->IsOpen() && | 144 if (popup_->IsOpen() && |
| 133 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) | 145 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) |
| 134 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); | 146 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); |
| 135 } | 147 } |
| 136 | 148 |
| 137 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { | 149 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { |
| 138 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { | 150 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { |
| 139 // Warm up DNS Prefetch cache, or preconnect to a search service. | 151 // Warm up DNS Prefetch cache, or preconnect to a search service. |
| 140 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, | 152 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, |
| 141 AutocompleteMatchType::NUM_TYPES); | 153 AutocompleteMatchType::NUM_TYPES); |
| 142 if (profile_->GetNetworkPredictor()) { | 154 if (profile_->GetNetworkPredictor()) { |
| 143 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( | 155 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( |
| 144 match.destination_url, | 156 match.destination_url, |
| 145 predictors::AutocompleteActionPredictor::IsPreconnectable(match)); | 157 predictors::AutocompleteActionPredictor::IsPreconnectable(match)); |
| 146 } | 158 } |
| 147 // We could prefetch the alternate nav URL, if any, but because there | 159 // We could prefetch the alternate nav URL, if any, but because there |
| 148 // can be many of these as a user types an initial series of characters, | 160 // can be many of these as a user types an initial series of characters, |
| 149 // the OS DNS cache could suffer eviction problems for minimal gain. | 161 // the OS DNS cache could suffer eviction problems for minimal gain. |
| 150 } | 162 } |
| 151 } | 163 } |
| OLD | NEW |