// 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.

#include "chrome/browser/ash/scanning/scan_service.h"

#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "ash/webui/scanning/mojom/scanning.mojom-test-utils.h"
#include "ash/webui/scanning/mojom/scanning.mojom.h"
#include "ash/webui/scanning/scanning_uma.h"
#include "base/containers/flat_set.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.h"
#include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h"
#include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
#include "chrome/browser/ui/ash/holding_space/scoped_test_mount_point.h"
#include "chrome/browser/ui/ash/test_session_controller.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/components/dbus/lorgnette/lorgnette_service.pb.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"

namespace ash {

using holding_space::ScopedTestMountPoint;

namespace {

namespace mojo_ipc = scanning::mojom;

using ProtoScanFailureMode = lorgnette::ScanFailureMode;

// Path to the user's "My files" folder.
constexpr char kMyFilesPath[] = "/home/chronos/user/MyFiles";

// Scanner names used for tests.
constexpr char kFirstTestScannerName[] = "Test Scanner 1";
constexpr char16_t kFirstTestScannerName16[] = u"Test Scanner 1";
constexpr char kSecondTestScannerName[] = "Test Scanner 2";
constexpr char16_t kSecondTestScannerName16[] = u"Test Scanner 2";
constexpr char kEpsonTestName[] =
    "airscan:escl:EPSON XP-7100 Series:http://100.107.108.190:443/eSCL/";

// Document source name used for tests.
constexpr char kDocumentSourceName[] = "Flatbed";
constexpr char kAdfSourceName[] = "ADF Duplex";

// Resolutions used for tests.
constexpr uint32_t kFirstResolution = 75;
constexpr uint32_t kSecondResolution = 300;

// Email used for test profile.
constexpr char kUserEmail[] = "user@email.com";

// Translation from file type to saved file extension.
const std::map<mojo_ipc::FileType, std::string> kFileTypes = {
    {mojo_ipc::FileType::kJpg, "jpg"},
    {mojo_ipc::FileType::kPdf, "pdf"},
    {mojo_ipc::FileType::kPng, "png"}};

// Returns a DocumentSource object.
lorgnette::DocumentSource CreateLorgnetteDocumentSource() {
  lorgnette::DocumentSource source;
  source.set_type(lorgnette::SOURCE_PLATEN);
  source.set_name(kDocumentSourceName);
  source.add_color_modes(lorgnette::MODE_COLOR);
  source.add_resolutions(kFirstResolution);
  source.add_resolutions(kSecondResolution);
  return source;
}

// Returns an ADF Duplex DocumentSource object.
lorgnette::DocumentSource CreateAdfDuplexDocumentSource() {
  lorgnette::DocumentSource source;
  source.set_type(lorgnette::SOURCE_ADF_DUPLEX);
  source.set_name(kAdfSourceName);
  return source;
}

// Returns a ScannerCapabilities object.
lorgnette::ScannerCapabilities CreateLorgnetteScannerCapabilities() {
  lorgnette::ScannerCapabilities caps;
  *caps.add_sources() = CreateLorgnetteDocumentSource();
  return caps;
}

// Returns a ScannerCapabilities object used for testing a scanner
// that flips alternate pages..
lorgnette::ScannerCapabilities CreateEpsonScannerCapabilities() {
  lorgnette::ScannerCapabilities caps;
  *caps.add_sources() = CreateAdfDuplexDocumentSource();
  caps.add_color_modes(lorgnette::MODE_COLOR);
  caps.add_resolutions(kFirstResolution);
  caps.add_resolutions(kSecondResolution);
  return caps;
}

// Returns single FilePath to mimic saved PDF format scan.
base::FilePath CreateSavedPdfScanPath(const base::FilePath& dir,
                                      const base::Time::Exploded& scan_time) {
  return dir.Append(base::StringPrintf("scan_%02d%02d%02d-%02d%02d%02d.pdf",
                                       scan_time.year, scan_time.month,
                                       scan_time.day_of_month, scan_time.hour,
                                       scan_time.minute, scan_time.second));
}

// Returns a vector of FilePaths to mimic saved scans.
std::vector<base::FilePath> CreateSavedScanPaths(
    const base::FilePath& dir,
    const base::Time::Exploded& scan_time,
    const mojo_ipc::FileType& file_type,
    int num_pages_to_scan) {
  const auto typeAndExtension = kFileTypes.find(file_type);
  EXPECT_NE(typeAndExtension, kFileTypes.cend());
  std::vector<base::FilePath> file_paths;
  if (file_type == mojo_ipc::FileType::kPdf) {
    file_paths.reserve(1);
    file_paths.push_back(CreateSavedPdfScanPath(dir, scan_time));
  } else {
    file_paths.reserve(num_pages_to_scan);
    for (int i = 1; i <= num_pages_to_scan; i++) {
      file_paths.push_back(dir.Append(base::StringPrintf(
          "scan_%02d%02d%02d-%02d%02d%02d_%d.%s", scan_time.year,
          scan_time.month, scan_time.day_of_month, scan_time.hour,
          scan_time.minute, scan_time.second, i,
          typeAndExtension->second.c_str())));
    }
  }
  return file_paths;
}

// Returns a manually generated PNG image. |alpha| is used to make unique PNGs.
std::string CreatePng(const int alpha = 255) {
  DCHECK(alpha >= 0 && alpha <= 255);

  SkBitmap bitmap;
  bitmap.allocN32Pixels(100, 100);
  bitmap.eraseARGB(alpha, 0, 255, 0);
  std::vector<unsigned char> bytes;
  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bytes);
  return std::string(bytes.begin(), bytes.end());
}

// Returns scan settings with the given path and file type.
mojo_ipc::ScanSettings CreateScanSettings(const base::FilePath& scan_to_path,
                                          const mojo_ipc::FileType& file_type,
                                          const std::string source = "") {
  mojo_ipc::ScanSettings settings;
  settings.scan_to_path = scan_to_path;
  settings.file_type = file_type;
  settings.source_name = source;
  return settings;
}

// Returns a profile manager set up to generate testing profiles.
std::unique_ptr<TestingProfileManager> CreateTestingProfileManager() {
  auto profile_manager = std::make_unique<TestingProfileManager>(
      TestingBrowserProcess::GetGlobal());
  EXPECT_TRUE(profile_manager->SetUp());
  return profile_manager;
}

}  // namespace

