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) { |
| 45 if (chrome::ShouldAllowPrefetchNonDefaultMatch()) { |
| 46 const AutocompleteResult::const_iterator prefetch_match = std::find_if( |
| 47 result.begin(), result.end(), SearchProvider::ShouldPrefetch); |
| 48 return prefetch_match != result.end() ? &(*prefetch_match) : NULL; |
| 49 } |
| 50 |
42 // If the default match should be prefetched, do that. | 51 // If the default match should be prefetched, do that. |
43 const AutocompleteResult::const_iterator default_match( | 52 const AutocompleteResult::const_iterator default_match( |
44 result.default_match()); | 53 result.default_match()); |
45 if ((default_match != result.end()) && | 54 if ((default_match != result.end()) && |
46 SearchProvider::ShouldPrefetch(*default_match)) | 55 SearchProvider::ShouldPrefetch(*default_match)) |
47 return &(*default_match); | 56 return &(*default_match); |
48 | 57 |
49 // Otherwise, if the top match is a verbatim match and the very next match is | 58 // Otherwise, if the top match is a verbatim match and the very next match |
50 // prefetchable, fetch that. | 59 // is prefetchable, fetch that. |
51 if ((result.ShouldHideTopMatch() || | 60 if ((result.ShouldHideTopMatch() || |
52 result.TopMatchIsStandaloneVerbatimMatch()) && | 61 result.TopMatchIsStandaloneVerbatimMatch()) && |
53 (result.size() > 1) && | 62 (result.size() > 1) && |
54 SearchProvider::ShouldPrefetch(result.match_at(1))) | 63 SearchProvider::ShouldPrefetch(result.match_at(1))) |
55 return &result.match_at(1); | 64 return &result.match_at(1); |
56 | 65 |
57 return NULL; | 66 return NULL; |
58 } | 67 } |
59 | 68 |
60 } // namespace | 69 } // namespace |
(...skipping 18 matching lines...) Expand all Loading... |
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(); |
86 if (default_match_changed) { | 95 if (default_match_changed) { |
87 // The default match has changed, we need to let the OmniboxEditModel know | 96 // The default match has changed, we need to let the OmniboxEditModel know |
88 // about new inline autocomplete text (blue highlight). | 97 // about new inline autocomplete text (blue highlight). |
89 const AutocompleteResult& result = this->result(); | 98 const AutocompleteResult::const_iterator match(result().default_match()); |
90 const AutocompleteResult::const_iterator match(result.default_match()); | 99 if (match != result().end()) { |
91 if (match != result.end()) { | |
92 current_match_ = *match; | 100 current_match_ = *match; |
93 if (!prerender::IsOmniboxEnabled(profile_)) | 101 if (!prerender::IsOmniboxEnabled(profile_)) |
94 DoPreconnect(*match); | 102 DoPreconnect(*match); |
95 omnibox_edit_model_->OnCurrentMatchChanged(); | 103 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 { | 104 } else { |
111 InvalidateCurrentMatch(); | 105 InvalidateCurrentMatch(); |
112 popup_->OnResultChanged(); | 106 popup_->OnResultChanged(); |
113 omnibox_edit_model_->OnPopupDataChanged(base::string16(), NULL, | 107 omnibox_edit_model_->OnPopupDataChanged(base::string16(), NULL, |
114 base::string16(), false); | 108 base::string16(), false); |
115 } | 109 } |
116 } else { | 110 } else { |
117 popup_->OnResultChanged(); | 111 popup_->OnResultChanged(); |
118 } | 112 } |
119 | 113 |
120 if (!popup_->IsOpen() && was_open) { | 114 if (!popup_->IsOpen() && was_open) { |
121 // Accept the temporary text as the user text, because it makes little sense | 115 // Accept the temporary text as the user text, because it makes little sense |
122 // to have temporary text when the popup is closed. | 116 // to have temporary text when the popup is closed. |
123 omnibox_edit_model_->AcceptTemporaryTextAsUserText(); | 117 omnibox_edit_model_->AcceptTemporaryTextAsUserText(); |
124 } | 118 } |
| 119 |
| 120 if (chrome::IsInstantExtendedAPIEnabled() && |
| 121 ((default_match_changed && result().default_match() != result().end()) || |
| 122 (chrome::ShouldAllowPrefetchNonDefaultMatch() && !result().empty()))) { |
| 123 InstantSuggestion prefetch_suggestion; |
| 124 const AutocompleteMatch* match_to_prefetch = GetMatchToPrefetch(result()); |
| 125 if (match_to_prefetch) { |
| 126 prefetch_suggestion.text = match_to_prefetch->contents; |
| 127 prefetch_suggestion.metadata = |
| 128 SearchProvider::GetSuggestMetadata(*match_to_prefetch); |
| 129 } |
| 130 // Send the prefetch suggestion unconditionally to the InstantPage. If |
| 131 // there is no suggestion to prefetch, we need to send a blank query to |
| 132 // clear the prefetched results. |
| 133 omnibox_edit_model_->SetSuggestionToPrefetch(prefetch_suggestion); |
| 134 } |
125 } | 135 } |
126 | 136 |
127 void OmniboxController::InvalidateCurrentMatch() { | 137 void OmniboxController::InvalidateCurrentMatch() { |
128 current_match_ = AutocompleteMatch(); | 138 current_match_ = AutocompleteMatch(); |
129 } | 139 } |
130 | 140 |
131 void OmniboxController::ClearPopupKeywordMode() const { | 141 void OmniboxController::ClearPopupKeywordMode() const { |
132 if (popup_->IsOpen() && | 142 if (popup_->IsOpen() && |
133 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) | 143 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) |
134 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); | 144 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); |
135 } | 145 } |
136 | 146 |
137 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { | 147 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { |
138 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { | 148 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { |
139 // Warm up DNS Prefetch cache, or preconnect to a search service. | 149 // Warm up DNS Prefetch cache, or preconnect to a search service. |
140 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, | 150 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, |
141 AutocompleteMatchType::NUM_TYPES); | 151 AutocompleteMatchType::NUM_TYPES); |
142 if (profile_->GetNetworkPredictor()) { | 152 if (profile_->GetNetworkPredictor()) { |
143 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( | 153 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( |
144 match.destination_url, | 154 match.destination_url, |
145 predictors::AutocompleteActionPredictor::IsPreconnectable(match)); | 155 predictors::AutocompleteActionPredictor::IsPreconnectable(match)); |
146 } | 156 } |
147 // We could prefetch the alternate nav URL, if any, but because there | 157 // 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, | 158 // 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. | 159 // the OS DNS cache could suffer eviction problems for minimal gain. |
150 } | 160 } |
151 } | 161 } |
OLD | NEW |