| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 ExecutionContext* PaymentRequest::getExecutionContext() const | 224 ExecutionContext* PaymentRequest::getExecutionContext() const |
| 203 { | 225 { |
| 204 return ContextLifecycleObserver::getExecutionContext(); | 226 return ContextLifecycleObserver::getExecutionContext(); |
| 205 } | 227 } |
| 206 | 228 |
| 207 ScriptPromise PaymentRequest::complete(ScriptState* scriptState, bool success) | 229 ScriptPromise PaymentRequest::complete(ScriptState* scriptState, bool success) |
| 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 // The payment provider should respond in PaymentRequest::OnComplete(). |
| 213 m_paymentProvider->Complete(success); | 235 m_paymentProvider->Complete(success); |
| 214 | 236 |
| 237 m_completeResolver = ScriptPromiseResolver::create(scriptState); |
| 215 return m_completeResolver->promise(); | 238 return m_completeResolver->promise(); |
| 216 } | 239 } |
| 217 | 240 |
| 241 void PaymentRequest::onUpdatePaymentDetails(const ScriptValue& detailsScriptValu
e) |
| 242 { |
| 243 if (!m_showResolver || !m_paymentProvider) |
| 244 return; |
| 245 |
| 246 PaymentDetails details; |
| 247 TrackExceptionState exceptionState; |
| 248 V8PaymentDetails::toImpl(detailsScriptValue.isolate(), detailsScriptValue.v8
Value(), details, exceptionState); |
| 249 if (exceptionState.hadException()) { |
| 250 m_showResolver->reject(DOMException::create(SyntaxError, exceptionState.
message())); |
| 251 stopResolversAndCloseMojoConnection(); |
| 252 return; |
| 253 } |
| 254 |
| 255 validatePaymentDetails(details, exceptionState); |
| 256 if (exceptionState.hadException()) { |
| 257 m_showResolver->reject(DOMException::create(SyntaxError, exceptionState.
message())); |
| 258 stopResolversAndCloseMojoConnection(); |
| 259 return; |
| 260 } |
| 261 |
| 262 // Set the currently selected option if only one option was passed. |
| 263 if (details.hasShippingOptions() && details.shippingOptions().size() == 1) |
| 264 m_shippingOption = details.shippingOptions().begin()->id(); |
| 265 else |
| 266 m_shippingOption = String(); |
| 267 |
| 268 m_paymentProvider->UpdateWith(mojom::blink::PaymentDetails::From(details)); |
| 269 } |
| 270 |
| 271 void PaymentRequest::onUpdatePaymentDetailsFailure(const ScriptValue& error) |
| 272 { |
| 273 if (m_showResolver) |
| 274 m_showResolver->reject(error); |
| 275 if (m_completeResolver) |
| 276 m_completeResolver->reject(error); |
| 277 stopResolversAndCloseMojoConnection(); |
| 278 } |
| 279 |
| 218 DEFINE_TRACE(PaymentRequest) | 280 DEFINE_TRACE(PaymentRequest) |
| 219 { | 281 { |
| 220 visitor->trace(m_details); | 282 visitor->trace(m_details); |
| 221 visitor->trace(m_options); | 283 visitor->trace(m_options); |
| 222 visitor->trace(m_shippingAddress); | 284 visitor->trace(m_shippingAddress); |
| 223 visitor->trace(m_showResolver); | 285 visitor->trace(m_showResolver); |
| 224 visitor->trace(m_completeResolver); | 286 visitor->trace(m_completeResolver); |
| 225 EventTargetWithInlineData::trace(visitor); | 287 EventTargetWithInlineData::trace(visitor); |
| 226 ContextLifecycleObserver::trace(visitor); | 288 ContextLifecycleObserver::trace(visitor); |
| 227 } | 289 } |
| 228 | 290 |
| 229 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s
upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c
onst ScriptValue& data, ExceptionState& exceptionState) | 291 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()) | 292 : ContextLifecycleObserver(scriptState->getExecutionContext()) |
| 231 , m_supportedMethods(supportedMethods) | |
| 232 , m_details(details) | |
| 233 , m_options(options) | 293 , m_options(options) |
| 234 , m_clientBinding(this) | 294 , m_clientBinding(this) |
| 235 { | 295 { |
| 236 // TODO(rouslan): Also check for a top-level browsing context. | 296 // TODO(rouslan): Also check for a top-level browsing context. |
| 237 // https://github.com/w3c/browser-payment-api/issues/2 | 297 // https://github.com/w3c/browser-payment-api/issues/2 |
| 238 if (!scriptState->getExecutionContext()->isSecureContext()) { | 298 if (!scriptState->getExecutionContext()->isSecureContext()) { |
| 239 exceptionState.throwSecurityError("Must be in a secure context"); | 299 exceptionState.throwSecurityError("Must be in a secure context"); |
| 240 return; | 300 return; |
| 241 } | 301 } |
| 242 | 302 |
| 243 if (supportedMethods.isEmpty()) { | 303 if (supportedMethods.isEmpty()) { |
| 244 exceptionState.throwTypeError("Must specify at least one payment method
identifier"); | 304 exceptionState.throwTypeError("Must specify at least one payment method
identifier"); |
| 245 return; | 305 return; |
| 246 } | 306 } |
| 307 m_supportedMethods = supportedMethods; |
| 247 | 308 |
| 248 if (!details.hasItems()) { | 309 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()) | 310 if (exceptionState.hadException()) |
| 260 return; | 311 return; |
| 261 | 312 m_details = details; |
| 262 if (details.hasShippingOptions()) { | |
| 263 validateShippingOptionsOrPaymentItems(details.shippingOptions(), excepti
onState); | |
| 264 if (exceptionState.hadException()) | |
| 265 return; | |
| 266 } | |
| 267 | 313 |
| 268 if (!data.isEmpty()) { | 314 if (!data.isEmpty()) { |
| 269 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value()); | 315 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value()); |
| 270 if (!value) { | 316 if (!value) { |
| 271 exceptionState.throwTypeError("Unable to parse payment method specif
ic data"); | 317 exceptionState.throwTypeError("Unable to parse payment method specif
ic data"); |
| 272 return; | 318 return; |
| 273 } | 319 } |
| 274 if (!value->isNull()) { | 320 if (!value->isNull()) { |
| 275 if (value->getType() != JSONValue::TypeObject) { | 321 if (value->getType() != JSONValue::TypeObject) { |
| 276 exceptionState.throwTypeError("Payment method specific data shou
ld be a JSON-serializable object"); | 322 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); | 355 DCHECK(!m_completeResolver); |
| 310 | 356 |
| 311 String errorMessage; | 357 String errorMessage; |
| 312 if (!PaymentsValidators::isValidShippingAddress(address, &errorMessage)) { | 358 if (!PaymentsValidators::isValidShippingAddress(address, &errorMessage)) { |
| 313 m_showResolver->reject(DOMException::create(SyntaxError, errorMessage)); | 359 m_showResolver->reject(DOMException::create(SyntaxError, errorMessage)); |
| 314 stopResolversAndCloseMojoConnection(); | 360 stopResolversAndCloseMojoConnection(); |
| 315 return; | 361 return; |
| 316 } | 362 } |
| 317 | 363 |
| 318 m_shippingAddress = new ShippingAddress(std::move(address)); | 364 m_shippingAddress = new ShippingAddress(std::move(address)); |
| 319 Event* event = Event::create(EventTypeNames::shippingaddresschange); | 365 PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::create(EventTy
peNames::shippingaddresschange); |
| 320 event->setTarget(this); | 366 event->setTarget(this); |
| 321 getExecutionContext()->getEventQueue()->enqueueEvent(event); | 367 event->setPaymentDetailsUpdater(this); |
| 368 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); |
| 369 DCHECK(success); |
| 370 ALLOW_UNUSED_LOCAL(success); |
| 322 } | 371 } |
| 323 | 372 |
| 324 void PaymentRequest::OnShippingOptionChange(const String& shippingOptionId) | 373 void PaymentRequest::OnShippingOptionChange(const String& shippingOptionId) |
| 325 { | 374 { |
| 326 DCHECK(m_showResolver); | 375 DCHECK(m_showResolver); |
| 327 DCHECK(!m_completeResolver); | 376 DCHECK(!m_completeResolver); |
| 328 m_shippingOption = shippingOptionId; | 377 m_shippingOption = shippingOptionId; |
| 329 Event* event = Event::create(EventTypeNames::shippingoptionchange); | 378 PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::create(EventTy
peNames::shippingoptionchange); |
| 330 event->setTarget(this); | 379 event->setTarget(this); |
| 331 getExecutionContext()->getEventQueue()->enqueueEvent(event); | 380 event->setPaymentDetailsUpdater(this); |
| 381 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); |
| 382 DCHECK(success); |
| 383 ALLOW_UNUSED_LOCAL(success); |
| 332 } | 384 } |
| 333 | 385 |
| 334 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response
) | 386 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response
) |
| 335 { | 387 { |
| 336 DCHECK(m_showResolver); | 388 DCHECK(m_showResolver); |
| 337 DCHECK(!m_completeResolver); | 389 DCHECK(!m_completeResolver); |
| 338 | 390 |
| 339 if (response->shipping_address) { | 391 if (response->shipping_address) { |
| 340 String errorMessage; | 392 String errorMessage; |
| 341 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre
ss, &errorMessage)) { | 393 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre
ss, &errorMessage)) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 if (m_showResolver) | 433 if (m_showResolver) |
| 382 m_showResolver->stop(); | 434 m_showResolver->stop(); |
| 383 m_showResolver.clear(); | 435 m_showResolver.clear(); |
| 384 | 436 |
| 385 if (m_clientBinding.is_bound()) | 437 if (m_clientBinding.is_bound()) |
| 386 m_clientBinding.Close(); | 438 m_clientBinding.Close(); |
| 387 m_paymentProvider.reset(); | 439 m_paymentProvider.reset(); |
| 388 } | 440 } |
| 389 | 441 |
| 390 } // namespace blink | 442 } // namespace blink |
| OLD | NEW |