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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 void DownloadHistory::HistoryAdapter::UpdateDownload( | 185 void DownloadHistory::HistoryAdapter::UpdateDownload( |
173 const history::DownloadRow& data) { | 186 const history::DownloadRow& data) { |
174 history_->UpdateDownload(data); | 187 history_->UpdateDownload(data); |
175 } | 188 } |
176 | 189 |
177 void DownloadHistory::HistoryAdapter::RemoveDownloads( | 190 void DownloadHistory::HistoryAdapter::RemoveDownloads( |
178 const std::set<uint32>& ids) { | 191 const std::set<uint32>& ids) { |
179 history_->RemoveDownloads(ids); | 192 history_->RemoveDownloads(ids); |
180 } | 193 } |
181 | 194 |
182 | |
183 DownloadHistory::Observer::Observer() {} | 195 DownloadHistory::Observer::Observer() {} |
184 DownloadHistory::Observer::~Observer() {} | 196 DownloadHistory::Observer::~Observer() {} |
185 | 197 |
186 bool DownloadHistory::IsPersisted(content::DownloadItem* item) { | 198 // static |
187 DownloadHistoryData* data = DownloadHistoryData::Get(item); | 199 bool DownloadHistory::IsPersisted(const content::DownloadItem* item) { |
| 200 const DownloadHistoryData* data = DownloadHistoryData::Get(item); |
188 return data && (data->state() == DownloadHistoryData::PERSISTED); | 201 return data && (data->state() == DownloadHistoryData::PERSISTED); |
189 } | 202 } |
190 | 203 |
191 DownloadHistory::DownloadHistory(content::DownloadManager* manager, | 204 DownloadHistory::DownloadHistory(content::DownloadManager* manager, |
192 scoped_ptr<HistoryAdapter> history) | 205 scoped_ptr<HistoryAdapter> history) |
193 : notifier_(manager, this), | 206 : notifier_(manager, this), |
194 history_(history.Pass()), | 207 history_(history.Pass()), |
195 loading_id_(content::DownloadItem::kInvalidId), | 208 loading_id_(content::DownloadItem::kInvalidId), |
196 history_size_(0), | 209 history_size_(0), |
197 weak_ptr_factory_(this) { | 210 weak_ptr_factory_(this) { |
(...skipping 17 matching lines...) Expand all Loading... |
215 void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { | 228 void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { |
216 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 229 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
217 observers_.AddObserver(observer); | 230 observers_.AddObserver(observer); |
218 } | 231 } |
219 | 232 |
220 void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { | 233 void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { |
221 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 234 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
222 observers_.RemoveObserver(observer); | 235 observers_.RemoveObserver(observer); |
223 } | 236 } |
224 | 237 |
| 238 bool DownloadHistory::WasRestoredFromHistory( |
| 239 const content::DownloadItem* download) const { |
| 240 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 241 const DownloadHistoryData* data = DownloadHistoryData::Get(download); |
| 242 |
| 243 // The OnDownloadCreated handler sets the was_restored_from_history flag when |
| 244 // resetting the loading_id_. So one of the two conditions below will hold for |
| 245 // a download restored from history even if the caller of this method is |
| 246 // racing with our OnDownloadCreated handler. |
| 247 return (data && data->was_restored_from_history()) || |
| 248 download->GetId() == loading_id_; |
| 249 } |
| 250 |
225 void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { | 251 void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { |
226 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 252 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
227 // ManagerGoingDown() may have happened before the history loaded. | 253 // ManagerGoingDown() may have happened before the history loaded. |
228 if (!notifier_.GetManager()) | 254 if (!notifier_.GetManager()) |
229 return; | 255 return; |
230 for (InfoVector::const_iterator it = infos->begin(); | 256 for (InfoVector::const_iterator it = infos->begin(); |
231 it != infos->end(); ++it) { | 257 it != infos->end(); ++it) { |
232 loading_id_ = it->id; | 258 loading_id_ = it->id; |
233 content::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( | 259 content::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( |
234 loading_id_, | 260 loading_id_, |
(...skipping 11 matching lines...) Expand all Loading... |
246 it->danger_type, | 272 it->danger_type, |
247 it->interrupt_reason, | 273 it->interrupt_reason, |
248 it->opened); | 274 it->opened); |
249 #if !defined(OS_ANDROID) | 275 #if !defined(OS_ANDROID) |
250 if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) { | 276 if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) { |
251 new extensions::DownloadedByExtension( | 277 new extensions::DownloadedByExtension( |
252 item, it->by_ext_id, it->by_ext_name); | 278 item, it->by_ext_id, it->by_ext_name); |
253 item->UpdateObservers(); | 279 item->UpdateObservers(); |
254 } | 280 } |
255 #endif | 281 #endif |
256 DCHECK_EQ(DownloadHistoryData::Get(item)->state(), | 282 DCHECK_EQ(DownloadHistoryData::PERSISTED, |
257 DownloadHistoryData::PERSISTED); | 283 DownloadHistoryData::Get(item)->state()); |
258 ++history_size_; | 284 ++history_size_; |
259 } | 285 } |
260 notifier_.GetManager()->CheckForHistoryFilesRemoval(); | 286 notifier_.GetManager()->CheckForHistoryFilesRemoval(); |
261 } | 287 } |
262 | 288 |
263 void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { | 289 void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { |
264 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 290 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
265 | 291 |
266 uint32 download_id = item->GetId(); | 292 uint32 download_id = item->GetId(); |
267 DownloadHistoryData* data = DownloadHistoryData::Get(item); | 293 DownloadHistoryData* data = DownloadHistoryData::Get(item); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 | 365 |
340 void DownloadHistory::OnDownloadCreated( | 366 void DownloadHistory::OnDownloadCreated( |
341 content::DownloadManager* manager, content::DownloadItem* item) { | 367 content::DownloadManager* manager, content::DownloadItem* item) { |
342 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 368 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
343 | 369 |
344 // All downloads should pass through OnDownloadCreated exactly once. | 370 // All downloads should pass through OnDownloadCreated exactly once. |
345 CHECK(!DownloadHistoryData::Get(item)); | 371 CHECK(!DownloadHistoryData::Get(item)); |
346 DownloadHistoryData* data = new DownloadHistoryData(item); | 372 DownloadHistoryData* data = new DownloadHistoryData(item); |
347 if (item->GetId() == loading_id_) { | 373 if (item->GetId() == loading_id_) { |
348 data->SetState(DownloadHistoryData::PERSISTED); | 374 data->SetState(DownloadHistoryData::PERSISTED); |
| 375 data->set_was_restored_from_history(true); |
349 loading_id_ = content::DownloadItem::kInvalidId; | 376 loading_id_ = content::DownloadItem::kInvalidId; |
350 } | 377 } |
351 if (item->GetState() == content::DownloadItem::IN_PROGRESS) { | 378 if (item->GetState() == content::DownloadItem::IN_PROGRESS) { |
352 data->set_info(GetDownloadRow(item)); | 379 data->set_info(GetDownloadRow(item)); |
353 } | 380 } |
354 MaybeAddToHistory(item); | 381 MaybeAddToHistory(item); |
355 } | 382 } |
356 | 383 |
357 void DownloadHistory::OnDownloadUpdated( | 384 void DownloadHistory::OnDownloadUpdated( |
358 content::DownloadManager* manager, content::DownloadItem* item) { | 385 content::DownloadManager* manager, content::DownloadItem* item) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 removing_ids_.insert(download_id); | 451 removing_ids_.insert(download_id); |
425 } | 452 } |
426 | 453 |
427 void DownloadHistory::RemoveDownloadsBatch() { | 454 void DownloadHistory::RemoveDownloadsBatch() { |
428 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 455 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
429 IdSet remove_ids; | 456 IdSet remove_ids; |
430 removing_ids_.swap(remove_ids); | 457 removing_ids_.swap(remove_ids); |
431 history_->RemoveDownloads(remove_ids); | 458 history_->RemoveDownloads(remove_ids); |
432 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadsRemoved(remove_ids)); | 459 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadsRemoved(remove_ids)); |
433 } | 460 } |
OLD | NEW |