Chromium Code Reviews| Index: components/previews/core/previews_opt_out_store_sql.cc |
| diff --git a/components/previews/core/previews_opt_out_store_sql.cc b/components/previews/core/previews_opt_out_store_sql.cc |
| index a6fe9e7ea690cdba8274d72cbb8c90c75c69e98f..c11eed37b2d23a0c72404201eed0f89699d4ae8d 100644 |
| --- a/components/previews/core/previews_opt_out_store_sql.cc |
| +++ b/components/previews/core/previews_opt_out_store_sql.cc |
| @@ -4,7 +4,9 @@ |
| #include "components/previews/core/previews_opt_out_store_sql.h" |
| +#include <map> |
| #include <string> |
| +#include <utility> |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| @@ -55,18 +57,28 @@ int MaxRowsInOptOutDB() { |
| return base::StringToInt(max_rows, &value) ? value : 3200; |
| } |
| -// This is a macro instead of a const, so it can be used inline in other SQL |
| -// statements below. |
| +// Table names use a macro instead of a const, so they can be used inline in |
| +// other SQL statements below. |
| #define PREVIEWS_TABLE_NAME "previews_v1" |
| +#define ENABLED_PREVIEWS_TABLE_NAME "enabled_previews_v1" |
| void CreateSchema(sql::Connection* db) { |
| - const char kSql[] = "CREATE TABLE IF NOT EXISTS " PREVIEWS_TABLE_NAME |
| - " (host_name VARCHAR NOT NULL," |
| - " time INTEGER NOT NULL," |
| - " opt_out INTEGER NOT NULL," |
| - " type INTEGER NOT NULL," |
| - " PRIMARY KEY(host_name, time DESC, opt_out, type))"; |
| - if (!db->Execute(kSql)) |
| + const char kSqlCreatePreviewsTable[] = |
| + "CREATE TABLE IF NOT EXISTS " PREVIEWS_TABLE_NAME |
| + " (host_name VARCHAR NOT NULL," |
| + " time INTEGER NOT NULL," |
| + " opt_out INTEGER NOT NULL," |
| + " type INTEGER NOT NULL," |
| + " PRIMARY KEY(host_name, time DESC, opt_out, type))"; |
| + if (!db->Execute(kSqlCreatePreviewsTable)) |
| + return; |
| + |
| + const char kSqlCreateEnabledTypeVersionTable[] = |
| + "CREATE TABLE IF NOT EXISTS " ENABLED_PREVIEWS_TABLE_NAME |
| + " (type INTEGER NOT NULL," |
| + " version INTEGER NOT NULL," |
| + " PRIMARY KEY(type))"; |
| + if (!db->Execute(kSqlCreateEnabledTypeVersionTable)) |
| return; |
| } |
| @@ -168,10 +180,112 @@ void MaybeEvictHostEntryFromDataBase(sql::Connection* db, |
| statement_delete_by_host.Run(); |
| } |
| +// Deletes every preview navigation entry for |type|. |
| +void ClearBlacklistForTypeInDataBase(sql::Connection* db, PreviewsType type) { |
| + const char kSql[] = "DELETE FROM " PREVIEWS_TABLE_NAME " WHERE type == ?"; |
| + sql::Statement statement(db->GetUniqueStatement(kSql)); |
| + statement.BindInt(0, static_cast<int>(type)); |
| + statement.Run(); |
| +} |
| + |
| +std::unique_ptr<std::map<PreviewsType, int>> GetStoredPreviews( |
|
RyanSturm
2017/02/15 00:30:29
Add a comment to all the helper methods here. Can
dougarnett
2017/02/15 17:20:07
Done. Please give it a look. I also renamed the ma
|
| + sql::Connection* db) { |
| + const char kSqlLoadEnabledPreviewsVersions[] = |
| + "SELECT type, version FROM " ENABLED_PREVIEWS_TABLE_NAME; |
| + |
| + sql::Statement statement( |
| + db->GetUniqueStatement(kSqlLoadEnabledPreviewsVersions)); |
| + |
| + std::unique_ptr<std::map<PreviewsType, int>> stored_previews( |
| + new std::map<PreviewsType, int>()); |
| + while (statement.Step()) { |
| + PreviewsType type = static_cast<PreviewsType>(statement.ColumnInt(0)); |
| + int version = statement.ColumnInt(1); |
| + stored_previews->insert({type, version}); |
| + } |
| + return stored_previews; |
| +} |
| + |
| +void InsertEnabledPreviewInDataBase(sql::Connection* db, |
| + PreviewsType type, |
| + int version) { |
| + const char kSqlInsert[] = "INSERT INTO " ENABLED_PREVIEWS_TABLE_NAME |
| + " (type, version)" |
| + " VALUES " |
| + " (?, ?)"; |
| + |
| + sql::Statement statement_insert(db->GetUniqueStatement(kSqlInsert)); |
| + statement_insert.BindInt(0, static_cast<int>(type)); |
| + statement_insert.BindInt(1, version); |
| + statement_insert.Run(); |
| +} |
| + |
| +void UpdateEnabledPreviewInDataBase(sql::Connection* db, |
| + PreviewsType type, |
| + int version) { |
| + const char kSqlUpdate[] = "UPDATE " ENABLED_PREVIEWS_TABLE_NAME |
| + " SET version = ?" |
| + " WHERE type = ?"; |
| + |
| + sql::Statement statement_update( |
| + db->GetCachedStatement(SQL_FROM_HERE, kSqlUpdate)); |
| + statement_update.BindInt(0, version); |
| + statement_update.BindInt(1, static_cast<int>(type)); |
| + statement_update.Run(); |
| +} |
| + |
| +void DeleteEnabledPreviewInDataBase(sql::Connection* db, PreviewsType type) { |
| + const char kSqlDelete[] = |
| + "DELETE FROM " ENABLED_PREVIEWS_TABLE_NAME " WHERE type == ?"; |
| + |
| + sql::Statement statement_delete(db->GetUniqueStatement(kSqlDelete)); |
| + statement_delete.BindInt(0, static_cast<int>(type)); |
| + statement_delete.Run(); |
| +} |
| + |
| +// Checks the current set of enabled previews (with their current version) |
| +// and where a preview is now disabled or has a different version, cleans up |
| +// any associated blacklist entries. |
| +void CheckAndReconcileEnabledPreviewsWithDataBase(sql::Connection* db) { |
| + std::unique_ptr<std::map<PreviewsType, int>> stored_previews( |
| + GetStoredPreviews(db)); |
| + |
| + std::unique_ptr<PreviewsTypeList> enabled_previews(GetEnabledPreviews()); |
| + |
| + for (auto enabled_it = enabled_previews->begin(); |
| + enabled_it != enabled_previews->end(); ++enabled_it) { |
| + PreviewsType type = enabled_it->first; |
| + int current_version = enabled_it->second; |
| + auto stored_it = stored_previews->find(type); |
| + if (stored_it == stored_previews->end()) { |
| + InsertEnabledPreviewInDataBase(db, type, current_version); |
| + } else { |
| + if (stored_it->second != current_version) { |
| + DCHECK_GE(current_version, stored_it->second); |
| + ClearBlacklistForTypeInDataBase(db, type); |
| + UpdateEnabledPreviewInDataBase(db, type, current_version); |
| + } |
| + // Erase entry from the local map to detect any newly disabled types. |
| + stored_previews->erase(stored_it); |
| + } |
| + } |
| + |
| + // Now check for any types that are no longer enabled. |
| + for (auto stored_it = stored_previews->begin(); |
| + stored_it != stored_previews->end(); ++stored_it) { |
| + PreviewsType type = stored_it->first; |
| + ClearBlacklistForTypeInDataBase(db, type); |
| + DeleteEnabledPreviewInDataBase(db, type); |
| + } |
| +} |
| + |
| void LoadBlackListFromDataBase( |
| sql::Connection* db, |
| scoped_refptr<base::SingleThreadTaskRunner> runner, |
| LoadBlackListCallback callback) { |
| + // First handle any update needed wrt enabled previews and their versions. |
| + CheckAndReconcileEnabledPreviewsWithDataBase(db); |
| + |
| // Gets the table sorted by host and time. Limits the number of hosts using |
| // most recent opt_out time as the limiting function. Sorting is free due to |
| // the table structure, and it improves performance in the loop below. |