class FakeScanJobObserver : public mojo_ipc::ScanJobObserver {
 public:
  FakeScanJobObserver() = default;
  ~FakeScanJobObserver() override = default;

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

  // mojo_ipc::ScanJobObserver:
  void OnPageProgress(uint32_t page_number,
                      uint32_t progress_percent) override {
    progress_ = progress_percent;
  }

  void OnPageComplete(const std::vector<uint8_t>& page_data,
                      const uint32_t new_page_index) override {
    page_complete_ = true;
    new_page_index_ = new_page_index;
  }

  void OnScanComplete(
      ProtoScanFailureMode result,
      const std::vector<base::FilePath>& scanned_file_paths) override {
    scan_result_ = result;
    scanned_file_paths_ = scanned_file_paths;
  }

  void OnCancelComplete(bool success) override {
    cancel_scan_success_ = success;
  }

  void OnMultiPageScanFail(ProtoScanFailureMode result) override {
    multi_page_scan_result_ = result;
  }

  // Creates a pending remote that can be passed in calls to
  // ScanService::StartScan().
  mojo::PendingRemote<mojo_ipc::ScanJobObserver> GenerateRemote() {
    if (receiver_.is_bound())
      receiver_.reset();

    mojo::PendingRemote<mojo_ipc::ScanJobObserver> remote;
    receiver_.Bind(remote.InitWithNewPipeAndPassReceiver());
    return remote;
  }

  // Returns true if the scan completed successfully.
  bool scan_success() const {
    return progress_ == 100 && page_complete_ &&
           scan_result_ == ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE;
  }

  // Returns true if the cancel scan request completed successfully.
  bool cancel_scan_success() const { return cancel_scan_success_; }

  uint32_t new_page_index() const { return new_page_index_; }

  // Returns the result of the scan job.
  ProtoScanFailureMode scan_result() const { return scan_result_; }

  // Returns the result of the multi-page scan job.
  ProtoScanFailureMode multi_page_scan_result() const {
    return multi_page_scan_result_;
  }

