Chromium Code Reviews| 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..8eea517f2c4aad0c45c0ebcd1a47c151925f95b7 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,9 +175,12 @@ 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); |
| + info.state = IntToState(statement.ColumnInt(6)); |
| info.end_time = base::Time::FromTimeT(statement.ColumnInt64(7)); |
| info.opened = statement.ColumnInt(8) != 0; |
| + if (info.state == DownloadItem::MAX_DOWNLOAD_STATE) { |
| + continue; |
|
Randy Smith (Not in Mondays)
2012/08/07 20:36:16
UMA? (You're welcome to say not in this CL, but I
sky
2012/08/07 20:54:17
Why add this? At best we do a DCHECK for this sort
asanka
2012/08/07 20:56:14
If you skip this early, wouldn't you risk not upda
Randy Smith (Not in Mondays)
2012/08/07 21:01:35
The basic problem is that almost any sanitization
benjhayden
2012/08/08 01:11:52
This layer of abstraction separates the compiler-g
benjhayden
2012/08/08 01:11:52
Done.
benjhayden
2012/08/08 01:11:52
Done.
benjhayden
2012/08/08 01:11:52
This isn't just sanitization. It's a mapping, a la
Randy Smith (Not in Mondays)
2012/08/08 01:52:25
Good point. Ok.
|
| + } |
| results->push_back(info); |
| if (info.db_handle >= next_db_handle_) |
| next_db_handle_ = info.db_handle + 1; |
| @@ -147,11 +195,14 @@ void DownloadDatabase::QueryDownloads( |
| bool DownloadDatabase::UpdateDownload(const DownloadPersistentStoreInfo& data) { |
| CheckThread(); |
| DCHECK(data.db_handle > 0); |
| + int state = StateToInt(data.state); |
| + if (state == kStateInvalid) |
| + return false; |
|
Randy Smith (Not in Mondays)
2012/08/07 20:36:16
DCHECK? If we get an invalid state here, it means
benjhayden
2012/08/08 01:11:52
Is it possible for UpdateDownload to see a downloa
Randy Smith (Not in Mondays)
2012/08/08 01:52:25
Not sure enough for this CL :-} :-|.
|
| 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 +226,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 +244,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 +262,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 +300,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 +320,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(); |
| } |