blob: 291bf93718beb6bd01a77dd0eec172af918f17ad [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/core/can_make_payment_query.h"
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "components/payments/core/features.h"
#include "url/gurl.h"
namespace payments {
CanMakePaymentQuery::CanMakePaymentQuery() {}
CanMakePaymentQuery::~CanMakePaymentQuery() {}
bool CanMakePaymentQuery::CanQuery(
const GURL& top_level_origin,
const GURL& frame_origin,
const std::map<std::string, std::set<std::string>>& query,
bool per_method_quota) {
// Check both with and without per-method quota, so that both queries are
// recorded in case if two different tabs of the same website run with and
// without the origin trial.
bool can_query_with_per_method_quota =
CanQueryWithPerMethodQuota(top_level_origin, frame_origin, query);
bool can_query_without_per_method_quota =
CanQueryWithoutPerMethodQuota(top_level_origin, frame_origin, query);
if (per_method_quota ||
base::FeatureList::IsEnabled(
features::kWebPaymentsPerMethodCanMakePaymentQuota)) {
return can_query_with_per_method_quota;
}
return can_query_without_per_method_quota;
}
bool CanMakePaymentQuery::CanQueryWithPerMethodQuota(
const GURL& top_level_origin,
const GURL& frame_origin,
const std::map<std::string, std::set<std::string>>& query) {
bool can_query = true;
for (const auto& method_and_params : query) {
std::string method = method_and_params.first;
std::set<std::string> params = method_and_params.second;
const std::string id =
frame_origin.spec() + ":" + top_level_origin.spec() + ":" + method;
auto it = per_method_queries_.find(id);
if (it == per_method_queries_.end()) {
auto timer = std::make_unique<base::OneShotTimer>();
timer->Start(FROM_HERE, base::TimeDelta::FromMinutes(30),
base::BindOnce(
&CanMakePaymentQuery::ExpireQuotaForFrameOriginAndMethod,
base::Unretained(this), id));
timers_.insert(std::make_pair(id, std::move(timer)));
per_method_queries_.insert(std::make_pair(id, params));
continue;
}
can_query &= it->second == params;
}
return can_query;
}
bool CanMakePaymentQuery::CanQueryWithoutPerMethodQuota(
const GURL& top_level_origin,
const GURL& frame_origin,
const std::map<std::string, std::set<std::string>>& query) {
const std::string id = frame_origin.spec() + ":" + top_level_origin.spec();
const auto& it = queries_.find(id);
if (it == queries_.end()) {
auto timer = std::make_unique<base::OneShotTimer>();
timer->Start(FROM_HERE, base::TimeDelta::FromMinutes(30),
base::BindOnce(&CanMakePaymentQuery::ExpireQuotaForFrameOrigin,
base::Unretained(this), id));
timers_.insert(std::make_pair(id, std::move(timer)));
queries_.insert(std::make_pair(id, query));
return true;
}
return it->second == query;
}
void CanMakePaymentQuery::ExpireQuotaForFrameOrigin(const std::string& id) {
timers_.erase(id);
queries_.erase(id);
}
void CanMakePaymentQuery::ExpireQuotaForFrameOriginAndMethod(
const std::string& id) {
timers_.erase(id);
per_method_queries_.erase(id);
}
} // namespace payments