blob: 3e918fe24495d838c845a3b278a37ea69da1537f [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/payments/content/payment_manifest_parser_host.h"
#include <algorithm>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/utility_process_mojo_client.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/url_constants.h"
namespace payments {
namespace {
const size_t kMaximumNumberOfItems = 100U;
} // namespace
PaymentManifestParserHost::PaymentManifestParserHost() : callback_counter_(0) {}
PaymentManifestParserHost::~PaymentManifestParserHost() {}
void PaymentManifestParserHost::StartUtilityProcess() {
mojo_client_ = base::MakeUnique<
content::UtilityProcessMojoClient<mojom::PaymentManifestParser>>(
l10n_util::GetStringUTF16(
IDS_UTILITY_PROCESS_PAYMENT_MANIFEST_PARSER_NAME));
mojo_client_->set_error_callback(
base::Bind(&PaymentManifestParserHost::OnUtilityProcessStopped,
base::Unretained(this)));
mojo_client_->Start();
}
void PaymentManifestParserHost::ParsePaymentMethodManifest(
const std::string& content,
PaymentMethodCallback callback) {
if (!mojo_client_) {
std::move(callback).Run(std::vector<GURL>(), std::vector<url::Origin>(),
false);
return;
}
int64_t callback_identifier = callback_counter_++;
const auto& result = pending_payment_method_callbacks_.insert(
std::make_pair(callback_identifier, std::move(callback)));
DCHECK(result.second);
DCHECK_GE(10U, pending_payment_method_callbacks_.size());
mojo_client_->service()->ParsePaymentMethodManifest(
content, base::Bind(&PaymentManifestParserHost::OnPaymentMethodParse,
base::Unretained(this), callback_identifier));
}
void PaymentManifestParserHost::ParseWebAppManifest(const std::string& content,
WebAppCallback callback) {
if (!mojo_client_) {
std::move(callback).Run(std::vector<mojom::WebAppManifestSectionPtr>());
return;
}
int64_t callback_identifier = callback_counter_++;
const auto& result = pending_web_app_callbacks_.insert(
std::make_pair(callback_identifier, std::move(callback)));
DCHECK(result.second);
DCHECK_GE(10U, pending_web_app_callbacks_.size());
mojo_client_->service()->ParseWebAppManifest(
content, base::Bind(&PaymentManifestParserHost::OnWebAppParse,
base::Unretained(this), callback_identifier));
}
void PaymentManifestParserHost::OnPaymentMethodParse(
int64_t callback_identifier,
const std::vector<GURL>& web_app_manifest_urls,
const std::vector<url::Origin>& supported_origins,
bool all_origins_supported) {
const auto& pending_callback_it =
pending_payment_method_callbacks_.find(callback_identifier);
if (pending_callback_it == pending_payment_method_callbacks_.end()) {
// If unable to find the pending callback, then something went wrong in the
// utility process. Stop the utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
const size_t kMaximumNumberOfSupportedOrigins = 100000;
if (web_app_manifest_urls.size() > kMaximumNumberOfItems ||
supported_origins.size() > kMaximumNumberOfSupportedOrigins) {
// If more than 100 web app manifests URLs or more than 100,000 supported
// origins, then something went wrong in the utility process. Stop the
// utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
for (const auto& url : web_app_manifest_urls) {
if (!url.is_valid() || !url.SchemeIs(url::kHttpsScheme)) {
// If not a valid URL with HTTPS scheme, then something went wrong in the
// utility process. Stop the utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
}
if (all_origins_supported && !supported_origins.empty()) {
// The format of the payment method manifest does not allow for both of
// these conditions to be true. Something went wrong in the utility process.
// Stop the utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
for (const auto& origin : supported_origins) {
if (!origin.GetURL().is_valid() || origin.scheme() != url::kHttpsScheme) {
// If not a valid origin with HTTPS scheme, then something went wrong in
// the utility process. Stop the utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
}
PaymentMethodCallback callback = std::move(pending_callback_it->second);
pending_payment_method_callbacks_.erase(pending_callback_it);
// Can trigger synchronous deletion of this object, so can't access any of
// the member variables after this block.
std::move(callback).Run(web_app_manifest_urls, supported_origins,
all_origins_supported);
}
void PaymentManifestParserHost::OnWebAppParse(
int64_t callback_identifier,
std::vector<mojom::WebAppManifestSectionPtr> manifest) {
const auto& pending_callback_it =
pending_web_app_callbacks_.find(callback_identifier);
if (pending_callback_it == pending_web_app_callbacks_.end()) {
// If unable to find the pending callback, then something went wrong in the
// utility process. Stop the utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
if (manifest.size() > kMaximumNumberOfItems) {
// If more than 100 items, then something went wrong in the utility
// process. Stop the utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
for (size_t i = 0; i < manifest.size(); ++i) {
if (manifest[i]->fingerprints.size() > kMaximumNumberOfItems) {
// If more than 100 items, then something went wrong in the utility
// process. Stop the utility process and notify all callbacks.
OnUtilityProcessStopped();
return;
}
}
WebAppCallback callback = std::move(pending_callback_it->second);
pending_web_app_callbacks_.erase(pending_callback_it);
// Can trigger synchronous deletion of this object, so can't access any of
// the member variables after this block.
std::move(callback).Run(std::move(manifest));
}
void PaymentManifestParserHost::OnUtilityProcessStopped() {
mojo_client_.reset();
std::map<int64_t, PaymentMethodCallback> payment_method_callbacks =
std::move(pending_payment_method_callbacks_);
std::map<int64_t, WebAppCallback> web_app_callbacks =
std::move(pending_web_app_callbacks_);
for (auto& callback : payment_method_callbacks) {
// Can trigger synchronous deletion of this object, so can't access any of
// the member variables after this line.
std::move(callback.second)
.Run(std::vector<GURL>(), std::vector<url::Origin>(), false);
}
for (auto& callback : web_app_callbacks) {
// Can trigger synchronous deletion of this object, so can't access any of
// the member variables after this line.
std::move(callback.second)
.Run(std::vector<mojom::WebAppManifestSectionPtr>());
}
}
} // namespace payments