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 "components/history/core/browser/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 |
11 #include "base/debug/alias.h" | 11 #include "base/debug/alias.h" |
12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
18 #include "base/time/time.h" | 18 #include "base/time/time.h" |
19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
20 #include "chrome/browser/history/download_row.h" | 20 #include "components/history/core/browser/download_constants.h" |
| 21 #include "components/history/core/browser/download_row.h" |
21 #include "components/history/core/browser/history_types.h" | 22 #include "components/history/core/browser/history_types.h" |
22 #include "content/public/browser/download_interrupt_reasons.h" | |
23 #include "content/public/browser/download_item.h" | |
24 #include "sql/statement.h" | 23 #include "sql/statement.h" |
25 | 24 |
26 using content::DownloadItem; | |
27 | |
28 namespace history { | 25 namespace history { |
29 | 26 |
30 namespace { | 27 namespace { |
31 | 28 |
32 // Reason for dropping a particular record. | 29 // Reason for dropping a particular record. |
33 enum DroppedReason { | 30 enum DroppedReason { |
34 DROPPED_REASON_BAD_STATE = 0, | 31 DROPPED_REASON_BAD_STATE = 0, |
35 DROPPED_REASON_BAD_DANGER_TYPE = 1, | 32 DROPPED_REASON_BAD_DANGER_TYPE = 1, |
36 DROPPED_REASON_BAD_ID = 2, | 33 DROPPED_REASON_BAD_ID = 2, |
37 DROPPED_REASON_DUPLICATE_ID = 3, | 34 DROPPED_REASON_DUPLICATE_ID = 3, |
38 DROPPED_REASON_MAX | 35 DROPPED_REASON_MAX |
39 }; | 36 }; |
40 | 37 |
41 #if defined(OS_POSIX) | 38 #if defined(OS_POSIX) |
42 | 39 |
43 // Binds/reads the given file path to the given column of the given statement. | 40 // Binds/reads the given file path to the given column of the given statement. |
44 void BindFilePath(sql::Statement& statement, const base::FilePath& path, | 41 void BindFilePath(sql::Statement& statement, |
| 42 const base::FilePath& path, |
45 int col) { | 43 int col) { |
46 statement.BindString(col, path.value()); | 44 statement.BindString(col, path.value()); |
47 } | 45 } |
48 base::FilePath ColumnFilePath(sql::Statement& statement, int col) { | 46 base::FilePath ColumnFilePath(sql::Statement& statement, int col) { |
49 return base::FilePath(statement.ColumnString(col)); | 47 return base::FilePath(statement.ColumnString(col)); |
50 } | 48 } |
51 | 49 |
52 #else | 50 #else |
53 | 51 |
54 // See above. | 52 // See above. |
55 void BindFilePath(sql::Statement& statement, const base::FilePath& path, | 53 void BindFilePath(sql::Statement& statement, |
| 54 const base::FilePath& path, |
56 int col) { | 55 int col) { |
57 statement.BindString16(col, path.value()); | 56 statement.BindString16(col, path.value()); |
58 } | 57 } |
59 base::FilePath ColumnFilePath(sql::Statement& statement, int col) { | 58 base::FilePath ColumnFilePath(sql::Statement& statement, int col) { |
60 return base::FilePath(statement.ColumnString16(col)); | 59 return base::FilePath(statement.ColumnString16(col)); |
61 } | 60 } |
62 | 61 |
63 #endif | 62 #endif |
64 | 63 |
65 } // namespace | 64 } // namespace |
66 | 65 |
67 // These constants and the transformation functions below are used to allow | 66 DownloadDatabase::DownloadDatabase( |
68 // DownloadItem::DownloadState and DownloadDangerType to change without | 67 DownloadInterruptReason download_interrupt_no_reason, |
69 // breaking the database schema. | 68 DownloadInterruptReason download_interrupt_crash) |
70 // They guarantee that the values of the |state| field in the database are one | |
71 // of the values returned by StateToInt, and that the values of the |state| | |
72 // field of the DownloadRows returned by QueryDownloads() are one of the values | |
73 // returned by IntToState(). | |
74 const int DownloadDatabase::kStateInvalid = -1; | |
75 const int DownloadDatabase::kStateInProgress = 0; | |
76 const int DownloadDatabase::kStateComplete = 1; | |
77 const int DownloadDatabase::kStateCancelled = 2; | |
78 const int DownloadDatabase::kStateBug140687 = 3; | |
79 const int DownloadDatabase::kStateInterrupted = 4; | |
80 | |
81 const int DownloadDatabase::kDangerTypeInvalid = -1; | |
82 const int DownloadDatabase::kDangerTypeNotDangerous = 0; | |
83 const int DownloadDatabase::kDangerTypeDangerousFile = 1; | |
84 const int DownloadDatabase::kDangerTypeDangerousUrl = 2; | |
85 const int DownloadDatabase::kDangerTypeDangerousContent = 3; | |
86 const int DownloadDatabase::kDangerTypeMaybeDangerousContent = 4; | |
87 const int DownloadDatabase::kDangerTypeUncommonContent = 5; | |
88 const int DownloadDatabase::kDangerTypeUserValidated = 6; | |
89 const int DownloadDatabase::kDangerTypeDangerousHost = 7; | |
90 const int DownloadDatabase::kDangerTypePotentiallyUnwanted = 8; | |
91 | |
92 int DownloadDatabase::StateToInt(DownloadItem::DownloadState state) { | |
93 switch (state) { | |
94 case DownloadItem::IN_PROGRESS: return DownloadDatabase::kStateInProgress; | |
95 case DownloadItem::COMPLETE: return DownloadDatabase::kStateComplete; | |
96 case DownloadItem::CANCELLED: return DownloadDatabase::kStateCancelled; | |
97 case DownloadItem::INTERRUPTED: return DownloadDatabase::kStateInterrupted; | |
98 case DownloadItem::MAX_DOWNLOAD_STATE: | |
99 NOTREACHED(); | |
100 return DownloadDatabase::kStateInvalid; | |
101 } | |
102 NOTREACHED(); | |
103 return DownloadDatabase::kStateInvalid; | |
104 } | |
105 | |
106 DownloadItem::DownloadState DownloadDatabase::IntToState(int state) { | |
107 switch (state) { | |
108 case DownloadDatabase::kStateInProgress: return DownloadItem::IN_PROGRESS; | |
109 case DownloadDatabase::kStateComplete: return DownloadItem::COMPLETE; | |
110 case DownloadDatabase::kStateCancelled: return DownloadItem::CANCELLED; | |
111 // We should not need kStateBug140687 here because MigrateDownloadsState() | |
112 // is called in HistoryDatabase::Init(). | |
113 case DownloadDatabase::kStateInterrupted: return DownloadItem::INTERRUPTED; | |
114 default: return DownloadItem::MAX_DOWNLOAD_STATE; | |
115 } | |
116 } | |
117 | |
118 int DownloadDatabase::DangerTypeToInt(content::DownloadDangerType danger_type) { | |
119 switch (danger_type) { | |
120 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: | |
121 return DownloadDatabase::kDangerTypeNotDangerous; | |
122 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: | |
123 return DownloadDatabase::kDangerTypeDangerousFile; | |
124 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: | |
125 return DownloadDatabase::kDangerTypeDangerousUrl; | |
126 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: | |
127 return DownloadDatabase::kDangerTypeDangerousContent; | |
128 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: | |
129 return DownloadDatabase::kDangerTypeMaybeDangerousContent; | |
130 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: | |
131 return DownloadDatabase::kDangerTypeUncommonContent; | |
132 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: | |
133 return DownloadDatabase::kDangerTypeUserValidated; | |
134 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: | |
135 return DownloadDatabase::kDangerTypeDangerousHost; | |
136 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: | |
137 return DownloadDatabase::kDangerTypePotentiallyUnwanted; | |
138 case content::DOWNLOAD_DANGER_TYPE_MAX: | |
139 NOTREACHED(); | |
140 return DownloadDatabase::kDangerTypeInvalid; | |
141 } | |
142 NOTREACHED(); | |
143 return DownloadDatabase::kDangerTypeInvalid; | |
144 } | |
145 | |
146 content::DownloadDangerType DownloadDatabase::IntToDangerType(int danger_type) { | |
147 switch (danger_type) { | |
148 case DownloadDatabase::kDangerTypeNotDangerous: | |
149 return content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS; | |
150 case DownloadDatabase::kDangerTypeDangerousFile: | |
151 return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; | |
152 case DownloadDatabase::kDangerTypeDangerousUrl: | |
153 return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; | |
154 case DownloadDatabase::kDangerTypeDangerousContent: | |
155 return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT; | |
156 case DownloadDatabase::kDangerTypeMaybeDangerousContent: | |
157 return content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; | |
158 case DownloadDatabase::kDangerTypeUncommonContent: | |
159 return content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT; | |
160 case DownloadDatabase::kDangerTypeUserValidated: | |
161 return content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED; | |
162 case DownloadDatabase::kDangerTypeDangerousHost: | |
163 return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST; | |
164 case DownloadDatabase::kDangerTypePotentiallyUnwanted: | |
165 return content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED; | |
166 default: | |
167 return content::DOWNLOAD_DANGER_TYPE_MAX; | |
168 } | |
169 } | |
170 | |
171 DownloadDatabase::DownloadDatabase() | |
172 : owning_thread_set_(false), | 69 : owning_thread_set_(false), |
173 owning_thread_(0), | 70 owning_thread_(0), |
174 in_progress_entry_cleanup_completed_(false) { | 71 in_progress_entry_cleanup_completed_(false), |
| 72 download_interrupt_no_reason_(download_interrupt_no_reason), |
| 73 download_interrupt_crash_(download_interrupt_crash) { |
175 } | 74 } |
176 | 75 |
177 DownloadDatabase::~DownloadDatabase() { | 76 DownloadDatabase::~DownloadDatabase() { |
178 } | 77 } |
179 | 78 |
180 bool DownloadDatabase::EnsureColumnExists( | 79 bool DownloadDatabase::EnsureColumnExists(const std::string& name, |
181 const std::string& name, const std::string& type) { | 80 const std::string& type) { |
182 std::string add_col = "ALTER TABLE downloads ADD COLUMN " + name + " " + type; | 81 std::string add_col = "ALTER TABLE downloads ADD COLUMN " + name + " " + type; |
183 return GetDB().DoesColumnExist("downloads", name.c_str()) || | 82 return GetDB().DoesColumnExist("downloads", name.c_str()) || |
184 GetDB().Execute(add_col.c_str()); | 83 GetDB().Execute(add_col.c_str()); |
185 } | 84 } |
186 | 85 |
187 bool DownloadDatabase::MigrateMimeType() { | 86 bool DownloadDatabase::MigrateMimeType() { |
188 return EnsureColumnExists("mime_type", "VARCHAR(255) NOT NULL" | 87 return EnsureColumnExists("mime_type", "VARCHAR(255) NOT NULL" |
189 " DEFAULT \"\"") && | 88 " DEFAULT \"\"") && |
190 EnsureColumnExists("original_mime_type", "VARCHAR(255) NOT NULL" | 89 EnsureColumnExists("original_mime_type", "VARCHAR(255) NOT NULL" |
191 " DEFAULT \"\""); | 90 " DEFAULT \"\""); |
192 } | 91 } |
193 | 92 |
194 bool DownloadDatabase::MigrateDownloadsState() { | 93 bool DownloadDatabase::MigrateDownloadsState() { |
195 sql::Statement statement(GetDB().GetUniqueStatement( | 94 sql::Statement statement(GetDB().GetUniqueStatement( |
196 "UPDATE downloads SET state=? WHERE state=?")); | 95 "UPDATE downloads SET state=? WHERE state=?")); |
197 statement.BindInt(0, kStateInterrupted); | 96 statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED)); |
198 statement.BindInt(1, kStateBug140687); | 97 statement.BindInt(1, DownloadStateToInt(DownloadState::BUG_140687)); |
199 return statement.Run(); | 98 return statement.Run(); |
200 } | 99 } |
201 | 100 |
202 bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() { | 101 bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() { |
203 // We need to rename the table and copy back from it because SQLite | 102 // We need to rename the table and copy back from it because SQLite |
204 // provides no way to rename or delete a column. | 103 // provides no way to rename or delete a column. |
205 if (!GetDB().Execute("ALTER TABLE downloads RENAME TO downloads_tmp")) | 104 if (!GetDB().Execute("ALTER TABLE downloads RENAME TO downloads_tmp")) |
206 return false; | 105 return false; |
207 | 106 |
208 const char kReasonPathDangerSchema[] = | 107 const char kReasonPathDangerSchema[] = |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 " total_bytes, state, danger_type, interrupt_reason, end_time, opened ) " | 142 " total_bytes, state, danger_type, interrupt_reason, end_time, opened ) " |
244 "SELECT id, full_path, full_path, " | 143 "SELECT id, full_path, full_path, " |
245 " CASE start_time WHEN 0 THEN 0 ELSE " | 144 " CASE start_time WHEN 0 THEN 0 ELSE " |
246 " (start_time + 11644473600) * 1000000 END, " | 145 " (start_time + 11644473600) * 1000000 END, " |
247 " received_bytes, total_bytes, " | 146 " received_bytes, total_bytes, " |
248 " state, ?, ?, " | 147 " state, ?, ?, " |
249 " CASE end_time WHEN 0 THEN 0 ELSE " | 148 " CASE end_time WHEN 0 THEN 0 ELSE " |
250 " (end_time + 11644473600) * 1000000 END, " | 149 " (end_time + 11644473600) * 1000000 END, " |
251 " opened " | 150 " opened " |
252 "FROM downloads_tmp")); | 151 "FROM downloads_tmp")); |
253 statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE); | 152 statement_populate.BindInt( |
254 statement_populate.BindInt(1, kDangerTypeNotDangerous); | 153 0, DownloadInterruptReasonToInt(download_interrupt_no_reason_)); |
| 154 statement_populate.BindInt( |
| 155 1, DownloadDangerTypeToInt(DownloadDangerType::NOT_DANGEROUS)); |
255 if (!statement_populate.Run()) | 156 if (!statement_populate.Run()) |
256 return false; | 157 return false; |
257 | 158 |
258 // Create new chain table and populate it. | 159 // Create new chain table and populate it. |
259 if (!GetDB().Execute(kReasonPathDangerUrlChainSchema)) | 160 if (!GetDB().Execute(kReasonPathDangerUrlChainSchema)) |
260 return false; | 161 return false; |
261 | 162 |
262 if (!GetDB().Execute("INSERT INTO downloads_url_chains " | 163 if (!GetDB().Execute("INSERT INTO downloads_url_chains " |
263 " ( id, chain_index, url) " | 164 " ( id, chain_index, url) " |
264 " SELECT id, 0, url from downloads_tmp")) | 165 " SELECT id, 0, url from downloads_tmp")) |
(...skipping 24 matching lines...) Expand all Loading... |
289 const char kSchema[] = | 190 const char kSchema[] = |
290 "CREATE TABLE downloads (" | 191 "CREATE TABLE downloads (" |
291 "id INTEGER PRIMARY KEY," // Primary key. | 192 "id INTEGER PRIMARY KEY," // Primary key. |
292 "current_path LONGVARCHAR NOT NULL," // Current disk location | 193 "current_path LONGVARCHAR NOT NULL," // Current disk location |
293 "target_path LONGVARCHAR NOT NULL," // Final disk location | 194 "target_path LONGVARCHAR NOT NULL," // Final disk location |
294 "start_time INTEGER NOT NULL," // When the download was started. | 195 "start_time INTEGER NOT NULL," // When the download was started. |
295 "received_bytes INTEGER NOT NULL," // Total size downloaded. | 196 "received_bytes INTEGER NOT NULL," // Total size downloaded. |
296 "total_bytes INTEGER NOT NULL," // Total size of the download. | 197 "total_bytes INTEGER NOT NULL," // Total size of the download. |
297 "state INTEGER NOT NULL," // 1=complete, 4=interrupted | 198 "state INTEGER NOT NULL," // 1=complete, 4=interrupted |
298 "danger_type INTEGER NOT NULL," // Danger type, validated. | 199 "danger_type INTEGER NOT NULL," // Danger type, validated. |
299 "interrupt_reason INTEGER NOT NULL," // content::DownloadInterruptReason | 200 "interrupt_reason INTEGER NOT NULL," // DownloadInterruptReason |
300 "end_time INTEGER NOT NULL," // When the download completed. | 201 "end_time INTEGER NOT NULL," // When the download completed. |
301 "opened INTEGER NOT NULL," // 1 if it has ever been opened | 202 "opened INTEGER NOT NULL," // 1 if it has ever been opened |
302 // else 0 | 203 // else 0 |
303 "referrer VARCHAR NOT NULL," // HTTP Referrer | 204 "referrer VARCHAR NOT NULL," // HTTP Referrer |
304 "by_ext_id VARCHAR NOT NULL," // ID of extension that started the | 205 "by_ext_id VARCHAR NOT NULL," // ID of extension that started the |
305 // download | 206 // download |
306 "by_ext_name VARCHAR NOT NULL," // name of extension | 207 "by_ext_name VARCHAR NOT NULL," // name of extension |
307 "etag VARCHAR NOT NULL," // ETag | 208 "etag VARCHAR NOT NULL," // ETag |
308 "last_modified VARCHAR NOT NULL," // Last-Modified header | 209 "last_modified VARCHAR NOT NULL," // Last-Modified header |
309 "mime_type VARCHAR(255) NOT NULL," // MIME type. | 210 "mime_type VARCHAR(255) NOT NULL," // MIME type. |
(...skipping 17 matching lines...) Expand all Loading... |
327 return (!GetDB().DoesTableExist("downloads_url_chain") && | 228 return (!GetDB().DoesTableExist("downloads_url_chain") && |
328 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema)); | 229 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema)); |
329 } | 230 } |
330 } | 231 } |
331 | 232 |
332 uint32 DownloadDatabase::GetNextDownloadId() { | 233 uint32 DownloadDatabase::GetNextDownloadId() { |
333 sql::Statement select_max_id(GetDB().GetUniqueStatement( | 234 sql::Statement select_max_id(GetDB().GetUniqueStatement( |
334 "SELECT max(id) FROM downloads")); | 235 "SELECT max(id) FROM downloads")); |
335 bool result = select_max_id.Step(); | 236 bool result = select_max_id.Step(); |
336 DCHECK(result); | 237 DCHECK(result); |
337 // If there are zero records in the downloads table, then max(id) will return | 238 // If there are zero records in the downloads table, then max(id) will |
338 // 0 = kInvalidId, so GetNextDownloadId() will set *id = kInvalidId + 1. | 239 // return 0 = kInvalidDownloadId, so GetNextDownloadId() will set |
339 // If there is at least one record but all of the |id|s are <= kInvalidId, | 240 // *id = kInvalidDownloadId + 1. |
340 // then max(id) will return <= kInvalidId, so GetNextDownloadId should return | 241 // |
341 // kInvalidId + 1. Note that any records with |id <= kInvalidId| will be | 242 // If there is at least one record but all of the |id|s are |
342 // dropped in QueryDownloads() | 243 // <= kInvalidDownloadId, then max(id) will return <= kInvalidDownloadId, |
| 244 // so GetNextDownloadId() should return kInvalidDownloadId + 1. |
| 245 // |
| 246 // Note that any records with |id <= kInvalidDownloadId| will be dropped in |
| 247 // QueryDownloads(). |
| 248 // |
343 // SQLITE doesn't have unsigned integers. | 249 // SQLITE doesn't have unsigned integers. |
344 return 1 + static_cast<uint32>(std::max( | 250 return 1 + static_cast<uint32>(std::max( |
345 static_cast<int64>(content::DownloadItem::kInvalidId), | 251 static_cast<int64>(kInvalidDownloadId), |
346 select_max_id.ColumnInt64(0))); | 252 select_max_id.ColumnInt64(0))); |
347 } | 253 } |
348 | 254 |
349 bool DownloadDatabase::DropDownloadTable() { | 255 bool DownloadDatabase::DropDownloadTable() { |
350 return GetDB().Execute("DROP TABLE downloads"); | 256 return GetDB().Execute("DROP TABLE downloads"); |
351 } | 257 } |
352 | 258 |
353 void DownloadDatabase::QueryDownloads( | 259 void DownloadDatabase::QueryDownloads(std::vector<DownloadRow>* results) { |
354 std::vector<DownloadRow>* results) { | |
355 EnsureInProgressEntriesCleanedUp(); | 260 EnsureInProgressEntriesCleanedUp(); |
356 | 261 |
357 results->clear(); | 262 results->clear(); |
358 std::set<uint32> ids; | 263 std::set<uint32> ids; |
359 | 264 |
360 std::map<uint32, DownloadRow*> info_map; | 265 std::map<uint32, DownloadRow*> info_map; |
361 | 266 |
362 sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE, | 267 sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE, |
363 "SELECT id, current_path, target_path, " | 268 "SELECT id, current_path, target_path, " |
364 "mime_type, original_mime_type, " | 269 "mime_type, original_mime_type, " |
365 "start_time, received_bytes, " | 270 "start_time, received_bytes, " |
366 "total_bytes, state, danger_type, interrupt_reason, end_time, opened, " | 271 "total_bytes, state, danger_type, interrupt_reason, end_time, opened, " |
367 "referrer, by_ext_id, by_ext_name, etag, last_modified " | 272 "referrer, by_ext_id, by_ext_name, etag, last_modified " |
368 "FROM downloads ORDER BY start_time")); | 273 "FROM downloads ORDER BY start_time")); |
369 | 274 |
370 while (statement_main.Step()) { | 275 while (statement_main.Step()) { |
371 scoped_ptr<DownloadRow> info(new DownloadRow()); | 276 scoped_ptr<DownloadRow> info(new DownloadRow()); |
372 int column = 0; | 277 int column = 0; |
373 | 278 |
374 // SQLITE does not have unsigned integers, so explicitly handle negative | 279 // SQLITE does not have unsigned integers, so explicitly handle negative |
375 // |id|s instead of casting them to very large uint32s, which would break | 280 // |id|s instead of casting them to very large uint32s, which would break |
376 // the max(id) logic in GetNextDownloadId(). | 281 // the max(id) logic in GetNextDownloadId(). |
377 int64 signed_id = statement_main.ColumnInt64(column++); | 282 int64 signed_id = statement_main.ColumnInt64(column++); |
378 info->id = static_cast<uint32>(signed_id); | 283 info->id = IntToDownloadId(signed_id); |
379 info->current_path = ColumnFilePath(statement_main, column++); | 284 info->current_path = ColumnFilePath(statement_main, column++); |
380 info->target_path = ColumnFilePath(statement_main, column++); | 285 info->target_path = ColumnFilePath(statement_main, column++); |
381 info->mime_type = statement_main.ColumnString(column++); | 286 info->mime_type = statement_main.ColumnString(column++); |
382 info->original_mime_type = statement_main.ColumnString(column++); | 287 info->original_mime_type = statement_main.ColumnString(column++); |
383 info->start_time = base::Time::FromInternalValue( | 288 info->start_time = |
384 statement_main.ColumnInt64(column++)); | 289 base::Time::FromInternalValue(statement_main.ColumnInt64(column++)); |
385 info->received_bytes = statement_main.ColumnInt64(column++); | 290 info->received_bytes = statement_main.ColumnInt64(column++); |
386 info->total_bytes = statement_main.ColumnInt64(column++); | 291 info->total_bytes = statement_main.ColumnInt64(column++); |
387 int state = statement_main.ColumnInt(column++); | 292 int state = statement_main.ColumnInt(column++); |
388 info->state = IntToState(state); | 293 info->state = IntToDownloadState(state); |
389 if (info->state == DownloadItem::MAX_DOWNLOAD_STATE) | 294 if (info->state == DownloadState::INVALID) |
390 UMA_HISTOGRAM_COUNTS("Download.DatabaseInvalidState", state); | 295 UMA_HISTOGRAM_COUNTS("Download.DatabaseInvalidState", state); |
391 info->danger_type = IntToDangerType(statement_main.ColumnInt(column++)); | 296 info->danger_type = |
392 info->interrupt_reason = static_cast<content::DownloadInterruptReason>( | 297 IntToDownloadDangerType(statement_main.ColumnInt(column++)); |
393 statement_main.ColumnInt(column++)); | 298 info->interrupt_reason = |
394 info->end_time = base::Time::FromInternalValue( | 299 IntToDownloadInterruptReason(statement_main.ColumnInt(column++)); |
395 statement_main.ColumnInt64(column++)); | 300 info->end_time = |
| 301 base::Time::FromInternalValue(statement_main.ColumnInt64(column++)); |
396 info->opened = statement_main.ColumnInt(column++) != 0; | 302 info->opened = statement_main.ColumnInt(column++) != 0; |
397 info->referrer_url = GURL(statement_main.ColumnString(column++)); | 303 info->referrer_url = GURL(statement_main.ColumnString(column++)); |
398 info->by_ext_id = statement_main.ColumnString(column++); | 304 info->by_ext_id = statement_main.ColumnString(column++); |
399 info->by_ext_name = statement_main.ColumnString(column++); | 305 info->by_ext_name = statement_main.ColumnString(column++); |
400 info->etag = statement_main.ColumnString(column++); | 306 info->etag = statement_main.ColumnString(column++); |
401 info->last_modified = statement_main.ColumnString(column++); | 307 info->last_modified = statement_main.ColumnString(column++); |
402 | 308 |
403 // If the record is corrupted, note that and drop it. | 309 // If the record is corrupted, note that and drop it. |
404 // http://crbug.com/251269 | 310 // http://crbug.com/251269 |
405 DroppedReason dropped_reason = DROPPED_REASON_MAX; | 311 DroppedReason dropped_reason = DROPPED_REASON_MAX; |
406 if (signed_id <= static_cast<int64>(content::DownloadItem::kInvalidId)) { | 312 if (signed_id <= static_cast<int64>(kInvalidDownloadId)) { |
407 // SQLITE doesn't have unsigned integers. | 313 // SQLITE doesn't have unsigned integers. |
408 dropped_reason = DROPPED_REASON_BAD_ID; | 314 dropped_reason = DROPPED_REASON_BAD_ID; |
409 } else if (!ids.insert(info->id).second) { | 315 } else if (!ids.insert(info->id).second) { |
410 dropped_reason = DROPPED_REASON_DUPLICATE_ID; | 316 dropped_reason = DROPPED_REASON_DUPLICATE_ID; |
411 NOTREACHED() << info->id; | 317 NOTREACHED() << info->id; |
412 } else if (info->state == DownloadItem::MAX_DOWNLOAD_STATE) { | 318 } else if (info->state == DownloadState::INVALID) { |
413 dropped_reason = DROPPED_REASON_BAD_STATE; | 319 dropped_reason = DROPPED_REASON_BAD_STATE; |
414 } else if (info->danger_type == content::DOWNLOAD_DANGER_TYPE_MAX) { | 320 } else if (info->danger_type == DownloadDangerType::INVALID) { |
415 dropped_reason = DROPPED_REASON_BAD_DANGER_TYPE; | 321 dropped_reason = DROPPED_REASON_BAD_DANGER_TYPE; |
416 } | 322 } |
417 if (dropped_reason != DROPPED_REASON_MAX) { | 323 if (dropped_reason != DROPPED_REASON_MAX) { |
418 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseRecordDropped", | 324 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseRecordDropped", |
419 dropped_reason, | 325 dropped_reason, |
420 DROPPED_REASON_MAX + 1); | 326 DROPPED_REASON_MAX + 1); |
421 } else { | 327 } else { |
422 DCHECK(!ContainsKey(info_map, info->id)); | 328 DCHECK(!ContainsKey(info_map, info->id)); |
423 uint32 id = info->id; | 329 uint32 id = info->id; |
424 info_map[id] = info.release(); | 330 info_map[id] = info.release(); |
425 } | 331 } |
426 } | 332 } |
427 | 333 |
428 sql::Statement statement_chain(GetDB().GetCachedStatement( | 334 sql::Statement statement_chain(GetDB().GetCachedStatement( |
429 SQL_FROM_HERE, | 335 SQL_FROM_HERE, |
430 "SELECT id, chain_index, url FROM downloads_url_chains " | 336 "SELECT id, chain_index, url FROM downloads_url_chains " |
431 "ORDER BY id, chain_index")); | 337 "ORDER BY id, chain_index")); |
432 | 338 |
433 while (statement_chain.Step()) { | 339 while (statement_chain.Step()) { |
434 int column = 0; | 340 int column = 0; |
435 // See the comment above about SQLITE lacking unsigned integers. | 341 // See the comment above about SQLITE lacking unsigned integers. |
436 int64 signed_id = statement_chain.ColumnInt64(column++); | 342 int64 signed_id = statement_chain.ColumnInt64(column++); |
437 int chain_index = statement_chain.ColumnInt(column++); | 343 int chain_index = statement_chain.ColumnInt(column++); |
438 | 344 |
439 if (signed_id <= static_cast<int64>(content::DownloadItem::kInvalidId)) | 345 if (signed_id <= static_cast<int64>(kInvalidDownloadId)) |
440 continue; | 346 continue; |
441 uint32 id = static_cast<uint32>(signed_id); | 347 uint32 id = IntToDownloadId(signed_id); |
442 | 348 |
443 // Note that these DCHECKs may trip as a result of corrupted databases. | 349 // Note that these DCHECKs may trip as a result of corrupted databases. |
444 // We have them because in debug builds the chances are higher there's | 350 // We have them because in debug builds the chances are higher there's |
445 // an actual bug than that the database is corrupt, but we handle the | 351 // an actual bug than that the database is corrupt, but we handle the |
446 // DB corruption case in production code. | 352 // DB corruption case in production code. |
447 | 353 |
448 // Confirm the id has already been seen--if it hasn't, discard the | 354 // Confirm the id has already been seen--if it hasn't, discard the |
449 // record. | 355 // record. |
450 DCHECK(ContainsKey(info_map, id)); | 356 DCHECK(ContainsKey(info_map, id)); |
451 if (!ContainsKey(info_map, id)) | 357 if (!ContainsKey(info_map, id)) |
(...skipping 27 matching lines...) Expand all Loading... |
479 results->push_back(*row); | 385 results->push_back(*row); |
480 } | 386 } |
481 delete row; | 387 delete row; |
482 it->second = NULL; | 388 it->second = NULL; |
483 } | 389 } |
484 } | 390 } |
485 | 391 |
486 bool DownloadDatabase::UpdateDownload(const DownloadRow& data) { | 392 bool DownloadDatabase::UpdateDownload(const DownloadRow& data) { |
487 EnsureInProgressEntriesCleanedUp(); | 393 EnsureInProgressEntriesCleanedUp(); |
488 | 394 |
489 DCHECK_NE(content::DownloadItem::kInvalidId, data.id); | 395 DCHECK_NE(kInvalidDownloadId, data.id); |
490 int state = StateToInt(data.state); | 396 if (data.state == DownloadState::INVALID) { |
491 if (state == kStateInvalid) { | |
492 NOTREACHED(); | 397 NOTREACHED(); |
493 return false; | 398 return false; |
494 } | 399 } |
495 int danger_type = DangerTypeToInt(data.danger_type); | 400 if (data.danger_type == DownloadDangerType::INVALID) { |
496 if (danger_type == kDangerTypeInvalid) { | |
497 NOTREACHED(); | 401 NOTREACHED(); |
498 return false; | 402 return false; |
499 } | 403 } |
500 | 404 |
501 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 405 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
502 "UPDATE downloads " | 406 "UPDATE downloads " |
503 "SET current_path=?, target_path=?, " | 407 "SET current_path=?, target_path=?, " |
504 "mime_type=?, original_mime_type=?, " | 408 "mime_type=?, original_mime_type=?, " |
505 "received_bytes=?, state=?, " | 409 "received_bytes=?, state=?, " |
506 "danger_type=?, interrupt_reason=?, end_time=?, total_bytes=?, " | 410 "danger_type=?, interrupt_reason=?, end_time=?, total_bytes=?, " |
507 "opened=?, by_ext_id=?, by_ext_name=?, etag=?, last_modified=? " | 411 "opened=?, by_ext_id=?, by_ext_name=?, etag=?, last_modified=? " |
508 "WHERE id=?")); | 412 "WHERE id=?")); |
509 int column = 0; | 413 int column = 0; |
510 BindFilePath(statement, data.current_path, column++); | 414 BindFilePath(statement, data.current_path, column++); |
511 BindFilePath(statement, data.target_path, column++); | 415 BindFilePath(statement, data.target_path, column++); |
512 statement.BindString(column++, data.mime_type); | 416 statement.BindString(column++, data.mime_type); |
513 statement.BindString(column++, data.original_mime_type); | 417 statement.BindString(column++, data.original_mime_type); |
514 statement.BindInt64(column++, data.received_bytes); | 418 statement.BindInt64(column++, data.received_bytes); |
515 statement.BindInt(column++, state); | 419 statement.BindInt(column++, DownloadStateToInt(data.state)); |
516 statement.BindInt(column++, danger_type); | 420 statement.BindInt(column++, DownloadDangerTypeToInt(data.danger_type)); |
517 statement.BindInt(column++, static_cast<int>(data.interrupt_reason)); | 421 statement.BindInt(column++, |
| 422 DownloadInterruptReasonToInt(data.interrupt_reason)); |
518 statement.BindInt64(column++, data.end_time.ToInternalValue()); | 423 statement.BindInt64(column++, data.end_time.ToInternalValue()); |
519 statement.BindInt64(column++, data.total_bytes); | 424 statement.BindInt64(column++, data.total_bytes); |
520 statement.BindInt(column++, (data.opened ? 1 : 0)); | 425 statement.BindInt(column++, (data.opened ? 1 : 0)); |
521 statement.BindString(column++, data.by_ext_id); | 426 statement.BindString(column++, data.by_ext_id); |
522 statement.BindString(column++, data.by_ext_name); | 427 statement.BindString(column++, data.by_ext_name); |
523 statement.BindString(column++, data.etag); | 428 statement.BindString(column++, data.etag); |
524 statement.BindString(column++, data.last_modified); | 429 statement.BindString(column++, data.last_modified); |
525 statement.BindInt(column++, data.id); | 430 statement.BindInt(column++, DownloadIdToInt(data.id)); |
526 | 431 |
527 return statement.Run(); | 432 return statement.Run(); |
528 } | 433 } |
529 | 434 |
530 void DownloadDatabase::EnsureInProgressEntriesCleanedUp() { | 435 void DownloadDatabase::EnsureInProgressEntriesCleanedUp() { |
531 if (in_progress_entry_cleanup_completed_) | 436 if (in_progress_entry_cleanup_completed_) |
532 return; | 437 return; |
533 | 438 |
534 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 439 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
535 "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?")); | 440 "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?")); |
536 statement.BindInt(0, kStateInterrupted); | 441 statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED)); |
537 statement.BindInt(1, content::DOWNLOAD_INTERRUPT_REASON_CRASH); | 442 statement.BindInt(1, DownloadInterruptReasonToInt(download_interrupt_crash_)); |
538 statement.BindInt(2, kStateInProgress); | 443 statement.BindInt(2, DownloadStateToInt(DownloadState::IN_PROGRESS)); |
539 | 444 |
540 statement.Run(); | 445 statement.Run(); |
541 in_progress_entry_cleanup_completed_ = true; | 446 in_progress_entry_cleanup_completed_ = true; |
542 } | 447 } |
543 | 448 |
544 bool DownloadDatabase::CreateDownload(const DownloadRow& info) { | 449 bool DownloadDatabase::CreateDownload(const DownloadRow& info) { |
545 DCHECK_NE(content::DownloadItem::kInvalidId, info.id); | 450 DCHECK_NE(kInvalidDownloadId, info.id); |
546 EnsureInProgressEntriesCleanedUp(); | 451 EnsureInProgressEntriesCleanedUp(); |
547 | 452 |
548 if (info.url_chain.empty()) | 453 if (info.url_chain.empty()) |
549 return false; | 454 return false; |
550 | 455 |
551 int state = StateToInt(info.state); | 456 if (info.state == DownloadState::INVALID) |
552 if (state == kStateInvalid) | |
553 return false; | 457 return false; |
554 | 458 |
555 int danger_type = DangerTypeToInt(info.danger_type); | 459 if (info.danger_type == DownloadDangerType::INVALID) |
556 if (danger_type == kDangerTypeInvalid) | |
557 return false; | 460 return false; |
558 | 461 |
559 { | 462 { |
560 sql::Statement statement_insert(GetDB().GetCachedStatement( | 463 sql::Statement statement_insert(GetDB().GetCachedStatement( |
561 SQL_FROM_HERE, | 464 SQL_FROM_HERE, |
562 "INSERT INTO downloads " | 465 "INSERT INTO downloads " |
563 "(id, current_path, target_path, " | 466 "(id, current_path, target_path, " |
564 " mime_type, original_mime_type, " | 467 " mime_type, original_mime_type, " |
565 " start_time, " | 468 " start_time, " |
566 " received_bytes, total_bytes, state, danger_type, interrupt_reason, " | 469 " received_bytes, total_bytes, state, danger_type, interrupt_reason, " |
567 " end_time, opened, referrer, by_ext_id, by_ext_name, etag, " | 470 " end_time, opened, referrer, by_ext_id, by_ext_name, etag, " |
568 " last_modified) " | 471 " last_modified) " |
569 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); | 472 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
570 | 473 |
571 int column = 0; | 474 int column = 0; |
572 statement_insert.BindInt(column++, info.id); | 475 statement_insert.BindInt(column++, DownloadIdToInt(info.id)); |
573 BindFilePath(statement_insert, info.current_path, column++); | 476 BindFilePath(statement_insert, info.current_path, column++); |
574 BindFilePath(statement_insert, info.target_path, column++); | 477 BindFilePath(statement_insert, info.target_path, column++); |
575 statement_insert.BindString(column++, info.mime_type); | 478 statement_insert.BindString(column++, info.mime_type); |
576 statement_insert.BindString(column++, info.original_mime_type); | 479 statement_insert.BindString(column++, info.original_mime_type); |
577 statement_insert.BindInt64(column++, info.start_time.ToInternalValue()); | 480 statement_insert.BindInt64(column++, info.start_time.ToInternalValue()); |
578 statement_insert.BindInt64(column++, info.received_bytes); | 481 statement_insert.BindInt64(column++, info.received_bytes); |
579 statement_insert.BindInt64(column++, info.total_bytes); | 482 statement_insert.BindInt64(column++, info.total_bytes); |
580 statement_insert.BindInt(column++, state); | 483 statement_insert.BindInt(column++, DownloadStateToInt(info.state)); |
581 statement_insert.BindInt(column++, danger_type); | 484 statement_insert.BindInt(column++, |
582 statement_insert.BindInt(column++, info.interrupt_reason); | 485 DownloadDangerTypeToInt(info.danger_type)); |
| 486 statement_insert.BindInt( |
| 487 column++, DownloadInterruptReasonToInt(info.interrupt_reason)); |
583 statement_insert.BindInt64(column++, info.end_time.ToInternalValue()); | 488 statement_insert.BindInt64(column++, info.end_time.ToInternalValue()); |
584 statement_insert.BindInt(column++, info.opened ? 1 : 0); | 489 statement_insert.BindInt(column++, info.opened ? 1 : 0); |
585 statement_insert.BindString(column++, info.referrer_url.spec()); | 490 statement_insert.BindString(column++, info.referrer_url.spec()); |
586 statement_insert.BindString(column++, info.by_ext_id); | 491 statement_insert.BindString(column++, info.by_ext_id); |
587 statement_insert.BindString(column++, info.by_ext_name); | 492 statement_insert.BindString(column++, info.by_ext_name); |
588 statement_insert.BindString(column++, info.etag); | 493 statement_insert.BindString(column++, info.etag); |
589 statement_insert.BindString(column++, info.last_modified); | 494 statement_insert.BindString(column++, info.last_modified); |
590 if (!statement_insert.Run()) { | 495 if (!statement_insert.Run()) { |
591 // GetErrorCode() returns a bitmask where the lower byte is a more general | 496 // GetErrorCode() returns a bitmask where the lower byte is a more general |
592 // code and the upper byte is a more specific code. In order to save | 497 // code and the upper byte is a more specific code. In order to save |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 size_t DownloadDatabase::CountDownloads() { | 567 size_t DownloadDatabase::CountDownloads() { |
663 EnsureInProgressEntriesCleanedUp(); | 568 EnsureInProgressEntriesCleanedUp(); |
664 | 569 |
665 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 570 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
666 "SELECT count(*) from downloads")); | 571 "SELECT count(*) from downloads")); |
667 statement.Step(); | 572 statement.Step(); |
668 return statement.ColumnInt(0); | 573 return statement.ColumnInt(0); |
669 } | 574 } |
670 | 575 |
671 } // namespace history | 576 } // namespace history |
OLD | NEW |