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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/history/thumbnail_database.cc
diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc
index 0397f961e3859bec530897d2e8c13f3bcc8d212f..d9462ada00ae4b5b1ce8bef8a5a18c56d1f07aeb 100644
--- a/chrome/browser/history/thumbnail_database.cc
+++ b/chrome/browser/history/thumbnail_database.cc
@@ -26,6 +26,53 @@
#include "base/mac/mac_util.h"
#endif
+// Description of database tables:
+//
+// icon_mapping
+// id Unique ID.
+// page_url Page URL which has one or more associated favicons.
+// icon_id The ID of favicon that this mapping maps to.
+//
+// favicons This table associates a row to each favicon for a
+// |page_url| in the |icon_mapping| table. This is the
+// default favicon |page_url|/favicon.ico plus any favicons
+// associated via <link rel="icon_type" href="url">.
+// The |id| matches the |icon_id| field in the appropriate
+// row in the icon_mapping table.
+//
+// id Unique ID.
+// url The URL at which the favicon file is located.
+// icon_type The type of the favicon specified in the rel attribute of
+// the link tag. The FAVICON type is used for the default
+// favicon.ico favicon.
+// sizes Sizes is a listing of all the sizes at which the favicon
+// at |url| is available from the web. Note that this may
+// include sizes for which a bitmap is not stored in the
+// favicon_bitmaps table. Each widthxheight pair is
+// separated by a space. Width and height are separated by
+// a space as well. For instance, if |icon_id| represents a
+// .ico file containing 16x16 and 32x32 bitmaps, |sizes|
+// would be "16 16 32 32".
+//
+// favicon_bitmaps This table contains the PNG encoded bitmap data of the
+// favicons. There is a separate row for every size in a
+// multi resolution bitmap. The bitmap data is associated
+// to the favicon via the |icon_id| field which matches
+// the |id| field in the appropriate row in the |favicons|
+// table. There is not necessarily a row for each size
+// specified in the sizes attribute.
+//
+// id Unique ID.
+// icon_id The ID of the favicon that the bitmap is associated to.
+// last_updated The time at which this favicon was inserted into the
+// table. This is used to determine if it needs to be
+// redownloaded from the web.
+// image_data PNG encoded data of the favicon.
+// width Pixel width of |image_data|.
+// height Pixel height of |image_data|.
+
+
+
static void FillIconMapping(const sql::Statement& statement,
const GURL& page_url,
history::IconMapping* icon_mapping) {
@@ -39,8 +86,8 @@ static void FillIconMapping(const sql::Statement& statement,
namespace history {
// Version number of the database.
-static const int kCurrentVersionNumber = 5;
-static const int kCompatibleVersionNumber = 5;
+static const int kCurrentVersionNumber = 6;
+static const int kCompatibleVersionNumber = 6;
// Use 90 quality (out of 100) which is pretty high, because we're very
// sensitive to artifacts for these small sized, highly detailed images.
@@ -66,7 +113,7 @@ ThumbnailDatabase::ThumbnailDatabase()
}
sql::InitStatus ThumbnailDatabase::CantUpgradeToVersion(int cur_version) {
- LOG(WARNING) << "Unable to update to thumbnail database to version 4" <<
+ LOG(WARNING) << "Unable to update to thumbnail database to version " <<
cur_version << ".";
db_.Close();
return sql::INIT_FAILURE;
@@ -98,6 +145,8 @@ sql::InitStatus ThumbnailDatabase::Init(
if (!meta_table_.Init(&db_, kCurrentVersionNumber,
kCompatibleVersionNumber) ||
!InitThumbnailTable() ||
+ !InitFaviconBitmapsTable(&db_, false) ||
+ !InitFaviconBitmapsIndex() ||
!InitFaviconsTable(&db_, false) ||
!InitFaviconsIndex() ||
!InitIconMappingTable(&db_, false) ||
@@ -127,10 +176,17 @@ sql::InitStatus ThumbnailDatabase::Init(
}
if (cur_version == 4) {
+ ++cur_version;
if (!UpgradeToVersion5())
return CantUpgradeToVersion(cur_version);
}
+ if (cur_version == 5) {
+ ++cur_version;
+ if (!UpgradeToVersion6())
+ return CantUpgradeToVersion(cur_version);
+ }
+
LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
"Thumbnail database version " << cur_version << " is too old to handle.";
@@ -211,7 +267,7 @@ bool ThumbnailDatabase::RecreateThumbnailTable() {
bool ThumbnailDatabase::InitFaviconsTable(sql::Connection* db,
bool is_temporary) {
// Note: if you update the schema, don't forget to update
- // CopyToTemporaryFaviconTable as well.
+ // CopyFaviconAndFaviconBitmapsToTemporaryTables as well.
const char* name = is_temporary ? "temp_favicons" : "favicons";
if (!db->DoesTableExist(name)) {
std::string sql;
@@ -220,8 +276,6 @@ bool ThumbnailDatabase::InitFaviconsTable(sql::Connection* db,
sql.append("("
"id INTEGER PRIMARY KEY,"
"url LONGVARCHAR NOT NULL,"
- "last_updated INTEGER DEFAULT 0,"
- "image_data BLOB,"
// Set the default icon_type as FAVICON to be consistent with
// table upgrade in UpgradeToVersion4().
"icon_type INTEGER DEFAULT 1,"
@@ -238,6 +292,34 @@ bool ThumbnailDatabase::InitFaviconsIndex() {
db_.Execute("CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)");
}
+bool ThumbnailDatabase::InitFaviconBitmapsTable(sql::Connection* db,
+ bool is_temporary) {
+ // Note: if you update the schema, don't forget to update
+ // CopyFaviconAndFaviconBitmapsToTemporaryTables as well.
+ const char* name = is_temporary ? "temp_favicon_bitmaps" : "favicon_bitmaps";
+ if (!db->DoesTableExist(name)) {
+ std::string sql;
+ sql.append("CREATE TABLE ");
+ sql.append(name);
+ sql.append("("
+ "id INTEGER PRIMARY KEY,"
+ "icon_id INTEGER NOT NULL,"
+ "last_updated INTEGER DEFAULT 0,"
+ "image_data BLOB,"
+ "width INTEGER DEFAULT 0,"
+ "height INTEGER DEFAULT 0)");
+ if (!db->Execute(sql.c_str()))
+ return false;
+ }
+ return true;
+}
+
+bool ThumbnailDatabase::InitFaviconBitmapsIndex() {
+ // Add an index on the icon_id column.
+ return db_.Execute("CREATE INDEX IF NOT EXISTS favicon_bitmaps_icon_id ON "
+ "favicon_bitmaps(icon_id)");
+}
+
void ThumbnailDatabase::BeginTransaction() {
db_.BeginTransaction();
}
@@ -365,30 +447,84 @@ bool ThumbnailDatabase::ThumbnailScoreForId(URLID id,
return true;
}
-bool ThumbnailDatabase::SetFavicon(
- URLID icon_id,
- scoped_refptr<base::RefCountedMemory> icon_data,
- base::Time time) {
+bool ThumbnailDatabase::GetFaviconBitmaps(
+ FaviconID icon_id,
+ std::vector<FaviconBitmap>* favicon_bitmaps) {
+ DCHECK(icon_id);
+ sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
+ "SELECT id, last_updated, image_data, width, height FROM favicon_bitmaps "
+ "WHERE icon_id=?"));
+ statement.BindInt64(0, icon_id);
+
+ bool result = false;
+ while (statement.Step()) {
+ result = true;
+ if (!favicon_bitmaps)
+ return result;
+
+ FaviconBitmap favicon_bitmap;
+ favicon_bitmap.bitmap_id = statement.ColumnInt64(0);
+ favicon_bitmap.icon_id = icon_id;
+ favicon_bitmap.last_updated =
+ base::Time::FromTimeT(statement.ColumnInt64(1));
+ if (statement.ColumnByteLength(2) > 0) {
+ scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
+ statement.ColumnBlobAsVector(2, &data->data());
+ favicon_bitmap.bitmap_data = data;
+ }
+ favicon_bitmap.pixel_size = gfx::Size(statement.ColumnInt(3),
+ statement.ColumnInt(4));
+ favicon_bitmaps->push_back(favicon_bitmap);
+ }
+ return result;
+}
+
+FaviconBitmapID ThumbnailDatabase::AddFaviconBitmap(
+ FaviconID icon_id,
+ const scoped_refptr<base::RefCountedMemory>& icon_data,
+ base::Time time,
+ const gfx::Size& pixel_size) {
DCHECK(icon_id);
sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
- "UPDATE favicons SET image_data=?, last_updated=? WHERE id=?"));
+ "INSERT INTO favicon_bitmaps (icon_id, image_data, last_updated, width, "
+ "height) VALUES (?, ?, ?, ?, ?)"));
+ statement.BindInt64(0, icon_id);
if (icon_data->size()) {
- statement.BindBlob(0, icon_data->front(),
+ statement.BindBlob(1, icon_data->front(),
static_cast<int>(icon_data->size()));
} else {
- statement.BindNull(0);
+ statement.BindNull(1);
}
- statement.BindInt64(1, time.ToTimeT());
- statement.BindInt64(2, icon_id);
+ statement.BindInt64(2, time.ToTimeT());
+ statement.BindInt(3, pixel_size.width());
+ statement.BindInt(4, pixel_size.height());
+
+ if (!statement.Run())
+ return 0;
+ return db_.GetLastInsertRowId();
+}
+
+bool ThumbnailDatabase::DeleteFaviconBitmapsForFavicon(FaviconID icon_id) {
+ sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
+ "DELETE FROM favicon_bitmaps WHERE icon_id=?"));
+ statement.BindInt64(0, icon_id);
+ return statement.Run();
+}
+
+bool ThumbnailDatabase::SetFaviconSizes(FaviconID icon_id,
+ const std::string& sizes) {
+ sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE favicons SET sizes=? WHERE id=?"));
+ statement.BindString(0, sizes);
+ statement.BindInt64(1, icon_id);
return statement.Run();
}
-bool ThumbnailDatabase::SetFaviconLastUpdateTime(FaviconID icon_id,
- base::Time time) {
+bool ThumbnailDatabase::SetFaviconOutOfDate(FaviconID icon_id) {
sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
- "UPDATE favicons SET last_updated=? WHERE id=?"));
- statement.BindInt64(0, time.ToTimeT());
+ "UPDATE favicon_bitmaps SET last_updated=? WHERE icon_id=?"));
+ statement.BindInt64(0, 0);
statement.BindInt64(1, icon_id);
return statement.Run();
@@ -414,27 +550,46 @@ FaviconID ThumbnailDatabase::GetFaviconIDForFaviconURL(const GURL& icon_url,
bool ThumbnailDatabase::GetFavicon(
FaviconID icon_id,
base::Time* last_updated,
- std::vector<unsigned char>* png_icon_data,
+ scoped_refptr<base::RefCountedMemory>* png_icon_data,
GURL* icon_url,
IconType* icon_type) {
DCHECK(icon_id);
+ std::vector<FaviconBitmap> favicon_bitmaps;
+ if (!GetFaviconBitmaps(icon_id, &favicon_bitmaps))
+ return false;
+
+ if (favicon_bitmaps.empty())
+ return false;
+
+ if (last_updated)
+ *last_updated = favicon_bitmaps[0].last_updated;
+
+ *png_icon_data = favicon_bitmaps[0].bitmap_data;
+
+ return GetFaviconHeader(icon_id, icon_url, icon_type, NULL);
+}
+
+bool ThumbnailDatabase::GetFaviconHeader(
+ FaviconID icon_id,
+ GURL* icon_url,
+ IconType* icon_type,
+ std::string* sizes) {
+ DCHECK(icon_id);
+
sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
- "SELECT last_updated, image_data, url, icon_type "
- "FROM favicons WHERE id=?"));
+ "SELECT url, icon_type, sizes FROM favicons WHERE id=?"));
statement.BindInt64(0, icon_id);
if (!statement.Step())
return false; // No entry for the id.
- if (last_updated)
- *last_updated = base::Time::FromTimeT(statement.ColumnInt64(0));
- if (statement.ColumnByteLength(1) > 0)
- statement.ColumnBlobAsVector(1, png_icon_data);
if (icon_url)
- *icon_url = GURL(statement.ColumnString(2));
+ *icon_url = GURL(statement.ColumnString(0));
if (icon_type)
- *icon_type = static_cast<history::IconType>(statement.ColumnInt(3));
+ *icon_type = static_cast<history::IconType>(statement.ColumnInt(1));
+ if (sizes)
+ *sizes = statement.ColumnString(2);
return true;
}
@@ -452,11 +607,33 @@ FaviconID ThumbnailDatabase::AddFavicon(const GURL& icon_url,
return db_.GetLastInsertRowId();
}
+FaviconID ThumbnailDatabase::AddFavicon(
+ const GURL& icon_url,
+ IconType icon_type,
+ const std::string& sizes,
+ const scoped_refptr<base::RefCountedMemory>& icon_data,
+ base::Time time,
+ const gfx::Size& pixel_size) {
+ FaviconID icon_id = AddFavicon(icon_url, icon_type);
+ if (!icon_id ||
+ !SetFaviconSizes(icon_id, sizes) ||
+ !AddFaviconBitmap(icon_id, icon_data, time, pixel_size)) {
+ return 0;
+ }
+ return icon_id;
+}
+
bool ThumbnailDatabase::DeleteFavicon(FaviconID id) {
- sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
+ sql::Statement statement;
+ statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE,
"DELETE FROM favicons WHERE id = ?"));
statement.BindInt64(0, id);
+ if (!statement.Run())
+ return false;
+ statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE,
+ "DELETE FROM favicon_bitmaps WHERE icon_id = ?"));
+ statement.BindInt64(0, id);
return statement.Run();
}
@@ -588,49 +765,74 @@ bool ThumbnailDatabase::MigrateIconMappingData(URLDatabase* url_db) {
return true;
}
-IconMappingID ThumbnailDatabase::AddToTemporaryIconMappingTable(
- const GURL& page_url, const FaviconID icon_id) {
- return AddIconMapping(page_url, icon_id, true);
+bool ThumbnailDatabase::InitTemporaryTables() {
+ return InitIconMappingTable(&db_, true) &&
+ InitFaviconsTable(&db_, true) &&
+ InitFaviconBitmapsTable(&db_, true);
}
-bool ThumbnailDatabase::CommitTemporaryIconMappingTable() {
- // Delete the old icon_mapping table.
- if (!db_.Execute("DROP TABLE icon_mapping"))
- return false;
+bool ThumbnailDatabase::CommitTemporaryTables() {
+ const char* main_tables[] = { "icon_mapping",
+ "favicons",
+ "favicon_bitmaps" };
+ const char* temporary_tables[] = { "temp_icon_mapping",
+ "temp_favicons",
+ "temp_favicon_bitmaps" };
+ DCHECK_EQ(arraysize(main_tables), arraysize(temporary_tables));
- // Rename the temporary one.
- if (!db_.Execute("ALTER TABLE temp_icon_mapping RENAME TO icon_mapping"))
- return false;
+ for (size_t i = 0; i < arraysize(main_tables); ++i) {
+ // Delete the main table.
+ std::string sql;
+ sql.append("DROP TABLE ");
+ sql.append(main_tables[i]);
+ if (!db_.Execute(sql.c_str()))
+ return false;
+
+ // Rename the temporary table.
+ sql.clear();
+ sql.append("ALTER TABLE ");
+ sql.append(temporary_tables[i]);
+ sql.append(" RENAME TO ");
+ sql.append(main_tables[i]);
+ if (!db_.Execute(sql.c_str()))
+ return false;
+ }
- // The renamed table needs the index (the temporary table doesn't have one).
- return InitIconMappingIndex();
+ // The renamed tables needs indices (the temporary tables don't have any).
+ return InitIconMappingIndex() &&
+ InitFaviconsIndex() &&
+ InitFaviconBitmapsIndex();
}
-FaviconID ThumbnailDatabase::CopyToTemporaryFaviconTable(FaviconID source) {
- sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
- "INSERT INTO temp_favicons (url, last_updated, image_data, icon_type)"
- "SELECT url, last_updated, image_data, icon_type "
- "FROM favicons WHERE id = ?"));
+IconMappingID ThumbnailDatabase::AddToTemporaryIconMappingTable(
+ const GURL& page_url, const FaviconID icon_id) {
+ return AddIconMapping(page_url, icon_id, true);
+}
+
+FaviconID ThumbnailDatabase::CopyFaviconAndFaviconBitmapsToTemporaryTables(
+ FaviconID source) {
+ sql::Statement statement;
+ statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE,
+ "INSERT INTO temp_favicons (url, icon_type, sizes) "
+ "SELECT url, icon_type, sizes FROM favicons WHERE id = ?"));
statement.BindInt64(0, source);
if (!statement.Run())
return 0;
- // We return the ID of the newly inserted favicon.
- return db_.GetLastInsertRowId();
-}
+ FaviconID new_favicon_id = db_.GetLastInsertRowId();
-bool ThumbnailDatabase::CommitTemporaryFaviconTable() {
- // Delete the old favicons table.
- if (!db_.Execute("DROP TABLE favicons"))
- return false;
-
- // Rename the temporary one.
- if (!db_.Execute("ALTER TABLE temp_favicons RENAME TO favicons"))
- return false;
+ statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE,
+ "INSERT INTO temp_favicon_bitmaps (icon_id, last_updated, image_data, "
+ "width, height) "
+ "SELECT ?, last_updated, image_data, width, height "
+ "FROM favicon_bitmaps WHERE icon_id = ?"));
+ statement.BindInt64(0, new_favicon_id);
+ statement.BindInt64(1, source);
+ if (!statement.Run())
+ return 0;
- // The renamed table needs the index (the temporary table doesn't have one).
- return InitFaviconsIndex();
+ return new_favicon_id;
}
bool ThumbnailDatabase::NeedsMigrationToTopSites() {
@@ -639,12 +841,13 @@ bool ThumbnailDatabase::NeedsMigrationToTopSites() {
bool ThumbnailDatabase::RenameAndDropThumbnails(const FilePath& old_db_file,
const FilePath& new_db_file) {
- // Init favicons table - same schema as the thumbnails.
+ // Init favicons tables - same schema as the thumbnails.
sql::Connection favicons;
if (OpenDatabase(&favicons, new_db_file) != sql::INIT_OK)
return false;
- if (!InitFaviconsTable(&favicons, false) ||
+ if (!InitFaviconBitmapsTable(&favicons, false) ||
+ !InitFaviconsTable(&favicons, false) ||
!InitIconMappingTable(&favicons, false)) {
favicons.Close();
return false;
@@ -678,10 +881,14 @@ bool ThumbnailDatabase::RenameAndDropThumbnails(const FilePath& old_db_file,
}
}
- // Move favicons to the new DB.
- if (!db_.Execute("INSERT OR REPLACE INTO new_favicons.favicons "
- "SELECT * FROM favicons")) {
- DLOG(FATAL) << "Unable to copy favicons.";
+ // Move favicons and favicon_bitmaps to new DB.
+ bool successfully_moved_data =
+ db_.Execute("INSERT OR REPLACE INTO new_favicons.favicon_bitmaps "
+ "SELECT * FROM favicon_bitmaps") &&
+ db_.Execute("INSERT OR REPLACE INTO new_favicons.favicons "
+ "SELECT * FROM favicons");
+ if (!successfully_moved_data) {
+ DLOG(FATAL) << "Unable to copy favicons and favicon_bitmaps.";
BeginTransaction();
return false;
}
@@ -704,7 +911,7 @@ bool ThumbnailDatabase::RenameAndDropThumbnails(const FilePath& old_db_file,
if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber))
return false;
- if (!InitFaviconsIndex())
+ if (!InitFaviconBitmapsIndex() || !InitFaviconsIndex())
return false;
// Reopen the transaction.
@@ -786,4 +993,28 @@ bool ThumbnailDatabase::UpgradeToVersion5() {
return true;
}
+bool ThumbnailDatabase::UpgradeToVersion6() {
+ bool success =
+ db_.Execute("INSERT INTO favicon_bitmaps (icon_id, last_updated, "
+ "image_data, width, height)"
+ "SELECT id, last_updated, image_data, 0, 0 FROM favicons") &&
+ db_.Execute("CREATE TABLE temp_favicons ("
+ "id INTEGER PRIMARY KEY,"
+ "url LONGVARCHAR NOT NULL,"
+ "icon_type INTEGER DEFAULT 1,"
+ // Set the default icon_type as FAVICON to be consistent with
+ // table upgrade in UpgradeToVersion4().
+ "sizes LONGVARCHAR)") &&
+ db_.Execute("INSERT INTO temp_favicons (id, url, icon_type) "
+ "SELECT id, url, icon_type FROM favicons") &&
+ db_.Execute("DROP TABLE favicons") &&
+ db_.Execute("ALTER TABLE temp_favicons RENAME TO favicons");
+ if (!success)
+ return false;
+
+ meta_table_.SetVersionNumber(6);
+ meta_table_.SetCompatibleVersionNumber(std::min(6, kCompatibleVersionNumber));
+ return true;
+}
+
} // namespace history
« 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