Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: components/history/core/browser/download_database.cc

Issue 1870223002: [Downloads/History] Comply with RFC 4122 when generating GUIDs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add a comment explaining previous GUID generation scheme and why no migration is necessary. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | components/history/core/browser/history_backend_db_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | components/history/core/browser/history_backend_db_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698