OLD | NEW |
---|---|
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" |
11 #include "bindings/modules/v8/V8PaymentDetails.h" | |
11 #include "core/EventTypeNames.h" | 12 #include "core/EventTypeNames.h" |
12 #include "core/dom/DOMException.h" | 13 #include "core/dom/DOMException.h" |
13 #include "core/dom/ExceptionCode.h" | 14 #include "core/dom/ExceptionCode.h" |
14 #include "core/events/Event.h" | 15 #include "core/events/Event.h" |
15 #include "core/events/EventQueue.h" | 16 #include "core/events/EventQueue.h" |
16 #include "modules/EventTargetModulesNames.h" | 17 #include "modules/EventTargetModulesNames.h" |
17 #include "modules/payments/PaymentItem.h" | 18 #include "modules/payments/PaymentItem.h" |
19 #include "modules/payments/PaymentRequestUpdateEvent.h" | |
18 #include "modules/payments/PaymentResponse.h" | 20 #include "modules/payments/PaymentResponse.h" |
19 #include "modules/payments/PaymentsValidators.h" | 21 #include "modules/payments/PaymentsValidators.h" |
20 #include "modules/payments/ShippingAddress.h" | 22 #include "modules/payments/ShippingAddress.h" |
21 #include "modules/payments/ShippingOption.h" | 23 #include "modules/payments/ShippingOption.h" |
22 #include "mojo/public/cpp/bindings/interface_request.h" | 24 #include "mojo/public/cpp/bindings/interface_request.h" |
23 #include "mojo/public/cpp/bindings/wtf_array.h" | 25 #include "mojo/public/cpp/bindings/wtf_array.h" |
24 #include "platform/mojo/MojoHelper.h" | 26 #include "platform/mojo/MojoHelper.h" |
25 #include "public/platform/ServiceRegistry.h" | 27 #include "public/platform/ServiceRegistry.h" |
26 #include <utility> | 28 #include <utility> |
27 | 29 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 return; | 140 return; |
139 } | 141 } |
140 | 142 |
141 if (!PaymentsValidators::isValidAmountFormat(item.amount().value(), &err orMessage)) { | 143 if (!PaymentsValidators::isValidAmountFormat(item.amount().value(), &err orMessage)) { |
142 exceptionState.throwTypeError(errorMessage); | 144 exceptionState.throwTypeError(errorMessage); |
143 return; | 145 return; |
144 } | 146 } |
145 } | 147 } |
146 } | 148 } |
147 | 149 |
150 void validatePaymentDetails(const PaymentDetails& details, ExceptionState& excep tionState) | |
151 { | |
152 if (!details.hasItems()) { | |
153 exceptionState.throwTypeError("Must specify items"); | |
154 return; | |
155 } | |
156 | |
157 if (details.items().isEmpty()) { | |
158 exceptionState.throwTypeError("Must specify at least one item"); | |
159 return; | |
160 } | |
161 | |
162 validateShippingOptionsOrPaymentItems(details.items(), exceptionState); | |
163 if (exceptionState.hadException()) | |
164 return; | |
165 | |
166 if (details.hasShippingOptions()) | |
167 validateShippingOptionsOrPaymentItems(details.shippingOptions(), excepti onState); | |
168 } | |
169 | |
148 } // namespace | 170 } // namespace |
149 | 171 |
150 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptio nState) | 172 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptio nState) |
151 { | 173 { |
152 return new PaymentRequest(scriptState, supportedMethods, details, PaymentOpt ions(), ScriptValue(), exceptionState); | 174 return new PaymentRequest(scriptState, supportedMethods, details, PaymentOpt ions(), ScriptValue(), exceptionState); |
153 } | 175 } |
154 | 176 |
155 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, ExceptionState& exceptionState) | 177 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, ExceptionState& exceptionState) |
156 { | 178 { |
157 return new PaymentRequest(scriptState, supportedMethods, details, options, S criptValue(), exceptionState); | 179 return new PaymentRequest(scriptState, supportedMethods, details, options, S criptValue(), exceptionState); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 { | 230 { |
209 if (m_completeResolver) | 231 if (m_completeResolver) |
210 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called complete() once")); | 232 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called complete() once")); |
211 | 233 |
212 m_completeResolver = ScriptPromiseResolver::create(scriptState); | 234 m_completeResolver = ScriptPromiseResolver::create(scriptState); |
213 m_paymentProvider->Complete(success); | 235 m_paymentProvider->Complete(success); |
214 | 236 |
215 return m_completeResolver->promise(); | 237 return m_completeResolver->promise(); |
216 } | 238 } |
217 | 239 |
240 void PaymentRequest::onUpdatePaymentDetails(const ScriptValue& detailsScriptValu e) | |
241 { | |
242 if (!m_showResolver || !m_paymentProvider) | |
243 return; | |
244 | |
245 PaymentDetails details; | |
246 TrackExceptionState exceptionState; | |
247 V8PaymentDetails::toImpl(detailsScriptValue.isolate(), detailsScriptValue.v8 Value(), details, exceptionState); | |
248 if (exceptionState.hadException()) { | |
249 m_showResolver->reject(DOMException::create(SyntaxError, exceptionState. message())); | |
250 cleanUp(); | |
251 return; | |
252 } | |
253 | |
254 validatePaymentDetails(details, exceptionState); | |
255 if (exceptionState.hadException()) { | |
256 m_showResolver->reject(DOMException::create(SyntaxError, exceptionState. message())); | |
257 cleanUp(); | |
258 return; | |
259 } | |
260 | |
261 // Set the currently selected option if only one option was passed. | |
262 if (details.hasShippingOptions() && details.shippingOptions().size() == 1) | |
263 m_shippingOption = details.shippingOptions().begin()->id(); | |
264 else | |
265 m_shippingOption = String(); | |
266 | |
267 m_paymentProvider->UpdateWith(mojom::blink::PaymentDetails::From(details)); | |
268 } | |
269 | |
270 void PaymentRequest::onUpdatePaymentDetailsFailure(const ScriptValue& error) | |
271 { | |
272 if (m_showResolver) | |
273 m_showResolver->reject(error); | |
274 if (m_completeResolver) | |
275 m_completeResolver->reject(error); | |
276 cleanUp(); | |
277 } | |
278 | |
218 DEFINE_TRACE(PaymentRequest) | 279 DEFINE_TRACE(PaymentRequest) |
219 { | 280 { |
220 visitor->trace(m_details); | 281 visitor->trace(m_details); |
221 visitor->trace(m_options); | 282 visitor->trace(m_options); |
222 visitor->trace(m_shippingAddress); | 283 visitor->trace(m_shippingAddress); |
223 visitor->trace(m_showResolver); | 284 visitor->trace(m_showResolver); |
224 visitor->trace(m_completeResolver); | 285 visitor->trace(m_completeResolver); |
225 EventTargetWithInlineData::trace(visitor); | 286 EventTargetWithInlineData::trace(visitor); |
226 ContextLifecycleObserver::trace(visitor); | 287 ContextLifecycleObserver::trace(visitor); |
227 } | 288 } |
228 | 289 |
229 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c onst ScriptValue& data, ExceptionState& exceptionState) | 290 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c onst ScriptValue& data, ExceptionState& exceptionState) |
230 : ContextLifecycleObserver(scriptState->getExecutionContext()) | 291 : ContextLifecycleObserver(scriptState->getExecutionContext()) |
231 , m_supportedMethods(supportedMethods) | |
232 , m_details(details) | |
233 , m_options(options) | 292 , m_options(options) |
234 , m_clientBinding(this) | 293 , m_clientBinding(this) |
235 { | 294 { |
236 // TODO(rouslan): Also check for a top-level browsing context. | 295 // TODO(rouslan): Also check for a top-level browsing context. |
237 // https://github.com/w3c/browser-payment-api/issues/2 | 296 // https://github.com/w3c/browser-payment-api/issues/2 |
238 if (!scriptState->getExecutionContext()->isSecureContext()) { | 297 if (!scriptState->getExecutionContext()->isSecureContext()) { |
239 exceptionState.throwSecurityError("Must be in a secure context"); | 298 exceptionState.throwSecurityError("Must be in a secure context"); |
240 return; | 299 return; |
241 } | 300 } |
242 | 301 |
243 if (supportedMethods.isEmpty()) { | 302 if (supportedMethods.isEmpty()) { |
244 exceptionState.throwTypeError("Must specify at least one payment method identifier"); | 303 exceptionState.throwTypeError("Must specify at least one payment method identifier"); |
245 return; | 304 return; |
246 } | 305 } |
306 m_supportedMethods = supportedMethods; | |
247 | 307 |
248 if (!details.hasItems()) { | 308 validatePaymentDetails(details, exceptionState); |
249 exceptionState.throwTypeError("Must specify items"); | |
250 return; | |
251 } | |
252 | |
253 if (details.items().isEmpty()) { | |
254 exceptionState.throwTypeError("Must specify at least one item"); | |
255 return; | |
256 } | |
257 | |
258 validateShippingOptionsOrPaymentItems(details.items(), exceptionState); | |
259 if (exceptionState.hadException()) | 309 if (exceptionState.hadException()) |
260 return; | 310 return; |
261 | 311 m_details = details; |
262 if (details.hasShippingOptions()) { | |
263 validateShippingOptionsOrPaymentItems(details.shippingOptions(), excepti onState); | |
264 if (exceptionState.hadException()) | |
265 return; | |
266 } | |
267 | 312 |
268 if (!data.isEmpty()) { | 313 if (!data.isEmpty()) { |
269 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value()); | 314 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value()); |
270 if (!value) { | 315 if (!value) { |
271 exceptionState.throwTypeError("Unable to parse payment method specif ic data"); | 316 exceptionState.throwTypeError("Unable to parse payment method specif ic data"); |
272 return; | 317 return; |
273 } | 318 } |
274 if (!value->isNull()) { | 319 if (!value->isNull()) { |
275 if (value->getType() != JSONValue::TypeObject) { | 320 if (value->getType() != JSONValue::TypeObject) { |
276 exceptionState.throwTypeError("Payment method specific data shou ld be a JSON-serializable object"); | 321 exceptionState.throwTypeError("Payment method specific data shou ld be a JSON-serializable object"); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
309 DCHECK(!m_completeResolver); | 354 DCHECK(!m_completeResolver); |
310 | 355 |
311 String errorMessage; | 356 String errorMessage; |
312 if (!PaymentsValidators::isValidShippingAddress(address, &errorMessage)) { | 357 if (!PaymentsValidators::isValidShippingAddress(address, &errorMessage)) { |
313 m_showResolver->reject(DOMException::create(SyntaxError, errorMessage)); | 358 m_showResolver->reject(DOMException::create(SyntaxError, errorMessage)); |
314 cleanUp(); | 359 cleanUp(); |
315 return; | 360 return; |
316 } | 361 } |
317 | 362 |
318 m_shippingAddress = new ShippingAddress(std::move(address)); | 363 m_shippingAddress = new ShippingAddress(std::move(address)); |
319 Event* event = Event::create(EventTypeNames::shippingaddresschange); | 364 PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::create(EventTy peNames::shippingaddresschange); |
320 event->setTarget(this); | 365 event->setTarget(this); |
321 getExecutionContext()->getEventQueue()->enqueueEvent(event); | 366 event->setPaymentDetailsUpdater(this); |
367 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); | |
368 ASSERT_UNUSED(success, success); | |
322 } | 369 } |
323 | 370 |
324 void PaymentRequest::OnShippingOptionChange(const String& shippingOptionId) | 371 void PaymentRequest::OnShippingOptionChange(const String& shippingOptionId) |
325 { | 372 { |
326 DCHECK(m_showResolver); | 373 DCHECK(m_showResolver); |
327 DCHECK(!m_completeResolver); | 374 DCHECK(!m_completeResolver); |
328 m_shippingOption = shippingOptionId; | 375 m_shippingOption = shippingOptionId; |
329 Event* event = Event::create(EventTypeNames::shippingoptionchange); | 376 PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::create(EventTy peNames::shippingoptionchange); |
330 event->setTarget(this); | 377 event->setTarget(this); |
331 getExecutionContext()->getEventQueue()->enqueueEvent(event); | 378 event->setPaymentDetailsUpdater(this); |
379 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); | |
380 ASSERT_UNUSED(success, success); | |
332 } | 381 } |
333 | 382 |
334 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response ) | 383 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response ) |
335 { | 384 { |
336 DCHECK(m_showResolver); | 385 DCHECK(m_showResolver); |
337 DCHECK(!m_completeResolver); | 386 DCHECK(!m_completeResolver); |
338 | 387 |
339 if (response->shipping_address) { | 388 if (response->shipping_address) { |
340 String errorMessage; | 389 String errorMessage; |
341 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre ss, &errorMessage)) { | 390 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre ss, &errorMessage)) { |
342 m_showResolver->reject(DOMException::create(SyntaxError, errorMessag e)); | 391 m_showResolver->reject(DOMException::create(SyntaxError, errorMessag e)); |
343 cleanUp(); | 392 cleanUp(); |
344 return; | 393 return; |
345 } | 394 } |
346 | 395 |
347 m_shippingAddress = new ShippingAddress(std::move(response->shipping_add ress)); | 396 m_shippingAddress = new ShippingAddress(std::move(response->shipping_add ress)); |
348 m_shippingOption = response->shipping_option_id; | 397 m_shippingOption = response->shipping_option_id; |
349 } | 398 } |
350 | 399 |
351 m_showResolver->resolve(new PaymentResponse(std::move(response), this)); | 400 m_showResolver->resolve(new PaymentResponse(std::move(response), this)); |
401 m_showResolver.clear(); | |
haraken
2016/05/03 12:34:35
Don't you want to call cleanUp()?
please use gerrit instead
2016/05/03 21:38:33
Should not call cleanUp() here, because the mercha
| |
352 } | 402 } |
353 | 403 |
354 void PaymentRequest::OnError() | 404 void PaymentRequest::OnError() |
355 { | 405 { |
356 if (m_completeResolver) | 406 if (m_completeResolver) |
357 m_completeResolver->reject(DOMException::create(SyntaxError, "Request ca ncelled")); | 407 m_completeResolver->reject(DOMException::create(SyntaxError, "Request ca ncelled")); |
358 if (m_showResolver) | 408 if (m_showResolver) |
359 m_showResolver->reject(DOMException::create(SyntaxError, "Request cancel led")); | 409 m_showResolver->reject(DOMException::create(SyntaxError, "Request cancel led")); |
360 cleanUp(); | 410 cleanUp(); |
361 } | 411 } |
362 | 412 |
363 void PaymentRequest::OnComplete() | 413 void PaymentRequest::OnComplete() |
364 { | 414 { |
365 DCHECK(m_completeResolver); | 415 DCHECK(m_completeResolver); |
366 m_completeResolver->resolve(); | 416 m_completeResolver->resolve(); |
367 cleanUp(); | 417 cleanUp(); |
368 } | 418 } |
369 | 419 |
370 void PaymentRequest::cleanUp() | 420 void PaymentRequest::cleanUp() |
371 { | 421 { |
372 m_completeResolver.clear(); | 422 m_completeResolver.clear(); |
373 m_showResolver.clear(); | 423 m_showResolver.clear(); |
374 if (m_clientBinding.is_bound()) | 424 if (m_clientBinding.is_bound()) |
375 m_clientBinding.Close(); | 425 m_clientBinding.Close(); |
376 m_paymentProvider.reset(); | 426 m_paymentProvider.reset(); |
377 } | 427 } |
378 | 428 |
379 } // namespace blink | 429 } // namespace blink |
OLD | NEW |