// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/payments/payment_app_info_fetcher.h"

#include <limits>
#include <string_view>
#include <utility>

#include "base/base64.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/task/sequenced_task_runner.h"
#include "components/payments/content/icon/icon_size.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/manifest_icon_downloader.h"
#include "content/public/browser/page.h"
#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
#include "third_party/blink/public/common/manifest/manifest_util.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
#include "ui/gfx/codec/png_codec.h"
#include "url/origin.h"

namespace content {

PaymentAppInfoFetcher::PaymentAppInfo::PaymentAppInfo() {}

PaymentAppInfoFetcher::PaymentAppInfo::~PaymentAppInfo() {}

void PaymentAppInfoFetcher::Start(
    const GURL& context_url,
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
    PaymentAppInfoFetchCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  std::unique_ptr<std::vector<GlobalRenderFrameHostId>> frame_routing_ids =
      service_worker_context->GetWindowClientFrameRoutingIds(
          blink::StorageKey::CreateFirstParty(
              url::Origin::Create(context_url)));

  SelfDeleteFetcher* fetcher = new SelfDeleteFetcher(std::move(callback));
  fetcher->Start(context_url, std::move(frame_routing_ids));
}

PaymentAppInfoFetcher::SelfDeleteFetcher::SelfDeleteFetcher(
    PaymentAppInfoFetchCallback callback)
    : fetched_payment_app_info_(std::make_unique<PaymentAppInfo>()),
      callback_(std::move(callback)) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

PaymentAppInfoFetcher::SelfDeleteFetcher::~SelfDeleteFetcher() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

void PaymentAppInfoFetcher::SelfDeleteFetcher::Start(
    const GURL& context_url,
    const std::unique_ptr<std::vector<GlobalRenderFrameHostId>>&
        frame_routing_ids) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (frame_routing_ids->empty()) {
    // Cannot print this error to the developer console, because the appropriate
    // developer console has not been found.
    LOG(ERROR)
        << "Unable to find the top level web content for retrieving the web "
           "app manifest of a payment handler for \""
        << context_url << "\".";
    RunCallbackAndDestroy();
    return;
  }

  for (const auto& frame : *frame_routing_ids) {
    // Find out the RenderFrameHost registering the payment app. Although a
    // service worker can manage instruments, the first instrument must be set
    // on a page that has a link to a web app manifest, so it can be fetched
    // here.
    RenderFrameHostImpl* render_frame_host =
        RenderFrameHostImpl::FromID(frame.child_id, frame.frame_routing_id);
    if (!render_frame_host ||
        context_url.spec().compare(
            render_frame_host->GetLastCommittedURL().spec()) != 0) {
      continue;
    }

    // Get the WebContents associated with the frame and print console messages
    // to the main frame of the WebContents since web app manifest is only
    // available in the main frame's document by definition. The main frame's
    // document must come from the same origin.
    WebContentsImpl* web_content = static_cast<WebContentsImpl*>(
        WebContents::FromRenderFrameHost(render_frame_host));
    if (!web_content) {
      render_frame_host->AddMessageToConsole(
          blink::mojom::ConsoleMessageLevel::kError,
          "Unable to find the web page for \"" + context_url.spec() +
              "\" to fetch payment handler manifest (for name and icon).");
      continue;
    }

    if (web_content->IsHidden()) {
      web_content->GetPrimaryMainFrame()->AddMessageToConsole(
          blink::mojom::ConsoleMessageLevel::kError,
          "Unable to fetch payment handler manifest (for name and icon) for "
          "\"" +
              context_url.spec() + "\" from a hidden top level web page \"" +
              web_content->GetLastCommittedURL().spec() + "\".");
      continue;
    }

    if (!url::IsSameOriginWith(context_url,
                               web_content->GetLastCommittedURL())) {
      web_content->GetPrimaryMainFrame()->AddMessageToConsole(
          blink::mojom::ConsoleMessageLevel::kError,
          "Unable to fetch payment handler manifest (for name and icon) for "
          "\"" +
              context_url.spec() +
              "\" from a cross-origin top level web page \"" +
              web_content->GetLastCommittedURL().spec() + "\".");
      continue;
    }

    web_contents_ = web_content->GetWeakPtr();
    web_contents_->GetPrimaryPage().GetManifest(
        base::BindOnce(&PaymentAppInfoFetcher::SelfDeleteFetcher::
                           FetchPaymentAppManifestCallback,
                       weak_ptr_factory_.GetWeakPtr()));
    return;
  }

  // Cannot print this error to the developer console, because the appropriate
  // developer console has not been found.
  LOG(ERROR)
      << "Unable to find the top level web content for retrieving the web "
         "app manifest of a payment handler for \""
      << context_url << "\".";

  RunCallbackAndDestroy();
}

void PaymentAppInfoFetcher::SelfDeleteFetcher::RunCallbackAndDestroy() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback_),
                                std::move(fetched_payment_app_info_)));
  delete this;
}

