OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/history/core/browser/download_database.h" | 5 #include "components/history/core/browser/download_database.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 return EnsureColumnExists("etag", "VARCHAR NOT NULL DEFAULT \"\"") && | 185 return EnsureColumnExists("etag", "VARCHAR NOT NULL DEFAULT \"\"") && |
186 EnsureColumnExists("last_modified", "VARCHAR NOT NULL DEFAULT \"\""); | 186 EnsureColumnExists("last_modified", "VARCHAR NOT NULL DEFAULT \"\""); |
187 } | 187 } |
188 | 188 |
189 bool DownloadDatabase::MigrateHashHttpMethodAndGenerateGuids() { | 189 bool DownloadDatabase::MigrateHashHttpMethodAndGenerateGuids() { |
190 if (!EnsureColumnExists("guid", "VARCHAR NOT NULL DEFAULT ''") || | 190 if (!EnsureColumnExists("guid", "VARCHAR NOT NULL DEFAULT ''") || |
191 !EnsureColumnExists("hash", "BLOB NOT NULL DEFAULT X''") || | 191 !EnsureColumnExists("hash", "BLOB NOT NULL DEFAULT X''") || |
192 !EnsureColumnExists("http_method", "VARCHAR NOT NULL DEFAULT ''")) | 192 !EnsureColumnExists("http_method", "VARCHAR NOT NULL DEFAULT ''")) |
193 return false; | 193 return false; |
194 | 194 |
195 // Generate GUIDs for each download. The GUID is generated thusly: | 195 // Generate GUIDs for each download. GUIDs based on random data should conform |
| 196 // with RFC 4122 section 4.4. Given the following field layout (based on RFC |
| 197 // 4122): |
196 // | 198 // |
197 // XXXXXXXX-RRRR-RRRR-RRRR-RRRRRRRRRRRR | 199 // 0 1 2 3 |
| 200 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| 201 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 202 // | time_low | |
| 203 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 204 // | time_mid | time_hi_and_version | |
| 205 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 206 // |clk_seq_hi_res | clk_seq_low | node (0-1) | |
| 207 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 208 // | node (2-5) | |
| 209 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 210 // |
| 211 // * Bits 4-7 of time_hi_and_version should be set to 0b0100 == 4 |
| 212 // * Bits 6-7 of clk_seq_hi_res should be set to 0b10 |
| 213 // * All other bits should be random or pseudorandom. |
| 214 // |
| 215 // We are going to take the liberty of setting time_low to the 32-bit download |
| 216 // ID. That will guarantee that no two randomly generated GUIDs will collide |
| 217 // even if the 90 bits of entropy doesn't save us. |
| 218 // |
| 219 // Translated to the canonical string representation, the GUID is generated |
| 220 // thusly: |
| 221 // |
| 222 // XXXXXXXX-RRRR-4RRR-yRRR-RRRRRRRRRRRR |
198 // \__ __/ \___________ ____________/ | 223 // \__ __/ \___________ ____________/ |
199 // \/ \/ | 224 // \/ \/ |
200 // | Random hex digits | 225 // | R = random hex digit. |
| 226 // | y = one of {'8','9','A','B'} selected randomly. |
| 227 // | 4 = the character '4'. |
201 // | | 228 // | |
202 // Hex representation of 32-bit download ID. | 229 // Hex representation of 32-bit download ID. |
203 // | 230 // |
204 // The 96 random bits provide entropy while the 32-bits from the download ID | |
205 // ensure that the generated identifiers will at least be unique amongst the | |
206 // download rows in the unlikely event there's a collision in the 96 entropy | |
207 // bits. | |
208 // | |
209 // This GUID generation scheme is only used for migrated download rows and | 231 // This GUID generation scheme is only used for migrated download rows and |
210 // assumes that the likelihood of a collision with a GUID generated via | 232 // assumes that the likelihood of a collision with a GUID generated via |
211 // base::GenerateGUID() will be vanishingly small. | 233 // base::GenerateGUID() will be vanishingly small. |
| 234 // |
| 235 // A previous version of this code generated GUIDs that used random bits for |
| 236 // all but the first 32-bits. I.e. the scheme didn't respect the 6 fixed bits |
| 237 // as prescribed for type 4 GUIDs. The resulting GUIDs are not believed to |
| 238 // have an elevated risk of collision with GUIDs generated via |
| 239 // base::GenerateGUID() and are considered valid by all known consumers. Hence |
| 240 // no additional migration logic is being introduced to fix those GUIDs. |
212 const char kMigrateGuidsQuery[] = | 241 const char kMigrateGuidsQuery[] = |
213 "UPDATE downloads SET guid = printf" | 242 "UPDATE downloads SET guid = printf" |
214 "(\"%08X-%s-%s-%s-%s\", id, hex(randomblob(2)), hex(randomblob(2))," | 243 "(\"%08X-%s-4%s-%01X%s-%s\"," |
215 " hex(randomblob(2)), hex(randomblob(6)))"; | 244 " id," |
| 245 " hex(randomblob(2))," |
| 246 " substr(hex(randomblob(2)),2)," |
| 247 " (8 | (random() & 3))," |
| 248 " substr(hex(randomblob(2)),2)," |
| 249 " hex(randomblob(6)))"; |
216 return GetDB().Execute(kMigrateGuidsQuery); | 250 return GetDB().Execute(kMigrateGuidsQuery); |
217 } | 251 } |
218 | 252 |
219 bool DownloadDatabase::InitDownloadTable() { | 253 bool DownloadDatabase::InitDownloadTable() { |
220 const char kSchema[] = | 254 const char kSchema[] = |
221 "CREATE TABLE downloads (" | 255 "CREATE TABLE downloads (" |
222 "id INTEGER PRIMARY KEY," // Primary key. | 256 "id INTEGER PRIMARY KEY," // Primary key. |
223 "guid VARCHAR NOT NULL," // GUID. | 257 "guid VARCHAR NOT NULL," // GUID. |
224 "current_path LONGVARCHAR NOT NULL," // Current disk location | 258 "current_path LONGVARCHAR NOT NULL," // Current disk location |
225 "target_path LONGVARCHAR NOT NULL," // Final disk location | 259 "target_path LONGVARCHAR NOT NULL," // Final disk location |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 size_t DownloadDatabase::CountDownloads() { | 648 size_t DownloadDatabase::CountDownloads() { |
615 EnsureInProgressEntriesCleanedUp(); | 649 EnsureInProgressEntriesCleanedUp(); |
616 | 650 |
617 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 651 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
618 "SELECT count(*) from downloads")); | 652 "SELECT count(*) from downloads")); |
619 statement.Step(); | 653 statement.Step(); |
620 return statement.ColumnInt(0); | 654 return statement.ColumnInt(0); |
621 } | 655 } |
622 | 656 |
623 } // namespace history | 657 } // namespace history |
OLD | NEW |