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

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

Issue 15875007: app_list: Search result launch history and boost. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix guest mode crash Created 7 years, 7 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/app_list/search/history_data.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "chrome/browser/ui/app_list/search/history_data_observer.h"
12 #include "chrome/browser/ui/app_list/search/history_data_store.h"
13
14 namespace app_list {
15
16 namespace {
17
18 // A struct used to sort query entries by time.
19 struct EntrySortData {
20 EntrySortData() : query(NULL), update_time(NULL) {}
21 EntrySortData(const std::string* query,
22 const base::Time* update_time)
23 : query(query),
24 update_time(update_time) {
25 }
26
27 const std::string* query;
28 const base::Time* update_time;
29 };
30
31 bool EntrySortByTimeAscending(const EntrySortData& entry1,
32 const EntrySortData& entry2) {
33 return *entry1.update_time < *entry2.update_time;
34 }
35
36 } // namespace
37
38 HistoryData::Data::Data() {}
39 HistoryData::Data::~Data() {}
40
41 HistoryData::HistoryData(HistoryDataStore* store,
42 size_t max_entry,
43 size_t max_secondary)
44 : store_(store),
45 max_entry_(max_entry),
46 max_secondary_(max_secondary) {
47 store_->Load(base::Bind(&HistoryData::OnStoreLoaded, AsWeakPtr()));
48 }
49
50 HistoryData::~HistoryData() {}
51
52 void HistoryData::Add(const std::string& query, const std::string& result_id) {
53 Associations::iterator assoc_it = associations_.find(query);
54
55 // Creates a primary association if query is seen for the first time.
56 if (assoc_it == associations_.end()) {
57 Data& data = associations_[query];
58 data.primary = result_id;
59 data.update_time = base::Time::Now();
60
61 store_->SetPrimary(query, result_id);
62 store_->SetUpdateTime(query, data.update_time);
63
64 TrimEntries();
65 return;
66 }
67
68 Data& data = assoc_it->second;
69 data.update_time = base::Time::Now();
70 store_->SetUpdateTime(query, data.update_time);
71
72 SecondaryDeque& secondary = data.secondary;
73 if (!secondary.empty() && secondary.back() == result_id) {
74 // Nothing to do if the last secondary is the current primary.
75 if (data.primary == result_id)
76 return;
77
78 // If |result_id| is the last (the most recent) secondary and it's not the
79 // current primary, promote it and demote the primary.
80 secondary.pop_back();
81 secondary.push_back(data.primary);
82 data.primary = result_id;
83
84 store_->SetPrimary(query, result_id);
85 store_->SetSecondary(query, secondary);
86 return;
87 }
88
89 // Otherwise, append to secondary list.
90 SecondaryDeque::iterator secondary_it =
91 std::find(secondary.begin(), secondary.end(), result_id);
92 if (secondary_it != secondary.end())
93 secondary.erase(secondary_it);
94
95 secondary.push_back(result_id);
96 if (secondary.size() > max_secondary_)
97 secondary.pop_front();
98 store_->SetSecondary(query, secondary);
99 }
100
101 scoped_ptr<KnownResults> HistoryData::GetKnownResults(
102 const std::string& query) const {
103 scoped_ptr<KnownResults> results(new KnownResults);
104 KnownResults& known_results = *results.get();
James Cook 2013/05/23 21:51:08 This feels a little strange. Can you just use resu
xiyuan 2013/05/23 22:38:13 Done.
105 for (Associations::const_iterator assoc_it =
106 associations_.lower_bound(query);
107 assoc_it != associations_.end();
108 ++assoc_it) {
109 // Break out of the loop if |query| is no longer a prefix.
110 if (assoc_it->first.size() < query.size() ||
111 strncmp(assoc_it->first.c_str(),
112 query.c_str(),
113 query.length()) != 0) {
114 break;
115 }
116
117 const bool perfect = assoc_it->first == query;
118 // Primary match should always be returned.
119 known_results[assoc_it->second.primary] =
120 perfect ? PERFECT_PRIMARY : PREFIX_PRIMARY;
121
122 const KnownResultType secondary_type =
123 perfect ? PERFECT_SECONDARY : PREFIX_SECONDARY;
124 const HistoryData::SecondaryDeque& secondary = assoc_it->second.secondary;
125 for (HistoryData::SecondaryDeque::const_iterator secondary_it =
126 secondary.begin();
127 secondary_it != secondary.end();
128 ++secondary_it) {
129 const std::string& secondary_result_id = (*secondary_it);
130
131 // Secondary match only gets added if there there is no primary match.
132 if (known_results.find(secondary_result_id) != known_results.end())
133 continue;
134 known_results[secondary_result_id] = secondary_type;
135 }
136 }
137
138 return results.Pass();
139 }
140
141 void HistoryData::AddObserver(HistoryDataObserver* observer) {
142 observers_.AddObserver(observer);
143 }
144
145 void HistoryData::RemoveObserver(HistoryDataObserver* observer) {
146 observers_.RemoveObserver(observer);
147 }
148
149 void HistoryData::OnStoreLoaded(scoped_ptr<Associations> loaded_data) {
150 if (loaded_data)
151 loaded_data->swap(associations_);
152
153 FOR_EACH_OBSERVER(HistoryDataObserver, observers_,
154 OnHistoryDataLoadedFromStore());
155 }
156
157 void HistoryData::TrimEntries() {
158 if (associations_.size() <= max_entry_)
159 return;
160
161 std::vector<EntrySortData> entries;
162 for (Associations::const_iterator it = associations_.begin();
163 it != associations_.end(); ++it) {
164 entries.push_back(EntrySortData(&it->first, &it->second.update_time));
165 }
166
167 const size_t entries_to_remove = associations_.size() - max_entry_;
168 std::partial_sort(entries.begin(),
169 entries.begin() + entries_to_remove,
170 entries.end(),
171 &EntrySortByTimeAscending);
172
173 for (size_t i = 0; i < entries_to_remove; ++i) {
174 const std::string& query = *entries[i].query;
175 store_->Delete(query);
176 associations_.erase(query);
177 }
178 }
179
180 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698