File: dlp_files_event_storage.cc

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 (142 lines) | stat: -rw-r--r-- 5,380 bytes parent folder | download | duplicates (6)
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
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/policy/dlp/dlp_files_event_storage.h"

#include "base/containers/flat_map.h"
#include "base/metrics/histogram_functions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_file_destination.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
#include "components/enterprise/data_controls/core/browser/dlp_histogram_helper.h"

namespace policy {

DlpFilesEventStorage::DlpFilesEventStorage(base::TimeDelta cooldown_timeout,
                                           size_t entries_num_limit)
    : cooldown_delta_(cooldown_timeout),
      task_runner_(base::SequencedTaskRunner::GetCurrentDefault()),
      entries_num_limit_(entries_num_limit) {}
DlpFilesEventStorage::~DlpFilesEventStorage() = default;

DlpFilesEventStorage::EventEntry::EventEntry(base::TimeTicks timestamp)
    : timestamp(timestamp) {}
DlpFilesEventStorage::EventEntry::~EventEntry() = default;

bool DlpFilesEventStorage::StoreEventAndCheckIfItShouldBeReported(
    FileId file_id,
    const DlpFileDestination& dst) {
  if (entries_num_ == entries_num_limit_) {
    // If we end up here we probably have already spammed the server with a lot
    // of events, better to stop for a while.
    return false;
  }

  const base::TimeTicks now = base::TimeTicks::Now();

  const auto file_it = events_.find(file_id);
  if (file_it == events_.end()) {  // Check for new (file_id, dst) pair
    InsertNewFileAndDestinationPair(file_id, dst, now);
    return true;
  }

  auto dst_it = file_it->second.find(dst);
  if (dst_it == file_it->second.end()) {  // Check for new dst for this file_id
    AddDestinationToFile(file_it, file_id, dst, now);
    // Skip reporting if we don't know the destination (i.e., it is
    // kUnknownComponent) and at least an entry for `file_id` is stored in
    // `events_`.
    return (dst.component().has_value() &&
            dst.component().value() !=
                data_controls::Component::kUnknownComponent) ||
           dst.url().has_value();
  }

  // Found existing (file_id, dst) pair, update it
  UpdateFileAndDestinationPair(dst_it, now);

  const auto time_diff = now - dst_it->second.timestamp;

  // Record the time difference between two identical file events.
  base::UmaHistogramTimes(data_controls::GetDlpHistogramPrefix() +
                              data_controls::dlp::kSameFileEventTimeDiffUMA,
                          time_diff);

  // Report only if enough time has passed.
  return time_diff > cooldown_delta_;
}

base::TimeDelta DlpFilesEventStorage::GetDeduplicationCooldownForTesting()
    const {
  return cooldown_delta_;
}

std::size_t DlpFilesEventStorage::GetSizeForTesting() const {
  return entries_num_;
}

void DlpFilesEventStorage::SetTaskRunnerForTesting(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
  task_runner_ = task_runner;
}

void DlpFilesEventStorage::AddDestinationToFile(
    EventsMap::iterator file_it,
    FileId file_id,
    const DlpFileDestination& dst,
    const base::TimeTicks timestamp) {
  const auto [it, _] = file_it->second.emplace(dst, timestamp);
  StartEvictionTimer(file_id, dst, it->second);
  entries_num_++;
  data_controls::DlpCountHistogram(data_controls::dlp::kActiveFileEventsCount,
                                   entries_num_, entries_num_limit_);
}

void DlpFilesEventStorage::InsertNewFileAndDestinationPair(
    FileId file_id,
    const DlpFileDestination& dst,
    const base::TimeTicks timestamp) {
  const auto [file_it, _] =
      events_.emplace(file_id, std::map<DlpFileDestination, EventEntry>());
  const auto [dst_it, __] = file_it->second.emplace(dst, timestamp);
  StartEvictionTimer(file_id, dst, dst_it->second);
  entries_num_++;
  data_controls::DlpCountHistogram(data_controls::dlp::kActiveFileEventsCount,
                                   entries_num_, entries_num_limit_);
}

void DlpFilesEventStorage::UpdateFileAndDestinationPair(
    DestinationsMap::iterator dst_it,
    const base::TimeTicks timestamp) {
  dst_it->second.timestamp = timestamp;
  DCHECK(dst_it->second.eviction_timer.IsRunning());
  dst_it->second.eviction_timer.Reset();
  data_controls::DlpCountHistogram(data_controls::dlp::kActiveFileEventsCount,
                                   entries_num_, entries_num_limit_);
}

void DlpFilesEventStorage::StartEvictionTimer(FileId file_id,
                                              const DlpFileDestination& dst,
                                              EventEntry& event_value) {
  event_value.eviction_timer.SetTaskRunner(task_runner_);
  event_value.eviction_timer.Start(
      FROM_HERE, cooldown_delta_,
      base::BindOnce(&DlpFilesEventStorage::OnEvictionTimerUp,
                     base::Unretained(this), file_id, dst));
}

void DlpFilesEventStorage::OnEvictionTimerUp(FileId file_id,
                                             DlpFileDestination dst) {
  auto event_it = events_.find(file_id);
  DCHECK(event_it != events_.end());
  DCHECK(event_it->second.count(dst));
  event_it->second.erase(std::move(dst));
  if (event_it->second.empty()) {
    events_.erase(event_it);
  }
  --entries_num_;
}

}  // namespace policy