Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/offline_pages/offline_page_metadata_store_sql.h" | 5 #include "components/offline_pages/offline_page_metadata_store_sql.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 | 26 |
| 27 // This is a macro instead of a const so that | 27 // This is a macro instead of a const so that |
| 28 // it can be used inline in other SQL statements below. | 28 // it can be used inline in other SQL statements below. |
| 29 #define OFFLINE_PAGES_TABLE_NAME "offlinepages_v1" | 29 #define OFFLINE_PAGES_TABLE_NAME "offlinepages_v1" |
| 30 | 30 |
| 31 bool CreateOfflinePagesTable(sql::Connection* db) { | 31 bool CreateOfflinePagesTable(sql::Connection* db) { |
| 32 const char kSql[] = "CREATE TABLE IF NOT EXISTS " OFFLINE_PAGES_TABLE_NAME | 32 const char kSql[] = "CREATE TABLE IF NOT EXISTS " OFFLINE_PAGES_TABLE_NAME |
| 33 "(offline_id INTEGER PRIMARY KEY NOT NULL," | 33 "(offline_id INTEGER PRIMARY KEY NOT NULL," |
| 34 " creation_time INTEGER NOT NULL," | 34 " creation_time INTEGER NOT NULL," |
| 35 " file_size INTEGER NOT NULL," | 35 " file_size INTEGER NOT NULL," |
| 36 " version INTEGER NOT NULL," | |
| 37 " last_access_time INTEGER NOT NULL," | 36 " last_access_time INTEGER NOT NULL," |
| 38 " access_count INTEGER NOT NULL," | 37 " access_count INTEGER NOT NULL," |
| 39 // TODO(fgorski): Remove. Never used. | |
| 40 " status INTEGER NOT NULL DEFAULT 0," | |
| 41 // A note on this field: It will be NULL for now and is | |
| 42 // reserved for later use. We will treat NULL as | |
| 43 // "Unknown" in any subsequent queries for user_initiated | |
| 44 // values. | |
| 45 " user_initiated INTEGER," // this is actually a boolean | |
| 46 " expiration_time INTEGER NOT NULL DEFAULT 0," | 38 " expiration_time INTEGER NOT NULL DEFAULT 0," |
| 47 " client_namespace VARCHAR NOT NULL," | 39 " client_namespace VARCHAR NOT NULL," |
| 48 " client_id VARCHAR NOT NULL," | 40 " client_id VARCHAR NOT NULL," |
| 49 " online_url VARCHAR NOT NULL," | 41 " online_url VARCHAR NOT NULL," |
| 50 // TODO(fgorski): Remove. Never used. | |
| 51 " offline_url VARCHAR NOT NULL DEFAULT ''," | |
| 52 " file_path VARCHAR NOT NULL," | 42 " file_path VARCHAR NOT NULL," |
| 53 " title VARCHAR NOT NULL DEFAULT ''" | 43 " title VARCHAR NOT NULL DEFAULT ''" |
| 54 ")"; | 44 ")"; |
| 55 return db->Execute(kSql); | 45 return db->Execute(kSql); |
| 56 } | 46 } |
| 57 | 47 |
| 58 bool RefreshColumnsFrom52To54(sql::Connection* db) { | 48 bool UpgradeFrom52(sql::Connection* db) { |
| 59 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME | 49 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME |
| 60 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { | 50 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 61 return false; | 51 return false; |
| 62 } | 52 } |
| 63 if (!CreateOfflinePagesTable(db)) | 53 if (!CreateOfflinePagesTable(db)) |
| 64 return false; | 54 return false; |
| 65 if (!db->Execute( | 55 if (!db->Execute( |
| 66 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME | 56 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME |
| 67 " (offline_id, creation_time, file_size, version, last_access_time, " | 57 " (offline_id, creation_time, file_size, last_access_time, " |
| 68 "access_count, status, user_initiated, client_namespace, client_id, " | 58 "access_count, client_namespace, client_id, " |
| 69 "online_url, offline_url, file_path) " | 59 "online_url, file_path) " |
| 70 "SELECT offline_id, creation_time, file_size, version, " | 60 "SELECT " |
| 71 "last_access_time, " | 61 "offline_id, creation_time, file_size, last_access_time, " |
| 72 "access_count, status, user_initiated, client_namespace, client_id, " | 62 "access_count, client_namespace, client_id, " |
| 73 "online_url, offline_url, file_path " | 63 "online_url, file_path " |
| 74 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { | 64 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 75 return false; | 65 return false; |
| 76 } | 66 } |
| 77 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) | 67 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) |
| 78 return false; | 68 return false; |
| 79 | 69 |
| 80 return true; | 70 return true; |
| 81 } | 71 } |
| 82 | 72 |
| 83 bool RefreshColumnsFrom53To54(sql::Connection* db) { | 73 bool UpgradeFrom53(sql::Connection* db) { |
| 84 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME | 74 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME |
| 85 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { | 75 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 86 return false; | 76 return false; |
| 87 } | 77 } |
| 88 if (!CreateOfflinePagesTable(db)) | 78 if (!CreateOfflinePagesTable(db)) |
| 89 return false; | 79 return false; |
| 90 if (!db->Execute( | 80 if (!db->Execute( |
| 91 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME | 81 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME |
| 92 " (offline_id, creation_time, file_size, version, last_access_time, " | 82 " (offline_id, creation_time, file_size, last_access_time, " |
| 93 "access_count, status, user_initiated, client_namespace, client_id, " | 83 "access_count, expiration_time, client_namespace, client_id, " |
| 94 "online_url, offline_url, file_path, expiration_time) " | 84 "online_url, file_path) " |
| 95 "SELECT offline_id, creation_time, file_size, version, " | 85 "SELECT " |
| 96 "last_access_time, " | 86 "offline_id, creation_time, file_size, last_access_time, " |
| 97 "access_count, status, user_initiated, client_namespace, client_id, " | 87 "access_count, expiration_time, client_namespace, client_id, " |
| 98 "online_url, offline_url, file_path, expiration_time " | 88 "online_url, file_path " |
| 99 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { | 89 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 100 return false; | 90 return false; |
| 101 } | 91 } |
| 92 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) | |
| 93 return false; | |
| 94 | |
| 95 return true; | |
| 96 } | |
| 97 | |
| 98 bool UpgradeFrom54(sql::Connection* db) { | |
| 99 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME | |
| 100 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { | |
| 101 return false; | |
| 102 } | |
| 103 if (!CreateOfflinePagesTable(db)) | |
| 104 return false; | |
| 105 if (!db->Execute( | |
|
dewittj
2016/09/13 18:10:07
Now that there are 3 copies of this function, it s
fgorski
2016/09/13 21:40:21
Done.
| |
| 106 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME | |
| 107 " (offline_id, creation_time, file_size, last_access_time, " | |
| 108 "access_count, expiration_time, client_namespace, client_id, " | |
| 109 "online_url, file_path, title) " | |
| 110 "SELECT " | |
| 111 "offline_id, creation_time, file_size, last_access_time, " | |
| 112 "access_count, expiration_time, client_namespace, client_id, " | |
| 113 "online_url, file_path, title " | |
| 114 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { | |
| 115 return false; | |
| 116 } | |
| 102 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) | 117 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) |
| 103 return false; | 118 return false; |
| 104 | 119 |
| 105 return true; | 120 return true; |
| 106 } | 121 } |
| 107 | 122 |
| 108 bool CreateSchema(sql::Connection* db) { | 123 bool CreateSchema(sql::Connection* db) { |
| 109 // If you create a transaction but don't Commit() it is automatically | 124 // If you create a transaction but don't Commit() it is automatically |
| 110 // rolled back by its destructor when it falls out of scope. | 125 // rolled back by its destructor when it falls out of scope. |
| 111 sql::Transaction transaction(db); | 126 sql::Transaction transaction(db); |
| 112 if (!transaction.Begin()) | 127 if (!transaction.Begin()) |
| 113 return false; | 128 return false; |
| 114 | 129 |
| 115 if (!db->DoesTableExist(OFFLINE_PAGES_TABLE_NAME)) { | 130 if (!db->DoesTableExist(OFFLINE_PAGES_TABLE_NAME)) { |
| 116 if (!CreateOfflinePagesTable(db)) | 131 if (!CreateOfflinePagesTable(db)) |
| 117 return false; | 132 return false; |
| 118 } | 133 } |
| 119 | 134 |
| 135 // Last Schema update was M55. When making a new Schema update, please update | |
| 136 // all methods below to appropriately upgrade from their respective milestones | |
| 137 // and add appropriate method to cover changes from M55. | |
|
dewittj
2016/09/13 18:10:08
I would like to see somewhere a log of the changes
romax
2016/09/13 18:32:14
I wish these comments can be with those upgrade fu
fgorski
2016/09/13 21:40:21
Done.
| |
| 120 if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "expiration_time")) { | 138 if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "expiration_time")) { |
| 121 if (!RefreshColumnsFrom52To54(db)) | 139 if (!UpgradeFrom52(db)) |
| 122 return false; | 140 return false; |
| 123 } else if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "title")) { | 141 } else if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "title")) { |
| 124 if (!RefreshColumnsFrom53To54(db)) | 142 if (!UpgradeFrom53(db)) |
| 143 return false; | |
| 144 } else if (db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "offline_url")) { | |
| 145 if (!UpgradeFrom54(db)) | |
| 125 return false; | 146 return false; |
| 126 } | 147 } |
| 127 | 148 |
| 128 // TODO(bburns): Add indices here. | 149 // TODO(bburns): Add indices here. |
| 129 return transaction.Commit(); | 150 return transaction.Commit(); |
| 130 } | 151 } |
| 131 | 152 |
| 132 bool DeleteByOfflineId(sql::Connection* db, int64_t offline_id) { | 153 bool DeleteByOfflineId(sql::Connection* db, int64_t offline_id) { |
| 133 static const char kSql[] = | 154 static const char kSql[] = |
| 134 "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id=?"; | 155 "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id=?"; |
| 135 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 156 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 136 statement.BindInt64(0, offline_id); | 157 statement.BindInt64(0, offline_id); |
| 137 return statement.Run(); | 158 return statement.Run(); |
| 138 } | 159 } |
| 139 | 160 |
| 161 base::FilePath GetPathFromString(const std::string& path_string) { | |
|
dewittj
2016/09/13 18:10:07
Maybe name this GetPathFromUTF8String (and similar
fgorski
2016/09/13 21:40:21
Done.
| |
| 162 #if defined(OS_POSIX) | |
| 163 return base::FilePath(path_string); | |
| 164 #elif defined(OS_WIN) | |
| 165 return base::FilePath(base::UTF8ToWide(path_string)); | |
| 166 #else | |
| 167 #error Unknown OS | |
| 168 #endif | |
| 169 } | |
| 170 | |
| 171 std::string GetStringFromPath(const base::FilePath& path) { | |
| 172 #if defined(OS_POSIX) | |
| 173 return path.value(); | |
| 174 #elif defined(OS_WIN) | |
| 175 return base::WideToUTF8(path.value()); | |
| 176 #else | |
| 177 #error Unknown OS | |
| 178 #endif | |
| 179 } | |
| 180 | |
| 140 // Create an offline page item from a SQL result. Expects complete rows with | 181 // Create an offline page item from a SQL result. Expects complete rows with |
| 141 // all columns present. | 182 // all columns present. |
| 142 OfflinePageItem MakeOfflinePageItem(sql::Statement* statement) { | 183 OfflinePageItem MakeOfflinePageItem(sql::Statement* statement) { |
| 143 int64_t id = statement->ColumnInt64(0); | 184 int64_t id = statement->ColumnInt64(0); |
| 144 base::Time creation_time = | 185 base::Time creation_time = |
| 145 base::Time::FromInternalValue(statement->ColumnInt64(1)); | 186 base::Time::FromInternalValue(statement->ColumnInt64(1)); |
| 146 int64_t file_size = statement->ColumnInt64(2); | 187 int64_t file_size = statement->ColumnInt64(2); |
| 147 ClientId client_id(statement->ColumnString(9), | 188 base::Time last_access_time = |
| 148 statement->ColumnString(10)); | 189 base::Time::FromInternalValue(statement->ColumnInt64(3)); |
| 149 GURL url(statement->ColumnString(11)); | 190 int access_count = statement->ColumnInt(4); |
| 150 #if defined(OS_POSIX) | 191 base::Time expiration_time = |
| 151 base::FilePath path(statement->ColumnString(13)); | 192 base::Time::FromInternalValue(statement->ColumnInt64(5)); |
| 152 #elif defined(OS_WIN) | 193 ClientId client_id(statement->ColumnString(6), statement->ColumnString(7)); |
| 153 base::FilePath path(base::UTF8ToWide(statement->ColumnString(13))); | 194 GURL url(statement->ColumnString(8)); |
| 154 #else | 195 base::FilePath path(GetPathFromString(statement->ColumnString(9))); |
| 155 #error Unknown OS | 196 base::string16 title = statement->ColumnString16(10); |
| 156 #endif | |
| 157 | 197 |
| 158 OfflinePageItem item(url, id, client_id, path, file_size, creation_time); | 198 OfflinePageItem item(url, id, client_id, path, file_size, creation_time); |
| 159 item.version = statement->ColumnInt(3); | 199 item.last_access_time = last_access_time; |
| 160 item.last_access_time = base::Time::FromInternalValue( | 200 item.access_count = access_count; |
| 161 statement->ColumnInt64(4)); | 201 item.expiration_time = expiration_time; |
| 162 item.access_count = statement->ColumnInt(5); | 202 item.title = title; |
| 163 item.expiration_time = | |
| 164 base::Time::FromInternalValue(statement->ColumnInt64(8)); | |
| 165 item.title = statement->ColumnString16(14); | |
| 166 return item; | 203 return item; |
| 167 } | 204 } |
| 168 | 205 |
| 169 bool InsertOrReplace(sql::Connection* db, const OfflinePageItem& item) { | 206 bool InsertOrReplace(sql::Connection* db, const OfflinePageItem& item) { |
| 170 const char kSql[] = | 207 const char kSql[] = |
| 171 "INSERT OR REPLACE INTO " OFFLINE_PAGES_TABLE_NAME | 208 "INSERT OR REPLACE INTO " OFFLINE_PAGES_TABLE_NAME |
| 172 " (offline_id, online_url, client_namespace, client_id, file_path, " | 209 " (offline_id, online_url, client_namespace, client_id, file_path, " |
| 173 "file_size, creation_time, last_access_time, version, access_count, " | 210 "file_size, creation_time, last_access_time, access_count, " |
| 174 "expiration_time, title)" | 211 "expiration_time, title)" |
| 175 " VALUES " | 212 " VALUES " |
| 176 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; | 213 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
| 177 | 214 |
| 178 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 215 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 179 statement.BindInt64(0, item.offline_id); | 216 statement.BindInt64(0, item.offline_id); |
| 180 statement.BindString(1, item.url.spec()); | 217 statement.BindString(1, item.url.spec()); |
| 181 statement.BindString(2, item.client_id.name_space); | 218 statement.BindString(2, item.client_id.name_space); |
| 182 statement.BindString(3, item.client_id.id); | 219 statement.BindString(3, item.client_id.id); |
| 183 #if defined(OS_POSIX) | 220 statement.BindString(4, GetStringFromPath(item.file_path)); |
| 184 std::string path_string = item.file_path.value(); | |
| 185 #elif defined(OS_WIN) | |
| 186 std::string path_string = base::WideToUTF8(item.file_path.value()); | |
| 187 #else | |
| 188 #error Unknown OS | |
| 189 #endif | |
| 190 statement.BindString(4, path_string); | |
| 191 statement.BindInt64(5, item.file_size); | 221 statement.BindInt64(5, item.file_size); |
| 192 statement.BindInt64(6, item.creation_time.ToInternalValue()); | 222 statement.BindInt64(6, item.creation_time.ToInternalValue()); |
| 193 statement.BindInt64(7, item.last_access_time.ToInternalValue()); | 223 statement.BindInt64(7, item.last_access_time.ToInternalValue()); |
| 194 statement.BindInt(8, item.version); | 224 statement.BindInt(8, item.access_count); |
| 195 statement.BindInt(9, item.access_count); | 225 statement.BindInt64(9, item.expiration_time.ToInternalValue()); |
| 196 statement.BindInt64(10, item.expiration_time.ToInternalValue()); | 226 statement.BindString16(10, item.title); |
| 197 statement.BindString16(11, item.title); | |
| 198 return statement.Run(); | 227 return statement.Run(); |
| 199 } | 228 } |
| 200 | 229 |
| 201 bool InitDatabase(sql::Connection* db, base::FilePath path) { | 230 bool InitDatabase(sql::Connection* db, base::FilePath path) { |
| 202 db->set_page_size(4096); | 231 db->set_page_size(4096); |
| 203 db->set_cache_size(500); | 232 db->set_cache_size(500); |
| 204 db->set_histogram_tag("OfflinePageMetadata"); | 233 db->set_histogram_tag("OfflinePageMetadata"); |
| 205 db->set_exclusive_locking(); | 234 db->set_exclusive_locking(); |
| 206 | 235 |
| 207 base::File::Error err; | 236 base::File::Error err; |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 DCHECK(db_.get()); | 456 DCHECK(db_.get()); |
| 428 if (!db_.get()) { | 457 if (!db_.get()) { |
| 429 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | 458 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 430 base::Bind(callback)); | 459 base::Bind(callback)); |
| 431 return false; | 460 return false; |
| 432 } | 461 } |
| 433 return true; | 462 return true; |
| 434 } | 463 } |
| 435 | 464 |
| 436 } // namespace offline_pages | 465 } // namespace offline_pages |
| OLD | NEW |