Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: chrome/browser/download/download_history.cc

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

Powered by Google App Engine
This is Rietveld 408576698