chromium/chrome/browser/ash/file_manager/documents_provider_root_manager.h

// Copyright 2019 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_FILE_MANAGER_DOCUMENTS_PROVIDER_ROOT_MANAGER_H_
#define CHROME_BROWSER_ASH_FILE_MANAGER_DOCUMENTS_PROVIDER_ROOT_MANAGER_H_

#include <optional>
#include <string>
#include <vector>

#include "ash/components/arc/mojom/file_system.mojom-forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"

class Profile;

namespace arc {

class ArcFileSystemOperationRunner;

}  // namespace arc

namespace file_manager {

// Keeps track of available DocumentsProvider roots.
//
// This interacts with ARC container via Mojo API, and keeps track of currently
// available roots.
// In addition, This class filters roots so that File Manager doesn't have
// duplicated volumes. (e.g. Google Drive root from ARC container should be
// filtered out since Files app has its own Google Drive integration.)
// This notifies its observers about roots which are added, deleted, or
// modified.
// When metadata of a root is modified, both OnDocumentsProviderRootRemoved()
// and OnDocumentsProviderRootAdded() will be called for observers in this
// order.
// Note that this class's instance will not interact with ARC container until
// SetEnabled(true) is called. This is not enable by default.
class DocumentsProviderRootManager : public arc::ArcFileSystemBridge::Observer {
 public:
  class Observer {
   public:
    virtual ~Observer() = default;

    // Called when a new available root is found. When an existing root is
    // modified, both RootRemoved() and RootAdded() will be called in this
    // order.
    virtual void OnDocumentsProviderRootAdded(
        const std::string& authority,
        const std::string& root_id,
        const std::string& document_id,
        const std::string& title,
        const std::string& summary,
        const GURL& icon_url,
        bool read_only,
        const std::vector<std::string>& mime_types) = 0;

    // Called when an existing root is not available anymore. When an existing
    // root is modified, both RootRemoved() and RootAdded() will be called in
    // this order.
    virtual void OnDocumentsProviderRootRemoved(const std::string& authority,
                                                const std::string& root_id) = 0;
  };
  DocumentsProviderRootManager(Profile* profile,
                               arc::ArcFileSystemOperationRunner* runner);

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

  ~DocumentsProviderRootManager() override;

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Allows DocumentsProviderRootManager retrieve DocumentsProvider roots from
  // ARC container.
  void SetEnabled(bool enabled);

  // ArcFileSystemBridge::Observer overrides:
  void OnRootsChanged() override;

 private:
  struct RootInfo {
    std::string authority;
    std::string root_id;
    std::string document_id;
    std::string title;
    std::string summary;
    SkBitmap icon;
    bool supports_create;
    std::vector<std::string> mime_types;

    RootInfo();
    RootInfo(const RootInfo& that);
    RootInfo(RootInfo&& that) noexcept;
    ~RootInfo();
    RootInfo& operator=(const RootInfo& that);
    RootInfo& operator=(RootInfo&& that) noexcept;
    bool operator<(const RootInfo& rhs) const;
  };

  // Requests ArcFileSystemOperationRunner to retrieve available roots from ARC
  // container.
  void RequestGetRoots();

  // Called when retrieving available roots from ARC container is done.
  void OnGetRoots(std::optional<std::vector<arc::mojom::RootPtr>> maybe_roots);

  // Updates this class's internal list of available roots.
  void UpdateRoots(std::vector<RootInfo> roots);

  // Clears this class's internal list of available roots.
  void ClearRoots();

  // Notifies observers that a new available root is found.
  void NotifyRootAdded(const RootInfo& root_info);

  // Notifies observers that an existing root is removed.
  void NotifyRootRemoved(const RootInfo& root_info);

  const raw_ptr<Profile> profile_;
  const raw_ptr<arc::ArcFileSystemOperationRunner> runner_;
  bool is_enabled_ = false;
  base::ObserverList<Observer>::Unchecked observer_list_;
  std::vector<RootInfo> current_roots_;

  base::WeakPtrFactory<DocumentsProviderRootManager> weak_ptr_factory_{this};
};

}  // namespace file_manager

#endif  // CHROME_BROWSER_ASH_FILE_MANAGER_DOCUMENTS_PROVIDER_ROOT_MANAGER_H_