1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/history/download_database.h" 6 7 #include <limits> 8 #include <vector> 9 10 #include "app/sql/statement.h" 11 #include "base/file_path.h" 12 #include "base/utf_string_conversions.h" 13 #include "build/build_config.h" 14 #include "chrome/browser/download/download_item.h" 15 #include "chrome/browser/history/download_create_info.h" 16 17 // Download schema: 18 // 19 // id SQLite-generated primary key. 20 // full_path Location of the download on disk. 21 // url URL of the downloaded file. 22 // start_time When the download was started. 23 // received_bytes Total size downloaded. 24 // total_bytes Total size of the download. 25 // state Identifies if this download is completed or not. Not used 26 // directly by the history system. See DownloadItem's 27 // DownloadState for where this is used. 28 29 namespace history { 30 31 namespace { 32 33 #if defined(OS_POSIX) 34 35 // Binds/reads the given file path to the given column of the given statement. 36 void BindFilePath(sql::Statement& statement, const FilePath& path, int col) { 37 statement.BindString(col, path.value()); 38 } 39 FilePath ColumnFilePath(sql::Statement& statement, int col) { 40 return FilePath(statement.ColumnString(col)); 41 } 42 43 #else 44 45 // See above. 46 void BindFilePath(sql::Statement& statement, const FilePath& path, int col) { 47 statement.BindString(col, UTF16ToUTF8(path.value())); 48 } 49 FilePath ColumnFilePath(sql::Statement& statement, int col) { 50 return FilePath(UTF8ToUTF16(statement.ColumnString(col))); 51 } 52 53 #endif 54 55 } // namespace 56 57 DownloadDatabase::DownloadDatabase() { 58 } 59 60 DownloadDatabase::~DownloadDatabase() { 61 } 62 63 bool DownloadDatabase::InitDownloadTable() { 64 if (!GetDB().DoesTableExist("downloads")) { 65 if (!GetDB().Execute( 66 "CREATE TABLE downloads (" 67 "id INTEGER PRIMARY KEY," 68 "full_path LONGVARCHAR NOT NULL," 69 "url LONGVARCHAR NOT NULL," 70 "start_time INTEGER NOT NULL," 71 "received_bytes INTEGER NOT NULL," 72 "total_bytes INTEGER NOT NULL," 73 "state INTEGER NOT NULL)")) 74 return false; 75 } 76 return true; 77 } 78 79 bool DownloadDatabase::DropDownloadTable() { 80 return GetDB().Execute("DROP TABLE downloads"); 81 } 82 83 void DownloadDatabase::QueryDownloads( 84 std::vector<DownloadCreateInfo>* results) { 85 results->clear(); 86 87 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 88 "SELECT id, full_path, url, start_time, received_bytes, " 89 "total_bytes, state " 90 "FROM downloads " 91 "ORDER BY start_time")); 92 if (!statement) 93 return; 94 95 while (statement.Step()) { 96 DownloadCreateInfo info; 97 info.db_handle = statement.ColumnInt64(0); 98 99 info.path = ColumnFilePath(statement, 1); 100 info.url_chain.push_back(GURL(statement.ColumnString(2))); 101 info.start_time = base::Time::FromTimeT(statement.ColumnInt64(3)); 102 info.received_bytes = statement.ColumnInt64(4); 103 info.total_bytes = statement.ColumnInt64(5); 104 info.state = statement.ColumnInt(6); 105 results->push_back(info); 106 } 107 } 108 109 bool DownloadDatabase::UpdateDownload(int64 received_bytes, 110 int32 state, 111 DownloadID db_handle) { 112 DCHECK(db_handle > 0); 113 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 114 "UPDATE downloads " 115 "SET received_bytes=?, state=? WHERE id=?")); 116 if (!statement) 117 return false; 118 119 statement.BindInt64(0, received_bytes); 120 statement.BindInt(1, state); 121 statement.BindInt64(2, db_handle); 122 return statement.Run(); 123 } 124 125 bool DownloadDatabase::UpdateDownloadPath(const FilePath& path, 126 DownloadID db_handle) { 127 DCHECK(db_handle > 0); 128 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 129 "UPDATE downloads SET full_path=? WHERE id=?")); 130 if (!statement) 131 return false; 132 133 BindFilePath(statement, path, 0); 134 statement.BindInt64(1, db_handle); 135 return statement.Run(); 136 } 137 138 bool DownloadDatabase::CleanUpInProgressEntries() { 139 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 140 "UPDATE downloads SET state=? WHERE state=?")); 141 if (!statement) 142 return false; 143 statement.BindInt(0, DownloadItem::CANCELLED); 144 statement.BindInt(1, DownloadItem::IN_PROGRESS); 145 return statement.Run(); 146 } 147 148 int64 DownloadDatabase::CreateDownload(const DownloadCreateInfo& info) { 149 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 150 "INSERT INTO downloads " 151 "(full_path, url, start_time, received_bytes, total_bytes, state) " 152 "VALUES (?, ?, ?, ?, ?, ?)")); 153 if (!statement) 154 return 0; 155 156 BindFilePath(statement, info.path, 0); 157 statement.BindString(1, info.url().spec()); 158 statement.BindInt64(2, info.start_time.ToTimeT()); 159 statement.BindInt64(3, info.received_bytes); 160 statement.BindInt64(4, info.total_bytes); 161 statement.BindInt(5, info.state); 162 163 if (statement.Run()) 164 return GetDB().GetLastInsertRowId(); 165 return 0; 166 } 167 168 void DownloadDatabase::RemoveDownload(DownloadID db_handle) { 169 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 170 "DELETE FROM downloads WHERE id=?")); 171 if (!statement) 172 return; 173 174 statement.BindInt64(0, db_handle); 175 statement.Run(); 176 } 177 178 void DownloadDatabase::RemoveDownloadsBetween(base::Time delete_begin, 179 base::Time delete_end) { 180 // This does not use an index. We currently aren't likely to have enough 181 // downloads where an index by time will give us a lot of benefit. 182 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 183 "DELETE FROM downloads WHERE start_time >= ? AND start_time < ? " 184 "AND (State = ? OR State = ? OR State = ?)")); 185 if (!statement) 186 return; 187 188 time_t start_time = delete_begin.ToTimeT(); 189 time_t end_time = delete_end.ToTimeT(); 190 statement.BindInt64(0, start_time); 191 statement.BindInt64( 192 1, 193 end_time ? end_time : std::numeric_limits<int64>::max()); 194 statement.BindInt(2, DownloadItem::COMPLETE); 195 statement.BindInt(3, DownloadItem::CANCELLED); 196 statement.BindInt(4, DownloadItem::INTERRUPTED); 197 statement.Run(); 198 } 199 200 } // namespace history 201