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

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<WTFArray<PaymentMethodDataPtr>, WTF::Vector<blink::PaymentR equest::MethodData>> {
105 static WTFArray<PaymentMethodDataPtr> Convert(const WTF::Vector<blink::Payme ntRequest::MethodData>& input)
106 {
107 WTFArray<PaymentMethodDataPtr> output(input.size());
108 for (size_t i = 0; i < input.size(); ++i) {
109 output[i] = PaymentMethodData::New();
110 output[i]->supported_methods = WTF::Vector<WTF::String>(input[i].sup portedMethods);
111 output[i]->data = input[i].stringifiedData;
112 }
113 return output;
114 }
115 };
116
101 } // namespace mojo 117 } // namespace mojo
102 118
103 namespace blink { 119 namespace blink {
104 namespace { 120 namespace {
105 121
106 // Validates ShippingOption and PaymentItem dictionaries, which happen to have i dentical fields, 122 // Validates ShippingOption and PaymentItem dictionaries, which happen to have i dentical fields,
107 // except for "id", which is present only in ShippingOption. 123 // except for "id", which is present only in ShippingOption.
108 template <typename T> 124 template <typename T>
109 void validateShippingOptionsOrPaymentItems(HeapVector<T> items, ExceptionState& exceptionState) 125 void validateShippingOptionsOrPaymentItems(HeapVector<T> items, ExceptionState& exceptionState)
110 { 126 {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 validateShippingOptionsOrPaymentItems(details.displayItems(), exceptionState ); 183 validateShippingOptionsOrPaymentItems(details.displayItems(), exceptionState );
168 if (exceptionState.hadException()) 184 if (exceptionState.hadException())
169 return; 185 return;
170 186
171 if (details.hasShippingOptions()) { 187 if (details.hasShippingOptions()) {
172 validateShippingOptionsOrPaymentItems(details.shippingOptions(), excepti onState); 188 validateShippingOptionsOrPaymentItems(details.shippingOptions(), excepti onState);
173 validateShippingOptionsIds(details.shippingOptions(), exceptionState); 189 validateShippingOptionsIds(details.shippingOptions(), exceptionState);
174 } 190 }
175 } 191 }
176 192
193 void validateAndConvertPaymentMethodData(const HeapVector<PaymentMethodData>& pa ymentMethodData, Vector<PaymentRequest::MethodData>* methodData, ExceptionState& exceptionState)
194 {
195 if (paymentMethodData.isEmpty()) {
196 exceptionState.throwTypeError("Must specify at least one payment method identifier");
197 return;
198 }
199
200 for (const auto& pmd : paymentMethodData) {
201 if (pmd.supportedMethods().isEmpty()) {
202 exceptionState.throwTypeError("Must specify at least one payment met hod identifier");
203 return;
204 }
205
206 String stringifiedData;
207 if (pmd.hasData() && !pmd.data().isEmpty()) {
208 RefPtr<JSONValue> value = toJSONValue(pmd.data().context(), pmd.data ().v8Value());
209 if (!value) {
210 exceptionState.throwTypeError("Unable to parse payment method sp ecific data");
211 return;
212 }
213 if (!value->isNull() && value->getType() != JSONValue::TypeObject) {
please use gerrit instead 2016/06/03 18:22:28 If value->isNull(), then you should not stringify
zino 2016/06/04 00:48:46 Done.
214 exceptionState.throwTypeError("Data should be a JSON-serializabl e object");
215 return;
216 }
217 stringifiedData = JSONObject::cast(value)->toJSONString();
218 }
219 methodData->append(PaymentRequest::MethodData(pmd.supportedMethods(), st ringifiedData));
220 }
221 }
222
177 } // namespace 223 } // namespace
178 224
179 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, ExceptionState& exceptio nState) 225 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, ExceptionState& exceptionState)
180 { 226 {
181 return new PaymentRequest(scriptState, supportedMethods, details, PaymentOpt ions(), ScriptValue(), exceptionState); 227 return new PaymentRequest(scriptState, methodData, details, PaymentOptions() , exceptionState);
182 } 228 }
183 229
184 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const Vector<St ring>& supportedMethods, const PaymentDetails& details, const PaymentOptions& op tions, ExceptionState& exceptionState) 230 PaymentRequest* PaymentRequest::create(ScriptState* scriptState, const HeapVecto r<PaymentMethodData>& methodData, const PaymentDetails& details, const PaymentOp tions& options, ExceptionState& exceptionState)
185 { 231 {
186 return new PaymentRequest(scriptState, supportedMethods, details, options, S criptValue(), exceptionState); 232 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 } 233 }
193 234
194 PaymentRequest::~PaymentRequest() 235 PaymentRequest::~PaymentRequest()
195 { 236 {
196 } 237 }
197 238
198 ScriptPromise PaymentRequest::show(ScriptState* scriptState) 239 ScriptPromise PaymentRequest::show(ScriptState* scriptState)
199 { 240 {
200 if (m_showResolver) 241 if (m_showResolver)
201 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once")); 242 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Already called show() once"));
202 243
203 if (!scriptState->domWindow() || !scriptState->domWindow()->frame()) 244 if (!scriptState->domWindow() || !scriptState->domWindow()->frame())
204 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request")); 245 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "Cannot show the payment request"));
205 246
206 DCHECK(!m_paymentProvider.is_bound()); 247 DCHECK(!m_paymentProvider.is_bound());
207 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider)); 248 scriptState->domWindow()->frame()->serviceRegistry()->connectToRemoteService (mojo::GetProxy(&m_paymentProvider));
208 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this)))); 249 m_paymentProvider.set_connection_error_handler(createBaseCallback(bind(&Paym entRequest::OnError, WeakPersistentThisPointer<PaymentRequest>(this))));
209 m_paymentProvider->SetClient(m_clientBinding.CreateInterfacePtrAndBind()); 250 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); 251 m_paymentProvider->Show(mojo::WTFArray<mojom::blink::PaymentMethodDataPtr>:: From(m_methodData), mojom::blink::PaymentDetails::From(m_details), mojom::blink: :PaymentOptions::From(m_options));
211
212 m_showResolver = ScriptPromiseResolver::create(scriptState); 252 m_showResolver = ScriptPromiseResolver::create(scriptState);
213 return m_showResolver->promise(); 253 return m_showResolver->promise();
214 } 254 }
215 255
216 void PaymentRequest::abort(ExceptionState& exceptionState) 256 void PaymentRequest::abort(ExceptionState& exceptionState)
217 { 257 {
218 if (!m_showResolver) { 258 if (!m_showResolver) {
219 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort"); 259 exceptionState.throwDOMException(InvalidStateError, "Never called show() , so nothing to abort");
220 return; 260 return;
221 } 261 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 { 328 {
289 visitor->trace(m_details); 329 visitor->trace(m_details);
290 visitor->trace(m_options); 330 visitor->trace(m_options);
291 visitor->trace(m_shippingAddress); 331 visitor->trace(m_shippingAddress);
292 visitor->trace(m_showResolver); 332 visitor->trace(m_showResolver);
293 visitor->trace(m_completeResolver); 333 visitor->trace(m_completeResolver);
294 EventTargetWithInlineData::trace(visitor); 334 EventTargetWithInlineData::trace(visitor);
295 ContextLifecycleObserver::trace(visitor); 335 ContextLifecycleObserver::trace(visitor);
296 } 336 }
297 337
298 PaymentRequest::PaymentRequest(ScriptState* scriptState, const Vector<String>& s upportedMethods, const PaymentDetails& details, const PaymentOptions& options, c onst ScriptValue& data, ExceptionState& exceptionState) 338 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o ptions, ExceptionState& exceptionState)
299 : ContextLifecycleObserver(scriptState->getExecutionContext()) 339 : ContextLifecycleObserver(scriptState->getExecutionContext())
300 , ActiveScriptWrappable(this) 340 , ActiveScriptWrappable(this)
301 , m_options(options) 341 , m_options(options)
302 , m_clientBinding(this) 342 , m_clientBinding(this)
303 { 343 {
344 validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionStat e);
345 if (exceptionState.hadException())
346 return;
347
304 if (!scriptState->getExecutionContext()->isSecureContext()) { 348 if (!scriptState->getExecutionContext()->isSecureContext()) {
305 exceptionState.throwSecurityError("Must be in a secure context"); 349 exceptionState.throwSecurityError("Must be in a secure context");
306 return; 350 return;
307 } 351 }
308 352
309 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) { 353 if (!scriptState->domWindow()->frame() || !scriptState->domWindow()->frame() ->isMainFrame()) {
310 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt"); 354 exceptionState.throwSecurityError("Must be in a top-level browsing conte xt");
311 return; 355 return;
312 } 356 }
313 357
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); 358 validatePaymentDetails(details, exceptionState);
321 if (exceptionState.hadException()) 359 if (exceptionState.hadException())
322 return; 360 return;
323 m_details = details; 361 m_details = details;
324 362
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. 363 // 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) 364 if (options.requestShipping() && details.hasShippingOptions() && details.shi ppingOptions().size() == 1)
355 m_shippingOption = details.shippingOptions().begin()->id(); 365 m_shippingOption = details.shippingOptions().begin()->id();
356 } 366 }
357 367
358 void PaymentRequest::contextDestroyed() 368 void PaymentRequest::contextDestroyed()
359 { 369 {
360 clearResolversAndCloseMojoConnection(); 370 clearResolversAndCloseMojoConnection();
361 } 371 }
362 372
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 void PaymentRequest::clearResolversAndCloseMojoConnection() 453 void PaymentRequest::clearResolversAndCloseMojoConnection()
444 { 454 {
445 m_completeResolver.clear(); 455 m_completeResolver.clear();
446 m_showResolver.clear(); 456 m_showResolver.clear();
447 if (m_clientBinding.is_bound()) 457 if (m_clientBinding.is_bound())
448 m_clientBinding.Close(); 458 m_clientBinding.Close();
449 m_paymentProvider.reset(); 459 m_paymentProvider.reset();
450 } 460 }
451 461
452 } // namespace blink 462 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698