File: install_event_log_manager.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (251 lines) | stat: -rw-r--r-- 8,831 bytes parent folder | download | duplicates (7)
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
// Copyright 2020 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_ASH_POLICY_REPORTING_INSTALL_EVENT_LOG_MANAGER_H_
#define CHROME_BROWSER_ASH_POLICY_REPORTING_INSTALL_EVENT_LOG_MANAGER_H_

#include <memory>
#include <set>
#include <string>

#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"

class Profile;

namespace base {
class FilePath;
class SequencedTaskRunner;
}  // namespace base

namespace policy {

// Ties together collection, storage and upload of app install event logs. The
// app refers to extension or ARC++ app.
// Newly added log entries are held in memory first and stored to disk no more
// than five seconds later. The log is also written to disk every time it has
// been successfully uploaded to the server and on logout.
//
// Uploads to the server are scheduled as follows:
// * The first upload happens fifteen minutes after |this| is instantiated. This
//   ensures that initial activity in short-lived, ephemeral sessions is not
//   lost.
// * Subsequent uploads are scheduled three hours after the last successful
//   upload and suspended if the log becomes empty.
// * If the log is getting full, the next upload is expedited from three hours
//   to fifteen minutes delay.
class InstallEventLogManagerBase {
 public:
  // Helper that returns a |base::SequencedTaskRunner| for background operations
  // on an event log. All background operations relating to a given log file,
  // whether by an |InstallEventLogManagerBase| or any other class, must use the
  // same |base::SequencedTaskRunner| returned by a |LogTaskRunnerWrapper|
  // instance to ensure correct serialization.
  class LogTaskRunnerWrapper {
   public:
    LogTaskRunnerWrapper();
    virtual ~LogTaskRunnerWrapper();

    // Returns a |base::SequencedTaskRunner| that executes tasks in order and
    // runs any pending tasks on shutdown (to ensure the log is stored to disk).
    // Virtual for testing.
    virtual scoped_refptr<base::SequencedTaskRunner> GetTaskRunner();

   private:
    scoped_refptr<base::SequencedTaskRunner> task_runner_;
  };

  // All accesses to the |profile|'s app install event log file must use
  // the same |log_task_runner_wrapper| to ensure correct I/O serialization.
  InstallEventLogManagerBase(LogTaskRunnerWrapper* log_task_runner_wrapper,
                             Profile* profile);
  ~InstallEventLogManagerBase();

  // The current size of the log, returned by each operation on the log store.
  struct LogSize {
    // The total number of log entries, across all apps.
    int total_size;
    // The maximum number of log entries for a single app.
    int max_size;
  };

  // Once created, |InstallLog| runs in the background and must be accessed and
  // eventually destroyed via |log_task_runner_|.  |T| specifies the event type
  // and |C| specifies the type of type of event log class.
  template <typename T, class C>
  class InstallLog {
   public:
    InstallLog();
    InstallLog(const InstallLog<T, C>& install_log) = delete;
    InstallLog<T, C> operator=(const InstallLog<T, C>& install_log) = delete;
    virtual ~InstallLog();

    // Loads the log from disk or creates an empty log if the log file does not
    // exist. Must be called before any other methods, including the destructor.
    LogSize Init(const base::FilePath& file_path);

    // Adds an identical log entry for each app in |ids|.
    LogSize Add(const std::set<std::string>& ids, const T& event);

    // Stores the log to disk.
    void Store();

    // Clears log entries that were previously serialized and stores the
    // resulting log to disk.
    LogSize ClearSerializedAndStore();

   protected:
    // Returns the current size of the log.
    LogSize GetSize() const;

    // The actual log store.
    std::unique_ptr<C> log_;

    // Ensures that methods are not called from the wrong thread.
    SEQUENCE_CHECKER(sequence_checker_);
  };

  // Helper class that manages the storing and uploading of logs.
  class LogUpload {
   public:
    LogUpload();
    virtual ~LogUpload() = 0;

    // Callback invoked by |InstallLog::Init()|. Schedules the first log upload.
    void OnLogInit(const LogSize& log_size);

