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

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: 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 template <> 101 template <>
100 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> { 102 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> {
101 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input) 103 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input)
102 { 104 {
103 PaymentOptionsPtr output = PaymentOptions::New(); 105 PaymentOptionsPtr output = PaymentOptions::New();
104 output->request_shipping = input.requestShipping(); 106 output->request_shipping = input.requestShipping();
105 return output; 107 return output;
106 } 108 }
107 }; 109 };
108 110
111 template <>
112 struct TypeConverter<WTFArray<PaymentMethodDataPtr>, WTF::Vector<blink::PaymentR equest::MethodData>> {
113 static WTFArray<PaymentMethodDataPtr> Convert(const WTF::Vector<blink::Payme ntRequest::MethodData>& input)
114 {
115 WTFArray<PaymentMethodDataPtr> output(input.size());
116 for (size_t i = 0; i < input.size(); ++i) {
117 output[i] = PaymentMethodData::New();
118 output[i]->supported_methods = WTF::Vector<WTF::String>(input[i].sup portedMethods);
119 output[i]->stringified_data = input[i].stringifiedData;
120 }
121 return output;
122 }
123 };
124
109 } // namespace mojo 125 } // namespace mojo
110 126
111 namespace blink { 127 namespace blink {
112 namespace { 128 namespace {
113 129
114 // Validates ShippingOption or PaymentItem, which happen to have identical field s, 130 // Validates ShippingOption or PaymentItem, which happen to have identical field s,
115 // except for "id", which is present only in ShippingOption. 131 // except for "id", which is present only in ShippingOption.
116 template <typename T> 132 template <typename T>
117 void validateShippingOptionOrPaymentItem(const T& item, ExceptionState& exceptio nState) 133 void validateShippingOptionOrPaymentItem(const T& item, ExceptionState& exceptio nState)
118 { 134 {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 validateDisplayItems(details.displayItems(), exceptionState); 207 validateDisplayItems(details.displayItems(), exceptionState);
192 if (exceptionState.hadException()) 208 if (exceptionState.hadException())
193 return; 209 return;
194 } 210 }
195 211
196 if (details.hasShippingOptions()) { 212 if (details.hasShippingOptions()) {
197 validateShippingOptions(details.shippingOptions(), exceptionState); 213 validateShippingOptions(details.shippingOptions(), exceptionState);
198 } 214 }
199 } 215 }
200 216
217 void validateAndConvertPaymentMethodData(const HeapVector<PaymentMethodData>& pa ymentMethodData, Vector<PaymentRequest::MethodData>* methodData, ExceptionState& exceptionState)
218 {
219 if (paymentMethodData.isEmpty()) {
220 exceptionState.throwTypeError("Must specify at least one payment method identifier");
221 return;
222 }
223
224 for (const auto& pmd : paymentMethodData) {
225 if (pmd.supportedMethods().isEmpty()) {
226 exceptionState.throwTypeError("Must specify at least one payment met hod identifier");
227 return;
228 }
229
230 String stringifiedData = "";
231 if (pmd.hasData() && !pmd.data().isEmpty()) {
232 RefPtr<JSONValue> value = toJSONValue(pmd.data().context(), pmd.data ().v8Value());
233 if (!value) {
234 exceptionState.throwTypeError("Unable to parse payment method sp ecific data");
235 return;
236 }
237 if (!value->isNull()) {
238 if (value->getType() != JSONValue::TypeObject) {
239 exceptionState.throwTypeError("Data should be a JSON-seriali zable object");
240 return;
241 }
242 stringifiedData = JSONObject::cast(value)->toJSONString();
243 }
244 }
245 methodData->append(PaymentRequest::MethodData(pmd.supportedMethods(), st ringifiedData));
246 }
247 }
248
201 String getSelectedShippingOption(const PaymentDetails& details) 249 String getSelectedShippingOption(const PaymentDetails& details)
202 { 250 {
203 String result; 251 String result;
204 if (!details.hasShippingOptions()) 252 if (!details.hasShippingOptions())
205 return result; 253 return result;
206 254
207 for (size_t i = 0; i < details.shippingOptions().size(); ++i) { 255 for (size_t i = 0; i < details.shippingOptions().size(); ++i) {
208 if (details.shippingOptions()[i].hasSelected() && details.shippingOption s()[i].selected()) { 256 if (details.shippingOptions()[i].hasSelected() && details.shippingOption s()[i].selected()) {
209 result = details.shippingOptions()[i].id(); 257 result = details.shippingOptions()[i].id();
210 } 258 }
211 } 259 }
212 260
213 return result; 261 return result;
214 } 262 }
215 263
216 } // namespace 264 } // namespace
217 265
218 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptio nState) 266 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, ExceptionState& exceptionState)
219 { 267 {
220 return new PaymentRequest(scriptState, supportedMethods, details, PaymentOpt ions(), ScriptValue(), exceptionState); 268 return new PaymentRequest(scriptState, methodData, details, PaymentOptions() , exceptionState);
221 } 269 }
222 270
223 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, ExceptionState& exceptionState) 271 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, const PaymentOp tions& options, ExceptionState& exceptionState)
224 { 272 {
225 return new PaymentRequest(scriptState, supportedMethods, details, options, S criptValue(), exceptionState); 273 return new PaymentRequest(scriptState, methodData, details, options, excepti onState);
226 }
227
228 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, const ScriptValue& data, ExceptionState& exceptionState)
229 {
230 return new PaymentRequest(scriptState, supportedMethods, details, options, d ata, exceptionState);
231 } 274 }
232 275
233 PaymentRequest::~PaymentRequest() 276 PaymentRequest::~PaymentRequest()
234 { 277 {
235 } 278 }
236 279
237 ScriptPromise PaymentRequest::show(ScriptState* scriptState) 280 ScriptPromise PaymentRequest::show(ScriptState* scriptState)
238 { 281 {
239 if (m_showResolver) 282 if (m_showResolver)
240 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once")); 283 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once"));
241 284
242 if (!scriptState->domWindow() || !scriptState->domWindow()->frame()) 285 if (!scriptState->domWindow() || !scriptState->domWindow()->frame())
243 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request")); 286 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request"));
244 287
245 DCHECK(!m_paymentProvider.is_bound()); 288 DCHECK(!m_paymentProvider.is_bound());
246 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider)); 289 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider));
247 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this)))); 290 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this))));
248 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind()); 291 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
249 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); 292 m_paymentProvider->Show(mojo::WTFArray<mojom::blink::PaymentMethodDataPtr>:: From(m_methodData), mojom::blink::PaymentDetails::From(m_details), mojom::blink: :PaymentOptions::From(m_options));
250 293
251 m_showResolver = ScriptPromiseResolver::create(scriptState); 294 m_showResolver = ScriptPromiseResolver::create(scriptState);
252 return m_showResolver->promise(); 295 return m_showResolver->promise();
253 } 296 }
254 297
255 void PaymentRequest::abort(ExceptionState& exceptionState) 298 void PaymentRequest::abort(ExceptionState& exceptionState)
256 { 299 {
257 if (!m_showResolver) { 300 if (!m_showResolver) {
258 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort"); 301 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort");
259 return; 302 return;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 { 367 {
325 visitor->trace(m_details); 368 visitor->trace(m_details);
326 visitor->trace(m_options); 369 visitor->trace(m_options);
327 visitor->trace(m_shippingAddress); 370 visitor->trace(m_shippingAddress);
328 visitor->trace(m_showResolver); 371 visitor->trace(m_showResolver);
329 visitor->trace(m_completeResolver); 372 visitor->trace(m_completeResolver);
330 EventTargetWithInlineData::trace(visitor); 373 EventTargetWithInlineData::trace(visitor);
331 ContextLifecycleObserver::trace(visitor); 374 ContextLifecycleObserver::trace(visitor);
332 } 375 }
333 376
334 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c onst ScriptValue& data, ExceptionState& exceptionState) 377 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o ptions, ExceptionState& exceptionState)
335 : ContextLifecycleObserver(scriptState->getExecutionContext()) 378 : ContextLifecycleObserver(scriptState->getExecutionContext())
336 , ActiveScriptWrappable(this) 379 , ActiveScriptWrappable(this)
337 , m_options(options) 380 , m_options(options)
338 , m_clientBinding(this) 381 , m_clientBinding(this)
339 { 382 {
383 validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionStat e);
384 if (exceptionState.hadException())
385 return;
386
340 if (!scriptState->getExecutionContext()->isSecureContext()) { 387 if (!scriptState->getExecutionContext()->isSecureContext()) {
341 exceptionState.throwSecurityError("Must be in a secure context"); 388 exceptionState.throwSecurityError("Must be in a secure context");
342 return; 389 return;
343 } 390 }
344 391
345 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) { 392 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) {
346 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt"); 393 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt");
347 return; 394 return;
348 } 395 }
349 396
350 if (supportedMethods.isEmpty()) {
351 exceptionState.throwTypeError("Must specify at least one payment method identifier");
352 return;
353 }
354 m_supportedMethods = supportedMethods;
355
356 validatePaymentDetails(details, exceptionState); 397 validatePaymentDetails(details, exceptionState);
357 if (exceptionState.hadException()) 398 if (exceptionState.hadException())
358 return; 399 return;
359 m_details = details; 400 m_details = details;
360 401
361 if (!data.isEmpty()) {
362 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value());
363 if (!value) {
364 exceptionState.throwTypeError("Unable to parse payment method specif ic data");
365 return;
366 }
367 if (!value->isNull()) {
368 if (value->getType() != JSONValue::TypeObject) {
369 exceptionState.throwTypeError("Payment method specific data shou ld be a JSON-serializable object");
370 return;
371 }
372
373 RefPtr<JSONObject> jsonData = JSONObject::cast(value);
374 for (const auto& paymentMethodSpecificKeyValue : *jsonData) {
375 if (!supportedMethods.contains(paymentMethodSpecificKeyValue.key )) {
376 exceptionState.throwTypeError("'" + paymentMethodSpecificKey Value.key + "' should match one of the payment method identifiers");
377 return;
378 }
379 if (paymentMethodSpecificKeyValue.value->getType() != JSONValue: :TypeObject) {
380 exceptionState.throwTypeError("Data for '" + paymentMethodSp ecificKeyValue.key + "' should be a JSON-serializable object");
381 return;
382 }
383 }
384
385 m_stringifiedData = jsonData->toJSONString();
386 }
387 }
388
389 if (m_options.requestShipping()) 402 if (m_options.requestShipping())
390 m_shippingOption = getSelectedShippingOption(details); 403 m_shippingOption = getSelectedShippingOption(details);
391 } 404 }
392 405
393 void PaymentRequest::contextDestroyed() 406 void PaymentRequest::contextDestroyed()
394 { 407 {
395 clearResolversAndCloseMojoConnection(); 408 clearResolversAndCloseMojoConnection();
396 } 409 }
397 410
398 bool PaymentRequest::hasPendingActivity() const 411 bool PaymentRequest::hasPendingActivity() const
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 void PaymentRequest::clearResolversAndCloseMojoConnection() 503 void PaymentRequest::clearResolversAndCloseMojoConnection()
491 { 504 {
492 m_completeResolver.clear(); 505 m_completeResolver.clear();
493 m_showResolver.clear(); 506 m_showResolver.clear();
494 if (m_clientBinding.is_bound()) 507 if (m_clientBinding.is_bound())
495 m_clientBinding.Close(); 508 m_clientBinding.Close();
496 m_paymentProvider.reset(); 509 m_paymentProvider.reset();
497 } 510 }
498 511
499 } // namespace blink 512 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698