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

Side by Side Diff: components/omnibox/browser/physical_web_provider.cc

Issue 2591053002: Show PhysicalWebProvider suggestions with omnibox input (Closed)
Patch Set: clear had_physical_web_suggestions_ Created 3 years, 12 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 (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 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 "components/omnibox/browser/physical_web_provider.h"
6
5 #include "base/memory/ptr_util.h" 7 #include "base/memory/ptr_util.h"
6 #include "base/metrics/histogram_macros.h" 8 #include "base/metrics/histogram_macros.h"
9 #include "base/strings/string_util.h"
7 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
8 #include "base/values.h" 11 #include "base/values.h"
12 #include "components/bookmarks/browser/titled_url_index.h"
13 #include "components/bookmarks/browser/titled_url_node_sorter.h"
9 #include "components/omnibox/browser/autocomplete_provider_client.h" 14 #include "components/omnibox/browser/autocomplete_provider_client.h"
10 #include "components/omnibox/browser/autocomplete_provider_listener.h" 15 #include "components/omnibox/browser/autocomplete_provider_listener.h"
16 #include "components/omnibox/browser/autocomplete_provider_utils.h"
11 #include "components/omnibox/browser/history_url_provider.h" 17 #include "components/omnibox/browser/history_url_provider.h"
12 #include "components/omnibox/browser/physical_web_provider.h" 18 #include "components/omnibox/browser/omnibox_field_trial.h"
19 #include "components/omnibox/browser/physical_web_node.h"
20 #include "components/omnibox/browser/url_prefix.h"
13 #include "components/omnibox/browser/verbatim_match.h" 21 #include "components/omnibox/browser/verbatim_match.h"
14 #include "components/physical_web/data_source/physical_web_data_source.h" 22 #include "components/physical_web/data_source/physical_web_data_source.h"
15 #include "components/url_formatter/url_formatter.h" 23 #include "components/url_formatter/url_formatter.h"
16 #include "grit/components_strings.h" 24 #include "grit/components_strings.h"
17 #include "ui/base/l10n/l10n_util.h" 25 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/gfx/text_elider.h" 26 #include "ui/gfx/text_elider.h"
19 #include "url/gurl.h" 27 #include "url/gurl.h"
20 28
21 namespace { 29 namespace {
22 30
23 // Relevance score of the first Physical Web URL autocomplete match. This score
24 // is intended to be between ClipboardURLProvider and ZeroSuggestProvider.
25 // Subsequent matches should decrease in relevance to preserve the ordering
26 // in the metadata list.
27 static const int kPhysicalWebUrlBaseRelevance = 700;
28
29 // The maximum length of the page title's part of the overflow item's 31 // The maximum length of the page title's part of the overflow item's
30 // description. Longer titles will be truncated to this length. In a normal 32 // description. Longer titles will be truncated to this length. In a normal
31 // Physical Web match item (non-overflow item) we allow the omnibox display to 33 // Physical Web match item (non-overflow item) we allow the omnibox display to
32 // truncate the title instead. 34 // truncate the title instead.
33 static const size_t kMaxTitleLengthInOverflow = 15; 35 static const size_t kMaxTitleLengthInOverflow = 15;
36
37 // The maximum number of Physical Web URLs to retrieve from the index.
38 static const size_t kPhysicalWebIndexMaxMatches = 50;
39
34 } 40 }
35 41
36 // static 42 // static
37 const size_t PhysicalWebProvider::kPhysicalWebMaxMatches = 1; 43 const size_t PhysicalWebProvider::kPhysicalWebMaxMatches = 1;
38 44
39 // static 45 // static
40 PhysicalWebProvider* PhysicalWebProvider::Create( 46 PhysicalWebProvider* PhysicalWebProvider::Create(
41 AutocompleteProviderClient* client, 47 AutocompleteProviderClient* client,
42 HistoryURLProvider* history_url_provider) { 48 HistoryURLProvider* history_url_provider) {
43 return new PhysicalWebProvider(client, history_url_provider); 49 return new PhysicalWebProvider(client, history_url_provider);
44 } 50 }
45 51
46 void PhysicalWebProvider::Start(const AutocompleteInput& input, 52 void PhysicalWebProvider::Start(const AutocompleteInput& input,
47 bool minimal_changes) { 53 bool minimal_changes) {
48 DCHECK(kPhysicalWebMaxMatches < kMaxMatches); 54 DCHECK(kPhysicalWebMaxMatches < kMaxMatches);
49 55
50 Stop(false, false); 56 Stop(false, false);
51 57
52 done_ = false; 58 done_ = false;
53 matches_.clear(); 59 matches_.clear();
54 60
55 // Stop providing suggestions when the user enters text into the omnibox. 61 had_physical_web_suggestions_ = false;
56 if (!input.from_omnibox_focus()) { 62 if (input.from_omnibox_focus()) {
Mark P 2016/12/22 04:58:16 nit: {} unnecessary
mattreynolds 2017/01/04 01:04:03 Done.
57 done_ = true; 63 had_physical_web_suggestions_at_focus_or_later_ = false;
58 return;
59 } 64 }
60 65
61 // Don't provide suggestions in incognito mode. 66 // Don't provide suggestions in incognito mode.
62 if (client_->IsOffTheRecord()) { 67 if (client_->IsOffTheRecord()) {
63 done_ = true; 68 done_ = true;
64 nearby_url_count_ = 0; 69 nearby_url_count_ = 0;
65 return; 70 return;
66 } 71 }
67 72
68 physical_web::PhysicalWebDataSource* data_source = 73 physical_web::PhysicalWebDataSource* data_source =
69 client_->GetPhysicalWebDataSource(); 74 client_->GetPhysicalWebDataSource();
70 if (!data_source) { 75 if (!data_source) {
71 done_ = true; 76 done_ = true;
72 nearby_url_count_ = 0; 77 nearby_url_count_ = 0;
73 return; 78 return;
74 } 79 }
75 80
76 ConstructMatches(data_source->GetMetadata().get()); 81 if (input.from_omnibox_focus()) {
82 ConstructZeroSuggestMatches(data_source->GetMetadata());
77 83
78 // Physical Web matches should never be default. If the omnibox input is 84 if (!matches_.empty()) {
79 // non-empty and we have at least one Physical Web match, add the current URL 85 had_physical_web_suggestions_ = true;
80 // as the default so that hitting enter after focusing the omnibox causes the 86 had_physical_web_suggestions_at_focus_or_later_ = true;
81 // current page to reload. If the input field is empty, no default match is 87 }
82 // required. 88
83 if (!matches_.empty() && !input.text().empty()) { 89 if (!zero_suggest_enabled_) {
84 matches_.push_back(VerbatimMatchForURL(client_, input, input.current_url(), 90 matches_.clear();
85 history_url_provider_, -1)); 91 }
92
93 // In zero-suggest, Physical Web matches should never be default. If the
94 // omnibox input is non-empty and we have at least one Physical Web match,
95 // add the current URL as the default so that hitting enter after focusing
96 // the omnibox causes the current page to reload. If the input field is
97 // empty, no default match is required.
98 if (!matches_.empty() && !input.text().empty()) {
99 matches_.push_back(
100 VerbatimMatchForURL(client_, input, input.current_url(),
101 history_url_provider_, -1));
102 }
103 } else {
104 ConstructQuerySuggestMatches(data_source->GetMetadata(), input);
105
106 if (!matches_.empty()) {
107 had_physical_web_suggestions_ = true;
108 had_physical_web_suggestions_at_focus_or_later_ = true;
109 }
110
111 if (!after_typing_enabled_) {
112 matches_.clear();
113 }
86 } 114 }
87 115
88 done_ = true; 116 done_ = true;
89 } 117 }
90 118
91 void PhysicalWebProvider::Stop(bool clear_cached_results, 119 void PhysicalWebProvider::Stop(bool clear_cached_results,
92 bool due_to_user_inactivity) { 120 bool due_to_user_inactivity) {
93 done_ = true; 121 done_ = true;
94 } 122 }
95 123
96 void PhysicalWebProvider::AddProviderInfo(ProvidersInfo* provider_info) const { 124 void PhysicalWebProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
97 // AddProviderInfo is called for each autocomplete provider to allow 125 // Record whether the provider could have provided a Physical Web suggestion,
98 // provider-specific diagnostic info to be added to the omnibox log entry. 126 // even if the suggestion could not be displayed due to the current field
99 // In this case we do not append any diagnostic info and are taking advantage 127 // trial.
100 // of the fact that this method is only called when the user has accepted an 128 provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
101 // autocomplete suggestion. 129 metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
130 new_entry.set_provider(AsOmniboxEventProviderType());
131 new_entry.set_provider_done(done_);
132 std::vector<uint32_t> field_trial_hashes;
133 OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes);
134 for (size_t i = 0; i < field_trial_hashes.size(); ++i) {
135 if (had_physical_web_suggestions_)
136 new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]);
137 if (had_physical_web_suggestions_at_focus_or_later_) {
138 new_entry.mutable_field_trial_triggered_in_session()->Add(
139 field_trial_hashes[i]);
140 }
141 }
102 142
103 // When the user accepts an autocomplete suggestion, record the number of 143 // When the user accepts an autocomplete suggestion, record the number of
104 // nearby Physical Web URLs at the time the provider last constructed matches. 144 // nearby Physical Web URLs at the time the provider last constructed matches.
105 UMA_HISTOGRAM_EXACT_LINEAR("Omnibox.SuggestionUsed.NearbyURLCount", 145 UMA_HISTOGRAM_EXACT_LINEAR("Omnibox.SuggestionUsed.NearbyURLCount",
106 nearby_url_count_, 50); 146 nearby_url_count_, 50);
107 } 147 }
108 148
109 PhysicalWebProvider::PhysicalWebProvider( 149 PhysicalWebProvider::PhysicalWebProvider(
110 AutocompleteProviderClient* client, 150 AutocompleteProviderClient* client,
111 HistoryURLProvider* history_url_provider) 151 HistoryURLProvider* history_url_provider)
112 : AutocompleteProvider(AutocompleteProvider::TYPE_PHYSICAL_WEB), 152 : AutocompleteProvider(AutocompleteProvider::TYPE_PHYSICAL_WEB),
113 client_(client), 153 client_(client),
114 history_url_provider_(history_url_provider) {} 154 history_url_provider_(history_url_provider),
155 zero_suggest_enabled_(
156 OmniboxFieldTrial::InPhysicalWebZeroSuggestFieldTrial()),
157 after_typing_enabled_(
158 OmniboxFieldTrial::InPhysicalWebAfterTypingFieldTrial()),
159 zero_suggest_base_relevance_(
160 OmniboxFieldTrial::GetPhysicalWebZeroSuggestBaseRelevance()),
161 after_typing_base_relevance_(
162 OmniboxFieldTrial::GetPhysicalWebAfterTypingBaseRelevance()) {}
115 163
116 PhysicalWebProvider::~PhysicalWebProvider() { 164 PhysicalWebProvider::~PhysicalWebProvider() {
117 } 165 }
118 166
119 void PhysicalWebProvider::ConstructMatches(base::ListValue* metadata_list) { 167 void PhysicalWebProvider::ConstructZeroSuggestMatches(
168 std::unique_ptr<base::ListValue> metadata_list) {
120 nearby_url_count_ = metadata_list->GetSize(); 169 nearby_url_count_ = metadata_list->GetSize();
121 size_t used_slots = 0; 170 size_t used_slots = 0;
122 171
123 for (size_t i = 0; i < nearby_url_count_; ++i) { 172 for (size_t i = 0; i < nearby_url_count_; ++i) {
124 base::DictionaryValue* metadata_item = NULL; 173 base::DictionaryValue* metadata_item = NULL;
125 if (!metadata_list->GetDictionary(i, &metadata_item)) { 174 if (!metadata_list->GetDictionary(i, &metadata_item)) {
126 continue; 175 continue;
127 } 176 }
128 177
129 std::string url_string; 178 std::string url_string;
130 std::string title_string; 179 std::string title_string;
131 if (!metadata_item->GetString(physical_web::kResolvedUrlKey, &url_string) || 180 if (!metadata_item->GetString(physical_web::kResolvedUrlKey, &url_string) ||
132 !metadata_item->GetString(physical_web::kTitleKey, &title_string)) { 181 !metadata_item->GetString(physical_web::kTitleKey, &title_string)) {
133 continue; 182 continue;
134 } 183 }
135 base::string16 title = 184 base::string16 title =
136 AutocompleteMatch::SanitizeString(base::UTF8ToUTF16(title_string)); 185 AutocompleteMatch::SanitizeString(base::UTF8ToUTF16(title_string));
137 186
138 // Add match items with decreasing relevance to preserve the ordering in 187 // Add match items with decreasing relevance to preserve the ordering in
139 // the metadata list. 188 // the metadata list.
140 int relevance = kPhysicalWebUrlBaseRelevance - used_slots; 189 int relevance = zero_suggest_base_relevance_ - used_slots;
141 190
142 // Append an overflow item if creating a match for each metadata item would 191 // Append an overflow item if creating a match for each metadata item would
143 // exceed the match limit. 192 // exceed the match limit.
144 const size_t remaining_slots = kPhysicalWebMaxMatches - used_slots; 193 const size_t remaining_slots = kPhysicalWebMaxMatches - used_slots;
145 const size_t remaining_metadata = nearby_url_count_ - i; 194 const size_t remaining_metadata = nearby_url_count_ - i;
146 if ((remaining_slots == 1) && (remaining_metadata > remaining_slots)) { 195 if ((remaining_slots == 1) && (remaining_metadata > remaining_slots)) {
147 AppendOverflowItem(remaining_metadata, relevance, title); 196 AppendOverflowItem(remaining_metadata, relevance, title);
148 break; 197 break;
149 } 198 }
150 199
(...skipping 20 matching lines...) Expand all
171 ACMatchClassification(0, ACMatchClassification::NONE)); 220 ACMatchClassification(0, ACMatchClassification::NONE));
172 221
173 matches_.push_back(match); 222 matches_.push_back(match);
174 ++used_slots; 223 ++used_slots;
175 } 224 }
176 225
177 UMA_HISTOGRAM_EXACT_LINEAR( 226 UMA_HISTOGRAM_EXACT_LINEAR(
178 "Omnibox.PhysicalWebProviderMatches", matches_.size(), kMaxMatches); 227 "Omnibox.PhysicalWebProviderMatches", matches_.size(), kMaxMatches);
179 } 228 }
180 229
230 void PhysicalWebProvider::ConstructQuerySuggestMatches(
231 std::unique_ptr<base::ListValue> metadata_list,
232 const AutocompleteInput& input) {
233 // Passing nullptr for the TitledUrlNodeSorter will cause the returned match
234 // list to be unsorted.
235 bookmarks::TitledUrlIndex index(nullptr);
236 std::vector<std::unique_ptr<PhysicalWebNode> > nodes;
237 const size_t metadata_count = metadata_list->GetSize();
238 for (size_t i = 0; i < metadata_count; ++i) {
239 base::DictionaryValue* metadata_item = NULL;
240 if (metadata_list->GetDictionary(i, &metadata_item)) {
241 nodes.push_back(base::MakeUnique<PhysicalWebNode>(*metadata_item));
242 index.Add(nodes.back().get());
243 }
244 }
245
246 std::vector<bookmarks::TitledUrlMatch> titled_url_matches;
247 index.GetResultsMatching(input.text(), kPhysicalWebIndexMaxMatches,
248 query_parser::MatchingAlgorithm::DEFAULT,
249 &titled_url_matches);
250
251 size_t used_slots = 0;
252 const base::string16 fixed_up_input(FixupUserInput(input).second);
253 for (auto titled_url_match : titled_url_matches) {
254 const int relevance = after_typing_base_relevance_ - used_slots;
255 matches_.push_back(
256 TitledUrlMatchToAutocompleteMatch(
257 this, client_->GetSchemeClassifier(), input, fixed_up_input,
258 titled_url_match, AutocompleteMatchType::PHYSICAL_WEB, relevance));
259 ++used_slots;
260 if (matches_.size() >= kPhysicalWebMaxMatches) {
261 break;
262 }
263 }
264 }
265
181 void PhysicalWebProvider::AppendOverflowItem(int additional_url_count, 266 void PhysicalWebProvider::AppendOverflowItem(int additional_url_count,
182 int relevance, 267 int relevance,
183 const base::string16& title) { 268 const base::string16& title) {
184 std::string url_string = "chrome://physical-web"; 269 std::string url_string = "chrome://physical-web";
185 GURL url(url_string); 270 GURL url(url_string);
186 271
187 AutocompleteMatch match(this, relevance, false, 272 AutocompleteMatch match(this, relevance, false,
188 AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW); 273 AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW);
189 match.destination_url = url; 274 match.destination_url = url;
190 275
(...skipping 14 matching lines...) Expand all
205 AutocompleteInput::FormattedStringWithEquivalentMeaning( 290 AutocompleteInput::FormattedStringWithEquivalentMeaning(
206 url, match.contents, client_->GetSchemeClassifier()); 291 url, match.contents, client_->GetSchemeClassifier());
207 292
208 match.description = 293 match.description =
209 l10n_util::GetStringUTF16(IDS_PHYSICAL_WEB_OVERFLOW_DESCRIPTION); 294 l10n_util::GetStringUTF16(IDS_PHYSICAL_WEB_OVERFLOW_DESCRIPTION);
210 match.description_class.push_back( 295 match.description_class.push_back(
211 ACMatchClassification(0, ACMatchClassification::NONE)); 296 ACMatchClassification(0, ACMatchClassification::NONE));
212 297
213 matches_.push_back(match); 298 matches_.push_back(match);
214 } 299 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698