  // Returns file paths of the saved scan files.
  std::vector<base::FilePath> scanned_file_paths() const {
    return scanned_file_paths_;
  }

 private:
  uint32_t progress_ = 0;
  bool page_complete_ = false;
  uint32_t new_page_index_ = UINT32_MAX;
  ProtoScanFailureMode scan_result_ =
      ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN;
  ProtoScanFailureMode multi_page_scan_result_ =
      ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN;
  bool cancel_scan_success_ = false;
  std::vector<base::FilePath> scanned_file_paths_;
  mojo::Receiver<mojo_ipc::ScanJobObserver> receiver_{this};
};

class ScanServiceTest : public testing::Test {
 public:
  ScanServiceTest()
      : profile_manager_(CreateTestingProfileManager()),
        profile_(profile_manager_->CreateTestingProfile(kUserEmail)),
        scanned_files_mount_(
            ScopedTestMountPoint::CreateAndMountDownloads(profile_)),
        session_controller_(std::make_unique<TestSessionController>()),
        user_manager_(new ash::FakeChromeUserManager),
        user_manager_owner_(base::WrapUnique(user_manager_)) {
    DCHECK(scanned_files_mount_->IsValid());
    const AccountId account_id(AccountId::FromUserEmail(kUserEmail));
    user_manager_->AddUser(account_id);
    user_manager_->LoginUser(account_id);
    SetupScanService(scanned_files_mount_->GetRootPath(),
                     base::FilePath("/google/drive"));
  }

  void SetupScanService(base::FilePath my_files_path,
                        base::FilePath google_drive_path) {
    scan_service_ = std::make_unique<ScanService>(
        &fake_lorgnette_scanner_manager_, my_files_path, google_drive_path,
        profile_);
    if (scan_service_remote_.is_bound()) {
      scan_service_remote_.reset();
    }
    scan_service_->BindInterface(
        scan_service_remote_.BindNewPipeAndPassReceiver());
  }

  // Gets scanners by calling ScanService::GetScanners() via the mojo::Remote.
  std::vector<mojo_ipc::ScannerPtr> GetScanners() {
    std::vector<mojo_ipc::ScannerPtr> scanners;
    mojo_ipc::ScanServiceAsyncWaiter(scan_service_remote_.get())
        .GetScanners(&scanners);
    return scanners;
  }

  // Gets scanner capabilities for the scanner identified by |scanner_id| by
  // calling ScanService::GetScannerCapabilities() via the mojo::Remote.
  mojo_ipc::ScannerCapabilitiesPtr GetScannerCapabilities(
      const base::UnguessableToken& scanner_id) {
    mojo_ipc::ScannerCapabilitiesPtr caps =
        mojo_ipc::ScannerCapabilities::New();
    mojo_ipc::ScanServiceAsyncWaiter(scan_service_remote_.get())
        .GetScannerCapabilities(scanner_id, &caps);
    return caps;
  }

  // Starts a scan with the scanner identified by |scanner_id| with the given
  // |settings| by calling ScanService::StartScan() via the mojo::Remote.
  bool StartScan(const base::UnguessableToken& scanner_id,
                 mojo_ipc::ScanSettingsPtr settings) {
    bool success;
    mojo_ipc::ScanServiceAsyncWaiter(scan_service_remote_.get())
        .StartScan(scanner_id, std::move(settings),
                   fake_scan_job_observer_.GenerateRemote(), &success);
    task_environment_.RunUntilIdle();
    return success;
  }

  // Starts a multi-page scan with the scanner identified by |scanner_id| with
  // the given |settings| by calling ScanService::StartMultiPageScan() via the
  // mojo::Remote. Binds the returned MultiPageScanController
  // mojo::PendingRemote.
  bool StartMultiPageScan(const base::UnguessableToken& scanner_id,
                          mojo_ipc::ScanSettingsPtr settings) {
    mojo::PendingRemote<mojo_ipc::MultiPageScanController> pending_remote;
    mojo_ipc::ScanServiceAsyncWaiter(scan_service_remote_.get())
        .StartMultiPageScan(scanner_id, std::move(settings),
                            fake_scan_job_observer_.GenerateRemote(),
                            &pending_remote);
    if (!pending_remote.is_valid())
      return false;

    multi_page_scan_controller_remote_.Bind(std::move(pending_remote));
    task_environment_.RunUntilIdle();
    return true;
  }

