Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/payments/BasicCardPayment.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "BasicCardPayment.h"
8
#include "PaymentAddress.h"
9
#include "mozilla/ClearOnShutdown.h"
10
#include "nsArrayUtils.h"
11
#include "nsISupportsPrimitives.h"
12
#include "nsCharSeparatedTokenizer.h"
13
#include "nsDataHashtable.h"
14
15
namespace mozilla {
16
namespace dom {
17
#ifndef PaymentBasicCardMacros
18
#define PaymentBasicCardMacros
19
20
0
#define AMEX NS_LITERAL_STRING("amex")
21
0
#define CARTEBANCAIRE NS_LITERAL_STRING("cartebancaire")
22
0
#define DINERS NS_LITERAL_STRING("diners")
23
0
#define DISCOVER NS_LITERAL_STRING("discover")
24
0
#define JCB NS_LITERAL_STRING("jcb")
25
0
#define MASTERCARD NS_LITERAL_STRING("mastercard")
26
0
#define MIR NS_LITERAL_STRING("mir")
27
0
#define UNIONPAY NS_LITERAL_STRING("unionpay")
28
0
#define VISA NS_LITERAL_STRING("visa")
29
30
0
#define CardholderName NS_LITERAL_STRING("cardholderName")
31
0
#define CardNumber NS_LITERAL_STRING("cardNumber")
32
0
#define ExpiryMonth NS_LITERAL_STRING("expiryMonth")
33
0
#define ExpiryYear NS_LITERAL_STRING("expiryYear")
34
0
#define CardSecurityCode NS_LITERAL_STRING("cardSecurityCode")
35
36
0
#define Country NS_LITERAL_STRING("country")
37
0
#define AddressLine NS_LITERAL_STRING("addressLine")
38
0
#define Region NS_LITERAL_STRING("region")
39
0
#define City NS_LITERAL_STRING("city")
40
0
#define DependentLocality NS_LITERAL_STRING("dependentLocality")
41
0
#define PostalCode NS_LITERAL_STRING("postalCode")
42
0
#define SortingCode NS_LITERAL_STRING("sortingCode")
43
0
#define Organization NS_LITERAL_STRING("organization")
44
0
#define Recipient NS_LITERAL_STRING("recipient")
45
0
#define Phone NS_LITERAL_STRING("phone")
46
47
0
#define PropertySpliter NS_LITERAL_STRING(";")
48
0
#define KeyValueSpliter NS_LITERAL_STRING(":")
49
0
#define AddressLineSpliter NS_LITERAL_STRING("%")
50
51
#define EncodeBasicCardProperty(aPropertyName, aPropertyValue, aResult)        \
52
0
  do {                                                                         \
53
0
    if (!(aPropertyValue).IsEmpty()) {                                         \
54
0
      (aResult) += (aPropertyName)                                             \
55
0
                 + KeyValueSpliter                                             \
56
0
                 + (aPropertyValue)                                            \
57
0
                 + PropertySpliter;                                            \
58
0
    }                                                                          \
59
0
  } while(0)
60
61
#define EncodeAddressProperty(aAddress, aPropertyName, aResult)                \
62
0
  do {                                                                         \
63
0
    nsAutoString propertyValue;                                                \
64
0
    NS_ENSURE_SUCCESS((aAddress)->Get##aPropertyName(propertyValue),           \
65
0
                                                     NS_ERROR_FAILURE);        \
66
0
    EncodeBasicCardProperty((aPropertyName) ,propertyValue , (aResult));       \
67
0
  } while(0)
68
69
#define DecodeBasicCardProperty(aPropertyName, aPropertyValue,                 \
70
                                aMatchPropertyName, aResponse)                 \
71
0
  do {                                                                         \
72
0
    if ((aPropertyName).Equals((aMatchPropertyName))) {                        \
73
0
      (aResponse).m##aMatchPropertyName.Construct();                           \
74
0
      (aResponse).m##aMatchPropertyName.Value() = (aPropertyValue);            \
75
0
    }                                                                          \
76
0
  } while(0)
77
78
#define DecodeAddressProperty(aPropertyName, aPropertyValue,                   \
79
                              aMatchPropertyName, aMatchPropertyValue)         \
80
0
  do {                                                                         \
81
0
    if ((aPropertyName).Equals((aMatchPropertyName))) {                        \
82
0
      (aMatchPropertyValue) = (aPropertyValue);                                \
83
0
    }                                                                          \
84
0
  } while(0)
