| 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 "chrome/browser/history/download_database.h" | 5 #include "chrome/browser/history/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 19 matching lines...) Expand all Loading... |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 // Reason for dropping a particular record. | 32 // Reason for dropping a particular record. |
| 33 enum DroppedReason { | 33 enum DroppedReason { |
| 34 DROPPED_REASON_BAD_STATE = 0, | 34 DROPPED_REASON_BAD_STATE = 0, |
| 35 DROPPED_REASON_BAD_DANGER_TYPE = 1, | 35 DROPPED_REASON_BAD_DANGER_TYPE = 1, |
| 36 DROPPED_REASON_MAX | 36 DROPPED_REASON_MAX |
| 37 }; | 37 }; |
| 38 | 38 |
| 39 static const char kSchema[] = | 39 static const char kSchema[] = |
| 40 "CREATE TABLE downloads (" | 40 "CREATE TABLE downloads (" |
| 41 "id INTEGER PRIMARY KEY," // Primary key. | 41 "id INTEGER PRIMARY KEY," // Primary key. |
| 42 "current_path LONGVARCHAR NOT NULL," // Current disk location of the download | 42 "current_path LONGVARCHAR NOT NULL," // Current disk location |
| 43 "target_path LONGVARCHAR NOT NULL," // Final disk location of the download | 43 "target_path LONGVARCHAR NOT NULL," // Final disk location |
| 44 "start_time INTEGER NOT NULL," // When the download was started. | 44 "start_time INTEGER NOT NULL," // When the download was started. |
| 45 "received_bytes INTEGER NOT NULL," // Total size downloaded. | 45 "received_bytes INTEGER NOT NULL," // Total size downloaded. |
| 46 "total_bytes INTEGER NOT NULL," // Total size of the download. | 46 "total_bytes INTEGER NOT NULL," // Total size of the download. |
| 47 "state INTEGER NOT NULL," // 1=complete, 4=interrupted | 47 "state INTEGER NOT NULL," // 1=complete, 4=interrupted |
| 48 "danger_type INTEGER NOT NULL, " // Not dangerous, danger type, validated. | 48 "danger_type INTEGER NOT NULL, " // Not dangerous, danger type, validated. |
| 49 "interrupt_reason INTEGER NOT NULL," // Reason the download was interrupted. | 49 "interrupt_reason INTEGER NOT NULL," |
| 50 "end_time INTEGER NOT NULL," // When the download completed. | 50 "end_time INTEGER NOT NULL," // When the download completed. |
| 51 "opened INTEGER NOT NULL)"; // 1 if it has ever been opened else 0 | 51 "opened INTEGER NOT NULL," // 1 if it has ever been opened else 0 |
| 52 "referrer VARCHAR NOT NULL)"; // HTTP Referrer |
| 52 | 53 |
| 53 static const char kUrlChainSchema[] = | 54 static const char kUrlChainSchema[] = |
| 54 "CREATE TABLE downloads_url_chains (" | 55 "CREATE TABLE downloads_url_chains (" |
| 55 "id INTEGER NOT NULL," // downloads.id. | 56 "id INTEGER NOT NULL," // downloads.id. |
| 56 "chain_index INTEGER NOT NULL," // Index of url in chain | 57 "chain_index INTEGER NOT NULL," // Index of url in chain |
| 57 // 0 is initial target, | 58 // 0 is initial target, |
| 58 // MAX is target after redirects. | 59 // MAX is target after redirects. |
| 59 "url LONGVARCHAR NOT NULL, " // URL. | 60 "url LONGVARCHAR NOT NULL, " // URL. |
| 60 "PRIMARY KEY (id, chain_index) )"; | 61 "PRIMARY KEY (id, chain_index) )"; |
| 61 | 62 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 if (!GetDB().Execute(kSchema)) | 228 if (!GetDB().Execute(kSchema)) |
| 228 return false; | 229 return false; |
| 229 | 230 |
| 230 // Populate it. As we do so, we transform the time values from time_t | 231 // Populate it. As we do so, we transform the time values from time_t |
| 231 // (seconds since 1/1/1970 UTC), to our internal measure (microseconds | 232 // (seconds since 1/1/1970 UTC), to our internal measure (microseconds |
| 232 // since the Windows Epoch). Note that this is dependent on the | 233 // since the Windows Epoch). Note that this is dependent on the |
| 233 // internal representation of base::Time and needs to change if that changes. | 234 // internal representation of base::Time and needs to change if that changes. |
| 234 sql::Statement statement_populate(GetDB().GetUniqueStatement( | 235 sql::Statement statement_populate(GetDB().GetUniqueStatement( |
| 235 "INSERT INTO downloads " | 236 "INSERT INTO downloads " |
| 236 "( id, current_path, target_path, start_time, received_bytes, total_bytes, " | 237 "( id, current_path, target_path, start_time, received_bytes, total_bytes, " |
| 237 " state, danger_type, interrupt_reason, end_time, opened ) " | 238 " state, danger_type, interrupt_reason, end_time, opened, referrer ) " |
| 238 "SELECT id, full_path, full_path, " | 239 "SELECT id, full_path, full_path, " |
| 239 " CASE start_time WHEN 0 THEN 0 ELSE " | 240 " CASE start_time WHEN 0 THEN 0 ELSE " |
| 240 " (start_time + 11644473600) * 1000000 END, " | 241 " (start_time + 11644473600) * 1000000 END, " |
| 241 " received_bytes, total_bytes, " | 242 " received_bytes, total_bytes, " |
| 242 " state, ?, ?, " | 243 " state, ?, ?, " |
| 243 " CASE end_time WHEN 0 THEN 0 ELSE " | 244 " CASE end_time WHEN 0 THEN 0 ELSE " |
| 244 " (end_time + 11644473600) * 1000000 END, " | 245 " (end_time + 11644473600) * 1000000 END, " |
| 245 " opened " | 246 " opened, \"\" " |
| 246 "FROM downloads_tmp")); | 247 "FROM downloads_tmp")); |
| 247 statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE); | 248 statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE); |
| 248 statement_populate.BindInt(1, kDangerTypeNotDangerous); | 249 statement_populate.BindInt(1, kDangerTypeNotDangerous); |
| 249 if (!statement_populate.Run()) | 250 if (!statement_populate.Run()) |
| 250 return false; | 251 return false; |
| 251 | 252 |
| 252 // Create new chain table and populate it. | 253 // Create new chain table and populate it. |
| 253 if (!GetDB().Execute(kUrlChainSchema)) | 254 if (!GetDB().Execute(kUrlChainSchema)) |
| 254 return false; | 255 return false; |
| 255 | 256 |
| 256 if (!GetDB().Execute("INSERT INTO downloads_url_chains " | 257 if (!GetDB().Execute("INSERT INTO downloads_url_chains " |
| 257 " ( id, chain_index, url) " | 258 " ( id, chain_index, url) " |
| 258 " SELECT id, 0, url from downloads_tmp")) | 259 " SELECT id, 0, url from downloads_tmp")) |
| 259 return false; | 260 return false; |
| 260 | 261 |
| 261 // Get rid of temporary table. | 262 // Get rid of temporary table. |
| 262 if (!GetDB().Execute("DROP TABLE downloads_tmp")) | 263 if (!GetDB().Execute("DROP TABLE downloads_tmp")) |
| 263 return false; | 264 return false; |
| 264 | 265 |
| 265 return true; | 266 return true; |
| 266 } | 267 } |
| 267 | 268 |
| 269 bool DownloadDatabase::MigrateReferrer() { |
| 270 return EnsureColumnExists("referrer", "VARCHAR NOT NULL DEFAULT \"\""); |
| 271 } |
| 272 |
| 268 bool DownloadDatabase::InitDownloadTable() { | 273 bool DownloadDatabase::InitDownloadTable() { |
| 269 GetMetaTable().GetValue(kNextDownloadId, &next_id_); | 274 GetMetaTable().GetValue(kNextDownloadId, &next_id_); |
| 270 if (GetDB().DoesTableExist("downloads")) { | 275 if (GetDB().DoesTableExist("downloads")) { |
| 271 return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") && | 276 return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") && |
| 272 EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0"); | 277 EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0"); |
| 273 } else { | 278 } else { |
| 274 // If the "downloads" table doesn't exist, the downloads_url_chain | 279 // If the "downloads" table doesn't exist, the downloads_url_chain |
| 275 // table better not. | 280 // table better not. |
| 276 return (!GetDB().DoesTableExist("downloads_url_chain") && | 281 return (!GetDB().DoesTableExist("downloads_url_chain") && |
| 277 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema)); | 282 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 288 | 293 |
| 289 results->clear(); | 294 results->clear(); |
| 290 if (next_db_handle_ < 1) | 295 if (next_db_handle_ < 1) |
| 291 next_db_handle_ = 1; | 296 next_db_handle_ = 1; |
| 292 std::set<int64> db_handles; | 297 std::set<int64> db_handles; |
| 293 | 298 |
| 294 std::map<DownloadID, DownloadRow*> info_map; | 299 std::map<DownloadID, DownloadRow*> info_map; |
| 295 | 300 |
| 296 sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE, | 301 sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 297 "SELECT id, current_path, target_path, start_time, received_bytes, " | 302 "SELECT id, current_path, target_path, start_time, received_bytes, " |
| 298 "total_bytes, state, danger_type, interrupt_reason, end_time, opened " | 303 "total_bytes, state, danger_type, interrupt_reason, end_time, opened, " |
| 299 "FROM downloads " | 304 "referrer " |
| 300 "ORDER BY start_time")); | 305 "FROM downloads ORDER BY start_time")); |
| 301 | 306 |
| 302 while (statement_main.Step()) { | 307 while (statement_main.Step()) { |
| 303 scoped_ptr<DownloadRow> info(new DownloadRow()); | 308 scoped_ptr<DownloadRow> info(new DownloadRow()); |
| 304 int column = 0; | 309 int column = 0; |
| 305 | 310 |
| 306 int db_handle = statement_main.ColumnInt64(column++); | 311 int db_handle = statement_main.ColumnInt64(column++); |
| 307 info->db_handle = db_handle; | 312 info->db_handle = db_handle; |
| 308 info->current_path = ColumnFilePath(statement_main, column++); | 313 info->current_path = ColumnFilePath(statement_main, column++); |
| 309 info->target_path = ColumnFilePath(statement_main, column++); | 314 info->target_path = ColumnFilePath(statement_main, column++); |
| 310 info->start_time = base::Time::FromInternalValue( | 315 info->start_time = base::Time::FromInternalValue( |
| 311 statement_main.ColumnInt64(column++)); | 316 statement_main.ColumnInt64(column++)); |
| 312 info->received_bytes = statement_main.ColumnInt64(column++); | 317 info->received_bytes = statement_main.ColumnInt64(column++); |
| 313 info->total_bytes = statement_main.ColumnInt64(column++); | 318 info->total_bytes = statement_main.ColumnInt64(column++); |
| 314 int state = statement_main.ColumnInt(column++); | 319 int state = statement_main.ColumnInt(column++); |
| 315 info->state = IntToState(state); | 320 info->state = IntToState(state); |
| 316 if (info->state == DownloadItem::MAX_DOWNLOAD_STATE) | 321 if (info->state == DownloadItem::MAX_DOWNLOAD_STATE) |
| 317 UMA_HISTOGRAM_COUNTS("Download.DatabaseInvalidState", state); | 322 UMA_HISTOGRAM_COUNTS("Download.DatabaseInvalidState", state); |
| 318 info->danger_type = IntToDangerType(statement_main.ColumnInt(column++)); | 323 info->danger_type = IntToDangerType(statement_main.ColumnInt(column++)); |
| 319 info->interrupt_reason = static_cast<content::DownloadInterruptReason>( | 324 info->interrupt_reason = static_cast<content::DownloadInterruptReason>( |
| 320 statement_main.ColumnInt(column++)); | 325 statement_main.ColumnInt(column++)); |
| 321 info->end_time = base::Time::FromInternalValue( | 326 info->end_time = base::Time::FromInternalValue( |
| 322 statement_main.ColumnInt64(column++)); | 327 statement_main.ColumnInt64(column++)); |
| 323 info->opened = statement_main.ColumnInt(column++) != 0; | 328 info->opened = statement_main.ColumnInt(column++) != 0; |
| 329 info->referrer_url = GURL(statement_main.ColumnString(column++)); |
| 324 if (info->db_handle >= next_db_handle_) | 330 if (info->db_handle >= next_db_handle_) |
| 325 next_db_handle_ = info->db_handle + 1; | 331 next_db_handle_ = info->db_handle + 1; |
| 326 if (!db_handles.insert(info->db_handle).second) { | 332 if (!db_handles.insert(info->db_handle).second) { |
| 327 // info->db_handle was already in db_handles. The database is corrupt. | 333 // info->db_handle was already in db_handles. The database is corrupt. |
| 328 base::debug::Alias(&info->db_handle); | 334 base::debug::Alias(&info->db_handle); |
| 329 DCHECK(false); | 335 DCHECK(false); |
| 330 } | 336 } |
| 331 | 337 |
| 332 // If the record is corrupted, note that and drop it. | 338 // If the record is corrupted, note that and drop it. |
| 333 if (info->state == DownloadItem::MAX_DOWNLOAD_STATE || | 339 if (info->state == DownloadItem::MAX_DOWNLOAD_STATE || |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 return kUninitializedHandle; | 481 return kUninitializedHandle; |
| 476 | 482 |
| 477 int db_handle = next_db_handle_++; | 483 int db_handle = next_db_handle_++; |
| 478 | 484 |
| 479 { | 485 { |
| 480 sql::Statement statement_insert(GetDB().GetCachedStatement( | 486 sql::Statement statement_insert(GetDB().GetCachedStatement( |
| 481 SQL_FROM_HERE, | 487 SQL_FROM_HERE, |
| 482 "INSERT INTO downloads " | 488 "INSERT INTO downloads " |
| 483 "(id, current_path, target_path, start_time, " | 489 "(id, current_path, target_path, start_time, " |
| 484 " received_bytes, total_bytes, state, danger_type, interrupt_reason, " | 490 " received_bytes, total_bytes, state, danger_type, interrupt_reason, " |
| 485 " end_time, opened) " | 491 " end_time, opened, referrer) " |
| 486 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); | 492 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
| 487 | 493 |
| 488 int column = 0; | 494 int column = 0; |
| 489 statement_insert.BindInt64(column++, db_handle); | 495 statement_insert.BindInt64(column++, db_handle); |
| 490 BindFilePath(statement_insert, info.current_path, column++); | 496 BindFilePath(statement_insert, info.current_path, column++); |
| 491 BindFilePath(statement_insert, info.target_path, column++); | 497 BindFilePath(statement_insert, info.target_path, column++); |
| 492 statement_insert.BindInt64(column++, info.start_time.ToInternalValue()); | 498 statement_insert.BindInt64(column++, info.start_time.ToInternalValue()); |
| 493 statement_insert.BindInt64(column++, info.received_bytes); | 499 statement_insert.BindInt64(column++, info.received_bytes); |
| 494 statement_insert.BindInt64(column++, info.total_bytes); | 500 statement_insert.BindInt64(column++, info.total_bytes); |
| 495 statement_insert.BindInt(column++, state); | 501 statement_insert.BindInt(column++, state); |
| 496 statement_insert.BindInt(column++, danger_type); | 502 statement_insert.BindInt(column++, danger_type); |
| 497 statement_insert.BindInt(column++, info.interrupt_reason); | 503 statement_insert.BindInt(column++, info.interrupt_reason); |
| 498 statement_insert.BindInt64(column++, info.end_time.ToInternalValue()); | 504 statement_insert.BindInt64(column++, info.end_time.ToInternalValue()); |
| 499 statement_insert.BindInt(column++, info.opened ? 1 : 0); | 505 statement_insert.BindInt(column++, info.opened ? 1 : 0); |
| 506 statement_insert.BindString(column++, info.referrer_url.spec()); |
| 500 if (!statement_insert.Run()) { | 507 if (!statement_insert.Run()) { |
| 501 // GetErrorCode() returns a bitmask where the lower byte is a more general | 508 // GetErrorCode() returns a bitmask where the lower byte is a more general |
| 502 // code and the upper byte is a more specific code. In order to save | 509 // code and the upper byte is a more specific code. In order to save |
| 503 // memory, take the general code, of which there are fewer than 50. See | 510 // memory, take the general code, of which there are fewer than 50. See |
| 504 // also sql/connection.cc | 511 // also sql/connection.cc |
| 505 // http://www.sqlite.org/c3ref/c_abort_rollback.html | 512 // http://www.sqlite.org/c3ref/c_abort_rollback.html |
| 506 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainInsertError", | 513 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainInsertError", |
| 507 GetDB().GetErrorCode() & 0xff, 50); | 514 GetDB().GetErrorCode() & 0xff, 50); |
| 508 return kUninitializedHandle; | 515 return kUninitializedHandle; |
| 509 } | 516 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 int DownloadDatabase::CountDownloads() { | 582 int DownloadDatabase::CountDownloads() { |
| 576 EnsureInProgressEntriesCleanedUp(); | 583 EnsureInProgressEntriesCleanedUp(); |
| 577 | 584 |
| 578 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 585 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 579 "SELECT count(*) from downloads")); | 586 "SELECT count(*) from downloads")); |
| 580 statement.Step(); | 587 statement.Step(); |
| 581 return statement.ColumnInt(0); | 588 return statement.ColumnInt(0); |
| 582 } | 589 } |
| 583 | 590 |
| 584 } // namespace history | 591 } // namespace history |
| OLD | NEW |