| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // DownloadHistory manages persisting DownloadItems to the history service by | 5 // DownloadHistory manages persisting DownloadItems to the history service by |
| 6 // observing a single DownloadManager and all its DownloadItems using an | 6 // observing a single DownloadManager and all its DownloadItems using an |
| 7 // AllDownloadItemNotifier. | 7 // AllDownloadItemNotifier. |
| 8 // | 8 // |
| 9 // DownloadHistory decides whether and when to add items to, remove items from, | 9 // DownloadHistory decides whether and when to add items to, remove items from, |
| 10 // and update items in the database. DownloadHistory uses DownloadHistoryData to | 10 // and update items in the database. DownloadHistory uses DownloadHistoryData to |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 PERSISTING, | 56 PERSISTING, |
| 57 PERSISTED, | 57 PERSISTED, |
| 58 }; | 58 }; |
| 59 | 59 |
| 60 static DownloadHistoryData* Get(content::DownloadItem* item) { | 60 static DownloadHistoryData* Get(content::DownloadItem* item) { |
| 61 base::SupportsUserData::Data* data = item->GetUserData(kKey); | 61 base::SupportsUserData::Data* data = item->GetUserData(kKey); |
| 62 return (data == NULL) ? NULL : | 62 return (data == NULL) ? NULL : |
| 63 static_cast<DownloadHistoryData*>(data); | 63 static_cast<DownloadHistoryData*>(data); |
| 64 } | 64 } |
| 65 | 65 |
| 66 static const DownloadHistoryData* Get(const content::DownloadItem* item) { |
| 67 const base::SupportsUserData::Data* data = item->GetUserData(kKey); |
| 68 return (data == NULL) ? NULL |
| 69 : static_cast<const DownloadHistoryData*>(data); |
| 70 } |
| 71 |
| 66 explicit DownloadHistoryData(content::DownloadItem* item) | 72 explicit DownloadHistoryData(content::DownloadItem* item) |
| 67 : state_(NOT_PERSISTED) { | 73 : state_(NOT_PERSISTED), |
| 74 was_restored_from_history_(false) { |
| 68 item->SetUserData(kKey, this); | 75 item->SetUserData(kKey, this); |
| 69 } | 76 } |
| 70 | 77 |
| 71 virtual ~DownloadHistoryData() { | 78 virtual ~DownloadHistoryData() { |
| 72 } | 79 } |
| 73 | 80 |
| 74 PersistenceState state() const { return state_; } | 81 PersistenceState state() const { return state_; } |
| 75 void SetState(PersistenceState s) { state_ = s; } | 82 void SetState(PersistenceState s) { state_ = s; } |
| 76 | 83 |
| 84 bool was_restored_from_history() const { return was_restored_from_history_; } |
| 85 void set_was_restored_from_history(bool value) { |
| 86 was_restored_from_history_ = value; |
| 87 } |
| 88 |
| 77 // This allows DownloadHistory::OnDownloadUpdated() to see what changed in a | 89 // This allows DownloadHistory::OnDownloadUpdated() to see what changed in a |
| 78 // DownloadItem if anything, in order to prevent writing to the database | 90 // DownloadItem if anything, in order to prevent writing to the database |
| 79 // unnecessarily. It is nullified when the item is no longer in progress in | 91 // unnecessarily. It is nullified when the item is no longer in progress in |
| 80 // order to save memory. | 92 // order to save memory. |
| 81 history::DownloadRow* info() { return info_.get(); } | 93 history::DownloadRow* info() { return info_.get(); } |
| 82 void set_info(const history::DownloadRow& i) { | 94 void set_info(const history::DownloadRow& i) { |
| 83 info_.reset(new history::DownloadRow(i)); | 95 info_.reset(new history::DownloadRow(i)); |
| 84 } | 96 } |
| 85 void clear_info() { | 97 void clear_info() { |
| 86 info_.reset(); | 98 info_.reset(); |
| 87 } | 99 } |
| 88 | 100 |
| 89 private: | 101 private: |
| 90 static const char kKey[]; | 102 static const char kKey[]; |
| 91 | 103 |
| 92 PersistenceState state_; | 104 PersistenceState state_; |
| 93 scoped_ptr<history::DownloadRow> info_; | 105 scoped_ptr<history::DownloadRow> info_; |
| 106 bool was_restored_from_history_; |
| 94 | 107 |
| 95 DISALLOW_COPY_AND_ASSIGN(DownloadHistoryData); | 108 DISALLOW_COPY_AND_ASSIGN(DownloadHistoryData); |
| 96 }; | 109 }; |
| 97 | 110 |
| 98 const char DownloadHistoryData::kKey[] = | 111 const char DownloadHistoryData::kKey[] = |
| 99 "DownloadItem DownloadHistoryData"; | 112 "DownloadItem DownloadHistoryData"; |
| 100 | 113 |
| 101 history::DownloadRow GetDownloadRow( | 114 history::DownloadRow GetDownloadRow( |
| 102 content::DownloadItem* item) { | 115 content::DownloadItem* item) { |
| 103 std::string by_ext_id, by_ext_name; | 116 std::string by_ext_id, by_ext_name; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 void DownloadHistory::HistoryAdapter::UpdateDownload( | 184 void DownloadHistory::HistoryAdapter::UpdateDownload( |
| 172 const history::DownloadRow& data) { | 185 const history::DownloadRow& data) { |
| 173 history_->UpdateDownload(data); | 186 history_->UpdateDownload(data); |
| 174 } | 187 } |
| 175 | 188 |
| 176 void DownloadHistory::HistoryAdapter::RemoveDownloads( | 189 void DownloadHistory::HistoryAdapter::RemoveDownloads( |
| 177 const std::set<uint32>& ids) { | 190 const std::set<uint32>& ids) { |
| 178 history_->RemoveDownloads(ids); | 191 history_->RemoveDownloads(ids); |
| 179 } | 192 } |
| 180 | 193 |
| 181 | |
| 182 DownloadHistory::Observer::Observer() {} | 194 DownloadHistory::Observer::Observer() {} |
| 183 DownloadHistory::Observer::~Observer() {} | 195 DownloadHistory::Observer::~Observer() {} |
| 184 | 196 |
| 185 bool DownloadHistory::IsPersisted(content::DownloadItem* item) { | 197 // static |
| 186 DownloadHistoryData* data = DownloadHistoryData::Get(item); | 198 bool DownloadHistory::IsPersisted(const content::DownloadItem* item) { |
| 199 const DownloadHistoryData* data = DownloadHistoryData::Get(item); |
| 187 return data && (data->state() == DownloadHistoryData::PERSISTED); | 200 return data && (data->state() == DownloadHistoryData::PERSISTED); |
| 188 } | 201 } |
| 189 | 202 |
| 190 DownloadHistory::DownloadHistory(content::DownloadManager* manager, | 203 DownloadHistory::DownloadHistory(content::DownloadManager* manager, |
| 191 scoped_ptr<HistoryAdapter> history) | 204 scoped_ptr<HistoryAdapter> history) |
| 192 : notifier_(manager, this), | 205 : notifier_(manager, this), |
| 193 history_(history.Pass()), | 206 history_(history.Pass()), |
| 194 loading_id_(content::DownloadItem::kInvalidId), | 207 loading_id_(content::DownloadItem::kInvalidId), |
| 195 history_size_(0), | 208 history_size_(0), |
| 196 weak_ptr_factory_(this) { | 209 weak_ptr_factory_(this) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 214 void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { | 227 void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { |
| 215 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 228 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 216 observers_.AddObserver(observer); | 229 observers_.AddObserver(observer); |
| 217 } | 230 } |
| 218 | 231 |
| 219 void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { | 232 void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { |
| 220 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 233 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 221 observers_.RemoveObserver(observer); | 234 observers_.RemoveObserver(observer); |
| 222 } | 235 } |
| 223 | 236 |
| 237 bool DownloadHistory::WasRestoredFromHistory( |
| 238 const content::DownloadItem* download) const { |
| 239 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 240 const DownloadHistoryData* data = DownloadHistoryData::Get(download); |
| 241 |
| 242 // The OnDownloadCreated handler sets the was_restored_from_history flag when |
| 243 // resetting the loading_id_. So one of the two conditions below will hold for |
| 244 // a download restored from history even if the caller of this method is |
| 245 // racing with our OnDownloadCreated handler. |
| 246 return (data && data->was_restored_from_history()) || |
| 247 download->GetId() == loading_id_; |
| 248 } |
| 249 |
| 224 void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { | 250 void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { |
| 225 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 251 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 226 // ManagerGoingDown() may have happened before the history loaded. | 252 // ManagerGoingDown() may have happened before the history loaded. |
| 227 if (!notifier_.GetManager()) | 253 if (!notifier_.GetManager()) |
| 228 return; | 254 return; |
| 229 for (InfoVector::const_iterator it = infos->begin(); | 255 for (InfoVector::const_iterator it = infos->begin(); |
| 230 it != infos->end(); ++it) { | 256 it != infos->end(); ++it) { |
| 231 loading_id_ = it->id; | 257 loading_id_ = it->id; |
| 232 content::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( | 258 content::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( |
| 233 loading_id_, | 259 loading_id_, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 244 it->state, | 270 it->state, |
| 245 it->danger_type, | 271 it->danger_type, |
| 246 it->interrupt_reason, | 272 it->interrupt_reason, |
| 247 it->opened); | 273 it->opened); |
| 248 #if !defined(OS_ANDROID) | 274 #if !defined(OS_ANDROID) |
| 249 if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) { | 275 if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) { |
| 250 new DownloadedByExtension(item, it->by_ext_id, it->by_ext_name); | 276 new DownloadedByExtension(item, it->by_ext_id, it->by_ext_name); |
| 251 item->UpdateObservers(); | 277 item->UpdateObservers(); |
| 252 } | 278 } |
| 253 #endif | 279 #endif |
| 254 DCHECK_EQ(DownloadHistoryData::Get(item)->state(), | 280 DCHECK_EQ(DownloadHistoryData::PERSISTED, |
| 255 DownloadHistoryData::PERSISTED); | 281 DownloadHistoryData::Get(item)->state()); |
| 256 ++history_size_; | 282 ++history_size_; |
| 257 } | 283 } |
| 258 notifier_.GetManager()->CheckForHistoryFilesRemoval(); | 284 notifier_.GetManager()->CheckForHistoryFilesRemoval(); |
| 259 } | 285 } |
| 260 | 286 |
| 261 void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { | 287 void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { |
| 262 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 288 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 263 | 289 |
| 264 uint32 download_id = item->GetId(); | 290 uint32 download_id = item->GetId(); |
| 265 DownloadHistoryData* data = DownloadHistoryData::Get(item); | 291 DownloadHistoryData* data = DownloadHistoryData::Get(item); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 | 363 |
| 338 void DownloadHistory::OnDownloadCreated( | 364 void DownloadHistory::OnDownloadCreated( |
| 339 content::DownloadManager* manager, content::DownloadItem* item) { | 365 content::DownloadManager* manager, content::DownloadItem* item) { |
| 340 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 366 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 341 | 367 |
| 342 // All downloads should pass through OnDownloadCreated exactly once. | 368 // All downloads should pass through OnDownloadCreated exactly once. |
| 343 CHECK(!DownloadHistoryData::Get(item)); | 369 CHECK(!DownloadHistoryData::Get(item)); |
| 344 DownloadHistoryData* data = new DownloadHistoryData(item); | 370 DownloadHistoryData* data = new DownloadHistoryData(item); |
| 345 if (item->GetId() == loading_id_) { | 371 if (item->GetId() == loading_id_) { |
| 346 data->SetState(DownloadHistoryData::PERSISTED); | 372 data->SetState(DownloadHistoryData::PERSISTED); |
| 373 data->set_was_restored_from_history(true); |
| 347 loading_id_ = content::DownloadItem::kInvalidId; | 374 loading_id_ = content::DownloadItem::kInvalidId; |
| 348 } | 375 } |
| 349 if (item->GetState() == content::DownloadItem::IN_PROGRESS) { | 376 if (item->GetState() == content::DownloadItem::IN_PROGRESS) { |
| 350 data->set_info(GetDownloadRow(item)); | 377 data->set_info(GetDownloadRow(item)); |
| 351 } | 378 } |
| 352 MaybeAddToHistory(item); | 379 MaybeAddToHistory(item); |
| 353 } | 380 } |
| 354 | 381 |
| 355 void DownloadHistory::OnDownloadUpdated( | 382 void DownloadHistory::OnDownloadUpdated( |
| 356 content::DownloadManager* manager, content::DownloadItem* item) { | 383 content::DownloadManager* manager, content::DownloadItem* item) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 removing_ids_.insert(download_id); | 449 removing_ids_.insert(download_id); |
| 423 } | 450 } |
| 424 | 451 |
| 425 void DownloadHistory::RemoveDownloadsBatch() { | 452 void DownloadHistory::RemoveDownloadsBatch() { |
| 426 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 453 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 427 IdSet remove_ids; | 454 IdSet remove_ids; |
| 428 removing_ids_.swap(remove_ids); | 455 removing_ids_.swap(remove_ids); |
| 429 history_->RemoveDownloads(remove_ids); | 456 history_->RemoveDownloads(remove_ids); |
| 430 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadsRemoved(remove_ids)); | 457 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadsRemoved(remove_ids)); |
| 431 } | 458 } |
| OLD | NEW |