OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/file_util.h" | 5 #include "base/file_util.h" |
6 #include "base/memory/ref_counted.h" | 6 #include "base/memory/ref_counted.h" |
7 #include "base/strings/string_split.h" | 7 #include "base/strings/string_split.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "chrome/browser/history/history_types.h" | 9 #include "chrome/browser/history/history_types.h" |
10 #include "chrome/browser/history/top_sites.h" | 10 #include "chrome/browser/history/top_sites.h" |
11 #include "chrome/browser/history/top_sites_database.h" | 11 #include "chrome/browser/history/top_sites_database.h" |
12 #include "chrome/common/thumbnail_score.h" | |
12 #include "sql/connection.h" | 13 #include "sql/connection.h" |
13 #include "sql/transaction.h" | 14 #include "sql/transaction.h" |
14 | 15 |
16 // Description of database table: | |
17 // | |
18 // thumbnails | |
19 // url URL of the sites for which we have a thumbnail. | |
20 // url_rank Index of the URL in that thumbnail, 0-based. The thumbnail | |
21 // with the highest rank will be the next one evicted. Forced | |
22 // thumbnails have a rank of -1. | |
23 // title The title to display under that thumbnail. | |
24 // redirects A space separated list of URLs that are known to redirect | |
25 // to this url. | |
26 // boring_score How "boring" that thumbnail is. See ThumbnailScore. | |
27 // good_clipping True if the thumbnail was clipped from the bottom, keeping | |
28 // the entire width of the window. See ThumbnailScore. | |
29 // at_top True if the thumbnail was captured at the top of the | |
30 // website. | |
31 // last_updated The time at which this thumbnail was last updated. | |
32 // load_completed True if the thumbnail was captured after the page load was | |
33 // completed. | |
34 // last_forced If this is a forced thumbnail, records the last time it | |
35 // was forced. If it's not a forced thumbnail, 0. | |
36 | |
15 namespace history { | 37 namespace history { |
16 | 38 |
39 // TODO(beaudoin): Fill revision/date details of Version 3 after landing. | |
40 // Version 3: by beaudoin@chromium.org | |
17 // Version 2: eb0b24e6/r87284 by satorux@chromium.org on 2011-05-31 | 41 // Version 2: eb0b24e6/r87284 by satorux@chromium.org on 2011-05-31 |
18 // Version 1: 809cc4d8/r64072 by sky@chromium.org on 2010-10-27 | 42 // Version 1: 809cc4d8/r64072 by sky@chromium.org on 2010-10-27 |
19 | 43 |
20 // From the version 1 to 2, one column was added. Old versions of Chrome | 44 // From the version 1 to 2, one column was added. Old versions of Chrome |
21 // should be able to read version 2 files just fine. | 45 // should be able to read version 2 files just fine. Same thing for version 2 |
46 // to 3. | |
22 // NOTE(shess): When changing the version, add a new golden file for | 47 // NOTE(shess): When changing the version, add a new golden file for |
23 // the new version and a test to verify that Init() works with it. | 48 // the new version and a test to verify that Init() works with it. |
24 static const int kVersionNumber = 2; | 49 static const int kVersionNumber = 3; |
25 | 50 |
26 TopSitesDatabase::TopSitesDatabase() { | 51 TopSitesDatabase::TopSitesDatabase() { |
27 } | 52 } |
28 | 53 |
29 TopSitesDatabase::~TopSitesDatabase() { | 54 TopSitesDatabase::~TopSitesDatabase() { |
30 } | 55 } |
31 | 56 |
32 bool TopSitesDatabase::Init(const base::FilePath& db_name) { | 57 bool TopSitesDatabase::Init(const base::FilePath& db_name) { |
33 bool file_existed = base::PathExists(db_name); | 58 bool file_existed = base::PathExists(db_name); |
34 | 59 |
(...skipping 27 matching lines...) Expand all Loading... | |
62 if (!InitThumbnailTable()) | 87 if (!InitThumbnailTable()) |
63 return false; | 88 return false; |
64 | 89 |
65 if (meta_table_.GetVersionNumber() == 1) { | 90 if (meta_table_.GetVersionNumber() == 1) { |
66 if (!UpgradeToVersion2()) { | 91 if (!UpgradeToVersion2()) { |
67 LOG(WARNING) << "Unable to upgrade top sites database to version 2."; | 92 LOG(WARNING) << "Unable to upgrade top sites database to version 2."; |
68 return false; | 93 return false; |
69 } | 94 } |
70 } | 95 } |
71 | 96 |
97 if (meta_table_.GetVersionNumber() == 2) { | |
98 if (!UpgradeToVersion3()) { | |
99 LOG(WARNING) << "Unable to upgrade top sites database to version 3."; | |
100 return false; | |
101 } | |
102 } | |
103 | |
72 // Version check. | 104 // Version check. |
73 if (meta_table_.GetVersionNumber() != kVersionNumber) | 105 if (meta_table_.GetVersionNumber() != kVersionNumber) |
74 return false; | 106 return false; |
75 | 107 |
76 // Initialization is complete. | 108 // Initialization is complete. |
77 if (!transaction.Commit()) | 109 if (!transaction.Commit()) |
78 return false; | 110 return false; |
79 | 111 |
80 return true; | 112 return true; |
81 } | 113 } |
82 | 114 |
83 bool TopSitesDatabase::InitThumbnailTable() { | 115 bool TopSitesDatabase::InitThumbnailTable() { |
84 if (!db_->DoesTableExist("thumbnails")) { | 116 if (!db_->DoesTableExist("thumbnails")) { |
85 if (!db_->Execute("CREATE TABLE thumbnails (" | 117 if (!db_->Execute("CREATE TABLE thumbnails (" |
86 "url LONGVARCHAR PRIMARY KEY," | 118 "url LONGVARCHAR PRIMARY KEY," |
87 "url_rank INTEGER ," | 119 "url_rank INTEGER," |
88 "title LONGVARCHAR," | 120 "title LONGVARCHAR," |
89 "thumbnail BLOB," | 121 "thumbnail BLOB," |
90 "redirects LONGVARCHAR," | 122 "redirects LONGVARCHAR," |
91 "boring_score DOUBLE DEFAULT 1.0, " | 123 "boring_score DOUBLE DEFAULT 1.0," |
92 "good_clipping INTEGER DEFAULT 0, " | 124 "good_clipping INTEGER DEFAULT 0," |
93 "at_top INTEGER DEFAULT 0, " | 125 "at_top INTEGER DEFAULT 0," |
94 "last_updated INTEGER DEFAULT 0, " | 126 "last_updated INTEGER DEFAULT 0," |
95 "load_completed INTEGER DEFAULT 0) ")) { | 127 "load_completed INTEGER DEFAULT 0," |
128 "last_forced INTEGER DEFAULT 0)")) { | |
96 LOG(WARNING) << db_->GetErrorMessage(); | 129 LOG(WARNING) << db_->GetErrorMessage(); |
97 return false; | 130 return false; |
98 } | 131 } |
99 } | 132 } |
100 return true; | 133 return true; |
101 } | 134 } |
102 | 135 |
103 bool TopSitesDatabase::UpgradeToVersion2() { | 136 bool TopSitesDatabase::UpgradeToVersion2() { |
104 // Add 'load_completed' column. | 137 // Add 'load_completed' column. |
105 if (!db_->Execute( | 138 if (!db_->Execute( |
106 "ALTER TABLE thumbnails ADD load_completed INTEGER DEFAULT 0")) { | 139 "ALTER TABLE thumbnails ADD load_completed INTEGER DEFAULT 0")) { |
107 NOTREACHED(); | 140 NOTREACHED(); |
108 return false; | 141 return false; |
109 } | 142 } |
110 meta_table_.SetVersionNumber(2); | 143 meta_table_.SetVersionNumber(2); |
111 return true; | 144 return true; |
112 } | 145 } |
113 | 146 |
147 bool TopSitesDatabase::UpgradeToVersion3() { | |
148 // Add 'last_forced' column. | |
149 if (!db_->Execute( | |
150 "ALTER TABLE thumbnails ADD last_forced INTEGER DEFAULT 0")) { | |
151 NOTREACHED(); | |
152 return false; | |
153 } | |
154 meta_table_.SetVersionNumber(3); | |
155 return true; | |
156 } | |
157 | |
114 void TopSitesDatabase::GetPageThumbnails(MostVisitedURLList* urls, | 158 void TopSitesDatabase::GetPageThumbnails(MostVisitedURLList* urls, |
115 URLToImagesMap* thumbnails) { | 159 URLToImagesMap* thumbnails) { |
116 sql::Statement statement(db_->GetCachedStatement( | 160 sql::Statement statement(db_->GetCachedStatement( |
117 SQL_FROM_HERE, | 161 SQL_FROM_HERE, |
118 "SELECT url, url_rank, title, thumbnail, redirects, " | 162 "SELECT url, url_rank, title, thumbnail, redirects, " |
119 "boring_score, good_clipping, at_top, last_updated, load_completed " | 163 "boring_score, good_clipping, at_top, last_updated, load_completed, " |
120 "FROM thumbnails ORDER BY url_rank ")); | 164 "last_forced FROM thumbnails ORDER BY url_rank, last_forced")); |
121 | 165 |
122 if (!statement.is_valid()) { | 166 if (!statement.is_valid()) { |
123 LOG(WARNING) << db_->GetErrorMessage(); | 167 LOG(WARNING) << db_->GetErrorMessage(); |
124 return; | 168 return; |
125 } | 169 } |
126 | 170 |
127 urls->clear(); | 171 urls->clear(); |
128 thumbnails->clear(); | 172 thumbnails->clear(); |
129 | 173 |
130 while (statement.Step()) { | 174 while (statement.Step()) { |
131 // Results are sorted by url_rank. | 175 // Results are sorted by url_rank. For forced thumbnails with url_rank = -1, |
176 // thumbnails are sorted by last_forced. | |
132 MostVisitedURL url; | 177 MostVisitedURL url; |
133 GURL gurl(statement.ColumnString(0)); | 178 GURL gurl(statement.ColumnString(0)); |
134 url.url = gurl; | 179 url.url = gurl; |
135 url.title = statement.ColumnString16(2); | 180 url.title = statement.ColumnString16(2); |
181 url.last_forced_time = | |
182 base::Time::FromInternalValue(statement.ColumnInt64(10)); | |
136 std::string redirects = statement.ColumnString(4); | 183 std::string redirects = statement.ColumnString(4); |
137 SetRedirects(redirects, &url); | 184 SetRedirects(redirects, &url); |
138 urls->push_back(url); | 185 urls->push_back(url); |
139 | 186 |
140 std::vector<unsigned char> data; | 187 std::vector<unsigned char> data; |
141 statement.ColumnBlobAsVector(3, &data); | 188 statement.ColumnBlobAsVector(3, &data); |
142 Images thumbnail; | 189 Images thumbnail; |
143 if (!data.empty()) | 190 if (!data.empty()) |
144 thumbnail.thumbnail = base::RefCountedBytes::TakeVector(&data); | 191 thumbnail.thumbnail = base::RefCountedBytes::TakeVector(&data); |
145 thumbnail.thumbnail_score.boring_score = statement.ColumnDouble(5); | 192 thumbnail.thumbnail_score.boring_score = statement.ColumnDouble(5); |
146 thumbnail.thumbnail_score.good_clipping = statement.ColumnBool(6); | 193 thumbnail.thumbnail_score.good_clipping = statement.ColumnBool(6); |
147 thumbnail.thumbnail_score.at_top = statement.ColumnBool(7); | 194 thumbnail.thumbnail_score.at_top = statement.ColumnBool(7); |
148 thumbnail.thumbnail_score.time_at_snapshot = | 195 thumbnail.thumbnail_score.time_at_snapshot = |
149 base::Time::FromInternalValue(statement.ColumnInt64(8)); | 196 base::Time::FromInternalValue(statement.ColumnInt64(8)); |
150 thumbnail.thumbnail_score.load_completed = statement.ColumnBool(9); | 197 thumbnail.thumbnail_score.load_completed = statement.ColumnBool(9); |
151 | |
152 (*thumbnails)[gurl] = thumbnail; | 198 (*thumbnails)[gurl] = thumbnail; |
153 } | 199 } |
154 } | 200 } |
155 | 201 |
156 // static | 202 // static |
157 std::string TopSitesDatabase::GetRedirects(const MostVisitedURL& url) { | 203 std::string TopSitesDatabase::GetRedirects(const MostVisitedURL& url) { |
158 std::vector<std::string> redirects; | 204 std::vector<std::string> redirects; |
159 for (size_t i = 0; i < url.redirects.size(); i++) | 205 for (size_t i = 0; i < url.redirects.size(); i++) |
160 redirects.push_back(url.redirects[i].spec()); | 206 redirects.push_back(url.redirects[i].spec()); |
161 return JoinString(redirects, ' '); | 207 return JoinString(redirects, ' '); |
162 } | 208 } |
163 | 209 |
164 // static | 210 // static |
165 void TopSitesDatabase::SetRedirects(const std::string& redirects, | 211 void TopSitesDatabase::SetRedirects(const std::string& redirects, |
166 MostVisitedURL* url) { | 212 MostVisitedURL* url) { |
167 std::vector<std::string> redirects_vector; | 213 std::vector<std::string> redirects_vector; |
168 base::SplitStringAlongWhitespace(redirects, &redirects_vector); | 214 base::SplitStringAlongWhitespace(redirects, &redirects_vector); |
169 for (size_t i = 0; i < redirects_vector.size(); ++i) | 215 for (size_t i = 0; i < redirects_vector.size(); ++i) |
170 url->redirects.push_back(GURL(redirects_vector[i])); | 216 url->redirects.push_back(GURL(redirects_vector[i])); |
171 } | 217 } |
172 | 218 |
173 void TopSitesDatabase::SetPageThumbnail(const MostVisitedURL& url, | 219 void TopSitesDatabase::SetPageThumbnail(const MostVisitedURL& url, |
174 int new_rank, | 220 int new_rank, |
175 const Images& thumbnail) { | 221 const Images& thumbnail) { |
176 sql::Transaction transaction(db_.get()); | 222 sql::Transaction transaction(db_.get()); |
177 transaction.Begin(); | 223 transaction.Begin(); |
178 | 224 |
179 int rank = GetURLRank(url); | 225 int rank = GetURLRank(url); |
180 if (rank == -1) { | 226 if (rank == kRankOfNonExistingURL) { |
181 AddPageThumbnail(url, new_rank, thumbnail); | 227 AddPageThumbnail(url, new_rank, thumbnail); |
182 } else { | 228 } else { |
183 UpdatePageRankNoTransaction(url, new_rank); | 229 UpdatePageRankNoTransaction(url, new_rank); |
184 UpdatePageThumbnail(url, thumbnail); | 230 UpdatePageThumbnail(url, thumbnail); |
185 } | 231 } |
186 | 232 |
187 transaction.Commit(); | 233 transaction.Commit(); |
188 } | 234 } |
189 | 235 |
190 bool TopSitesDatabase::UpdatePageThumbnail( | 236 bool TopSitesDatabase::UpdatePageThumbnail( |
191 const MostVisitedURL& url, const Images& thumbnail) { | 237 const MostVisitedURL& url, const Images& thumbnail) { |
192 sql::Statement statement(db_->GetCachedStatement( | 238 sql::Statement statement(db_->GetCachedStatement( |
193 SQL_FROM_HERE, | 239 SQL_FROM_HERE, |
194 "UPDATE thumbnails SET " | 240 "UPDATE thumbnails SET " |
195 "title = ?, thumbnail = ?, redirects = ?, " | 241 "title = ?, thumbnail = ?, redirects = ?, " |
196 "boring_score = ?, good_clipping = ?, at_top = ?, last_updated = ?, " | 242 "boring_score = ?, good_clipping = ?, at_top = ?, last_updated = ?, " |
197 "load_completed = ? " | 243 "load_completed = ?, last_forced = ?" |
198 "WHERE url = ? ")); | 244 "WHERE url = ? ")); |
199 statement.BindString16(0, url.title); | 245 statement.BindString16(0, url.title); |
200 if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) { | 246 if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) { |
201 statement.BindBlob(1, thumbnail.thumbnail->front(), | 247 statement.BindBlob(1, thumbnail.thumbnail->front(), |
202 static_cast<int>(thumbnail.thumbnail->size())); | 248 static_cast<int>(thumbnail.thumbnail->size())); |
203 } | 249 } |
204 statement.BindString(2, GetRedirects(url)); | 250 statement.BindString(2, GetRedirects(url)); |
205 const ThumbnailScore& score = thumbnail.thumbnail_score; | 251 const ThumbnailScore& score = thumbnail.thumbnail_score; |
206 statement.BindDouble(3, score.boring_score); | 252 statement.BindDouble(3, score.boring_score); |
207 statement.BindBool(4, score.good_clipping); | 253 statement.BindBool(4, score.good_clipping); |
208 statement.BindBool(5, score.at_top); | 254 statement.BindBool(5, score.at_top); |
209 statement.BindInt64(6, score.time_at_snapshot.ToInternalValue()); | 255 statement.BindInt64(6, score.time_at_snapshot.ToInternalValue()); |
210 statement.BindBool(7, score.load_completed); | 256 statement.BindBool(7, score.load_completed); |
211 statement.BindString(8, url.url.spec()); | 257 statement.BindInt64(8, url.last_forced_time.ToInternalValue()); |
258 statement.BindString(9, url.url.spec()); | |
212 | 259 |
213 return statement.Run(); | 260 return statement.Run(); |
214 } | 261 } |
215 | 262 |
216 void TopSitesDatabase::AddPageThumbnail(const MostVisitedURL& url, | 263 void TopSitesDatabase::AddPageThumbnail(const MostVisitedURL& url, |
217 int new_rank, | 264 int new_rank, |
218 const Images& thumbnail) { | 265 const Images& thumbnail) { |
219 int count = GetRowCount(); | |
220 | |
221 sql::Statement statement(db_->GetCachedStatement( | 266 sql::Statement statement(db_->GetCachedStatement( |
222 SQL_FROM_HERE, | 267 SQL_FROM_HERE, |
223 "INSERT OR REPLACE INTO thumbnails " | 268 "INSERT OR REPLACE INTO thumbnails " |
224 "(url, url_rank, title, thumbnail, redirects, " | 269 "(url, url_rank, title, thumbnail, redirects, " |
225 "boring_score, good_clipping, at_top, last_updated, load_completed) " | 270 "boring_score, good_clipping, at_top, last_updated, load_completed, " |
226 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); | 271 "last_forced) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
227 statement.BindString(0, url.url.spec()); | 272 statement.BindString(0, url.url.spec()); |
228 statement.BindInt(1, count); // Make it the last url. | 273 statement.BindInt(1, kRankOfForcedURL); // Fist make it a forced thumbnail. |
229 statement.BindString16(2, url.title); | 274 statement.BindString16(2, url.title); |
230 if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) { | 275 if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) { |
231 statement.BindBlob(3, thumbnail.thumbnail->front(), | 276 statement.BindBlob(3, thumbnail.thumbnail->front(), |
232 static_cast<int>(thumbnail.thumbnail->size())); | 277 static_cast<int>(thumbnail.thumbnail->size())); |
233 } | 278 } |
234 statement.BindString(4, GetRedirects(url)); | 279 statement.BindString(4, GetRedirects(url)); |
235 const ThumbnailScore& score = thumbnail.thumbnail_score; | 280 const ThumbnailScore& score = thumbnail.thumbnail_score; |
236 statement.BindDouble(5, score.boring_score); | 281 statement.BindDouble(5, score.boring_score); |
237 statement.BindBool(6, score.good_clipping); | 282 statement.BindBool(6, score.good_clipping); |
238 statement.BindBool(7, score.at_top); | 283 statement.BindBool(7, score.at_top); |
239 statement.BindInt64(8, score.time_at_snapshot.ToInternalValue()); | 284 statement.BindInt64(8, score.time_at_snapshot.ToInternalValue()); |
240 statement.BindBool(9, score.load_completed); | 285 statement.BindBool(9, score.load_completed); |
286 int64 last_forced = url.last_forced_time.ToInternalValue(); | |
287 DCHECK((last_forced == 0) == (new_rank != kRankOfForcedURL)) | |
288 << "Thumbnail without a forced time stamp has a forced rank, or the " | |
brettw
2013/10/28 22:22:27
Nit: intend 2 more spaces.
beaudoin
2013/10/29 15:27:50
Done.
| |
289 << "opposite."; | |
290 statement.BindInt64(10, last_forced); | |
241 if (!statement.Run()) | 291 if (!statement.Run()) |
242 return; | 292 return; |
243 | 293 |
244 UpdatePageRankNoTransaction(url, new_rank); | 294 // Update rank if this is not a forced thumbnail. |
295 if (new_rank != kRankOfForcedURL) | |
296 UpdatePageRankNoTransaction(url, new_rank); | |
245 } | 297 } |
246 | 298 |
247 void TopSitesDatabase::UpdatePageRank(const MostVisitedURL& url, | 299 void TopSitesDatabase::UpdatePageRank(const MostVisitedURL& url, |
248 int new_rank) { | 300 int new_rank) { |
301 DCHECK((url.last_forced_time.ToInternalValue() == 0) == | |
302 (new_rank != kRankOfForcedURL)) | |
303 << "Thumbnail without a forced time stamp has a forced rank, or the " | |
brettw
2013/10/28 22:22:27
ditto
beaudoin
2013/10/29 15:27:50
Done.
| |
304 << "opposite."; | |
249 sql::Transaction transaction(db_.get()); | 305 sql::Transaction transaction(db_.get()); |
250 transaction.Begin(); | 306 transaction.Begin(); |
251 UpdatePageRankNoTransaction(url, new_rank); | 307 UpdatePageRankNoTransaction(url, new_rank); |
252 transaction.Commit(); | 308 transaction.Commit(); |
253 } | 309 } |
254 | 310 |
255 // Caller should have a transaction open. | 311 // Caller should have a transaction open. |
256 void TopSitesDatabase::UpdatePageRankNoTransaction( | 312 void TopSitesDatabase::UpdatePageRankNoTransaction( |
257 const MostVisitedURL& url, int new_rank) { | 313 const MostVisitedURL& url, int new_rank) { |
258 DCHECK_GT(db_->transaction_nesting(), 0); | 314 DCHECK_GT(db_->transaction_nesting(), 0); |
315 | |
259 int prev_rank = GetURLRank(url); | 316 int prev_rank = GetURLRank(url); |
260 if (prev_rank == -1) { | 317 if (prev_rank == kRankOfNonExistingURL) { |
261 LOG(WARNING) << "Updating rank of an unknown URL: " << url.url.spec(); | 318 LOG(WARNING) << "Updating rank of an unknown URL: " << url.url.spec(); |
262 return; | 319 return; |
263 } | 320 } |
264 | 321 |
265 // Shift the ranks. | 322 // Shift the ranks. |
266 if (prev_rank > new_rank) { | 323 if (prev_rank > new_rank) { |
267 // Shift up | 324 if (new_rank == kRankOfForcedURL) { |
268 sql::Statement shift_statement(db_->GetCachedStatement( | 325 // From non-forced to forced, shift down. |
269 SQL_FROM_HERE, | 326 // Example: 2 -> -1 |
270 "UPDATE thumbnails " | 327 // -1, -1, -1, 0, 1, [2 -> -1], [3 -> 2], [4 -> 3] |
271 "SET url_rank = url_rank + 1 " | 328 sql::Statement shift_statement(db_->GetCachedStatement( |
272 "WHERE url_rank >= ? AND url_rank < ?")); | 329 SQL_FROM_HERE, |
273 shift_statement.BindInt(0, new_rank); | 330 "UPDATE thumbnails " |
274 shift_statement.BindInt(1, prev_rank); | 331 "SET url_rank = url_rank - 1 " |
275 shift_statement.Run(); | 332 "WHERE url_rank > ?")); |
333 shift_statement.BindInt(0, prev_rank); | |
334 shift_statement.Run(); | |
335 } else { | |
336 // From non-forced to non-forced, shift up. | |
337 // Example: 3 -> 1 | |
338 // -1, -1, -1, 0, [1 -> 2], [2 -> 3], [3 -> 1], 4 | |
339 sql::Statement shift_statement(db_->GetCachedStatement( | |
340 SQL_FROM_HERE, | |
341 "UPDATE thumbnails " | |
342 "SET url_rank = url_rank + 1 " | |
343 "WHERE url_rank >= ? AND url_rank < ?")); | |
344 shift_statement.BindInt(0, new_rank); | |
345 shift_statement.BindInt(1, prev_rank); | |
346 shift_statement.Run(); | |
347 } | |
276 } else if (prev_rank < new_rank) { | 348 } else if (prev_rank < new_rank) { |
277 // Shift down | 349 if (prev_rank == kRankOfForcedURL) { |
278 sql::Statement shift_statement(db_->GetCachedStatement( | 350 // From non-forced to forced, shift up. |
279 SQL_FROM_HERE, | 351 // Example: -1 -> 2 |
280 "UPDATE thumbnails " | 352 // -1, [-1 -> 2], -1, 0, 1, [2 -> 3], [3 -> 4], [4 -> 5] |
281 "SET url_rank = url_rank - 1 " | 353 sql::Statement shift_statement(db_->GetCachedStatement( |
282 "WHERE url_rank > ? AND url_rank <= ?")); | 354 SQL_FROM_HERE, |
283 shift_statement.BindInt(0, prev_rank); | 355 "UPDATE thumbnails " |
284 shift_statement.BindInt(1, new_rank); | 356 "SET url_rank = url_rank + 1 " |
285 shift_statement.Run(); | 357 "WHERE url_rank >= ?")); |
358 shift_statement.BindInt(0, new_rank); | |
359 shift_statement.Run(); | |
360 } else { | |
361 // From non-forced to non-forced, shift down. | |
362 // Example: 1 -> 3. | |
363 // -1, -1, -1, 0, [1 -> 3], [2 -> 1], [3 -> 2], 4 | |
364 sql::Statement shift_statement(db_->GetCachedStatement( | |
365 SQL_FROM_HERE, | |
366 "UPDATE thumbnails " | |
367 "SET url_rank = url_rank - 1 " | |
368 "WHERE url_rank > ? AND url_rank <= ?")); | |
369 shift_statement.BindInt(0, prev_rank); | |
370 shift_statement.BindInt(1, new_rank); | |
371 shift_statement.Run(); | |
372 } | |
286 } | 373 } |
287 | 374 |
288 // Set the url's rank. | 375 // Set the url's rank and last_forced, since the latter changes when a URL |
376 // goes from forced to non-forced and vice-versa. | |
289 sql::Statement set_statement(db_->GetCachedStatement( | 377 sql::Statement set_statement(db_->GetCachedStatement( |
290 SQL_FROM_HERE, | 378 SQL_FROM_HERE, |
291 "UPDATE thumbnails " | 379 "UPDATE thumbnails " |
292 "SET url_rank = ? " | 380 "SET url_rank = ?, last_forced = ? " |
293 "WHERE url == ?")); | 381 "WHERE url == ?")); |
294 set_statement.BindInt(0, new_rank); | 382 set_statement.BindInt(0, new_rank); |
295 set_statement.BindString(1, url.url.spec()); | 383 set_statement.BindInt64(1, url.last_forced_time.ToInternalValue()); |
384 set_statement.BindString(2, url.url.spec()); | |
296 set_statement.Run(); | 385 set_statement.Run(); |
297 } | 386 } |
298 | 387 |
299 bool TopSitesDatabase::GetPageThumbnail(const GURL& url, | 388 bool TopSitesDatabase::GetPageThumbnail(const GURL& url, |
300 Images* thumbnail) { | 389 Images* thumbnail) { |
301 sql::Statement statement(db_->GetCachedStatement( | 390 sql::Statement statement(db_->GetCachedStatement( |
302 SQL_FROM_HERE, | 391 SQL_FROM_HERE, |
303 "SELECT thumbnail, boring_score, good_clipping, at_top, last_updated " | 392 "SELECT thumbnail, boring_score, good_clipping, at_top, last_updated " |
304 "FROM thumbnails WHERE url=?")); | 393 "FROM thumbnails WHERE url=?")); |
305 statement.BindString(0, url.spec()); | 394 statement.BindString(0, url.spec()); |
306 if (!statement.Step()) | 395 if (!statement.Step()) |
307 return false; | 396 return false; |
308 | 397 |
309 std::vector<unsigned char> data; | 398 std::vector<unsigned char> data; |
310 statement.ColumnBlobAsVector(0, &data); | 399 statement.ColumnBlobAsVector(0, &data); |
311 thumbnail->thumbnail = base::RefCountedBytes::TakeVector(&data); | 400 thumbnail->thumbnail = base::RefCountedBytes::TakeVector(&data); |
312 thumbnail->thumbnail_score.boring_score = statement.ColumnDouble(1); | 401 thumbnail->thumbnail_score.boring_score = statement.ColumnDouble(1); |
313 thumbnail->thumbnail_score.good_clipping = statement.ColumnBool(2); | 402 thumbnail->thumbnail_score.good_clipping = statement.ColumnBool(2); |
314 thumbnail->thumbnail_score.at_top = statement.ColumnBool(3); | 403 thumbnail->thumbnail_score.at_top = statement.ColumnBool(3); |
315 thumbnail->thumbnail_score.time_at_snapshot = | 404 thumbnail->thumbnail_score.time_at_snapshot = |
316 base::Time::FromInternalValue(statement.ColumnInt64(4)); | 405 base::Time::FromInternalValue(statement.ColumnInt64(4)); |
317 return true; | 406 return true; |
318 } | 407 } |
319 | 408 |
320 int TopSitesDatabase::GetRowCount() { | |
321 sql::Statement select_statement(db_->GetCachedStatement( | |
322 SQL_FROM_HERE, | |
323 "SELECT COUNT (url) FROM thumbnails")); | |
324 if (select_statement.Step()) | |
325 return select_statement.ColumnInt(0); | |
326 | |
327 return 0; | |
328 } | |
329 | |
330 int TopSitesDatabase::GetURLRank(const MostVisitedURL& url) { | 409 int TopSitesDatabase::GetURLRank(const MostVisitedURL& url) { |
331 sql::Statement select_statement(db_->GetCachedStatement( | 410 sql::Statement select_statement(db_->GetCachedStatement( |
332 SQL_FROM_HERE, | 411 SQL_FROM_HERE, |
333 "SELECT url_rank " | 412 "SELECT url_rank " |
334 "FROM thumbnails WHERE url=?")); | 413 "FROM thumbnails WHERE url=?")); |
335 select_statement.BindString(0, url.url.spec()); | 414 select_statement.BindString(0, url.url.spec()); |
336 if (select_statement.Step()) | 415 if (select_statement.Step()) |
337 return select_statement.ColumnInt(0); | 416 return select_statement.ColumnInt(0); |
338 | 417 |
339 return -1; | 418 return kRankOfNonExistingURL; |
340 } | 419 } |
341 | 420 |
342 // Remove the record for this URL. Returns true iff removed successfully. | 421 // Remove the record for this URL. Returns true iff removed successfully. |
343 bool TopSitesDatabase::RemoveURL(const MostVisitedURL& url) { | 422 bool TopSitesDatabase::RemoveURL(const MostVisitedURL& url) { |
344 int old_rank = GetURLRank(url); | 423 int old_rank = GetURLRank(url); |
345 if (old_rank < 0) | 424 if (old_rank == kRankOfNonExistingURL) |
346 return false; | 425 return false; |
347 | 426 |
348 sql::Transaction transaction(db_.get()); | 427 sql::Transaction transaction(db_.get()); |
349 transaction.Begin(); | 428 transaction.Begin(); |
350 // Decrement all following ranks. | 429 if (old_rank != kRankOfForcedURL) { |
351 sql::Statement shift_statement(db_->GetCachedStatement( | 430 // Decrement all following ranks. |
352 SQL_FROM_HERE, | 431 sql::Statement shift_statement(db_->GetCachedStatement( |
353 "UPDATE thumbnails " | 432 SQL_FROM_HERE, |
354 "SET url_rank = url_rank - 1 " | 433 "UPDATE thumbnails " |
355 "WHERE url_rank > ?")); | 434 "SET url_rank = url_rank - 1 " |
356 shift_statement.BindInt(0, old_rank); | 435 "WHERE url_rank > ?")); |
436 shift_statement.BindInt(0, old_rank); | |
357 | 437 |
358 if (!shift_statement.Run()) | 438 if (!shift_statement.Run()) |
359 return false; | 439 return false; |
440 } | |
360 | 441 |
361 sql::Statement delete_statement( | 442 sql::Statement delete_statement( |
362 db_->GetCachedStatement(SQL_FROM_HERE, | 443 db_->GetCachedStatement(SQL_FROM_HERE, |
363 "DELETE FROM thumbnails WHERE url = ?")); | 444 "DELETE FROM thumbnails WHERE url = ?")); |
364 delete_statement.BindString(0, url.url.spec()); | 445 delete_statement.BindString(0, url.url.spec()); |
365 | 446 |
366 if (!delete_statement.Run()) | 447 if (!delete_statement.Run()) |
367 return false; | 448 return false; |
368 | 449 |
369 return transaction.Commit(); | 450 return transaction.Commit(); |
370 } | 451 } |
371 | 452 |
372 sql::Connection* TopSitesDatabase::CreateDB(const base::FilePath& db_name) { | 453 sql::Connection* TopSitesDatabase::CreateDB(const base::FilePath& db_name) { |
373 scoped_ptr<sql::Connection> db(new sql::Connection()); | 454 scoped_ptr<sql::Connection> db(new sql::Connection()); |
374 // Settings copied from ThumbnailDatabase. | 455 // Settings copied from ThumbnailDatabase. |
375 db->set_histogram_tag("TopSites"); | 456 db->set_histogram_tag("TopSites"); |
376 db->set_page_size(4096); | 457 db->set_page_size(4096); |
377 db->set_cache_size(32); | 458 db->set_cache_size(32); |
378 | 459 |
379 if (!db->Open(db_name)) { | 460 if (!db->Open(db_name)) { |
380 LOG(ERROR) << db->GetErrorMessage(); | 461 LOG(ERROR) << db->GetErrorMessage(); |
381 return NULL; | 462 return NULL; |
382 } | 463 } |
383 | 464 |
384 return db.release(); | 465 return db.release(); |
385 } | 466 } |
386 | 467 |
387 } // namespace history | 468 } // namespace history |
OLD | NEW |