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

content / browser / file_system_access / file_path_watcher / file_path_watcher_change_tracker.h [blame]

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_PATH_WATCHER_FILE_PATH_WATCHER_CHANGE_TRACKER_H_
#define CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_PATH_WATCHER_FILE_PATH_WATCHER_CHANGE_TRACKER_H_

#include "base/files/file_path.h"
#include "content/browser/file_system_access/file_path_watcher/file_path_watcher.h"

namespace content {

class FilePathWatcherChangeTracker {
 public:
  using ChangeInfo = FilePathWatcher::ChangeInfo;
  using ChangeType = FilePathWatcher::ChangeType;

  FilePathWatcherChangeTracker(base::FilePath target_path,
                               FilePathWatcher::Type type);
  FilePathWatcherChangeTracker(const FilePathWatcherChangeTracker&) = delete;
  FilePathWatcherChangeTracker& operator=(const FilePathWatcherChangeTracker&) =
      delete;

  FilePathWatcherChangeTracker(FilePathWatcherChangeTracker&&);
  FilePathWatcherChangeTracker& operator=(FilePathWatcherChangeTracker&&) =
      default;

  ~FilePathWatcherChangeTracker();

  // Returns whether the `FilePathWatcherChangeTracker` knows the target exists.
  bool KnowTargetExists();

  // Add a change reported by the Window's OS.
  void AddChange(base::FilePath path, DWORD win_change_type);

  // Call when changes may have been missed.
  void MayHaveMissedChanges();

  // Gets the ChangeInfo's to report since the last call to `PopChanges`.
  //
  // Passing `next_change_soon` as true indicates another change will be added
  // soon so we don't need to finish coalescing events yet.
  std::vector<ChangeInfo> PopChanges(bool next_change_soon);

 private:
  enum class ExistenceStatus {
    // We know the file exists.
    kExists,
    // We know the file is gone.
    kGone,
    // The file may or may not exist because an ancestor was moved into place.
    kMayHaveMovedIntoPlace,
  };

  // Converts a `change_info` from `kMoved` to `kCreated` if it's a move from
  // out of scope to in scope. All moves into scope should be reported as
  // created.
  void ConvertMoveToCreateIfOutOfScope(ChangeInfo& change_info);

  void HandleChangeEffect(ExistenceStatus before_action,
                          ExistenceStatus after_action);

  void HandleSelfChange(ChangeInfo change);

  void HandleDescendantChange(ChangeInfo change, bool is_direct_child);

  void HandleAncestorChange(ChangeInfo change);

  void HandleOtherChange(ChangeInfo change);

  // The path that we're tracking changes for.
  base::FilePath target_path_;
  FilePathWatcher::Type type_;

  // Our current knowledge about the the existence of target based on what's
  // been passed to `AddChange` and calls to `GetFileInfo`.
  ExistenceStatus target_status_;

  // Changes to report based on what OS changes have been passed to `AddChange`.
  std::vector<ChangeInfo> changes_;

  // The path of the last `FILE_ACTION_RENAMED_OLD_NAME` OS change that was
  // passed to `AddChange`. Used to coalesce the move into a single event.
  base::FilePath last_moved_from_path_;

  // The `ChangeInfo` of the last `FILE_ACTION_RENAMED_OLD_NAME` OS change that
  // was passed to `AddChange`. Used to coalesce the move into a single event.
  ChangeInfo last_move_change_;

  // The `ChangeInfo` of the last `FILE_ACTION_REMOVED` OS change that was
  // passed to `AddChange`. Used to coalesce the overwrites into a single move
  // event.
  std::optional<ChangeInfo> last_deleted_change_;
};
}  // namespace content

#endif  // CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_PATH_WATCHER_FILE_PATH_WATCHER_CHANGE_TRACKER_H_