| Index: chrome/browser/history/download_database.cc
|
| diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc
|
| index 5039e186765eb606500d8cd6f5e8715703a1a14f..c0769df9291cc34be8742e775dabf5ba8f5c09b5 100644
|
| --- a/chrome/browser/history/download_database.cc
|
| +++ b/chrome/browser/history/download_database.cc
|
| @@ -38,6 +38,43 @@ static const char kSchema[] =
|
| "end_time INTEGER NOT NULL," // When the download completed.
|
| "opened INTEGER NOT NULL)"; // 1 if it has ever been opened else 0
|
|
|
| +// These constants and next two functions are used to allow
|
| +// DownloadItem::DownloadState to change without breaking the database schema.
|
| +// They guarantee that the values of the |state| field in the database are one
|
| +// of the values returned by StateToInt, and that the values of the |state|
|
| +// field of the DownloadPersistentStoreInfos returned by QueryDownloads() are
|
| +// one of the values returned by IntToState().
|
| +static const int kStateInvalid = -1;
|
| +static const int kStateInProgress = 0;
|
| +static const int kStateComplete = 1;
|
| +static const int kStateCancelled = 2;
|
| +static const int kStateBug140687 = 3;
|
| +static const int kStateInterrupted = 4;
|
| +
|
| +int StateToInt(DownloadItem::DownloadState state) {
|
| + switch (state) {
|
| + case DownloadItem::IN_PROGRESS: return kStateInProgress;
|
| + case DownloadItem::COMPLETE: return kStateComplete;
|
| + case DownloadItem::CANCELLED: return kStateCancelled;
|
| + case DownloadItem::REMOVING: return kStateInvalid;
|
| + case DownloadItem::INTERRUPTED: return kStateInterrupted;
|
| + case DownloadItem::MAX_DOWNLOAD_STATE: return kStateInvalid;
|
| + default: return kStateInvalid;
|
| + }
|
| +}
|
| +
|
| +DownloadItem::DownloadState IntToState(int state) {
|
| + switch (state) {
|
| + case kStateInProgress: return DownloadItem::IN_PROGRESS;
|
| + case kStateComplete: return DownloadItem::COMPLETE;
|
| + case kStateCancelled: return DownloadItem::CANCELLED;
|
| + // We should not need kStateBug140687 here because MigrateDownloadState()
|
| + // is called in HistoryDatabase::Init().
|
| + case kStateInterrupted: return DownloadItem::INTERRUPTED;
|
| + default: return DownloadItem::MAX_DOWNLOAD_STATE;
|
| + }
|
| +}
|
| +
|
| #if defined(OS_POSIX)
|
|
|
| // Binds/reads the given file path to the given column of the given statement.
|
| @@ -92,6 +129,14 @@ bool DownloadDatabase::EnsureColumnExists(
|
| GetDB().Execute(add_col.c_str());
|
| }
|
|
|
| +bool DownloadDatabase::MigrateDownloadsState() {
|
| + sql::Statement statement(GetDB().GetUniqueStatement(
|
| + "UPDATE downloads SET state=? WHERE state=?"));
|
| + statement.BindInt(0, kStateInterrupted);
|
| + statement.BindInt(1, kStateBug140687);
|
| + return statement.Run();
|
| +}
|
| +
|
| bool DownloadDatabase::InitDownloadTable() {
|
| CheckThread();
|
| GetMetaTable().GetValue(kNextDownloadId, &next_id_);
|
| @@ -130,10 +175,10 @@ void DownloadDatabase::QueryDownloads(
|
| info.start_time = base::Time::FromTimeT(statement.ColumnInt64(3));
|
| info.received_bytes = statement.ColumnInt64(4);
|
| info.total_bytes = statement.ColumnInt64(5);
|
| - info.state = statement.ColumnInt(6);
|
| + int state = statement.ColumnInt(6);
|
| + info.state = IntToState(state);
|
| info.end_time = base::Time::FromTimeT(statement.ColumnInt64(7));
|
| info.opened = statement.ColumnInt(8) != 0;
|
| - results->push_back(info);
|
| if (info.db_handle >= next_db_handle_)
|
| next_db_handle_ = info.db_handle + 1;
|
| if (!db_handles.insert(info.db_handle).second) {
|
| @@ -141,17 +186,27 @@ void DownloadDatabase::QueryDownloads(
|
| base::debug::Alias(&info.db_handle);
|
| DCHECK(false);
|
| }
|
| + if (info.state == DownloadItem::MAX_DOWNLOAD_STATE) {
|
| + UMA_HISTOGRAM_COUNTS("Download.DatabaseInvalidState", state);
|
| + continue;
|
| + }
|
| + results->push_back(info);
|
| }
|
| }
|
|
|
| bool DownloadDatabase::UpdateDownload(const DownloadPersistentStoreInfo& data) {
|
| CheckThread();
|
| DCHECK(data.db_handle > 0);
|
| + int state = StateToInt(data.state);
|
| + if (state == kStateInvalid) {
|
| + // TODO(benjhayden) [D]CHECK instead.
|
| + return false;
|
| + }
|
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| "UPDATE downloads "
|
| "SET received_bytes=?, state=?, end_time=?, opened=? WHERE id=?"));
|
| statement.BindInt64(0, data.received_bytes);
|
| - statement.BindInt(1, data.state);
|
| + statement.BindInt(1, state);
|
| statement.BindInt64(2, data.end_time.ToTimeT());
|
| statement.BindInt(3, (data.opened ? 1 : 0));
|
| statement.BindInt64(4, data.db_handle);
|
| @@ -175,8 +230,8 @@ bool DownloadDatabase::CleanUpInProgressEntries() {
|
| CheckThread();
|
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| "UPDATE downloads SET state=? WHERE state=?"));
|
| - statement.BindInt(0, DownloadItem::CANCELLED);
|
| - statement.BindInt(1, DownloadItem::IN_PROGRESS);
|
| + statement.BindInt(0, kStateCancelled);
|
| + statement.BindInt(1, kStateInProgress);
|
|
|
| return statement.Run();
|
| }
|
| @@ -193,6 +248,10 @@ int64 DownloadDatabase::CreateDownload(
|
| CHECK_NE(0, next_db_handle_);
|
| }
|
|
|
| + int state = StateToInt(info.state);
|
| + if (state == kStateInvalid)
|
| + return false;
|
| +
|
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| "INSERT INTO downloads "
|
| "(id, full_path, url, start_time, received_bytes, total_bytes, state, "
|
| @@ -207,7 +266,7 @@ int64 DownloadDatabase::CreateDownload(
|
| statement.BindInt64(3, info.start_time.ToTimeT());
|
| statement.BindInt64(4, info.received_bytes);
|
| statement.BindInt64(5, info.total_bytes);
|
| - statement.BindInt(6, info.state);
|
| + statement.BindInt(6, state);
|
| statement.BindInt64(7, info.end_time.ToTimeT());
|
| statement.BindInt(8, info.opened ? 1 : 0);
|
|
|
| @@ -245,9 +304,9 @@ bool DownloadDatabase::RemoveDownloadsBetween(base::Time delete_begin,
|
| count.BindInt64(
|
| 1,
|
| end_time ? end_time : std::numeric_limits<int64>::max());
|
| - count.BindInt(2, DownloadItem::COMPLETE);
|
| - count.BindInt(3, DownloadItem::CANCELLED);
|
| - count.BindInt(4, DownloadItem::INTERRUPTED);
|
| + count.BindInt(2, kStateComplete);
|
| + count.BindInt(3, kStateCancelled);
|
| + count.BindInt(4, kStateInterrupted);
|
| if (count.Step())
|
| num_downloads_deleted = count.ColumnInt(0);
|
| }
|
| @@ -265,9 +324,9 @@ bool DownloadDatabase::RemoveDownloadsBetween(base::Time delete_begin,
|
| statement.BindInt64(
|
| 1,
|
| end_time ? end_time : std::numeric_limits<int64>::max());
|
| - statement.BindInt(2, DownloadItem::COMPLETE);
|
| - statement.BindInt(3, DownloadItem::CANCELLED);
|
| - statement.BindInt(4, DownloadItem::INTERRUPTED);
|
| + statement.BindInt(2, kStateComplete);
|
| + statement.BindInt(3, kStateCancelled);
|
| + statement.BindInt(4, kStateInterrupted);
|
|
|
| success = statement.Run();
|
| }
|
|
|