| Index: chrome/browser/history/download_database.cc | 
| diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc | 
| index 0f8dca6af414c710ad7aa1e9b14a97950140bec7..6ce94890bed26dfa73271770781eadcfc6d204fd 100644 | 
| --- a/chrome/browser/history/download_database.cc | 
| +++ b/chrome/browser/history/download_database.cc | 
| @@ -16,7 +16,7 @@ | 
|  | 
| // Download schema: | 
| // | 
| -//   id             SQLite-generated primary key. | 
| +//   pid            DownloadPrefs-generated unique persistent identifier. | 
| //   full_path      Location of the download on disk. | 
| //   url            URL of the downloaded file. | 
| //   start_time     When the download was started. | 
| @@ -61,77 +61,136 @@ DownloadDatabase::~DownloadDatabase() { | 
| } | 
|  | 
| bool DownloadDatabase::InitDownloadTable() { | 
| -  if (!GetDB().DoesTableExist("downloads")) { | 
| -    if (!GetDB().Execute( | 
| +  return GetDB().DoesTableExist("downloads") || | 
| +         GetDB().Execute( | 
| "CREATE TABLE downloads (" | 
| -        "id INTEGER PRIMARY KEY," | 
| +        "pid INTEGER PRIMARY KEY," | 
| "full_path LONGVARCHAR NOT NULL," | 
| "url LONGVARCHAR NOT NULL," | 
| "start_time INTEGER NOT NULL," | 
| "received_bytes INTEGER NOT NULL," | 
| "total_bytes INTEGER NOT NULL," | 
| -        "state INTEGER NOT NULL)")) | 
| -      return false; | 
| -  } | 
| -  return true; | 
| +        "state INTEGER NOT NULL)"); | 
| } | 
|  | 
| bool DownloadDatabase::DropDownloadTable() { | 
| return GetDB().Execute("DROP TABLE downloads"); | 
| } | 
|  | 
| -void DownloadDatabase::QueryDownloads( | 
| -    std::vector<DownloadHistoryInfo>* results) { | 
| -  results->clear(); | 
| +bool DownloadDatabase::MaybeUpgradeTable( | 
| +    DownloadQueryParameters::GetNextIdThunk get_next_id) { | 
| +  static const char kNoPidColumnError[] = "no such column: pid"; | 
| +  sql::Statement have_pid(GetDB().GetUniqueStatement( | 
| +      "SELECT pid FROM downloads")); | 
| +  if (!have_pid && | 
| +      (std::string(GetDB().GetErrorMessage()) == std::string(kNoPidColumnError))) { | 
| +    CHECK(!get_next_id.is_null()); | 
| +    std::vector<DownloadHistoryInfo> infos; | 
| +    sql::Statement get_infos(GetDB().GetUniqueStatement( | 
| +        "SELECT full_path, url, start_time, received_bytes, " | 
| +        "total_bytes, state FROM downloads")); | 
| +    if (!get_infos) { | 
| +      return false; | 
| +    } | 
| +    while (get_infos.Step()) { | 
| +      infos.push_back(DownloadHistoryInfo( | 
| +          ColumnFilePath(get_infos, 1)/*path*/, | 
| +          GURL(get_infos.ColumnString(2))/*url*/, | 
| +          GURL("")/*referrer*/, | 
| +          base::Time::FromTimeT(get_infos.ColumnInt64(3))/*start*/, | 
| +          get_infos.ColumnInt64(4)/*received*/, | 
| +          get_infos.ColumnInt64(5)/*total*/, | 
| +          get_infos.ColumnInt(6)/*state*/, | 
| +          get_next_id.Run()/*id*/)); | 
| +    } | 
| +    if (!DropDownloadTable()) { | 
| +      return false; | 
| +    } | 
| +    if (!InitDownloadTable()) { | 
| +      return false; | 
| +    } | 
| +    for (std::vector<DownloadHistoryInfo>::const_iterator iter = infos.begin(); | 
| +         iter != infos.end(); ++iter) { | 
| +      sql::Statement reinsert(GetDB().GetCachedStatement(SQL_FROM_HERE, | 
| +          "INSERT INTO downloads (pid, full_path, url, start_time, " | 
| +          "received_bytes, total_bytes, state) VALUES (?, ?, ?, ?, ?, ?, ?)")); | 
| +      if (!reinsert) { | 
| +        return false; | 
| +      } | 
| +      reinsert.BindInt(0, iter->id); | 
| +      BindFilePath(reinsert, iter->path, 1); | 
| +      reinsert.BindString(2, iter->url.spec()); | 
| +      reinsert.BindInt64(3, iter->start_time.ToTimeT()); | 
| +      reinsert.BindInt64(4, iter->received_bytes); | 
| +      reinsert.BindInt64(5, iter->total_bytes); | 
| +      reinsert.BindInt(6, iter->state); | 
| +      if (!reinsert.Run()) { | 
| +        return false; | 
| +      } | 
| +    } | 
| +    sql::Statement have_pid2(GetDB().GetUniqueStatement( | 
| +          "SELECT pid FROM downloads")); | 
| +    if (!have_pid2) { | 
| +      return false; | 
| +    } | 
| +  } | 
| +  return true; | 
| +} | 
| + | 
| +void DownloadDatabase::QueryDownloads(DownloadQueryParameters* params) { | 
| +  params->results.clear(); | 
| +  if (!MaybeUpgradeTable(params->get_next_id)) { | 
| +    return; | 
| +  } | 
|  | 
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 
| -      "SELECT id, full_path, url, start_time, received_bytes, " | 
| +      "SELECT pid, full_path, url, start_time, received_bytes, " | 
| "total_bytes, state " | 
| "FROM downloads " | 
| "ORDER BY start_time")); | 
| -  if (!statement) | 
| +  if (!statement) { | 
| return; | 
| +  } | 
|  | 
| while (statement.Step()) { | 
| -    DownloadHistoryInfo info; | 
| -    info.db_handle = statement.ColumnInt64(0); | 
| - | 
| -    info.path = ColumnFilePath(statement, 1); | 
| -    info.url = GURL(statement.ColumnString(2)); | 
| -    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); | 
| -    results->push_back(info); | 
| +    params->results.push_back(DownloadHistoryInfo( | 
| +        ColumnFilePath(statement, 1)/*path*/, | 
| +        GURL(statement.ColumnString(2))/*url*/, | 
| +        GURL("")/*referrer*/, | 
| +        base::Time::FromTimeT(statement.ColumnInt64(3))/*start*/, | 
| +        statement.ColumnInt64(4)/*received*/, | 
| +        statement.ColumnInt64(5)/*total*/, | 
| +        statement.ColumnInt(6)/*state*/, | 
| +        statement.ColumnInt64(0)/*id*/)); | 
| } | 
| } | 
|  | 
| bool DownloadDatabase::UpdateDownload(int64 received_bytes, | 
| int32 state, | 
| -                                      DownloadID db_handle) { | 
| -  DCHECK(db_handle > 0); | 
| +                                      DownloadID id) { | 
| +  DCHECK(id >= 0) << id; | 
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 
| "UPDATE downloads " | 
| -      "SET received_bytes=?, state=? WHERE id=?")); | 
| +      "SET received_bytes=?, state=? WHERE pid=?")); | 
| if (!statement) | 
| return false; | 
|  | 
| statement.BindInt64(0, received_bytes); | 
| statement.BindInt(1, state); | 
| -  statement.BindInt64(2, db_handle); | 
| +  statement.BindInt64(2, id); | 
| return statement.Run(); | 
| } | 
|  | 
| bool DownloadDatabase::UpdateDownloadPath(const FilePath& path, | 
| -                                          DownloadID db_handle) { | 
| -  DCHECK(db_handle > 0); | 
| +                                          DownloadID id) { | 
| +  DCHECK(id >= 0); | 
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 
| -      "UPDATE downloads SET full_path=? WHERE id=?")); | 
| +      "UPDATE downloads SET full_path=? WHERE pid=?")); | 
| if (!statement) | 
| return false; | 
|  | 
| BindFilePath(statement, path, 0); | 
| -  statement.BindInt64(1, db_handle); | 
| +  statement.BindInt64(1, id); | 
| return statement.Run(); | 
| } | 
|  | 
| @@ -145,33 +204,32 @@ bool DownloadDatabase::CleanUpInProgressEntries() { | 
| return statement.Run(); | 
| } | 
|  | 
| -int64 DownloadDatabase::CreateDownload(const DownloadHistoryInfo& info) { | 
| +bool DownloadDatabase::CreateDownload(const DownloadHistoryInfo& info) { | 
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 
| "INSERT INTO downloads " | 
| -      "(full_path, url, start_time, received_bytes, total_bytes, state) " | 
| -      "VALUES (?, ?, ?, ?, ?, ?)")); | 
| +      "(pid, full_path, url, start_time, received_bytes, total_bytes, state) " | 
| +      "VALUES (?, ?, ?, ?, ?, ?, ?)")); | 
| if (!statement) | 
| -    return 0; | 
| +    return false; | 
|  | 
| -  BindFilePath(statement, info.path, 0); | 
| -  statement.BindString(1, info.url.spec()); | 
| -  statement.BindInt64(2, info.start_time.ToTimeT()); | 
| -  statement.BindInt64(3, info.received_bytes); | 
| -  statement.BindInt64(4, info.total_bytes); | 
| -  statement.BindInt(5, info.state); | 
| +  statement.BindInt(0, info.id); | 
| +  BindFilePath(statement, info.path, 1); | 
| +  statement.BindString(2, info.url.spec()); | 
| +  statement.BindInt64(3, info.start_time.ToTimeT()); | 
| +  statement.BindInt64(4, info.received_bytes); | 
| +  statement.BindInt64(5, info.total_bytes); | 
| +  statement.BindInt(6, info.state); | 
|  | 
| -  if (statement.Run()) | 
| -    return GetDB().GetLastInsertRowId(); | 
| -  return 0; | 
| +  return statement.Run(); | 
| } | 
|  | 
| -void DownloadDatabase::RemoveDownload(DownloadID db_handle) { | 
| +void DownloadDatabase::RemoveDownload(DownloadID id) { | 
| sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 
| -      "DELETE FROM downloads WHERE id=?")); | 
| +      "DELETE FROM downloads WHERE pid=?")); | 
| if (!statement) | 
| return; | 
|  | 
| -  statement.BindInt64(0, db_handle); | 
| +  statement.BindInt64(0, id); | 
| statement.Run(); | 
| } | 
|  | 
|  |