  void ResetMultiPageScanControllerRemote() {
    multi_page_scan_controller_remote_.reset();
  }

  bool ScanNextPage(const base::UnguessableToken& scanner_id,
                    mojo_ipc::ScanSettingsPtr settings) {
    bool success;
    mojo_ipc::MultiPageScanControllerAsyncWaiter(
        multi_page_scan_controller_remote_.get())
        .ScanNextPage(scanner_id, std::move(settings), &success);
    task_environment_.RunUntilIdle();
    return success;
  }

  // Performs a cancel scan request.
  void CancelScan() {
    scan_service_remote_->CancelScan();
    task_environment_.RunUntilIdle();
  }

  void CompleteMultiPageScan() {
    multi_page_scan_controller_remote_->CompleteMultiPageScan();
    task_environment_.RunUntilIdle();
  }

  void RemovePage(const uint32_t page_index) {
    multi_page_scan_controller_remote_->RemovePage(page_index);
    task_environment_.RunUntilIdle();
  }

  bool RescanPage(const base::UnguessableToken& scanner_id,
                  mojo_ipc::ScanSettingsPtr settings,
                  const uint32_t page_index) {
    bool success;
    mojo_ipc::MultiPageScanControllerAsyncWaiter(
        multi_page_scan_controller_remote_.get())
        .RescanPage(scanner_id, std::move(settings), page_index, &success);
    task_environment_.RunUntilIdle();
    return success;
  }

 protected:
  // A `BrowserTaskEnvironment` allows the test to create a `TestingProfile`.
  content::BrowserTaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  FakeLorgnetteScannerManager fake_lorgnette_scanner_manager_;
  FakeScanJobObserver fake_scan_job_observer_;
  std::unique_ptr<TestingProfileManager> profile_manager_;
  TestingProfile* const profile_;
  std::unique_ptr<ScopedTestMountPoint> scanned_files_mount_;
  std::unique_ptr<TestSessionController> session_controller_;
  ash::FakeChromeUserManager* const user_manager_;
  user_manager::ScopedUserManager user_manager_owner_;
  std::unique_ptr<ScanService> scan_service_;

 private:
  mojo::Remote<mojo_ipc::ScanService> scan_service_remote_;
  mojo::Remote<mojo_ipc::MultiPageScanController>
      multi_page_scan_controller_remote_;
};

// Test that no scanners are returned when there are no scanner names.
TEST_F(ScanServiceTest, NoScannerNames) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse({});
  auto scanners = GetScanners();
  EXPECT_TRUE(scanners.empty());
}

// Test that a scanner is returned with the correct display name.
TEST_F(ScanServiceTest, GetScanners) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);
  EXPECT_EQ(scanners[0]->display_name, kFirstTestScannerName16);
}

// Test that two returned scanners have unique IDs.
TEST_F(ScanServiceTest, UniqueScannerIds) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName, kSecondTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 2u);
  EXPECT_EQ(scanners[0]->display_name, kFirstTestScannerName16);
  EXPECT_EQ(scanners[1]->display_name, kSecondTestScannerName16);
  EXPECT_NE(scanners[0]->id, scanners[1]->id);
}

// Test that the number of detected scanners is recorded.
TEST_F(ScanServiceTest, RecordNumDetectedScanners) {
  base::HistogramTester histogram_tester;
  histogram_tester.ExpectTotalCount("Scanning.NumDetectedScanners", 0);
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName, kSecondTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 2u);
  histogram_tester.ExpectUniqueSample("Scanning.NumDetectedScanners", 2, 1);
}

// Test that attempting to get capabilities with a scanner ID that doesn't
// correspond to a scanner results in obtaining no capabilities.
TEST_F(ScanServiceTest, BadScannerId) {
  auto caps = GetScannerCapabilities(base::UnguessableToken::Create());
  EXPECT_TRUE(caps->sources.empty());
}

