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) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DownloadHistory manages persisting DownloadItems to the history service by 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// observing a single DownloadManager and all its DownloadItems using an 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// AllDownloadItemNotifier. 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DownloadHistory decides whether and when to add items to, remove items from, 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and update items in the database. DownloadHistory uses DownloadHistoryData to 117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// store per-DownloadItem data such as whether the item is persisted or being 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// persisted, and the last history::DownloadRow that was passed to the database. 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// When the DownloadManager and its delegate (ChromeDownloadManagerDelegate) are 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// initialized, DownloadHistory is created and queries the HistoryService. When 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// the HistoryService calls back from QueryDownloads() to QueryCallback(), 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// DownloadHistory uses DownloadManager::CreateDownloadItem() to inform 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// DownloadManager of these persisted DownloadItems. CreateDownloadItem() 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// internally calls OnDownloadCreated(), which normally adds items to the 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// database, so QueryCallback() uses |loading_id_| to disable adding these items 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// to the database. If a download is removed via OnDownloadRemoved() while the 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// item is still being added to the database, DownloadHistory uses 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |removed_while_adding_| to remember to remove the item when its ItemAdded() 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// callback is called. All callbacks are bound with a weak pointer to 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// DownloadHistory to prevent use-after-free bugs. 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ChromeDownloadManagerDelegate owns DownloadHistory, and deletes it in 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Shutdown(), which is called by DownloadManagerImpl::Shutdown() after all 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DownloadItems are destroyed. 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_history.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_crx_util.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/download_database.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/download_row.h" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_item.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/download_manager.h" 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS) 41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/extensions/api/downloads/downloads_api.h" 42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Per-DownloadItem data. This information does not belong inside DownloadItem, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and keeping maps in DownloadHistory from DownloadItem to this information is 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// error-prone and complicated. Unfortunately, DownloadHistory::removing_*_ and 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// removed_while_adding_ cannot be moved into this class partly because 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DownloadHistoryData is destroyed when DownloadItems are destroyed, and we 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// have no control over when DownloadItems are destroyed. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DownloadHistoryData : public base::SupportsUserData::Data { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch enum PersistenceState { 557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NOT_PERSISTED, 567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PERSISTING, 577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PERSISTED, 587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch }; 597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static DownloadHistoryData* Get(content::DownloadItem* item) { 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SupportsUserData::Data* data = item->GetUserData(kKey); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (data == NULL) ? NULL : 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<DownloadHistoryData*>(data); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static const DownloadHistoryData* Get(const content::DownloadItem* item) { 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::SupportsUserData::Data* data = item->GetUserData(kKey); 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (data == NULL) ? NULL 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : static_cast<const DownloadHistoryData*>(data); 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch explicit DownloadHistoryData(content::DownloadItem* item) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : state_(NOT_PERSISTED), 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) was_restored_from_history_(false) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->SetUserData(kKey, this); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~DownloadHistoryData() { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PersistenceState state() const { return state_; } 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch void SetState(PersistenceState s) { state_ = s; } 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool was_restored_from_history() const { return was_restored_from_history_; } 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void set_was_restored_from_history(bool value) { 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) was_restored_from_history_ = value; 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This allows DownloadHistory::OnDownloadUpdated() to see what changed in a 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DownloadItem if anything, in order to prevent writing to the database 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // unnecessarily. It is nullified when the item is no longer in progress in 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // order to save memory. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::DownloadRow* info() { return info_.get(); } 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void set_info(const history::DownloadRow& i) { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info_.reset(new history::DownloadRow(i)); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void clear_info() { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info_.reset(); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const char kKey[]; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PersistenceState state_; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<history::DownloadRow> info_; 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool was_restored_from_history_; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DownloadHistoryData); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char DownloadHistoryData::kKey[] = 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "DownloadItem DownloadHistoryData"; 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)history::DownloadRow GetDownloadRow( 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadItem* item) { 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::string by_ext_id, by_ext_name; 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS) 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu extensions::DownloadedByExtension* by_ext = 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu extensions::DownloadedByExtension::Get(item); 120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (by_ext) { 121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) by_ext_id = by_ext->id(); 122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) by_ext_name = by_ext->name(); 123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return history::DownloadRow( 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetFullPath(), 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetTargetFilePath(), 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetUrlChain(), 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetReferrerUrl(), 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) item->GetMimeType(), 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) item->GetOriginalMimeType(), 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetStartTime(), 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetEndTime(), 135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch item->GetETag(), 136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch item->GetLastModifiedTime(), 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetReceivedBytes(), 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetTotalBytes(), 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetState(), 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetDangerType(), 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->GetLastReason(), 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch item->GetId(), 143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) item->GetOpened(), 144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) by_ext_id, 145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) by_ext_name); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ShouldUpdateHistory(const history::DownloadRow* previous, 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const history::DownloadRow& current) { 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ignore url, referrer, mime_type, original_mime_type, start_time, 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // id, db_handle, which don't change. 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ((previous == NULL) || 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->current_path != current.current_path) || 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->target_path != current.target_path) || 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->end_time != current.end_time) || 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->received_bytes != current.received_bytes) || 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->total_bytes != current.total_bytes) || 158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (previous->etag != current.etag) || 159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch (previous->last_modified != current.last_modified) || 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->state != current.state) || 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->danger_type != current.danger_type) || 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (previous->interrupt_reason != current.interrupt_reason) || 163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (previous->opened != current.opened) || 164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (previous->by_ext_id != current.by_ext_id) || 165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (previous->by_ext_name != current.by_ext_name)); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::vector<history::DownloadRow> InfoVector; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // anonymous namespace 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadHistory::HistoryAdapter::HistoryAdapter(HistoryService* history) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : history_(history) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadHistory::HistoryAdapter::~HistoryAdapter() {} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::HistoryAdapter::QueryDownloads( 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HistoryService::DownloadQueryCallback& callback) { 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_->QueryDownloads(callback); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::HistoryAdapter::CreateDownload( 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const history::DownloadRow& info, 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HistoryService::DownloadCreateCallback& callback) { 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_->CreateDownload(info, callback); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::HistoryAdapter::UpdateDownload( 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const history::DownloadRow& data) { 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_->UpdateDownload(data); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::HistoryAdapter::RemoveDownloads( 1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::set<uint32>& ids) { 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch history_->RemoveDownloads(ids); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadHistory::Observer::Observer() {} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadHistory::Observer::~Observer() {} 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DownloadHistory::IsPersisted(const content::DownloadItem* item) { 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DownloadHistoryData* data = DownloadHistoryData::Get(item); 2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return data && (data->state() == DownloadHistoryData::PERSISTED); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DownloadHistory::DownloadHistory(content::DownloadManager* manager, 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<HistoryAdapter> history) 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : notifier_(manager, this), 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_(history.Pass()), 2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch loading_id_(content::DownloadItem::kInvalidId), 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_size_(0), 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadManager::DownloadVector items; 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notifier_.GetManager()->GetAllDownloads(&items); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (content::DownloadManager::DownloadVector::const_iterator 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it = items.begin(); it != items.end(); ++it) { 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnDownloadCreated(notifier_.GetManager(), *it); 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_->QueryDownloads(base::Bind( 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &DownloadHistory::QueryCallback, weak_ptr_factory_.GetWeakPtr())); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadHistory::~DownloadHistory() { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, OnDownloadHistoryDestroyed()); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observers_.Clear(); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observers_.AddObserver(observer); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observers_.RemoveObserver(observer); 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DownloadHistory::WasRestoredFromHistory( 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::DownloadItem* download) const { 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DownloadHistoryData* data = DownloadHistoryData::Get(download); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The OnDownloadCreated handler sets the was_restored_from_history flag when 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // resetting the loading_id_. So one of the two conditions below will hold for 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // a download restored from history even if the caller of this method is 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // racing with our OnDownloadCreated handler. 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (data && data->was_restored_from_history()) || 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) download->GetId() == loading_id_; 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ManagerGoingDown() may have happened before the history loaded. 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!notifier_.GetManager()) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (InfoVector::const_iterator it = infos->begin(); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != infos->end(); ++it) { 2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch loading_id_ = it->id; 2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch content::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( 2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch loading_id_, 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->current_path, 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->target_path, 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->url_chain, 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->referrer_url, 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) it->mime_type, 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) it->original_mime_type, 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->start_time, 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->end_time, 272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->etag, 273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->last_modified, 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->received_bytes, 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->total_bytes, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->state, 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->danger_type, 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->interrupt_reason, 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->opened); 28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS) 281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) { 2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new extensions::DownloadedByExtension( 2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu item, it->by_ext_id, it->by_ext_name); 284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) item->UpdateObservers(); 285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(DownloadHistoryData::PERSISTED, 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DownloadHistoryData::Get(item)->state()); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++history_size_; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notifier_.GetManager()->CheckForHistoryFilesRemoval(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch uint32 download_id = item->GetId(); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadHistoryData* data = DownloadHistoryData::Get(item); 2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool removing = removing_ids_.find(download_id) != removing_ids_.end(); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(benjhayden): Remove IsTemporary(). 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (download_crx_util::IsExtensionDownload(*item) || 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item->IsTemporary() || 3047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (data->state() != DownloadHistoryData::NOT_PERSISTED) || 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) removing) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data->SetState(DownloadHistoryData::PERSISTING); 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data->info() == NULL) { 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Keep the info here regardless of whether the item is in progress so that, 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // when ItemAdded() calls OnDownloadUpdated(), it can decide whether to 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update the db and/or clear the info. 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data->set_info(GetDownloadRow(item)); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_->CreateDownload(*data->info(), base::Bind( 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &DownloadHistory::ItemAdded, weak_ptr_factory_.GetWeakPtr(), 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) download_id)); 3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch FOR_EACH_OBSERVER(Observer, observers_, OnDownloadStored( 3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch item, *data->info())); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DownloadHistory::ItemAdded(uint32 download_id, bool success) { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (removed_while_adding_.find(download_id) != 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) removed_while_adding_.end()) { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) removed_while_adding_.erase(download_id); 3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (success) 3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleRemoveDownload(download_id); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!notifier_.GetManager()) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadItem* item = notifier_.GetManager()->GetDownload( 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) download_id); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!item) { 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This item will have called OnDownloadDestroyed(). If the item should 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have been removed from history, then it would have also called 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OnDownloadRemoved(), which would have put |download_id| in 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // removed_while_adding_, handled above. 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadHistoryData* data = DownloadHistoryData::Get(item); 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The sql INSERT statement failed. Avoid an infinite loop: don't 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // automatically retry. Retry adding the next time the item is updated by 3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // resetting the state to NOT_PERSISTED. 3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!success) { 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(20) << __FUNCTION__ << " INSERT failed id=" << download_id; 3527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data->SetState(DownloadHistoryData::NOT_PERSISTED); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data->SetState(DownloadHistoryData::PERSISTED); 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Download.HistorySize2", 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_size_, 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0/*min*/, 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (1 << 23)/*max*/, 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (1 << 7)/*num_buckets*/); 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++history_size_; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In case the item changed or became temporary while it was being added. 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't just update all of the item's observers because we're the only 3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // observer that can also see data->state(), which is the only thing that 3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // ItemAdded() changed. 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnDownloadUpdated(notifier_.GetManager(), item); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::OnDownloadCreated( 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadManager* manager, content::DownloadItem* item) { 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // All downloads should pass through OnDownloadCreated exactly once. 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!DownloadHistoryData::Get(item)); 3777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DownloadHistoryData* data = new DownloadHistoryData(item); 3787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (item->GetId() == loading_id_) { 3797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data->SetState(DownloadHistoryData::PERSISTED); 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data->set_was_restored_from_history(true); 3817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch loading_id_ = content::DownloadItem::kInvalidId; 3827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item->GetState() == content::DownloadItem::IN_PROGRESS) { 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data->set_info(GetDownloadRow(item)); 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MaybeAddToHistory(item); 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::OnDownloadUpdated( 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadManager* manager, content::DownloadItem* item) { 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadHistoryData* data = DownloadHistoryData::Get(item); 3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (data->state() == DownloadHistoryData::NOT_PERSISTED) { 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MaybeAddToHistory(item); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item->IsTemporary()) { 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnDownloadRemoved(notifier_.GetManager(), item); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::DownloadRow current_info(GetDownloadRow(item)); 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool should_update = ShouldUpdateHistory(data->info(), current_info); 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Download.HistoryPropagatedUpdate", 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) should_update, 2); 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (should_update) { 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history_->UpdateDownload(current_info); 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, OnDownloadStored( 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item, current_info)); 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item->GetState() == content::DownloadItem::IN_PROGRESS) { 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data->set_info(current_info); 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data->clear_info(); 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::OnDownloadOpened( 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadManager* manager, content::DownloadItem* item) { 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnDownloadUpdated(manager, item); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::OnDownloadRemoved( 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadManager* manager, content::DownloadItem* item) { 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadHistoryData* data = DownloadHistoryData::Get(item); 4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (data->state() != DownloadHistoryData::PERSISTED) { 4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (data->state() == DownloadHistoryData::PERSISTING) { 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ScheduleRemoveDownload will be called when history_ calls ItemAdded(). 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) removed_while_adding_.insert(item->GetId()); 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleRemoveDownload(item->GetId()); 4377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // This is important: another OnDownloadRemoved() handler could do something 4387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // that synchronously fires an OnDownloadUpdated(). 4397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch data->SetState(DownloadHistoryData::NOT_PERSISTED); 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ItemAdded increments history_size_ only if the item wasn't 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // removed_while_adding_, so the next line does not belong in 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ScheduleRemoveDownload(). 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --history_size_; 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DownloadHistory::ScheduleRemoveDownload(uint32 download_id) { 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For database efficiency, batch removals together if they happen all at 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // once. 4517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (removing_ids_.empty()) { 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DownloadHistory::RemoveDownloadsBatch, 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) removing_ids_.insert(download_id); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadHistory::RemoveDownloadsBatch() { 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IdSet remove_ids; 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) removing_ids_.swap(remove_ids); 4637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch history_->RemoveDownloads(remove_ids); 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, OnDownloadsRemoved(remove_ids)); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 466