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 | |
6 // observing a single DownloadManager and all its DownloadItems. | |
7 // DownloadHistory decides whether and when to add items to, remove items from, | |
8 // and update items in the database. DownloadHistory uses DownloadHistoryData to | |
9 // store per-DownloadItem data such as its db_handle, whether the item is being | |
10 // added and waiting for its db_handle, and the last DownloadPersistentStoreInfo | |
11 // that was passed to the database. When the DownloadManager and its delegate | |
12 // (ChromeDownloadManagerDelegate) are initialized, DownloadHistory is created | |
13 // and queries the HistoryService. When the HistoryService calls back from | |
14 // QueryDownloads() to QueryCallback(), DownloadHistory uses | |
15 // DownloadManager::CreateDownloadItem() to inform DownloadManager of these | |
16 // persisted DownloadItems. CreateDownloadItem() internally calls | |
17 // OnDownloadCreated(), which normally adds items to the database, so | |
18 // QueryCallback() uses |loading_db_handle_| to disable adding these items to | |
19 // the database as it matches them up with their db_handles. If a download is | |
20 // removed via OnDownloadRemoved() while the item is still being added to the | |
21 // database, DownloadHistory uses |removed_while_adding_| to remember to remove | |
22 // the item when its ItemAdded() callback is called. All callbacks are bound | |
23 // with a weak pointer to DownloadHistory to prevent use-after-free bugs. | |
24 // ChromeDownloadManagerDelegate owns DownloadHistory, and deletes it in | |
25 // Shutdown(), which is called by DownloadManagerImpl::Shutdown() after all | |
26 // DownloadItems are destroyed. | |
27 | |
5 #include "chrome/browser/download/download_history.h" | 28 #include "chrome/browser/download/download_history.h" |
6 | 29 |
7 #include "base/logging.h" | 30 #include "base/metrics/histogram.h" |
8 #include "chrome/browser/download/download_crx_util.h" | 31 #include "chrome/browser/download/download_crx_util.h" |
9 #include "chrome/browser/history/history_marshaling.h" | 32 #include "chrome/browser/history/download_database.h" |
10 #include "chrome/browser/history/history_service_factory.h" | 33 #include "chrome/browser/history/download_persistent_store_info.h" |
11 #include "chrome/browser/profiles/profile.h" | 34 #include "content/public/browser/browser_thread.h" |
12 #include "content/public/browser/download_item.h" | 35 #include "content/public/browser/download_item.h" |
13 #include "content/public/browser/download_persistent_store_info.h" | 36 #include "content/public/browser/download_manager.h" |
14 | 37 |
38 using content::BrowserThread; | |
15 using content::DownloadItem; | 39 using content::DownloadItem; |
16 using content::DownloadPersistentStoreInfo; | 40 using content::DownloadManager; |
17 | 41 |
18 DownloadHistory::DownloadHistory(Profile* profile) | 42 namespace { |
19 : profile_(profile), | 43 |
20 next_fake_db_handle_(DownloadItem::kUninitializedHandle - 1) { | 44 // Per-DownloadItem data. This information does not belong inside DownloadItem, |
21 DCHECK(profile); | 45 // and keeping maps in DownloadHistory from DownloadItem to this information is |
22 } | 46 // error-prone and complicated. Unfortunately, DownloadHistory::removing_ and |
23 | 47 // removed_while_adding_ cannot be moved into this class partly because |
24 DownloadHistory::~DownloadHistory() {} | 48 // DownloadHistoryData is destroyed when DownloadItems are destroyed, and we |
25 | 49 // have no control over when DownloadItems are destroyed. |
26 void DownloadHistory::GetNextId( | 50 class DownloadHistoryData : public base::SupportsUserData::Data { |
27 const HistoryService::DownloadNextIdCallback& callback) { | 51 public: |
28 HistoryService* hs = HistoryServiceFactory::GetForProfile( | 52 static DownloadHistoryData* Get(DownloadItem* item) { |
29 profile_, Profile::EXPLICIT_ACCESS); | 53 base::SupportsUserData::Data* data = item->GetUserData(kKey); |
30 if (!hs) | 54 return (data == NULL) ? NULL : |
31 return; | 55 static_cast<DownloadHistoryData*>(data); |
32 | 56 } |
33 hs->GetNextDownloadId(&history_consumer_, callback); | 57 |
34 } | 58 DownloadHistoryData(DownloadItem* item, int64 handle) |
35 | 59 : is_adding_(false), |
36 void DownloadHistory::Load( | 60 db_handle_(handle), |
37 const HistoryService::DownloadQueryCallback& callback) { | 61 info_(NULL) { |
38 HistoryService* hs = HistoryServiceFactory::GetForProfile( | 62 item->SetUserData(kKey, this); |
39 profile_, Profile::EXPLICIT_ACCESS); | 63 } |
40 if (!hs) | 64 |
41 return; | 65 virtual ~DownloadHistoryData() { |
42 | 66 } |
43 hs->QueryDownloads(&history_consumer_, callback); | 67 |
44 | 68 // Whether this item is currently being added to the database. |
45 // This is the initial load, so do a cleanup of corrupt in-progress entries. | 69 bool is_adding() const { return is_adding_; } |
46 hs->CleanUpInProgressEntries(); | 70 void set_is_adding(bool a) { is_adding_ = a; } |
71 | |
72 // Whether this item is already persisted in the database. | |
73 bool is_persisted() const { | |
74 return db_handle_ != history::DownloadDatabase::kUninitializedHandle; | |
75 } | |
76 | |
77 int64 db_handle() const { return db_handle_; } | |
78 void set_db_handle(int64 h) { db_handle_ = h; } | |
79 | |
80 // This allows OnDownloadUpdated() to see what changed in a DownloadItem if | |
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
nit: DownloadHistory::OnDownloadUpdated().
benjhayden
2012/09/13 15:18:16
Done.
| |
81 // anything, in order to prevent writing to the database unnecessarily. It is | |
82 // nullified when the item is no longer in progress in order to save memory. | |
83 DownloadPersistentStoreInfo* info() { return info_.get(); } | |
84 void set_info(const DownloadPersistentStoreInfo& i) { | |
85 info_.reset(new DownloadPersistentStoreInfo(i)); | |
86 } | |
87 void clear_info() { | |
88 info_.reset(); | |
89 } | |
90 | |
91 private: | |
92 static const char kKey[]; | |
93 | |
94 bool is_adding_; | |
95 int64 db_handle_; | |
96 scoped_ptr<DownloadPersistentStoreInfo> info_; | |
97 | |
98 DISALLOW_COPY_AND_ASSIGN(DownloadHistoryData); | |
99 }; | |
100 | |
101 const char DownloadHistoryData::kKey[] = | |
102 "DownloadItem DownloadHistoryData"; | |
103 | |
104 DownloadPersistentStoreInfo GetPersistentStoreInfo(DownloadItem* item) { | |
105 DownloadHistoryData* dhd = DownloadHistoryData::Get(item); | |
106 return DownloadPersistentStoreInfo( | |
107 item->GetFullPath(), | |
108 item->GetURL(), | |
109 item->GetReferrerUrl(), | |
110 item->GetStartTime(), | |
111 item->GetEndTime(), | |
112 item->GetReceivedBytes(), | |
113 item->GetTotalBytes(), | |
114 item->GetState(), | |
115 ((dhd != NULL) ? dhd->db_handle() | |
116 : history::DownloadDatabase::kUninitializedHandle), | |
117 item->GetOpened()); | |
118 } | |
119 | |
120 typedef std::vector<DownloadPersistentStoreInfo> InfoVector; | |
121 | |
122 // The HistoryService would normally use CancelableRequestConsumer to ensure | |
123 // that callbacks from the HistoryService are run on the same thread that issued | |
124 // the request, but DownloadHistory has opted for less magic by relying on | |
125 // WeakPtrs instead, so it uses Ensure*OnUI to explicitly bounce to the UI | |
126 // thread. | |
127 void EnsureQueryOnUI( | |
128 const base::Callback<void(scoped_ptr<InfoVector>)>& callback, | |
129 scoped_ptr<InfoVector> infos) { | |
130 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
131 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | |
132 callback, base::Passed(infos.Pass()))); | |
133 return; | |
134 } | |
135 callback.Run(infos.Pass()); | |
136 } | |
137 | |
138 void EnsureItemAddedOnUI(const base::Callback<void(int64)>& callback, | |
139 int64 handle) { | |
140 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
141 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | |
142 callback, handle)); | |
143 return; | |
144 } | |
145 callback.Run(handle); | |
146 } | |
147 | |
148 void EnsureVisitedOnUI( | |
149 const base::Callback<void(bool, int, base::Time)>& callback, | |
150 bool success, int count, base::Time first_visit) { | |
151 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
152 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | |
153 callback, success, count, first_visit)); | |
154 return; | |
155 } | |
156 callback.Run(success, count, first_visit); | |
157 } | |
158 | |
159 } // anonymous namespace | |
160 | |
161 DownloadHistory::DownloadHistory( | |
162 DownloadManager* manager, | |
163 HistoryService* history) | |
164 : manager_(manager), | |
165 history_(history), | |
166 loading_db_handle_(history::DownloadDatabase::kUninitializedHandle), | |
167 history_size_(0), | |
168 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | |
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
170 DCHECK(manager_); | |
171 manager_->AddObserver(this); | |
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
What about DownloadItems that were created on the
benjhayden
2012/09/13 15:18:16
Done.
| |
172 history_->QueryDownloads(base::Bind(&EnsureQueryOnUI, base::Bind( | |
173 &DownloadHistory::QueryCallback, weak_ptr_factory_.GetWeakPtr()))); | |
174 } | |
175 | |
176 DownloadHistory::~DownloadHistory() { | |
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
178 for (ItemSet::const_iterator iter = observing_items_.begin(); | |
179 iter != observing_items_.end(); ++iter) { | |
180 (*iter)->RemoveObserver(this); | |
181 } | |
182 observing_items_.clear(); | |
183 if (manager_) | |
184 manager_->RemoveObserver(this); | |
185 } | |
186 | |
187 void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { | |
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
189 // ManagerGoingDown() may have happened before the history loaded. | |
190 if (!manager_) | |
191 return; | |
192 for (InfoVector::const_iterator it = infos->begin(); | |
193 it != infos->end(); ++it) { | |
194 // OnDownloadCreated() is called inside DM::CreateDownloadItem(), so set | |
195 // loading_db_handle_ to match up the created item with its db_handle. All | |
196 // methods run on the UI thread and CreateDownloadItem() is synchronous. | |
197 loading_db_handle_ = it->db_handle; | |
198 DownloadItem* download_item = manager_->CreateDownloadItem( | |
199 it->path, | |
200 it->url, | |
201 it->referrer_url, | |
202 it->start_time, | |
203 it->end_time, | |
204 it->received_bytes, | |
205 it->total_bytes, | |
206 it->state, | |
207 it->opened); | |
208 DownloadHistoryData* dhd = DownloadHistoryData::Get(download_item); | |
209 // If this DCHECK fails, then you probably added an Observer that | |
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
nit, suggestion: Blank line before comment? (I.e.
benjhayden
2012/09/13 15:18:16
Done.
| |
210 // synchronously creates a DownloadItem in response to | |
211 // DownloadManager::OnDownloadCreated(), and your observer runs before | |
212 // DownloadHistory, and DownloadManager creates items synchronously. Just | |
213 // bounce your DownloadItem creation off the message loop to flush | |
214 // DownloadHistory::OnDownloadCreated. | |
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
I like this DCHECK and comment, but if you're rely
benjhayden
2012/09/13 15:18:16
Done.
| |
215 DCHECK_EQ(it->db_handle, dhd->db_handle()); | |
216 ++history_size_; | |
217 } | |
218 manager_->CheckForHistoryFilesRemoval(); | |
219 } | |
220 | |
221 void DownloadHistory::OnDownloadCreated( | |
222 DownloadManager* manager, DownloadItem* item) { | |
223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
224 | |
225 // Observe even temporary downloads in case they are marked not temporary. | |
226 item->AddObserver(this); | |
227 observing_items_.insert(item); | |
228 // All downloads should pass through OnDownloadCreated exactly once. | |
229 CHECK(!DownloadHistoryData::Get(item)); | |
230 DownloadHistoryData* dhd = new DownloadHistoryData(item, loading_db_handle_); | |
231 loading_db_handle_ = history::DownloadDatabase::kUninitializedHandle; | |
232 if (item->GetState() == DownloadItem::IN_PROGRESS) { | |
233 dhd->set_info(GetPersistentStoreInfo(item)); | |
234 } | |
235 MaybeAddToHistory(item); | |
236 } | |
237 | |
238 void DownloadHistory::MaybeAddToHistory(DownloadItem* item) { | |
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
240 int32 download_id = item->GetId(); | |
241 DownloadHistoryData* dhd = DownloadHistoryData::Get(item); | |
242 bool removing = (removing_.find(dhd->db_handle()) != removing_.end()); | |
243 // TODO(benjhayden): Remove IsTemporary(). | |
244 if (download_crx_util::IsExtensionDownload(*item) || | |
245 dhd->is_persisted() || | |
246 item->IsTemporary() || | |
247 removing || | |
248 dhd->is_adding()) | |
249 return; | |
250 dhd->set_is_adding(true); | |
251 if (dhd->info() == NULL) { | |
252 // Keep the info here regardless of whether the item is in progress so | |
253 // that, when ItemAdded() calls OnDownloadUpdated(), it can choose more | |
254 // intelligently whether to Update the db and/or discard the info. | |
255 dhd->set_info(GetPersistentStoreInfo(item)); | |
256 } | |
257 history_->CreateDownload(*dhd->info(), base::Bind( | |
258 &EnsureItemAddedOnUI, base::Bind( | |
259 &DownloadHistory::ItemAdded, weak_ptr_factory_.GetWeakPtr(), | |
260 download_id))); | |
261 } | |
262 | |
263 void DownloadHistory::ItemAdded(int32 download_id, int64 db_handle) { | |
264 if (removed_while_adding_.find(download_id) != | |
265 removed_while_adding_.end()) { | |
266 removed_while_adding_.erase(download_id); | |
267 if (removing_.empty()) { | |
268 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
269 base::Bind(&DownloadHistory::RemoveDownloadsBatch, | |
270 weak_ptr_factory_.GetWeakPtr())); | |
271 } | |
272 removing_.insert(db_handle); | |
273 return; | |
274 } | |
275 | |
276 if (!manager_) | |
277 return; | |
278 | |
279 DownloadItem* item = manager_->GetDownload(download_id); | |
280 if (!item) { | |
281 // This item will have called OnDownloadDestroyed(). If the item should | |
282 // have been removed from history, then it would have also called | |
283 // OnDownloadRemoved(), which would have put |download_id| in | |
284 // removed_while_adding_, handled above. | |
285 return; | |
286 } | |
287 | |
288 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.HistorySize2", | |
289 history_size_, | |
290 0/*min*/, | |
291 (1 << 23)/*max*/, | |
292 (1 << 7)/*num_buckets*/); | |
293 ++history_size_; | |
294 | |
295 DownloadHistoryData* dhd = DownloadHistoryData::Get(item); | |
296 dhd->set_is_adding(false); | |
297 DCHECK(db_handle > history::DownloadDatabase::kUninitializedHandle); | |
Randy Smith (Not in Mondays)
2012/09/11 18:36:53
nit: !=
benjhayden
2012/09/13 15:18:16
Done.
| |
298 dhd->set_db_handle(db_handle); | |
299 | |
300 // In case the item changed or became temporary while it was being added. | |
301 // Don't just update all of the item's observers because we're the only | |
302 // observer that can also see db_handle, which is the only thing that | |
303 // ItemAdded changed. | |
304 OnDownloadUpdated(item); | |
305 } | |
306 | |
307 void DownloadHistory::OnDownloadUpdated(DownloadItem* item) { | |
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
309 | |
310 DownloadHistoryData* dhd = DownloadHistoryData::Get(item); | |
311 if (!dhd->is_persisted()) { | |
312 MaybeAddToHistory(item); | |
313 return; | |
314 } | |
315 if (item->IsTemporary()) { | |
316 OnDownloadRemoved(item); | |
317 return; | |
318 } | |
319 | |
320 // TODO(asanka): Persist GetTargetFilePath() as well. | |
321 DownloadPersistentStoreInfo current_info(GetPersistentStoreInfo(item)); | |
322 DownloadPersistentStoreInfo* previous_info = dhd->info(); | |
323 bool do_update = ( | |
324 (previous_info == NULL) || | |
325 (previous_info->path != current_info.path) || | |
326 (previous_info->end_time != current_info.end_time) || | |
327 (previous_info->received_bytes != current_info.received_bytes) || | |
328 (previous_info->total_bytes != current_info.total_bytes) || | |
329 (previous_info->state != current_info.state) || | |
330 (previous_info->opened != current_info.opened)); | |
331 UMA_HISTOGRAM_ENUMERATION("Download.HistoryPropagatedUpdate", do_update, 2); | |
332 if (do_update) | |
333 history_->UpdateDownload(current_info); | |
334 if (item->GetState() == DownloadItem::IN_PROGRESS) { | |
335 dhd->set_info(current_info); | |
336 } else { | |
337 dhd->clear_info(); | |
338 } | |
339 } | |
340 | |
341 // Downloads may be opened after they are completed. | |
342 void DownloadHistory::OnDownloadOpened(DownloadItem* item) { | |
343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
344 DownloadHistoryData* dhd = DownloadHistoryData::Get(item); | |
345 if (!dhd->is_persisted()) { | |
346 MaybeAddToHistory(item); | |
347 return; | |
348 } | |
349 if (item->IsTemporary()) { | |
350 OnDownloadRemoved(item); | |
351 return; | |
352 } | |
353 | |
354 DownloadPersistentStoreInfo current_info(GetPersistentStoreInfo(item)); | |
355 history_->UpdateDownload(current_info); | |
356 if (item->GetState() == DownloadItem::IN_PROGRESS) { | |
357 dhd->set_info(current_info); | |
358 } | |
359 } | |
360 | |
361 void DownloadHistory::OnDownloadRemoved(DownloadItem* item) { | |
362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
363 | |
364 DownloadHistoryData* dhd = DownloadHistoryData::Get(item); | |
365 if (!dhd->is_persisted()) { | |
366 if (dhd->is_adding()) { | |
367 removed_while_adding_.insert(item->GetId()); | |
368 } | |
369 return; | |
370 } | |
371 | |
372 // For database efficiency, batch removals together if they happen all at | |
373 // once. | |
374 if (removing_.empty()) { | |
375 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
376 base::Bind(&DownloadHistory::RemoveDownloadsBatch, | |
377 weak_ptr_factory_.GetWeakPtr())); | |
378 } | |
379 removing_.insert(dhd->db_handle()); | |
380 dhd->set_db_handle(history::DownloadDatabase::kUninitializedHandle); | |
381 --history_size_; | |
382 } | |
383 | |
384 void DownloadHistory::RemoveDownloadsBatch() { | |
385 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
386 HandleSet remove_handles; | |
387 removing_.swap(remove_handles); | |
388 history_->RemoveDownloads(remove_handles); | |
389 } | |
390 | |
391 void DownloadHistory::ManagerGoingDown(DownloadManager* manager) { | |
392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
393 DCHECK_EQ(manager_, manager); | |
394 manager_->RemoveObserver(this); | |
395 manager_ = NULL; | |
396 } | |
397 | |
398 void DownloadHistory::OnDownloadDestroyed(DownloadItem* item) { | |
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
400 item->RemoveObserver(this); | |
401 observing_items_.erase(item); | |
47 } | 402 } |
48 | 403 |
49 void DownloadHistory::CheckVisitedReferrerBefore( | 404 void DownloadHistory::CheckVisitedReferrerBefore( |
50 int32 download_id, | 405 int32 download_id, |
51 const GURL& referrer_url, | 406 const GURL& referrer_url, |
52 const VisitedBeforeDoneCallback& callback) { | 407 const VisitedBeforeDoneCallback& callback) { |
53 if (referrer_url.is_valid()) { | 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
54 HistoryService* hs = HistoryServiceFactory::GetForProfileIfExists( | 409 if (!referrer_url.is_valid()) { |
55 profile_, Profile::EXPLICIT_ACCESS); | 410 callback.Run(false); |
56 if (hs) { | 411 return; |
57 HistoryService::Handle handle = | 412 } |
58 hs->GetVisibleVisitCountToHost(referrer_url, &history_consumer_, | 413 history_->GetVisibleVisitCountToHostSimple( |
59 base::Bind(&DownloadHistory::OnGotVisitCountToHost, | 414 referrer_url, |
60 base::Unretained(this))); | 415 base::Bind(&EnsureVisitedOnUI, base::Bind( |
61 visited_before_requests_[handle] = callback; | 416 &DownloadHistory::OnGotVisitCountToHost, |
62 return; | 417 weak_ptr_factory_.GetWeakPtr(), callback))); |
63 } | 418 } |
64 } | 419 |
65 callback.Run(false); | 420 void DownloadHistory::OnGotVisitCountToHost( |
66 } | 421 const VisitedBeforeDoneCallback& callback, |
67 | 422 bool found_visits, |
68 void DownloadHistory::AddEntry( | 423 int count, |
69 DownloadItem* download_item, | 424 base::Time first_visit) { |
70 const HistoryService::DownloadCreateCallback& callback) { | |
71 DCHECK(download_item); | |
72 // Do not store the download in the history database for a few special cases: | |
73 // - incognito mode (that is the point of this mode) | |
74 // - extensions (users don't think of extension installation as 'downloading') | |
75 // - temporary download, like in drag-and-drop | |
76 // - history service is not available (e.g. in tests) | |
77 // We have to make sure that these handles don't collide with normal db | |
78 // handles, so we use a negative value. Eventually, they could overlap, but | |
79 // you'd have to do enough downloading that your ISP would likely stab you in | |
80 // the neck first. YMMV. | |
81 HistoryService* hs = HistoryServiceFactory::GetForProfileIfExists( | |
82 profile_, Profile::EXPLICIT_ACCESS); | |
83 if (download_crx_util::IsExtensionDownload(*download_item) || | |
84 download_item->IsTemporary() || !hs) { | |
85 callback.Run(download_item->GetId(), GetNextFakeDbHandle()); | |
86 return; | |
87 } | |
88 | |
89 int32 id = download_item->GetId(); | |
90 DownloadPersistentStoreInfo history_info = | |
91 download_item->GetPersistentStoreInfo(); | |
92 hs->CreateDownload(id, history_info, &history_consumer_, callback); | |
93 } | |
94 | |
95 void DownloadHistory::UpdateEntry(DownloadItem* download_item) { | |
96 // Don't store info in the database if the download was initiated while in | |
97 // incognito mode or if it hasn't been initialized in our database table. | |
98 if (download_item->GetDbHandle() <= DownloadItem::kUninitializedHandle) | |
99 return; | |
100 | |
101 HistoryService* hs = HistoryServiceFactory::GetForProfileIfExists( | |
102 profile_, Profile::EXPLICIT_ACCESS); | |
103 if (!hs) | |
104 return; | |
105 hs->UpdateDownload(download_item->GetPersistentStoreInfo()); | |
106 } | |
107 | |
108 void DownloadHistory::UpdateDownloadPath(DownloadItem* download_item, | |
109 const FilePath& new_path) { | |
110 // No update necessary if the download was initiated while in incognito mode. | |
111 if (download_item->GetDbHandle() <= DownloadItem::kUninitializedHandle) | |
112 return; | |
113 | |
114 HistoryService* hs = HistoryServiceFactory::GetForProfileIfExists( | |
115 profile_, Profile::EXPLICIT_ACCESS); | |
116 if (hs) | |
117 hs->UpdateDownloadPath(new_path, download_item->GetDbHandle()); | |
118 } | |
119 | |
120 void DownloadHistory::RemoveEntry(DownloadItem* download_item) { | |
121 // No update necessary if the download was initiated while in incognito mode. | |
122 if (download_item->GetDbHandle() <= DownloadItem::kUninitializedHandle) | |
123 return; | |
124 | |
125 HistoryService* hs = HistoryServiceFactory::GetForProfileIfExists( | |
126 profile_, Profile::EXPLICIT_ACCESS); | |
127 if (hs) | |
128 hs->RemoveDownload(download_item->GetDbHandle()); | |
129 } | |
130 | |
131 void DownloadHistory::RemoveEntriesBetween(const base::Time remove_begin, | |
132 const base::Time remove_end) { | |
133 HistoryService* hs = HistoryServiceFactory::GetForProfileIfExists( | |
134 profile_, Profile::EXPLICIT_ACCESS); | |
135 if (hs) | |
136 hs->RemoveDownloadsBetween(remove_begin, remove_end); | |
137 } | |
138 | |
139 int64 DownloadHistory::GetNextFakeDbHandle() { | |
140 return next_fake_db_handle_--; | |
141 } | |
142 | |
143 void DownloadHistory::OnGotVisitCountToHost(HistoryService::Handle handle, | |
144 bool found_visits, | |
145 int count, | |
146 base::Time first_visit) { | |
147 VisitedBeforeRequestsMap::iterator request = | |
148 visited_before_requests_.find(handle); | |
149 DCHECK(request != visited_before_requests_.end()); | |
150 VisitedBeforeDoneCallback callback = request->second; | |
151 visited_before_requests_.erase(request); | |
152 callback.Run(found_visits && count && | 425 callback.Run(found_visits && count && |
153 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); | 426 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); |
154 } | 427 } |
OLD | NEW |