85
86
#endif
87
88
namespace {
89
90
bool IsValidNetwork(const nsAString& aNetwork)
91
0
{
92
0
  return AMEX.Equals(aNetwork) ||
93
0
         CARTEBANCAIRE.Equals(aNetwork) ||
94
0
         DINERS.Equals(aNetwork) ||
95
0
         DISCOVER.Equals(aNetwork) ||
96
0
         JCB.Equals(aNetwork) ||
97
0
         MASTERCARD.Equals(aNetwork) ||
98
0
         MIR.Equals(aNetwork) ||
99
0
         UNIONPAY.Equals(aNetwork) ||
100
0
         VISA.Equals(aNetwork);
101
0
}
102
103
bool IsBasicCardKey(const nsAString& aKey)
104
0
{
105
0
  return CardholderName.Equals(aKey) ||
106
0
         CardNumber.Equals(aKey) ||
107
0
         ExpiryMonth.Equals(aKey) ||
108
0
         ExpiryYear.Equals(aKey) ||
109
0
         CardSecurityCode.Equals(aKey);
110
0
}
111
112
bool IsAddressKey(const nsAString& aKey)
113
0
{
114
0
  return Country.Equals(aKey) ||
115
0
         AddressLine.Equals(aKey) ||
116
0
         Region.Equals(aKey) ||
117
0
         City.Equals(aKey) ||
118
0
         DependentLocality.Equals(aKey) ||
119
0
         PostalCode.Equals(aKey) ||
120
0
         SortingCode.Equals(aKey) ||
121
0
         Organization.Equals(aKey) ||
122
0
         Recipient.Equals(aKey) ||
123
0
         Phone.Equals(aKey);
124
0
}
125
126
} // end of namespace
127
128
129
StaticRefPtr<BasicCardService> gBasicCardService;
130
131
already_AddRefed<BasicCardService>
132
BasicCardService::GetService()
133
0
{
134
0
  if (!gBasicCardService) {
135
0
    gBasicCardService = new BasicCardService();
136
0
    ClearOnShutdown(&gBasicCardService);
137
0
  }
138
0
  RefPtr<BasicCardService> service = gBasicCardService;
139
0
  return service.forget();
140
0
}
141
142
bool
143
BasicCardService::IsBasicCardPayment(const nsAString& aSupportedMethods)
144
0
{
145
0
  return aSupportedMethods.Equals(NS_LITERAL_STRING("basic-card"));
146
0
}
147
148
bool
149
BasicCardService::IsValidBasicCardRequest(JSContext* aCx,
150
                                          JSObject* aData,
151
                                          nsAString& aErrorMsg)
152
0
{
153
0
  if (!aData) {
154
0
    return true;
155
0
  }
156
0
  JS::RootedValue data(aCx, JS::ObjectValue(*aData));
157
0
158
0
  BasicCardRequest request;
159
0
  if (!request.Init(aCx, data)) {
160
0
    aErrorMsg.AssignLiteral("Fail to convert methodData.data to BasicCardRequest.");
161
0
    return false;
162
0
  }
163
0
164
0
  if (request.mSupportedNetworks.WasPassed()) {
165
0
    for (const nsString& network : request.mSupportedNetworks.Value()) {
166
0
      if (!IsValidNetwork(network)) {
167
0
        aErrorMsg.Assign(network + NS_LITERAL_STRING(" is not an valid network."));
168
0
        return false;
169
0
      }
170
0
    }
171
0
  }
172
0
  return true;
173
0
}
174
175
bool
176
BasicCardService::IsValidExpiryMonth(const nsAString& aExpiryMonth)
177
0
{
178
0
  // ExpiryMonth can only be
179
0
  //   1. empty string
180
0
  //   2. 01 ~ 12
181
0
  if (aExpiryMonth.IsEmpty()) {
182
0
    return true;
183
0
  }
184
0
  if (aExpiryMonth.Length() != 2) {
185
0
    return false;
186
0
  }
187
0
  // can only be 00 ~ 09
188
0
  if (aExpiryMonth.CharAt(0) == '0') {
189
0
    if (aExpiryMonth.CharAt(1) < '0' || aExpiryMonth.CharAt(1) > '9') {
190
0
      return false;
191
0
    }
192
0
    return true;
193
0
  }
194
0
  // can only be 11 or 12
195
0
  if (aExpiryMonth.CharAt(0) == '1') {
196
0
    if (aExpiryMonth.CharAt(1) != '1' && aExpiryMonth.CharAt(1) != '2') {
197
0
      return false;
198
0
    }
199
0
    return true;
200
0
  }
201
0
  return false;
202
0
}
203
204
bool
205
BasicCardService::IsValidExpiryYear(const nsAString& aExpiryYear)
206
0
{
207
0
  // ExpiryYear can only be
208
0
  //   1. empty string
209
0
  //   2. 0000 ~ 9999
210
0
  if (!aExpiryYear.IsEmpty()) {
211
0
    if (aExpiryYear.Length() != 4) {
212
0
      return false;
213
0
    }
214
0
    for (uint32_t index = 0; index < 4; ++index) {
215
0
      if (aExpiryYear.CharAt(index) < '0' ||
216
0
          aExpiryYear.CharAt(index) > '9') {
217
0
        return false;
218
0
      }
219
0
    }
220
0
  }
221
0
  return true;
222
0
}
223
224
nsresult
225
BasicCardService::EncodeBasicCardData(const nsAString& aCardholderName,
226
                                      const nsAString& aCardNumber,
227
                                      const nsAString& aExpiryMonth,
228
                                      const nsAString& aExpiryYear,
229
                                      const nsAString& aCardSecurityCode,
230
                                      nsIPaymentAddress* aBillingAddress,
231
                                      nsAString& aResult)
