chromium/chrome/browser/extensions/api/document_scan/document_scan_api.cc

// Copyright 2014 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/extensions/api/document_scan/document_scan_api.h"

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

#include "base/functional/bind.h"
#include "chrome/browser/extensions/api/document_scan/document_scan_api_handler.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/crosapi/crosapi_ash.h"
#include "chrome/browser/ash/crosapi/crosapi_manager.h"
#include "chrome/browser/ash/crosapi/document_scan_ash.h"
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/lacros/lacros_service.h"
#endif

namespace extensions {

namespace {

// Error messages that can be included in a response when scanning fails.
constexpr char kUserGestureRequiredError[] =
    "User gesture required to perform scan";
constexpr char kScanImageError[] = "Failed to scan image";

}  // namespace

DocumentScanScanFunction::DocumentScanScanFunction() = default;
DocumentScanScanFunction::~DocumentScanScanFunction() = default;

ExtensionFunction::ResponseAction DocumentScanScanFunction::Run() {
  auto params = api::document_scan::Scan::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  if (!user_gesture()) {
    return RespondNow(Error(kUserGestureRequiredError));
  }

  std::vector<std::string> mime_types;
  if (params->options.mime_types) {
    mime_types = std::move(*params->options.mime_types);
  }

  DocumentScanAPIHandler::Get(browser_context())
      ->SimpleScan(
          mime_types,
          base::BindOnce(&DocumentScanScanFunction::OnScanCompleted, this));

  return RespondLater();
}

void DocumentScanScanFunction::OnScanCompleted(
    std::optional<api::document_scan::ScanResults> scan_results,
    std::optional<std::string> error) {
  if (error) {
    Respond(Error(*error));
    return;
  }

  if (!scan_results) {
    Respond(Error(kScanImageError));
    return;
  }

  Respond(WithArguments(scan_results->ToValue()));
}

DocumentScanGetScannerListFunction::DocumentScanGetScannerListFunction() =
    default;
DocumentScanGetScannerListFunction::~DocumentScanGetScannerListFunction() =
    default;

ExtensionFunction::ResponseAction DocumentScanGetScannerListFunction::Run() {
  auto params = api::document_scan::GetScannerList::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->GetScannerList(
          ChromeExtensionFunctionDetails(this).GetNativeWindowForUI(),
          extension_, user_gesture(), std::move(params->filter),
          base::BindOnce(
              &DocumentScanGetScannerListFunction::OnScannerListReceived,
              this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanGetScannerListFunction::OnScannerListReceived(
    api::document_scan::GetScannerListResponse response) {
  Respond(ArgumentList(
      api::document_scan::GetScannerList::Results::Create(response)));
}

DocumentScanOpenScannerFunction::DocumentScanOpenScannerFunction() = default;
DocumentScanOpenScannerFunction::~DocumentScanOpenScannerFunction() = default;

ExtensionFunction::ResponseAction DocumentScanOpenScannerFunction::Run() {
  auto params = api::document_scan::OpenScanner::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->OpenScanner(
          extension_, std::move(params->scanner_id),
          base::BindOnce(&DocumentScanOpenScannerFunction::OnResponseReceived,
                         this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanOpenScannerFunction::OnResponseReceived(
    api::document_scan::OpenScannerResponse response) {
  Respond(
      ArgumentList(api::document_scan::OpenScanner::Results::Create(response)));
}

DocumentScanGetOptionGroupsFunction::DocumentScanGetOptionGroupsFunction() =
    default;
DocumentScanGetOptionGroupsFunction::~DocumentScanGetOptionGroupsFunction() =
    default;

ExtensionFunction::ResponseAction DocumentScanGetOptionGroupsFunction::Run() {
  auto params = api::document_scan::GetOptionGroups::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->GetOptionGroups(
          extension_, std::move(params->scanner_handle),
          base::BindOnce(
              &DocumentScanGetOptionGroupsFunction::OnResponseReceived, this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanGetOptionGroupsFunction::OnResponseReceived(
    api::document_scan::GetOptionGroupsResponse response) {
  Respond(ArgumentList(
      api::document_scan::GetOptionGroups::Results::Create(response)));
}

DocumentScanCloseScannerFunction::DocumentScanCloseScannerFunction() = default;
DocumentScanCloseScannerFunction::~DocumentScanCloseScannerFunction() = default;

ExtensionFunction::ResponseAction DocumentScanCloseScannerFunction::Run() {
  auto params = api::document_scan::CloseScanner::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->CloseScanner(
          extension_, std::move(params->scanner_handle),
          base::BindOnce(&DocumentScanCloseScannerFunction::OnResponseReceived,
                         this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanCloseScannerFunction::OnResponseReceived(
    api::document_scan::CloseScannerResponse response) {
  Respond(ArgumentList(
      api::document_scan::CloseScanner::Results::Create(response)));
}

DocumentScanSetOptionsFunction::DocumentScanSetOptionsFunction() = default;
DocumentScanSetOptionsFunction::~DocumentScanSetOptionsFunction() = default;

ExtensionFunction::ResponseAction DocumentScanSetOptionsFunction::Run() {
  auto params = api::document_scan::SetOptions::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->SetOptions(
          extension_, std::move(params->scanner_handle),
          std::move(params->options),
          base::BindOnce(&DocumentScanSetOptionsFunction::OnResponseReceived,
                         this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanSetOptionsFunction::OnResponseReceived(
    api::document_scan::SetOptionsResponse response) {
  Respond(
      ArgumentList(api::document_scan::SetOptions::Results::Create(response)));
}

DocumentScanStartScanFunction::DocumentScanStartScanFunction() = default;
DocumentScanStartScanFunction::~DocumentScanStartScanFunction() = default;

ExtensionFunction::ResponseAction DocumentScanStartScanFunction::Run() {
  auto params = api::document_scan::StartScan::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->StartScan(
          ChromeExtensionFunctionDetails(this).GetNativeWindowForUI(),
          extension_, user_gesture(), std::move(params->scanner_handle),
          std::move(params->options),
          base::BindOnce(&DocumentScanStartScanFunction::OnResponseReceived,
                         this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanStartScanFunction::OnResponseReceived(
    api::document_scan::StartScanResponse response) {
  Respond(
      ArgumentList(api::document_scan::StartScan::Results::Create(response)));
}

DocumentScanCancelScanFunction::DocumentScanCancelScanFunction() = default;
DocumentScanCancelScanFunction::~DocumentScanCancelScanFunction() = default;

ExtensionFunction::ResponseAction DocumentScanCancelScanFunction::Run() {
  auto params = api::document_scan::CancelScan::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->CancelScan(
          extension_, std::move(params->job),
          base::BindOnce(&DocumentScanCancelScanFunction::OnResponseReceived,
                         this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanCancelScanFunction::OnResponseReceived(
    api::document_scan::CancelScanResponse response) {
  Respond(
      ArgumentList(api::document_scan::CancelScan::Results::Create(response)));
}

DocumentScanReadScanDataFunction::DocumentScanReadScanDataFunction() = default;
DocumentScanReadScanDataFunction::~DocumentScanReadScanDataFunction() = default;

ExtensionFunction::ResponseAction DocumentScanReadScanDataFunction::Run() {
  auto params = api::document_scan::ReadScanData::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  DocumentScanAPIHandler::Get(browser_context())
      ->ReadScanData(
          extension_, std::move(params->job),
          base::BindOnce(&DocumentScanReadScanDataFunction::OnResponseReceived,
                         this));

  return did_respond() ? AlreadyResponded() : RespondLater();
}

void DocumentScanReadScanDataFunction::OnResponseReceived(
    api::document_scan::ReadScanDataResponse response) {
  Respond(ArgumentList(
      api::document_scan::ReadScanData::Results::Create(response)));
}

}  // namespace extensions