    // Callback invoked by all other operations on |InstallLog| that may change
    // its contents. (Re-)schedules log upload and log storage to disk.
    void OnLogChange(const LogSize& log_size);

    // Stores the log to disk.
    virtual void StoreLog() = 0;

    // Ensure that an upload is either already requested or scheduled for the
    // future. If |expedited| is |true|, ensures that a scheduled upload lies no
    // more than fifteen minutes in the future.
    void EnsureUpload(bool expedited);

    // Requests that uploader upload the log to the server.
    void RequestUpload();

    virtual void RequestUploadForUploader() = 0;

    template <typename T, typename C>
    void OnSerializeLogDone(T callback, std::unique_ptr<C> log);

    // The current size of the log.
    LogSize log_size_;

    // Any change to the log contents causes a task to be scheduled that will
    // store the log contents to disk five seconds later. Changes during this
    // five second window will be picked up by the scheduled store and do not
    // require another store to be scheduled.
    bool store_scheduled_ = false;

    // Whether an upload request has been sent to the uploader already. If
    // so, no further uploads are scheduled until the current request is
    // successful. The uploader retries indefinitely on errors.
    bool upload_requested_ = false;

    // Whether an upload has been scheduled for some time in the future.
    bool upload_scheduled_ = false;

    // Whether a scheduled upload is expedited (fifteen minute delay) instead of
    // regular (three hour delay).
    bool expedited_upload_scheduled_ = false;

    // After successful upload, uploaded log entries are cleared and the log is
    // stored to disk. If a store task is scheduled, this factory's weak
    // pointers are invalidated to cancel it and avoid unnecessary I/O.
    base::WeakPtrFactory<LogUpload> store_weak_factory_{this};

    // Invalidated to cancel a pending upload when the log becomes empty after
    // upload or an expedited upload is needed instead of a previously scheduled
    // regular upload.
    base::WeakPtrFactory<LogUpload> upload_weak_factory_{this};

    // Used by log store owner to access |this|. Invalidated when |this| is
    // destroyed as log store owner outlives it.
    base::WeakPtrFactory<LogUpload> log_weak_factory_{this};
  };

  // Task runner via which log store owner is accessed.
  const scoped_refptr<base::SequencedTaskRunner> log_task_runner_;
};

// Implementation details.
template <typename T, class C>
InstallEventLogManagerBase::InstallLog<T, C>::InstallLog() {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

template <typename T, class C>
InstallEventLogManagerBase::InstallLog<T, C>::~InstallLog() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(log_);
  log_->Store();
}

template <typename T, class C>
InstallEventLogManagerBase::LogSize
InstallEventLogManagerBase::InstallLog<T, C>::Init(
    const base::FilePath& file_path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!log_);
  log_ = std::make_unique<C>(file_path);
  return GetSize();
}

template <typename T, class C>
InstallEventLogManagerBase::LogSize
InstallEventLogManagerBase::InstallLog<T, C>::Add(
    const std::set<std::string>& ids,
    const T& event) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(log_);
  for (const auto& id : ids) {
    log_->Add(id, event);
  }
  return GetSize();
}

template <typename T, class C>
void InstallEventLogManagerBase::InstallLog<T, C>::Store() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(log_);
  log_->Store();
}

template <typename T, class C>
InstallEventLogManagerBase::LogSize
InstallEventLogManagerBase::InstallLog<T, C>::ClearSerializedAndStore() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(log_);
  log_->ClearSerialized();
  log_->Store();
  return GetSize();
}

template <typename T, class C>
InstallEventLogManagerBase::LogSize
InstallEventLogManagerBase::InstallLog<T, C>::GetSize() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  LogSize size;
  size.total_size = log_->total_size();
  size.max_size = log_->max_size();
  return size;
}

template <typename T, typename C>
void InstallEventLogManagerBase::LogUpload::OnSerializeLogDone(
    T callback,
    std::unique_ptr<C> log) {
  std::move(callback).Run(log.get());
}

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_REPORTING_INSTALL_EVENT_LOG_MANAGER_H_