File: download_item_warning_data.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 (226 lines) | stat: -rw-r--r-- 9,611 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
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
// 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.

#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_WARNING_DATA_H_
#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_WARNING_DATA_H_

#include <optional>
#include <vector>

#include "base/supports_user_data.h"
#include "base/time/time.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"

namespace download {
class DownloadItem;
}

// Per DownloadItem data for storing warning events on download warnings. The
// data is only set if a warning is shown. These events are added to Safe
// Browsing reports.
class DownloadItemWarningData : public base::SupportsUserData::Data {
 public:
  // The surface that the warning is shown. See
  // go/chrome-download-warning-surfaces for details.
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  enum class WarningSurface {
    // Applicable actions: DISCARD, OPEN_SUBPAGE
    BUBBLE_MAINPAGE = 1,
    // Applicable actions: PROCEED, DISCARD, DISMISS, CLOSE, BACK,
    // PROCEED_DEEP_SCAN, ACCEPT_DEEP_SCAN, OPEN_LEARN_MORE_LINK
    BUBBLE_SUBPAGE = 2,
    // Applicable actions: DISCARD, KEEP, PROCEED, ACCEPT_DEEP_SCAN
    // PROCEED on the downloads page indicates saving a "suspicious" download
    // directly, without going through the prompt. In contrast, KEEP indicates
    // opening the prompt, for a "dangerous" download.
    DOWNLOADS_PAGE = 3,
    // Applicable actions: PROCEED, CANCEL
    DOWNLOAD_PROMPT = 4,
    // Applicable actions: OPEN_SUBPAGE
    // Note: This is only used on Lacros. DownloadItemWarningData is only
    // applied for v2 notifications on ChromeOS Lacros, not for the legacy
    // ChromeOS notifications used on ChromeOS Ash and on Lacros pre-v2. Other
    // platforms do not have desktop notifications for downloads.
    // TODO(chlily): CLOSE should be logged as well but there is currently no
    // way to tell when a download is dangerous on the Ash side, which handles
    // the notification close.
    DOWNLOAD_NOTIFICATION = 5,
    kMaxValue = DOWNLOAD_NOTIFICATION
  };

  // Users action on the warning surface.
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  enum class WarningAction {
    // The warning is shown. This is a special action that may not be triggered
    // by user. We will use the first instance of this action as the anchor to
    // track the latency of other actions.
    SHOWN = 0,
    // The user clicks proceed, which means the user decides to bypass the
    // warning. This is a terminal action.
    // Note that this corresponds to DownloadCommands::Command::KEEP, despite
    // the confusing naming.
    PROCEED = 1,
    // The user clicks discard, which means the user decides to obey the
    // warning and the dangerous download is deleted from disk.
    DISCARD = 2,
    // The user has clicked the keep button on the surface, which causes another
    // surface (e.g. download prompt) to be displayed. This is not a terminal
    // action.
    KEEP = 3,
    // The user has clicked the close button on the surface.
    CLOSE = 4,
    // The user clicks cancel on the download prompt.
    CANCEL = 5,
    // The user has dismissed the bubble by clicking anywhere outside
    // the bubble.
    DISMISS = 6,
    // The user has clicked the back button on the bubble subpage to go back
    // to the bubble main page.
    BACK = 7,
    // The user has opened the download bubble subpage.
    OPEN_SUBPAGE = 8,
    // The user clicks proceed on a prompt for deep scanning.
    PROCEED_DEEP_SCAN = 9,
    // The user clicks the learn more link on the bubble subpage.
    OPEN_LEARN_MORE_LINK = 10,
    // The user accepts starting a deep scan.
    ACCEPT_DEEP_SCAN = 11,
    kMaxValue = ACCEPT_DEEP_SCAN
  };

  struct WarningActionEvent {
    WarningSurface surface;
    WarningAction action;
    // The latency between when the warning is shown for the first time and when
    // this event has happened.
    int64_t action_latency_msec;
    // A terminal action means that the warning disappears after this event,
    // the download is either deleted or saved.
    bool is_terminal_action = false;

    WarningActionEvent(WarningSurface surface,
                       WarningAction action,
                       int64_t action_latency_msec,
                       bool is_terminal_action);

    // Serializes the surface, action, and action_latency_msec into a string
    // in a colon-separated format such as "DOWNLOADS_PAGE:DISCARD:10000".
    std::string ToString() const;
  };

