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