| Index: components/history/core/browser/thumbnail_database.cc
|
| diff --git a/components/history/core/browser/thumbnail_database.cc b/components/history/core/browser/thumbnail_database.cc
|
| index c8b430f4f71d8dd70f0111995c5ce74297cec7d9..06d7176e5d31be142791c11f866b998e1c1e1db5 100644
|
| --- a/components/history/core/browser/thumbnail_database.cc
|
| +++ b/components/history/core/browser/thumbnail_database.cc
|
| @@ -271,6 +271,22 @@ void DatabaseErrorCallback(sql::Connection* db,
|
| DLOG(FATAL) << db->GetErrorMessage();
|
| }
|
|
|
| +void DeleteOrphanagedFaviconBitmaps(sql::Connection* db) {
|
| + sql::Statement favicons(db->GetCachedStatement(
|
| + SQL_FROM_HERE,
|
| + "DELETE FROM favicon_bitmaps WHERE NOT EXISTS (SELECT id FROM favicons "
|
| + "WHERE favicon_bitmaps.icon_id = favicons.id)"));
|
| + favicons.Run();
|
| +}
|
| +
|
| +void DeleteOrphanagedMappings(sql::Connection* db) {
|
| + sql::Statement mappings(db->GetCachedStatement(
|
| + SQL_FROM_HERE,
|
| + "DELETE FROM icon_mapping WHERE NOT EXISTS (SELECT id FROM favicons "
|
| + "WHERE favicons.id = icon_mapping.icon_id)"));
|
| + mappings.Run();
|
| +}
|
| +
|
| } // namespace
|
|
|
| ThumbnailDatabase::IconMappingEnumerator::IconMappingEnumerator() {
|
| @@ -412,6 +428,151 @@ void ThumbnailDatabase::TrimMemory(bool aggressively) {
|
| db_.TrimMemory(aggressively);
|
| }
|
|
|
| +void ThumbnailDatabase::ClearOldOnDemandFavicons(
|
| + base::Time deletion_threshold) {
|
| + // Select all bitmaps (and their page URLs) that have not been accessed for a
|
| + // while. Restrict to on-demand bitmaps (i.e. with last_requested != 0).
|
| + sql::Statement delete_candidates(db_.GetCachedStatement(
|
| + SQL_FROM_HERE,
|
| + "SELECT favicon_bitmaps.icon_id, icon_mapping.page_url FROM "
|
| + "favicon_bitmaps, icon_mapping WHERE favicon_bitmaps.icon_id = "
|
| + "icon_mapping.icon_id AND favicon_bitmaps.last_requested>0 AND "
|
| + "favicon_bitmaps.last_requested<?;"));
|
| + delete_candidates.BindInt64(0, deletion_threshold.ToInternalValue());
|
| +
|
| + // Multiple page URLs may map to the same favicon. We omit the favicon from
|
| + // cleaning if at least one of its associated page URLs is bookmarked.
|
| + std::set<favicon_base::FaviconID> ids_of_icons_with_some_bookmarked_page;
|
| + std::set<favicon_base::FaviconID> ids_of_icons_with_no_bookmarked_page;
|
| + while (delete_candidates.Step()) {
|
| + favicon_base::FaviconID icon_id = delete_candidates.ColumnInt64(0);
|
| + if (ids_of_icons_with_some_bookmarked_page.count(icon_id))
|
| + continue;
|
| +
|
| + GURL page_url = GURL(delete_candidates.ColumnString(1));
|
| + if (backend_client_ && backend_client_->IsBookmarked(page_url)) {
|
| + ids_of_icons_with_some_bookmarked_page.insert(icon_id);
|
| + ids_of_icons_with_no_bookmarked_page.erase(icon_id);
|
| + continue;
|
| + }
|
| +
|
| + ids_of_icons_with_no_bookmarked_page.insert(icon_id);
|
| + }
|
| +
|
| + for (favicon_base::FaviconID icon_id : ids_of_icons_with_no_bookmarked_page) {
|
| + sql::Statement statement(db_.GetCachedStatement(
|
| + SQL_FROM_HERE, "DELETE FROM favicons WHERE id=?"));
|
| + statement.BindInt64(0, icon_id);
|
| + statement.Run();
|
| + }
|
| +
|
| + // The bitmaps and mappings for all deleted favicons are deleted at once.
|
| + DeleteOrphanagedFaviconBitmaps(&db_);
|
| + DeleteOrphanagedMappings(&db_);
|
| +}
|
| +
|
| +void ThumbnailDatabase::ClearOldOnDemandFaviconsOneByOne(
|
| + base::Time deletion_threshold) {
|
| + // Select all bitmaps (and their page URLs) that have not been accessed for a
|
| + // while. Restrict to on-demand bitmaps (i.e. with last_requested != 0).
|
| + sql::Statement delete_candidates(db_.GetCachedStatement(
|
| + SQL_FROM_HERE,
|
| + "SELECT favicon_bitmaps.icon_id, icon_mapping.page_url FROM "
|
| + "favicon_bitmaps, icon_mapping WHERE favicon_bitmaps.icon_id = "
|
| + "icon_mapping.icon_id AND favicon_bitmaps.last_requested>0 AND "
|
| + "favicon_bitmaps.last_requested<?;"));
|
| + delete_candidates.BindInt64(0, deletion_threshold.ToInternalValue());
|
| +
|
| + // Multiple page URLs may map to the same favicon. We omit the favicon from
|
| + // cleaning if at least one of its associated page URLs is bookmarked.
|
| + std::set<favicon_base::FaviconID> ids_of_icons_with_some_bookmarked_page;
|
| + std::set<favicon_base::FaviconID> ids_of_icons_with_no_bookmarked_page;
|
| + while (delete_candidates.Step()) {
|
| + favicon_base::FaviconID icon_id = delete_candidates.ColumnInt64(0);
|
| + if (ids_of_icons_with_some_bookmarked_page.count(icon_id))
|
| + continue;
|
| +
|
| + GURL page_url = GURL(delete_candidates.ColumnString(1));
|
| + if (backend_client_ && backend_client_->IsBookmarked(page_url)) {
|
| + ids_of_icons_with_some_bookmarked_page.insert(icon_id);
|
| + ids_of_icons_with_no_bookmarked_page.erase(icon_id);
|
| + continue;
|
| + }
|
| +
|
| + ids_of_icons_with_no_bookmarked_page.insert(icon_id);
|
| + }
|
| +
|
| + for (favicon_base::FaviconID icon_id : ids_of_icons_with_no_bookmarked_page) {
|
| + sql::Statement statement(db_.GetCachedStatement(
|
| + SQL_FROM_HERE, "DELETE FROM favicons WHERE id=?"));
|
| + statement.BindInt64(0, icon_id);
|
| + statement.Run();
|
| +
|
| + sql::Statement statement2(db_.GetCachedStatement(
|
| + SQL_FROM_HERE, "DELETE FROM favicon_bitmaps WHERE icon_id=?"));
|
| + statement2.BindInt64(0, icon_id);
|
| + statement2.Run();
|
| +
|
| + sql::Statement statement3(db_.GetCachedStatement(
|
| + SQL_FROM_HERE, "DELETE FROM icon_mapping WHERE icon_id=?"));
|
| + statement3.BindInt64(0, icon_id);
|
| + statement3.Run();
|
| + }
|
| +}
|
| +
|
| +void ThumbnailDatabase::ClearOldOnDemandFaviconsNoJoin(
|
| + base::Time deletion_threshold) {
|
| + // Select all bitmaps (and their page URLs) that have not been accessed for a
|
| + // while. Restrict to on-demand bitmaps (i.e. with last_requested != 0).
|
| + sql::Statement delete_candidates(
|
| + db_.GetCachedStatement(SQL_FROM_HERE,
|
| + "SELECT icon_id FROM favicon_bitmaps WHERE "
|
| + "favicon_bitmaps.last_requested>0 AND "
|
| + "favicon_bitmaps.last_requested<?;"));
|
| + delete_candidates.BindInt64(0, deletion_threshold.ToInternalValue());
|
| +
|
| + // Multiple page URLs may map to the same favicon. We omit the favicon from
|
| + // cleaning if at least one of its associated page URLs is bookmarked.
|
| + std::set<favicon_base::FaviconID> ids_of_icons_with_some_bookmarked_page;
|
| + std::set<favicon_base::FaviconID> ids_of_icons_with_no_bookmarked_page;
|
| + while (delete_candidates.Step()) {
|
| + favicon_base::FaviconID icon_id = delete_candidates.ColumnInt64(0);
|
| + if (ids_of_icons_with_some_bookmarked_page.count(icon_id))
|
| + continue;
|
| +
|
| + ids_of_icons_with_no_bookmarked_page.insert(icon_id);
|
| +
|
| + if (!backend_client_)
|
| + continue;
|
| +
|
| + sql::Statement delete_candidate_urls(db_.GetCachedStatement(
|
| + SQL_FROM_HERE,
|
| + "SELECT page_url FROM icon_mapping WHERE icon_mapping.icon_id=?;"));
|
| + delete_candidate_urls.BindInt64(0, icon_id);
|
| +
|
| + while (delete_candidate_urls.Step()) {
|
| + GURL page_url = GURL(delete_candidate_urls.ColumnString(0));
|
| + if (!backend_client_->IsBookmarked(page_url))
|
| + continue;
|
| +
|
| + ids_of_icons_with_some_bookmarked_page.insert(icon_id);
|
| + ids_of_icons_with_no_bookmarked_page.erase(icon_id);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + for (favicon_base::FaviconID icon_id : ids_of_icons_with_no_bookmarked_page) {
|
| + sql::Statement statement(db_.GetCachedStatement(
|
| + SQL_FROM_HERE, "DELETE FROM favicons WHERE id=?"));
|
| + statement.BindInt64(0, icon_id);
|
| + statement.Run();
|
| + }
|
| +
|
| + // The bitmaps and mappings for all deleted favicons are deleted at once.
|
| + DeleteOrphanagedFaviconBitmaps(&db_);
|
| + DeleteOrphanagedMappings(&db_);
|
| +}
|
| +
|
| bool ThumbnailDatabase::GetFaviconBitmapIDSizes(
|
| favicon_base::FaviconID icon_id,
|
| std::vector<FaviconBitmapIDSize>* bitmap_id_sizes) {
|
|
|