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 10 matching lines...) Expand all Loading... | |
| 21 namespace offline_pages { | 21 namespace offline_pages { |
| 22 | 22 |
| 23 using StoreState = OfflinePageMetadataStore::StoreState; | 23 using StoreState = OfflinePageMetadataStore::StoreState; |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 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 // New columns should be added at the end of the list in order to avoid | 31 bool CreateOfflinePagesTable(sql::Connection* db) { |
| 32 // complicated table upgrade. | 32 const char kSql[] = "CREATE TABLE IF NOT EXISTS " OFFLINE_PAGES_TABLE_NAME |
| 33 const char kOfflinePagesColumns[] = | 33 "(offline_id INTEGER PRIMARY KEY NOT NULL," |
| 34 "(offline_id INTEGER PRIMARY KEY NOT NULL," | 34 " creation_time INTEGER NOT NULL," |
| 35 " creation_time INTEGER NOT NULL," | 35 " file_size INTEGER NOT NULL," |
| 36 " file_size INTEGER NOT NULL," | 36 " version INTEGER NOT NULL," |
|
Dmitry Titov
2016/09/12 23:14:31
Looks like 'version' should also be "Remove. Never
fgorski
2016/09/12 23:22:00
Acknowledged. As discussed, the upgrade patch will
| |
| 37 " version INTEGER NOT NULL," | 37 " last_access_time INTEGER NOT NULL," |
| 38 " last_access_time INTEGER NOT NULL," | 38 " access_count INTEGER NOT NULL," |
| 39 " access_count INTEGER NOT NULL," | 39 // TODO(fgorski): Remove. Never used. |
| 40 " status INTEGER NOT NULL DEFAULT 0," | 40 " status INTEGER NOT NULL DEFAULT 0," |
| 41 // A note on this field: It will be NULL for now and is reserved for | 41 // A note on this field: It will be NULL for now and is |
|
dewittj
2016/09/12 23:25:38
Please update this comment to refer to the version
fgorski
2016/09/13 03:27:53
The field is being dropped, as it was never used.
| |
| 42 // later use. We will treat NULL as "Unknown" in any subsequent queries | 42 // reserved for later use. We will treat NULL as |
| 43 // for user_initiated values. | 43 // "Unknown" in any subsequent queries for user_initiated |
| 44 " user_initiated INTEGER," // this is actually a boolean | 44 // values. |
| 45 " expiration_time INTEGER NOT NULL DEFAULT 0," | 45 " user_initiated INTEGER," // this is actually a boolean |
|
Dmitry Titov
2016/09/12 23:14:31
Same here.
fgorski
2016/09/12 23:22:00
Acknowledged. As discussed, already handled by upg
| |
| 46 " client_namespace VARCHAR NOT NULL," | 46 " expiration_time INTEGER NOT NULL DEFAULT 0," |
| 47 " client_id VARCHAR NOT NULL," | 47 " client_namespace VARCHAR NOT NULL," |
| 48 " online_url VARCHAR NOT NULL," | 48 " client_id VARCHAR NOT NULL," |
| 49 " offline_url VARCHAR NOT NULL DEFAULT ''," | 49 " online_url VARCHAR NOT NULL," |
| 50 " file_path VARCHAR NOT NULL," | 50 // TODO(fgorski): Remove. Never used. |
| 51 " title VARCHAR NOT NULL DEFAULT ''" | 51 " offline_url VARCHAR NOT NULL DEFAULT ''," |
| 52 ")"; | 52 " file_path VARCHAR NOT NULL," |
| 53 | 53 " title VARCHAR NOT NULL DEFAULT ''" |
| 54 // This is cloned from //content/browser/appcache/appcache_database.cc | 54 ")"; |
| 55 struct TableInfo { | 55 return db->Execute(kSql); |
| 56 const char* table_name; | |
| 57 const char* columns; | |
| 58 }; | |
| 59 | |
| 60 const TableInfo kOfflinePagesTable{OFFLINE_PAGES_TABLE_NAME, | |
| 61 kOfflinePagesColumns}; | |
| 62 | |
| 63 // This enum is used to define the indices for the columns in each row | |
| 64 // that hold the different pieces of offline page. | |
| 65 enum : int { | |
| 66 OP_OFFLINE_ID = 0, | |
| 67 OP_CREATION_TIME, | |
| 68 OP_FILE_SIZE, | |
| 69 OP_VERSION, | |
| 70 OP_LAST_ACCESS_TIME, | |
| 71 OP_ACCESS_COUNT, | |
| 72 OP_STATUS, | |
| 73 OP_USER_INITIATED, | |
| 74 OP_EXPIRATION_TIME, // Added in M53. | |
| 75 OP_CLIENT_NAMESPACE, | |
| 76 OP_CLIENT_ID, | |
| 77 OP_ONLINE_URL, | |
| 78 OP_OFFLINE_URL, | |
| 79 OP_FILE_PATH, | |
| 80 OP_TITLE, // Added in M54. | |
| 81 }; | |
| 82 | |
| 83 bool CreateTable(sql::Connection* db, const TableInfo& table_info) { | |
| 84 std::string sql("CREATE TABLE "); | |
| 85 sql += table_info.table_name; | |
| 86 sql += table_info.columns; | |
| 87 return db->Execute(sql.c_str()); | |
| 88 } | 56 } |
| 89 | 57 |
| 90 bool RefreshColumnsFrom52To54(sql::Connection* db) { | 58 bool RefreshColumnsFrom52To54(sql::Connection* db) { |
| 91 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME | 59 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME |
| 92 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { | 60 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 93 return false; | 61 return false; |
| 94 } | 62 } |
| 95 if (!CreateTable(db, kOfflinePagesTable)) | 63 if (!CreateOfflinePagesTable(db)) |
| 96 return false; | 64 return false; |
| 97 if (!db->Execute( | 65 if (!db->Execute( |
| 98 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME | 66 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME |
| 99 " (offline_id, creation_time, file_size, version, last_access_time, " | 67 " (offline_id, creation_time, file_size, version, last_access_time, " |
| 100 "access_count, status, user_initiated, client_namespace, client_id, " | 68 "access_count, status, user_initiated, client_namespace, client_id, " |
| 101 "online_url, offline_url, file_path) " | 69 "online_url, offline_url, file_path) " |
| 102 "SELECT offline_id, creation_time, file_size, version, " | 70 "SELECT offline_id, creation_time, file_size, version, " |
| 103 "last_access_time, " | 71 "last_access_time, " |
| 104 "access_count, status, user_initiated, client_namespace, client_id, " | 72 "access_count, status, user_initiated, client_namespace, client_id, " |
| 105 "online_url, offline_url, file_path " | 73 "online_url, offline_url, file_path " |
| 106 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { | 74 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 107 return false; | 75 return false; |
| 108 } | 76 } |
| 109 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) | 77 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) |
| 110 return false; | 78 return false; |
| 111 | 79 |
| 112 return true; | 80 return true; |
| 113 } | 81 } |
| 114 | 82 |
| 115 bool RefreshColumnsFrom53To54(sql::Connection* db) { | 83 bool RefreshColumnsFrom53To54(sql::Connection* db) { |
| 116 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME | 84 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME |
| 117 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { | 85 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 118 return false; | 86 return false; |
| 119 } | 87 } |
| 120 if (!CreateTable(db, kOfflinePagesTable)) | 88 if (!CreateOfflinePagesTable(db)) |
| 121 return false; | 89 return false; |
| 122 if (!db->Execute( | 90 if (!db->Execute( |
| 123 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME | 91 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME |
| 124 " (offline_id, creation_time, file_size, version, last_access_time, " | 92 " (offline_id, creation_time, file_size, version, last_access_time, " |
| 125 "access_count, status, user_initiated, client_namespace, client_id, " | 93 "access_count, status, user_initiated, client_namespace, client_id, " |
| 126 "online_url, offline_url, file_path, expiration_time) " | 94 "online_url, offline_url, file_path, expiration_time) " |
| 127 "SELECT offline_id, creation_time, file_size, version, " | 95 "SELECT offline_id, creation_time, file_size, version, " |
| 128 "last_access_time, " | 96 "last_access_time, " |
| 129 "access_count, status, user_initiated, client_namespace, client_id, " | 97 "access_count, status, user_initiated, client_namespace, client_id, " |
| 130 "online_url, offline_url, file_path, expiration_time " | 98 "online_url, offline_url, file_path, expiration_time " |
| 131 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { | 99 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) { |
| 132 return false; | 100 return false; |
| 133 } | 101 } |
| 134 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) | 102 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) |
| 135 return false; | 103 return false; |
| 136 | 104 |
| 137 return true; | 105 return true; |
| 138 } | 106 } |
| 139 | 107 |
| 140 bool CreateSchema(sql::Connection* db) { | 108 bool CreateSchema(sql::Connection* db) { |
| 141 // If you create a transaction but don't Commit() it is automatically | 109 // If you create a transaction but don't Commit() it is automatically |
| 142 // rolled back by its destructor when it falls out of scope. | 110 // rolled back by its destructor when it falls out of scope. |
| 143 sql::Transaction transaction(db); | 111 sql::Transaction transaction(db); |
| 144 if (!transaction.Begin()) | 112 if (!transaction.Begin()) |
| 145 return false; | 113 return false; |
| 146 | 114 |
| 147 if (!db->DoesTableExist(kOfflinePagesTable.table_name)) { | 115 if (!db->DoesTableExist(OFFLINE_PAGES_TABLE_NAME)) { |
| 148 if (!CreateTable(db, kOfflinePagesTable)) | 116 if (!CreateOfflinePagesTable(db)) |
| 149 return false; | 117 return false; |
| 150 } | 118 } |
| 151 | 119 |
| 152 if (!db->DoesColumnExist(kOfflinePagesTable.table_name, "expiration_time")) { | 120 if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "expiration_time")) { |
| 153 if (!RefreshColumnsFrom52To54(db)) | 121 if (!RefreshColumnsFrom52To54(db)) |
| 154 return false; | 122 return false; |
| 155 } else if (!db->DoesColumnExist(kOfflinePagesTable.table_name, "title")) { | 123 } else if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "title")) { |
| 156 if (!RefreshColumnsFrom53To54(db)) | 124 if (!RefreshColumnsFrom53To54(db)) |
| 157 return false; | 125 return false; |
| 158 } | 126 } |
| 159 | 127 |
| 160 // TODO(bburns): Add indices here. | 128 // TODO(bburns): Add indices here. |
| 161 return transaction.Commit(); | 129 return transaction.Commit(); |
| 162 } | 130 } |
| 163 | 131 |
| 164 bool DeleteByOfflineId(sql::Connection* db, int64_t offline_id) { | 132 bool DeleteByOfflineId(sql::Connection* db, int64_t offline_id) { |
| 165 static const char kSql[] = | 133 static const char kSql[] = |
| 166 "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id=?"; | 134 "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id=?"; |
| 167 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 135 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 168 statement.BindInt64(0, offline_id); | 136 statement.BindInt64(0, offline_id); |
| 169 return statement.Run(); | 137 return statement.Run(); |
| 170 } | 138 } |
| 171 | 139 |
| 172 // Create an offline page item from a SQL result. Expects complete rows with | 140 // Create an offline page item from a SQL result. Expects complete rows with |
| 173 // all columns present. | 141 // all columns present. |
| 174 OfflinePageItem MakeOfflinePageItem(sql::Statement* statement) { | 142 OfflinePageItem MakeOfflinePageItem(sql::Statement* statement) { |
| 175 int64_t id = statement->ColumnInt64(OP_OFFLINE_ID); | 143 int64_t id = statement->ColumnInt64(0); |
| 176 GURL url(statement->ColumnString(OP_ONLINE_URL)); | 144 base::Time creation_time = |
| 177 ClientId client_id(statement->ColumnString(OP_CLIENT_NAMESPACE), | 145 base::Time::FromInternalValue(statement->ColumnInt64(1)); |
| 178 statement->ColumnString(OP_CLIENT_ID)); | 146 int64_t file_size = statement->ColumnInt64(2); |
| 147 ClientId client_id(statement->ColumnString(9), | |
| 148 statement->ColumnString(10)); | |
| 149 GURL url(statement->ColumnString(11)); | |
| 179 #if defined(OS_POSIX) | 150 #if defined(OS_POSIX) |
| 180 base::FilePath path(statement->ColumnString(OP_FILE_PATH)); | 151 base::FilePath path(statement->ColumnString(13)); |
| 181 #elif defined(OS_WIN) | 152 #elif defined(OS_WIN) |
| 182 base::FilePath path(base::UTF8ToWide(statement->ColumnString(OP_FILE_PATH))); | 153 base::FilePath path(base::UTF8ToWide(statement->ColumnString(13))); |
| 183 #else | 154 #else |
| 184 #error Unknown OS | 155 #error Unknown OS |
| 185 #endif | 156 #endif |
| 186 int64_t file_size = statement->ColumnInt64(OP_FILE_SIZE); | |
| 187 base::Time creation_time = | |
| 188 base::Time::FromInternalValue(statement->ColumnInt64(OP_CREATION_TIME)); | |
| 189 | 157 |
| 190 OfflinePageItem item(url, id, client_id, path, file_size, creation_time); | 158 OfflinePageItem item(url, id, client_id, path, file_size, creation_time); |
| 159 item.version = statement->ColumnInt(3); | |
| 191 item.last_access_time = base::Time::FromInternalValue( | 160 item.last_access_time = base::Time::FromInternalValue( |
| 192 statement->ColumnInt64(OP_LAST_ACCESS_TIME)); | 161 statement->ColumnInt64(4)); |
| 193 item.version = statement->ColumnInt(OP_VERSION); | 162 item.access_count = statement->ColumnInt(5); |
| 194 item.access_count = statement->ColumnInt(OP_ACCESS_COUNT); | |
| 195 item.expiration_time = | 163 item.expiration_time = |
| 196 base::Time::FromInternalValue(statement->ColumnInt64(OP_EXPIRATION_TIME)); | 164 base::Time::FromInternalValue(statement->ColumnInt64(8)); |
| 197 item.title = statement->ColumnString16(OP_TITLE); | 165 item.title = statement->ColumnString16(14); |
| 198 return item; | 166 return item; |
| 199 } | 167 } |
| 200 | 168 |
| 201 bool InsertOrReplace(sql::Connection* db, const OfflinePageItem& item) { | 169 bool InsertOrReplace(sql::Connection* db, const OfflinePageItem& item) { |
| 202 const char kSql[] = | 170 const char kSql[] = |
| 203 "INSERT OR REPLACE INTO " OFFLINE_PAGES_TABLE_NAME | 171 "INSERT OR REPLACE INTO " OFFLINE_PAGES_TABLE_NAME |
| 204 " (offline_id, online_url, client_namespace, client_id, file_path, " | 172 " (offline_id, online_url, client_namespace, client_id, file_path, " |
| 205 "file_size, creation_time, last_access_time, version, access_count, " | 173 "file_size, creation_time, last_access_time, version, access_count, " |
| 206 "expiration_time, title)" | 174 "expiration_time, title)" |
| 207 " VALUES " | 175 " VALUES " |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 DCHECK(db_.get()); | 427 DCHECK(db_.get()); |
| 460 if (!db_.get()) { | 428 if (!db_.get()) { |
| 461 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | 429 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 462 base::Bind(callback)); | 430 base::Bind(callback)); |
| 463 return false; | 431 return false; |
| 464 } | 432 } |
| 465 return true; | 433 return true; |
| 466 } | 434 } |
| 467 | 435 |
| 468 } // namespace offline_pages | 436 } // namespace offline_pages |
| OLD | NEW |