// Test that failing to obtain capabilities from the LorgnetteScannerManager
// results in obtaining no capabilities.
TEST_F(ScanServiceTest, NoCapabilities) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  fake_lorgnette_scanner_manager_.SetGetScannerCapabilitiesResponse(
      absl::nullopt);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);
  auto caps = GetScannerCapabilities(scanners[0]->id);
  EXPECT_TRUE(caps->sources.empty());
}

// Test that scanner capabilities can be obtained successfully.
TEST_F(ScanServiceTest, GetScannerCapabilities) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  fake_lorgnette_scanner_manager_.SetGetScannerCapabilitiesResponse(
      CreateLorgnetteScannerCapabilities());
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);
  auto caps = GetScannerCapabilities(scanners[0]->id);
  ASSERT_EQ(caps->sources.size(), 1u);
  EXPECT_EQ(caps->sources[0]->type, mojo_ipc::SourceType::kFlatbed);
  EXPECT_EQ(caps->sources[0]->name, kDocumentSourceName);
  ASSERT_EQ(caps->sources[0]->color_modes.size(), 1u);
  EXPECT_EQ(caps->sources[0]->color_modes[0], mojo_ipc::ColorMode::kColor);
  ASSERT_EQ(caps->sources[0]->resolutions.size(), 2u);
  EXPECT_EQ(caps->sources[0]->resolutions[0], kFirstResolution);
  EXPECT_EQ(caps->sources[0]->resolutions[1], kSecondResolution);
}

// Test that attempting to scan with a scanner ID that doesn't correspond to a
// scanner results in a failed scan.
TEST_F(ScanServiceTest, ScanWithBadScannerId) {
  EXPECT_FALSE(StartScan(base::UnguessableToken::Create(),
                         mojo_ipc::ScanSettings::New()));
}

// Test that attempting to scan with an unsupported file path fails.
// Specifically, use a file path with directory navigation (e.g. "..") to verify
// it can't be used to save scanned images to an unsupported path.
TEST_F(ScanServiceTest, ScanWithUnsupportedFilePath) {
  const base::FilePath my_files_path(kMyFilesPath);
  SetupScanService(my_files_path, base::FilePath("/google/drive"));

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {"TestData"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      my_files_path.Append("../../../var/log"), mojo_ipc::FileType::kPng);
  EXPECT_FALSE(StartScan(scanners[0]->id, settings.Clone()));
}

// Test that a scan can be performed successfully.
TEST_F(ScanServiceTest, Scan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreatePng(), CreatePng(),
                                              CreatePng()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  base::Time::Exploded scan_time;
  // Since we're using mock time, this is deterministic.
  base::Time::Now().LocalExplode(&scan_time);

  base::HistogramTester histogram_tester;
  int num_single_file_scans = 0u;
  int num_multi_file_scans = 0u;
  for (int type_num = static_cast<int>(mojo_ipc::FileType::kMinValue);
       type_num <= static_cast<int>(mojo_ipc::FileType::kMaxValue);
       ++type_num) {
    auto type = static_cast<mojo_ipc::FileType>(type_num);

    const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
        scanned_files_mount_->GetRootPath(), scan_time, type, scan_data.size());
    for (const auto& saved_scan_path : saved_scan_paths)
      EXPECT_FALSE(base::PathExists(saved_scan_path));

    mojo_ipc::ScanSettings settings =
        CreateScanSettings(scanned_files_mount_->GetRootPath(), type);
    EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
    for (const auto& saved_scan_path : saved_scan_paths)
      EXPECT_TRUE(base::PathExists(saved_scan_path));

    EXPECT_TRUE(fake_scan_job_observer_.scan_success());
    EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
              fake_scan_job_observer_.scan_result());
    EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());
    EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());

    // Verify that the histograms have been updated correctly.
    histogram_tester.ExpectBucketCount(
        "Scanning.NumFilesCreated", saved_scan_paths.size(),
        type == mojo_ipc::FileType::kPdf ? ++num_single_file_scans
                                         : ++num_multi_file_scans);
    histogram_tester.ExpectUniqueSample(
        "Scanning.NumPagesScanned", scan_data.size(),
        num_single_file_scans + num_multi_file_scans);
  }
}

