1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_HISTORY_H_
#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_HISTORY_H_
#include <set>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chrome/browser/download/all_download_item_notifier.h"
#include "chrome/browser/history/history_service.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
namespace history {
struct DownloadRow;
} // namespace history
// Observes a single DownloadManager and all its DownloadItems, keeping the
// DownloadDatabase up to date.
class DownloadHistory : public AllDownloadItemNotifier::Observer {
public:
typedef std::set<uint32> IdSet;
// Caller must guarantee that HistoryService outlives HistoryAdapter.
class HistoryAdapter {
public:
explicit HistoryAdapter(HistoryService* history);
virtual ~HistoryAdapter();
virtual void QueryDownloads(
const HistoryService::DownloadQueryCallback& callback);
virtual void CreateDownload(
const history::DownloadRow& info,
const HistoryService::DownloadCreateCallback& callback);
virtual void UpdateDownload(const history::DownloadRow& data);
virtual void RemoveDownloads(const std::set<uint32>& ids);
private:
HistoryService* history_;
DISALLOW_COPY_AND_ASSIGN(HistoryAdapter);
};
class Observer {
public:
Observer();
virtual ~Observer();
// Fires when a download is added to or updated in the database, just after
// the task is posted to the history thread.
virtual void OnDownloadStored(content::DownloadItem* item,
const history::DownloadRow& info) {}
// Fires when RemoveDownloads messages are sent to the DB thread.
virtual void OnDownloadsRemoved(const IdSet& ids) {}
// Fires when the DownloadHistory is being destroyed so that implementors
// can RemoveObserver() and nullify their DownloadHistory*s.
virtual void OnDownloadHistoryDestroyed() {}
};
// Returns true if the download is persisted. Not reliable when called from
// within a DownloadManager::Observer::OnDownloadCreated handler since the
// persisted state may not yet have been updated for a download that was
// restored from history.
static bool IsPersisted(const content::DownloadItem* item);
// Neither |manager| nor |history| may be NULL.
// DownloadService creates DownloadHistory some time after DownloadManager is
// created and destroys DownloadHistory as DownloadManager is shutting down.
DownloadHistory(
content::DownloadManager* manager,
scoped_ptr<HistoryAdapter> history);
~DownloadHistory() override;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Returns true if the download was restored from history. Safe to call from
// within a DownloadManager::Observer::OnDownloadCreated handler and can be
// used to distinguish between downloads that were created due to new requests
// vs. downloads that were created due to being restored from history. Note
// that the return value is only reliable for downloads that were restored by
// this specific DownloadHistory instance.
bool WasRestoredFromHistory(const content::DownloadItem* item) const;
private:
typedef std::set<content::DownloadItem*> ItemSet;
// Callback from |history_| containing all entries in the downloads database
// table.
void QueryCallback(
scoped_ptr<std::vector<history::DownloadRow> > infos);
// May add |item| to |history_|.
void MaybeAddToHistory(content::DownloadItem* item);
// Callback from |history_| when an item was successfully inserted into the
// database.
void ItemAdded(uint32 id, bool success);
// AllDownloadItemNotifier::Observer
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
void OnDownloadUpdated(content::DownloadManager* manager,
content::DownloadItem* item) override;
void OnDownloadOpened(content::DownloadManager* manager,
content::DownloadItem* item) override;
void OnDownloadRemoved(content::DownloadManager* manager,
content::DownloadItem* item) override;
// Schedule a record to be removed from |history_| the next time
// RemoveDownloadsBatch() runs. Schedule RemoveDownloadsBatch() to be run soon
// if it isn't already scheduled.
void ScheduleRemoveDownload(uint32 download_id);
// Removes all |removing_ids_| from |history_|.
void RemoveDownloadsBatch();
AllDownloadItemNotifier notifier_;
scoped_ptr<HistoryAdapter> history_;
// Identifier of the item being created in QueryCallback(), matched up with
// created items in OnDownloadCreated() so that the item is not re-added to
// the database.
uint32 loading_id_;
// Identifiers of items that are scheduled for removal from history, to
// facilitate batching removals together for database efficiency.
IdSet removing_ids_;
// |GetId()|s of items that were removed while they were being added, so that
// they can be removed when the database finishes adding them.
// TODO(benjhayden) Can this be removed now that it doesn't need to wait for
// the db_handle, and can rely on PostTask sequentiality?
IdSet removed_while_adding_;
// Count the number of items in the history for UMA.
int64 history_size_;
ObserverList<Observer> observers_;
base::WeakPtrFactory<DownloadHistory> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DownloadHistory);
};
#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_HISTORY_H_
|