File: files_policy_notification_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 (445 lines) | stat: -rw-r--r-- 18,670 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
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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
// Copyright 2023 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_DLP_FILES_POLICY_NOTIFICATION_MANAGER_H_
#define CHROME_BROWSER_ASH_POLICY_DLP_FILES_POLICY_NOTIFICATION_MANAGER_H_

#include <memory>
#include <optional>
#include <queue>

#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ash/file_manager/io_task.h"
#include "chrome/browser/ash/file_manager/io_task_controller.h"
#include "chrome/browser/ash/policy/dlp/dialogs/files_policy_dialog.h"
#include "chrome/browser/chromeos/policy/dlp/dialogs/policy_dialog_base.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_confidential_file.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_file_destination.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_files_utils.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/browser_context.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/widget/widget_observer.h"

namespace content {
class BrowserContext;
}  // namespace content

namespace policy {

// The type of policy notification.
enum class NotificationType {
  kError,
  kWarning,
};

// The policy notification button index.
enum NotificationButton {
  CANCEL = 0,
  OK,
};

// FilesPolicyNotificationManager is responsible for showing block and warning
// notifications/dialogs for files because of DLP and enterprise connectors
// policies.
class FilesPolicyNotificationManager
    : public KeyedService,
      public BrowserListObserver,
      public file_manager::io_task::IOTaskController::Observer {
 public:
  explicit FilesPolicyNotificationManager(content::BrowserContext* context);

  FilesPolicyNotificationManager(const FilesPolicyNotificationManager&) =
      delete;
  FilesPolicyNotificationManager& operator=(
      const FilesPolicyNotificationManager&) = delete;

  ~FilesPolicyNotificationManager() override;

  // KeyedService overrides:
  void Shutdown() override;

  // Show DLP block UI. If `task_id` is set, the corresponding IOTask will be
  // updated with the blocked files. Otherwise a desktop notification will be
  // shown.
  virtual void ShowDlpBlockedFiles(
      std::optional<file_manager::io_task::IOTaskId> task_id,
      std::vector<base::FilePath> blocked_files,
      dlp::FileAction action);

  // Associates `dialog_info` to the given enterprise connectors `reason` in the
  // information corresponding to the IOTask with `task_id`. This will replace
  // previously stored dialog info with the same `reason`.
  virtual void SetConnectorsBlockedFiles(
      file_manager::io_task::IOTaskId task_id,
      dlp::FileAction action,
      FilesPolicyDialog::BlockReason reason,
      FilesPolicyDialog::Info dialog_info);

  // Shows DLP Warning UI. If `task_id` is set, the corresponding IOTask
  // will be paused. Otherwise a desktop notification will be shown. Virtual
  // to allow overrides in tests.
  virtual void ShowDlpWarning(
      WarningWithJustificationCallback callback,
      std::optional<file_manager::io_task::IOTaskId> task_id,
      std::vector<base::FilePath> warning_files,
      const DlpFileDestination& destination,
      dlp::FileAction action);

  // Shows Connectors Warning UI and pauses the corresponding IOTask.
  // Virtual to allow overrides in tests.
  virtual void ShowConnectorsWarning(WarningWithJustificationCallback callback,
                                     file_manager::io_task::IOTaskId task_id,
                                     dlp::FileAction action,
                                     FilesPolicyDialog::Info dialog_info);

  // Shows a Files Policy warning or error desktop notification with
  // `notification_id` based on `status`. Used for IO tasks.
  virtual void ShowFilesPolicyNotification(
      const std::string& notification_id,
      const file_manager::io_task::ProgressStatus& status);

  // Shows a policy dialog of type `type` for task identified by `task_id`.
  // Used for copy and move operations.
  virtual void ShowDialog(file_manager::io_task::IOTaskId task_id,
                          FilesDialogType type);

  // Shows a DLP warning timeout notification for `action`. `notification_id`
  // should have value for IO tasks. When it  doesn't have a value, i.e. for non
  // IO tasks, computes a new unique id for the notification.
  void ShowDlpWarningTimeoutNotification(
      dlp::FileAction action,
      std::optional<std::string> notification_id = std::nullopt);

  // Returns whether IO task is being tracked.
  bool HasIOTask(file_manager::io_task::IOTaskId task_id) const;

  // Runs warning callback for the corresponding IOTask with should_proceed set
  // to true.
  virtual void OnIOTaskResumed(file_manager::io_task::IOTaskId task_id);

  // Force shows a desktop notification for all tracked IO tasks with blocked
  // files.
  void ShowBlockedNotifications();

  // Clears any info stored about the task with `task_id`.
  virtual void OnErrorItemDismissed(file_manager::io_task::IOTaskId task_id);

  std::map<FilesPolicyDialog::BlockReason, FilesPolicyDialog::Info>
  GetIOTaskDialogInfoMapForTesting(
      file_manager::io_task::IOTaskId task_id) const;
  // Returns whether IO task has a warning timeout timer.
  bool HasWarningTimerForTesting(file_manager::io_task::IOTaskId task_id) const;

  // Used in tests to set the test task runner.
  void SetTaskRunnerForTesting(scoped_refptr<base::SequencedTaskRunner>);

 protected:
  // The number of notifications shown so far. Used to calculate a unique
  // notification ID. Only applies to non IOTasks operations (upload, download,
  // etc.) as notifications for IOTasks are shown based on the task state from
  // the SystemNotificationManager.
  size_t notification_count_ = 0;

 private:
  // Holds all information related to file task warning. Any extra information
  // needed for custom messaging should be added here.
  struct WarningInfo {
    WarningInfo() = delete;
    WarningInfo(Policy warning_reason,
                WarningWithJustificationCallback warning_callback,
                WarningWithJustificationCallback dialog_callback,
                FilesPolicyDialog::Info dialog_info);
    WarningInfo(WarningInfo&& other);
    ~WarningInfo();

    // Warning reason. There should be only one policy per warning as mixed
    // warnings aren't supported.
    Policy warning_reason;
    // Warning callback.
    WarningWithJustificationCallback warning_callback;
    // Invoked by clicking on dialog's buttons. Wrapper around `callback` as it
    // performs additional actions before running `callback` with the same
    // `should_proceed` parameter.
    WarningWithJustificationCallback dialog_callback;
    // Holds warning dialog info such as the warned files, the warning message,
    // an optional custom learn more URL or whether bypassing the warning
    // requires a user justification that should be used when displaying the
    // dialog.
    FilesPolicyDialog::Info dialog_info;

    // A potentially saved justification for bypassing a warning.
    std::optional<std::u16string> user_justification;
  };

  // Holds needed information for each tracked file task.
  class FileTaskInfo : public views::WidgetObserver {
   public:
    explicit FileTaskInfo(dlp::FileAction action);
    FileTaskInfo(FileTaskInfo&& other);
    ~FileTaskInfo() override;

    // Starts observing `widget`. Should be called when the warning/error dialog
    // is created.
    void AddWidget(views::Widget* widget);
    // Closes `widget_` if it's not nullptr.
    void CloseWidget();
    views::Widget* widget() const { return widget_; }

    // Sets `warning_info_`.
    void SetWarningInfo(WarningInfo warning_info);
    // Resets `warning_info_`.
    void ResetWarningInfo();
    // Returns a pointer to WarningInfo if it exists. Otherwise, it returns
    // nullptr.
    WarningInfo* GetWarningInfo();
    // Returns true if `warning_info_` has value.
    bool HasWarningInfo() const;

    const std::map<FilesPolicyDialog::BlockReason, FilesPolicyDialog::Info>&
    block_info_map() const {
      return block_info_map_;
    }

    // Stores `dialog_info` associated with the given `reason`.
    // Calling this method a second time with the same `reason` will overwrite
    // previously stored `files` and `dialog_settings`.
    void SetBlockedFiles(FilesPolicyDialog::BlockReason reason,
                         FilesPolicyDialog::Info dialog_info);

    // Returns the overall number of blocked files irrespective of their block
    // reason.
    size_t GetBlockedFilesSize() const;

    dlp::FileAction action() const { return action_; }

   private:
    // views::WidgetObserver overrides:
    void OnWidgetDestroying(views::Widget* widget) override;

    // Should have value only if there's warning.
    std::optional<WarningInfo> warning_info_;
    // A map of files and dialog settings blocked for certain block reasons.
    std::map<FilesPolicyDialog::BlockReason, FilesPolicyDialog::Info>
        block_info_map_;
    // The action that's restricted.
    dlp::FileAction action_;
    // Warning/Error dialog widget. Each FileTask is expected to have only one
    // open dialog at a time.
    raw_ptr<views::Widget> widget_ = nullptr;
    // Warning/Error dialog widget observation.
    base::ScopedObservation<views::Widget, views::WidgetObserver>
        widget_observation_{this};
  };

  // Callback to show the dialog. Invoked with a Files App window when
  // successfully opened, or null if opening the Files App times out.
  using ShowDialogCallback = base::OnceCallback<void(gfx::NativeWindow)>;

  // Holds information for showing a Files Policy dialog.
  struct DialogInfo {
    DialogInfo() = delete;
    DialogInfo(ShowDialogCallback callback,
               file_manager::io_task::IOTaskId task_id,
               base::OnceClosure timeout_callback);
    DialogInfo(ShowDialogCallback callback,
               std::string notification_id,
               base::OnceClosure timeout_callback);
    ~DialogInfo();

    // Id of the task for which dialog is being shown. Used for Copy and Move
    // IOTasks.
    std::optional<file_manager::io_task::IOTaskId> task_id;
    // Id of the notification for which dialog is being shown. Used for non IO
    // tasks.
    std::optional<std::string> notification_id;
    // Callback to show the dialog.
    ShowDialogCallback dialog_callback;
    // Callback to stop waiting for the Files app.
    base::OnceClosure timeout_callback;
    base::TimeTicks created_at;
    base::OneShotTimer timeout_timer;
  };

  // Shows a Files Policy warning or error desktop notification with
  // `notification_id` for an IOTask with `task_id`.
  void ShowFilesPolicyNotification(const std::string& notification_id,
                                   file_manager::io_task::IOTaskId task_id);

  // Click handler for Data Leak Prevention or Enterprise Connectors policy
  // warning notifications.
  void HandleFilesPolicyWarningNotificationClick(
      file_manager::io_task::IOTaskId task_id,
      std::string notification_id,
      std::optional<int> button_index);

  // Click handler for Data Leak Prevention or Enterprise Connectors policy
  // error notifications.
  void HandleFilesPolicyErrorNotificationClick(
      file_manager::io_task::IOTaskId task_id,
      std::string notification_id,
      std::optional<int> button_index);

  // Click handler for DLP warning notifications. Used for non IO tasks.
  void HandleDlpWarningNotificationClick(std::string notification_id,
                                         std::optional<int> button_index);

  // Click handler for DLP error notifications. Used for non IO tasks.
  void HandleDlpErrorNotificationClick(std::string notification_id,
                                       std::vector<base::FilePath> files,
                                       dlp::FileAction action,
                                       std::optional<int> button_index);

  // Shows a FilesPolicyDialog of `type` for task with `task_id`.
  void ShowDialogForIOTask(file_manager::io_task::IOTaskId task_id,
                           FilesDialogType type,
                           gfx::NativeWindow modal_parent);

  // Shows a FilesPolicyDialog of `type` for non-IO task associated with
  // `notification_id`.
  void ShowDialogForNonIOTask(std::string notification_id,
                              FilesDialogType type,
                              gfx::NativeWindow modal_parent);

  // Shows a FilesPolicyDialog of `type` based on `info`.
  void ShowFilesPolicyDialog(FileTaskInfo& info,
                             FilesDialogType type,
                             gfx::NativeWindow modal_parent);

  // Starts tracking IO task with `task_id`.
  void AddIOTask(file_manager::io_task::IOTaskId task_id,
                 dlp::FileAction action);

  // Launches the Files App in default directory and appends `dialog_info` to
  // the queue of pending dialogs in order to show the dialog over it.
  void LaunchFilesApp(std::unique_ptr<DialogInfo> dialog_info);

  // BrowserListObserver overrides:
  // Called when opening a new Files App window to use as the modal parent for a
  // FilesPolicyDialog.
  void OnBrowserAdded(Browser* browser) override;

  // file_manager::io_task::IOTaskController::Observer overrides:
  void OnIOTaskStatus(
      const file_manager::io_task::ProgressStatus& status) override;

  // Returns whether IO task has any blocked file.
  bool HasBlockedFiles(file_manager::io_task::IOTaskId task_id) const;

  // Returns whether IO task has a warning.
  bool HasWarning(file_manager::io_task::IOTaskId task_id) const;

  // Returns whether non IO task is being tracked.
  bool HasNonIOTask(const std::string& notification_id) const;

  // Returns whether non IO task has any blocked file.
  bool HasBlockedFiles(const std::string& notification_id) const;

  // Returns whether non IO task has a warning.
  bool HasWarning(const std::string& notification_id) const;

  // Called when the user clicks on one of the warning dialog's buttons.
  // Resumes/cancels the task with `task_id` based on the value of
  // `should_proceed`. Used for Copy and Move IOTasks.
  void OnIOTaskWarningDialogClicked(
      file_manager::io_task::IOTaskId task_id,
      Policy warning_reason,
      std::optional<std::u16string> user_justification,
      bool should_proceed);

  // Called when the user clicks on one of the warning dialog's buttons.
  // associated with `notification_id`. Resumes/cancels the operation based on
  // the value of `should_proceed`.
  void OnNonIOTaskWarningDialogClicked(
      const std::string& notification_id,
      std::optional<std::u16string> user_justification,
      bool should_proceed);

  // Opens DLP Learn more link and closes the notification having
  // `notification_id`.
  void OnDlpLearnMoreButtonClicked(const std::string& notification_id,
                                   std::optional<int> button_index);

  // Calls the IOTaskController to resume the task with `task_id`.
  void Resume(file_manager::io_task::IOTaskId task_id);

  // Calls the IOTaskController to cancel the task with `task_id`.
  void Cancel(file_manager::io_task::IOTaskId task_id);

  // Shows DLP block desktop notification.
  void ShowDlpBlockNotification(std::vector<base::FilePath> blocked_files,
                                dlp::FileAction action);

  // Shows DLP warning desktop notification.
  void ShowDlpWarningNotification(WarningWithJustificationCallback callback,
                                  std::vector<base::FilePath> warning_files,
                                  const DlpFileDestination& destination,
                                  dlp::FileAction action);

  // Pauses IO task due to `warning_reason`.
  void PauseIOTask(file_manager::io_task::IOTaskId task_id,
                   WarningWithJustificationCallback callback,
                   dlp::FileAction action,
                   Policy warning_reason,
                   FilesPolicyDialog::Info dialog_info);

  // Called after opening the Files App times out.
  // Stops waiting for the app and shows a dialog for `task_id` without a modal
  // parent (i.e. as a system modal).
  void OnIOTaskAppLaunchTimedOut(file_manager::io_task::IOTaskId task_id);

  // Called after opening the Files App times out.
  // Stops waiting for the app and shows a dialog for `notification_id` without
  // a modal parent (i.e. as a system modal).
  void OnNonIOTaskAppLaunchTimedOut(std::string notification_id);

  // Helper method that pops the oldest entry from `pending_dialogs_` and
  // creates a dialog with with `modal_parent`. No-op if the list is empty.
  void ShowPendingDialog(gfx::NativeWindow modal_parent);

  // Called when the warning times out. Stops waiting for the user input,
  // cancels the task, and runs the warning callback with should_proceed set to
  // false.
  void OnIOTaskWarningTimedOut(const file_manager::io_task::IOTaskId& task_id);

  // Called when the warning times out. Stops waiting for the user input, and
  // runs the warning callback with should_proceed set to false.
  void OnNonIOTaskWarningTimedOut(const std::string& notification_id);

  // Callback to show a policy dialog after waiting to open a Files App window.
  base::OnceCallback<void(gfx::NativeWindow)> pending_callback_;

  // Context for which the FPNM is created.
  raw_ptr<content::BrowserContext, DanglingUntriaged> context_;

  // A map from tracked IO tasks ids to their info.
  std::map<file_manager::io_task::IOTaskId, FileTaskInfo> io_tasks_;

  // A map from notification ids to related task info for non IO operations.
  std::map<std::string, FileTaskInfo> non_io_tasks_;

  // Callbacks to show a policy dialog after waiting to open a Files App window.
  std::queue<std::unique_ptr<DialogInfo>> pending_dialogs_;

  // Used to fallack to system modal if opening the Files App times out.
  scoped_refptr<base::SequencedTaskRunner> task_runner_;

  // Active timers for IOTasks warnings.
  base::flat_map<file_manager::io_task::IOTaskId,
                 std::unique_ptr<base::OneShotTimer>>
      io_tasks_warning_timers_;

  // Active timers for non-IOTasks warnings.
  base::flat_map<std::string, std::unique_ptr<base::OneShotTimer>>
      non_io_tasks_warning_timers_;

  base::WeakPtrFactory<FilesPolicyNotificationManager> weak_factory_{this};
};

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_DLP_FILES_POLICY_NOTIFICATION_MANAGER_H_