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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_LAST_DOWNLOAD_FINDER_H_
#define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_LAST_DOWNLOAD_FINDER_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "base/types/strong_alias.h"
#include "chrome/browser/profiles/profile_manager_observer.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.h"
#include "components/history/core/browser/download_row.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
class Profile;
namespace safe_browsing {
class ClientIncidentReport_DownloadDetails;
class ClientIncidentReport_NonBinaryDownloadDetails;
// Finds the most recent executable download and non-executable download by
// any on-the-record profile with history that participates in safe browsing
// extended reporting.
class LastDownloadFinder : public ProfileManagerObserver,
public ProfileObserver,
public history::HistoryServiceObserver {
public:
typedef base::RepeatingCallback<void(
content::BrowserContext* context,
DownloadMetadataManager::GetDownloadDetailsCallback)>
DownloadDetailsGetter;
// The type of a callback run by the finder upon completion. Each argument is
// a protobuf containing details of the respective download that was found,
// or an empty pointer if none was found.
typedef base::OnceCallback<void(
std::unique_ptr<ClientIncidentReport_DownloadDetails>,
std::unique_ptr<ClientIncidentReport_NonBinaryDownloadDetails>)>
LastDownloadCallback;
LastDownloadFinder(const LastDownloadFinder&) = delete;
LastDownloadFinder& operator=(const LastDownloadFinder&) = delete;
~LastDownloadFinder() override;
// Initiates an asynchronous search for the most recent downloads. |callback|
// will be run when the search is complete. The returned instance can be
// deleted to terminate the search, in which case |callback| is not invoked.
// Returns NULL without running |callback| if there are no eligible profiles
// to search.
static std::unique_ptr<LastDownloadFinder> Create(
DownloadDetailsGetter download_details_getter,
LastDownloadCallback callback);
protected:
// Protected constructor so that unit tests can create a fake finder.
LastDownloadFinder();
private:
// Holds state for a Profile for which a query is currently pending. The State
// describes what we are waiting for. The observation is a mechanism to ensure
// that we do not attempt to process the results of a search for a Profile
// that is no longer valid. This guarantees that a PendingProfileData exists
// iff the Profile is alive and we are waiting on a query for it.
struct PendingProfileData {
enum State {
WAITING_FOR_METADATA,
WAITING_FOR_HISTORY,
WAITING_FOR_NON_BINARY_HISTORY,
};
// Makes the `finder` start observing `profile`.
PendingProfileData(LastDownloadFinder* finder,
Profile* profile,
State state);
~PendingProfileData();
Profile* profile() { return observation.GetSource(); }
State state;
base::ScopedObservation<Profile, LastDownloadFinder> observation;
};
// We identify Profiles by their addresses, in the form of a uintptr_t value,
// which is derived from a Profile* but is not to be dereferenced.
using ProfileKey = base::StrongAlias<class ProfileKeyTag, uintptr_t>;
using PendingProfilesMap = std::map<ProfileKey, PendingProfileData>;
LastDownloadFinder(DownloadDetailsGetter download_details_getter,
LastDownloadCallback callback);
// Returns the address of the Profile in a safe form to be used as a map key.
static inline ProfileKey KeyForProfile(Profile* profile);
// Adds |profile| to the set of profiles to be searched if it is an
// on-the-record profile with history that participates in safe browsing
// extended reporting. A search for metadata is initiated immediately.
void SearchInProfile(Profile* profile);
// Adds every profile in `profiles` to the set of profiles to be searched if
// it is an on-the-record profile with history that participates in safe
// browsing extended reporting. A search for metadata is initiated
// immediately.
void SearchInProfiles(const std::vector<Profile*>& profiles);
// DownloadMetadataManager::GetDownloadDetailsCallback. If |details| are
// provided, retrieves them if they are the most relevant results. Otherwise
// begins a search in history. Reports results if there are no more pending
// queries.
void OnMetadataQuery(
ProfileKey profile_key,
std::unique_ptr<ClientIncidentReport_DownloadDetails> details);
// HistoryService::DownloadQueryCallback. Retrieves the most recent completed
// executable download from |downloads| and reports results if there are no
// more pending queries.
void OnDownloadQuery(ProfileKey profile_key,
std::vector<history::DownloadRow> downloads);
// Severs ties with the Profile whose state is pointed at by `iter` within
// `pending_profiles_`, either after a query finishes or to abandon an ongoing
// query. Also reports results if there are no more pending queries.
void RemoveProfileAndReportIfDone(PendingProfilesMap::iterator iter);
// Invokes the caller-supplied callback with the download found.
void ReportResults();
// ProfileManagerObserver:
void OnProfileAdded(Profile* profile) override;
// ProfileObserver:
void OnProfileWillBeDestroyed(Profile* profile) override;
// history::HistoryServiceObserver:
void OnHistoryServiceLoaded(history::HistoryService* service) override;
void HistoryServiceBeingDeleted(
history::HistoryService* history_service) override;
// Caller-supplied callback to make an asynchronous request for a profile's
// persistent download details.
DownloadDetailsGetter download_details_getter_;
// Caller-supplied callback to be invoked when the most recent download is
// found.
LastDownloadCallback callback_;
// A mapping of profiles for which a query is pending to their respective
// states. Items are removed from here when a query finishes, or when we
// abandon a query.
PendingProfilesMap pending_profiles_;
// The most interesting download details retrieved from download metadata.
std::unique_ptr<ClientIncidentReport_DownloadDetails> details_;
// The most recent download, updated progressively as query results arrive.
history::DownloadRow most_recent_binary_row_;
// The most recent non-binary download, updated progressively as query results
// arrive.
history::DownloadRow most_recent_non_binary_row_;
// HistoryServiceObserver
base::ScopedMultiSourceObservation<history::HistoryService,
history::HistoryServiceObserver>
history_service_observations_{this};
// A factory for asynchronous operations on profiles' HistoryService.
base::WeakPtrFactory<LastDownloadFinder> weak_ptr_factory_{this};
};
} // namespace safe_browsing
#endif // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_LAST_DOWNLOAD_FINDER_H_
|