blob: 0426e8eb2039af37d565191f313a8cf8437e734d [file] [log] [blame]
// Copyright 2019 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/service_worker_payment_app_factory.h"
#include <map>
#include <utility>
#include "base/bind.h"
#include "base/check_op.h"
#include "base/memory/weak_ptr.h"
#include "components/payments/content/payment_manifest_web_data_service.h"
#include "components/payments/content/service_worker_payment_app.h"
#include "components/payments/content/service_worker_payment_app_finder.h"
#include "content/public/browser/web_contents.h"
namespace payments {
namespace {
std::vector<mojom::PaymentMethodDataPtr> Clone(
const std::vector<mojom::PaymentMethodDataPtr>& original) {
std::vector<mojom::PaymentMethodDataPtr> clone(original.size());
std::transform(
original.begin(), original.end(), clone.begin(),
[](const mojom::PaymentMethodDataPtr& item) { return item.Clone(); });
return clone;
}
} // namespace
class ServiceWorkerPaymentAppCreator {
public:
ServiceWorkerPaymentAppCreator(
ServiceWorkerPaymentAppFactory* owner,
base::WeakPtr<PaymentAppFactory::Delegate> delegate)
: owner_(owner), delegate_(delegate) {}
~ServiceWorkerPaymentAppCreator() {}
void CreatePaymentApps(
content::InstalledPaymentAppsFinder::PaymentApps apps,
ServiceWorkerPaymentAppFinder::InstallablePaymentApps installable_apps,
const std::string& error_message) {
if (!delegate_) {
FinishAndCleanup();
return;
}
if (!error_message.empty())
delegate_->OnPaymentAppCreationError(error_message);
number_of_pending_sw_payment_apps_ = apps.size() + installable_apps.size();
if (number_of_pending_sw_payment_apps_ == 0U) {
FinishAndCleanup();
return;
}
base::RepeatingClosure show_processing_spinner = base::BindRepeating(
&PaymentAppFactory::Delegate::ShowProcessingSpinner, delegate_);
for (auto& installed_app : apps) {
auto app = std::make_unique<ServiceWorkerPaymentApp>(
delegate_->GetWebContents(), delegate_->GetTopOrigin(),
delegate_->GetFrameOrigin(), delegate_->GetSpec(),
std::move(installed_app.second), delegate_->IsOffTheRecord(),
show_processing_spinner);
app->ValidateCanMakePayment(base::BindOnce(
&ServiceWorkerPaymentAppCreator::OnSWPaymentAppValidated,
weak_ptr_factory_.GetWeakPtr()));
PaymentApp* raw_payment_app_pointer = app.get();
available_apps_[raw_payment_app_pointer] = std::move(app);
}
for (auto& installable_app : installable_apps) {
auto app = std::make_unique<ServiceWorkerPaymentApp>(
delegate_->GetWebContents(), delegate_->GetTopOrigin(),
delegate_->GetFrameOrigin(), delegate_->GetSpec(),
std::move(installable_app.second), installable_app.first.spec(),
delegate_->IsOffTheRecord(), show_processing_spinner);
app->ValidateCanMakePayment(base::BindOnce(
&ServiceWorkerPaymentAppCreator::OnSWPaymentAppValidated,
weak_ptr_factory_.GetWeakPtr()));
PaymentApp* raw_payment_app_pointer = app.get();
available_apps_[raw_payment_app_pointer] = std::move(app);
}
}
base::WeakPtr<ServiceWorkerPaymentAppCreator> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private:
void OnSWPaymentAppValidated(ServiceWorkerPaymentApp* app, bool result) {
if (!delegate_) {
FinishAndCleanup();
return;
}
auto iterator = available_apps_.find(app);
if (iterator != available_apps_.end()) {
if (result)
delegate_->OnPaymentAppCreated(std::move(iterator->second));
available_apps_.erase(iterator);
}
if (--number_of_pending_sw_payment_apps_ == 0)
FinishAndCleanup();
}
void FinishAndCleanup() {
if (delegate_)
delegate_->OnDoneCreatingPaymentApps();
owner_->DeleteCreator(this);
}
ServiceWorkerPaymentAppFactory* owner_;
base::WeakPtr<PaymentAppFactory::Delegate> delegate_;
std::map<PaymentApp*, std::unique_ptr<PaymentApp>> available_apps_;
int number_of_pending_sw_payment_apps_ = 0;
base::WeakPtrFactory<ServiceWorkerPaymentAppCreator> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPaymentAppCreator);
};
ServiceWorkerPaymentAppFactory::ServiceWorkerPaymentAppFactory()
: PaymentAppFactory(PaymentApp::Type::SERVICE_WORKER_APP) {}
ServiceWorkerPaymentAppFactory::~ServiceWorkerPaymentAppFactory() {}
void ServiceWorkerPaymentAppFactory::Create(base::WeakPtr<Delegate> delegate) {
DCHECK(delegate->GetWebContents());
auto creator = std::make_unique<ServiceWorkerPaymentAppCreator>(
/*owner=*/this, delegate);
ServiceWorkerPaymentAppCreator* creator_raw_pointer = creator.get();
creators_[creator_raw_pointer] = std::move(creator);
ServiceWorkerPaymentAppFinder::GetOrCreateForCurrentDocument(
delegate->GetInitiatorRenderFrameHost())
->GetAllPaymentApps(
delegate->GetFrameSecurityOrigin(),
delegate->GetPaymentManifestWebDataService(),
Clone(delegate->GetMethodData()),
delegate->MayCrawlForInstallablePaymentApps(),
base::BindOnce(&ServiceWorkerPaymentAppCreator::CreatePaymentApps,
creator_raw_pointer->GetWeakPtr()),
base::BindOnce([]() {
// Nothing needs to be done after writing cache. This callback is
// used only in tests.
}));
}
void ServiceWorkerPaymentAppFactory::DeleteCreator(
ServiceWorkerPaymentAppCreator* creator_raw_pointer) {
size_t number_of_deleted_creators = creators_.erase(creator_raw_pointer);
DCHECK_EQ(1U, number_of_deleted_creators);
}
} // namespace payments