Add the referrer url to the downloads table in the History database.

Review URL: https://chromiumcodereview.appspot.com/17397003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207933 0039d316-1c4b-4281-b951-d872f2087c98
parent 04af4991
...@@ -37,18 +37,19 @@ enum DroppedReason { ...@@ -37,18 +37,19 @@ enum DroppedReason {
}; };
static const char kSchema[] = static const char kSchema[] =
"CREATE TABLE downloads (" "CREATE TABLE downloads ("
"id INTEGER PRIMARY KEY," // Primary key. "id INTEGER PRIMARY KEY," // Primary key.
"current_path LONGVARCHAR NOT NULL," // Current disk location of the download "current_path LONGVARCHAR NOT NULL," // Current disk location
"target_path LONGVARCHAR NOT NULL," // Final disk location of the download "target_path LONGVARCHAR NOT NULL," // Final disk location
"start_time INTEGER NOT NULL," // When the download was started. "start_time INTEGER NOT NULL," // When the download was started.
"received_bytes INTEGER NOT NULL," // Total size downloaded. "received_bytes INTEGER NOT NULL," // Total size downloaded.
"total_bytes INTEGER NOT NULL," // Total size of the download. "total_bytes INTEGER NOT NULL," // Total size of the download.
"state INTEGER NOT NULL," // 1=complete, 4=interrupted "state INTEGER NOT NULL," // 1=complete, 4=interrupted
"danger_type INTEGER NOT NULL, " // Not dangerous, danger type, validated. "danger_type INTEGER NOT NULL, " // Not dangerous, danger type, validated.
"interrupt_reason INTEGER NOT NULL," // Reason the download was interrupted. "interrupt_reason INTEGER NOT NULL,"
"end_time INTEGER NOT NULL," // When the download completed. "end_time INTEGER NOT NULL," // When the download completed.
"opened INTEGER NOT NULL)"; // 1 if it has ever been opened else 0 "opened INTEGER NOT NULL," // 1 if it has ever been opened else 0
"referrer VARCHAR NOT NULL)"; // HTTP Referrer
static const char kUrlChainSchema[] = static const char kUrlChainSchema[] =
"CREATE TABLE downloads_url_chains (" "CREATE TABLE downloads_url_chains ("
...@@ -234,7 +235,7 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() { ...@@ -234,7 +235,7 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() {
sql::Statement statement_populate(GetDB().GetUniqueStatement( sql::Statement statement_populate(GetDB().GetUniqueStatement(
"INSERT INTO downloads " "INSERT INTO downloads "
"( id, current_path, target_path, start_time, received_bytes, total_bytes, " "( id, current_path, target_path, start_time, received_bytes, total_bytes, "
" state, danger_type, interrupt_reason, end_time, opened ) " " state, danger_type, interrupt_reason, end_time, opened, referrer ) "
"SELECT id, full_path, full_path, " "SELECT id, full_path, full_path, "
" CASE start_time WHEN 0 THEN 0 ELSE " " CASE start_time WHEN 0 THEN 0 ELSE "
" (start_time + 11644473600) * 1000000 END, " " (start_time + 11644473600) * 1000000 END, "
...@@ -242,7 +243,7 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() { ...@@ -242,7 +243,7 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() {
" state, ?, ?, " " state, ?, ?, "
" CASE end_time WHEN 0 THEN 0 ELSE " " CASE end_time WHEN 0 THEN 0 ELSE "
" (end_time + 11644473600) * 1000000 END, " " (end_time + 11644473600) * 1000000 END, "
" opened " " opened, \"\" "
"FROM downloads_tmp")); "FROM downloads_tmp"));
statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE); statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE);
statement_populate.BindInt(1, kDangerTypeNotDangerous); statement_populate.BindInt(1, kDangerTypeNotDangerous);
...@@ -265,6 +266,10 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() { ...@@ -265,6 +266,10 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() {
return true; return true;
} }
bool DownloadDatabase::MigrateReferrer() {
return EnsureColumnExists("referrer", "VARCHAR NOT NULL DEFAULT \"\"");
}
bool DownloadDatabase::InitDownloadTable() { bool DownloadDatabase::InitDownloadTable() {
GetMetaTable().GetValue(kNextDownloadId, &next_id_); GetMetaTable().GetValue(kNextDownloadId, &next_id_);
if (GetDB().DoesTableExist("downloads")) { if (GetDB().DoesTableExist("downloads")) {
...@@ -295,9 +300,9 @@ void DownloadDatabase::QueryDownloads( ...@@ -295,9 +300,9 @@ void DownloadDatabase::QueryDownloads(
sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE, sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE,
"SELECT id, current_path, target_path, start_time, received_bytes, " "SELECT id, current_path, target_path, start_time, received_bytes, "
"total_bytes, state, danger_type, interrupt_reason, end_time, opened " "total_bytes, state, danger_type, interrupt_reason, end_time, opened, "
"FROM downloads " "referrer "
"ORDER BY start_time")); "FROM downloads ORDER BY start_time"));
while (statement_main.Step()) { while (statement_main.Step()) {
scoped_ptr<DownloadRow> info(new DownloadRow()); scoped_ptr<DownloadRow> info(new DownloadRow());
...@@ -321,6 +326,7 @@ void DownloadDatabase::QueryDownloads( ...@@ -321,6 +326,7 @@ void DownloadDatabase::QueryDownloads(
info->end_time = base::Time::FromInternalValue( info->end_time = base::Time::FromInternalValue(
statement_main.ColumnInt64(column++)); statement_main.ColumnInt64(column++));
info->opened = statement_main.ColumnInt(column++) != 0; info->opened = statement_main.ColumnInt(column++) != 0;
info->referrer_url = GURL(statement_main.ColumnString(column++));
if (info->db_handle >= next_db_handle_) if (info->db_handle >= next_db_handle_)
next_db_handle_ = info->db_handle + 1; next_db_handle_ = info->db_handle + 1;
if (!db_handles.insert(info->db_handle).second) { if (!db_handles.insert(info->db_handle).second) {
...@@ -482,8 +488,8 @@ int64 DownloadDatabase::CreateDownload(const DownloadRow& info) { ...@@ -482,8 +488,8 @@ int64 DownloadDatabase::CreateDownload(const DownloadRow& info) {
"INSERT INTO downloads " "INSERT INTO downloads "
"(id, current_path, target_path, start_time, " "(id, current_path, target_path, start_time, "
" received_bytes, total_bytes, state, danger_type, interrupt_reason, " " received_bytes, total_bytes, state, danger_type, interrupt_reason, "
" end_time, opened) " " end_time, opened, referrer) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
int column = 0; int column = 0;
statement_insert.BindInt64(column++, db_handle); statement_insert.BindInt64(column++, db_handle);
...@@ -497,6 +503,7 @@ int64 DownloadDatabase::CreateDownload(const DownloadRow& info) { ...@@ -497,6 +503,7 @@ int64 DownloadDatabase::CreateDownload(const DownloadRow& info) {
statement_insert.BindInt(column++, info.interrupt_reason); statement_insert.BindInt(column++, info.interrupt_reason);
statement_insert.BindInt64(column++, info.end_time.ToInternalValue()); statement_insert.BindInt64(column++, info.end_time.ToInternalValue());
statement_insert.BindInt(column++, info.opened ? 1 : 0); statement_insert.BindInt(column++, info.opened ? 1 : 0);
statement_insert.BindString(column++, info.referrer_url.spec());
if (!statement_insert.Run()) { if (!statement_insert.Run()) {
// GetErrorCode() returns a bitmask where the lower byte is a more general // GetErrorCode() returns a bitmask where the lower byte is a more general
// code and the upper byte is a more specific code. In order to save // code and the upper byte is a more specific code. In order to save
......
...@@ -67,6 +67,10 @@ class DownloadDatabase { ...@@ -67,6 +67,10 @@ class DownloadDatabase {
// two target paths to downloads. // two target paths to downloads.
bool MigrateDownloadsReasonPathsAndDangerType(); bool MigrateDownloadsReasonPathsAndDangerType();
// Returns true if able to successfully add the referrer column to the
// downloads table.
bool MigrateReferrer();
// Creates the downloads table if needed. // Creates the downloads table if needed.
bool InitDownloadTable(); bool InitDownloadTable();
......
...@@ -27,7 +27,7 @@ namespace { ...@@ -27,7 +27,7 @@ namespace {
// Current version number. We write databases at the "current" version number, // Current version number. We write databases at the "current" version number,
// but any previous version that can read the "compatible" one can make do with // but any previous version that can read the "compatible" one can make do with
// or database without *too* many bad effects. // or database without *too* many bad effects.
static const int kCurrentVersionNumber = 25; static const int kCurrentVersionNumber = 26;
static const int kCompatibleVersionNumber = 16; static const int kCompatibleVersionNumber = 16;
static const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold"; static const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
...@@ -418,6 +418,15 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() { ...@@ -418,6 +418,15 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
meta_table_.SetVersionNumber(cur_version); meta_table_.SetVersionNumber(cur_version);
} }
if (cur_version == 25) {
if (!MigrateReferrer()) {
LOG(WARNING) << "Unable to migrate history to version 26";
return sql::INIT_FAILURE;
}
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
// When the version is too old, we just try to continue anyway, there should // When the version is too old, we just try to continue anyway, there should
// not be a released product that makes a database too old for us to handle. // not be a released product that makes a database too old for us to handle.
LOG_IF(WARNING, cur_version < GetCurrentVersion()) << LOG_IF(WARNING, cur_version < GetCurrentVersion()) <<
......
...@@ -165,10 +165,10 @@ class HistoryBackendDBTest : public HistoryUnitTestBase { ...@@ -165,10 +165,10 @@ class HistoryBackendDBTest : public HistoryUnitTestBase {
std::vector<GURL> url_chain; std::vector<GURL> url_chain;
url_chain.push_back(GURL("foo-url")); url_chain.push_back(GURL("foo-url"));
DownloadRow download(base::FilePath(FILE_PATH_LITERAL("foo-path")), DownloadRow download(base::FilePath(FILE_PATH_LITERAL("current-path")),
base::FilePath(FILE_PATH_LITERAL("foo-path")), base::FilePath(FILE_PATH_LITERAL("target-path")),
url_chain, url_chain,
GURL(std::string()), GURL("http://referrer.com/"),
time, time,
time, time,
0, 0,
...@@ -177,7 +177,7 @@ class HistoryBackendDBTest : public HistoryUnitTestBase { ...@@ -177,7 +177,7 @@ class HistoryBackendDBTest : public HistoryUnitTestBase {
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
content::DOWNLOAD_INTERRUPT_REASON_NONE, content::DOWNLOAD_INTERRUPT_REASON_NONE,
0, 0,
0); false);
return db_->CreateDownload(download); return db_->CreateDownload(download);
} }
...@@ -221,12 +221,33 @@ TEST_F(HistoryBackendDBTest, ClearBrowsingData_Downloads) { ...@@ -221,12 +221,33 @@ TEST_F(HistoryBackendDBTest, ClearBrowsingData_Downloads) {
db_->QueryDownloads(&downloads); db_->QueryDownloads(&downloads);
EXPECT_EQ(0U, downloads.size()); EXPECT_EQ(0U, downloads.size());
// Add a download, test that it was added, remove it, test that it was // Add a download, test that it was added correctly, remove it, test that it
// removed. // was removed.
DownloadID handle; DownloadID handle;
EXPECT_NE(0, handle = AddDownload(DownloadItem::COMPLETE, Time())); Time now = Time();
EXPECT_NE(0, handle = AddDownload(DownloadItem::COMPLETE, now));
db_->QueryDownloads(&downloads); db_->QueryDownloads(&downloads);
EXPECT_EQ(1U, downloads.size()); EXPECT_EQ(1U, downloads.size());
EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("current-path")),
downloads[0].current_path);
EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("target-path")),
downloads[0].target_path);
EXPECT_EQ(1UL, downloads[0].url_chain.size());
EXPECT_EQ(GURL("foo-url"), downloads[0].url_chain[0]);
EXPECT_EQ(std::string("http://referrer.com/"),
std::string(downloads[0].referrer_url.spec()));
EXPECT_EQ(now, downloads[0].start_time);
EXPECT_EQ(now, downloads[0].end_time);
EXPECT_EQ(0, downloads[0].received_bytes);
EXPECT_EQ(512, downloads[0].total_bytes);
EXPECT_EQ(DownloadItem::COMPLETE, downloads[0].state);
EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
downloads[0].danger_type);
EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
downloads[0].interrupt_reason);
EXPECT_FALSE(downloads[0].opened);
db_->RemoveDownload(handle); db_->RemoveDownload(handle);
db_->QueryDownloads(&downloads); db_->QueryDownloads(&downloads);
EXPECT_EQ(0U, downloads.size()); EXPECT_EQ(0U, downloads.size());
...@@ -411,6 +432,54 @@ TEST_F(HistoryBackendDBTest, MigrateDownloadsReasonPathsAndDangerType) { ...@@ -411,6 +432,54 @@ TEST_F(HistoryBackendDBTest, MigrateDownloadsReasonPathsAndDangerType) {
} }
} }
TEST_F(HistoryBackendDBTest, MigrateReferrer) {
Time now(base::Time::Now());
ASSERT_NO_FATAL_FAILURE(CreateDBVersion(22));
{
sql::Connection db;
ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
sql::Statement s(db.GetUniqueStatement(
"INSERT INTO downloads (id, full_path, url, start_time, "
"received_bytes, total_bytes, state, end_time, opened) VALUES "
"(?, ?, ?, ?, ?, ?, ?, ?, ?)"));
int64 db_handle = 0;
s.BindInt64(0, ++db_handle);
s.BindString(1, "full_path");
s.BindString(2, "http://whatever.com/index.html");
s.BindInt64(3, now.ToTimeT());
s.BindInt64(4, 100);
s.BindInt64(5, 100);
s.BindInt(6, 1);
s.BindInt64(7, now.ToTimeT());
s.BindInt(8, 1);
ASSERT_TRUE(s.Run());
}
// Re-open the db using the HistoryDatabase, which should migrate to version
// 26, creating the referrer column.
CreateBackendAndDatabase();
DeleteBackend();
{
// Re-open the db for manual manipulation.
sql::Connection db;
ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
// The version should have been updated.
int cur_version = HistoryDatabase::GetCurrentVersion();
ASSERT_LE(26, cur_version);
{
sql::Statement s(db.GetUniqueStatement(
"SELECT value FROM meta WHERE key = 'version'"));
EXPECT_TRUE(s.Step());
EXPECT_EQ(cur_version, s.ColumnInt(0));
}
{
sql::Statement s(db.GetUniqueStatement(
"SELECT referrer from downloads"));
EXPECT_TRUE(s.Step());
EXPECT_EQ(std::string(), s.ColumnString(0));
}
}
}
TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) { TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
// Create the DB. // Create the DB.
CreateBackendAndDatabase(); CreateBackendAndDatabase();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment