chromium/chrome/browser/ash/wallpaper_handlers/sea_pen_utils.cc

// Copyright 2023 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/wallpaper_handlers/sea_pen_utils.h"

#include <string>

#include "ash/constants/ash_features.h"
#include "ash/wallpaper/wallpaper_utils/sea_pen_metadata_utils.h"
#include "ash/wallpaper/wallpaper_utils/sea_pen_utils_generated.h"
#include "ash/webui/common/mojom/sea_pen.mojom.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "components/manta/proto/manta.pb.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/size.h"

namespace wallpaper_handlers {

gfx::Size GetLargestDisplaySizeLandscape() {
  // Screen should be non-null if the user is selecting SeaPen thumbnails.
  CHECK(display::Screen::HasScreen());

  gfx::Size largest_size;
  uint64_t largest_area = 0u;
  for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
    DVLOG(2) << display.ToString();
    auto next_area = display.GetSizeInPixel().Area64();
    if (next_area > largest_area) {
      largest_size = display.GetSizeInPixel();
      largest_area = next_area;
    }
  }
  DCHECK_GT(largest_area, 0u);

  if (largest_size.height() > largest_size.width()) {
    // Always landscape orientation.
    largest_size.Transpose();
  }

  DVLOG(2) << "largest_size=" << largest_size.ToString();
  return largest_size;
}

bool IsValidOutput(const manta::proto::OutputData& output,
                   const std::string_view source) {
  if (!output.has_generation_seed()) {
    LOG(WARNING) << "Manta output data missing id for " << source;
    return false;
  }
  if (!output.has_image() || !output.image().has_serialized_bytes() ||
      output.image().serialized_bytes().empty()) {
    LOG(WARNING) << "Manta output data missing image for" << source;
    return false;
  }
  return true;
}

manta::proto::Request CreateMantaRequest(
    const ash::personalization_app::mojom::SeaPenQueryPtr& query,
    std::optional<uint32_t> generation_seed,
    int num_outputs,
    const gfx::Size& size,
    manta::proto::FeatureName feature_name) {
  DVLOG(2) << __func__ << " generation_seed=" << generation_seed.value_or(0)
           << " num_outputs=" << num_outputs
           << " image_dimensions=" << size.ToString();

  manta::proto::Request request;
  request.set_feature_name(feature_name);

  {
    manta::proto::RequestConfig& request_config =
        *request.mutable_request_config();
    if (generation_seed) {
      request_config.set_generation_seed(*generation_seed);
    }

    // Ignore image_dimensions for CHROMEOS_VC_BACKGROUNDS, since
    // CHROMEOS_VC_BACKGROUNDS returns with default size.
    if (feature_name != manta::proto::FeatureName::CHROMEOS_VC_BACKGROUNDS) {
      manta::proto::ImageDimensions& image_dimensions =
          *request_config.mutable_image_dimensions();
      image_dimensions.set_width(size.width());
      image_dimensions.set_height(size.height());
    }

    request_config.set_num_outputs(num_outputs);
  }

  manta::proto::InputData& input_data = *request.add_input_data();
  if (query->is_text_query()) {
    input_data.set_text(query->get_text_query());
  } else if (query->is_template_query() &&
             ash::IsValidTemplateQuery(query->get_template_query())) {
    input_data.set_tag(kTemplateIdTag.data());
    input_data.set_text(
        ash::TemplateIdToString(query->get_template_query()->id));
    for (auto option : query->get_template_query()->options) {
      manta::proto::InputData& input_option = *request.add_input_data();
      input_option.set_tag(ash::TemplateChipToString(option.first));
      input_option.set_text(ash::TemplateOptionToString(option.second));
    }
  }
  if (ash::features::IsSeaPenUseExptTemplateEnabled()) {
    manta::proto::InputData& expt_template_option = *request.add_input_data();
    expt_template_option.set_tag("use_expt_template");
    expt_template_option.set_text("true");
  }
  return request;
}

std::string GetFeedbackText(
    const ash::personalization_app::mojom::SeaPenQueryPtr& query,
    const ash::personalization_app::mojom::SeaPenFeedbackMetadataPtr&
        metadata) {
  if (query->is_template_query() &&
      !ash::IsValidTemplateQuery(query->get_template_query())) {
    return "";
  }

  std::string feedback_text;
  const char* hashtag = metadata->log_id.starts_with("VcBackground")
                            ? "#VCBackground"
                            : "#AIWallpaper";
  const char* sentiment = metadata->is_positive ? "Positive" : "Negative";
  const char* query_text =
      query->is_text_query()
          ? query->get_text_query().c_str()
          : query->get_template_query()->user_visible_query->text.c_str();
  base::StringAppendF(&feedback_text, "%s %s: %s\n", hashtag, sentiment,
                      query_text);
  if (query->is_template_query()) {
    base::StringAppendF(&feedback_text, "template: %s\n",
                        metadata->log_id.c_str());
    base::StringAppendF(&feedback_text, "options: ");
    for (const auto& [chip, option] : query->get_template_query()->options) {
      base::StringAppendF(&feedback_text, "(%s, %s)",
                          ash::TemplateChipToString(chip).c_str(),
                          ash::TemplateOptionToString(option).c_str());
    }
    base::StringAppendF(&feedback_text, "\n");
  }
  base::StringAppendF(&feedback_text, "generation_seed: %u\n",
                      metadata->generation_seed);
  return feedback_text;
}

}  // namespace wallpaper_handlers