| OLD | NEW |
| 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 /** | 5 /** |
| 6 * @fileoverview JavaScript implementation of the Payment Request API. When | 6 * @fileoverview JavaScript implementation of the Payment Request API. When |
| 7 * loaded, installs the API onto the window object. Conforms | 7 * loaded, installs the API onto the window object. Conforms |
| 8 * to https://www.w3.org/TR/payment-request/. Note: This is a work in progress. | 8 * to https://www.w3.org/TR/payment-request/. Note: This is a work in progress. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 * PaymentResponse.prototype.complete, if any. | 180 * PaymentResponse.prototype.complete, if any. |
| 181 * @type {window.PaymentRequest} | 181 * @type {window.PaymentRequest} |
| 182 */ | 182 */ |
| 183 __gCrWeb['paymentRequestManager'].responsePromiseResolver = null; | 183 __gCrWeb['paymentRequestManager'].responsePromiseResolver = null; |
| 184 | 184 |
| 185 /** | 185 /** |
| 186 * Parses |paymentResponseData| into a window.PaymentResponse object. | 186 * Parses |paymentResponseData| into a window.PaymentResponse object. |
| 187 * @param {!SerializedPaymentResponse} paymentResponseData | 187 * @param {!SerializedPaymentResponse} paymentResponseData |
| 188 * @return {window.PaymentResponse} | 188 * @return {window.PaymentResponse} |
| 189 */ | 189 */ |
| 190 var parsePaymentResponseData = function(paymentResponseData) { | 190 __gCrWeb['paymentRequestManager'].parsePaymentResponseData = function( |
| 191 paymentResponseData) { |
| 191 return new window.PaymentResponse( | 192 return new window.PaymentResponse( |
| 192 paymentResponseData['methodName'], paymentResponseData['details']); | 193 paymentResponseData['methodName'], paymentResponseData['details']); |
| 193 }; | 194 }; |
| 194 | 195 |
| 195 /** | 196 /** |
| 196 * The event that enables the web page to update the details of the payment | 197 * The event that enables the web page to update the details of the payment |
| 197 * request in response to a user interaction. | 198 * request in response to a user interaction. |
| 198 * @type {Event} | 199 * @type {Event} |
| 199 */ | 200 */ |
| 200 var updateEvent = null; | 201 __gCrWeb['paymentRequestManager'].updateEvent = null; |
| 201 | 202 |
| 202 /** | 203 /** |
| 203 * Handles invocation of updateWith() on the updateEvent object. Updates the | 204 * Handles invocation of updateWith() on the updateEvent object. Updates the |
| 204 * payment details when the |updateWithPromise| is resolved. Throws an error | 205 * payment details when the |updateWithPromise| is resolved. Throws an error |
| 205 * if |updateWithPromise| is not a valid instance of Promise or if it fulfills | 206 * if |updateWithPromise| is not a valid instance of Promise or if it fulfills |
| 206 * with an invalid instance of window.PaymentDetails. | 207 * with an invalid instance of window.PaymentDetails. |
| 207 * @param {?Promise<?window.PaymentDetails|undefined>|undefined} | 208 * @param {?Promise<?window.PaymentDetails|undefined>|undefined} |
| 208 * updateWithPromise | 209 * updateWithPromise |
| 209 */ | 210 */ |
| 210 var updateWith = function(updateWithPromise) { | 211 __gCrWeb['paymentRequestManager'].updateWith = function(updateWithPromise) { |
| 211 // Check to see |updateWithPromise| is an instance of Promise. | 212 // Check to see |updateWithPromise| is an instance of Promise. |
| 212 if (!updateWithPromise || !(updateWithPromise.then instanceof Function) || | 213 if (!updateWithPromise || !(updateWithPromise.then instanceof Function) || |
| 213 !(updateWithPromise.catch instanceof Function)) { | 214 !(updateWithPromise.catch instanceof Function)) { |
| 214 throw new TypeError('An instance of Promise must be provided'); | 215 throw new TypeError('An instance of Promise must be provided'); |
| 215 } | 216 } |
| 216 | 217 |
| 217 updateWithPromise | 218 updateWithPromise |
| 218 .then(function(paymentDetails) { | 219 .then(function(paymentDetails) { |
| 219 if (!paymentDetails) | 220 if (!paymentDetails) |
| 220 throw new TypeError( | 221 throw new TypeError( |
| 221 'An instance of PaymentDetails must be provided.'); | 222 'An instance of PaymentDetails must be provided.'); |
| 222 | 223 |
| 223 var message = { | 224 var message = { |
| 224 'command': 'paymentRequest.updatePaymentDetails', | 225 'command': 'paymentRequest.updatePaymentDetails', |
| 225 'payment_details': paymentDetails, | 226 'payment_details': paymentDetails, |
| 226 }; | 227 }; |
| 227 __gCrWeb.message.invokeOnHost(message); | 228 __gCrWeb.message.invokeOnHost(message); |
| 228 | 229 |
| 229 updateEvent = null; | 230 __gCrWeb['paymentRequestManager'].updateEvent = null; |
| 230 }) | 231 }) |
| 231 .catch(function() { | 232 .catch(function() { |
| 232 var message = { | 233 var message = { |
| 233 'command': 'paymentRequest.requestCancel', | 234 'command': 'paymentRequest.requestCancel', |
| 234 }; | 235 }; |
| 235 __gCrWeb.message.invokeOnHost(message); | 236 __gCrWeb.message.invokeOnHost(message); |
| 236 | 237 |
| 237 updateEvent = null; | 238 __gCrWeb['paymentRequestManager'].updateEvent = null; |
| 238 }); | 239 }); |
| 239 }; | 240 }; |
| 240 | 241 |
| 241 /** | 242 /** |
| 242 * Resolves the pending PaymentRequest. | 243 * Resolves the pending PaymentRequest. |
| 243 * @param {!SerializedPaymentResponse} paymentResponseData The response to | 244 * @param {!SerializedPaymentResponse} paymentResponseData The response to |
| 244 * provide to the resolve function of the Promise. | 245 * provide to the resolve function of the Promise. |
| 245 */ | 246 */ |
| 246 __gCrWeb['paymentRequestManager'].resolveRequestPromise = function( | 247 __gCrWeb['paymentRequestManager'].resolveRequestPromise = function( |
| 247 paymentResponseData) { | 248 paymentResponseData) { |
| 248 if (!__gCrWeb['paymentRequestManager'].requestPromiseResolver) { | 249 if (!__gCrWeb['paymentRequestManager'].requestPromiseResolver) { |
| 249 throw new Error('Internal PaymentRequest error: No Promise to resolve.'); | 250 throw new Error('Internal PaymentRequest error: No Promise to resolve.'); |
| 250 } | 251 } |
| 251 | 252 |
| 252 if (!paymentResponseData) { | 253 if (!paymentResponseData) { |
| 253 __gCrWeb['paymentRequestManager'].rejectRequestPromise( | 254 __gCrWeb['paymentRequestManager'].rejectRequestPromise( |
| 254 'Internal PaymentRequest error: PaymentResponse missing.'); | 255 'Internal PaymentRequest error: PaymentResponse missing.'); |
| 255 } | 256 } |
| 256 | 257 |
| 257 var paymentResponse = null; | 258 var paymentResponse = null; |
| 258 try { | 259 try { |
| 259 paymentResponse = parsePaymentResponseData(paymentResponseData); | 260 paymentResponse = |
| 261 __gCrWeb['paymentRequestManager'].parsePaymentResponseData( |
| 262 paymentResponseData); |
| 260 } catch (e) { | 263 } catch (e) { |
| 261 __gCrWeb['paymentRequestManager'].rejectRequestPromise( | 264 __gCrWeb['paymentRequestManager'].rejectRequestPromise( |
| 262 'Internal PaymentRequest error: failed to parse PaymentResponse.'); | 265 'Internal PaymentRequest error: failed to parse PaymentResponse.'); |
| 263 } | 266 } |
| 264 | 267 |
| 265 __gCrWeb['paymentRequestManager'].responsePromiseResolver = | 268 __gCrWeb['paymentRequestManager'].responsePromiseResolver = |
| 266 new __gCrWeb.PromiseResolver(); | 269 new __gCrWeb.PromiseResolver(); |
| 267 __gCrWeb['paymentRequestManager'].requestPromiseResolver.resolve( | 270 __gCrWeb['paymentRequestManager'].requestPromiseResolver.resolve( |
| 268 paymentResponse); | 271 paymentResponse); |
| 269 __gCrWeb['paymentRequestManager'].requestPromiseResolver = null; | 272 __gCrWeb['paymentRequestManager'].requestPromiseResolver = null; |
| 270 __gCrWeb['paymentRequestManager'].pendingRequest = null; | 273 __gCrWeb['paymentRequestManager'].pendingRequest = null; |
| 274 __gCrWeb['paymentRequestManager'].updateEvent = null; |
| 271 }; | 275 }; |
| 272 | 276 |
| 273 /** | 277 /** |
| 274 * Rejects the pending PaymentRequest. | 278 * Rejects the pending PaymentRequest. |
| 275 * @param {!string} message An error message explaining why the Promise is | 279 * @param {!string} message An error message explaining why the Promise is |
| 276 * being rejected. | 280 * being rejected. |
| 277 */ | 281 */ |
| 278 __gCrWeb['paymentRequestManager'].rejectRequestPromise = function(message) { | 282 __gCrWeb['paymentRequestManager'].rejectRequestPromise = function(message) { |
| 279 if (!__gCrWeb['paymentRequestManager'].requestPromiseResolver) { | 283 if (!__gCrWeb['paymentRequestManager'].requestPromiseResolver) { |
| 280 throw new Error( | 284 throw new Error( |
| 281 'Internal PaymentRequest error: No Promise to reject. ', | 285 'Internal PaymentRequest error: No Promise to reject. ', |
| 282 'Message was: ', message); | 286 'Message was: ', message); |
| 283 } | 287 } |
| 284 | 288 |
| 285 __gCrWeb['paymentRequestManager'].requestPromiseResolver.reject(message); | 289 __gCrWeb['paymentRequestManager'].requestPromiseResolver.reject(message); |
| 286 __gCrWeb['paymentRequestManager'].requestPromiseResolver = null; | 290 __gCrWeb['paymentRequestManager'].requestPromiseResolver = null; |
| 287 __gCrWeb['paymentRequestManager'].pendingRequest = null; | 291 __gCrWeb['paymentRequestManager'].pendingRequest = null; |
| 292 __gCrWeb['paymentRequestManager'].updateEvent = null; |
| 288 }; | 293 }; |
| 289 | 294 |
| 290 /** | 295 /** |
| 291 * Serializes |paymentRequest| to a SerializedPaymentRequest object. | 296 * Serializes |paymentRequest| to a SerializedPaymentRequest object. |
| 292 * @param {window.PaymentRequest} paymentRequest | 297 * @param {window.PaymentRequest} paymentRequest |
| 293 * @return {SerializedPaymentRequest} | 298 * @return {SerializedPaymentRequest} |
| 294 */ | 299 */ |
| 295 __gCrWeb['paymentRequestManager'].serializePaymentRequest = function( | 300 __gCrWeb['paymentRequestManager'].serializePaymentRequest = function( |
| 296 paymentRequest) { | 301 paymentRequest) { |
| 297 var serialized = { | 302 var serialized = { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 322 */ | 327 */ |
| 323 __gCrWeb['paymentRequestManager'].updateShippingOptionAndDispatchEvent = | 328 __gCrWeb['paymentRequestManager'].updateShippingOptionAndDispatchEvent = |
| 324 function(shippingOptionID) { | 329 function(shippingOptionID) { |
| 325 if (!__gCrWeb['paymentRequestManager'].pendingRequest) { | 330 if (!__gCrWeb['paymentRequestManager'].pendingRequest) { |
| 326 __gCrWeb['paymentRequestManager'].rejectRequestPromise( | 331 __gCrWeb['paymentRequestManager'].rejectRequestPromise( |
| 327 'Internal PaymentRequest error: No pending request.'); | 332 'Internal PaymentRequest error: No pending request.'); |
| 328 } | 333 } |
| 329 | 334 |
| 330 var pendingRequest = __gCrWeb['paymentRequestManager'].pendingRequest; | 335 var pendingRequest = __gCrWeb['paymentRequestManager'].pendingRequest; |
| 331 | 336 |
| 332 if (updateEvent) { | 337 if (__gCrWeb['paymentRequestManager'].updateEvent) { |
| 333 __gCrWeb['paymentRequestManager'].rejectRequestPromise( | 338 __gCrWeb['paymentRequestManager'].rejectRequestPromise( |
| 334 'Internal PaymentRequest error: Only one update may take ' + | 339 'Internal PaymentRequest error: Only one update may take ' + |
| 335 'place at a time.'); | 340 'place at a time.'); |
| 336 } | 341 } |
| 337 | 342 |
| 338 pendingRequest.shippingOption = shippingOptionID; | 343 pendingRequest.shippingOption = shippingOptionID; |
| 339 | 344 |
| 340 updateEvent = new Event( | 345 __gCrWeb['paymentRequestManager'].updateEvent = new Event( |
| 341 'shippingoptionchange', {'bubbles': true, 'cancelable': false}); | 346 'shippingoptionchange', {'bubbles': true, 'cancelable': false}); |
| 342 Object.defineProperty(updateEvent, 'updateWith', {value: updateWith}); | 347 |
| 348 Object.defineProperty(__gCrWeb['paymentRequestManager'].updateEvent, |
| 349 'updateWith', {value: __gCrWeb['paymentRequestManager'].updateWith}); |
| 343 | 350 |
| 344 // setTimeout() is used in order to return immediately. Otherwise the | 351 // setTimeout() is used in order to return immediately. Otherwise the |
| 345 // dispatchEvent call waits for all event handlers to return, which could | 352 // dispatchEvent call waits for all event handlers to return, which could |
| 346 // cause a ReentryGuard failure. | 353 // cause a ReentryGuard failure. |
| 347 window.setTimeout(function() { | 354 window.setTimeout(function() { |
| 348 pendingRequest.dispatchEvent(updateEvent); | 355 pendingRequest.dispatchEvent( |
| 356 __gCrWeb['paymentRequestManager'].updateEvent); |
| 349 }, 0); | 357 }, 0); |
| 350 }; | 358 }; |
| 351 | 359 |
| 352 /** | 360 /** |
| 353 * Updates the shipping_address property of the PaymentRequest object to | 361 * Updates the shipping_address property of the PaymentRequest object to |
| 354 * |shippingAddress| and dispatches a shippingaddresschange event. | 362 * |shippingAddress| and dispatches a shippingaddresschange event. |
| 355 * @param {!window.PaymentAddress} shippingAddress | 363 * @param {!window.PaymentAddress} shippingAddress |
| 356 */ | 364 */ |
| 357 __gCrWeb['paymentRequestManager'].updateShippingAddressAndDispatchEvent = | 365 __gCrWeb['paymentRequestManager'].updateShippingAddressAndDispatchEvent = |
| 358 function(shippingAddress) { | 366 function(shippingAddress) { |
| 359 if (!__gCrWeb['paymentRequestManager'].pendingRequest) { | 367 if (!__gCrWeb['paymentRequestManager'].pendingRequest) { |
| 360 __gCrWeb['paymentRequestManager'].rejectRequestPromise( | 368 __gCrWeb['paymentRequestManager'].rejectRequestPromise( |
| 361 'Internal PaymentRequest error: No pending request.'); | 369 'Internal PaymentRequest error: No pending request.'); |
| 362 } | 370 } |
| 363 | 371 |
| 364 var pendingRequest = __gCrWeb['paymentRequestManager'].pendingRequest; | 372 var pendingRequest = __gCrWeb['paymentRequestManager'].pendingRequest; |
| 365 | 373 |
| 366 if (updateEvent) { | 374 if (__gCrWeb['paymentRequestManager'].updateEvent) { |
| 367 __gCrWeb['paymentRequestManager'].rejectRequestPromise( | 375 __gCrWeb['paymentRequestManager'].rejectRequestPromise( |
| 368 'Internal PaymentRequest error: Only one update may take ' + | 376 'Internal PaymentRequest error: Only one update may take ' + |
| 369 'place at a time.'); | 377 'place at a time.'); |
| 370 } | 378 } |
| 371 | 379 |
| 372 pendingRequest.shippingAddress = shippingAddress; | 380 pendingRequest.shippingAddress = shippingAddress; |
| 373 | 381 |
| 374 updateEvent = new Event( | 382 __gCrWeb['paymentRequestManager'].updateEvent = new Event( |
| 375 'shippingaddresschange', {'bubbles': true, 'cancelable': false}); | 383 'shippingaddresschange', {'bubbles': true, 'cancelable': false}); |
| 376 Object.defineProperty(updateEvent, 'updateWith', {value: updateWith}); | 384 |
| 385 Object.defineProperty(__gCrWeb['paymentRequestManager'].updateEvent, |
| 386 'updateWith', {value: __gCrWeb['paymentRequestManager'].updateWith}); |
| 377 | 387 |
| 378 // setTimeout() is used in order to return immediately. Otherwise the | 388 // setTimeout() is used in order to return immediately. Otherwise the |
| 379 // dispatchEvent call waits for all event handlers to return, which could | 389 // dispatchEvent call waits for all event handlers to return, which could |
| 380 // cause a ReentryGuard failure. | 390 // cause a ReentryGuard failure. |
| 381 window.setTimeout(function() { | 391 window.setTimeout(function() { |
| 382 pendingRequest.dispatchEvent(updateEvent); | 392 pendingRequest.dispatchEvent( |
| 393 __gCrWeb['paymentRequestManager'].updateEvent); |
| 383 }, 0); | 394 }, 0); |
| 384 }; | 395 }; |
| 385 }()); // End of anonymous object | 396 }()); // End of anonymous object |
| 386 | 397 |
| 387 /** | 398 /** |
| 388 * A request to make a payment. | 399 * A request to make a payment. |
| 389 * @param {!Array<!window.PaymentMethodData>} methodData Payment method | 400 * @param {!Array<!window.PaymentMethodData>} methodData Payment method |
| 390 * identifiers for the payment methods that the web site accepts and any | 401 * identifiers for the payment methods that the web site accepts and any |
| 391 * associated payment method specific data. | 402 * associated payment method specific data. |
| 392 * @param {!window.PaymentDetails} details Information about the transaction | 403 * @param {!window.PaymentDetails} details Information about the transaction |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 */ | 591 */ |
| 581 this.methodName = methodName; | 592 this.methodName = methodName; |
| 582 | 593 |
| 583 /** | 594 /** |
| 584 * @type {Object} | 595 * @type {Object} |
| 585 */ | 596 */ |
| 586 this.details = details; | 597 this.details = details; |
| 587 }; | 598 }; |
| 588 | 599 |
| 589 /** | 600 /** |
| 601 * Contains the possible values for the string argument accepted by |
| 602 * window.PaymentResponse.prototype.complete. |
| 603 * @enum {string} |
| 604 */ |
| 605 var PaymentComplete = { |
| 606 SUCCESS: 'success', |
| 607 FAIL: 'fail', |
| 608 UNKNOWN: 'unknown' |
| 609 }; |
| 610 |
| 611 /** |
| 590 * Communicates the result of processing the payment. | 612 * Communicates the result of processing the payment. |
| 591 * @param {boolean} success Indicates whether processing succeeded. | 613 * @param {PaymentComplete=} opt_result Indicates whether payment was |
| 614 * successfully processed. |
| 592 * @return {!Promise} A promise to notify the caller when the user interface has | 615 * @return {!Promise} A promise to notify the caller when the user interface has |
| 593 * been closed. | 616 * been closed. |
| 594 */ | 617 */ |
| 595 window.PaymentResponse.prototype.complete = function(success) { | 618 window.PaymentResponse.prototype.complete = function(opt_result) { |
| 619 if (opt_result != PaymentComplete.UNKNOWN && |
| 620 opt_result != PaymentComplete.SUCCESS && |
| 621 opt_result != PaymentComplete.FAIL) { |
| 622 opt_result = PaymentComplete.UNKNOWN; |
| 623 } |
| 624 |
| 596 if (!__gCrWeb['paymentRequestManager'].responsePromiseResolver) { | 625 if (!__gCrWeb['paymentRequestManager'].responsePromiseResolver) { |
| 597 throw new Error('Internal PaymentRequest error: No Promise to return.'); | 626 throw new Error('Internal PaymentRequest error: No Promise to return.'); |
| 598 } | 627 } |
| 599 | 628 |
| 600 var message = { | 629 var message = { |
| 601 'command': 'paymentRequest.responseComplete' | 630 'command': 'paymentRequest.responseComplete', |
| 631 'result': opt_result, |
| 602 }; | 632 }; |
| 603 __gCrWeb.message.invokeOnHost(message); | 633 __gCrWeb.message.invokeOnHost(message); |
| 604 | 634 |
| 605 return __gCrWeb['paymentRequestManager'].responsePromiseResolver.promise; | 635 return __gCrWeb['paymentRequestManager'].responsePromiseResolver.promise; |
| 606 }; | 636 }; |
| OLD | NEW |