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

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 43 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> {
Marijn Kruisselbrink 2016/06/01 18:20:24 I believe these days typemaps and StructTraits are
please use gerrit instead 2016/06/01 19:20:21 Let's make TypeConverters into typemaps or StrucTr
105 static PaymentMethodDataPtr Convert(const blink::PaymentMethodData& input)
106 {
107 PaymentMethodDataPtr output = PaymentMethodData::New();
108 output->supported_methods = Vector<WTF::String>(input.supportedMethods() );
109 if (input.hasData() && !input.data().isEmpty())
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 if (methodData.isEmpty()) {
194 exceptionState.throwTypeError("Must specify at least one payment method identifier");
195 return;
196 }
197
198 for (const auto& md : methodData) {
199 if (md.supportedMethods().isEmpty()) {
200 exceptionState.throwTypeError("Must specify at least one payment met hod identifier");
201 return;
202 }
203
204 if (!md.data().isEmpty()) {
205 RefPtr<JSONValue> value = toJSONValue(md.data().context(), md.data() .v8Value());
206 if (!value) {
207 exceptionState.throwTypeError("Unable to parse payment method sp ecific data");
208 return;
209 }
210 if (!value->isNull() && value->getType() != JSONValue::TypeObject) {
211 exceptionState.throwTypeError("Data should be a JSON-serializabl e object");
212 return;
213 }
214 }
215 }
216 }
217
177 } // namespace 218 } // namespace
178 219
179 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptio nState) 220 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, ExceptionState& exceptionState)
180 { 221 {
181 return new PaymentRequest(scriptState, supportedMethods, details, PaymentOpt ions(), ScriptValue(), exceptionState); 222 return new PaymentRequest(scriptState, methodData, details, PaymentOptions() , exceptionState);
182 } 223 }
183 224
184 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, ExceptionState& exceptionState) 225 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, const PaymentOp tions& options, ExceptionState& exceptionState)
185 { 226 {
186 return new PaymentRequest(scriptState, supportedMethods, details, options, S criptValue(), exceptionState); 227 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 } 228 }
193 229
194 PaymentRequest::~PaymentRequest() 230 PaymentRequest::~PaymentRequest()
195 { 231 {
196 } 232 }
197 233
198 ScriptPromise PaymentRequest::show(ScriptState* scriptState) 234 ScriptPromise PaymentRequest::show(ScriptState* scriptState)
199 { 235 {
200 if (m_showResolver) 236 if (m_showResolver)
201 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once")); 237 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once"));
202 238
203 if (!scriptState->domWindow() || !scriptState->domWindow()->frame()) 239 if (!scriptState->domWindow() || !scriptState->domWindow()->frame())
204 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request")); 240 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request"));
205 241
206 DCHECK(!m_paymentProvider.is_bound()); 242 DCHECK(!m_paymentProvider.is_bound());
207 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider)); 243 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider));
208 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this)))); 244 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this))));
209 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind()); 245 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); 246 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); 247 m_showResolver = ScriptPromiseResolver::create(scriptState);
213 return m_showResolver->promise(); 248 return m_showResolver->promise();
214 } 249 }
215 250
216 void PaymentRequest::abort(ExceptionState& exceptionState) 251 void PaymentRequest::abort(ExceptionState& exceptionState)
217 { 252 {
218 if (!m_showResolver) { 253 if (!m_showResolver) {
219 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort"); 254 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort");
220 return; 255 return;
221 } 256 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 { 314 {
280 if (m_showResolver) 315 if (m_showResolver)
281 m_showResolver->reject(error); 316 m_showResolver->reject(error);
282 if (m_completeResolver) 317 if (m_completeResolver)
283 m_completeResolver->reject(error); 318 m_completeResolver->reject(error);
284 clearResolversAndCloseMojoConnection(); 319 clearResolversAndCloseMojoConnection();
285 } 320 }
286 321
287 DEFINE_TRACE(PaymentRequest) 322 DEFINE_TRACE(PaymentRequest)
288 { 323 {
324 visitor->trace(m_methodData);
289 visitor->trace(m_details); 325 visitor->trace(m_details);
290 visitor->trace(m_options); 326 visitor->trace(m_options);
291 visitor->trace(m_shippingAddress); 327 visitor->trace(m_shippingAddress);
292 visitor->trace(m_showResolver); 328 visitor->trace(m_showResolver);
293 visitor->trace(m_completeResolver); 329 visitor->trace(m_completeResolver);
294 EventTargetWithInlineData::trace(visitor); 330 EventTargetWithInlineData::trace(visitor);
295 ContextLifecycleObserver::trace(visitor); 331 ContextLifecycleObserver::trace(visitor);
296 } 332 }
297 333
298 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c onst ScriptValue& data, ExceptionState& exceptionState) 334 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o ptions, ExceptionState& exceptionState)
299 : ContextLifecycleObserver(scriptState->getExecutionContext()) 335 : ContextLifecycleObserver(scriptState->getExecutionContext())
300 , ActiveScriptWrappable(this) 336 , ActiveScriptWrappable(this)
301 , m_options(options) 337 , m_options(options)
302 , m_clientBinding(this) 338 , m_clientBinding(this)
303 { 339 {
340 validatePaymentMethodData(methodData, exceptionState);
341 if (exceptionState.hadException())
342 return;
343 m_methodData = methodData;
344
345 // TODO(rouslan): Also check for a top-level browsing context.
346 // https://github.com/w3c/browser-payment-api/issues/2
please use gerrit instead 2016/06/01 19:20:21 Bad merge? This comment should be gone now.
304 if (!scriptState->getExecutionContext()->isSecureContext()) { 347 if (!scriptState->getExecutionContext()->isSecureContext()) {
305 exceptionState.throwSecurityError("Must be in a secure context"); 348 exceptionState.throwSecurityError("Must be in a secure context");
306 return; 349 return;
307 } 350 }
308 351
309 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) { 352 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) {
310 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt"); 353 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt");
311 return; 354 return;
312 } 355 }
313 356
314 if (supportedMethods.isEmpty()) {
315 exceptionState.throwTypeError("Must specify at least one payment method identifier");
316 return;
317 }
318 m_supportedMethods = supportedMethods;
319
320 validatePaymentDetails(details, exceptionState); 357 validatePaymentDetails(details, exceptionState);
321 if (exceptionState.hadException()) 358 if (exceptionState.hadException())
322 return; 359 return;
323 m_details = details; 360 m_details = details;
324 361
325 if (!data.isEmpty()) {
326 RefPtr<JSONValue> value = toJSONValue(data.context(), data.v8Value());
327 if (!value) {
328 exceptionState.throwTypeError("Unable to parse payment method specif ic data");
329 return;
330 }
331 if (!value->isNull()) {
332 if (value->getType() != JSONValue::TypeObject) {
333 exceptionState.throwTypeError("Payment method specific data shou ld be a JSON-serializable object");
334 return;
335 }
336
337 RefPtr<JSONObject> jsonData = JSONObject::cast(value);
338 for (const auto& paymentMethodSpecificKeyValue : *jsonData) {
339 if (!supportedMethods.contains(paymentMethodSpecificKeyValue.key )) {
340 exceptionState.throwTypeError("'" + paymentMethodSpecificKey Value.key + "' should match one of the payment method identifiers");
341 return;
342 }
343 if (paymentMethodSpecificKeyValue.value->getType() != JSONValue: :TypeObject) {
344 exceptionState.throwTypeError("Data for '" + paymentMethodSp ecificKeyValue.key + "' should be a JSON-serializable object");
345 return;
346 }
347 }
348
349 m_stringifiedData = jsonData->toJSONString();
350 }
351 }
352
353 // Set the currently selected option if only one option is passed and shippi ng is requested. 362 // Set the currently selected option if only one option is passed and shippi ng is requested.
354 if (options.requestShipping() && details.hasShippingOptions() && details.shi ppingOptions().size() == 1) 363 if (options.requestShipping() && details.hasShippingOptions() && details.shi ppingOptions().size() == 1)
355 m_shippingOption = details.shippingOptions().begin()->id(); 364 m_shippingOption = details.shippingOptions().begin()->id();
356 } 365 }
357 366
358 void PaymentRequest::contextDestroyed() 367 void PaymentRequest::contextDestroyed()
359 { 368 {
360 clearResolversAndCloseMojoConnection(); 369 clearResolversAndCloseMojoConnection();
361 } 370 }
362 371
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 void PaymentRequest::clearResolversAndCloseMojoConnection() 452 void PaymentRequest::clearResolversAndCloseMojoConnection()
444 { 453 {
445 m_completeResolver.clear(); 454 m_completeResolver.clear();
446 m_showResolver.clear(); 455 m_showResolver.clear();
447 if (m_clientBinding.is_bound()) 456 if (m_clientBinding.is_bound())
448 m_clientBinding.Close(); 457 m_clientBinding.Close();
449 m_paymentProvider.reset(); 458 m_paymentProvider.reset();
450 } 459 }
451 460
452 } // namespace blink 461 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698