summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing/incident_reporting/last_download_finder.h
blob: 588b04c826a0a388ddc7b5c090ed762781113947 (plain)
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
// Copyright 2014 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_SAFE_BROWSING_INCIDENT_REPORTING_LAST_DOWNLOAD_FINDER_H_
#define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_LAST_DOWNLOAD_FINDER_H_

#include <map>
#include <vector>

#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_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_observer.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"

class Profile;

namespace content {
class NotificationDetails;
class NotificationSource;
}

namespace history {
class HistoryService;
}

namespace safe_browsing {

class ClientIncidentReport_DownloadDetails;

// Finds the most recent executable downloaded by any on-the-record profile with
// history that participates in safe browsing.
class LastDownloadFinder : public content::NotificationObserver,
                           public history::HistoryServiceObserver {
 public:
  typedef base::Callback<void(
      content::BrowserContext* context,
      const DownloadMetadataManager::GetDownloadDetailsCallback&)>
      DownloadDetailsGetter;

  // The type of a callback run by the finder upon completion. The argument is a
  // protobuf containing details of the download that was found, or an empty
  // pointer if none was found.
  typedef base::Callback<void(scoped_ptr<ClientIncidentReport_DownloadDetails>)>
      LastDownloadCallback;

  ~LastDownloadFinder() override;

  // Initiates an asynchronous search for the most recent download. |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 scoped_ptr<LastDownloadFinder> Create(
      const DownloadDetailsGetter& download_details_getter,
      const LastDownloadCallback& callback);

 protected:
  // Protected constructor so that unit tests can create a fake finder.
  LastDownloadFinder();

 private:
  enum ProfileWaitState {
    WAITING_FOR_METADATA,
    WAITING_FOR_HISTORY,
  };

  LastDownloadFinder(const DownloadDetailsGetter& download_details_getter,
                     const std::vector<Profile*>& profiles,
                     const LastDownloadCallback& callback);

  // 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. A
  // search for metadata is initiated immediately.
  void SearchInProfile(Profile* profile);

  // 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(
      Profile* profile,
      scoped_ptr<ClientIncidentReport_DownloadDetails> details);

  // Abandons the search for downloads in |profile|, reporting results if there
  // are no more pending queries.
  void AbandonSearchInProfile(Profile* profile);

  // HistoryService::DownloadQueryCallback. Retrieves the most recent completed
  // executable download from |downloads| and reports results if there are no
  // more pending queries.
  void OnDownloadQuery(
      Profile* profile,
      scoped_ptr<std::vector<history::DownloadRow> > downloads);

  // Removes the profile pointed to by |it| from profile_states_ and reports
  // results if there are no more pending queries.
  void RemoveProfileAndReportIfDone(
      std::map<Profile*, ProfileWaitState>::iterator iter);

  // Invokes the caller-supplied callback with the download found.
  void ReportResults();

  // content::NotificationObserver methods.
  void Observe(int type,
               const content::NotificationSource& source,
               const content::NotificationDetails& details) 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 download query is pending to their
  // respective states.
  std::map<Profile*, ProfileWaitState> profile_states_;

  // Registrar for observing profile lifecycle notifications.
  content::NotificationRegistrar notification_registrar_;

  // The most interesting download details retrieved from download metadata.
  scoped_ptr<ClientIncidentReport_DownloadDetails> details_;

  // The most recent download, updated progressively as query results arrive.
  history::DownloadRow most_recent_row_;

  // HistoryServiceObserver
  ScopedObserver<history::HistoryService, history::HistoryServiceObserver>
      history_service_observer_;

  // A factory for asynchronous operations on profiles' HistoryService.
  base::WeakPtrFactory<LastDownloadFinder> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(LastDownloadFinder);
};

}  // namespace safe_browsing

#endif  // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_LAST_DOWNLOAD_FINDER_H_