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 |