Chromium Code Reviews| 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 |