232
0
{
233
0
  // aBillingAddress can be nullptr
234
0
  if (aCardNumber.IsEmpty()) {
235
0
    return NS_ERROR_FAILURE;
236
0
  }
237
0
  EncodeBasicCardProperty(CardholderName, aCardholderName, aResult);
238
0
  EncodeBasicCardProperty(CardNumber, aCardNumber, aResult);
239
0
  EncodeBasicCardProperty(ExpiryMonth, aExpiryMonth, aResult);
240
0
  EncodeBasicCardProperty(ExpiryYear, aExpiryYear, aResult);
241
0
  EncodeBasicCardProperty(CardSecurityCode, aCardSecurityCode, aResult);
242
0
  if (!aBillingAddress) {
243
0
    return NS_OK;
244
0
  }
245
0
  EncodeAddressProperty(aBillingAddress, Country, aResult);
246
0
  nsCOMPtr<nsIArray> addressLine;
247
0
  NS_ENSURE_SUCCESS(aBillingAddress->GetAddressLine(getter_AddRefs(addressLine)),
248
0
                                                    NS_ERROR_FAILURE);
249
0
  uint32_t length;
250
0
  nsAutoString addressLineString;
251
0
  NS_ENSURE_SUCCESS(addressLine->GetLength(&length), NS_ERROR_FAILURE);
252
0
  for (uint32_t index = 0; index < length; ++index) {
253
0
    nsCOMPtr<nsISupportsString> address = do_QueryElementAt(addressLine, index);
254
0
    MOZ_ASSERT(address);
255
0
    nsAutoString addressString;
256
0
    NS_ENSURE_SUCCESS(address->GetData(addressString), NS_ERROR_FAILURE);
257
0
    addressLineString += addressString + AddressLineSpliter;
258
0
  }
259
0
  EncodeBasicCardProperty(AddressLine ,addressLineString , aResult);
260
0
  EncodeAddressProperty(aBillingAddress, Region, aResult);
261
0
  EncodeAddressProperty(aBillingAddress, City, aResult);
262
0
  EncodeAddressProperty(aBillingAddress, DependentLocality, aResult);
263
0
  EncodeAddressProperty(aBillingAddress, PostalCode, aResult);
264
0
  EncodeAddressProperty(aBillingAddress, SortingCode, aResult);
265
0
  EncodeAddressProperty(aBillingAddress, Organization, aResult);
266
0
  EncodeAddressProperty(aBillingAddress, Recipient, aResult);
267
0
  EncodeAddressProperty(aBillingAddress, Phone, aResult);
268
0
  return NS_OK;
269
0
}
270
271
nsresult
272
BasicCardService::DecodeBasicCardData(const nsAString& aData,
273
                                      nsPIDOMWindowInner* aWindow,
274
                                      BasicCardResponse& aResponse)