// Test that an Epson ADF Duplex scan, which produces flipped pages, completes
// successfully.
TEST_F(ScanServiceTest, RotateEpsonADF) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse({kEpsonTestName});
  fake_lorgnette_scanner_manager_.SetGetScannerCapabilitiesResponse(
      CreateEpsonScannerCapabilities());
  const std::vector<std::string> scan_data = {CreatePng(), CreatePng(),
                                              CreatePng()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  base::Time::Exploded scan_time;
  // Since we're using mock time, this is deterministic.
  base::Time::Now().LocalExplode(&scan_time);

  mojo_ipc::ScanSettings settings =
      CreateScanSettings(scanned_files_mount_->GetRootPath(),
                         mojo_ipc::FileType::kPdf, "ADF Duplex");
  const base::FilePath saved_scan_path =
      CreateSavedPdfScanPath(scanned_files_mount_->GetRootPath(), scan_time);
  EXPECT_FALSE(base::PathExists(saved_scan_path));
  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_TRUE(base::PathExists(saved_scan_path));
  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  const std::vector<base::FilePath> scanned_file_paths =
      fake_scan_job_observer_.scanned_file_paths();
  EXPECT_EQ(1u, scanned_file_paths.size());
  EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());
  EXPECT_EQ(saved_scan_path, scanned_file_paths.front());
}

// Test that when a scan fails, the scan job is marked as failed.
TEST_F(ScanServiceTest, ScanFails) {
  // Skip setting the scan data in FakeLorgnetteScannerManager so the scan will
  // fail.
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
}

// Tests that a new scan job can succeed after the previous scan failed.
TEST_F(ScanServiceTest, ScanAfterFailedScan) {
  // Skip setting the scan data in FakeLorgnetteScannerManager so the scan will
  // fail.
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());

  // Set scan data so next scan is successful.
  const std::vector<std::string> scan_data = {"TestData1", "TestData2",
                                              "TestData3"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  base::Time::Exploded scan_time;
  // Since we're using mock time, this is deterministic.
  base::Time::Now().LocalExplode(&scan_time);

  const std::vector<base::FilePath> saved_scan_paths =
      CreateSavedScanPaths(scanned_files_mount_->GetRootPath(), scan_time,
                           mojo_ipc::FileType::kPng, scan_data.size());
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_TRUE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
            fake_scan_job_observer_.scan_result());
  EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());
  EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());
}

// Tests that a failed scan does not retain values from the previous successful
// scan.
TEST_F(ScanServiceTest, FailedScanAfterSuccessfulScan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {"TestData1", "TestData2",
                                              "TestData3"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  base::Time::Exploded scan_time;
  // Since we're using mock time, this is deterministic.
  base::Time::Now().LocalExplode(&scan_time);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);
  const std::vector<base::FilePath> saved_scan_paths =
      CreateSavedScanPaths(scanned_files_mount_->GetRootPath(), scan_time,
                           mojo_ipc::FileType::kPng, scan_data.size());
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_TRUE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
            fake_scan_job_observer_.scan_result());
  EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());
  EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());

  // Remove the scan data from FakeLorgnetteScannerManager so the scan will
  // fail.
  fake_lorgnette_scanner_manager_.SetScanResponse({});

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
}

// Test that canceling sends an update to the observer OnCancelComplete().
TEST_F(ScanServiceTest, CancelScanBeforeScanCompletes) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {"TestData"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);

  StartScan(scanners[0]->id, settings.Clone());
  CancelScan();
  EXPECT_TRUE(fake_scan_job_observer_.cancel_scan_success());
}

