Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(615)

Side by Side Diff: third_party/WebKit/Source/modules/payments/PaymentRequest.cpp

Issue 2470463002: Add data parameter to payment details modifier. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/payments/PaymentRequest.h" 5 #include "modules/payments/PaymentRequest.h"
6 6
7 #include "bindings/core/v8/ExceptionState.h" 7 #include "bindings/core/v8/ExceptionState.h"
8 #include "bindings/core/v8/JSONValuesForV8.h" 8 #include "bindings/core/v8/JSONValuesForV8.h"
9 #include "bindings/core/v8/ScriptPromiseResolver.h" 9 #include "bindings/core/v8/ScriptPromiseResolver.h"
10 #include "bindings/core/v8/ScriptState.h" 10 #include "bindings/core/v8/ScriptState.h"
(...skipping 19 matching lines...) Expand all
30 #include "public/platform/InterfaceProvider.h" 30 #include "public/platform/InterfaceProvider.h"
31 #include "public/platform/Platform.h" 31 #include "public/platform/Platform.h"
32 #include "public/platform/WebTraceLocation.h" 32 #include "public/platform/WebTraceLocation.h"
33 #include "wtf/HashSet.h" 33 #include "wtf/HashSet.h"
34 #include <utility> 34 #include <utility>
35 35
36 namespace mojo { 36 namespace mojo {
37 37
38 using blink::mojom::blink::PaymentCurrencyAmount; 38 using blink::mojom::blink::PaymentCurrencyAmount;
39 using blink::mojom::blink::PaymentCurrencyAmountPtr; 39 using blink::mojom::blink::PaymentCurrencyAmountPtr;
40 using blink::mojom::blink::PaymentDetails;
41 using blink::mojom::blink::PaymentDetailsModifier;
42 using blink::mojom::blink::PaymentDetailsModifierPtr;
43 using blink::mojom::blink::PaymentDetailsPtr;
44 using blink::mojom::blink::PaymentErrorReason;
45 using blink::mojom::blink::PaymentItem; 40 using blink::mojom::blink::PaymentItem;
46 using blink::mojom::blink::PaymentItemPtr; 41 using blink::mojom::blink::PaymentItemPtr;
47 using blink::mojom::blink::PaymentMethodData;
48 using blink::mojom::blink::PaymentMethodDataPtr;
49 using blink::mojom::blink::PaymentOptions; 42 using blink::mojom::blink::PaymentOptions;
50 using blink::mojom::blink::PaymentOptionsPtr; 43 using blink::mojom::blink::PaymentOptionsPtr;
51 using blink::mojom::blink::PaymentShippingOption; 44 using blink::mojom::blink::PaymentShippingOption;
52 using blink::mojom::blink::PaymentShippingOptionPtr; 45 using blink::mojom::blink::PaymentShippingOptionPtr;
53 using blink::mojom::blink::PaymentShippingType; 46 using blink::mojom::blink::PaymentShippingType;
54 47
55 template <> 48 template <>
56 struct TypeConverter<PaymentCurrencyAmountPtr, blink::PaymentCurrencyAmount> { 49 struct TypeConverter<PaymentCurrencyAmountPtr, blink::PaymentCurrencyAmount> {
57 static PaymentCurrencyAmountPtr Convert( 50 static PaymentCurrencyAmountPtr Convert(
58 const blink::PaymentCurrencyAmount& input) { 51 const blink::PaymentCurrencyAmount& input) {
(...skipping 22 matching lines...) Expand all
81 PaymentShippingOptionPtr output = PaymentShippingOption::New(); 74 PaymentShippingOptionPtr output = PaymentShippingOption::New();
82 output->id = input.id(); 75 output->id = input.id();
83 output->label = input.label(); 76 output->label = input.label();
84 output->amount = PaymentCurrencyAmount::From(input.amount()); 77 output->amount = PaymentCurrencyAmount::From(input.amount());
85 output->selected = input.hasSelected() && input.selected(); 78 output->selected = input.hasSelected() && input.selected();
86 return output; 79 return output;
87 } 80 }
88 }; 81 };
89 82
90 template <> 83 template <>
91 struct TypeConverter<PaymentDetailsModifierPtr, blink::PaymentDetailsModifier> {
92 static PaymentDetailsModifierPtr Convert(
93 const blink::PaymentDetailsModifier& input) {
94 PaymentDetailsModifierPtr output = PaymentDetailsModifier::New();
95 output->supported_methods =
96 WTF::Vector<WTF::String>(input.supportedMethods());
97
98 if (input.hasTotal())
99 output->total = PaymentItem::From(input.total());
100
101 if (input.hasAdditionalDisplayItems()) {
102 for (size_t i = 0; i < input.additionalDisplayItems().size(); ++i) {
103 output->additional_display_items.append(
104 PaymentItem::From(input.additionalDisplayItems()[i]));
105 }
106 }
107 return output;
108 }
109 };
110
111 template <>
112 struct TypeConverter<PaymentDetailsPtr, blink::PaymentDetails> {
113 static PaymentDetailsPtr Convert(const blink::PaymentDetails& input) {
114 PaymentDetailsPtr output = PaymentDetails::New();
115 output->total = PaymentItem::From(input.total());
116
117 if (input.hasDisplayItems()) {
118 for (size_t i = 0; i < input.displayItems().size(); ++i) {
119 output->display_items.append(
120 PaymentItem::From(input.displayItems()[i]));
121 }
122 }
123
124 if (input.hasShippingOptions()) {
125 for (size_t i = 0; i < input.shippingOptions().size(); ++i) {
126 output->shipping_options.append(
127 PaymentShippingOption::From(input.shippingOptions()[i]));
128 }
129 }
130
131 if (input.hasModifiers()) {
132 for (size_t i = 0; i < input.modifiers().size(); ++i) {
133 output->modifiers.append(
134 PaymentDetailsModifier::From(input.modifiers()[i]));
135 }
136 }
137
138 if (input.hasError())
139 output->error = input.error();
140 else
141 output->error = WTF::emptyString();
142
143 return output;
144 }
145 };
146
147 template <>
148 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> { 84 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> {
149 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input) { 85 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input) {
150 PaymentOptionsPtr output = PaymentOptions::New(); 86 PaymentOptionsPtr output = PaymentOptions::New();
151 output->request_payer_name = input.requestPayerName(); 87 output->request_payer_name = input.requestPayerName();
152 output->request_payer_email = input.requestPayerEmail(); 88 output->request_payer_email = input.requestPayerEmail();
153 output->request_payer_phone = input.requestPayerPhone(); 89 output->request_payer_phone = input.requestPayerPhone();
154 output->request_shipping = input.requestShipping(); 90 output->request_shipping = input.requestShipping();
155 91
156 if (input.shippingType() == "delivery") 92 if (input.shippingType() == "delivery")
157 output->shipping_type = PaymentShippingType::DELIVERY; 93 output->shipping_type = PaymentShippingType::DELIVERY;
158 else if (input.shippingType() == "pickup") 94 else if (input.shippingType() == "pickup")
159 output->shipping_type = PaymentShippingType::PICKUP; 95 output->shipping_type = PaymentShippingType::PICKUP;
160 else 96 else
161 output->shipping_type = PaymentShippingType::SHIPPING; 97 output->shipping_type = PaymentShippingType::SHIPPING;
162 98
163 return output; 99 return output;
164 } 100 }
165 }; 101 };
166 102
167 template <>
168 struct TypeConverter<WTFArray<PaymentMethodDataPtr>,
169 WTF::Vector<blink::PaymentRequest::MethodData>> {
170 static WTFArray<PaymentMethodDataPtr> Convert(
171 const WTF::Vector<blink::PaymentRequest::MethodData>& input) {
172 WTFArray<PaymentMethodDataPtr> output(input.size());
173 for (size_t i = 0; i < input.size(); ++i) {
174 output[i] = PaymentMethodData::New();
175 output[i]->supported_methods =
176 WTF::Vector<WTF::String>(input[i].supportedMethods);
177 output[i]->stringified_data = input[i].stringifiedData;
178 }
179 return output;
180 }
181 };
182
183 } // namespace mojo 103 } // namespace mojo
184 104
185 namespace blink { 105 namespace blink {
186 namespace { 106 namespace {
187 107
188 // If the website does not call complete() 60 seconds after show() has been 108 // If the website does not call complete() 60 seconds after show() has been
189 // resolved, then behave as if the website called complete("fail"). 109 // resolved, then behave as if the website called complete("fail").
190 static const int completeTimeoutSeconds = 60; 110 static const int completeTimeoutSeconds = 60;
191 111
192 // Validates ShippingOption or PaymentItem, which happen to have identical 112 // Validates ShippingOption or PaymentItem, which happen to have identical
193 // fields, except for "id", which is present only in ShippingOption. 113 // fields, except for "id", which is present only in ShippingOption.
194 template <typename T> 114 template <typename T>
195 void validateShippingOptionOrPaymentItem(const T& item, 115 void validateShippingOptionOrPaymentItem(const T& item,
Mathieu 2016/11/01 14:39:16 curious: are you worried that the exception is goi
please use gerrit instead 2016/11/02 16:27:09 Improving these error messages are a nice to have,
196 ExceptionState& exceptionState) { 116 ExceptionState& exceptionState) {
197 if (!item.hasLabel() || item.label().isEmpty()) { 117 if (!item.hasLabel() || item.label().isEmpty()) {
198 exceptionState.throwTypeError("Item label required"); 118 exceptionState.throwTypeError("Item label required");
199 return; 119 return;
200 } 120 }
201 121
202 if (!item.hasAmount()) { 122 if (!item.hasAmount()) {
203 exceptionState.throwTypeError("Currency amount required"); 123 exceptionState.throwTypeError("Currency amount required");
204 return; 124 return;
205 } 125 }
(...skipping 16 matching lines...) Expand all
222 return; 142 return;
223 } 143 }
224 144
225 if (!PaymentsValidators::isValidAmountFormat(item.amount().value(), 145 if (!PaymentsValidators::isValidAmountFormat(item.amount().value(),
226 &errorMessage)) { 146 &errorMessage)) {
227 exceptionState.throwTypeError(errorMessage); 147 exceptionState.throwTypeError(errorMessage);
228 return; 148 return;
229 } 149 }
230 } 150 }
231 151
232 void validateDisplayItems(const HeapVector<PaymentItem>& items, 152 String stringifyData(const ScriptValue& data, ExceptionState& exceptionState) {
Mathieu 2016/11/01 14:39:16 Not sure of the convention for documentation in Bl
please use gerrit instead 2016/11/02 16:27:09 Done.
233 ExceptionState& exceptionState) { 153 if (data.isEmpty())
234 for (const auto& item : items) { 154 return "";
235 validateShippingOptionOrPaymentItem(item, exceptionState); 155
236 if (exceptionState.hadException()) 156 std::unique_ptr<JSONValue> value =
237 return; 157 toJSONValue(data.context(), data.v8Value());
158 if (!value) {
159 exceptionState.throwTypeError(
160 "Unable to parse payment method specific data");
161 return "";
238 } 162 }
163
164 if (value->isNull())
Mathieu 2016/11/01 14:39:16 combine with previous block? if (!value || value-
please use gerrit instead 2016/11/02 16:27:09 That's right. "!value" catches objects that canno
165 return "";
166
167 if (value->getType() != JSONValue::TypeObject) {
168 exceptionState.throwTypeError("Data should be a JSON-serializable object");
169 return "";
170 }
171
172 return JSONObject::cast(value.get())->toJSONString();
239 } 173 }
240 174
241 // Returns false if |options| should be ignored, even if an exception was not 175 void validateAndConvertPaymentDetails(const PaymentDetails& input,
242 // thrown. TODO(rouslan): Clear shipping options instead of ignoring them when 176 bool requestShipping,
243 // http://crbug.com/601193 is fixed. 177 mojom::blink::PaymentDetailsPtr& output,
244 bool validateShippingOptions(const HeapVector<PaymentShippingOption>& options, 178 ExceptionState& exceptionState) {
245 ExceptionState& exceptionState) { 179 if (!input.hasTotal()) {
246 HashSet<String> uniqueIds; 180 exceptionState.throwTypeError("Must specify total");
247 for (const auto& option : options) {
248 if (!option.hasId() || option.id().isEmpty()) {
249 exceptionState.throwTypeError("ShippingOption id required");
250 return false;
251 }
252
253 if (uniqueIds.contains(option.id()))
254 return false;
255
256 uniqueIds.add(option.id());
257
258 validateShippingOptionOrPaymentItem(option, exceptionState);
259 if (exceptionState.hadException())
260 return false;
261 }
262
263 return true;
264 }
265
266 void validatePaymentDetailsModifiers(
267 const HeapVector<PaymentDetailsModifier>& modifiers,
268 ExceptionState& exceptionState) {
269 if (modifiers.isEmpty()) {
270 exceptionState.throwTypeError(
271 "Must specify at least one payment details modifier");
272 return; 181 return;
273 } 182 }
274 183
275 for (const auto& modifier : modifiers) { 184 validateShippingOptionOrPaymentItem(input.total(), exceptionState);
276 if (modifier.supportedMethods().isEmpty()) { 185 if (exceptionState.hadException())
277 exceptionState.throwTypeError( 186 return;
278 "Must specify at least one payment method identifier"); 187
188 if (input.total().amount().value()[0] == '-') {
189 exceptionState.throwTypeError("Total amount value should be non-negative");
190 return;
191 }
192
193 output->total = mojom::blink::PaymentItem::From(input.total());
194
195 if (input.hasDisplayItems()) {
196 output->display_items.resize(input.displayItems().size());
197 for (size_t i = 0; i < input.displayItems().size(); ++i) {
198 const PaymentItem& item = input.displayItems()[i];
199 validateShippingOptionOrPaymentItem(item, exceptionState);
200 if (exceptionState.hadException())
201 return;
202
203 output->display_items[i] = mojom::blink::PaymentItem::From(item);
204 }
205 }
206
207 if (input.hasShippingOptions() && requestShipping) {
208 HashSet<String> uniqueIds;
209 output->shipping_options.resize(input.shippingOptions().size());
210 for (size_t i = 0; i < input.shippingOptions().size(); ++i) {
211 const PaymentShippingOption& option = input.shippingOptions()[i];
212 if (!option.hasId() || option.id().isEmpty()) {
213 exceptionState.throwTypeError("ShippingOption id required");
214 return;
215 }
216
217 if (uniqueIds.contains(option.id())) {
218 // Duplicate identifiers cause all shipping options to be ignored.
219 output->shipping_options.resize(0);
220 break;
221 }
222
223 uniqueIds.add(option.id());
224
225 validateShippingOptionOrPaymentItem(option, exceptionState);
226 if (exceptionState.hadException())
227 return;
228
229 output->shipping_options[i] =
230 mojom::blink::PaymentShippingOption::From(option);
231 }
232 }
233
234 if (input.hasModifiers()) {
235 if (input.modifiers().isEmpty()) {
236 exceptionState.throwTypeError("At least one modifier expected");
279 return; 237 return;
280 } 238 }
281 239
282 if (modifier.hasTotal()) { 240 output->modifiers.resize(input.modifiers().size());
283 validateShippingOptionOrPaymentItem(modifier.total(), exceptionState); 241 for (size_t i = 0; i < input.modifiers().size(); ++i) {
242 const PaymentDetailsModifier& modifier = input.modifiers()[i];
243 output->modifiers[i] = mojom::blink::PaymentDetailsModifier::New();
244 if (modifier.supportedMethods().isEmpty()) {
245 exceptionState.throwTypeError(
246 "Modifier must specify at least one payment method identifier");
247 return;
248 }
249
250 output->modifiers[i]->supported_methods = modifier.supportedMethods();
251
252 if (modifier.hasTotal()) {
253 validateShippingOptionOrPaymentItem(modifier.total(), exceptionState);
254 if (exceptionState.hadException())
255 return;
256
257 if (modifier.total().amount().value()[0] == '-') {
258 exceptionState.throwTypeError(
259 "Modifier total amount value should be non-negative");
260 return;
261 }
262
263 output->modifiers[i]->total =
264 mojom::blink::PaymentItem::From(modifier.total());
265 }
266
267 output->modifiers[i]->stringified_data =
268 modifier.hasData() ? stringifyData(modifier.data(), exceptionState)
269 : "";
284 if (exceptionState.hadException()) 270 if (exceptionState.hadException())
285 return; 271 return;
286 272
287 if (modifier.total().amount().value()[0] == '-') { 273 if (modifier.hasAdditionalDisplayItems()) {
288 exceptionState.throwTypeError( 274 output->modifiers[i]->additional_display_items.resize(
289 "Total amount value should be non-negative"); 275 modifier.additionalDisplayItems().size());
290 return; 276 for (size_t j = 0; j < modifier.additionalDisplayItems().size(); ++j) {
277 const PaymentItem& item = modifier.additionalDisplayItems()[j];
278 validateShippingOptionOrPaymentItem(item, exceptionState);
279 if (exceptionState.hadException())
280 return;
281
282 output->modifiers[i]->additional_display_items[j] =
283 mojom::blink::PaymentItem::From(item);
284 }
291 } 285 }
292 } 286 }
293
294 if (modifier.hasAdditionalDisplayItems()) {
295 validateDisplayItems(modifier.additionalDisplayItems(), exceptionState);
296 if (exceptionState.hadException())
297 return;
298 }
299 }
300 }
301
302 // Returns false if the shipping options should be ignored without throwing an
303 // exception.
304 bool validatePaymentDetails(const PaymentDetails& details,
305 ExceptionState& exceptionState) {
306 bool keepShippingOptions = true;
307 if (!details.hasTotal()) {
308 exceptionState.throwTypeError("Must specify total");
309 return keepShippingOptions;
310 }
311
312 validateShippingOptionOrPaymentItem(details.total(), exceptionState);
313 if (exceptionState.hadException())
314 return keepShippingOptions;
315
316 if (details.total().amount().value()[0] == '-') {
317 exceptionState.throwTypeError("Total amount value should be non-negative");
318 return keepShippingOptions;
319 }
320
321 if (details.hasDisplayItems()) {
322 validateDisplayItems(details.displayItems(), exceptionState);
323 if (exceptionState.hadException())
324 return keepShippingOptions;
325 }
326
327 if (details.hasShippingOptions()) {
328 keepShippingOptions =
329 validateShippingOptions(details.shippingOptions(), exceptionState);
330
331 if (exceptionState.hadException())
332 return keepShippingOptions;
333 }
334
335 if (details.hasModifiers()) {
336 validatePaymentDetailsModifiers(details.modifiers(), exceptionState);
337 if (exceptionState.hadException())
338 return keepShippingOptions;
339 } 287 }
340 288
341 String errorMessage; 289 String errorMessage;
342 if (!PaymentsValidators::isValidErrorMsgFormat(details.error(), 290 if (!PaymentsValidators::isValidErrorMsgFormat(input.error(),
343 &errorMessage)) { 291 &errorMessage)) {
344 exceptionState.throwTypeError(errorMessage); 292 exceptionState.throwTypeError(errorMessage);
293 return;
345 } 294 }
346 295
347 return keepShippingOptions; 296 output->error =
297 input.hasError() && !input.error().isNull() ? input.error() : "";
348 } 298 }
349 299
350 void validateAndConvertPaymentMethodData( 300 void validateAndConvertPaymentMethodData(
Mathieu 2016/11/01 14:39:16 would benefit from a comment such as // Takes th
please use gerrit instead 2016/11/02 16:27:09 Done. Also added a similar comment to validatedAnd
351 const HeapVector<PaymentMethodData>& paymentMethodData, 301 const HeapVector<PaymentMethodData>& input,
352 Vector<PaymentRequest::MethodData>* methodData, 302 Vector<mojom::blink::PaymentMethodDataPtr>& output,
353 ExceptionState& exceptionState) { 303 ExceptionState& exceptionState) {
354 if (paymentMethodData.isEmpty()) { 304 if (input.isEmpty()) {
355 exceptionState.throwTypeError( 305 exceptionState.throwTypeError(
356 "Must specify at least one payment method identifier"); 306 "Must specify at least one payment method identifier");
357 return; 307 return;
358 } 308 }
359 309
360 for (const auto& pmd : paymentMethodData) { 310 output.resize(input.size());
311 for (size_t i = 0; i < input.size(); ++i) {
312 const PaymentMethodData& pmd = input[i];
361 if (pmd.supportedMethods().isEmpty()) { 313 if (pmd.supportedMethods().isEmpty()) {
362 exceptionState.throwTypeError( 314 exceptionState.throwTypeError(
363 "Must specify at least one payment method identifier"); 315 "Must specify at least one payment method identifier");
364 return; 316 return;
365 } 317 }
366 318
367 String stringifiedData = ""; 319 output[i] = mojom::blink::PaymentMethodData::New();
368 if (pmd.hasData() && !pmd.data().isEmpty()) { 320 output[i]->supported_methods = pmd.supportedMethods();
369 std::unique_ptr<JSONValue> value = 321 output[i]->stringified_data =
370 toJSONValue(pmd.data().context(), pmd.data().v8Value()); 322 pmd.hasData() ? stringifyData(pmd.data(), exceptionState) : "";
371 if (!value) { 323 if (exceptionState.hadException())
372 exceptionState.throwTypeError( 324 return;
373 "Unable to parse payment method specific data");
374 return;
375 }
376 if (!value->isNull()) {
377 if (value->getType() != JSONValue::TypeObject) {
378 exceptionState.throwTypeError(
379 "Data should be a JSON-serializable object");
380 return;
381 }
382 stringifiedData = JSONObject::cast(value.get())->toJSONString();
383 }
384 }
385 methodData->append(
386 PaymentRequest::MethodData(pmd.supportedMethods(), stringifiedData));
387 } 325 }
388 } 326 }
389 327
390 String getSelectedShippingOption(const PaymentDetails& details) { 328 String getSelectedShippingOption(
391 String result; 329 const mojom::blink::PaymentDetailsPtr& details) {
392 if (!details.hasShippingOptions()) 330 if (details->shipping_options.isEmpty())
393 return result; 331 return String();
394 332
395 for (int i = details.shippingOptions().size() - 1; i >= 0; --i) { 333 for (int i = details->shipping_options.size() - 1; i >= 0; --i) {
396 if (details.shippingOptions()[i].hasSelected() && 334 if (details->shipping_options[i]->selected)
397 details.shippingOptions()[i].selected()) { 335 return details->shipping_options[i]->id;
398 return details.shippingOptions()[i].id();
399 }
400 } 336 }
401 337
402 return result; 338 return String();
403 } 339 }
404 340
405 String getValidShippingType(const String& shippingType) { 341 String getValidShippingType(const String& shippingType) {
406 static const char* const validValues[] = { 342 static const char* const validValues[] = {
407 "shipping", "delivery", "pickup", 343 "shipping", "delivery", "pickup",
408 }; 344 };
409 for (size_t i = 0; i < WTF_ARRAY_LENGTH(validValues); i++) { 345 for (size_t i = 0; i < WTF_ARRAY_LENGTH(validValues); i++) {
410 if (shippingType == validValues[i]) 346 if (shippingType == validValues[i])
411 return shippingType; 347 return shippingType;
412 } 348 }
413 return validValues[0]; 349 return validValues[0];
414 } 350 }
415 351
416 mojom::blink::PaymentDetailsPtr maybeKeepShippingOptions(
417 mojom::blink::PaymentDetailsPtr details,
418 bool keep) {
419 if (!keep)
420 details->shipping_options.resize(0);
421
422 return details;
423 }
424
425 bool allowedToUsePaymentRequest(const Frame* frame) { 352 bool allowedToUsePaymentRequest(const Frame* frame) {
426 // To determine whether a Document object |document| is allowed to use the 353 // To determine whether a Document object |document| is allowed to use the
427 // feature indicated by attribute name |allowpaymentrequest|, run these steps: 354 // feature indicated by attribute name |allowpaymentrequest|, run these steps:
428 355
429 // 1. If |document| has no browsing context, then return false. 356 // 1. If |document| has no browsing context, then return false.
430 if (!frame) 357 if (!frame)
431 return false; 358 return false;
432 359
433 // 2. If |document|'s browsing context is a top-level browsing context, then 360 // 2. If |document|'s browsing context is a top-level browsing context, then
434 // return true. 361 // return true.
435 if (frame->isMainFrame()) 362 if (frame->isMainFrame())
436 return true; 363 return true;
437 364
438 // 3. If |document|'s browsing context has a browsing context container that 365 // 3. If |document|'s browsing context has a browsing context container that
439 // is an iframe element with an |allowpaymentrequest| attribute specified, and 366 // is an iframe element with an |allowpaymentrequest| attribute specified, and
440 // whose node document is allowed to use the feature indicated by 367 // whose node document is allowed to use the feature indicated by
441 // |allowpaymentrequest|, then return true. 368 // |allowpaymentrequest|, then return true.
442 HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(frame->owner()); 369 HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(frame->owner());
443 if (ownerElement && isHTMLIFrameElement(ownerElement)) { 370 if (ownerElement && isHTMLIFrameElement(ownerElement)) {
444 HTMLIFrameElement* iframe = toHTMLIFrameElement(ownerElement); 371 HTMLIFrameElement* iframe = toHTMLIFrameElement(ownerElement);
445 if (HTMLIFrameElementPayments::from(*iframe).allowPaymentRequest(*iframe)) 372 if (HTMLIFrameElementPayments::from(*iframe).allowPaymentRequest(*iframe))
446 return allowedToUsePaymentRequest(frame->tree().parent()); 373 return allowedToUsePaymentRequest(frame->tree().parent());
447 } 374 }
448 375
449 // 4. Return false. 376 // 4. Return false.
450 return false; 377 return false;
451 } 378 }
452 379
453 WTF::Vector<mojom::blink::PaymentMethodDataPtr> ConvertPaymentMethodData(
454 const Vector<PaymentRequest::MethodData>& blinkMethods) {
455 WTF::Vector<mojom::blink::PaymentMethodDataPtr> mojoMethods(
456 blinkMethods.size());
457 for (size_t i = 0; i < blinkMethods.size(); ++i) {
458 mojoMethods[i] = mojom::blink::PaymentMethodData::New();
459 mojoMethods[i]->supported_methods =
460 WTF::Vector<WTF::String>(blinkMethods[i].supportedMethods);
461 mojoMethods[i]->stringified_data = blinkMethods[i].stringifiedData;
462 }
463 return mojoMethods;
464 }
465
466 } // namespace 380 } // namespace
467 381
468 PaymentRequest* PaymentRequest::create( 382 PaymentRequest* PaymentRequest::create(
469 ScriptState* scriptState, 383 ScriptState* scriptState,
470 const HeapVector<PaymentMethodData>& methodData, 384 const HeapVector<PaymentMethodData>& methodData,
471 const PaymentDetails& details, 385 const PaymentDetails& details,
472 ExceptionState& exceptionState) { 386 ExceptionState& exceptionState) {
473 return new PaymentRequest(scriptState, methodData, details, PaymentOptions(), 387 return new PaymentRequest(scriptState, methodData, details, PaymentOptions(),
474 exceptionState); 388 exceptionState);
475 } 389 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 V8PaymentDetails::toImpl(detailsScriptValue.isolate(), 487 V8PaymentDetails::toImpl(detailsScriptValue.isolate(),
574 detailsScriptValue.v8Value(), details, 488 detailsScriptValue.v8Value(), details,
575 exceptionState); 489 exceptionState);
576 if (exceptionState.hadException()) { 490 if (exceptionState.hadException()) {
577 m_showResolver->reject( 491 m_showResolver->reject(
578 DOMException::create(SyntaxError, exceptionState.message())); 492 DOMException::create(SyntaxError, exceptionState.message()));
579 clearResolversAndCloseMojoConnection(); 493 clearResolversAndCloseMojoConnection();
580 return; 494 return;
581 } 495 }
582 496
583 bool keepShippingOptions = validatePaymentDetails(details, exceptionState); 497 mojom::blink::PaymentDetailsPtr validatedDetails =
498 mojom::blink::PaymentDetails::New();
499 validateAndConvertPaymentDetails(details, m_options.requestShipping(),
500 validatedDetails, exceptionState);
584 if (exceptionState.hadException()) { 501 if (exceptionState.hadException()) {
585 m_showResolver->reject( 502 m_showResolver->reject(
586 DOMException::create(SyntaxError, exceptionState.message())); 503 DOMException::create(SyntaxError, exceptionState.message()));
587 clearResolversAndCloseMojoConnection(); 504 clearResolversAndCloseMojoConnection();
588 return; 505 return;
589 } 506 }
590 507
591 if (m_options.requestShipping()) { 508 if (m_options.requestShipping())
592 if (keepShippingOptions) 509 m_shippingOption = getSelectedShippingOption(validatedDetails);
593 m_shippingOption = getSelectedShippingOption(details);
594 else
595 m_shippingOption = String();
596 }
597 510
598 m_paymentProvider->UpdateWith(maybeKeepShippingOptions( 511 m_paymentProvider->UpdateWith(std::move(validatedDetails));
599 mojom::blink::PaymentDetails::From(details), keepShippingOptions));
600 } 512 }
601 513
602 void PaymentRequest::onUpdatePaymentDetailsFailure(const String& error) { 514 void PaymentRequest::onUpdatePaymentDetailsFailure(const String& error) {
603 if (m_showResolver) 515 if (m_showResolver)
604 m_showResolver->reject(DOMException::create(AbortError, error)); 516 m_showResolver->reject(DOMException::create(AbortError, error));
605 if (m_completeResolver) 517 if (m_completeResolver)
606 m_completeResolver->reject(DOMException::create(AbortError, error)); 518 m_completeResolver->reject(DOMException::create(AbortError, error));
607 clearResolversAndCloseMojoConnection(); 519 clearResolversAndCloseMojoConnection();
608 } 520 }
609 521
(...skipping 15 matching lines...) Expand all
625 PaymentRequest::PaymentRequest(ScriptState* scriptState, 537 PaymentRequest::PaymentRequest(ScriptState* scriptState,
626 const HeapVector<PaymentMethodData>& methodData, 538 const HeapVector<PaymentMethodData>& methodData,
627 const PaymentDetails& details, 539 const PaymentDetails& details,
628 const PaymentOptions& options, 540 const PaymentOptions& options,
629 ExceptionState& exceptionState) 541 ExceptionState& exceptionState)
630 : ContextLifecycleObserver(scriptState->getExecutionContext()), 542 : ContextLifecycleObserver(scriptState->getExecutionContext()),
631 ActiveScriptWrappable(this), 543 ActiveScriptWrappable(this),
632 m_options(options), 544 m_options(options),
633 m_clientBinding(this), 545 m_clientBinding(this),
634 m_completeTimer(this, &PaymentRequest::onCompleteTimeout) { 546 m_completeTimer(this, &PaymentRequest::onCompleteTimeout) {
635 Vector<MethodData> validatedMethodData; 547 Vector<mojom::blink::PaymentMethodDataPtr> validatedMethodData;
636 validateAndConvertPaymentMethodData(methodData, &validatedMethodData, 548 validateAndConvertPaymentMethodData(methodData, validatedMethodData,
637 exceptionState); 549 exceptionState);
638 if (exceptionState.hadException()) 550 if (exceptionState.hadException())
639 return; 551 return;
640 552
641 if (!scriptState->getExecutionContext()->isSecureContext()) { 553 if (!scriptState->getExecutionContext()->isSecureContext()) {
642 exceptionState.throwSecurityError("Must be in a secure context"); 554 exceptionState.throwSecurityError("Must be in a secure context");
643 return; 555 return;
644 } 556 }
645 557
646 if (!allowedToUsePaymentRequest(scriptState->domWindow()->frame())) { 558 if (!allowedToUsePaymentRequest(scriptState->domWindow()->frame())) {
647 exceptionState.throwSecurityError( 559 exceptionState.throwSecurityError(
648 "Must be in a top-level browsing context or an iframe needs to specify " 560 "Must be in a top-level browsing context or an iframe needs to specify "
649 "'allowpaymentrequest' explicitly"); 561 "'allowpaymentrequest' explicitly");
650 return; 562 return;
651 } 563 }
652 564
653 bool keepShippingOptions = validatePaymentDetails(details, exceptionState); 565 mojom::blink::PaymentDetailsPtr validatedDetails =
566 mojom::blink::PaymentDetails::New();
567 validateAndConvertPaymentDetails(details, m_options.requestShipping(),
568 validatedDetails, exceptionState);
654 if (exceptionState.hadException()) 569 if (exceptionState.hadException())
655 return; 570 return;
656 571
657 if (details.hasError() && !details.error().isEmpty()) { 572 if (!validatedDetails->error.isEmpty()) {
658 exceptionState.throwTypeError("Error value should be empty"); 573 exceptionState.throwTypeError("Error value should be empty");
659 return; 574 return;
660 } 575 }
661 576
662 if (m_options.requestShipping()) { 577 if (m_options.requestShipping()) {
663 if (keepShippingOptions) 578 m_shippingOption = getSelectedShippingOption(validatedDetails);
664 m_shippingOption = getSelectedShippingOption(details);
665 m_shippingType = getValidShippingType(m_options.shippingType()); 579 m_shippingType = getValidShippingType(m_options.shippingType());
666 } 580 }
667 581
668 scriptState->domWindow()->frame()->interfaceProvider()->getInterface( 582 scriptState->domWindow()->frame()->interfaceProvider()->getInterface(
669 mojo::GetProxy(&m_paymentProvider)); 583 mojo::GetProxy(&m_paymentProvider));
670 m_paymentProvider.set_connection_error_handler(convertToBaseCallback( 584 m_paymentProvider.set_connection_error_handler(convertToBaseCallback(
671 WTF::bind(&PaymentRequest::OnError, wrapWeakPersistent(this), 585 WTF::bind(&PaymentRequest::OnError, wrapWeakPersistent(this),
672 mojom::blink::PaymentErrorReason::UNKNOWN))); 586 mojom::blink::PaymentErrorReason::UNKNOWN)));
673 m_paymentProvider->Init( 587 m_paymentProvider->Init(m_clientBinding.CreateInterfacePtrAndBind(),
674 m_clientBinding.CreateInterfacePtrAndBind(), 588 std::move(validatedMethodData),
675 ConvertPaymentMethodData(validatedMethodData), 589 std::move(validatedDetails),
676 maybeKeepShippingOptions( 590 mojom::blink::PaymentOptions::From(m_options));
677 mojom::blink::PaymentDetails::From(details),
678 keepShippingOptions && m_options.requestShipping()),
679 mojom::blink::PaymentOptions::From(m_options));
680 } 591 }
681 592
682 void PaymentRequest::contextDestroyed() { 593 void PaymentRequest::contextDestroyed() {
683 clearResolversAndCloseMojoConnection(); 594 clearResolversAndCloseMojoConnection();
684 } 595 }
685 596
686 void PaymentRequest::OnShippingAddressChange( 597 void PaymentRequest::OnShippingAddressChange(
687 mojom::blink::PaymentAddressPtr address) { 598 mojom::blink::PaymentAddressPtr address) {
688 DCHECK(m_showResolver); 599 DCHECK(m_showResolver);
689 DCHECK(!m_completeResolver); 600 DCHECK(!m_completeResolver);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 m_completeTimer.startOneShot(completeTimeoutSeconds, BLINK_FROM_HERE); 674 m_completeTimer.startOneShot(completeTimeoutSeconds, BLINK_FROM_HERE);
764 675
765 m_showResolver->resolve(new PaymentResponse(std::move(response), this)); 676 m_showResolver->resolve(new PaymentResponse(std::move(response), this));
766 677
767 // Do not close the mojo connection here. The merchant website should call 678 // Do not close the mojo connection here. The merchant website should call
768 // PaymentResponse::complete(String), which will be forwarded over the mojo 679 // PaymentResponse::complete(String), which will be forwarded over the mojo
769 // connection to display a success or failure message to the user. 680 // connection to display a success or failure message to the user.
770 m_showResolver.clear(); 681 m_showResolver.clear();
771 } 682 }
772 683
773 void PaymentRequest::OnError(mojo::PaymentErrorReason error) { 684 void PaymentRequest::OnError(mojom::blink::PaymentErrorReason error) {
774 if (!Platform::current()) { 685 if (!Platform::current()) {
775 // TODO(rockot): Clean this up once renderer shutdown sequence is fixed. 686 // TODO(rockot): Clean this up once renderer shutdown sequence is fixed.
776 return; 687 return;
777 } 688 }
778 689
779 bool isError = false; 690 bool isError = false;
780 ExceptionCode ec = UnknownError; 691 ExceptionCode ec = UnknownError;
781 String message; 692 String message;
782 693
783 switch (error) { 694 switch (error) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 m_completeTimer.stop(); 762 m_completeTimer.stop();
852 m_completeResolver.clear(); 763 m_completeResolver.clear();
853 m_showResolver.clear(); 764 m_showResolver.clear();
854 m_abortResolver.clear(); 765 m_abortResolver.clear();
855 if (m_clientBinding.is_bound()) 766 if (m_clientBinding.is_bound())
856 m_clientBinding.Close(); 767 m_clientBinding.Close();
857 m_paymentProvider.reset(); 768 m_paymentProvider.reset();
858 } 769 }
859 770
860 } // namespace blink 771 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698