chromium/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h

// Copyright 2020 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_UI_ASH_HOLDING_SPACE_HOLDING_SPACE_DOWNLOADS_DELEGATE_H_
#define CHROME_BROWSER_UI_ASH_HOLDING_SPACE_HOLDING_SPACE_DOWNLOADS_DELEGATE_H_

#include <memory>
#include <set>
#include <string>
#include <vector>

#include "base/containers/unique_ptr_adapters.h"
#include "base/scoped_observation.h"
#include "chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h"
#include "chrome/browser/download/notification/multi_profile_download_notifier.h"
#include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h"

namespace content {
class DownloadManager;
}  // namespace content

namespace ash {

namespace holding_space_metrics {
enum class EventSource;
}  // namespace holding_space_metrics

// A delegate of `HoldingSpaceKeyedService` tasked with monitoring the status of
// of downloads on its behalf.
class HoldingSpaceDownloadsDelegate
    : public HoldingSpaceKeyedServiceDelegate,
      public MultiProfileDownloadNotifier::Client,
      public arc::ArcFileSystemBridge::Observer {
 public:
  HoldingSpaceDownloadsDelegate(HoldingSpaceKeyedService* service,
                                HoldingSpaceModel* model);
  HoldingSpaceDownloadsDelegate(const HoldingSpaceDownloadsDelegate&) = delete;
  HoldingSpaceDownloadsDelegate& operator=(
      const HoldingSpaceDownloadsDelegate&) = delete;
  ~HoldingSpaceDownloadsDelegate() override;

  // Attempts to mark the download underlying the given `item` to open when
  // complete. Returns `std::nullopt` on success or the reason if the attempt
  // was not successful.
  std::optional<holding_space_metrics::ItemLaunchFailureReason>
  OpenWhenComplete(const HoldingSpaceItem* item);

 private:
  class InProgressDownload;

  // HoldingSpaceKeyedServiceDelegate:
  void OnPersistenceRestored() override;
  void OnHoldingSpaceItemsRemoved(
      const std::vector<const HoldingSpaceItem*>& items) override;

  // MultiProfileDownloadNotifier::Client:
  void OnManagerInitialized(content::DownloadManager* manager) override;
  void OnManagerGoingDown(content::DownloadManager* manager) override;
  void OnDownloadCreated(content::DownloadManager* manager,
                         download::DownloadItem* item) override;
  void OnDownloadUpdated(content::DownloadManager* manager,
                         download::DownloadItem* item) override;

  // arc::ArcFileSystemBridge::Observer:
  void OnMediaStoreUriAdded(
      const GURL& uri,
      const arc::mojom::MediaStoreMetadata& metadata) override;

  // Invoked when the specified `in_progress_download` is updated. If
  // `invalidate_image` is `true`, the image for the associated holding space
  // item will be explicitly invalidated. This is necessary if, for example, the
  // underlying download is transitioning to/from a dangerous or insecure state.
  void OnDownloadUpdated(InProgressDownload* in_progress_download,
                         bool invalidate_image);

  // Invoked when the specified `in_progress_download` is completed.
  void OnDownloadCompleted(InProgressDownload* in_progress_download);

  // Invoked when the specified `in_progress_download` fails. This may be due to
  // cancellation, interruption, or destruction of the underlying download.
  void OnDownloadFailed(const InProgressDownload* in_progress_download);

  // Invoked to erase the specified `in_progress_download` when it is no longer
  // needed either due to completion or failure of the underlying download.
  void EraseDownload(const InProgressDownload* in_progress_download);

  // Creates or updates the holding space item in the model associated with the
  // specified `in_progress_download`. If `invalidate_image` is `true`, the
  // image for the holding space item will be explicitly invalidated. This is
  // necessary if, for example, the underlying download is transitioning to/from
  // a dangerous or insecure state.
  void CreateOrUpdateHoldingSpaceItem(InProgressDownload* in_progress_download,
                                      bool invalidate_image);

  // Attempts to cancel/pause/resume the download underlying the given `item`.
  void Cancel(const HoldingSpaceItem* item,
              HoldingSpaceCommandId command_id,
              holding_space_metrics::EventSource event_source);
  void Pause(const HoldingSpaceItem* item,
             HoldingSpaceCommandId command_id,
             holding_space_metrics::EventSource event_source);
  void Resume(const HoldingSpaceItem* item,
              HoldingSpaceCommandId command_id,
              holding_space_metrics::EventSource event_source);

  // The collection of currently in-progress downloads.
  std::set<std::unique_ptr<InProgressDownload>, base::UniquePtrComparator>
      in_progress_downloads_;

  base::ScopedObservation<arc::ArcFileSystemBridge,
                          arc::ArcFileSystemBridge::Observer>
      arc_file_system_bridge_observation_{this};

  // Notifies this delegate of download events created for the profile
  // associated with this delegate's service. If the incognito profile
  // integration feature is enabled, the delegate is also notified of download
  // events created for incognito profiles spawned from the service's main
  // profile.
  MultiProfileDownloadNotifier download_notifier_{
      this, /*wait_for_manager_initialization=*/true};

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

}  // namespace ash

#endif  // CHROME_BROWSER_UI_ASH_HOLDING_SPACE_HOLDING_SPACE_DOWNLOADS_DELEGATE_H_