chromium/chrome/browser/download/android/chrome_duplicate_download_infobar_delegate.cc

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

#include "chrome/browser/download/android/chrome_duplicate_download_infobar_delegate.h"

#include <memory>
#include <optional>

#include "base/android/path_utils.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/download/android/download_controller.h"
#include "chrome/browser/download/android/download_dialog_utils.h"
#include "chrome/browser/ui/android/infobars/duplicate_download_infobar.h"
#include "components/download/public/common/download_path_reservation_tracker.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/infobars/core/infobar.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item_utils.h"
#include "ui/shell_dialogs/selected_file_info.h"

namespace android {

ChromeDuplicateDownloadInfoBarDelegate::
    ~ChromeDuplicateDownloadInfoBarDelegate() {
  if (download_item_)
    download_item_->RemoveObserver(this);
}

// static
void ChromeDuplicateDownloadInfoBarDelegate::Create(
    infobars::ContentInfoBarManager* infobar_manager,
    download::DownloadItem* download_item,
    const base::FilePath& file_path,
    DownloadTargetDeterminerDelegate::ConfirmationCallback callback) {
  infobar_manager->AddInfoBar(DuplicateDownloadInfoBar::CreateInfoBar(
      base::WrapUnique(new ChromeDuplicateDownloadInfoBarDelegate(
          download_item, file_path, std::move(callback)))));
}

void ChromeDuplicateDownloadInfoBarDelegate::OnDownloadDestroyed(
    download::DownloadItem* download_item) {
  DCHECK_EQ(download_item, download_item_);
  download_item_ = nullptr;
}

ChromeDuplicateDownloadInfoBarDelegate::ChromeDuplicateDownloadInfoBarDelegate(
    download::DownloadItem* download_item,
    const base::FilePath& file_path,
    DownloadTargetDeterminerDelegate::ConfirmationCallback
        file_selected_callback)
    : download_item_(download_item),
      file_path_(file_path),
      file_selected_callback_(std::move(file_selected_callback)) {
  download_item_->AddObserver(this);
}

infobars::InfoBarDelegate::InfoBarIdentifier
ChromeDuplicateDownloadInfoBarDelegate::GetIdentifier() const {
  return DUPLICATE_DOWNLOAD_INFOBAR_DELEGATE_ANDROID;
}

bool ChromeDuplicateDownloadInfoBarDelegate::Accept() {
  if (!download_item_) {
    return true;
  }

  base::FilePath download_dir;
  if (!base::android::GetDownloadsDirectory(&download_dir)) {
    return true;
  }

  download::DownloadPathReservationTracker::GetReservedPath(
      download_item_, file_path_, download_dir,
      base::FilePath(), /* fallback_directory */
      true, download::DownloadPathReservationTracker::UNIQUIFY,
      base::BindOnce(&DownloadDialogUtils::CreateNewFileDone,
                     std::move(file_selected_callback_)));
  return true;
}

bool ChromeDuplicateDownloadInfoBarDelegate::Cancel() {
  if (!download_item_)
    return true;

  std::move(file_selected_callback_)
      .Run(DownloadConfirmationResult::CANCELED, ui::SelectedFileInfo());
  return true;
}

std::string ChromeDuplicateDownloadInfoBarDelegate::GetFilePath() const {
  return file_path_.value();
}

void ChromeDuplicateDownloadInfoBarDelegate::InfoBarDismissed() {
  Cancel();
}

std::optional<Profile::OTRProfileID>
ChromeDuplicateDownloadInfoBarDelegate::GetOTRProfileID() const {
  content::BrowserContext* browser_context =
      content::DownloadItemUtils::GetBrowserContext(download_item_);
  // If belongs to an off-the-record profile, then the OTRProfileID should be
  // taken from the browser context to support multiple off-the-record profiles.
  if (browser_context && browser_context->IsOffTheRecord()) {
    return Profile::FromBrowserContext(browser_context)->GetOTRProfileID();
  }
  // If belongs to the regular profile, then OTRProfileID should be null.
  return std::nullopt;
}

}  // namespace android