Commit 29289e6c authored by Rouslan Solomakhin's avatar Rouslan Solomakhin Committed by Commit Bot

[Web Payment] Android activity to app splitter.

This patch adds a utility function (and corresponding unit test) for
separating a single Android payment app into multiple Android payment
apps that have exactly one payment activity per app. This enables
treating each PAY intent filter as its own payment app, including when
one app declares multiple PAY intent filter targets.

Bug: 1061503
Change-Id: Ieecd43607b282295667108f70f94b276997fe25c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2300276
Commit-Queue: Rouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: default avatarLiquan (Max) Gu <maxlg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798468}
parent 14b3ae3a
......@@ -6,6 +6,8 @@ static_library("core") {
sources = [
"android_app_description.cc",
"android_app_description.h",
"android_app_description_tools.cc",
"android_app_description_tools.h",
"autofill_card_validation.cc",
"autofill_card_validation.h",
"basic_card_response.cc",
......@@ -151,6 +153,7 @@ static_library("test_support") {
source_set("unit_tests") {
testonly = true
sources = [
"android_app_description_tools_unittest.cc",
"can_make_payment_query_unittest.cc",
"currency_formatter_unittest.cc",
"journey_logger_unittest.cc",
......
// Copyright 2020 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/android_app_description_tools.h"
#include <utility>
#include "base/check.h"
#include "components/payments/core/android_app_description.h"
namespace payments {
void SplitPotentiallyMultipleActivities(
std::unique_ptr<AndroidAppDescription> app,
std::vector<std::unique_ptr<AndroidAppDescription>>* destination) {
DCHECK(destination);
if (app->activities.empty())
return;
destination->emplace_back(std::move(app));
for (size_t i = 1; i < destination->front()->activities.size(); ++i) {
auto single_activity_app = std::make_unique<AndroidAppDescription>();
single_activity_app->package = destination->front()->package;
single_activity_app->service_names = destination->front()->service_names;
single_activity_app->activities.emplace_back(
std::move(destination->front()->activities[i]));
destination->emplace_back(std::move(single_activity_app));
}
destination->front()->activities.resize(1);
}
} // namespace payments
// Copyright 2020 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.
#ifndef COMPONENTS_PAYMENTS_CORE_ANDROID_APP_DESCRIPTION_TOOLS_H_
#define COMPONENTS_PAYMENTS_CORE_ANDROID_APP_DESCRIPTION_TOOLS_H_
#include <memory>
#include <vector>
namespace payments {
struct AndroidAppDescription;
// Moves each activity in the given |app| into its own AndroidAppDescription in
// |destination|, so the code can treat each PAY intent target as its own
// payment app.
//
// The function does not clear |destination|, so the results of multiple calls
// can be appended to the same |destination|, e.g., in a loop.
//
// The |destination| should not be null.
void SplitPotentiallyMultipleActivities(
std::unique_ptr<AndroidAppDescription> app,
std::vector<std::unique_ptr<AndroidAppDescription>>* destination);
} // namespace payments
#endif // COMPONENTS_PAYMENTS_CORE_ANDROID_APP_DESCRIPTION_TOOLS_H_
// Copyright 2020 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/android_app_description_tools.h"
#include <memory>
#include <utility>
#include <vector>
#include "components/payments/core/android_app_description.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace payments {
namespace {
// Absence of activities should result in zero apps.
TEST(AndroidAppDescriptionToolsTest, SplitNoActivities) {
std::vector<std::unique_ptr<AndroidAppDescription>> destination;
SplitPotentiallyMultipleActivities(std::make_unique<AndroidAppDescription>(),
&destination);
EXPECT_TRUE(destination.empty());
}
// One activity should result in one app.
TEST(AndroidAppDescriptionToolsTest, SplitOneActivity) {
std::vector<std::unique_ptr<AndroidAppDescription>> destination;
auto app = std::make_unique<AndroidAppDescription>();
app->package = "com.example.app";
app->service_names = {"com.example.app.Service"};
app->activities.emplace_back(std::make_unique<AndroidActivityDescription>());
app->activities.back()->name = "com.example.app.Activity";
app->activities.back()->default_payment_method = "https://example.test";
SplitPotentiallyMultipleActivities(std::move(app), &destination);
ASSERT_EQ(1U, destination.size());
EXPECT_EQ("com.example.app", destination.back()->package);
EXPECT_EQ(std::vector<std::string>{"com.example.app.Service"},
destination.back()->service_names);
ASSERT_EQ(1U, destination.back()->activities.size());
EXPECT_EQ("com.example.app.Activity",
destination.back()->activities.back()->name);
EXPECT_EQ("https://example.test",
destination.back()->activities.back()->default_payment_method);
}
// Two activities should result in two apps.
TEST(AndroidAppDescriptionToolsTest, SplitTwoActivities) {
std::vector<std::unique_ptr<AndroidAppDescription>> destination;
auto app = std::make_unique<AndroidAppDescription>();
app->package = "com.example.app";
app->service_names = {"com.example.app.Service"};
app->activities.emplace_back(std::make_unique<AndroidActivityDescription>());
app->activities.back()->name = "com.example.app.ActivityOne";
app->activities.back()->default_payment_method = "https://one.test";
app->activities.emplace_back(std::make_unique<AndroidActivityDescription>());
app->activities.back()->name = "com.example.app.ActivityTwo";
app->activities.back()->default_payment_method = "https://two.test";
SplitPotentiallyMultipleActivities(std::move(app), &destination);
ASSERT_EQ(2U, destination.size());
EXPECT_EQ("com.example.app", destination.front()->package);
EXPECT_EQ(std::vector<std::string>{"com.example.app.Service"},
destination.front()->service_names);
ASSERT_EQ(1U, destination.front()->activities.size());
EXPECT_EQ("com.example.app.ActivityOne",
destination.front()->activities.back()->name);
EXPECT_EQ("https://one.test",
destination.front()->activities.back()->default_payment_method);
EXPECT_EQ("com.example.app", destination.back()->package);
EXPECT_EQ(std::vector<std::string>{"com.example.app.Service"},
destination.back()->service_names);
ASSERT_EQ(1U, destination.back()->activities.size());
EXPECT_EQ("com.example.app.ActivityTwo",
destination.back()->activities.back()->name);
EXPECT_EQ("https://two.test",
destination.back()->activities.back()->default_payment_method);
}
} // namespace
} // namespace payments
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment