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

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: Rebase 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698