// Test that a multi-page image scan creates a holding space item.
TEST_F(ScanServiceTest, HoldingSpaceScan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreatePng(), CreatePng(),
                                              CreatePng()};
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  base::Time::Exploded scan_time;
  // Since we're using mock time, this is deterministic.
  base::Time::Now().LocalExplode(&scan_time);

  // Verify that the holding space starts out empty.
  HoldingSpaceKeyedService* holding_space_keyed_service =
      HoldingSpaceKeyedServiceFactory::GetInstance()->GetService(profile_);
  ASSERT_TRUE(holding_space_keyed_service);
  const HoldingSpaceModel* holding_space_model =
      holding_space_keyed_service->model_for_testing();
  ASSERT_TRUE(holding_space_model);
  size_t num_items_in_holding_space = 0u;
  ASSERT_EQ(num_items_in_holding_space, holding_space_model->items().size());

  for (int type_num = static_cast<int>(mojo_ipc::FileType::kMinValue);
       type_num <= static_cast<int>(mojo_ipc::FileType::kMaxValue);
       ++type_num) {
    auto type = static_cast<mojo_ipc::FileType>(type_num);

    fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
    const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
        scanned_files_mount_->GetRootPath(), scan_time, type, scan_data.size());
    for (const auto& saved_scan_path : saved_scan_paths)
      EXPECT_FALSE(base::PathExists(saved_scan_path));

    mojo_ipc::ScanSettings settings =
        CreateScanSettings(scanned_files_mount_->GetRootPath(), type);
    EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
    EXPECT_TRUE(fake_scan_job_observer_.scan_success());
    EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
              fake_scan_job_observer_.scan_result());
    EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());

    // Verify that the all pages of each scan are added to the holding space.
    EXPECT_EQ(num_items_in_holding_space + saved_scan_paths.size(),
              holding_space_model->items().size());
    for (const auto& saved_scan_path : saved_scan_paths) {
      EXPECT_TRUE(base::PathExists(saved_scan_path));
      HoldingSpaceItem* scanned_item =
          holding_space_model->items()[num_items_in_holding_space++].get();
      EXPECT_EQ(scanned_item->type(), HoldingSpaceItem::Type::kScan);
      EXPECT_EQ(scanned_item->file_path(), saved_scan_path);
    }

    // Remove the scan data from FakeLorgnetteScannerManager so the scan will
    // fail.
    fake_lorgnette_scanner_manager_.SetScanResponse({});

    EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
    EXPECT_FALSE(fake_scan_job_observer_.scan_success());
    EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
              fake_scan_job_observer_.scan_result());
    EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());

    // Verify that no item is added to the holding space when a scan fails.
    EXPECT_EQ(num_items_in_holding_space, holding_space_model->items().size());
  }
}

// Test that a multi-page scan can be performed successfully.
TEST_F(ScanServiceTest, MultiPageScan) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreatePng()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  base::Time::Exploded scan_time;
  // Since we're using mock time, this is deterministic.
  base::Time::Now().LocalExplode(&scan_time);
  const std::vector<base::FilePath> saved_scan_paths =
      CreateSavedScanPaths(scanned_files_mount_->GetRootPath(), scan_time,
                           mojo_ipc::FileType::kPdf, scan_data.size());
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  // Scan the first page without completing the scan.
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Scan the second page without completing the scan.
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Complete the multi-page scan expecting 2 pages to be scanned and a single
  // PDF to be created.
  CompleteMultiPageScan();
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_TRUE(base::PathExists(saved_scan_path));
  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 2, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      2, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.PageScanResult",
                                      scanning::ScanJobFailureReason::kSuccess,
                                      2);
}

// Test that when a multi-page scan fails, the scan job is marked as failed.
TEST_F(ScanServiceTest, MultiPageScanFails) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreatePng()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);

  // The first scan should pass with no failure.
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN,
            fake_scan_job_observer_.multi_page_scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(0u, fake_scan_job_observer_.new_page_index());

  // Set scan data to empty vector in FakeLorgnetteScannerManager so the next
  // scan will fail.
  fake_lorgnette_scanner_manager_.SetScanResponse({});
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.multi_page_scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());

  histogram_tester.ExpectBucketCount("Scanning.MultiPageScan.PageScanResult",
                                     scanning::ScanJobFailureReason::kSuccess,
                                     1);
  histogram_tester.ExpectBucketCount(
      "Scanning.MultiPageScan.PageScanResult",
      scanning::ScanJobFailureReason::kDeviceBusy, 1);
}

// Test that attempting to start a second multi-page scan while another
// multi-page scan session is going will fail.
TEST_F(ScanServiceTest, StartingAnotherMultiPageScan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreatePng()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);

  // The first scan should pass with no failure.
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN,
            fake_scan_job_observer_.multi_page_scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(0u, fake_scan_job_observer_.new_page_index());

  // The second attempt should fail.
  EXPECT_FALSE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
}

