15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/download_database.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/alias.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/download_row.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_types.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/download_interrupt_reasons.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_item.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadItem; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Reason for dropping a particular record. 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)enum DroppedReason { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DROPPED_REASON_BAD_STATE = 0, 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DROPPED_REASON_BAD_DANGER_TYPE = 1, 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DROPPED_REASON_BAD_ID = 2, 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DROPPED_REASON_DUPLICATE_ID = 3, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DROPPED_REASON_MAX 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_POSIX) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Binds/reads the given file path to the given column of the given statement. 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BindFilePath(sql::Statement& statement, const base::FilePath& path, 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int col) { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) statement.BindString(col, path.value()); 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::FilePath ColumnFilePath(sql::Statement& statement, int col) { 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::FilePath(statement.ColumnString(col)); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// See above. 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BindFilePath(sql::Statement& statement, const base::FilePath& path, 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int col) { 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) statement.BindString16(col, path.value()); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::FilePath ColumnFilePath(sql::Statement& statement, int col) { 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::FilePath(statement.ColumnString16(col)); 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// These constants and the transformation functions below are used to allow 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DownloadItem::DownloadState and DownloadDangerType to change without 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// breaking the database schema. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// They guarantee that the values of the |state| field in the database are one 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the values returned by StateToInt, and that the values of the |state| 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// field of the DownloadRows returned by QueryDownloads() are one of the values 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// returned by IntToState(). 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kStateInvalid = -1; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kStateInProgress = 0; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kStateComplete = 1; 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kStateCancelled = 2; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kStateBug140687 = 3; 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kStateInterrupted = 4; 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeInvalid = -1; 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeNotDangerous = 0; 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeDangerousFile = 1; 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeDangerousUrl = 2; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeDangerousContent = 3; 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeMaybeDangerousContent = 4; 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeUncommonContent = 5; 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeUserValidated = 6; 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int DownloadDatabase::kDangerTypeDangerousHost = 7; 90a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst int DownloadDatabase::kDangerTypePotentiallyUnwanted = 8; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int DownloadDatabase::StateToInt(DownloadItem::DownloadState state) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadItem::IN_PROGRESS: return DownloadDatabase::kStateInProgress; 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadItem::COMPLETE: return DownloadDatabase::kStateComplete; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadItem::CANCELLED: return DownloadDatabase::kStateCancelled; 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadItem::INTERRUPTED: return DownloadDatabase::kStateInterrupted; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case DownloadItem::MAX_DOWNLOAD_STATE: 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kStateInvalid; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kStateInvalid; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DownloadItem::DownloadState DownloadDatabase::IntToState(int state) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kStateInProgress: return DownloadItem::IN_PROGRESS; 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kStateComplete: return DownloadItem::COMPLETE; 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kStateCancelled: return DownloadItem::CANCELLED; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We should not need kStateBug140687 here because MigrateDownloadsState() 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is called in HistoryDatabase::Init(). 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kStateInterrupted: return DownloadItem::INTERRUPTED; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: return DownloadItem::MAX_DOWNLOAD_STATE; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int DownloadDatabase::DangerTypeToInt(content::DownloadDangerType danger_type) { 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (danger_type) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeNotDangerous; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeDangerousFile; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeDangerousUrl; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeDangerousContent; 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeMaybeDangerousContent; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeUncommonContent; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeUserValidated; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeDangerousHost; 136a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: 137a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return DownloadDatabase::kDangerTypePotentiallyUnwanted; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case content::DOWNLOAD_DANGER_TYPE_MAX: 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeInvalid; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DownloadDatabase::kDangerTypeInvalid; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)content::DownloadDangerType DownloadDatabase::IntToDangerType(int danger_type) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (danger_type) { 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeNotDangerous: 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS; 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeDangerousFile: 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeDangerousUrl: 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeDangerousContent: 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT; 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeMaybeDangerousContent: 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeUncommonContent: 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT; 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeUserValidated: 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED; 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DownloadDatabase::kDangerTypeDangerousHost: 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST; 164a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case DownloadDatabase::kDangerTypePotentiallyUnwanted: 165a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED; 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return content::DOWNLOAD_DANGER_TYPE_MAX; 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadDatabase::DownloadDatabase() 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : owning_thread_set_(false), 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owning_thread_(0), 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_progress_entry_cleanup_completed_(false) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadDatabase::~DownloadDatabase() { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadDatabase::EnsureColumnExists( 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, const std::string& type) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string add_col = "ALTER TABLE downloads ADD COLUMN " + name + " " + type; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetDB().DoesColumnExist("downloads", name.c_str()) || 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDB().Execute(add_col.c_str()); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool DownloadDatabase::MigrateMimeType() { 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EnsureColumnExists("mime_type", "VARCHAR(255) NOT NULL" 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) " DEFAULT \"\"") && 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EnsureColumnExists("original_mime_type", "VARCHAR(255) NOT NULL" 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) " DEFAULT \"\""); 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadDatabase::MigrateDownloadsState() { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetUniqueStatement( 1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch "UPDATE downloads SET state=? WHERE state=?")); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(0, kStateInterrupted); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(1, kStateBug140687); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.Run(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() { 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to rename the table and copy back from it because SQLite 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // provides no way to rename or delete a column. 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetDB().Execute("ALTER TABLE downloads RENAME TO downloads_tmp")) 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char kReasonPathDangerSchema[] = 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "CREATE TABLE downloads (" 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "id INTEGER PRIMARY KEY," 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "current_path LONGVARCHAR NOT NULL," 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "target_path LONGVARCHAR NOT NULL," 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "start_time INTEGER NOT NULL," 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "received_bytes INTEGER NOT NULL," 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "total_bytes INTEGER NOT NULL," 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "state INTEGER NOT NULL," 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "danger_type INTEGER NOT NULL," 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "interrupt_reason INTEGER NOT NULL," 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "end_time INTEGER NOT NULL," 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "opened INTEGER NOT NULL)"; 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static const char kReasonPathDangerUrlChainSchema[] = 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "CREATE TABLE downloads_url_chains (" 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "id INTEGER NOT NULL," // downloads.id. 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "chain_index INTEGER NOT NULL," // Index of url in chain 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // 0 is initial target, 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // MAX is target after redirects. 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "url LONGVARCHAR NOT NULL, " // URL. 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "PRIMARY KEY (id, chain_index) )"; 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Recreate main table. 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!GetDB().Execute(kReasonPathDangerSchema)) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Populate it. As we do so, we transform the time values from time_t 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (seconds since 1/1/1970 UTC), to our internal measure (microseconds 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // since the Windows Epoch). Note that this is dependent on the 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // internal representation of base::Time and needs to change if that changes. 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement_populate(GetDB().GetUniqueStatement( 241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "INSERT INTO downloads " 242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "( id, current_path, target_path, start_time, received_bytes, " 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) " total_bytes, state, danger_type, interrupt_reason, end_time, opened ) " 244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "SELECT id, full_path, full_path, " 245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " CASE start_time WHEN 0 THEN 0 ELSE " 246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " (start_time + 11644473600) * 1000000 END, " 247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " received_bytes, total_bytes, " 248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " state, ?, ?, " 249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " CASE end_time WHEN 0 THEN 0 ELSE " 250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " (end_time + 11644473600) * 1000000 END, " 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) " opened " 252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "FROM downloads_tmp")); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_populate.BindInt(1, kDangerTypeNotDangerous); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!statement_populate.Run()) 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create new chain table and populate it. 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!GetDB().Execute(kReasonPathDangerUrlChainSchema)) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetDB().Execute("INSERT INTO downloads_url_chains " 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " ( id, chain_index, url) " 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " SELECT id, 0, url from downloads_tmp")) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get rid of temporary table. 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetDB().Execute("DROP TABLE downloads_tmp")) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool DownloadDatabase::MigrateReferrer() { 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return EnsureColumnExists("referrer", "VARCHAR NOT NULL DEFAULT \"\""); 276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool DownloadDatabase::MigrateDownloadedByExtension() { 279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return EnsureColumnExists("by_ext_id", "VARCHAR NOT NULL DEFAULT \"\"") && 280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EnsureColumnExists("by_ext_name", "VARCHAR NOT NULL DEFAULT \"\""); 281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool DownloadDatabase::MigrateDownloadValidators() { 284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return EnsureColumnExists("etag", "VARCHAR NOT NULL DEFAULT \"\"") && 285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EnsureColumnExists("last_modified", "VARCHAR NOT NULL DEFAULT \"\""); 286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadDatabase::InitDownloadTable() { 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char kSchema[] = 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "CREATE TABLE downloads (" 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "id INTEGER PRIMARY KEY," // Primary key. 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "current_path LONGVARCHAR NOT NULL," // Current disk location 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "target_path LONGVARCHAR NOT NULL," // Final disk location 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "start_time INTEGER NOT NULL," // When the download was started. 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "received_bytes INTEGER NOT NULL," // Total size downloaded. 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "total_bytes INTEGER NOT NULL," // Total size of the download. 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "state INTEGER NOT NULL," // 1=complete, 4=interrupted 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "danger_type INTEGER NOT NULL," // Danger type, validated. 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "interrupt_reason INTEGER NOT NULL," // content::DownloadInterruptReason 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "end_time INTEGER NOT NULL," // When the download completed. 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "opened INTEGER NOT NULL," // 1 if it has ever been opened 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // else 0 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "referrer VARCHAR NOT NULL," // HTTP Referrer 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "by_ext_id VARCHAR NOT NULL," // ID of extension that started the 305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // download 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "by_ext_name VARCHAR NOT NULL," // name of extension 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "etag VARCHAR NOT NULL," // ETag 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "last_modified VARCHAR NOT NULL," // Last-Modified header 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "mime_type VARCHAR(255) NOT NULL," // MIME type. 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "original_mime_type VARCHAR(255) NOT NULL)"; // Original MIME type. 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char kUrlChainSchema[] = 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "CREATE TABLE downloads_url_chains (" 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "id INTEGER NOT NULL," // downloads.id. 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "chain_index INTEGER NOT NULL," // Index of url in chain 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // 0 is initial target, 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // MAX is target after redirects. 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "url LONGVARCHAR NOT NULL, " // URL. 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "PRIMARY KEY (id, chain_index) )"; 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetDB().DoesTableExist("downloads")) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") && 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0"); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the "downloads" table doesn't exist, the downloads_url_chain 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // table better not. 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (!GetDB().DoesTableExist("downloads_url_chain") && 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema)); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)uint32 DownloadDatabase::GetNextDownloadId() { 3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::Statement select_max_id(GetDB().GetUniqueStatement( 3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch "SELECT max(id) FROM downloads")); 335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool result = select_max_id.Step(); 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(result); 3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If there are zero records in the downloads table, then max(id) will return 3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 0 = kInvalidId, so GetNextDownloadId() will set *id = kInvalidId + 1. 3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If there is at least one record but all of the |id|s are <= kInvalidId, 3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // then max(id) will return <= kInvalidId, so GetNextDownloadId should return 3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // kInvalidId + 1. Note that any records with |id <= kInvalidId| will be 3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // dropped in QueryDownloads() 3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SQLITE doesn't have unsigned integers. 344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 1 + static_cast<uint32>(std::max( 3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static_cast<int64>(content::DownloadItem::kInvalidId), 3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch select_max_id.ColumnInt64(0))); 3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadDatabase::DropDownloadTable() { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetDB().Execute("DROP TABLE downloads"); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadDatabase::QueryDownloads( 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<DownloadRow>* results) { 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnsureInProgressEntriesCleanedUp(); 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->clear(); 3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::set<uint32> ids; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::map<uint32, DownloadRow*> info_map; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE, 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "SELECT id, current_path, target_path, " 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "mime_type, original_mime_type, " 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "start_time, received_bytes, " 366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "total_bytes, state, danger_type, interrupt_reason, end_time, opened, " 367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "referrer, by_ext_id, by_ext_name, etag, last_modified " 368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "FROM downloads ORDER BY start_time")); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (statement_main.Step()) { 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<DownloadRow> info(new DownloadRow()); 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int column = 0; 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SQLITE does not have unsigned integers, so explicitly handle negative 3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // |id|s instead of casting them to very large uint32s, which would break 3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // the max(id) logic in GetNextDownloadId(). 3777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int64 signed_id = statement_main.ColumnInt64(column++); 3787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch info->id = static_cast<uint32>(signed_id); 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->current_path = ColumnFilePath(statement_main, column++); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->target_path = ColumnFilePath(statement_main, column++); 381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) info->mime_type = statement_main.ColumnString(column++); 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) info->original_mime_type = statement_main.ColumnString(column++); 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->start_time = base::Time::FromInternalValue( 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_main.ColumnInt64(column++)); 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->received_bytes = statement_main.ColumnInt64(column++); 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->total_bytes = statement_main.ColumnInt64(column++); 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int state = statement_main.ColumnInt(column++); 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->state = IntToState(state); 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info->state == DownloadItem::MAX_DOWNLOAD_STATE) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_COUNTS("Download.DatabaseInvalidState", state); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->danger_type = IntToDangerType(statement_main.ColumnInt(column++)); 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->interrupt_reason = static_cast<content::DownloadInterruptReason>( 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_main.ColumnInt(column++)); 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->end_time = base::Time::FromInternalValue( 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_main.ColumnInt64(column++)); 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->opened = statement_main.ColumnInt(column++) != 0; 397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch info->referrer_url = GURL(statement_main.ColumnString(column++)); 398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) info->by_ext_id = statement_main.ColumnString(column++); 399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) info->by_ext_name = statement_main.ColumnString(column++); 400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch info->etag = statement_main.ColumnString(column++); 401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch info->last_modified = statement_main.ColumnString(column++); 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the record is corrupted, note that and drop it. 4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // http://crbug.com/251269 4057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DroppedReason dropped_reason = DROPPED_REASON_MAX; 4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (signed_id <= static_cast<int64>(content::DownloadItem::kInvalidId)) { 4077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SQLITE doesn't have unsigned integers. 4087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch dropped_reason = DROPPED_REASON_BAD_ID; 4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else if (!ids.insert(info->id).second) { 4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch dropped_reason = DROPPED_REASON_DUPLICATE_ID; 4117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NOTREACHED() << info->id; 4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else if (info->state == DownloadItem::MAX_DOWNLOAD_STATE) { 4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch dropped_reason = DROPPED_REASON_BAD_STATE; 4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else if (info->danger_type == content::DOWNLOAD_DANGER_TYPE_MAX) { 4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch dropped_reason = DROPPED_REASON_BAD_DANGER_TYPE; 4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (dropped_reason != DROPPED_REASON_MAX) { 4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_ENUMERATION("Download.DatabaseRecordDropped", 4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch dropped_reason, 4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DROPPED_REASON_MAX + 1); 4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else { 4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(!ContainsKey(info_map, info->id)); 4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch uint32 id = info->id; 4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch info_map[id] = info.release(); 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement_chain(GetDB().GetCachedStatement( 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SQL_FROM_HERE, 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SELECT id, chain_index, url FROM downloads_url_chains " 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "ORDER BY id, chain_index")); 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (statement_chain.Step()) { 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int column = 0; 4357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // See the comment above about SQLITE lacking unsigned integers. 4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int64 signed_id = statement_chain.ColumnInt64(column++); 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int chain_index = statement_chain.ColumnInt(column++); 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (signed_id <= static_cast<int64>(content::DownloadItem::kInvalidId)) 4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch continue; 4417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch uint32 id = static_cast<uint32>(signed_id); 4427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note that these DCHECKs may trip as a result of corrupted databases. 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We have them because in debug builds the chances are higher there's 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // an actual bug than that the database is corrupt, but we handle the 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DB corruption case in production code. 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Confirm the id has already been seen--if it hasn't, discard the 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // record. 4507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(ContainsKey(info_map, id)); 4517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!ContainsKey(info_map, id)) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Confirm all previous URLs in the chain have already been seen; 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if not, fill in with null or discard record. 4567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int current_chain_size = info_map[id]->url_chain.size(); 4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::vector<GURL>* url_chain(&info_map[id]->url_chain); 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(chain_index, current_chain_size); 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (current_chain_size < chain_index) { 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_chain->push_back(GURL()); 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_chain_size++; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_chain_size > chain_index) 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Save the record. 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_chain->push_back(GURL(statement_chain.ColumnString(2))); 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::map<uint32, DownloadRow*>::iterator 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it = info_map.begin(); it != info_map.end(); ++it) { 472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DownloadRow* row = it->second; 473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool empty_url_chain = row->url_chain.empty(); 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Download.DatabaseEmptyUrlChain", empty_url_chain); 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (empty_url_chain) { 4767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RemoveDownload(row->id); 477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Copy the contents of the stored info. 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) results->push_back(*row); 480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete row; 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->second = NULL; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DownloadDatabase::UpdateDownload(const DownloadRow& data) { 487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnsureInProgressEntriesCleanedUp(); 488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_NE(content::DownloadItem::kInvalidId, data.id); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int state = StateToInt(data.state); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state == kStateInvalid) { 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int danger_type = DangerTypeToInt(data.danger_type); 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (danger_type == kDangerTypeInvalid) { 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "UPDATE downloads " 503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "SET current_path=?, target_path=?, " 504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "mime_type=?, original_mime_type=?, " 505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "received_bytes=?, state=?, " 506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "danger_type=?, interrupt_reason=?, end_time=?, total_bytes=?, " 507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "opened=?, by_ext_id=?, by_ext_name=?, etag=?, last_modified=? " 508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch "WHERE id=?")); 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int column = 0; 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BindFilePath(statement, data.current_path, column++); 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BindFilePath(statement, data.target_path, column++); 512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) statement.BindString(column++, data.mime_type); 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) statement.BindString(column++, data.original_mime_type); 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(column++, data.received_bytes); 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt(column++, state); 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt(column++, danger_type); 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt(column++, static_cast<int>(data.interrupt_reason)); 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(column++, data.end_time.ToInternalValue()); 519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) statement.BindInt64(column++, data.total_bytes); 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt(column++, (data.opened ? 1 : 0)); 521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) statement.BindString(column++, data.by_ext_id); 522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) statement.BindString(column++, data.by_ext_name); 523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch statement.BindString(column++, data.etag); 524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch statement.BindString(column++, data.last_modified); 5257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch statement.BindInt(column++, data.id); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.Run(); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DownloadDatabase::EnsureInProgressEntriesCleanedUp() { 531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (in_progress_entry_cleanup_completed_) 532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?")); 536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) statement.BindInt(0, kStateInterrupted); 537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) statement.BindInt(1, content::DOWNLOAD_INTERRUPT_REASON_CRASH); 538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) statement.BindInt(2, kStateInProgress); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) statement.Run(); 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_progress_entry_cleanup_completed_ = true; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool DownloadDatabase::CreateDownload(const DownloadRow& info) { 5457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_NE(content::DownloadItem::kInvalidId, info.id); 546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnsureInProgressEntriesCleanedUp(); 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (info.url_chain.empty()) 5497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int state = StateToInt(info.state); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state == kStateInvalid) 5537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int danger_type = DangerTypeToInt(info.danger_type); 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (danger_type == kDangerTypeInvalid) 5577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement_insert(GetDB().GetCachedStatement( 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SQL_FROM_HERE, 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "INSERT INTO downloads " 563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "(id, current_path, target_path, " 564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) " mime_type, original_mime_type, " 565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) " start_time, " 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " received_bytes, total_bytes, state, danger_type, interrupt_reason, " 567ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " end_time, opened, referrer, by_ext_id, by_ext_name, etag, " 568ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch " last_modified) " 569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int column = 0; 5727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch statement_insert.BindInt(column++, info.id); 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BindFilePath(statement_insert, info.current_path, column++); 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BindFilePath(statement_insert, info.target_path, column++); 575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) statement_insert.BindString(column++, info.mime_type); 576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) statement_insert.BindString(column++, info.original_mime_type); 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt64(column++, info.start_time.ToInternalValue()); 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt64(column++, info.received_bytes); 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt64(column++, info.total_bytes); 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt(column++, state); 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt(column++, danger_type); 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt(column++, info.interrupt_reason); 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt64(column++, info.end_time.ToInternalValue()); 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert.BindInt(column++, info.opened ? 1 : 0); 585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch statement_insert.BindString(column++, info.referrer_url.spec()); 586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) statement_insert.BindString(column++, info.by_ext_id); 587a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) statement_insert.BindString(column++, info.by_ext_name); 588ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch statement_insert.BindString(column++, info.etag); 589ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch statement_insert.BindString(column++, info.last_modified); 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!statement_insert.Run()) { 591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // GetErrorCode() returns a bitmask where the lower byte is a more general 592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // code and the upper byte is a more specific code. In order to save 593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // memory, take the general code, of which there are fewer than 50. See 594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // also sql/connection.cc 595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // http://www.sqlite.org/c3ref/c_abort_rollback.html 596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainInsertError", 597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetDB().GetErrorCode() & 0xff, 50); 5987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sql::Statement count_urls(GetDB().GetCachedStatement(SQL_FROM_HERE, 604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "SELECT count(*) FROM downloads_url_chains WHERE id=?")); 6057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch count_urls.BindInt(0, info.id); 606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (count_urls.Step()) { 607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool corrupt_urls = count_urls.ColumnInt(0) > 0; 608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Download.DatabaseCorruptUrls", corrupt_urls); 609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (corrupt_urls) { 610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // There should not be any URLs in downloads_url_chains for this 6117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // info.id. If there are, we don't want them to interfere with 612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // inserting the correct URLs, so just remove them. 6137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RemoveDownloadURLs(info.id); 614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement_insert_chain( 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetDB().GetCachedStatement(SQL_FROM_HERE, 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "INSERT INTO downloads_url_chains " 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "(id, chain_index, url) " 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "VALUES (?, ?, ?)")); 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < info.url_chain.size(); ++i) { 6247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch statement_insert_chain.BindInt(0, info.id); 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert_chain.BindInt(1, i); 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert_chain.BindString(2, info.url_chain[i].spec()); 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!statement_insert_chain.Run()) { 628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainInsertError", 629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetDB().GetErrorCode() & 0xff, 50); 6307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RemoveDownload(info.id); 6317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement_insert_chain.Reset(true); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DownloadDatabase::RemoveDownload(uint32 id) { 639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnsureInProgressEntriesCleanedUp(); 640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement downloads_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "DELETE FROM downloads WHERE id=?")); 6437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch downloads_statement.BindInt(0, id); 644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!downloads_statement.Run()) { 645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainDeleteError", 646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetDB().GetErrorCode() & 0xff, 50); 647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 6497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RemoveDownloadURLs(id); 650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DownloadDatabase::RemoveDownloadURLs(uint32 id) { 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement urlchain_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "DELETE FROM downloads_url_chains WHERE id=?")); 6557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch urlchain_statement.BindInt(0, id); 656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!urlchain_statement.Run()) { 657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainDeleteError", 658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetDB().GetErrorCode() & 0xff, 50); 659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsize_t DownloadDatabase::CountDownloads() { 663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnsureInProgressEntriesCleanedUp(); 664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SELECT count(*) from downloads")); 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.Step(); 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return statement.ColumnInt(0); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 672