910e62b5创建于 1月15日历史提交
// 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 "components/commerce/core/commerce_utils.h"

#include <string>
#include <vector>

#include "base/check.h"
#include "base/feature_list.h"
#include "base/json/json_writer.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/escape.h"
#include "base/time/time.h"
#include "base/uuid.h"
#include "base/values.h"
#include "components/commerce/core/commerce_constants.h"
#include "components/commerce/core/commerce_feature_list.h"
#include "components/commerce/core/proto/price_tracking.pb.h"
#include "components/endpoint_fetcher/endpoint_fetcher.h"
#include "net/base/url_util.h"
#include "url/gurl.h"

namespace commerce {

GURL GetProductSpecsTabUrl(const std::vector<GURL>& urls) {
  auto urls_list = base::Value::List();

  for (auto& url : urls) {
    urls_list.Append(url.spec());
  }

  std::string json;
  if (!base::JSONWriter::Write(urls_list, &json)) {
    return GURL(commerce::kChromeUICompareUrl);
  }

  return net::AppendQueryParameter(GURL(commerce::kChromeUICompareUrl), "urls",
                                   json);
}

GURL GetProductSpecsTabUrlForID(const base::Uuid& uuid) {
  return net::AppendQueryParameter(GURL(commerce::kChromeUICompareUrl), "id",
                                   uuid.AsLowercaseString());
}

std::unique_ptr<ProductInfo> OptGuideResultToProductInfo(
    const optimization_guide::OptimizationMetadata& metadata,
    bool can_load_product_specs_full_page_ui) {
  if (!metadata.any_metadata().has_value()) {
    return nullptr;
  }

  std::optional<commerce::PriceTrackingData> parsed_any =
      optimization_guide::ParsedAnyMetadata<commerce::PriceTrackingData>(
          metadata.any_metadata().value());
  commerce::PriceTrackingData price_data = parsed_any.value();

  if (!parsed_any.has_value() || !price_data.IsInitialized()) {
    return nullptr;
  }

  const commerce::BuyableProduct buyable_product = price_data.buyable_product();

  std::unique_ptr<ProductInfo> info = std::make_unique<ProductInfo>();

  if (buyable_product.has_title()) {
    info->title = buyable_product.title();
  }

  if (buyable_product.has_gpc_title()) {
    info->product_cluster_title = buyable_product.gpc_title();
  }

  if (buyable_product.has_image_url()) {
    info->server_image_available = true;
    info->image_url = GURL(buyable_product.image_url());
  } else {
    info->server_image_available = false;
  }

  if (buyable_product.has_offer_id()) {
    info->offer_id = buyable_product.offer_id();
  }

  if (buyable_product.has_product_cluster_id()) {
    info->product_cluster_id = buyable_product.product_cluster_id();
  }

  if (buyable_product.has_current_price()) {
    info->currency_code = buyable_product.current_price().currency_code();
    info->amount_micros = buyable_product.current_price().amount_micros();
  }

  if (buyable_product.has_country_code()) {
    info->country_code = buyable_product.country_code();
  }

  // Check to see if there was a price drop associated with this product. Those
  // prices take priority over what BuyableProduct has.
  if (price_data.has_product_update()) {
    const commerce::ProductPriceUpdate price_update =
        price_data.product_update();

    // Both new and old price should exist and have the same currency code.
    bool currency_codes_match = price_update.new_price().currency_code() ==
                                price_update.old_price().currency_code();

    if (price_update.has_new_price() &&
        info->currency_code == price_update.new_price().currency_code() &&
        currency_codes_match) {
      info->amount_micros = price_update.new_price().amount_micros();
    }
    if (price_update.has_old_price() &&
        info->currency_code == price_update.old_price().currency_code() &&
        currency_codes_match) {
      info->previous_amount_micros.emplace(
          price_update.old_price().amount_micros());
    }
  }

  if (buyable_product.has_category_data()) {
    info->category_data = buyable_product.category_data();
  }

  // TODO(376128060): Remove the feature check after M132.
  if (can_load_product_specs_full_page_ui) {
    for (int i = 0; i < buyable_product.price_summary_size(); ++i) {
      info->price_summary.push_back(buyable_product.price_summary(i));
    }

    if (buyable_product.has_price_display_recommendation()) {
      info->price_display_recommendation =
          buyable_product.price_display_recommendation();
    }
  }

  return info;
}

void MaybeUseAlternateShoppingServer(
    endpoint_fetcher::EndpointFetcher::RequestParams::Builder& params_builder) {
  if (base::FeatureList::IsEnabled(commerce::kShoppingAlternateServer)) {
    params_builder.SetHeaders(
        std::vector<endpoint_fetcher::EndpointFetcher::RequestParams::Header>{
            {kAlternateServerHeaderName, kAlternateServerHeaderTrueValue}});
  }
}

}  // namespace commerce