mobile/android/components/PaymentsUI.js

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
     9 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    10 Cu.import("resource://gre/modules/Services.jsm");
    11 Cu.import("resource://gre/modules/JNI.jsm");
    13 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
    14                                    "@mozilla.org/childprocessmessagemanager;1",
    15                                    "nsIMessageSender");
    17 function paymentSuccess(aRequestId) {
    18   return function(aResult) {
    19     closePaymentTab(aRequestId, function() {
    20       cpmm.sendAsyncMessage("Payment:Success", { result: aResult,
    21                                     requestId: aRequestId });
    22     });
    23   }
    24 }
    26 function paymentFailed(aRequestId) {
    27   return function(aErrorMsg) {
    28     closePaymentTab(aRequestId, function() {
    29       cpmm.sendAsyncMessage("Payment:Failed", { errorMsg: aErrorMsg,
    30                                     requestId: aRequestId });
    31     });
    32   }
    33 }
    35 let paymentTabs = {};
    36 let cancelTabCallbacks = {};
    37 function paymentCanceled(aRequestId) {
    38   return function() {
    39     paymentFailed(aRequestId)();
    40   }
    41 }
    42 function closePaymentTab(aId, aCallback) {
    43   if (paymentTabs[aId]) {
    44     paymentTabs[aId].browser.removeEventListener("TabClose", cancelTabCallbacks[aId]);
    45     delete cancelTabCallbacks[aId];
    47     // We ask the UI to close the selected payment flow.
    48     let content = Services.wm.getMostRecentWindow("navigator:browser");
    49     if (content) {
    50       content.BrowserApp.closeTab(paymentTabs[aId]);
    51     }
    53     paymentTabs[aId] = null;
    54   }
    56   aCallback();
    57 }
    59 function PaymentUI() {
    60 }
    62 PaymentUI.prototype = {
    63   get bundle() {
    64     delete this.bundle;
    65     return this.bundle = Services.strings.createBundle("chrome://browser/locale/payments.properties");
    66   },
    68   confirmPaymentRequest: function confirmPaymentRequest(aRequestId,
    69                                                         aRequests,
    70                                                         aSuccessCb,
    71                                                         aErrorCb) {
    72     let _error = this._error(aErrorCb);
    74     let listItems = [];
    76     // If there's only one payment provider that will work, just move on without prompting the user.
    77     if (aRequests.length == 1) {
    78       aSuccessCb.onresult(aRequestId, aRequests[0].type);
    79       return;
    80     }
    82     // Otherwise, let the user select a payment provider from a list.
    83     for (let i = 0; i < aRequests.length; i++) {
    84       let request = aRequests[i];
    85       let requestText = request.providerName;
    86       if (request.productPrice) {
    87         requestText += " (" + request.productPrice[0].amount + " " +
    88                               request.productPrice[0].currency + ")";
    89       }
    90       listItems.push({ label: requestText });
    91     }
    93     let p = new Prompt({
    94       window: null,
    95       title: this.bundle.GetStringFromName("payments.providerdialog.title"),
    96     }).setSingleChoiceItems(listItems).show(function(data) {
    97       if (data.button > -1 && aSuccessCb) {
    98         aSuccessCb.onresult(aRequestId, aRequests[data.button].type);
    99       } else {
   100         _error(aRequestId, "USER_CANCELED");
   101       }
   102     });
   103   },
   105   _error: function(aCallback) {
   106     return function _error(id, msg) {
   107       if (aCallback) {
   108         aCallback.onresult(id, msg);
   109       }
   110     };
   111   },
   113   showPaymentFlow: function showPaymentFlow(aRequestId,
   114                                             aPaymentFlowInfo,
   115                                             aErrorCb) {
   116     let _error = this._error(aErrorCb);
   118     // We ask the UI to browse to the selected payment flow.
   119     let content = Services.wm.getMostRecentWindow("navigator:browser");
   120     if (!content) {
   121       _error(aRequestId, "NO_CONTENT_WINDOW");
   122       return;
   123     }
   125     // TODO: For now, known payment providers (BlueVia and Mozilla Market)
   126     // only accepts the JWT by GET, so we just add it to the URI.
   127     // https://github.com/mozilla-b2g/gaia/blob/master/apps/system/js/payment.js
   128     let tab = content.BrowserApp.addTab(aPaymentFlowInfo.uri + aPaymentFlowInfo.jwt);
   130     // Inject paymentSuccess and paymentFailed methods into the document after its loaded.
   131     tab.browser.addEventListener("DOMWindowCreated", function loadPaymentShim() {
   132       let frame = tab.browser.contentDocument.defaultView;
   133       try {
   134         frame.wrappedJSObject.mozPaymentProvider = {
   135           __exposedProps__: {
   136             paymentSuccess: 'r',
   137             paymentFailed: 'r',
   138             mnc: 'r',
   139             mcc: 'r',
   140           },
   142           _getNetworkInfo: function(type) {
   143             let jni = new JNI();
   144             let cls = jni.findClass("org/mozilla/gecko/GeckoNetworkManager");
   145             let method = jni.getStaticMethodID(cls, "get" + type.toUpperCase(), "()I");
   146             let val = jni.callStaticIntMethod(cls, method);
   147             jni.close();
   149             if (val < 0)
   150               return null;
   151             return val;
   152           },
   154           get mnc() {
   155             delete this.mnc;
   156             return this.mnc = this._getNetworkInfo("mnc");
   157           },
   159           get mcc() {
   160             delete this.mcc;
   161             return this.mcc = this._getNetworkInfo("mcc");
   162           },
   164           paymentSuccess: paymentSuccess(aRequestId),
   165           paymentFailed: paymentFailed(aRequestId)
   166         };
   167       } catch (e) {
   168         _error(aRequestId, "ERROR_ADDING_METHODS");
   169       } finally {
   170         tab.browser.removeEventListener("DOMWindowCreated", loadPaymentShim);
   171       }
   172     }, true);
   174     // Store a reference to the tab so that we can close it when the payment succeeds or fails.
   175     paymentTabs[aRequestId] = tab;
   176     cancelTabCallbacks[aRequestId] = paymentCanceled(aRequestId);
   178     // Fail the payment if the tab is closed on its own
   179     tab.browser.addEventListener("TabClose", cancelTabCallbacks[aRequestId]);
   180   },
   182   cleanup: function cleanup() {
   183     // Nothing to do here.
   184   },
   186   classID: Components.ID("{3c6c9575-f57e-427b-a8aa-57bc3cbff48f}"), 
   187   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue])
   188 }
   190 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUI]);

mercurial