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

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

Issue 1931233002: Implement PaymentRequestUpdateEvent (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@explicit-shipping
Patch Set: Created 4 years, 7 months 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"
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698