1 // 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 
5 #include "third_party/blink/renderer/core/html/trust_token_attribute_parsing.h"
6 
7 #include "services/network/public/mojom/trust_tokens.mojom-blink.h"
8 #include "services/network/trust_tokens/test/trust_token_test_util.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/blink/renderer/platform/json/json_parser.h"
11 #include "third_party/blink/renderer/platform/json/json_values.h"
12 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
13 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
14 
15 namespace blink {
16 namespace internal {
17 namespace {
18 
NetworkParamsToBlinkParams(network::mojom::TrustTokenParamsPtr params)19 network::mojom::blink::TrustTokenParamsPtr NetworkParamsToBlinkParams(
20     network::mojom::TrustTokenParamsPtr params) {
21   auto ret = network::mojom::blink::TrustTokenParams::New();
22   ret->type = params->type;
23   ret->refresh_policy = params->refresh_policy;
24   ret->sign_request_data = params->sign_request_data;
25   ret->include_timestamp_header = params->include_timestamp_header;
26   if (params->issuer)
27     ret->issuer = SecurityOrigin::CreateFromUrlOrigin(*params->issuer);
28   for (const std::string& header : params->additional_signed_headers) {
29     ret->additional_signed_headers.push_back(String::FromUTF8(header));
30   }
31   return ret;
32 }
33 
34 }  // namespace
35 
36 using TrustTokenAttributeParsingSuccess =
37     ::testing::TestWithParam<network::TrustTokenTestParameters>;
38 
39 INSTANTIATE_TEST_SUITE_P(
40     WithIssuanceParams,
41     TrustTokenAttributeParsingSuccess,
42     ::testing::ValuesIn(network::kIssuanceTrustTokenTestParameters));
43 INSTANTIATE_TEST_SUITE_P(
44     WithRedemptionParams,
45     TrustTokenAttributeParsingSuccess,
46     ::testing::ValuesIn(network::kRedemptionTrustTokenTestParameters));
47 INSTANTIATE_TEST_SUITE_P(
48     WithSigningParams,
49     TrustTokenAttributeParsingSuccess,
50     ::testing::ValuesIn(network::kSigningTrustTokenTestParameters));
51 
52 // Test roundtrip serializations-then-deserializations for a collection of test
53 // cases covering all possible values of all enum attributes, and all
54 // possibilities (e.g. optional members present vs. not present) for all other
55 // attributes.
TEST_P(TrustTokenAttributeParsingSuccess,Roundtrip)56 TEST_P(TrustTokenAttributeParsingSuccess, Roundtrip) {
57   network::mojom::TrustTokenParams network_expectation;
58   std::string input;
59 
60   network::TrustTokenParametersAndSerialization
61       expected_params_and_serialization =
62           network::SerializeTrustTokenParametersAndConstructExpectation(
63               GetParam());
64 
65   network::mojom::blink::TrustTokenParamsPtr expectation =
66       NetworkParamsToBlinkParams(
67           std::move(expected_params_and_serialization.params));
68 
69   std::unique_ptr<JSONValue> json_value = ParseJSON(
70       String::FromUTF8(expected_params_and_serialization.serialized_params));
71   ASSERT_TRUE(json_value);
72   auto result = TrustTokenParamsFromJson(std::move(json_value));
73   ASSERT_TRUE(result);
74 
75   // We can't use mojo's generated Equals method here because it doesn't play
76   // well with the "issuer" field's type of
77   // scoped_refptr<blink::SecurityOrigin>: in particular, the method does an
78   // address-to-address comparison of the pointers.
79   EXPECT_EQ(result->type, expectation->type);
80   EXPECT_EQ(result->refresh_policy, expectation->refresh_policy);
81   EXPECT_EQ(result->sign_request_data, expectation->sign_request_data);
82   EXPECT_EQ(result->include_timestamp_header,
83             expectation->include_timestamp_header);
84 
85   EXPECT_EQ(!!result->issuer, !!expectation->issuer);
86   if (result->issuer)
87     EXPECT_EQ(result->issuer->ToString(), expectation->issuer->ToString());
88 
89   EXPECT_EQ(result->additional_signed_headers,
90             expectation->additional_signed_headers);
91 }
92 
TEST(TrustTokenAttributeParsing,NotADictionary)93 TEST(TrustTokenAttributeParsing, NotADictionary) {
94   auto json = ParseJSON(R"(
95     3
96   )");
97   ASSERT_TRUE(json);
98   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
99 }
100 
TEST(TrustTokenAttributeParsing,MissingType)101 TEST(TrustTokenAttributeParsing, MissingType) {
102   auto json = ParseJSON(R"(
103     { }
104   )");
105   ASSERT_TRUE(json);
106   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
107 }
108 
TEST(TrustTokenAttributeParsing,TypeUnsafeType)109 TEST(TrustTokenAttributeParsing, TypeUnsafeType) {
110   auto json = ParseJSON(R"(
111     { "type": 3 }
112   )");
113   ASSERT_TRUE(json);
114   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
115 }
116 
TEST(TrustTokenAttributeParsing,InvalidType)117 TEST(TrustTokenAttributeParsing, InvalidType) {
118   auto json = ParseJSON(R"(
119     { "type": "not a valid type" }
120   )");
121   ASSERT_TRUE(json);
122   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
123 }
124 
TEST(TrustTokenAttributeParsing,TypeUnsafeRefreshPolicy)125 TEST(TrustTokenAttributeParsing, TypeUnsafeRefreshPolicy) {
126   auto json = ParseJSON(R"(
127     { "type": "token-request",
128       "refreshPolicy": 3 }
129   )");
130   ASSERT_TRUE(json);
131   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
132 }
133 
TEST(TrustTokenAttributeParsing,InvalidRefreshPolicy)134 TEST(TrustTokenAttributeParsing, InvalidRefreshPolicy) {
135   auto json = ParseJSON(R"(
136     { "type": "token-request",
137       "refreshPolicy": "not a valid refresh policy" }
138   )");
139   ASSERT_TRUE(json);
140   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
141 }
142 
TEST(TrustTokenAttributeParsing,TypeUnsafeSignRequestData)143 TEST(TrustTokenAttributeParsing, TypeUnsafeSignRequestData) {
144   auto json = ParseJSON(R"(
145     { "type": "token-request",
146       "signRequestData": 3 }
147   )");
148   ASSERT_TRUE(json);
149   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
150 }
151 
TEST(TrustTokenAttributeParsing,InvalidSignRequestData)152 TEST(TrustTokenAttributeParsing, InvalidSignRequestData) {
153   auto json = ParseJSON(R"(
154     { "type": "token-request",
155       "signRequestData": "not a member of the signRequestData enum" }
156   )");
157   ASSERT_TRUE(json);
158   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
159 }
160 
TEST(TrustTokenAttributeParsing,TypeUnsafeIncludeTimestampHeader)161 TEST(TrustTokenAttributeParsing, TypeUnsafeIncludeTimestampHeader) {
162   auto json = ParseJSON(R"(
163     { "type": "token-request",
164       "includeTimestampHeader": 3 }
165   )");
166   ASSERT_TRUE(json);
167   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
168 }
169 
TEST(TrustTokenAttributeParsing,TypeUnsafeIssuer)170 TEST(TrustTokenAttributeParsing, TypeUnsafeIssuer) {
171   auto json = ParseJSON(R"(
172     { "type": "token-request",
173       "issuer": 3 }
174   )");
175   ASSERT_TRUE(json);
176   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
177 }
178 
179 // Test that the parser requires that |issuer| be a valid origin.
TEST(TrustTokenAttributeParsing,NonUrlIssuer)180 TEST(TrustTokenAttributeParsing, NonUrlIssuer) {
181   JSONParseError err;
182   auto json = ParseJSON(R"(
183     { "type": "token-request",
184       "issuer": "not a URL" }
185   )",
186                         &err);
187   ASSERT_TRUE(json);
188   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
189 }
190 
191 // Test that the parser requires that |issuer| be a potentially trustworthy
192 // origin.
TEST(TrustTokenAttributeParsing,InsecureIssuer)193 TEST(TrustTokenAttributeParsing, InsecureIssuer) {
194   auto json = ParseJSON(R"(
195     { "type": "token-request",
196       "issuer": "http://not-potentially-trustworthy.example" }
197   )");
198   ASSERT_TRUE(json);
199   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
200 }
201 
202 // Test that the parser requires that |issuer| be a HTTP or HTTPS origin.
203 TEST(TrustTokenAttributeParsing, NonHttpNonHttpsIssuer) {
204   auto json = ParseJSON(R"(
205     { "type": "token-request",
206       "issuer": "file:///" }
207   )");
208   ASSERT_TRUE(json);
209   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
210 }
211 
212 TEST(TrustTokenAttributeParsing, TypeUnsafeAdditionalSignedHeaders) {
213   auto json = ParseJSON(R"(
214     { "type": "token-request",
215       "additionalSignedHeaders": 3}
216   )");
217   ASSERT_TRUE(json);
218   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
219 }
220 
221 // Test that the parser requires that all members of the additionalSignedHeaders
222 // be strings.
223 TEST(TrustTokenAttributeParsing, TypeUnsafeAdditionalSignedHeader) {
224   auto json = ParseJSON(R"(
225     { "type": "token-request",
226       "additionalSignedHeaders": ["plausible header", 17] }
227   )");
228   ASSERT_TRUE(json);
229   ASSERT_FALSE(TrustTokenParamsFromJson(std::move(json)));
230 }
231 
232 }  // namespace internal
233 }  // namespace blink
234