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

Side by Side Diff: chrome/browser/ui/app_list/search/mixer.cc

Issue 369693004: Make app list search result mixer more resilient to reordering. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix compile Created 6 years, 5 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 | Annotate | Revision Log
OLDNEW
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/app_list/search/mixer.h" 5 #include "chrome/browser/ui/app_list/search/mixer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map>
8 #include <set> 9 #include <set>
9 #include <string> 10 #include <string>
10 #include <vector> 11 #include <vector>
11 12
12 #include "chrome/browser/ui/app_list/search/chrome_search_result.h" 13 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
13 #include "ui/app_list/search_provider.h" 14 #include "ui/app_list/search_provider.h"
14 15
15 namespace app_list { 16 namespace app_list {
16 17
17 namespace { 18 namespace {
18 19
19 // Maximum number of results to show. 20 // Maximum number of results to show.
20 const size_t kMaxResults = 6; 21 const size_t kMaxResults = 6;
21 const size_t kMaxMainGroupResults = 4; 22 const size_t kMaxMainGroupResults = 4;
22 const size_t kMaxWebstoreResults = 2; 23 const size_t kMaxWebstoreResults = 2;
23 const size_t kMaxPeopleResults = 2; 24 const size_t kMaxPeopleResults = 2;
24 25
25 // A value to indicate no max number of results limit. 26 // A value to indicate no max number of results limit.
26 const size_t kNoMaxResultsLimit = 0; 27 const size_t kNoMaxResultsLimit = 0;
27 28
29 void UpdateResult(const ChromeSearchResult& source,
30 ChromeSearchResult* target) {
31 target->set_title(source.title());
32 target->set_title_tags(source.title_tags());
33 target->set_details(source.details());
34 target->set_details_tags(source.details_tags());
35 }
36
28 } // namespace 37 } // namespace
29 38
30 Mixer::SortData::SortData() : result(NULL), score(0.0) { 39 Mixer::SortData::SortData() : result(NULL), score(0.0) {
31 } 40 }
32 41
33 Mixer::SortData::SortData(ChromeSearchResult* result, double score) 42 Mixer::SortData::SortData(ChromeSearchResult* result, double score)
34 : result(result), score(score) { 43 : result(result), score(score) {
35 } 44 }
36 45
37 bool Mixer::SortData::operator<(const SortData& other) const { 46 bool Mixer::SortData::operator<(const SortData& other) const {
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 groups_[OMNIBOX_GROUP]->results().begin() + remaining_slots); 173 groups_[OMNIBOX_GROUP]->results().begin() + remaining_slots);
165 174
166 std::sort(results.begin(), results.end()); 175 std::sort(results.begin(), results.end());
167 RemoveDuplicates(&results); 176 RemoveDuplicates(&results);
168 if (results.size() > kMaxResults) 177 if (results.size() > kMaxResults)
169 results.resize(kMaxResults); 178 results.resize(kMaxResults);
170 179
171 Publish(results, ui_results_); 180 Publish(results, ui_results_);
172 } 181 }
173 182
174 void Mixer::Publish(const SortedResults& results, 183 void Mixer::Publish(const SortedResults& new_results,
175 AppListModel::SearchResults* ui_results) { 184 AppListModel::SearchResults* ui_results) {
176 for (size_t i = 0; i < results.size(); ++i) { 185 typedef std::map<std::string, ChromeSearchResult*> IdToResultMap;
177 ChromeSearchResult* result = results[i].result;
178 186
187 // The following algorithm is used:
188 // 1. Transform the |ui_results| list into an unordered map from result ID
189 // to item.
190 // 2. Use the order of items in |new_results| to build an ordered list. If the
191 // result IDs exist in the map, update and use the item in the map and delete
192 // it from the map afterwards. Otherwise, clone new items from |new_results|.
193 // 3. Delete the objects remaining in the map as they are unused.
194
195 // A map of the items in |ui_results| that takes ownership of the items.
196 IdToResultMap ui_results_map;
197 for (size_t i = 0; i < ui_results->item_count(); ++i) {
179 ChromeSearchResult* ui_result = 198 ChromeSearchResult* ui_result =
180 i < ui_results->item_count() 199 static_cast<ChromeSearchResult*>(ui_results->GetItemAt(i));
181 ? static_cast<ChromeSearchResult*>(ui_results->GetItemAt(i)) 200 ui_results_map[ui_result->id()] = ui_result;
182 : NULL; 201 }
183 if (ui_result && ui_result->id() == result->id()) { 202 // We have to erase all results at once so that observers are notified with
184 ui_result->set_title(result->title()); 203 // meaningful indexes.
185 ui_result->set_title_tags(result->title_tags()); 204 ui_results->RemoveAll();
186 ui_result->set_details(result->details()); 205
187 ui_result->set_details_tags(result->details_tags()); 206 // Add items back to |ui_results| in the order of |new_results|.
188 ui_results->NotifyItemsChanged(i, 1); 207 for (size_t i = 0; i < new_results.size(); ++i) {
208 ChromeSearchResult* new_result = new_results[i].result;
209 IdToResultMap::const_iterator ui_result_it =
210 ui_results_map.find(new_result->id());
211 if (ui_result_it != ui_results_map.end()) {
212 // Update and use the old result if it exists.
213 ChromeSearchResult* ui_result = ui_result_it->second;
214 UpdateResult(*new_result, ui_result);
215
216 // |ui_results| takes back ownership from |ui_results_map| here.
217 ui_results->Add(ui_result);
218
219 // Remove the item from the map so that it ends up only with unused
220 // results.
221 ui_results_map.erase(ui_result->id());
189 } else { 222 } else {
190 if (ui_result) 223 // Copy the result from |new_results| otherwise.
191 ui_results->DeleteAt(i); 224 ui_results->Add(new_result->Duplicate().release());
192 ui_results->AddAt(i, result->Duplicate().release());
193 } 225 }
194 } 226 }
195 227
196 while (ui_results->item_count() > results.size()) 228 // Delete the results remaining in the map as they are not in the new results.
197 ui_results->DeleteAt(ui_results->item_count() - 1); 229 for (IdToResultMap::const_iterator ui_result_it = ui_results_map.begin();
230 ui_result_it != ui_results_map.end();
231 ++ui_result_it) {
232 delete ui_result_it->second;
233 }
198 } 234 }
199 235
200 void Mixer::RemoveDuplicates(SortedResults* results) { 236 void Mixer::RemoveDuplicates(SortedResults* results) {
201 SortedResults final; 237 SortedResults final;
202 final.reserve(results->size()); 238 final.reserve(results->size());
203 239
204 std::set<std::string> id_set; 240 std::set<std::string> id_set;
205 for (SortedResults::iterator it = results->begin(); it != results->end(); 241 for (SortedResults::iterator it = results->begin(); it != results->end();
206 ++it) { 242 ++it) {
207 const std::string& id = it->result->id(); 243 const std::string& id = it->result->id();
208 if (id_set.find(id) != id_set.end()) 244 if (id_set.find(id) != id_set.end())
209 continue; 245 continue;
210 246
211 id_set.insert(id); 247 id_set.insert(id);
212 final.push_back(*it); 248 final.push_back(*it);
213 } 249 }
214 250
215 results->swap(final); 251 results->swap(final);
216 } 252 }
217 253
218 void Mixer::FetchResults(const KnownResults& known_results) { 254 void Mixer::FetchResults(const KnownResults& known_results) {
219 for (Groups::iterator group_it = groups_.begin(); 255 for (Groups::iterator group_it = groups_.begin();
220 group_it != groups_.end(); 256 group_it != groups_.end();
221 ++group_it) { 257 ++group_it) {
222 (*group_it)->FetchResults(known_results); 258 (*group_it)->FetchResults(known_results);
223 } 259 }
224 } 260 }
225 261
226 } // namespace app_list 262 } // namespace app_list
OLDNEW
« no previous file with comments | « chrome/browser/ui/app_list/search/mixer.h ('k') | chrome/browser/ui/app_list/search/mixer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698