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

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 21 matching lines...) Expand all
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::PaymentOptions; 38 using blink::mojom::blink::PaymentOptions;
39 using blink::mojom::blink::PaymentOptionsPtr; 39 using blink::mojom::blink::PaymentOptionsPtr;
40 using blink::mojom::blink::ShippingOption; 40 using blink::mojom::blink::ShippingOption;
41 using blink::mojom::blink::ShippingOptionPtr; 41 using blink::mojom::blink::ShippingOptionPtr;
42 using blink::mojom::blink::PaymentMethodData;
43 using blink::mojom::blink::PaymentMethodDataPtr;
please use gerrit instead 2016/05/29 19:57:12 Sort alphabetically.
zino 2016/06/01 17:43:46 Done.
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();
48 output->currency_code = input.currency(); 50 output->currency_code = input.currency();
49 output->value = input.value(); 51 output->value = input.value();
50 return output; 52 return output;
51 } 53 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 template <> 93 template <>
92 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> { 94 struct TypeConverter<PaymentOptionsPtr, blink::PaymentOptions> {
93 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input) 95 static PaymentOptionsPtr Convert(const blink::PaymentOptions& input)
94 { 96 {
95 PaymentOptionsPtr output = PaymentOptions::New(); 97 PaymentOptionsPtr output = PaymentOptions::New();
96 output->request_shipping = input.requestShipping(); 98 output->request_shipping = input.requestShipping();
97 return output; 99 return output;
98 } 100 }
99 }; 101 };
100 102
103 template <>
104 struct TypeConverter<PaymentMethodDataPtr, blink::PaymentMethodData> {
105 static PaymentMethodDataPtr Convert(const blink::PaymentMethodData& input)
106 {
107 PaymentMethodDataPtr output = PaymentMethodData::New();
108 output->supported_methods = Vector<WTF::String>(input.supportedMethods() );
please use gerrit instead 2016/05/29 19:57:12 output->supported_methods = mojom::WTFArray<String
zino 2016/06/01 17:43:46 I'm not sure but it's better to avoid unnecessary
109 if (!input.data().isEmpty())
please use gerrit instead 2016/05/29 19:57:12 if (input.hasData() && !input.data().isEmpty())
zino 2016/06/01 17:43:46 Done.
110 output->data = blink::JSONObject::cast(blink::toJSONValue(input.data ().context(), input.data().v8Value()))->toJSONString();
111 return output;
112 }
113 };
114
101 } // namespace mojo 115 } // namespace mojo
102 116
103 namespace blink { 117 namespace blink {
104 namespace { 118 namespace {
105 119
106 // Validates ShippingOption and PaymentItem dictionaries, which happen to have i dentical fields. 120 // Validates ShippingOption and PaymentItem dictionaries, which happen to have i dentical fields.
107 // except for "id", which is present only in ShippingOption. 121 // except for "id", which is present only in ShippingOption.
108 template <typename T> 122 template <typename T>
109 void validateShippingOptionsOrPaymentItems(HeapVector<T> items, ExceptionState& exceptionState) 123 void validateShippingOptionsOrPaymentItems(HeapVector<T> items, ExceptionState& exceptionState)
110 { 124 {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 validateShippingOptionsOrPaymentItems(details.items(), exceptionState); 181 validateShippingOptionsOrPaymentItems(details.items(), exceptionState);
168 if (exceptionState.hadException()) 182 if (exceptionState.hadException())
169 return; 183 return;
170 184
171 if (details.hasShippingOptions()) { 185 if (details.hasShippingOptions()) {
172 validateShippingOptionsOrPaymentItems(details.shippingOptions(), excepti onState); 186 validateShippingOptionsOrPaymentItems(details.shippingOptions(), excepti onState);
173 validateShippingOptionsIds(details.shippingOptions(), exceptionState); 187 validateShippingOptionsIds(details.shippingOptions(), exceptionState);
174 } 188 }
175 } 189 }
176 190
191 void validatePaymentMethodData(const HeapVector<PaymentMethodData>& methodData, ExceptionState& exceptionState)
192 {
193 for (const auto& md : methodData) {
194 if (md.supportedMethods().isEmpty()) {
195 exceptionState.throwTypeError("Must specify at least one payment met hod identifier");
196 return;
197 }
198
199 if (!md.data().isEmpty()) {
200 RefPtr<JSONValue> value = toJSONValue(md.data().context(), md.data() .v8Value());
201 if (!value) {
202 exceptionState.throwTypeError("Unable to parse payment method sp ecific data");
203 return;
204 }
205 if (!value->isNull() && value->getType() != JSONValue::TypeObject) {
206 exceptionState.throwTypeError("Data should be a JSON-serializabl e object");
207 return;
208 }
209 }
210 }
211 }
212
177 } // namespace 213 } // namespace
178 214
179 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptio nState) 215 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, ExceptionState& exceptionState)
180 { 216 {
181 return new PaymentRequest(scriptState, supportedMethods, details, PaymentOpt ions(), ScriptValue(), exceptionState); 217 return new PaymentRequest(scriptState, methodData, details, PaymentOptions() , exceptionState);
182 } 218 }
183 219
184 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, ExceptionState& exceptionState) 220 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, const PaymentOp tions& options, ExceptionState& exceptionState)
185 { 221 {
186 return new PaymentRequest(scriptState, supportedMethods, details, options, S criptValue(), exceptionState); 222 return new PaymentRequest(scriptState, methodData, details, options, excepti onState);
187 }
188
189 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, const ScriptValue& data, ExceptionState& exceptionState)
190 {
191 return new PaymentRequest(scriptState, supportedMethods, details, options, d ata, exceptionState);
192 } 223 }
193 224
194 PaymentRequest::~PaymentRequest() 225 PaymentRequest::~PaymentRequest()
195 { 226 {
196 } 227 }
197 228
198 ScriptPromise PaymentRequest::show(ScriptState* scriptState) 229 ScriptPromise PaymentRequest::show(ScriptState* scriptState)
199 { 230 {
200 if (m_showResolver) 231 if (m_showResolver)
201 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once")); 232 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once"));
202 233
203 if (!scriptState->domWindow() || !scriptState->domWindow()->frame()) 234 if (!scriptState->domWindow() || !scriptState->domWindow()->frame())
204 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request")); 235 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request"));
205 236
206 DCHECK(!m_paymentProvider.is_bound()); 237 DCHECK(!m_paymentProvider.is_bound());
207 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider)); 238 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider));
208 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this)))); 239 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this))));
209 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind()); 240 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
210 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); 241 m_paymentProvider->Show(mojo::WTFArray<blink::mojom::blink::PaymentMethodDat aPtr>::From(m_methodData), mojom::blink::PaymentDetails::From(m_details), mojom: :blink::PaymentOptions::From(m_options));
211
212 m_showResolver = ScriptPromiseResolver::create(scriptState); 242 m_showResolver = ScriptPromiseResolver::create(scriptState);
213 return m_showResolver->promise(); 243 return m_showResolver->promise();
214 } 244 }
215 245
216 void PaymentRequest::abort(ExceptionState& exceptionState) 246 void PaymentRequest::abort(ExceptionState& exceptionState)
217 { 247 {
218 if (!m_showResolver) { 248 if (!m_showResolver) {
219 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort"); 249 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort");
220 return; 250 return;
221 } 251 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 { 309 {
280 if (m_showResolver) 310 if (m_showResolver)
281 m_showResolver->reject(error); 311 m_showResolver->reject(error);
282 if (m_completeResolver) 312 if (m_completeResolver)
283 m_completeResolver->reject(error); 313 m_completeResolver->reject(error);
284 clearResolversAndCloseMojoConnection(); 314 clearResolversAndCloseMojoConnection();
285 } 315 }
286 316
287 DEFINE_TRACE(PaymentRequest) 317 DEFINE_TRACE(PaymentRequest)
288 { 318 {
319 visitor->trace(m_methodData);
289 visitor->trace(m_details); 320 visitor->trace(m_details);
290 visitor->trace(m_options); 321 visitor->trace(m_options);
291 visitor->trace(m_shippingAddress); 322 visitor->trace(m_shippingAddress);
292 visitor->trace(m_showResolver); 323 visitor->trace(m_showResolver);
293 visitor->trace(m_completeResolver); 324 visitor->trace(m_completeResolver);
294 EventTargetWithInlineData::trace(visitor); 325 EventTargetWithInlineData::trace(visitor);
295 ContextLifecycleObserver::trace(visitor); 326 ContextLifecycleObserver::trace(visitor);
296 } 327 }
297 328
298 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c onst ScriptValue& data, ExceptionState& exceptionState) 329 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o ptions, ExceptionState& exceptionState)
299 : ContextLifecycleObserver(scriptState->getExecutionContext()) 330 : ContextLifecycleObserver(scriptState->getExecutionContext())
300 , ActiveScriptWrappable(this) 331 , ActiveScriptWrappable(this)
301 , m_options(options) 332 , m_options(options)
302 , m_clientBinding(this) 333 , m_clientBinding(this)
303 { 334 {
335 if (methodData.isEmpty()) {
please use gerrit instead 2016/05/29 19:57:12 This block should be inside of validatePaymentMeth
zino 2016/06/01 17:43:46 Done.
336 exceptionState.throwTypeError("Must specify at least one payment method identifier");
337 return;
338 }
339
340 validatePaymentMethodData(methodData, exceptionState);
341 if (exceptionState.hadException())
342 return;
343 m_methodData = methodData;
344
304 // TODO(rouslan): Also check for a top-level browsing context. 345 // TODO(rouslan): Also check for a top-level browsing context.
305 // https://github.com/w3c/browser-payment-api/issues/2 346 // https://github.com/w3c/browser-payment-api/issues/2
306 if (!scriptState->getExecutionContext()->isSecureContext()) { 347 if (!scriptState->getExecutionContext()->isSecureContext()) {
307 exceptionState.throwSecurityError("Must be in a secure context"); 348 exceptionState.throwSecurityError("Must be in a secure context");
308 return; 349 return;
309 } 350 }
310 351
311 if (supportedMethods.isEmpty()) {
312 exceptionState.throwTypeError("Must specify at least one payment method identifier");
313 return;
314 }
315 m_supportedMethods = supportedMethods;
316
317 validatePaymentDetails(details, exceptionState); 352 validatePaymentDetails(details, exceptionState);
318 if (exceptionState.hadException()) 353 if (exceptionState.hadException())
319 return; 354 return;
320 m_details = details; 355 m_details = details;
321 356
322 if (!data.isEmpty()) {
323 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value());
324 if (!value) {
325 exceptionState.throwTypeError("Unable to parse payment method specif ic data");
326 return;
327 }
328 if (!value->isNull()) {
329 if (value->getType() != JSONValue::TypeObject) {
330 exceptionState.throwTypeError("Payment method specific data shou ld be a JSON-serializable object");
331 return;
332 }
333
334 RefPtr<JSONObject> jsonData = JSONObject::cast(value);
335 for (const auto& paymentMethodSpecificKeyValue : *jsonData) {
336 if (!supportedMethods.contains(paymentMethodSpecificKeyValue.key )) {
337 exceptionState.throwTypeError("'" + paymentMethodSpecificKey Value.key + "' should match one of the payment method identifiers");
338 return;
339 }
340 if (paymentMethodSpecificKeyValue.value->getType() != JSONValue: :TypeObject) {
341 exceptionState.throwTypeError("Data for '" + paymentMethodSp ecificKeyValue.key + "' should be a JSON-serializable object");
342 return;
343 }
344 }
345
346 m_stringifiedData = jsonData->toJSONString();
347 }
348 }
349
350 // Set the currently selected option if only one option is passed and shippi ng is requested. 357 // Set the currently selected option if only one option is passed and shippi ng is requested.
351 if (options.requestShipping() && details.hasShippingOptions() && details.shi ppingOptions().size() == 1) 358 if (options.requestShipping() && details.hasShippingOptions() && details.shi ppingOptions().size() == 1)
352 m_shippingOption = details.shippingOptions().begin()->id(); 359 m_shippingOption = details.shippingOptions().begin()->id();
353 } 360 }
354 361
355 void PaymentRequest::contextDestroyed() 362 void PaymentRequest::contextDestroyed()
356 { 363 {
357 clearResolversAndCloseMojoConnection(); 364 clearResolversAndCloseMojoConnection();
358 } 365 }
359 366
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 void PaymentRequest::clearResolversAndCloseMojoConnection() 447 void PaymentRequest::clearResolversAndCloseMojoConnection()
441 { 448 {
442 m_completeResolver.clear(); 449 m_completeResolver.clear();
443 m_showResolver.clear(); 450 m_showResolver.clear();
444 if (m_clientBinding.is_bound()) 451 if (m_clientBinding.is_bound())
445 m_clientBinding.Close(); 452 m_clientBinding.Close();
446 m_paymentProvider.reset(); 453 m_paymentProvider.reset();
447 } 454 }
448 455
449 } // namespace blink 456 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698