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

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

Issue 2020883002: PaymentRequest: Introduce PaymentMethodData. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 6 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"
(...skipping 17 matching lines...) Expand all
28 #include <utility> 28 #include <utility>
29 29
30 namespace mojo { 30 namespace mojo {
31 31
32 using blink::mojom::blink::CurrencyAmount; 32 using blink::mojom::blink::CurrencyAmount;
33 using blink::mojom::blink::CurrencyAmountPtr; 33 using blink::mojom::blink::CurrencyAmountPtr;
34 using blink::mojom::blink::PaymentDetails; 34 using blink::mojom::blink::PaymentDetails;
35 using blink::mojom::blink::PaymentDetailsPtr; 35 using blink::mojom::blink::PaymentDetailsPtr;
36 using blink::mojom::blink::PaymentItem; 36 using blink::mojom::blink::PaymentItem;
37 using blink::mojom::blink::PaymentItemPtr; 37 using blink::mojom::blink::PaymentItemPtr;
38 using blink::mojom::blink::PaymentMethodData;
39 using blink::mojom::blink::PaymentMethodDataPtr;
38 using blink::mojom::blink::PaymentOptions; 40 using blink::mojom::blink::PaymentOptions;
39 using blink::mojom::blink::PaymentOptionsPtr; 41 using blink::mojom::blink::PaymentOptionsPtr;
40 using blink::mojom::blink::ShippingOption; 42 using blink::mojom::blink::ShippingOption;
41 using blink::mojom::blink::ShippingOptionPtr; 43 using blink::mojom::blink::ShippingOptionPtr;
42 44
43 template <> 45 template <>
44 struct TypeConverter<CurrencyAmountPtr, blink::CurrencyAmount> { 46 struct TypeConverter<CurrencyAmountPtr, blink::CurrencyAmount> {
45 static CurrencyAmountPtr Convert(const blink::CurrencyAmount& input) 47 static CurrencyAmountPtr Convert(const blink::CurrencyAmount& input)
46 { 48 {
47 CurrencyAmountPtr output = CurrencyAmount::New(); 49 CurrencyAmountPtr output = CurrencyAmount::New();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 template <> 100 template <>
99 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> { 101 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> {
100 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input) 102 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input)
101 { 103 {
102 PaymentOptionsPtr output = PaymentOptions::New(); 104 PaymentOptionsPtr output = PaymentOptions::New();
103 output->request_shipping = input.requestShipping(); 105 output->request_shipping = input.requestShipping();
104 return output; 106 return output;
105 } 107 }
106 }; 108 };
107 109
110 template <>
111 struct TypeConverter<WTFArray<PaymentMethodDataPtr>, WTF::Vector<blink::PaymentR equest::MethodData>> {
112 static WTFArray<PaymentMethodDataPtr> Convert(const WTF::Vector<blink::Payme ntRequest::MethodData>& input)
113 {
114 WTFArray<PaymentMethodDataPtr> output(input.size());
115 for (size_t i = 0; i < input.size(); ++i) {
116 output[i] = PaymentMethodData::New();
117 output[i]->supported_methods = WTF::Vector<WTF::String>(input[i].sup portedMethods);
118 output[i]->data = input[i].stringifiedData;
119 }
120 return output;
121 }
122 };
123
108 } // namespace mojo 124 } // namespace mojo
109 125
110 namespace blink { 126 namespace blink {
111 namespace { 127 namespace {
112 128
113 // Validates ShippingOption or PaymentItem, which happen to have identical field s, 129 // Validates ShippingOption or PaymentItem, which happen to have identical field s,
114 // except for "id", which is present only in ShippingOption. 130 // except for "id", which is present only in ShippingOption.
115 template <typename T> 131 template <typename T>
116 void validateShippingOptionOrPaymentItem(const T& item, ExceptionState& exceptio nState) 132 void validateShippingOptionOrPaymentItem(const T& item, ExceptionState& exceptio nState)
117 { 133 {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 validateDisplayItems(details.displayItems(), exceptionState); 206 validateDisplayItems(details.displayItems(), exceptionState);
191 if (exceptionState.hadException()) 207 if (exceptionState.hadException())
192 return; 208 return;
193 } 209 }
194 210
195 if (details.hasShippingOptions()) { 211 if (details.hasShippingOptions()) {
196 validateShippingOptions(details.shippingOptions(), exceptionState); 212 validateShippingOptions(details.shippingOptions(), exceptionState);
197 } 213 }
198 } 214 }
199 215
216 void validateAndConvertPaymentMethodData(const HeapVector<PaymentMethodData>& pa ymentMethodData, Vector<PaymentRequest::MethodData>* methodData, ExceptionState& exceptionState)
217 {
218 if (paymentMethodData.isEmpty()) {
219 exceptionState.throwTypeError("Must specify at least one payment method identifier");
220 return;
221 }
222
223 for (const auto& pmd : paymentMethodData) {
224 if (pmd.supportedMethods().isEmpty()) {
225 exceptionState.throwTypeError("Must specify at least one payment met hod identifier");
226 return;
227 }
228
229 String stringifiedData = "";
230 if (pmd.hasData() && !pmd.data().isEmpty()) {
231 RefPtr<JSONValue> value = toJSONValue(pmd.data().context(), pmd.data ().v8Value());
232 if (!value) {
233 exceptionState.throwTypeError("Unable to parse payment method sp ecific data");
234 return;
235 }
236 if (!value->isNull()) {
237 if (value->getType() != JSONValue::TypeObject) {
238 exceptionState.throwTypeError("Data should be a JSON-seriali zable object");
239 return;
240 }
241 stringifiedData = JSONObject::cast(value)->toJSONString();
242 }
243 }
244 methodData->append(PaymentRequest::MethodData(pmd.supportedMethods(), st ringifiedData));
245 }
246 }
247
200 } // namespace 248 } // namespace
201 249
202 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptio nState) 250 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, ExceptionState& exceptionState)
203 { 251 {
204 return new PaymentRequest(scriptState, supportedMethods, details, PaymentOpt ions(), ScriptValue(), exceptionState); 252 return new PaymentRequest(scriptState, methodData, details, PaymentOptions() , exceptionState);
205 } 253 }
206 254
207 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, ExceptionState& exceptionState) 255 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, const PaymentOp tions& options, ExceptionState& exceptionState)
208 { 256 {
209 return new PaymentRequest(scriptState, supportedMethods, details, options, S criptValue(), exceptionState); 257 return new PaymentRequest(scriptState, methodData, details, options, excepti onState);
210 }
211
212 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, const ScriptValue& data, ExceptionState& exceptionState)
213 {
214 return new PaymentRequest(scriptState, supportedMethods, details, options, d ata, exceptionState);
215 } 258 }
216 259
217 PaymentRequest::~PaymentRequest() 260 PaymentRequest::~PaymentRequest()
218 { 261 {
219 } 262 }
220 263
221 ScriptPromise PaymentRequest::show(ScriptState* scriptState) 264 ScriptPromise PaymentRequest::show(ScriptState* scriptState)
222 { 265 {
223 if (m_showResolver) 266 if (m_showResolver)
224 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once")); 267 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once"));
225 268
226 if (!scriptState->domWindow() || !scriptState->domWindow()->frame()) 269 if (!scriptState->domWindow() || !scriptState->domWindow()->frame())
227 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request")); 270 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request"));
228 271
229 DCHECK(!m_paymentProvider.is_bound()); 272 DCHECK(!m_paymentProvider.is_bound());
230 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider)); 273 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider));
231 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this)))); 274 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this))));
232 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind()); 275 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
233 m_paymentProvider->Show(std::move(m_supportedMethods), mojom::blink::Payment Details::From(m_details), mojom::blink::PaymentOptions::From(m_options), m_strin gifiedData.isNull() ? "" : m_stringifiedData); 276 m_paymentProvider->Show(mojo::WTFArray<mojom::blink::PaymentMethodDataPtr>:: From(m_methodData), mojom::blink::PaymentDetails::From(m_details), mojom::blink: :PaymentOptions::From(m_options));
234
235 m_showResolver = ScriptPromiseResolver::create(scriptState); 277 m_showResolver = ScriptPromiseResolver::create(scriptState);
236 return m_showResolver->promise(); 278 return m_showResolver->promise();
237 } 279 }
238 280
239 void PaymentRequest::abort(ExceptionState& exceptionState) 281 void PaymentRequest::abort(ExceptionState& exceptionState)
240 { 282 {
241 if (!m_showResolver) { 283 if (!m_showResolver) {
242 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort"); 284 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort");
243 return; 285 return;
244 } 286 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 { 353 {
312 visitor->trace(m_details); 354 visitor->trace(m_details);
313 visitor->trace(m_options); 355 visitor->trace(m_options);
314 visitor->trace(m_shippingAddress); 356 visitor->trace(m_shippingAddress);
315 visitor->trace(m_showResolver); 357 visitor->trace(m_showResolver);
316 visitor->trace(m_completeResolver); 358 visitor->trace(m_completeResolver);
317 EventTargetWithInlineData::trace(visitor); 359 EventTargetWithInlineData::trace(visitor);
318 ContextLifecycleObserver::trace(visitor); 360 ContextLifecycleObserver::trace(visitor);
319 } 361 }
320 362
321 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c onst ScriptValue& data, ExceptionState& exceptionState) 363 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o ptions, ExceptionState& exceptionState)
322 : ContextLifecycleObserver(scriptState->getExecutionContext()) 364 : ContextLifecycleObserver(scriptState->getExecutionContext())
323 , ActiveScriptWrappable(this) 365 , ActiveScriptWrappable(this)
324 , m_options(options) 366 , m_options(options)
325 , m_clientBinding(this) 367 , m_clientBinding(this)
326 { 368 {
369 validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionStat e);
370 if (exceptionState.hadException())
371 return;
372
327 if (!scriptState->getExecutionContext()->isSecureContext()) { 373 if (!scriptState->getExecutionContext()->isSecureContext()) {
328 exceptionState.throwSecurityError("Must be in a secure context"); 374 exceptionState.throwSecurityError("Must be in a secure context");
329 return; 375 return;
330 } 376 }
331 377
332 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) { 378 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) {
333 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt"); 379 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt");
334 return; 380 return;
335 } 381 }
336 382
337 if (supportedMethods.isEmpty()) {
338 exceptionState.throwTypeError("Must specify at least one payment method identifier");
339 return;
340 }
341 m_supportedMethods = supportedMethods;
342
343 validatePaymentDetails(details, exceptionState); 383 validatePaymentDetails(details, exceptionState);
344 if (exceptionState.hadException()) 384 if (exceptionState.hadException())
345 return; 385 return;
346 m_details = details; 386 m_details = details;
347 387
348 if (!data.isEmpty()) {
349 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value());
350 if (!value) {
351 exceptionState.throwTypeError("Unable to parse payment method specif ic data");
352 return;
353 }
354 if (!value->isNull()) {
355 if (value->getType() != JSONValue::TypeObject) {
356 exceptionState.throwTypeError("Payment method specific data shou ld be a JSON-serializable object");
357 return;
358 }
359
360 RefPtr<JSONObject> jsonData = JSONObject::cast(value);
361 for (const auto& paymentMethodSpecificKeyValue : *jsonData) {
362 if (!supportedMethods.contains(paymentMethodSpecificKeyValue.key )) {
363 exceptionState.throwTypeError("'" + paymentMethodSpecificKey Value.key + "' should match one of the payment method identifiers");
364 return;
365 }
366 if (paymentMethodSpecificKeyValue.value->getType() != JSONValue: :TypeObject) {
367 exceptionState.throwTypeError("Data for '" + paymentMethodSp ecificKeyValue.key + "' should be a JSON-serializable object");
368 return;
369 }
370 }
371
372 m_stringifiedData = jsonData->toJSONString();
373 }
374 }
375
376 // Set the currently selected option if only one option is passed and shippi ng is requested. 388 // Set the currently selected option if only one option is passed and shippi ng is requested.
377 if (options.requestShipping() && details.hasShippingOptions() && details.shi ppingOptions().size() == 1) 389 if (options.requestShipping() && details.hasShippingOptions() && details.shi ppingOptions().size() == 1)
378 m_shippingOption = details.shippingOptions().begin()->id(); 390 m_shippingOption = details.shippingOptions().begin()->id();
379 } 391 }
380 392
381 void PaymentRequest::contextDestroyed() 393 void PaymentRequest::contextDestroyed()
382 { 394 {
383 clearResolversAndCloseMojoConnection(); 395 clearResolversAndCloseMojoConnection();
384 } 396 }
385 397
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 void PaymentRequest::clearResolversAndCloseMojoConnection() 490 void PaymentRequest::clearResolversAndCloseMojoConnection()
479 { 491 {
480 m_completeResolver.clear(); 492 m_completeResolver.clear();
481 m_showResolver.clear(); 493 m_showResolver.clear();
482 if (m_clientBinding.is_bound()) 494 if (m_clientBinding.is_bound())
483 m_clientBinding.Close(); 495 m_clientBinding.Close();
484 m_paymentProvider.reset(); 496 m_paymentProvider.reset();
485 } 497 }
486 498
487 } // namespace blink 499 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698