| // 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/utility/payment_manifest_parser.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/json/json_writer.h" |
| #include "base/run_loop.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "components/payments/core/error_logger.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace payments { |
| |
| namespace { |
| |
| std::string CreatePaymentMethodManifestJson( |
| const std::vector<GURL> web_app_manifest_urls, |
| const std::vector<url::Origin> supported_origins) { |
| std::string manifest = |
| "{" |
| " \"default_applications\":["; |
| for (auto iter = web_app_manifest_urls.begin(); |
| iter != web_app_manifest_urls.end(); ++iter) { |
| manifest += "\"" + iter->spec() + "\""; |
| if (iter != web_app_manifest_urls.end() - 1) |
| manifest += ","; |
| } |
| manifest += |
| " ]," |
| " \"supported_origins\":["; |
| for (auto iter = supported_origins.begin(); iter != supported_origins.end(); |
| ++iter) { |
| manifest += "\"" + iter->GetURL().spec() + "\""; |
| if (iter != supported_origins.end() - 1) |
| manifest += ","; |
| } |
| manifest += "]}"; |
| return manifest; |
| } |
| |
| } // namespace |
| |
| // Test fixture for payment manifest parser. |
| class PaymentManifestParserTest : public InProcessBrowserTest { |
| public: |
| PaymentManifestParserTest() |
| : parser_(std::make_unique<ErrorLogger>()), |
| all_origins_supported_(false) {} |
| ~PaymentManifestParserTest() override {} |
| |
| // Sends the |content| to the utility process to parse as a web app manifest |
| // and waits until the utility process responds. |
| void ParseWebAppManifest(const std::string& content) { |
| base::RunLoop run_loop; |
| parser_.ParseWebAppManifest( |
| content, |
| base::BindOnce(&PaymentManifestParserTest::OnWebAppManifestParsed, |
| base::Unretained(this), run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| // Sends the |content| to the utility process to parse as a payment method |
| // manifest and waits until the utility process responds. |
| void ParsePaymentMethodManifest(const std::string& content) { |
| base::RunLoop run_loop; |
| parser_.ParsePaymentMethodManifest( |
| content, base::BindOnce( |
| &PaymentManifestParserTest::OnPaymentMethodManifestParsed, |
| base::Unretained(this), run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| // The parsed web app manifest. |
| const std::vector<WebAppManifestSection>& web_app_manifest() const { |
| return web_app_manifest_; |
| } |
| |
| // The parsed web app manifest URLs from the payment method manifest. |
| const std::vector<GURL>& web_app_manifest_urls() const { |
| return web_app_manifest_urls_; |
| } |
| |
| // The parsed supported origins from the payment method manifest. |
| const std::vector<url::Origin>& supported_origins() const { |
| return supported_origins_; |
| } |
| |
| // Whether the parsed payment method manifest allows all origins to use the |
| // payment method. |
| bool all_origins_supported() const { return all_origins_supported_; } |
| |
| private: |
| // Called after the utility process has parsed the web app manifest. |
| void OnWebAppManifestParsed( |
| const base::Closure& resume_test, |
| const std::vector<WebAppManifestSection>& web_app_manifest) { |
| web_app_manifest_ = std::move(web_app_manifest); |
| DCHECK(!resume_test.is_null()); |
| resume_test.Run(); |
| } |
| |
| // Called after the utility process has parsed the payment method manifest. |
| void OnPaymentMethodManifestParsed( |
| const base::Closure& resume_test, |
| const std::vector<GURL>& web_app_manifest_urls, |
| const std::vector<url::Origin>& supported_origins, |
| bool all_origins_supported) { |
| web_app_manifest_urls_ = web_app_manifest_urls; |
| supported_origins_ = supported_origins; |
| all_origins_supported_ = all_origins_supported; |
| DCHECK(!resume_test.is_null()); |
| resume_test.Run(); |
| } |
| |
| PaymentManifestParser parser_; |
| std::vector<WebAppManifestSection> web_app_manifest_; |
| std::vector<GURL> web_app_manifest_urls_; |
| std::vector<url::Origin> supported_origins_; |
| bool all_origins_supported_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PaymentManifestParserTest); |
| }; |
| |
| // Handles a a manifest with 100 web app URLs. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, TooManyWebAppUrls) { |
| std::vector<GURL> web_app_manifest_urls_in; |
| web_app_manifest_urls_in.insert(web_app_manifest_urls_in.begin(), |
| /*count=*/101, |
| GURL("https://bobpay.com/manifest.json")); |
| std::string json = CreatePaymentMethodManifestJson( |
| web_app_manifest_urls_in, std::vector<url::Origin>()); |
| ParsePaymentMethodManifest(json); |
| EXPECT_TRUE(web_app_manifest_urls().empty()); |
| } |
| |
| // Handles a manifest with more than 100 supported origins. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, TooManySupportedOrigins) { |
| std::vector<url::Origin> supported_origins_in; |
| supported_origins_in.insert(supported_origins_in.begin(), /*count=*/100001, |
| url::Origin::Create(GURL("https://bobpay.com"))); |
| std::string json = CreatePaymentMethodManifestJson(std::vector<GURL>(), |
| supported_origins_in); |
| ParsePaymentMethodManifest(json); |
| EXPECT_TRUE(supported_origins().empty()); |
| } |
| |
| // Handles a manifest with an insecure supported origin. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, InsecureSupportedOrigin) { |
| std::string json = CreatePaymentMethodManifestJson( |
| std::vector<GURL>(), |
| std::vector<url::Origin>(1, |
| url::Origin::Create(GURL("http://bobpay.com")))); |
| ParsePaymentMethodManifest(json); |
| EXPECT_TRUE(supported_origins().empty()); |
| } |
| |
| // Handles a manifest with an insecure web app manifest URL. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, InsecureWebAppManifestUrl) { |
| std::string json = CreatePaymentMethodManifestJson( |
| std::vector<GURL>(1, GURL("http://bobpay.com/manifest.json")), |
| std::vector<url::Origin>()); |
| ParsePaymentMethodManifest(json); |
| EXPECT_TRUE(web_app_manifest_urls().empty()); |
| } |
| |
| // Handles a manifest with an invalid supported origin. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, InvalidSupportedOrigin) { |
| std::string json = CreatePaymentMethodManifestJson( |
| std::vector<GURL>(), |
| std::vector<url::Origin>(1, url::Origin::Create(GURL()))); |
| ParsePaymentMethodManifest(json); |
| EXPECT_TRUE(supported_origins().empty()); |
| } |
| |
| // Handles a manifest with an invalid web app manifest URL. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, InvalidWebAppManifestUrl) { |
| std::string json = CreatePaymentMethodManifestJson( |
| std::vector<GURL>(1, GURL()), std::vector<url::Origin>()); |
| ParsePaymentMethodManifest(json); |
| EXPECT_TRUE(web_app_manifest_urls().empty()); |
| } |
| |
| // Verify that the utility process correctly parses a payment method manifest |
| // that allows all origins to use the corresponding payment method name. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, AllOriginsSupported) { |
| ParsePaymentMethodManifest("{\"supported_origins\": \"*\"}"); |
| |
| EXPECT_TRUE(web_app_manifest_urls().empty()); |
| EXPECT_TRUE(supported_origins().empty()); |
| EXPECT_TRUE(all_origins_supported()); |
| } |
| |
| // Verify that the utility process correctly parses a payment method manifest |
| // with default applications and some supported origins. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, UrlsAndOrigins) { |
| ParsePaymentMethodManifest( |
| "{\"default_applications\": " |
| "[\"https://alicepay.com/web-app-manifest.json\"], " |
| "\"supported_origins\": [\"https://bobpay.com\"]}"); |
| |
| EXPECT_EQ( |
| std::vector<GURL>(1, GURL("https://alicepay.com/web-app-manifest.json")), |
| web_app_manifest_urls()); |
| EXPECT_EQ(std::vector<url::Origin>( |
| 1, url::Origin::Create(GURL("https://bobpay.com"))), |
| supported_origins()); |
| EXPECT_FALSE(all_origins_supported()); |
| } |
| |
| // Verifies a valid web app manifest is parsed correctly. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, WebAppManifest) { |
| ParseWebAppManifest( |
| "{" |
| " \"related_applications\": [{" |
| " \"platform\": \"play\", " |
| " \"id\": \"com.bobpay.app\", " |
| " \"min_version\": \"1\", " |
| " \"fingerprints\": [{" |
| " \"type\": \"sha256_cert\", " |
| " \"value\": \"00:01:02:03:04:05:06:07:08:09:A0:A1:A2:A3:A4:A5:A6:A7" |
| ":A8:A9:B0:B1:B2:B3:B4:B5:B6:B7:B8:B9:C0:C1\"" |
| " }]" |
| " }]" |
| "}"); |
| |
| ASSERT_EQ(1U, web_app_manifest().size()); |
| EXPECT_EQ("com.bobpay.app", web_app_manifest().front().id); |
| EXPECT_EQ(1, web_app_manifest().front().min_version); |
| ASSERT_EQ(1U, web_app_manifest().front().fingerprints.size()); |
| EXPECT_EQ( |
| std::vector<uint8_t>({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 0x08, 0x09, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, |
| 0xA6, 0xA7, 0xA8, 0xA9, 0xB0, 0xB1, 0xB2, 0xB3, |
| 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xC0, 0xC1}), |
| web_app_manifest().front().fingerprints.front()); |
| } |
| |
| // Handles a manifest with too many web app sections. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, |
| TooManyWebAppManifestSections) { |
| std::string manifest = " { \"related_applications\": ["; |
| std::string web_app_section = |
| "{" |
| " \"platform\": \"play\", " |
| " \"id\": \"com.bobpay.app\", " |
| " \"min_version\": \"1\", " |
| " \"fingerprints\": [{" |
| " \"type\": \"sha256_cert\", " |
| " \"value\": \"00:01:02:03:04:05:06:07:08:09:A0:A1:A2:A3:A4:A5:A6:A7" |
| ":A8:A9:B0:B1:B2:B3:B4:B5:B6:B7:B8:B9:C0:C1\"" |
| " }]" |
| "}"; |
| for (int i = 0; i < 100; i++) { |
| manifest += web_app_section; |
| manifest += ","; |
| } |
| manifest += web_app_section; // The 101th (last one) without comma. |
| manifest += "]}"; |
| ParseWebAppManifest(manifest); |
| EXPECT_TRUE(web_app_manifest().empty()); |
| } |
| |
| // Handles a manifest with too many fingerprints. |
| IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, TooManyFingerprints) { |
| std::string manifest = |
| "{ \"related_applications\": [{" |
| " \"platform\": \"play\", " |
| " \"id\": \"com.bobpay.app\", " |
| " \"min_version\": \"1\", " |
| " \"fingerprints\": ["; |
| std::string fingerprint = |
| " { \"type\": \"sha256_cert\", " |
| " \"value\": \"00:01:02:03:04:05:06:07:08:09:A0:A1:A2:A3:A4:A5:A6:A7" |
| ":A8:A9:B0:B1:B2:B3:B4:B5:B6:B7:B8:B9:C0:C1\"" |
| " }"; |
| for (int i = 0; i < 100; i++) { |
| manifest += fingerprint; |
| manifest += ","; |
| } |
| manifest += fingerprint; // Last one with no comma. |
| manifest += "]}]}"; |
| |
| ParseWebAppManifest(manifest); |
| EXPECT_TRUE(web_app_manifest().empty()); |
| } |
| |
| } // namespace payments |