blob: 8f1109ad13415c1f073f7dcf901119334465e9e3 [file] [log] [blame]
Rouslan Solomakhin03358342020-08-13 19:33:441// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Rouslan Solomakhin15c22fa2020-08-13 22:14:485#include "components/payments/content/android_app_communication.h"
6
7#include <memory>
8#include <string>
9#include <utility>
10#include <vector>
11
12#include "base/bind.h"
13#include "base/callback.h"
Rouslan Solomakhin03358342020-08-13 19:33:4414#include "components/payments/content/android_app_communication_test_support.h"
Rouslan Solomakhin15c22fa2020-08-13 22:14:4815#include "components/payments/core/android_app_description.h"
Lloyd Piquec49b3462020-11-20 02:14:2316#include "content/public/browser/web_contents.h"
17#include "content/public/test/test_web_contents_factory.h"
Rouslan Solomakhin03358342020-08-13 19:33:4418#include "testing/gtest/include/gtest/gtest.h"
Anton Bikineev1156b5f2021-05-15 22:35:3619#include "third_party/abseil-cpp/absl/types/optional.h"
Rouslan Solomakhin1043cf82020-08-14 01:17:4320#include "url/gurl.h"
Rouslan Solomakhin03358342020-08-13 19:33:4421
22namespace payments {
23namespace {
24
Rouslan Solomakhin15c22fa2020-08-13 22:14:4825std::vector<std::unique_ptr<AndroidAppDescription>> createApp(
26 const std::vector<std::string>& activity_names,
27 const std::string& default_payment_method,
28 const std::vector<std::string>& service_names) {
29 auto app = std::make_unique<AndroidAppDescription>();
30
31 for (const auto& activity_name : activity_names) {
32 auto activity = std::make_unique<AndroidActivityDescription>();
33 activity->name = activity_name;
34 activity->default_payment_method = default_payment_method;
35 app->activities.emplace_back(std::move(activity));
36 }
37
38 app->package = "com.example.app";
39 app->service_names = service_names;
40
41 std::vector<std::unique_ptr<AndroidAppDescription>> apps;
42 apps.emplace_back(std::move(app));
43
44 return apps;
45}
46
47class AndroidAppCommunicationTest : public testing::Test {
48 public:
49 AndroidAppCommunicationTest()
Lloyd Piquec49b3462020-11-20 02:14:2350 : support_(AndroidAppCommunicationTestSupport::Create()),
51 web_contents_(
52 web_contents_factory_.CreateWebContents(support_->context())) {}
Rouslan Solomakhin15c22fa2020-08-13 22:14:4853 ~AndroidAppCommunicationTest() override = default;
54
55 AndroidAppCommunicationTest(const AndroidAppCommunicationTest& other) =
56 delete;
57 AndroidAppCommunicationTest& operator=(
58 const AndroidAppCommunicationTest& other) = delete;
59
60 void OnGetAppDescriptionsResponse(
Anton Bikineev1156b5f2021-05-15 22:35:3661 const absl::optional<std::string>& error,
Rouslan Solomakhin15c22fa2020-08-13 22:14:4862 std::vector<std::unique_ptr<AndroidAppDescription>> apps) {
63 error_ = error;
64 apps_ = std::move(apps);
65 }
66
Anton Bikineev1156b5f2021-05-15 22:35:3667 void OnIsReadyToPayResponse(const absl::optional<std::string>& error,
Rouslan Solomakhin1043cf82020-08-14 01:17:4368 bool is_ready_to_pay) {
69 error_ = error;
70 is_ready_to_pay_ = is_ready_to_pay;
71 }
72
Anton Bikineev1156b5f2021-05-15 22:35:3673 void OnPaymentAppResponse(const absl::optional<std::string>& error,
Rouslan Solomakhin888a0b92020-08-14 16:34:3174 bool is_activity_result_ok,
75 const std::string& payment_method_identifier,
76 const std::string& stringified_details) {
77 error_ = error;
78 is_activity_result_ok_ = is_activity_result_ok;
79 payment_method_identifier_ = payment_method_identifier;
80 stringified_details_ = stringified_details;
81 }
82
Rouslan Solomakhin15c22fa2020-08-13 22:14:4883 std::unique_ptr<AndroidAppCommunicationTestSupport> support_;
Lloyd Piquec49b3462020-11-20 02:14:2384 content::TestWebContentsFactory web_contents_factory_;
85 content::WebContents* web_contents_;
Anton Bikineev1156b5f2021-05-15 22:35:3686 absl::optional<std::string> error_;
Rouslan Solomakhin15c22fa2020-08-13 22:14:4887 std::vector<std::unique_ptr<AndroidAppDescription>> apps_;
Rouslan Solomakhin1043cf82020-08-14 01:17:4388 bool is_ready_to_pay_ = false;
Rouslan Solomakhin888a0b92020-08-14 16:34:3189 bool is_activity_result_ok_ = false;
90 std::string payment_method_identifier_;
91 std::string stringified_details_;
Rouslan Solomakhin15c22fa2020-08-13 22:14:4892};
93
94TEST_F(AndroidAppCommunicationTest, OneInstancePerBrowserContext) {
95 auto communication_one =
96 AndroidAppCommunication::GetForBrowserContext(support_->context());
97 auto communication_two =
98 AndroidAppCommunication::GetForBrowserContext(support_->context());
99 EXPECT_EQ(communication_one.get(), communication_two.get());
100}
101
102TEST_F(AndroidAppCommunicationTest, NoArcForGetAppDescriptions) {
103 // Intentionally do not set an instance.
104
105 support_->ExpectNoListOfPaymentAppsQuery();
106
107 auto communication =
108 AndroidAppCommunication::GetForBrowserContext(support_->context());
109 communication->SetForTesting();
110 communication->GetAppDescriptions(
111 "com.example.app",
112 base::BindOnce(&AndroidAppCommunicationTest::OnGetAppDescriptionsResponse,
113 base::Unretained(this)));
114
115 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
116 ASSERT_TRUE(error_.has_value());
117 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
118 } else {
119 EXPECT_FALSE(error_.has_value());
120 }
121
122 EXPECT_TRUE(apps_.empty());
123}
124
125TEST_F(AndroidAppCommunicationTest, NoAppDescriptions) {
126 auto scoped_initialization = support_->CreateScopedInitialization();
127
128 support_->ExpectQueryListOfPaymentAppsAndRespond({});
129
130 auto communication =
131 AndroidAppCommunication::GetForBrowserContext(support_->context());
132 communication->SetForTesting();
133 communication->GetAppDescriptions(
134 "com.example.app",
135 base::BindOnce(&AndroidAppCommunicationTest::OnGetAppDescriptionsResponse,
136 base::Unretained(this)));
137
138 EXPECT_FALSE(error_.has_value());
139 EXPECT_TRUE(apps_.empty());
140}
141
142TEST_F(AndroidAppCommunicationTest, TwoActivitiesInPackage) {
143 auto scoped_initialization = support_->CreateScopedInitialization();
144
145 support_->ExpectQueryListOfPaymentAppsAndRespond(
146 createApp({"com.example.app.ActivityOne", "com.example.app.ActivityTwo"},
147 "https://play.google.com/billing", {}));
148
149 auto communication =
150 AndroidAppCommunication::GetForBrowserContext(support_->context());
151 communication->SetForTesting();
152 communication->GetAppDescriptions(
153 "com.example.app",
154 base::BindOnce(&AndroidAppCommunicationTest::OnGetAppDescriptionsResponse,
155 base::Unretained(this)));
156
157 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
158 ASSERT_TRUE(error_.has_value());
159 EXPECT_EQ(
160 "Found more than one PAY activity in the Trusted Web Activity, but at "
161 "most one activity is supported.",
162 error_.value());
163 } else {
164 EXPECT_FALSE(error_.has_value());
165 }
166 EXPECT_TRUE(apps_.empty());
167}
168
169TEST_F(AndroidAppCommunicationTest, TwoServicesInPackage) {
170 auto scoped_initialization = support_->CreateScopedInitialization();
171
172 support_->ExpectQueryListOfPaymentAppsAndRespond(
173 createApp({"com.example.app.Activity"}, "https://play.google.com/billing",
174 {"com.example.app.ServiceOne", "com.example.app.ServiceTwo"}));
175
176 auto communication =
177 AndroidAppCommunication::GetForBrowserContext(support_->context());
178 communication->SetForTesting();
179 communication->GetAppDescriptions(
180 "com.example.app",
181 base::BindOnce(&AndroidAppCommunicationTest::OnGetAppDescriptionsResponse,
182 base::Unretained(this)));
183
Rouslan Solomakhin1f85bba2020-08-17 11:18:16184 EXPECT_FALSE(error_.has_value());
Rouslan Solomakhin15c22fa2020-08-13 22:14:48185 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
Rouslan Solomakhin1f85bba2020-08-17 11:18:16186 ASSERT_EQ(1u, apps_.size());
187 ASSERT_NE(nullptr, apps_.front().get());
188 EXPECT_EQ("com.example.app", apps_.front()->package);
Rouslan Solomakhin15c22fa2020-08-13 22:14:48189
Rouslan Solomakhin1f85bba2020-08-17 11:18:16190 // The logic for checking for multiple services is cross-platform in
191 // android_payment_app_factory.cc, so the platform-specific implementations
192 // of android_app_communication.h do not check for this error condition.
193 std::vector<std::string> expected_service_names = {
194 "com.example.app.ServiceOne", "com.example.app.ServiceTwo"};
195 EXPECT_EQ(expected_service_names, apps_.front()->service_names);
196
197 ASSERT_EQ(1u, apps_.front()->activities.size());
198 ASSERT_NE(nullptr, apps_.front()->activities.front().get());
199 EXPECT_EQ("com.example.app.Activity",
200 apps_.front()->activities.front()->name);
201 EXPECT_EQ("https://play.google.com/billing",
202 apps_.front()->activities.front()->default_payment_method);
203 } else {
204 EXPECT_TRUE(apps_.empty());
205 }
Rouslan Solomakhin15c22fa2020-08-13 22:14:48206}
207
208TEST_F(AndroidAppCommunicationTest, ActivityAndService) {
209 auto scoped_initialization = support_->CreateScopedInitialization();
210
211 support_->ExpectQueryListOfPaymentAppsAndRespond(
212 createApp({"com.example.app.Activity"}, "https://play.google.com/billing",
213 {"com.example.app.Service"}));
214
215 auto communication =
216 AndroidAppCommunication::GetForBrowserContext(support_->context());
217 communication->SetForTesting();
218 communication->GetAppDescriptions(
219 "com.example.app",
220 base::BindOnce(&AndroidAppCommunicationTest::OnGetAppDescriptionsResponse,
221 base::Unretained(this)));
222
223 EXPECT_FALSE(error_.has_value());
224
225 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
226 ASSERT_EQ(1u, apps_.size());
227 ASSERT_NE(nullptr, apps_.front().get());
228 EXPECT_EQ("com.example.app", apps_.front()->package);
229 EXPECT_EQ(std::vector<std::string>{"com.example.app.Service"},
230 apps_.front()->service_names);
231 ASSERT_EQ(1u, apps_.front()->activities.size());
232 ASSERT_NE(nullptr, apps_.front()->activities.front().get());
233 EXPECT_EQ("com.example.app.Activity",
234 apps_.front()->activities.front()->name);
235 EXPECT_EQ("https://play.google.com/billing",
236 apps_.front()->activities.front()->default_payment_method);
237 } else {
238 EXPECT_TRUE(apps_.empty());
239 }
240}
241
242TEST_F(AndroidAppCommunicationTest, OnlyActivity) {
243 auto scoped_initialization = support_->CreateScopedInitialization();
244
245 support_->ExpectQueryListOfPaymentAppsAndRespond(createApp(
246 {"com.example.app.Activity"}, "https://play.google.com/billing", {}));
247
248 auto communication =
249 AndroidAppCommunication::GetForBrowserContext(support_->context());
250 communication->SetForTesting();
251 communication->GetAppDescriptions(
252 "com.example.app",
253 base::BindOnce(&AndroidAppCommunicationTest::OnGetAppDescriptionsResponse,
254 base::Unretained(this)));
255
256 EXPECT_FALSE(error_.has_value());
257
258 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
259 ASSERT_EQ(1u, apps_.size());
260 ASSERT_NE(nullptr, apps_.front().get());
261 EXPECT_EQ("com.example.app", apps_.front()->package);
262 EXPECT_TRUE(apps_.front()->service_names.empty());
263 ASSERT_EQ(1u, apps_.front()->activities.size());
264 ASSERT_NE(nullptr, apps_.front()->activities.front().get());
265 EXPECT_EQ("com.example.app.Activity",
266 apps_.front()->activities.front()->name);
267 EXPECT_EQ("https://play.google.com/billing",
268 apps_.front()->activities.front()->default_payment_method);
269 } else {
270 EXPECT_TRUE(apps_.empty());
271 }
272}
273
274TEST_F(AndroidAppCommunicationTest, OutsideOfTwa) {
275 auto scoped_initialization = support_->CreateScopedInitialization();
276
277 support_->ExpectNoListOfPaymentAppsQuery();
278
279 auto communication =
280 AndroidAppCommunication::GetForBrowserContext(support_->context());
281 communication->SetForTesting();
282 communication->GetAppDescriptions(
283 /*twa_package_name=*/"", // Empty string means this is not TWA.
284 base::BindOnce(&AndroidAppCommunicationTest::OnGetAppDescriptionsResponse,
285 base::Unretained(this)));
286
287 EXPECT_FALSE(error_.has_value());
288 EXPECT_TRUE(apps_.empty());
Rouslan Solomakhin03358342020-08-13 19:33:44289}
290
Rouslan Solomakhin1043cf82020-08-14 01:17:43291TEST_F(AndroidAppCommunicationTest, NoArcForIsReadyToPay) {
292 // Intentionally do not set an instance.
293
294 support_->ExpectNoIsReadyToPayQuery();
295
296 auto communication =
297 AndroidAppCommunication::GetForBrowserContext(support_->context());
298 communication->SetForTesting();
299
300 std::map<std::string, std::set<std::string>> stringified_method_data;
301 stringified_method_data["https://play.google.com/billing"].insert("{}");
302 communication->IsReadyToPay(
303 "com.example.app", "com.example.app.Service", stringified_method_data,
304 GURL("https://top-level-origin.com"),
305 GURL("https://payment-request-origin.com"), "payment-request-id",
306 base::BindOnce(&AndroidAppCommunicationTest::OnIsReadyToPayResponse,
307 base::Unretained(this)));
308
309 ASSERT_TRUE(error_.has_value());
310 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
311 EXPECT_FALSE(is_ready_to_pay_);
312}
313
314TEST_F(AndroidAppCommunicationTest, TwaIsReadyToPayOnlyWithPlayBilling) {
315 auto scoped_initialization = support_->CreateScopedInitialization();
316
317 support_->ExpectNoIsReadyToPayQuery();
318
319 auto communication =
320 AndroidAppCommunication::GetForBrowserContext(support_->context());
321 communication->SetForTesting();
322
323 std::map<std::string, std::set<std::string>> stringified_method_data;
324 stringified_method_data["https://example.com"].insert("{}");
325 communication->IsReadyToPay(
326 "com.example.app", "com.example.app.Service", stringified_method_data,
327 GURL("https://top-level-origin.com"),
328 GURL("https://payment-request-origin.com"), "payment-request-id",
329 base::BindOnce(&AndroidAppCommunicationTest::OnIsReadyToPayResponse,
330 base::Unretained(this)));
331
332 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
333 EXPECT_FALSE(error_.has_value());
334 } else {
335 ASSERT_TRUE(error_.has_value());
336 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
337 }
338
339 EXPECT_FALSE(is_ready_to_pay_);
340}
341
342TEST_F(AndroidAppCommunicationTest, MoreThanOnePaymentMethodDataNotReadyToPay) {
343 auto scoped_initialization = support_->CreateScopedInitialization();
344
345 support_->ExpectNoIsReadyToPayQuery();
346
347 auto communication =
348 AndroidAppCommunication::GetForBrowserContext(support_->context());
349 communication->SetForTesting();
350
351 std::map<std::string, std::set<std::string>> stringified_method_data;
352 stringified_method_data["https://play.google.com/billing"].insert(
353 "{\"product_id\": \"1\"}");
354 stringified_method_data["https://play.google.com/billing"].insert(
355 "{\"product_id\": \"2\"}");
356 communication->IsReadyToPay(
357 "com.example.app", "com.example.app.Service", stringified_method_data,
358 GURL("https://top-level-origin.com"),
359 GURL("https://payment-request-origin.com"), "payment-request-id",
360 base::BindOnce(&AndroidAppCommunicationTest::OnIsReadyToPayResponse,
361 base::Unretained(this)));
362
363 ASSERT_TRUE(error_.has_value());
364
365 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
366 EXPECT_EQ("At most one payment method specific data is supported.",
367 error_.value());
368 } else {
369 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
370 }
371
372 EXPECT_FALSE(is_ready_to_pay_);
373}
374
375TEST_F(AndroidAppCommunicationTest, EmptyMethodDataIsReadyToPay) {
376 auto scoped_initialization = support_->CreateScopedInitialization();
377
378 support_->ExpectQueryIsReadyToPayAndRespond(true);
379
380 auto communication =
381 AndroidAppCommunication::GetForBrowserContext(support_->context());
382 communication->SetForTesting();
383
384 std::map<std::string, std::set<std::string>> stringified_method_data;
385 stringified_method_data.insert(std::make_pair(
386 "https://play.google.com/billing", std::set<std::string>()));
387 communication->IsReadyToPay(
388 "com.example.app", "com.example.app.Service", stringified_method_data,
389 GURL("https://top-level-origin.com"),
390 GURL("https://payment-request-origin.com"), "payment-request-id",
391 base::BindOnce(&AndroidAppCommunicationTest::OnIsReadyToPayResponse,
392 base::Unretained(this)));
393
394 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
395 EXPECT_FALSE(error_.has_value());
396 EXPECT_TRUE(is_ready_to_pay_);
397 } else {
398 ASSERT_TRUE(error_.has_value());
399 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
400 EXPECT_FALSE(is_ready_to_pay_);
401 }
402}
403
404TEST_F(AndroidAppCommunicationTest, NotReadyToPay) {
405 auto scoped_initialization = support_->CreateScopedInitialization();
406
407 support_->ExpectQueryIsReadyToPayAndRespond(false);
408
409 auto communication =
410 AndroidAppCommunication::GetForBrowserContext(support_->context());
411 communication->SetForTesting();
412
413 std::map<std::string, std::set<std::string>> stringified_method_data;
414 stringified_method_data["https://play.google.com/billing"].insert("{}");
415 communication->IsReadyToPay(
416 "com.example.app", "com.example.app.Service", stringified_method_data,
417 GURL("https://top-level-origin.com"),
418 GURL("https://payment-request-origin.com"), "payment-request-id",
419 base::BindOnce(&AndroidAppCommunicationTest::OnIsReadyToPayResponse,
420 base::Unretained(this)));
421
422 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
423 EXPECT_FALSE(error_.has_value());
424 } else {
425 ASSERT_TRUE(error_.has_value());
426 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
427 }
428
429 EXPECT_FALSE(is_ready_to_pay_);
430}
431
432TEST_F(AndroidAppCommunicationTest, ReadyToPay) {
433 auto scoped_initialization = support_->CreateScopedInitialization();
434
435 support_->ExpectQueryIsReadyToPayAndRespond(true);
436
437 auto communication =
438 AndroidAppCommunication::GetForBrowserContext(support_->context());
439 communication->SetForTesting();
440
441 std::map<std::string, std::set<std::string>> stringified_method_data;
442 stringified_method_data["https://play.google.com/billing"].insert("{}");
443 communication->IsReadyToPay(
444 "com.example.app", "com.example.app.Service", stringified_method_data,
445 GURL("https://top-level-origin.com"),
446 GURL("https://payment-request-origin.com"), "payment-request-id",
447 base::BindOnce(&AndroidAppCommunicationTest::OnIsReadyToPayResponse,
448 base::Unretained(this)));
449
450 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
451 EXPECT_FALSE(error_.has_value());
452 EXPECT_TRUE(is_ready_to_pay_);
453 } else {
454 ASSERT_TRUE(error_.has_value());
455 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
456 EXPECT_FALSE(is_ready_to_pay_);
457 }
458}
459
Rouslan Solomakhin888a0b92020-08-14 16:34:31460TEST_F(AndroidAppCommunicationTest, NoArcForInvokePaymentApp) {
461 // Intentionally do not set an instance.
462
463 support_->ExpectNoPaymentAppInvoke();
464
465 auto communication =
466 AndroidAppCommunication::GetForBrowserContext(support_->context());
467 communication->SetForTesting();
468
469 std::map<std::string, std::set<std::string>> stringified_method_data;
470 stringified_method_data["https://play.google.com/billing"].insert("{}");
471 communication->InvokePaymentApp(
472 "com.example.app", "com.example.app.Activity", stringified_method_data,
473 GURL("https://top-level-origin.com"),
474 GURL("https://payment-request-origin.com"), "payment-request-id",
Lloyd Piquec49b3462020-11-20 02:14:23475 web_contents_,
Rouslan Solomakhin888a0b92020-08-14 16:34:31476 base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
477 base::Unretained(this)));
478
479 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
480 EXPECT_FALSE(is_activity_result_ok_);
481 EXPECT_TRUE(payment_method_identifier_.empty());
482 EXPECT_EQ("{}", stringified_details_);
483}
484
485TEST_F(AndroidAppCommunicationTest, TwaPaymentOnlyWithPlayBilling) {
486 auto scoped_initialization = support_->CreateScopedInitialization();
487
488 support_->ExpectNoPaymentAppInvoke();
489
490 auto communication =
491 AndroidAppCommunication::GetForBrowserContext(support_->context());
492 communication->SetForTesting();
493
494 std::map<std::string, std::set<std::string>> stringified_method_data;
495 stringified_method_data["https://example.com"].insert("{}");
496 communication->InvokePaymentApp(
497 "com.example.app", "com.example.app.Activity", stringified_method_data,
498 GURL("https://top-level-origin.com"),
499 GURL("https://payment-request-origin.com"), "payment-request-id",
Lloyd Piquec49b3462020-11-20 02:14:23500 web_contents_,
Rouslan Solomakhin888a0b92020-08-14 16:34:31501 base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
502 base::Unretained(this)));
503
504 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
505 EXPECT_FALSE(error_.has_value());
506 EXPECT_FALSE(is_activity_result_ok_);
507 EXPECT_TRUE(payment_method_identifier_.empty());
508 EXPECT_EQ("{}", stringified_details_);
509 } else {
510 ASSERT_TRUE(error_.has_value());
511 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
512 }
513}
514
515TEST_F(AndroidAppCommunicationTest, NoPaymentWithMoreThanOnePaymentMethodData) {
516 auto scoped_initialization = support_->CreateScopedInitialization();
517
518 support_->ExpectNoPaymentAppInvoke();
519
520 auto communication =
521 AndroidAppCommunication::GetForBrowserContext(support_->context());
522 communication->SetForTesting();
523
524 std::map<std::string, std::set<std::string>> stringified_method_data;
525 stringified_method_data["https://play.google.com/billing"].insert(
526 "{\"product_id\": \"1\"}");
527 stringified_method_data["https://play.google.com/billing"].insert(
528 "{\"product_id\": \"2\"}");
529 communication->InvokePaymentApp(
530 "com.example.app", "com.example.app.Activity", stringified_method_data,
531 GURL("https://top-level-origin.com"),
532 GURL("https://payment-request-origin.com"), "payment-request-id",
Lloyd Piquec49b3462020-11-20 02:14:23533 web_contents_,
Rouslan Solomakhin888a0b92020-08-14 16:34:31534 base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
535 base::Unretained(this)));
536
537 EXPECT_FALSE(is_activity_result_ok_);
538 EXPECT_EQ("{}", stringified_details_);
539 EXPECT_TRUE(payment_method_identifier_.empty());
540 ASSERT_TRUE(error_.has_value());
541
542 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
543 EXPECT_EQ("At most one payment method specific data is supported.",
544 error_.value());
545 } else {
546 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
547 }
548}
549
550TEST_F(AndroidAppCommunicationTest, PaymentWithEmptyMethodData) {
551 auto scoped_initialization = support_->CreateScopedInitialization();
552
553 support_->ExpectInvokePaymentAppAndRespond(
554 /*is_activity_result_ok=*/true,
555 /*payment_method_identifier=*/"https://play.google.com/billing",
556 /*stringified_details*/ "{\"status\": \"ok\"}");
557
558 auto communication =
559 AndroidAppCommunication::GetForBrowserContext(support_->context());
560 communication->SetForTesting();
561
562 std::map<std::string, std::set<std::string>> stringified_method_data;
563 stringified_method_data.insert(std::make_pair(
564 "https://play.google.com/billing", std::set<std::string>()));
565 communication->InvokePaymentApp(
566 "com.example.app", "com.example.app.Activity", stringified_method_data,
567 GURL("https://top-level-origin.com"),
568 GURL("https://payment-request-origin.com"), "payment-request-id",
Lloyd Piquec49b3462020-11-20 02:14:23569 web_contents_,
Rouslan Solomakhin888a0b92020-08-14 16:34:31570 base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
571 base::Unretained(this)));
572
573 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
574 EXPECT_FALSE(error_.has_value());
575 EXPECT_TRUE(is_activity_result_ok_);
576 EXPECT_EQ("https://play.google.com/billing", payment_method_identifier_);
577 EXPECT_EQ("{\"status\": \"ok\"}", stringified_details_);
578 } else {
579 ASSERT_TRUE(error_.has_value());
580 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
581 }
582}
583
584TEST_F(AndroidAppCommunicationTest, UserCancelInvokePaymentApp) {
585 auto scoped_initialization = support_->CreateScopedInitialization();
586
587 support_->ExpectInvokePaymentAppAndRespond(
588 /*is_activity_result_ok=*/false,
589 /*payment_method_identifier=*/"https://play.google.com/billing",
590 /*stringified_details*/ "{}");
591
592 auto communication =
593 AndroidAppCommunication::GetForBrowserContext(support_->context());
594 communication->SetForTesting();
595
596 std::map<std::string, std::set<std::string>> stringified_method_data;
597 stringified_method_data["https://play.google.com/billing"].insert("{}");
598 communication->InvokePaymentApp(
599 "com.example.app", "com.example.app.Activity", stringified_method_data,
600 GURL("https://top-level-origin.com"),
601 GURL("https://payment-request-origin.com"), "payment-request-id",
Lloyd Piquec49b3462020-11-20 02:14:23602 web_contents_,
Rouslan Solomakhin888a0b92020-08-14 16:34:31603 base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
604 base::Unretained(this)));
605
606 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
607 EXPECT_FALSE(error_.has_value());
608 EXPECT_FALSE(is_activity_result_ok_);
609 EXPECT_EQ("https://play.google.com/billing", payment_method_identifier_);
610 EXPECT_EQ("{}", stringified_details_);
611 } else {
612 ASSERT_TRUE(error_.has_value());
613 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
614 }
615}
616
617TEST_F(AndroidAppCommunicationTest, UserConfirmInvokePaymentApp) {
618 auto scoped_initialization = support_->CreateScopedInitialization();
619
620 support_->ExpectInvokePaymentAppAndRespond(
621 /*is_activity_result_ok=*/true,
622 /*payment_method_identifier=*/"https://play.google.com/billing",
623 /*stringified_details*/ "{\"status\": \"ok\"}");
624
625 auto communication =
626 AndroidAppCommunication::GetForBrowserContext(support_->context());
627 communication->SetForTesting();
628
629 std::map<std::string, std::set<std::string>> stringified_method_data;
630 stringified_method_data["https://play.google.com/billing"].insert("{}");
631 communication->InvokePaymentApp(
632 "com.example.app", "com.example.app.Activity", stringified_method_data,
633 GURL("https://top-level-origin.com"),
634 GURL("https://payment-request-origin.com"), "payment-request-id",
Lloyd Piquec49b3462020-11-20 02:14:23635 web_contents_,
Rouslan Solomakhin888a0b92020-08-14 16:34:31636 base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
637 base::Unretained(this)));
638
639 if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
640 EXPECT_FALSE(error_.has_value());
641 EXPECT_TRUE(is_activity_result_ok_);
642 EXPECT_EQ("https://play.google.com/billing", payment_method_identifier_);
643 EXPECT_EQ("{\"status\": \"ok\"}", stringified_details_);
644 } else {
645 ASSERT_TRUE(error_.has_value());
646 EXPECT_EQ("Unable to invoke Android apps.", error_.value());
647 }
648}
649
Rouslan Solomakhin03358342020-08-13 19:33:44650} // namespace
651} // namespace payments