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 "chrome/browser/history/thumbnail_database.h" | 5 #include "chrome/browser/history/thumbnail_database.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/memory/ref_counted_memory.h" | 12 #include "base/memory/ref_counted_memory.h" |
13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
14 #include "base/time.h" | 14 #include "base/time.h" |
15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
16 #include "chrome/browser/diagnostics/sqlite_diagnostics.h" | 16 #include "chrome/browser/diagnostics/sqlite_diagnostics.h" |
17 #include "chrome/browser/history/history_publisher.h" | 17 #include "chrome/browser/history/history_publisher.h" |
18 #include "chrome/browser/history/top_sites.h" | 18 #include "chrome/browser/history/top_sites.h" |
19 #include "chrome/browser/history/url_database.h" | 19 #include "chrome/browser/history/url_database.h" |
20 #include "chrome/common/thumbnail_score.h" | 20 #include "chrome/common/thumbnail_score.h" |
21 #include "sql/statement.h" | 21 #include "sql/statement.h" |
22 #include "sql/transaction.h" | 22 #include "sql/transaction.h" |
23 #include "ui/gfx/image/image_util.h" | 23 #include "ui/gfx/image/image_util.h" |
24 | 24 |
25 #if defined(OS_MACOSX) | 25 #if defined(OS_MACOSX) |
26 #include "base/mac/mac_util.h" | 26 #include "base/mac/mac_util.h" |
27 #endif | 27 #endif |
28 | 28 |
| 29 // Description of database tables: |
| 30 // |
| 31 // icon_mapping |
| 32 // id Unique ID. |
| 33 // page_url Page URL which has one or more associated favicons. |
| 34 // icon_id The ID of favicon that this mapping maps to. |
| 35 // |
| 36 // favicons This table associates a row to each favicon for a |
| 37 // |page_url| in the |icon_mapping| table. This is the |
| 38 // default favicon |page_url|/favicon.ico plus any favicons |
| 39 // associated via <link rel="icon_type" href="url">. |
| 40 // The |id| matches the |icon_id| field in the appropriate |
| 41 // row in the icon_mapping table. |
| 42 // |
| 43 // id Unique ID. |
| 44 // url The URL at which the favicon file is located. |
| 45 // icon_type The type of the favicon specified in the rel attribute of |
| 46 // the link tag. The FAVICON type is used for the default |
| 47 // favicon.ico favicon. |
| 48 // sizes Sizes is a listing of all the sizes at which the favicon |
| 49 // at |url| is available from the web. Note that this may |
| 50 // include sizes for which a bitmap is not stored in the |
| 51 // favicon_bitmaps table. Each widthxheight pair is |
| 52 // separated by a space. Width and height are separated by |
| 53 // a space as well. For instance, if |icon_id| represents a |
| 54 // .ico file containing 16x16 and 32x32 bitmaps, |sizes| |
| 55 // would be "16 16 32 32". |
| 56 // |
| 57 // favicon_bitmaps This table contains the PNG encoded bitmap data of the |
| 58 // favicons. There is a separate row for every size in a |
| 59 // multi resolution bitmap. The bitmap data is associated |
| 60 // to the favicon via the |icon_id| field which matches |
| 61 // the |id| field in the appropriate row in the |favicons| |
| 62 // table. There is not necessarily a row for each size |
| 63 // specified in the sizes attribute. |
| 64 // |
| 65 // id Unique ID. |
| 66 // icon_id The ID of the favicon that the bitmap is associated to. |
| 67 // last_updated The time at which this favicon was inserted into the |
| 68 // table. This is used to determine if it needs to be |
| 69 // redownloaded from the web. |
| 70 // image_data PNG encoded data of the favicon. |
| 71 // width Pixel width of |image_data|. |
| 72 // height Pixel height of |image_data|. |
| 73 |
| 74 |
| 75 |
29 static void FillIconMapping(const sql::Statement& statement, | 76 static void FillIconMapping(const sql::Statement& statement, |
30 const GURL& page_url, | 77 const GURL& page_url, |
31 history::IconMapping* icon_mapping) { | 78 history::IconMapping* icon_mapping) { |
32 icon_mapping->mapping_id = statement.ColumnInt64(0); | 79 icon_mapping->mapping_id = statement.ColumnInt64(0); |
33 icon_mapping->icon_id = statement.ColumnInt64(1); | 80 icon_mapping->icon_id = statement.ColumnInt64(1); |
34 icon_mapping->icon_type = | 81 icon_mapping->icon_type = |
35 static_cast<history::IconType>(statement.ColumnInt(2)); | 82 static_cast<history::IconType>(statement.ColumnInt(2)); |
36 icon_mapping->page_url = page_url; | 83 icon_mapping->page_url = page_url; |
37 } | 84 } |
38 | 85 |
39 namespace history { | 86 namespace history { |
40 | 87 |
41 // Version number of the database. | 88 // Version number of the database. |
42 static const int kCurrentVersionNumber = 5; | 89 static const int kCurrentVersionNumber = 6; |
43 static const int kCompatibleVersionNumber = 5; | 90 static const int kCompatibleVersionNumber = 6; |
44 | 91 |
45 // Use 90 quality (out of 100) which is pretty high, because we're very | 92 // Use 90 quality (out of 100) which is pretty high, because we're very |
46 // sensitive to artifacts for these small sized, highly detailed images. | 93 // sensitive to artifacts for these small sized, highly detailed images. |
47 static const int kImageQuality = 90; | 94 static const int kImageQuality = 90; |
48 | 95 |
49 ThumbnailDatabase::IconMappingEnumerator::IconMappingEnumerator() { | 96 ThumbnailDatabase::IconMappingEnumerator::IconMappingEnumerator() { |
50 } | 97 } |
51 | 98 |
52 ThumbnailDatabase::IconMappingEnumerator::~IconMappingEnumerator() { | 99 ThumbnailDatabase::IconMappingEnumerator::~IconMappingEnumerator() { |
53 } | 100 } |
54 | 101 |
55 bool ThumbnailDatabase::IconMappingEnumerator::GetNextIconMapping( | 102 bool ThumbnailDatabase::IconMappingEnumerator::GetNextIconMapping( |
56 IconMapping* icon_mapping) { | 103 IconMapping* icon_mapping) { |
57 if (!statement_.Step()) | 104 if (!statement_.Step()) |
58 return false; | 105 return false; |
59 FillIconMapping(statement_, GURL(statement_.ColumnString(3)), icon_mapping); | 106 FillIconMapping(statement_, GURL(statement_.ColumnString(3)), icon_mapping); |
60 return true; | 107 return true; |
61 } | 108 } |
62 | 109 |
63 ThumbnailDatabase::ThumbnailDatabase() | 110 ThumbnailDatabase::ThumbnailDatabase() |
64 : history_publisher_(NULL), | 111 : history_publisher_(NULL), |
65 use_top_sites_(false) { | 112 use_top_sites_(false) { |
66 } | 113 } |
67 | 114 |
68 sql::InitStatus ThumbnailDatabase::CantUpgradeToVersion(int cur_version) { | 115 sql::InitStatus ThumbnailDatabase::CantUpgradeToVersion(int cur_version) { |
69 LOG(WARNING) << "Unable to update to thumbnail database to version 4" << | 116 LOG(WARNING) << "Unable to update to thumbnail database to version " << |
70 cur_version << "."; | 117 cur_version << "."; |
71 db_.Close(); | 118 db_.Close(); |
72 return sql::INIT_FAILURE; | 119 return sql::INIT_FAILURE; |
73 } | 120 } |
74 | 121 |
75 ThumbnailDatabase::~ThumbnailDatabase() { | 122 ThumbnailDatabase::~ThumbnailDatabase() { |
76 // The DBCloseScoper will delete the DB and the cache. | 123 // The DBCloseScoper will delete the DB and the cache. |
77 } | 124 } |
78 | 125 |
79 sql::InitStatus ThumbnailDatabase::Init( | 126 sql::InitStatus ThumbnailDatabase::Init( |
(...skipping 11 matching lines...) Expand all Loading... |
91 | 138 |
92 #if defined(OS_MACOSX) | 139 #if defined(OS_MACOSX) |
93 // Exclude the thumbnails file from backups. | 140 // Exclude the thumbnails file from backups. |
94 base::mac::SetFileBackupExclusion(db_name); | 141 base::mac::SetFileBackupExclusion(db_name); |
95 #endif | 142 #endif |
96 | 143 |
97 // Create the tables. | 144 // Create the tables. |
98 if (!meta_table_.Init(&db_, kCurrentVersionNumber, | 145 if (!meta_table_.Init(&db_, kCurrentVersionNumber, |
99 kCompatibleVersionNumber) || | 146 kCompatibleVersionNumber) || |
100 !InitThumbnailTable() || | 147 !InitThumbnailTable() || |
| 148 !InitFaviconBitmapsTable(&db_, false) || |
| 149 !InitFaviconBitmapsIndex() || |
101 !InitFaviconsTable(&db_, false) || | 150 !InitFaviconsTable(&db_, false) || |
102 !InitFaviconsIndex() || | 151 !InitFaviconsIndex() || |
103 !InitIconMappingTable(&db_, false) || | 152 !InitIconMappingTable(&db_, false) || |
104 !InitIconMappingIndex()) { | 153 !InitIconMappingIndex()) { |
105 db_.Close(); | 154 db_.Close(); |
106 return sql::INIT_FAILURE; | 155 return sql::INIT_FAILURE; |
107 } | 156 } |
108 | 157 |
109 // Version check. We should not encounter a database too old for us to handle | 158 // Version check. We should not encounter a database too old for us to handle |
110 // in the wild, so we try to continue in that case. | 159 // in the wild, so we try to continue in that case. |
111 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { | 160 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
112 LOG(WARNING) << "Thumbnail database is too new."; | 161 LOG(WARNING) << "Thumbnail database is too new."; |
113 return sql::INIT_TOO_NEW; | 162 return sql::INIT_TOO_NEW; |
114 } | 163 } |
115 | 164 |
116 int cur_version = meta_table_.GetVersionNumber(); | 165 int cur_version = meta_table_.GetVersionNumber(); |
117 if (cur_version == 2) { | 166 if (cur_version == 2) { |
118 ++cur_version; | 167 ++cur_version; |
119 if (!UpgradeToVersion3()) | 168 if (!UpgradeToVersion3()) |
120 return CantUpgradeToVersion(cur_version); | 169 return CantUpgradeToVersion(cur_version); |
121 } | 170 } |
122 | 171 |
123 if (cur_version == 3) { | 172 if (cur_version == 3) { |
124 ++cur_version; | 173 ++cur_version; |
125 if (!UpgradeToVersion4() || !MigrateIconMappingData(url_db)) | 174 if (!UpgradeToVersion4() || !MigrateIconMappingData(url_db)) |
126 return CantUpgradeToVersion(cur_version); | 175 return CantUpgradeToVersion(cur_version); |
127 } | 176 } |
128 | 177 |
129 if (cur_version == 4) { | 178 if (cur_version == 4) { |
| 179 ++cur_version; |
130 if (!UpgradeToVersion5()) | 180 if (!UpgradeToVersion5()) |
131 return CantUpgradeToVersion(cur_version); | 181 return CantUpgradeToVersion(cur_version); |
132 } | 182 } |
133 | 183 |
| 184 if (cur_version == 5) { |
| 185 ++cur_version; |
| 186 if (!UpgradeToVersion6()) |
| 187 return CantUpgradeToVersion(cur_version); |
| 188 } |
| 189 |
134 LOG_IF(WARNING, cur_version < kCurrentVersionNumber) << | 190 LOG_IF(WARNING, cur_version < kCurrentVersionNumber) << |
135 "Thumbnail database version " << cur_version << " is too old to handle."; | 191 "Thumbnail database version " << cur_version << " is too old to handle."; |
136 | 192 |
137 // Initialization is complete. | 193 // Initialization is complete. |
138 if (!transaction.Commit()) { | 194 if (!transaction.Commit()) { |
139 db_.Close(); | 195 db_.Close(); |
140 return sql::INIT_FAILURE; | 196 return sql::INIT_FAILURE; |
141 } | 197 } |
142 | 198 |
143 return sql::INIT_OK; | 199 return sql::INIT_OK; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 return true; // Not needed after migration to TopSites. | 260 return true; // Not needed after migration to TopSites. |
205 | 261 |
206 if (!db_.Execute("DROP TABLE thumbnails")) | 262 if (!db_.Execute("DROP TABLE thumbnails")) |
207 return false; | 263 return false; |
208 return InitThumbnailTable(); | 264 return InitThumbnailTable(); |
209 } | 265 } |
210 | 266 |
211 bool ThumbnailDatabase::InitFaviconsTable(sql::Connection* db, | 267 bool ThumbnailDatabase::InitFaviconsTable(sql::Connection* db, |
212 bool is_temporary) { | 268 bool is_temporary) { |
213 // Note: if you update the schema, don't forget to update | 269 // Note: if you update the schema, don't forget to update |
214 // CopyToTemporaryFaviconTable as well. | 270 // CopyFaviconAndFaviconBitmapsToTemporaryTables as well. |
215 const char* name = is_temporary ? "temp_favicons" : "favicons"; | 271 const char* name = is_temporary ? "temp_favicons" : "favicons"; |
216 if (!db->DoesTableExist(name)) { | 272 if (!db->DoesTableExist(name)) { |
217 std::string sql; | 273 std::string sql; |
218 sql.append("CREATE TABLE "); | 274 sql.append("CREATE TABLE "); |
219 sql.append(name); | 275 sql.append(name); |
220 sql.append("(" | 276 sql.append("(" |
221 "id INTEGER PRIMARY KEY," | 277 "id INTEGER PRIMARY KEY," |
222 "url LONGVARCHAR NOT NULL," | 278 "url LONGVARCHAR NOT NULL," |
223 "last_updated INTEGER DEFAULT 0," | |
224 "image_data BLOB," | |
225 // Set the default icon_type as FAVICON to be consistent with | 279 // Set the default icon_type as FAVICON to be consistent with |
226 // table upgrade in UpgradeToVersion4(). | 280 // table upgrade in UpgradeToVersion4(). |
227 "icon_type INTEGER DEFAULT 1," | 281 "icon_type INTEGER DEFAULT 1," |
228 "sizes LONGVARCHAR)"); | 282 "sizes LONGVARCHAR)"); |
229 if (!db->Execute(sql.c_str())) | 283 if (!db->Execute(sql.c_str())) |
230 return false; | 284 return false; |
231 } | 285 } |
232 return true; | 286 return true; |
233 } | 287 } |
234 | 288 |
235 bool ThumbnailDatabase::InitFaviconsIndex() { | 289 bool ThumbnailDatabase::InitFaviconsIndex() { |
236 // Add an index on the url column. | 290 // Add an index on the url column. |
237 return | 291 return |
238 db_.Execute("CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)"); | 292 db_.Execute("CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)"); |
239 } | 293 } |
240 | 294 |
| 295 bool ThumbnailDatabase::InitFaviconBitmapsTable(sql::Connection* db, |
| 296 bool is_temporary) { |
| 297 // Note: if you update the schema, don't forget to update |
| 298 // CopyFaviconAndFaviconBitmapsToTemporaryTables as well. |
| 299 const char* name = is_temporary ? "temp_favicon_bitmaps" : "favicon_bitmaps"; |
| 300 if (!db->DoesTableExist(name)) { |
| 301 std::string sql; |
| 302 sql.append("CREATE TABLE "); |
| 303 sql.append(name); |
| 304 sql.append("(" |
| 305 "id INTEGER PRIMARY KEY," |
| 306 "icon_id INTEGER NOT NULL," |
| 307 "last_updated INTEGER DEFAULT 0," |
| 308 "image_data BLOB," |
| 309 "width INTEGER DEFAULT 0," |
| 310 "height INTEGER DEFAULT 0)"); |
| 311 if (!db->Execute(sql.c_str())) |
| 312 return false; |
| 313 } |
| 314 return true; |
| 315 } |
| 316 |
| 317 bool ThumbnailDatabase::InitFaviconBitmapsIndex() { |
| 318 // Add an index on the icon_id column. |
| 319 return db_.Execute("CREATE INDEX IF NOT EXISTS favicon_bitmaps_icon_id ON " |
| 320 "favicon_bitmaps(icon_id)"); |
| 321 } |
| 322 |
241 void ThumbnailDatabase::BeginTransaction() { | 323 void ThumbnailDatabase::BeginTransaction() { |
242 db_.BeginTransaction(); | 324 db_.BeginTransaction(); |
243 } | 325 } |
244 | 326 |
245 void ThumbnailDatabase::CommitTransaction() { | 327 void ThumbnailDatabase::CommitTransaction() { |
246 db_.CommitTransaction(); | 328 db_.CommitTransaction(); |
247 } | 329 } |
248 | 330 |
249 void ThumbnailDatabase::RollbackTransaction() { | 331 void ThumbnailDatabase::RollbackTransaction() { |
250 db_.RollbackTransaction(); | 332 db_.RollbackTransaction(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 double current_boring_score = select_statement.ColumnDouble(0); | 440 double current_boring_score = select_statement.ColumnDouble(0); |
359 bool current_clipping = select_statement.ColumnBool(1); | 441 bool current_clipping = select_statement.ColumnBool(1); |
360 bool current_at_top = select_statement.ColumnBool(2); | 442 bool current_at_top = select_statement.ColumnBool(2); |
361 base::Time last_updated = | 443 base::Time last_updated = |
362 base::Time::FromTimeT(select_statement.ColumnInt64(3)); | 444 base::Time::FromTimeT(select_statement.ColumnInt64(3)); |
363 *score = ThumbnailScore(current_boring_score, current_clipping, | 445 *score = ThumbnailScore(current_boring_score, current_clipping, |
364 current_at_top, last_updated); | 446 current_at_top, last_updated); |
365 return true; | 447 return true; |
366 } | 448 } |
367 | 449 |
368 bool ThumbnailDatabase::SetFavicon( | 450 bool ThumbnailDatabase::GetFaviconBitmaps( |
369 URLID icon_id, | 451 FaviconID icon_id, |
370 scoped_refptr<base::RefCountedMemory> icon_data, | 452 std::vector<FaviconBitmap>* favicon_bitmaps) { |
371 base::Time time) { | |
372 DCHECK(icon_id); | 453 DCHECK(icon_id); |
373 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 454 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
374 "UPDATE favicons SET image_data=?, last_updated=? WHERE id=?")); | 455 "SELECT id, last_updated, image_data, width, height FROM favicon_bitmaps " |
| 456 "WHERE icon_id=?")); |
| 457 statement.BindInt64(0, icon_id); |
| 458 |
| 459 bool result = false; |
| 460 while (statement.Step()) { |
| 461 result = true; |
| 462 if (!favicon_bitmaps) |
| 463 return result; |
| 464 |
| 465 FaviconBitmap favicon_bitmap; |
| 466 favicon_bitmap.bitmap_id = statement.ColumnInt64(0); |
| 467 favicon_bitmap.icon_id = icon_id; |
| 468 favicon_bitmap.last_updated = |
| 469 base::Time::FromTimeT(statement.ColumnInt64(1)); |
| 470 if (statement.ColumnByteLength(2) > 0) { |
| 471 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); |
| 472 statement.ColumnBlobAsVector(2, &data->data()); |
| 473 favicon_bitmap.bitmap_data = data; |
| 474 } |
| 475 favicon_bitmap.pixel_size = gfx::Size(statement.ColumnInt(3), |
| 476 statement.ColumnInt(4)); |
| 477 favicon_bitmaps->push_back(favicon_bitmap); |
| 478 } |
| 479 return result; |
| 480 } |
| 481 |
| 482 FaviconBitmapID ThumbnailDatabase::AddFaviconBitmap( |
| 483 FaviconID icon_id, |
| 484 const scoped_refptr<base::RefCountedMemory>& icon_data, |
| 485 base::Time time, |
| 486 const gfx::Size& pixel_size) { |
| 487 DCHECK(icon_id); |
| 488 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
| 489 "INSERT INTO favicon_bitmaps (icon_id, image_data, last_updated, width, " |
| 490 "height) VALUES (?, ?, ?, ?, ?)")); |
| 491 statement.BindInt64(0, icon_id); |
375 if (icon_data->size()) { | 492 if (icon_data->size()) { |
376 statement.BindBlob(0, icon_data->front(), | 493 statement.BindBlob(1, icon_data->front(), |
377 static_cast<int>(icon_data->size())); | 494 static_cast<int>(icon_data->size())); |
378 } else { | 495 } else { |
379 statement.BindNull(0); | 496 statement.BindNull(1); |
380 } | 497 } |
381 statement.BindInt64(1, time.ToTimeT()); | 498 statement.BindInt64(2, time.ToTimeT()); |
382 statement.BindInt64(2, icon_id); | 499 statement.BindInt(3, pixel_size.width()); |
| 500 statement.BindInt(4, pixel_size.height()); |
| 501 |
| 502 if (!statement.Run()) |
| 503 return 0; |
| 504 return db_.GetLastInsertRowId(); |
| 505 } |
| 506 |
| 507 bool ThumbnailDatabase::DeleteFaviconBitmapsForFavicon(FaviconID icon_id) { |
| 508 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
| 509 "DELETE FROM favicon_bitmaps WHERE icon_id=?")); |
| 510 statement.BindInt64(0, icon_id); |
| 511 return statement.Run(); |
| 512 } |
| 513 |
| 514 bool ThumbnailDatabase::SetFaviconSizes(FaviconID icon_id, |
| 515 const std::string& sizes) { |
| 516 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
| 517 "UPDATE favicons SET sizes=? WHERE id=?")); |
| 518 statement.BindString(0, sizes); |
| 519 statement.BindInt64(1, icon_id); |
383 | 520 |
384 return statement.Run(); | 521 return statement.Run(); |
385 } | 522 } |
386 | 523 |
387 bool ThumbnailDatabase::SetFaviconLastUpdateTime(FaviconID icon_id, | 524 bool ThumbnailDatabase::SetFaviconOutOfDate(FaviconID icon_id) { |
388 base::Time time) { | |
389 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 525 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
390 "UPDATE favicons SET last_updated=? WHERE id=?")); | 526 "UPDATE favicon_bitmaps SET last_updated=? WHERE icon_id=?")); |
391 statement.BindInt64(0, time.ToTimeT()); | 527 statement.BindInt64(0, 0); |
392 statement.BindInt64(1, icon_id); | 528 statement.BindInt64(1, icon_id); |
393 | 529 |
394 return statement.Run(); | 530 return statement.Run(); |
395 } | 531 } |
396 | 532 |
397 FaviconID ThumbnailDatabase::GetFaviconIDForFaviconURL(const GURL& icon_url, | 533 FaviconID ThumbnailDatabase::GetFaviconIDForFaviconURL(const GURL& icon_url, |
398 int required_icon_type, | 534 int required_icon_type, |
399 IconType* icon_type) { | 535 IconType* icon_type) { |
400 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 536 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
401 "SELECT id, icon_type FROM favicons WHERE url=? AND (icon_type & ? > 0) " | 537 "SELECT id, icon_type FROM favicons WHERE url=? AND (icon_type & ? > 0) " |
402 "ORDER BY icon_type DESC")); | 538 "ORDER BY icon_type DESC")); |
403 statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url)); | 539 statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url)); |
404 statement.BindInt(1, required_icon_type); | 540 statement.BindInt(1, required_icon_type); |
405 | 541 |
406 if (!statement.Step()) | 542 if (!statement.Step()) |
407 return 0; // not cached | 543 return 0; // not cached |
408 | 544 |
409 if (icon_type) | 545 if (icon_type) |
410 *icon_type = static_cast<IconType>(statement.ColumnInt(1)); | 546 *icon_type = static_cast<IconType>(statement.ColumnInt(1)); |
411 return statement.ColumnInt64(0); | 547 return statement.ColumnInt64(0); |
412 } | 548 } |
413 | 549 |
414 bool ThumbnailDatabase::GetFavicon( | 550 bool ThumbnailDatabase::GetFavicon( |
415 FaviconID icon_id, | 551 FaviconID icon_id, |
416 base::Time* last_updated, | 552 base::Time* last_updated, |
417 std::vector<unsigned char>* png_icon_data, | 553 scoped_refptr<base::RefCountedMemory>* png_icon_data, |
418 GURL* icon_url, | 554 GURL* icon_url, |
419 IconType* icon_type) { | 555 IconType* icon_type) { |
420 DCHECK(icon_id); | 556 DCHECK(icon_id); |
421 | 557 |
| 558 std::vector<FaviconBitmap> favicon_bitmaps; |
| 559 if (!GetFaviconBitmaps(icon_id, &favicon_bitmaps)) |
| 560 return false; |
| 561 |
| 562 if (favicon_bitmaps.empty()) |
| 563 return false; |
| 564 |
| 565 if (last_updated) |
| 566 *last_updated = favicon_bitmaps[0].last_updated; |
| 567 |
| 568 *png_icon_data = favicon_bitmaps[0].bitmap_data; |
| 569 |
| 570 return GetFaviconHeader(icon_id, icon_url, icon_type, NULL); |
| 571 } |
| 572 |
| 573 bool ThumbnailDatabase::GetFaviconHeader( |
| 574 FaviconID icon_id, |
| 575 GURL* icon_url, |
| 576 IconType* icon_type, |
| 577 std::string* sizes) { |
| 578 DCHECK(icon_id); |
| 579 |
422 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 580 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
423 "SELECT last_updated, image_data, url, icon_type " | 581 "SELECT url, icon_type, sizes FROM favicons WHERE id=?")); |
424 "FROM favicons WHERE id=?")); | |
425 statement.BindInt64(0, icon_id); | 582 statement.BindInt64(0, icon_id); |
426 | 583 |
427 if (!statement.Step()) | 584 if (!statement.Step()) |
428 return false; // No entry for the id. | 585 return false; // No entry for the id. |
429 | 586 |
430 if (last_updated) | |
431 *last_updated = base::Time::FromTimeT(statement.ColumnInt64(0)); | |
432 if (statement.ColumnByteLength(1) > 0) | |
433 statement.ColumnBlobAsVector(1, png_icon_data); | |
434 if (icon_url) | 587 if (icon_url) |
435 *icon_url = GURL(statement.ColumnString(2)); | 588 *icon_url = GURL(statement.ColumnString(0)); |
436 if (icon_type) | 589 if (icon_type) |
437 *icon_type = static_cast<history::IconType>(statement.ColumnInt(3)); | 590 *icon_type = static_cast<history::IconType>(statement.ColumnInt(1)); |
| 591 if (sizes) |
| 592 *sizes = statement.ColumnString(2); |
438 | 593 |
439 return true; | 594 return true; |
440 } | 595 } |
441 | 596 |
442 FaviconID ThumbnailDatabase::AddFavicon(const GURL& icon_url, | 597 FaviconID ThumbnailDatabase::AddFavicon(const GURL& icon_url, |
443 IconType icon_type) { | 598 IconType icon_type) { |
444 | 599 |
445 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 600 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
446 "INSERT INTO favicons (url, icon_type) VALUES (?, ?)")); | 601 "INSERT INTO favicons (url, icon_type) VALUES (?, ?)")); |
447 statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url)); | 602 statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url)); |
448 statement.BindInt(1, icon_type); | 603 statement.BindInt(1, icon_type); |
449 | 604 |
450 if (!statement.Run()) | 605 if (!statement.Run()) |
451 return 0; | 606 return 0; |
452 return db_.GetLastInsertRowId(); | 607 return db_.GetLastInsertRowId(); |
453 } | 608 } |
454 | 609 |
| 610 FaviconID ThumbnailDatabase::AddFavicon( |
| 611 const GURL& icon_url, |
| 612 IconType icon_type, |
| 613 const std::string& sizes, |
| 614 const scoped_refptr<base::RefCountedMemory>& icon_data, |
| 615 base::Time time, |
| 616 const gfx::Size& pixel_size) { |
| 617 FaviconID icon_id = AddFavicon(icon_url, icon_type); |
| 618 if (!icon_id || |
| 619 !SetFaviconSizes(icon_id, sizes) || |
| 620 !AddFaviconBitmap(icon_id, icon_data, time, pixel_size)) { |
| 621 return 0; |
| 622 } |
| 623 return icon_id; |
| 624 } |
| 625 |
455 bool ThumbnailDatabase::DeleteFavicon(FaviconID id) { | 626 bool ThumbnailDatabase::DeleteFavicon(FaviconID id) { |
456 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 627 sql::Statement statement; |
| 628 statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE, |
457 "DELETE FROM favicons WHERE id = ?")); | 629 "DELETE FROM favicons WHERE id = ?")); |
458 statement.BindInt64(0, id); | 630 statement.BindInt64(0, id); |
| 631 if (!statement.Run()) |
| 632 return false; |
459 | 633 |
| 634 statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE, |
| 635 "DELETE FROM favicon_bitmaps WHERE icon_id = ?")); |
| 636 statement.BindInt64(0, id); |
460 return statement.Run(); | 637 return statement.Run(); |
461 } | 638 } |
462 | 639 |
463 bool ThumbnailDatabase::GetIconMappingForPageURL(const GURL& page_url, | 640 bool ThumbnailDatabase::GetIconMappingForPageURL(const GURL& page_url, |
464 IconType required_icon_type, | 641 IconType required_icon_type, |
465 IconMapping* icon_mapping) { | 642 IconMapping* icon_mapping) { |
466 std::vector<IconMapping> icon_mappings; | 643 std::vector<IconMapping> icon_mappings; |
467 if (!GetIconMappingsForPageURL(page_url, &icon_mappings)) | 644 if (!GetIconMappingsForPageURL(page_url, &icon_mappings)) |
468 return false; | 645 return false; |
469 | 646 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 | 758 |
582 IconMapping info; | 759 IconMapping info; |
583 while (e.GetNextIconMapping(&info)) { | 760 while (e.GetNextIconMapping(&info)) { |
584 // TODO: Using bulk insert to improve the performance. | 761 // TODO: Using bulk insert to improve the performance. |
585 if (!AddIconMapping(info.page_url, info.icon_id)) | 762 if (!AddIconMapping(info.page_url, info.icon_id)) |
586 return false; | 763 return false; |
587 } | 764 } |
588 return true; | 765 return true; |
589 } | 766 } |
590 | 767 |
| 768 bool ThumbnailDatabase::InitTemporaryTables() { |
| 769 return InitIconMappingTable(&db_, true) && |
| 770 InitFaviconsTable(&db_, true) && |
| 771 InitFaviconBitmapsTable(&db_, true); |
| 772 } |
| 773 |
| 774 bool ThumbnailDatabase::CommitTemporaryTables() { |
| 775 const char* main_tables[] = { "icon_mapping", |
| 776 "favicons", |
| 777 "favicon_bitmaps" }; |
| 778 const char* temporary_tables[] = { "temp_icon_mapping", |
| 779 "temp_favicons", |
| 780 "temp_favicon_bitmaps" }; |
| 781 DCHECK_EQ(arraysize(main_tables), arraysize(temporary_tables)); |
| 782 |
| 783 for (size_t i = 0; i < arraysize(main_tables); ++i) { |
| 784 // Delete the main table. |
| 785 std::string sql; |
| 786 sql.append("DROP TABLE "); |
| 787 sql.append(main_tables[i]); |
| 788 if (!db_.Execute(sql.c_str())) |
| 789 return false; |
| 790 |
| 791 // Rename the temporary table. |
| 792 sql.clear(); |
| 793 sql.append("ALTER TABLE "); |
| 794 sql.append(temporary_tables[i]); |
| 795 sql.append(" RENAME TO "); |
| 796 sql.append(main_tables[i]); |
| 797 if (!db_.Execute(sql.c_str())) |
| 798 return false; |
| 799 } |
| 800 |
| 801 // The renamed tables needs indices (the temporary tables don't have any). |
| 802 return InitIconMappingIndex() && |
| 803 InitFaviconsIndex() && |
| 804 InitFaviconBitmapsIndex(); |
| 805 } |
| 806 |
591 IconMappingID ThumbnailDatabase::AddToTemporaryIconMappingTable( | 807 IconMappingID ThumbnailDatabase::AddToTemporaryIconMappingTable( |
592 const GURL& page_url, const FaviconID icon_id) { | 808 const GURL& page_url, const FaviconID icon_id) { |
593 return AddIconMapping(page_url, icon_id, true); | 809 return AddIconMapping(page_url, icon_id, true); |
594 } | 810 } |
595 | 811 |
596 bool ThumbnailDatabase::CommitTemporaryIconMappingTable() { | 812 FaviconID ThumbnailDatabase::CopyFaviconAndFaviconBitmapsToTemporaryTables( |
597 // Delete the old icon_mapping table. | 813 FaviconID source) { |
598 if (!db_.Execute("DROP TABLE icon_mapping")) | 814 sql::Statement statement; |
599 return false; | 815 statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE, |
600 | 816 "INSERT INTO temp_favicons (url, icon_type, sizes) " |
601 // Rename the temporary one. | 817 "SELECT url, icon_type, sizes FROM favicons WHERE id = ?")); |
602 if (!db_.Execute("ALTER TABLE temp_icon_mapping RENAME TO icon_mapping")) | |
603 return false; | |
604 | |
605 // The renamed table needs the index (the temporary table doesn't have one). | |
606 return InitIconMappingIndex(); | |
607 } | |
608 | |
609 FaviconID ThumbnailDatabase::CopyToTemporaryFaviconTable(FaviconID source) { | |
610 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | |
611 "INSERT INTO temp_favicons (url, last_updated, image_data, icon_type)" | |
612 "SELECT url, last_updated, image_data, icon_type " | |
613 "FROM favicons WHERE id = ?")); | |
614 statement.BindInt64(0, source); | 818 statement.BindInt64(0, source); |
615 | 819 |
616 if (!statement.Run()) | 820 if (!statement.Run()) |
617 return 0; | 821 return 0; |
618 | 822 |
619 // We return the ID of the newly inserted favicon. | 823 FaviconID new_favicon_id = db_.GetLastInsertRowId(); |
620 return db_.GetLastInsertRowId(); | |
621 } | |
622 | 824 |
623 bool ThumbnailDatabase::CommitTemporaryFaviconTable() { | 825 statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE, |
624 // Delete the old favicons table. | 826 "INSERT INTO temp_favicon_bitmaps (icon_id, last_updated, image_data, " |
625 if (!db_.Execute("DROP TABLE favicons")) | 827 "width, height) " |
626 return false; | 828 "SELECT ?, last_updated, image_data, width, height " |
| 829 "FROM favicon_bitmaps WHERE icon_id = ?")); |
| 830 statement.BindInt64(0, new_favicon_id); |
| 831 statement.BindInt64(1, source); |
| 832 if (!statement.Run()) |
| 833 return 0; |
627 | 834 |
628 // Rename the temporary one. | 835 return new_favicon_id; |
629 if (!db_.Execute("ALTER TABLE temp_favicons RENAME TO favicons")) | |
630 return false; | |
631 | |
632 // The renamed table needs the index (the temporary table doesn't have one). | |
633 return InitFaviconsIndex(); | |
634 } | 836 } |
635 | 837 |
636 bool ThumbnailDatabase::NeedsMigrationToTopSites() { | 838 bool ThumbnailDatabase::NeedsMigrationToTopSites() { |
637 return !use_top_sites_; | 839 return !use_top_sites_; |
638 } | 840 } |
639 | 841 |
640 bool ThumbnailDatabase::RenameAndDropThumbnails(const FilePath& old_db_file, | 842 bool ThumbnailDatabase::RenameAndDropThumbnails(const FilePath& old_db_file, |
641 const FilePath& new_db_file) { | 843 const FilePath& new_db_file) { |
642 // Init favicons table - same schema as the thumbnails. | 844 // Init favicons tables - same schema as the thumbnails. |
643 sql::Connection favicons; | 845 sql::Connection favicons; |
644 if (OpenDatabase(&favicons, new_db_file) != sql::INIT_OK) | 846 if (OpenDatabase(&favicons, new_db_file) != sql::INIT_OK) |
645 return false; | 847 return false; |
646 | 848 |
647 if (!InitFaviconsTable(&favicons, false) || | 849 if (!InitFaviconBitmapsTable(&favicons, false) || |
| 850 !InitFaviconsTable(&favicons, false) || |
648 !InitIconMappingTable(&favicons, false)) { | 851 !InitIconMappingTable(&favicons, false)) { |
649 favicons.Close(); | 852 favicons.Close(); |
650 return false; | 853 return false; |
651 } | 854 } |
652 favicons.Close(); | 855 favicons.Close(); |
653 | 856 |
654 // Can't attach within a transaction. | 857 // Can't attach within a transaction. |
655 if (transaction_nesting()) | 858 if (transaction_nesting()) |
656 CommitTransaction(); | 859 CommitTransaction(); |
657 | 860 |
(...skipping 13 matching lines...) Expand all Loading... |
671 #else | 874 #else |
672 attach.BindString(0, WideToUTF8(new_db_file.value())); | 875 attach.BindString(0, WideToUTF8(new_db_file.value())); |
673 #endif | 876 #endif |
674 | 877 |
675 if (!attach.Run()) { | 878 if (!attach.Run()) { |
676 BeginTransaction(); | 879 BeginTransaction(); |
677 return false; | 880 return false; |
678 } | 881 } |
679 } | 882 } |
680 | 883 |
681 // Move favicons to the new DB. | 884 // Move favicons and favicon_bitmaps to new DB. |
682 if (!db_.Execute("INSERT OR REPLACE INTO new_favicons.favicons " | 885 bool successfully_moved_data = |
683 "SELECT * FROM favicons")) { | 886 db_.Execute("INSERT OR REPLACE INTO new_favicons.favicon_bitmaps " |
684 DLOG(FATAL) << "Unable to copy favicons."; | 887 "SELECT * FROM favicon_bitmaps") && |
| 888 db_.Execute("INSERT OR REPLACE INTO new_favicons.favicons " |
| 889 "SELECT * FROM favicons"); |
| 890 if (!successfully_moved_data) { |
| 891 DLOG(FATAL) << "Unable to copy favicons and favicon_bitmaps."; |
685 BeginTransaction(); | 892 BeginTransaction(); |
686 return false; | 893 return false; |
687 } | 894 } |
688 | 895 |
689 if (!db_.Execute("DETACH new_favicons")) { | 896 if (!db_.Execute("DETACH new_favicons")) { |
690 DLOG(FATAL) << "Unable to detach database."; | 897 DLOG(FATAL) << "Unable to detach database."; |
691 BeginTransaction(); | 898 BeginTransaction(); |
692 return false; | 899 return false; |
693 } | 900 } |
694 | 901 |
695 db_.Close(); | 902 db_.Close(); |
696 | 903 |
697 // Reset the DB to point to new file. | 904 // Reset the DB to point to new file. |
698 if (OpenDatabase(&db_, new_db_file) != sql::INIT_OK) | 905 if (OpenDatabase(&db_, new_db_file) != sql::INIT_OK) |
699 return false; | 906 return false; |
700 | 907 |
701 file_util::Delete(old_db_file, false); | 908 file_util::Delete(old_db_file, false); |
702 | 909 |
703 meta_table_.Reset(); | 910 meta_table_.Reset(); |
704 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) | 911 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) |
705 return false; | 912 return false; |
706 | 913 |
707 if (!InitFaviconsIndex()) | 914 if (!InitFaviconBitmapsIndex() || !InitFaviconsIndex()) |
708 return false; | 915 return false; |
709 | 916 |
710 // Reopen the transaction. | 917 // Reopen the transaction. |
711 BeginTransaction(); | 918 BeginTransaction(); |
712 use_top_sites_ = true; | 919 use_top_sites_ = true; |
713 return true; | 920 return true; |
714 } | 921 } |
715 | 922 |
716 bool ThumbnailDatabase::InitIconMappingTable(sql::Connection* db, | 923 bool ThumbnailDatabase::InitIconMappingTable(sql::Connection* db, |
717 bool is_temporary) { | 924 bool is_temporary) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 | 986 |
780 bool ThumbnailDatabase::UpgradeToVersion5() { | 987 bool ThumbnailDatabase::UpgradeToVersion5() { |
781 if (!db_.Execute("ALTER TABLE favicons ADD sizes LONGVARCHAR")) { | 988 if (!db_.Execute("ALTER TABLE favicons ADD sizes LONGVARCHAR")) { |
782 return false; | 989 return false; |
783 } | 990 } |
784 meta_table_.SetVersionNumber(5); | 991 meta_table_.SetVersionNumber(5); |
785 meta_table_.SetCompatibleVersionNumber(std::min(5, kCompatibleVersionNumber)); | 992 meta_table_.SetCompatibleVersionNumber(std::min(5, kCompatibleVersionNumber)); |
786 return true; | 993 return true; |
787 } | 994 } |
788 | 995 |
| 996 bool ThumbnailDatabase::UpgradeToVersion6() { |
| 997 bool success = |
| 998 db_.Execute("INSERT INTO favicon_bitmaps (icon_id, last_updated, " |
| 999 "image_data, width, height)" |
| 1000 "SELECT id, last_updated, image_data, 0, 0 FROM favicons") && |
| 1001 db_.Execute("CREATE TABLE temp_favicons (" |
| 1002 "id INTEGER PRIMARY KEY," |
| 1003 "url LONGVARCHAR NOT NULL," |
| 1004 "icon_type INTEGER DEFAULT 1," |
| 1005 // Set the default icon_type as FAVICON to be consistent with |
| 1006 // table upgrade in UpgradeToVersion4(). |
| 1007 "sizes LONGVARCHAR)") && |
| 1008 db_.Execute("INSERT INTO temp_favicons (id, url, icon_type) " |
| 1009 "SELECT id, url, icon_type FROM favicons") && |
| 1010 db_.Execute("DROP TABLE favicons") && |
| 1011 db_.Execute("ALTER TABLE temp_favicons RENAME TO favicons"); |
| 1012 if (!success) |
| 1013 return false; |
| 1014 |
| 1015 meta_table_.SetVersionNumber(6); |
| 1016 meta_table_.SetCompatibleVersionNumber(std::min(6, kCompatibleVersionNumber)); |
| 1017 return true; |
| 1018 } |
| 1019 |
789 } // namespace history | 1020 } // namespace history |
OLD | NEW |