chromium/chrome/browser/extensions/api/printing/printing_api.cc

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

#include "chrome/browser/extensions/api/printing/printing_api.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/printing/printing_api_handler.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/quota_service.h"

namespace extensions {

PrintingSubmitJobFunction::~PrintingSubmitJobFunction() = default;

void PrintingSubmitJobFunction::GetQuotaLimitHeuristics(
    QuotaLimitHeuristics* heuristics) const {
  QuotaLimitHeuristic::Config config = {
      api::printing::MAX_SUBMIT_JOB_CALLS_PER_MINUTE, base::Minutes(1)};
  heuristics->push_back(std::make_unique<QuotaService::TimedLimit>(
      config, std::make_unique<QuotaLimitHeuristic::SingletonBucketMapper>(),
      "MAX_SUBMIT_JOB_CALLS_PER_MINUTE"));
}

ExtensionFunction::ResponseAction PrintingSubmitJobFunction::Run() {
  std::optional<api::printing::SubmitJob::Params> params =
      api::printing::SubmitJob::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);
  PrintingAPIHandler::Get(browser_context())
      ->SubmitJob(ChromeExtensionFunctionDetails(this).GetNativeWindowForUI(),
                  extension_, std::move(params),
                  base::BindOnce(
                      &PrintingSubmitJobFunction::OnPrintJobSubmitted, this));

  return RespondLater();
}

void PrintingSubmitJobFunction::OnPrintJobSubmitted(
    std::optional<api::printing::SubmitJobStatus> status,
    std::optional<std::string> job_id,
    std::optional<std::string> error) {
  if (error.has_value()) {
    Respond(Error(error.value()));
    return;
  }
  api::printing::SubmitJobResponse response;
  DCHECK(status.has_value());
  response.status = status.value();
  response.job_id = std::move(job_id);
  Respond(WithArguments(response.ToValue()));
}

PrintingCancelJobFunction::~PrintingCancelJobFunction() = default;

ExtensionFunction::ResponseAction PrintingCancelJobFunction::Run() {
  std::optional<api::printing::CancelJob::Params> params =
      api::printing::CancelJob::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);
  std::optional<std::string> error =
      PrintingAPIHandler::Get(browser_context())
          ->CancelJob(extension_id(), params->job_id);

  if (error.has_value())
    return RespondNow(Error(error.value()));
  return RespondNow(NoArguments());
}

PrintingGetPrintersFunction::PrintingGetPrintersFunction() = default;
PrintingGetPrintersFunction::~PrintingGetPrintersFunction() = default;

ExtensionFunction::ResponseAction PrintingGetPrintersFunction::Run() {
  PrintingAPIHandler::Get(browser_context())
      ->GetPrinters(
          base::BindOnce(&PrintingGetPrintersFunction::OnPrintersReady, this));
  return RespondLater();
}

void PrintingGetPrintersFunction::OnPrintersReady(
    std::vector<api::printing::Printer> printers) {
  Respond(ArgumentList(api::printing::GetPrinters::Results::Create(printers)));
}

PrintingGetPrinterInfoFunction::~PrintingGetPrinterInfoFunction() = default;

void PrintingGetPrinterInfoFunction::GetQuotaLimitHeuristics(
    QuotaLimitHeuristics* heuristics) const {
  QuotaLimitHeuristic::Config config = {
      api::printing::MAX_GET_PRINTER_INFO_CALLS_PER_MINUTE, base::Minutes(1)};
  heuristics->push_back(std::make_unique<QuotaService::TimedLimit>(
      config, std::make_unique<QuotaLimitHeuristic::SingletonBucketMapper>(),
      "MAX_GET_PRINTER_INFO_CALLS_PER_MINUTE"));
}

ExtensionFunction::ResponseAction PrintingGetPrinterInfoFunction::Run() {
  std::optional<api::printing::GetPrinterInfo::Params> params =
      api::printing::GetPrinterInfo::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);
  PrintingAPIHandler::Get(browser_context())
      ->GetPrinterInfo(
          params->printer_id,
          base::BindOnce(
              &PrintingGetPrinterInfoFunction::OnPrinterInfoRetrieved, this));

  return RespondLater();
}

void PrintingGetPrinterInfoFunction::OnPrinterInfoRetrieved(
    std::optional<base::Value> capabilities,
    std::optional<api::printing::PrinterStatus> status,
    std::optional<std::string> error) {
  if (error.has_value()) {
    Respond(Error(error.value()));
    return;
  }
  api::printing::GetPrinterInfoResponse response;
  if (capabilities.has_value()) {
    response.capabilities.emplace();
    base::Value capabilities_value = std::move(capabilities.value());
    CHECK(capabilities_value.is_dict());
    // It's safe just to swap values here as |capabilities_value| stores exactly
    // the same object as |response.capabilities| expects.
    std::swap(response.capabilities->additional_properties,
              capabilities_value.GetDict());
  }
  DCHECK(status.has_value());
  response.status = status.value();
  Respond(WithArguments(response.ToValue()));
}

}  // namespace extensions