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) { |