void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
    blink::mojom::ManifestRequestResult result,
    const GURL& url,
    blink::mojom::ManifestPtr manifest) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  manifest_url_ = url;
  if (manifest_url_.is_empty()) {
    WarnIfPossible(
        "The page that installed the payment handler does not contain a web "
        "app manifest link: <link rel=\"manifest\" "
        "href=\"some-file-name-here\">. This manifest defines the payment "
        "handler's name and icon. User may not recognize this payment handler "
        "in UI, because it will be labeled only by its origin.");
    RunCallbackAndDestroy();
    return;
  }

  if (blink::IsEmptyManifest(manifest) ||
      result != blink::mojom::ManifestRequestResult::kSuccess) {
    WarnIfPossible(
        "Unable to download a valid payment handler web app manifest from \"" +
        manifest_url_.spec() +
        "\". This manifest cannot be empty and must in JSON format. The "
        "manifest defines the payment handler's name and icon. User may not "
        "recognize this payment handler in UI, because it will be labeled only "
        "by its origin.");
    RunCallbackAndDestroy();
    return;
  }

  fetched_payment_app_info_->prefer_related_applications =
      manifest->prefer_related_applications;
  for (const auto& related_application : manifest->related_applications) {
    fetched_payment_app_info_->related_applications.emplace_back(
        StoredRelatedApplication());
    if (related_application.platform) {
      base::UTF16ToUTF8(
          related_application.platform->c_str(),
          related_application.platform->length(),
          &(fetched_payment_app_info_->related_applications.back().platform));
    }
    if (related_application.id) {
      base::UTF16ToUTF8(
          related_application.id->c_str(), related_application.id->length(),
          &(fetched_payment_app_info_->related_applications.back().id));
    }
  }

  if (!manifest->name) {
    WarnIfPossible("The payment handler's web app manifest \"" +
                   manifest_url_.spec() +
                   "\" does not contain a \"name\" field. User may not "
                   "recognize this payment handler in UI, because it will be "
                   "labeled only by its origin.");
  } else if (manifest->name->empty()) {
    WarnIfPossible(
        "The \"name\" field in the payment handler's web app manifest \"" +
        manifest_url_.spec() +
        "\" is empty. User may not recognize this payment handler in UI, "
        "because it will be labeled only by its origin.");
  } else {
    base::UTF16ToUTF8(manifest->name->c_str(), manifest->name->length(),
                      &(fetched_payment_app_info_->name));
  }

  if (manifest->icons.empty()) {
    WarnIfPossible(
        "Unable to download the payment handler's icon, because the web app "
        "manifest \"" +
        manifest_url_.spec() +
        "\" does not contain an \"icons\" field with a valid URL in \"src\" "
        "sub-field. User may not recognize this payment handler in UI.");
    RunCallbackAndDestroy();
    return;
  }

  if (!web_contents_) {
    LOG(WARNING) << "Unable to download the payment handler's icon because no "
                    "renderer was found, possibly because the page was closed "
                    "or navigated away during installation. User may not "
                    "recognize this payment handler in UI, because it will be "
                    "labeled only by its name and origin.";
    RunCallbackAndDestroy();
    return;
  }
  gfx::NativeView native_view = web_contents_->GetNativeView();

  icon_url_ = blink::ManifestIconSelector::FindBestMatchingIcon(
      manifest->icons,
      payments::IconSizeCalculator::IdealIconHeight(native_view),
      payments::IconSizeCalculator::MinimumIconHeight(),
      ManifestIconDownloader::kMaxWidthToHeightRatio,
      blink::mojom::ManifestImageResource_Purpose::ANY);
  if (!icon_url_.is_valid()) {
    WarnIfPossible(
        "No suitable payment handler icon found in the \"icons\" field defined "
        "in the web app manifest \"" +
        manifest_url_.spec() +
        "\". This is most likely due to unsupported MIME types in the "
        "\"icons\" field. User may not recognize this payment handler in UI.");
    RunCallbackAndDestroy();
    return;
  }

  bool can_download = ManifestIconDownloader::Download(
      web_contents_.get(), icon_url_,
      payments::IconSizeCalculator::IdealIconHeight(native_view),
      payments::IconSizeCalculator::MinimumIconHeight(),
      /* maximum_icon_size_in_px= */ std::numeric_limits<int>::max(),
      base::BindOnce(&PaymentAppInfoFetcher::SelfDeleteFetcher::OnIconFetched,
                     weak_ptr_factory_.GetWeakPtr()),
      false /* square_only */);
  // |can_download| is false only if web contents are  null or the icon URL is
  // not valid. Both of these conditions are manually checked above, so
  // |can_download| should never be false. The manual checks above are necessary
  // to provide more detailed error messages.
  DCHECK(can_download);
}

void PaymentAppInfoFetcher::SelfDeleteFetcher::OnIconFetched(
    const SkBitmap& icon) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (icon.drawsNothing()) {
    WarnIfPossible("Unable to download a valid payment handler icon from \"" +
                   icon_url_.spec() +
                   "\", which is defined in the web app manifest \"" +
                   manifest_url_.spec() +
                   "\". User may not recognize this payment handler in UI.");
    RunCallbackAndDestroy();
    return;
  }

  std::optional<std::vector<uint8_t>> bitmap_data =
      gfx::PNGCodec::EncodeBGRASkBitmap(icon, /*discard_transparency=*/false);
  fetched_payment_app_info_->icon = base::Base64Encode(bitmap_data.value());
  RunCallbackAndDestroy();
}

void PaymentAppInfoFetcher::SelfDeleteFetcher::WarnIfPossible(
    const std::string& message) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (web_contents_) {
    web_contents_->GetPrimaryMainFrame()->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kWarning, message);
  } else {
    LOG(WARNING) << message;
  }
}

}  // namespace content
