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

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

Issue 2470463002: Add data parameter to payment details modifier. (Closed)
Patch Set: Add comments and rebase 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/ScriptPromiseResolver.h" 8 #include "bindings/core/v8/ScriptPromiseResolver.h"
9 #include "bindings/core/v8/ScriptState.h" 9 #include "bindings/core/v8/ScriptState.h"
10 #include "bindings/core/v8/V8StringResource.h" 10 #include "bindings/core/v8/V8StringResource.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
(...skipping 29 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 // Converts a JSON-serializable object into a JSON string. For example, the
233 ExceptionState& exceptionState) { 153 // object
234 for (const auto& item : items) { 154 // var data = {"foo": "bar"};
235 validateShippingOptionOrPaymentItem(item, exceptionState); 155 // is converted into the string
236 if (exceptionState.hadException()) 156 // '{"foo": "bar"}'
157 String stringifyData(const ScriptValue& data, ExceptionState& exceptionState) {
158 if (data.isEmpty())
159 return "";
160
161 if (!data.v8Value()->IsObject() || data.v8Value()->IsArray()) {
162 exceptionState.throwTypeError("Data should be a JSON-serializable object");
163 return "";
164 }
165
166 v8::MaybeLocal<v8::String> value =
167 v8::JSON::Stringify(data.context(), data.v8Value().As<v8::Object>());
haraken 2016/11/03 15:21:32 Can you use ToLocal instead of MaybeLocal?
168 if (value.IsEmpty()) {
169 exceptionState.throwTypeError(
170 "Unable to parse payment method specific data");
171 return "";
172 }
173
174 return v8StringToWebCoreString<String>(value.ToLocalChecked(),
175 DoNotExternalize);
176 }
177
178 // Takes the PaymentDetails and requestShipping option as specified by the
179 // website/javascript and creates a validated Mojo PaymentDetailsPtr to e passed
180 // to the embedder/browser.
181 void validateAndConvertPaymentDetails(const PaymentDetails& input,
182 bool requestShipping,
183 mojom::blink::PaymentDetailsPtr& output,
184 ExceptionState& exceptionState) {
185 if (!input.hasTotal()) {
186 exceptionState.throwTypeError("Must specify total");
187 return;
188 }
189
190 validateShippingOptionOrPaymentItem(input.total(), exceptionState);
191 if (exceptionState.hadException())
192 return;
193
194 if (input.total().amount().value()[0] == '-') {
195 exceptionState.throwTypeError("Total amount value should be non-negative");
196 return;
197 }
198
199 output->total = mojom::blink::PaymentItem::From(input.total());
200
201 if (input.hasDisplayItems()) {
202 output->display_items.resize(input.displayItems().size());
203 for (size_t i = 0; i < input.displayItems().size(); ++i) {
204 const PaymentItem& item = input.displayItems()[i];
205 validateShippingOptionOrPaymentItem(item, exceptionState);
206 if (exceptionState.hadException())
207 return;
208
209 output->display_items[i] = mojom::blink::PaymentItem::From(item);
210 }
211 }
212
213 if (input.hasShippingOptions() && requestShipping) {
214 HashSet<String> uniqueIds;
215 output->shipping_options.resize(input.shippingOptions().size());
216 for (size_t i = 0; i < input.shippingOptions().size(); ++i) {
217 const PaymentShippingOption& option = input.shippingOptions()[i];
218 if (!option.hasId() || option.id().isEmpty()) {
219 exceptionState.throwTypeError("ShippingOption id required");
220 return;
221 }
222
223 if (uniqueIds.contains(option.id())) {
224 // Duplicate identifiers cause all shipping options to be ignored.
225 output->shipping_options.resize(0);
226 break;
227 }
228
229 uniqueIds.add(option.id());
230
231 validateShippingOptionOrPaymentItem(option, exceptionState);
232 if (exceptionState.hadException())
233 return;
234
235 output->shipping_options[i] =
236 mojom::blink::PaymentShippingOption::From(option);
237 }
238 }
239
240 if (input.hasModifiers()) {
241 if (input.modifiers().isEmpty()) {
242 exceptionState.throwTypeError("At least one modifier expected");
237 return; 243 return;
238 } 244 }
239 } 245
240 246 output->modifiers.resize(input.modifiers().size());
241 // Returns false if |options| should be ignored, even if an exception was not 247 for (size_t i = 0; i < input.modifiers().size(); ++i) {
242 // thrown. TODO(rouslan): Clear shipping options instead of ignoring them when 248 const PaymentDetailsModifier& modifier = input.modifiers()[i];
243 // http://crbug.com/601193 is fixed. 249 output->modifiers[i] = mojom::blink::PaymentDetailsModifier::New();
244 bool validateShippingOptions(const HeapVector<PaymentShippingOption>& options, 250 if (modifier.supportedMethods().isEmpty()) {
245 ExceptionState& exceptionState) { 251 exceptionState.throwTypeError(
246 HashSet<String> uniqueIds; 252 "Modifier must specify at least one payment method identifier");
247 for (const auto& option : options) { 253 return;
248 if (!option.hasId() || option.id().isEmpty()) { 254 }
249 exceptionState.throwTypeError("ShippingOption id required"); 255
250 return false; 256 output->modifiers[i]->supported_methods = modifier.supportedMethods();
251 } 257
252 258 if (modifier.hasTotal()) {
253 if (uniqueIds.contains(option.id())) 259 validateShippingOptionOrPaymentItem(modifier.total(), exceptionState);
254 return false; 260 if (exceptionState.hadException())
255 261 return;
256 uniqueIds.add(option.id()); 262
257 263 if (modifier.total().amount().value()[0] == '-') {
258 validateShippingOptionOrPaymentItem(option, exceptionState); 264 exceptionState.throwTypeError(
259 if (exceptionState.hadException()) 265 "Modifier total amount value should be non-negative");
260 return false; 266 return;
261 } 267 }
262 268
263 return true; 269 output->modifiers[i]->total =
264 } 270 mojom::blink::PaymentItem::From(modifier.total());
265 271 }
266 void validatePaymentDetailsModifiers( 272
267 const HeapVector<PaymentDetailsModifier>& modifiers, 273 output->modifiers[i]->stringified_data =
268 ExceptionState& exceptionState) { 274 modifier.hasData() ? stringifyData(modifier.data(), exceptionState)
269 if (modifiers.isEmpty()) { 275 : "";
270 exceptionState.throwTypeError(
271 "Must specify at least one payment details modifier");
272 return;
273 }
274
275 for (const auto& modifier : modifiers) {
276 if (modifier.supportedMethods().isEmpty()) {
277 exceptionState.throwTypeError(
278 "Must specify at least one payment method identifier");
279 return;
280 }
281
282 if (modifier.hasTotal()) {
283 validateShippingOptionOrPaymentItem(modifier.total(), exceptionState);
284 if (exceptionState.hadException()) 276 if (exceptionState.hadException())
285 return; 277 return;
286 278
287 if (modifier.total().amount().value()[0] == '-') { 279 if (modifier.hasAdditionalDisplayItems()) {
288 exceptionState.throwTypeError( 280 output->modifiers[i]->additional_display_items.resize(
289 "Total amount value should be non-negative"); 281 modifier.additionalDisplayItems().size());
290 return; 282 for (size_t j = 0; j < modifier.additionalDisplayItems().size(); ++j) {
291 } 283 const PaymentItem& item = modifier.additionalDisplayItems()[j];
292 } 284 validateShippingOptionOrPaymentItem(item, exceptionState);
293 285 if (exceptionState.hadException())
294 if (modifier.hasAdditionalDisplayItems()) { 286 return;
295 validateDisplayItems(modifier.additionalDisplayItems(), exceptionState); 287
296 if (exceptionState.hadException()) 288 output->modifiers[i]->additional_display_items[j] =
297 return; 289 mojom::blink::PaymentItem::From(item);
298 } 290 }
299 } 291 }
300 } 292 }
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 } 293 }
340 294
341 String errorMessage; 295 String errorMessage;
342 if (!PaymentsValidators::isValidErrorMsgFormat(details.error(), 296 if (!PaymentsValidators::isValidErrorMsgFormat(input.error(),
343 &errorMessage)) { 297 &errorMessage)) {
344 exceptionState.throwTypeError(errorMessage); 298 exceptionState.throwTypeError(errorMessage);
345 } 299 return;
346 300 }
347 return keepShippingOptions; 301
348 } 302 output->error =
349 303 input.hasError() && !input.error().isNull() ? input.error() : "";
304 }
305
306 // Takes the vector of PaymentMethodData objects as specified by the
307 // website/javascript and creates a vector of validated Mojo
308 // PaymentMethodDataPtr objects to be passed to the embedder/browser.
350 void validateAndConvertPaymentMethodData( 309 void validateAndConvertPaymentMethodData(
351 const HeapVector<PaymentMethodData>& paymentMethodData, 310 const HeapVector<PaymentMethodData>& input,
352 Vector<PaymentRequest::MethodData>* methodData, 311 Vector<mojom::blink::PaymentMethodDataPtr>& output,
353 ExceptionState& exceptionState) { 312 ExceptionState& exceptionState) {
354 if (paymentMethodData.isEmpty()) { 313 if (input.isEmpty()) {
355 exceptionState.throwTypeError( 314 exceptionState.throwTypeError(
356 "Must specify at least one payment method identifier"); 315 "Must specify at least one payment method identifier");
357 return; 316 return;
358 } 317 }
359 318
360 for (const auto& pmd : paymentMethodData) { 319 output.resize(input.size());
320 for (size_t i = 0; i < input.size(); ++i) {
321 const PaymentMethodData& pmd = input[i];
361 if (pmd.supportedMethods().isEmpty()) { 322 if (pmd.supportedMethods().isEmpty()) {
362 exceptionState.throwTypeError( 323 exceptionState.throwTypeError(
363 "Must specify at least one payment method identifier"); 324 "Must specify at least one payment method identifier");
364 return; 325 return;
365 } 326 }
366 327
367 String stringifiedData = ""; 328 output[i] = mojom::blink::PaymentMethodData::New();
368 if (pmd.hasData() && !pmd.data().isEmpty()) { 329 output[i]->supported_methods = pmd.supportedMethods();
369 if (!pmd.data().v8Value()->IsObject() || 330 output[i]->stringified_data =
370 pmd.data().v8Value()->IsArray()) { 331 pmd.hasData() ? stringifyData(pmd.data(), exceptionState) : "";
371 exceptionState.throwTypeError( 332 if (exceptionState.hadException())
372 "Data should be a JSON-serializable object"); 333 return;
373 return; 334 }
374 } 335 }
375 336
376 v8::MaybeLocal<v8::String> value = v8::JSON::Stringify( 337 String getSelectedShippingOption(
377 pmd.data().context(), pmd.data().v8Value().As<v8::Object>()); 338 const mojom::blink::PaymentDetailsPtr& details) {
378 if (value.IsEmpty()) { 339 if (details->shipping_options.isEmpty())
379 exceptionState.throwTypeError( 340 return String();
380 "Unable to parse payment method specific data"); 341
381 return; 342 for (int i = details->shipping_options.size() - 1; i >= 0; --i) {
382 } 343 if (details->shipping_options[i]->selected)
383 stringifiedData = v8StringToWebCoreString<String>(value.ToLocalChecked(), 344 return details->shipping_options[i]->id;
384 DoNotExternalize); 345 }
385 } 346
386 methodData->append( 347 return String();
387 PaymentRequest::MethodData(pmd.supportedMethods(), stringifiedData));
388 }
389 }
390
391 String getSelectedShippingOption(const PaymentDetails& details) {
392 String result;
393 if (!details.hasShippingOptions())
394 return result;
395
396 for (int i = details.shippingOptions().size() - 1; i >= 0; --i) {
397 if (details.shippingOptions()[i].hasSelected() &&
398 details.shippingOptions()[i].selected()) {
399 return details.shippingOptions()[i].id();
400 }
401 }
402
403 return result;
404 } 348 }
405 349
406 String getValidShippingType(const String& shippingType) { 350 String getValidShippingType(const String& shippingType) {
407 static const char* const validValues[] = { 351 static const char* const validValues[] = {
408 "shipping", "delivery", "pickup", 352 "shipping", "delivery", "pickup",
409 }; 353 };
410 for (size_t i = 0; i < WTF_ARRAY_LENGTH(validValues); i++) { 354 for (size_t i = 0; i < WTF_ARRAY_LENGTH(validValues); i++) {
411 if (shippingType == validValues[i]) 355 if (shippingType == validValues[i])
412 return shippingType; 356 return shippingType;
413 } 357 }
414 return validValues[0]; 358 return validValues[0];
415 } 359 }
416 360
417 mojom::blink::PaymentDetailsPtr maybeKeepShippingOptions(
418 mojom::blink::PaymentDetailsPtr details,
419 bool keep) {
420 if (!keep)
421 details->shipping_options.resize(0);
422
423 return details;
424 }
425
426 bool allowedToUsePaymentRequest(const Frame* frame) { 361 bool allowedToUsePaymentRequest(const Frame* frame) {
427 // To determine whether a Document object |document| is allowed to use the 362 // To determine whether a Document object |document| is allowed to use the
428 // feature indicated by attribute name |allowpaymentrequest|, run these steps: 363 // feature indicated by attribute name |allowpaymentrequest|, run these steps:
429 364
430 // 1. If |document| has no browsing context, then return false. 365 // 1. If |document| has no browsing context, then return false.
431 if (!frame) 366 if (!frame)
432 return false; 367 return false;
433 368
434 // 2. If |document|'s browsing context is a top-level browsing context, then 369 // 2. If |document|'s browsing context is a top-level browsing context, then
435 // return true. 370 // return true.
436 if (frame->isMainFrame()) 371 if (frame->isMainFrame())
437 return true; 372 return true;
438 373
439 // 3. If |document|'s browsing context has a browsing context container that 374 // 3. If |document|'s browsing context has a browsing context container that
440 // is an iframe element with an |allowpaymentrequest| attribute specified, and 375 // is an iframe element with an |allowpaymentrequest| attribute specified, and
441 // whose node document is allowed to use the feature indicated by 376 // whose node document is allowed to use the feature indicated by
442 // |allowpaymentrequest|, then return true. 377 // |allowpaymentrequest|, then return true.
443 HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(frame->owner()); 378 HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(frame->owner());
444 if (ownerElement && isHTMLIFrameElement(ownerElement)) { 379 if (ownerElement && isHTMLIFrameElement(ownerElement)) {
445 HTMLIFrameElement* iframe = toHTMLIFrameElement(ownerElement); 380 HTMLIFrameElement* iframe = toHTMLIFrameElement(ownerElement);
446 if (HTMLIFrameElementPayments::from(*iframe).allowPaymentRequest(*iframe)) 381 if (HTMLIFrameElementPayments::from(*iframe).allowPaymentRequest(*iframe))
447 return allowedToUsePaymentRequest(frame->tree().parent()); 382 return allowedToUsePaymentRequest(frame->tree().parent());
448 } 383 }
449 384
450 // 4. Return false. 385 // 4. Return false.
451 return false; 386 return false;
452 } 387 }
453 388
454 WTF::Vector<mojom::blink::PaymentMethodDataPtr> ConvertPaymentMethodData(
455 const Vector<PaymentRequest::MethodData>& blinkMethods) {
456 WTF::Vector<mojom::blink::PaymentMethodDataPtr> mojoMethods(
457 blinkMethods.size());
458 for (size_t i = 0; i < blinkMethods.size(); ++i) {
459 mojoMethods[i] = mojom::blink::PaymentMethodData::New();
460 mojoMethods[i]->supported_methods =
461 WTF::Vector<WTF::String>(blinkMethods[i].supportedMethods);
462 mojoMethods[i]->stringified_data = blinkMethods[i].stringifiedData;
463 }
464 return mojoMethods;
465 }
466
467 } // namespace 389 } // namespace
468 390
469 PaymentRequest* PaymentRequest::create( 391 PaymentRequest* PaymentRequest::create(
470 ScriptState* scriptState, 392 ScriptState* scriptState,
471 const HeapVector<PaymentMethodData>& methodData, 393 const HeapVector<PaymentMethodData>& methodData,
472 const PaymentDetails& details, 394 const PaymentDetails& details,
473 ExceptionState& exceptionState) { 395 ExceptionState& exceptionState) {
474 return new PaymentRequest(scriptState, methodData, details, PaymentOptions(), 396 return new PaymentRequest(scriptState, methodData, details, PaymentOptions(),
475 exceptionState); 397 exceptionState);
476 } 398 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 V8PaymentDetails::toImpl(detailsScriptValue.isolate(), 496 V8PaymentDetails::toImpl(detailsScriptValue.isolate(),
575 detailsScriptValue.v8Value(), details, 497 detailsScriptValue.v8Value(), details,
576 exceptionState); 498 exceptionState);
577 if (exceptionState.hadException()) { 499 if (exceptionState.hadException()) {
578 m_showResolver->reject( 500 m_showResolver->reject(
579 DOMException::create(SyntaxError, exceptionState.message())); 501 DOMException::create(SyntaxError, exceptionState.message()));
580 clearResolversAndCloseMojoConnection(); 502 clearResolversAndCloseMojoConnection();
581 return; 503 return;
582 } 504 }
583 505
584 bool keepShippingOptions = validatePaymentDetails(details, exceptionState); 506 mojom::blink::PaymentDetailsPtr validatedDetails =
507 mojom::blink::PaymentDetails::New();
508 validateAndConvertPaymentDetails(details, m_options.requestShipping(),
509 validatedDetails, exceptionState);
585 if (exceptionState.hadException()) { 510 if (exceptionState.hadException()) {
586 m_showResolver->reject( 511 m_showResolver->reject(
587 DOMException::create(SyntaxError, exceptionState.message())); 512 DOMException::create(SyntaxError, exceptionState.message()));
588 clearResolversAndCloseMojoConnection(); 513 clearResolversAndCloseMojoConnection();
589 return; 514 return;
590 } 515 }
591 516
592 if (m_options.requestShipping()) { 517 if (m_options.requestShipping())
593 if (keepShippingOptions) 518 m_shippingOption = getSelectedShippingOption(validatedDetails);
594 m_shippingOption = getSelectedShippingOption(details);
595 else
596 m_shippingOption = String();
597 }
598 519
599 m_paymentProvider->UpdateWith(maybeKeepShippingOptions( 520 m_paymentProvider->UpdateWith(std::move(validatedDetails));
600 mojom::blink::PaymentDetails::From(details), keepShippingOptions));
601 } 521 }
602 522
603 void PaymentRequest::onUpdatePaymentDetailsFailure(const String& error) { 523 void PaymentRequest::onUpdatePaymentDetailsFailure(const String& error) {
604 if (m_showResolver) 524 if (m_showResolver)
605 m_showResolver->reject(DOMException::create(AbortError, error)); 525 m_showResolver->reject(DOMException::create(AbortError, error));
606 if (m_completeResolver) 526 if (m_completeResolver)
607 m_completeResolver->reject(DOMException::create(AbortError, error)); 527 m_completeResolver->reject(DOMException::create(AbortError, error));
608 clearResolversAndCloseMojoConnection(); 528 clearResolversAndCloseMojoConnection();
609 } 529 }
610 530
(...skipping 15 matching lines...) Expand all
626 PaymentRequest::PaymentRequest(ScriptState* scriptState, 546 PaymentRequest::PaymentRequest(ScriptState* scriptState,
627 const HeapVector<PaymentMethodData>& methodData, 547 const HeapVector<PaymentMethodData>& methodData,
628 const PaymentDetails& details, 548 const PaymentDetails& details,
629 const PaymentOptions& options, 549 const PaymentOptions& options,
630 ExceptionState& exceptionState) 550 ExceptionState& exceptionState)
631 : ContextLifecycleObserver(scriptState->getExecutionContext()), 551 : ContextLifecycleObserver(scriptState->getExecutionContext()),
632 ActiveScriptWrappable(this), 552 ActiveScriptWrappable(this),
633 m_options(options), 553 m_options(options),
634 m_clientBinding(this), 554 m_clientBinding(this),
635 m_completeTimer(this, &PaymentRequest::onCompleteTimeout) { 555 m_completeTimer(this, &PaymentRequest::onCompleteTimeout) {
636 Vector<MethodData> validatedMethodData; 556 Vector<mojom::blink::PaymentMethodDataPtr> validatedMethodData;
637 validateAndConvertPaymentMethodData(methodData, &validatedMethodData, 557 validateAndConvertPaymentMethodData(methodData, validatedMethodData,
638 exceptionState); 558 exceptionState);
639 if (exceptionState.hadException()) 559 if (exceptionState.hadException())
640 return; 560 return;
641 561
642 if (!scriptState->getExecutionContext()->isSecureContext()) { 562 if (!scriptState->getExecutionContext()->isSecureContext()) {
643 exceptionState.throwSecurityError("Must be in a secure context"); 563 exceptionState.throwSecurityError("Must be in a secure context");
644 return; 564 return;
645 } 565 }
646 566
647 if (!allowedToUsePaymentRequest(scriptState->domWindow()->frame())) { 567 if (!allowedToUsePaymentRequest(scriptState->domWindow()->frame())) {
648 exceptionState.throwSecurityError( 568 exceptionState.throwSecurityError(
649 "Must be in a top-level browsing context or an iframe needs to specify " 569 "Must be in a top-level browsing context or an iframe needs to specify "
650 "'allowpaymentrequest' explicitly"); 570 "'allowpaymentrequest' explicitly");
651 return; 571 return;
652 } 572 }
653 573
654 bool keepShippingOptions = validatePaymentDetails(details, exceptionState); 574 mojom::blink::PaymentDetailsPtr validatedDetails =
575 mojom::blink::PaymentDetails::New();
576 validateAndConvertPaymentDetails(details, m_options.requestShipping(),
577 validatedDetails, exceptionState);
655 if (exceptionState.hadException()) 578 if (exceptionState.hadException())
656 return; 579 return;
657 580
658 if (details.hasError() && !details.error().isEmpty()) { 581 if (!validatedDetails->error.isEmpty()) {
659 exceptionState.throwTypeError("Error value should be empty"); 582 exceptionState.throwTypeError("Error value should be empty");
660 return; 583 return;
661 } 584 }
662 585
663 if (m_options.requestShipping()) { 586 if (m_options.requestShipping()) {
664 if (keepShippingOptions) 587 m_shippingOption = getSelectedShippingOption(validatedDetails);
665 m_shippingOption = getSelectedShippingOption(details);
666 m_shippingType = getValidShippingType(m_options.shippingType()); 588 m_shippingType = getValidShippingType(m_options.shippingType());
667 } 589 }
668 590
669 scriptState->domWindow()->frame()->interfaceProvider()->getInterface( 591 scriptState->domWindow()->frame()->interfaceProvider()->getInterface(
670 mojo::GetProxy(&m_paymentProvider)); 592 mojo::GetProxy(&m_paymentProvider));
671 m_paymentProvider.set_connection_error_handler(convertToBaseCallback( 593 m_paymentProvider.set_connection_error_handler(convertToBaseCallback(
672 WTF::bind(&PaymentRequest::OnError, wrapWeakPersistent(this), 594 WTF::bind(&PaymentRequest::OnError, wrapWeakPersistent(this),
673 mojom::blink::PaymentErrorReason::UNKNOWN))); 595 mojom::blink::PaymentErrorReason::UNKNOWN)));
674 m_paymentProvider->Init( 596 m_paymentProvider->Init(m_clientBinding.CreateInterfacePtrAndBind(),
675 m_clientBinding.CreateInterfacePtrAndBind(), 597 std::move(validatedMethodData),
676 ConvertPaymentMethodData(validatedMethodData), 598 std::move(validatedDetails),
677 maybeKeepShippingOptions( 599 mojom::blink::PaymentOptions::From(m_options));
678 mojom::blink::PaymentDetails::From(details),
679 keepShippingOptions && m_options.requestShipping()),
680 mojom::blink::PaymentOptions::From(m_options));
681 } 600 }
682 601
683 void PaymentRequest::contextDestroyed() { 602 void PaymentRequest::contextDestroyed() {
684 clearResolversAndCloseMojoConnection(); 603 clearResolversAndCloseMojoConnection();
685 } 604 }
686 605
687 void PaymentRequest::OnShippingAddressChange( 606 void PaymentRequest::OnShippingAddressChange(
688 mojom::blink::PaymentAddressPtr address) { 607 mojom::blink::PaymentAddressPtr address) {
689 DCHECK(m_showResolver); 608 DCHECK(m_showResolver);
690 DCHECK(!m_completeResolver); 609 DCHECK(!m_completeResolver);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 m_completeTimer.startOneShot(completeTimeoutSeconds, BLINK_FROM_HERE); 683 m_completeTimer.startOneShot(completeTimeoutSeconds, BLINK_FROM_HERE);
765 684
766 m_showResolver->resolve(new PaymentResponse(std::move(response), this)); 685 m_showResolver->resolve(new PaymentResponse(std::move(response), this));
767 686
768 // Do not close the mojo connection here. The merchant website should call 687 // Do not close the mojo connection here. The merchant website should call
769 // PaymentResponse::complete(String), which will be forwarded over the mojo 688 // PaymentResponse::complete(String), which will be forwarded over the mojo
770 // connection to display a success or failure message to the user. 689 // connection to display a success or failure message to the user.
771 m_showResolver.clear(); 690 m_showResolver.clear();
772 } 691 }
773 692
774 void PaymentRequest::OnError(mojo::PaymentErrorReason error) { 693 void PaymentRequest::OnError(mojom::blink::PaymentErrorReason error) {
775 if (!Platform::current()) { 694 if (!Platform::current()) {
776 // TODO(rockot): Clean this up once renderer shutdown sequence is fixed. 695 // TODO(rockot): Clean this up once renderer shutdown sequence is fixed.
777 return; 696 return;
778 } 697 }
779 698
780 bool isError = false; 699 bool isError = false;
781 ExceptionCode ec = UnknownError; 700 ExceptionCode ec = UnknownError;
782 String message; 701 String message;
783 702
784 switch (error) { 703 switch (error) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 m_completeTimer.stop(); 771 m_completeTimer.stop();
853 m_completeResolver.clear(); 772 m_completeResolver.clear();
854 m_showResolver.clear(); 773 m_showResolver.clear();
855 m_abortResolver.clear(); 774 m_abortResolver.clear();
856 if (m_clientBinding.is_bound()) 775 if (m_clientBinding.is_bound())
857 m_clientBinding.Close(); 776 m_clientBinding.Close();
858 m_paymentProvider.reset(); 777 m_paymentProvider.reset();
859 } 778 }
860 779
861 } // namespace blink 780 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698