275
0
{
276
0
  // aWindow can be nullptr
277
0
  bool isBillingAddressPassed = false;
278
0
  nsTArray<nsString> addressLine;
279
0
  nsAutoString country;
280
0
  nsAutoString region;
281
0
  nsAutoString city;
282
0
  nsAutoString dependentLocality;
283
0
  nsAutoString postalCode;
284
0
  nsAutoString sortingCode;
285
0
  nsAutoString organization;
286
0
  nsAutoString recipient;
287
0
  nsAutoString phone;
288
0
289
0
  nsCharSeparatedTokenizer propertyTokenizer(aData, PropertySpliter.CharAt(0));
290
0
  while (propertyTokenizer.hasMoreTokens()) {
291
0
    nsDependentSubstring property = propertyTokenizer.nextToken();
292
0
    nsCharSeparatedTokenizer keyValueTokenizer(property, KeyValueSpliter.CharAt(0));
293
0
    MOZ_ASSERT(keyValueTokenizer.hasMoreTokens());
294
0
    nsDependentSubstring key = keyValueTokenizer.nextToken();
295
0
    nsDependentSubstring value = keyValueTokenizer.nextToken();
296
0
    if (IsAddressKey(key) && !isBillingAddressPassed) {
297
0
      isBillingAddressPassed = true;
298
0
    }
299
0
    if (!IsAddressKey(key) && !IsBasicCardKey(key)) {
300
0
      return NS_ERROR_FAILURE;
301
0
    }
302
0
303
0
    if (key.Equals(CardNumber)) {
304
0
      aResponse.mCardNumber = (value);
305
0
    }
306
0
307
0
    DecodeBasicCardProperty(key, value, CardholderName, aResponse);
308
0
    DecodeBasicCardProperty(key, value, ExpiryMonth, aResponse);
309
0
    DecodeBasicCardProperty(key, value, ExpiryYear, aResponse);
310
0
    DecodeBasicCardProperty(key, value, CardSecurityCode, aResponse);
311
0
312
0
    DecodeAddressProperty(key, value, Country, country);
313
0
    DecodeAddressProperty(key, value, Region, region);
314
0
    DecodeAddressProperty(key, value, City, city);
315
0
    DecodeAddressProperty(key, value, DependentLocality, dependentLocality);
316
0
    DecodeAddressProperty(key, value, PostalCode, postalCode);
317
0
    DecodeAddressProperty(key, value, SortingCode, sortingCode);
318
0
    DecodeAddressProperty(key, value, Organization, organization);
319
0
    DecodeAddressProperty(key, value, Recipient, recipient);
320
0
    DecodeAddressProperty(key, value, Phone, phone);
321
0
322
0
    if ((key).Equals(AddressLine)) {
323
0
      nsCharSeparatedTokenizer addressTokenizer(value, AddressLineSpliter.CharAt(0));
324
0
      while (addressTokenizer.hasMoreTokens()) {
325
0
        addressLine.AppendElement(addressTokenizer.nextToken());
326
0
      }
327
0
    }
328
0
  }
329
0
  if (isBillingAddressPassed) {
330
0
    aResponse.mBillingAddress.Construct();
331
0
    aResponse.mBillingAddress.Value() = new PaymentAddress(aWindow,
332
0
                                                           country,
333
0
                                                           addressLine,
334
0
                                                           region,
335
0
                                                           city,
336
0
                                                           dependentLocality,
337
0
                                                           postalCode,
338
0
                                                           sortingCode,
339
0
                                                           organization,
340
0
                                                           recipient,
341
0
                                                           phone);
342
0
  }
343
0
  return NS_OK;
344
0
}
345
346
#ifdef PaymentBasicCardMacros
347
#undef PaymentBasicCardMacros
348
#undef EncodeBasicCardProperty
349
#undef EncodeAddressProperty
350
#undef DecodeBasicCardProperty
351
#undef DecodeAddressProperty
352
#undef AMEX
353
#undef CARTEBANCAIRE
354
#undef DINERS
355
#undef DISCOVER
356
#undef JCB
357
#undef MASTERCARD
358
#undef MIR
359
#undef UNIONPAY
360
#undef VISA
361
#undef CardholderName
362
#undef CardNumber
363
#undef ExpiryMonth
364
#undef ExpiryYear
365
#undef CardSecurityCode
366
#undef Country
367
#undef AddressLine
368
#undef Region
369
#undef City
370
#undef DependentLocality
371
#undef PostalCode
372
#undef SortingCode
373
#undef Organization
374
#undef Recipient
375
#undef Phone
376
#undef PropertySpliter
377
#undef KeyValueSpliter
378
#undef AddressLineSpliter
379
#endif
380
381
} // end of namespace dom
382
} // end of namespace mozilla