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

Side by Side Diff: chrome/browser/history/thumbnail_database.cc

Issue 10815068: Changes favicon database to support storing bitmaps of different sizes for the same icon_url (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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 (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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/history/thumbnail_database.h ('k') | chrome/browser/history/thumbnail_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698