// Test that a page can be removed from a multi-page scan with two scanned
// images.
TEST_F(ScanServiceTest, MultiPageScanRemoveWithTwoPages) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreatePng(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string second_scanned_image = CreatePng(/*alpha=*/2);
  const std::vector<std::string> second_scan_data = {second_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(second_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Delete the first page.
  RemovePage(0);
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(1u, scanned_images.size());
  EXPECT_EQ(second_scanned_image, scanned_images[0]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 1 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 1, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      1, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRemovePage, 1);
}

// Test that a page can be removed from a multi-page scan with three scanned
// images.
TEST_F(ScanServiceTest, MultiPageScanRemoveWithThreePages) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreatePng(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string second_scanned_image = CreatePng(/*alpha=*/2);
  const std::vector<std::string> second_scan_data = {second_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(second_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string third_scanned_image = CreatePng(/*alpha=*/3);
  const std::vector<std::string> third_scan_data = {third_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(third_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Delete the second page.
  RemovePage(1);
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(2u, scanned_images.size());
  EXPECT_EQ(first_scanned_image, scanned_images[0]);
  EXPECT_EQ(third_scanned_image, scanned_images[1]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 2 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 2, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      2, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRemovePage, 1);
}

// Test that if there's only one page available, the page is removed and the
// multi-page scan session is reset and a new session can be started.
TEST_F(ScanServiceTest, MultiPageScanRemoveLastPage) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreatePng()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Removing the page should reset the multi-page scan session.
  RemovePage(0);
  --new_page_index;

  // Start a new scan and complete it with 1 page.
  ResetMultiPageScanControllerRemote();
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(1u, scanned_images.size());

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 1 page
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 1, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      1, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRemovePage, 1);
}

// Test that a page can be rescanned and replaced from a multi-page scan with
// one scanned image.
TEST_F(ScanServiceTest, MultiPageScanRescanWithOnePage) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreatePng(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Rescan the page.
  const std::string rescanned_scanned_image = CreatePng(/*alpha=*/2);
  const std::vector<std::string> rescanned_scan_data = {
      rescanned_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(rescanned_scan_data);
  EXPECT_TRUE(RescanPage(scanners[0]->id, settings.Clone(), /*page_index=*/0));
  EXPECT_EQ(0u, fake_scan_job_observer_.new_page_index());
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(1u, scanned_images.size());
  EXPECT_EQ(rescanned_scanned_image, scanned_images[0]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 1 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 1, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      1, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRescanPage, 1);
}

// Test that a page can be rescanned and replaced from a multi-page scan with
// three scanned images.
TEST_F(ScanServiceTest, MultiPageScanRescanWithThreePages) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreatePng(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string second_scanned_image = CreatePng(/*alpha=*/2);
  const std::vector<std::string> second_scan_data = {second_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(second_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string third_scanned_image = CreatePng(/*alpha=*/3);
  const std::vector<std::string> third_scan_data = {third_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(third_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Rescan the second page.
  const std::string rescanned_scanned_image = CreatePng(/*alpha=*/4);
  const std::vector<std::string> rescanned_scan_data = {
      rescanned_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(rescanned_scan_data);
  EXPECT_TRUE(RescanPage(scanners[0]->id, settings.Clone(), /*page_index=*/1));
  EXPECT_EQ(1u, fake_scan_job_observer_.new_page_index());
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(3u, scanned_images.size());
  EXPECT_EQ(first_scanned_image, scanned_images[0]);
  EXPECT_EQ(rescanned_scanned_image, scanned_images[1]);
  EXPECT_EQ(third_scanned_image, scanned_images[2]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 3 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 3, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      3, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRescanPage, 1);
}

TEST_F(ScanServiceTest, ResetReceiverOnBindInterface) {
  // This test simulates a user refreshing the WebUI page. The receiver should
  // be reset before binding the new receiver. Otherwise we would get a DCHECK
  // error from mojo::Receiver
  mojo::Remote<scanning::mojom::ScanService> remote;
  scan_service_->BindInterface(remote.BindNewPipeAndPassReceiver());
  base::RunLoop().RunUntilIdle();

  remote.reset();

  scan_service_->BindInterface(remote.BindNewPipeAndPassReceiver());
  base::RunLoop().RunUntilIdle();
}
}  // namespace ash