  // Enum representing the trigger of the scan request.
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  // LINT.IfChange
  enum class DeepScanTrigger {
    // The trigger is unknown.
    TRIGGER_UNKNOWN = 0,

    // The trigger is the standard prompt in the download bubble,
    // shown for Advanced Protection or Enhanced Protection users.
    TRIGGER_CONSUMER_PROMPT = 1,

    // The trigger is the enterprise policy.
    TRIGGER_POLICY = 2,

    // The trigger is the encrypted archive prompt in the download
    // bubble, which requires the password as well as the file.
    TRIGGER_ENCRYPTED_CONSUMER_PROMPT = 3,

    // The trigger is automatic deep scanning, with no prompt, which
    // applies only to Enhanced Protection users.
    TRIGGER_IMMEDIATE_DEEP_SCAN = 4,

    kMaxValue = TRIGGER_IMMEDIATE_DEEP_SCAN,
  };
  // LINT.ThenChange(/tools/metrics/histograms/metadata/sb_client/enums.xml)

  ~DownloadItemWarningData() override;

  // Gets all warning actions associated with this `download`. Returns an
  // empty vector if there's no warning data or there is no warning shown for
  // this `download`.
  static std::vector<WarningActionEvent> GetWarningActionEvents(
      const download::DownloadItem* download);

  // Adds an `action` triggered on `surface` for `download`. It may not be
  // added if `download` is not dangerous, null or the length of events
  // associated with this `download` exceeds the limit.
  static void AddWarningActionEvent(download::DownloadItem* download,
                                    WarningSurface surface,
                                    WarningAction action);

  // Returns whether the download was an encrypted archive at the
  // top-level (i.e. the encryption was not within a nested archive).
  static bool IsTopLevelEncryptedArchive(
      const download::DownloadItem* download);
  static void SetIsTopLevelEncryptedArchive(
      download::DownloadItem* download,
      bool is_top_level_encrypted_archive);

  // Returns whether the user has entered an incorrect password for the
  // archive.
  static bool HasIncorrectPassword(const download::DownloadItem* download);
  static void SetHasIncorrectPassword(download::DownloadItem* download,
                                      bool has_incorrect_password);

  // Converts an `event` to the Safe Browsing report proto format.
  static safe_browsing::ClientSafeBrowsingReportRequest::DownloadWarningAction
  ConstructCsbrrDownloadWarningAction(const WarningActionEvent& event);

  // Returns whether we have shown a local password decryption prompt for this
  // download.
  static bool HasShownLocalDecryptionPrompt(
      const download::DownloadItem* download);
  static void SetHasShownLocalDecryptionPrompt(download::DownloadItem* download,
                                               bool has_shown);

  // Returns the reason we initiated deep scanning for the download.
  static DeepScanTrigger DownloadDeepScanTrigger(
      const download::DownloadItem* download);
  static void SetDeepScanTrigger(download::DownloadItem* download,
                                 DeepScanTrigger trigger);

  // Returns whether an encrypted archive was fully extracted.
  static bool IsFullyExtractedArchive(const download::DownloadItem* download);
  static void SetIsFullyExtractedArchive(download::DownloadItem* download,
                                         bool extracted);

  // Time and surface of the first SHOWN event. Time will be null if SHOWN has
  // not yet been logged. Surface will return nullopt if SHOWN has not yet been
  // logged.
  static base::Time WarningFirstShownTime(
      const download::DownloadItem* download);
  static std::optional<WarningSurface> WarningFirstShownSurface(
      const download::DownloadItem* download);

 private:
  DownloadItemWarningData();

  template <typename F, typename V>
  static V GetWithDefault(const download::DownloadItem* download,
                          F&& f,
                          V&& default_value);
  static DownloadItemWarningData* GetOrCreate(download::DownloadItem* download);

  std::vector<WarningActionEvent> ActionEvents() const;

  static const char kKey[];

  base::Time warning_first_shown_time_;
  std::optional<WarningSurface> warning_first_shown_surface_ = std::nullopt;
  std::vector<WarningActionEvent> action_events_;
  bool is_top_level_encrypted_archive_ = false;
  bool has_incorrect_password_ = false;
  bool has_shown_local_decryption_prompt_ = false;
  bool fully_extracted_archive_ = false;
  // Whether a "shown" event has been logged for the Downloads Page for this
  // download. Not persisted across restarts.
  bool logged_downloads_page_shown_ = false;
  DeepScanTrigger deep_scan_trigger_ = DeepScanTrigger::TRIGGER_UNKNOWN;
};

#endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_WARNING_DATA_H_