Bug 767818 - Implement navigator.pay. Part 4 - B2G implementation; r=fabrice

This commit is contained in:
Fernando Jiménez 2012-08-29 18:41:35 -03:00
parent 60675c0017
commit 8140be46f6
8 changed files with 228 additions and 1 deletions

View File

@ -0,0 +1,77 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// This JS shim contains the callbacks to fire DOMRequest events for
// navigator.pay API within the payment processor's scope.
"use strict";
dump("======================= payment.js ======================= \n");
let { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
const kClosePaymentFlowEvent = "close-payment-flow-dialog";
function paymentSuccess(aResult) {
closePaymentFlowDialog(function notifySuccess() {
cpmm.sendAsyncMessage("Payment:Success", { result: aResult });
});
}
function paymentFailed(aErrorMsg) {
closePaymentFlowDialog(function notifyError() {
cpmm.sendAsyncMessage("Payment:Failed", { errorMsg: aErrorMsg });
});
}
function closePaymentFlowDialog(aCallback) {
// After receiving the payment provider confirmation about the
// successful or failed payment flow, we notify the UI to close the
// payment flow dialog and return to the caller application.
let randomId = uuidgen.generateUUID().toString();
let id = kClosePaymentFlowEvent + "-" + randomId;
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.getContentWindow();
if (!content) {
return;
}
let detail = {
type: kClosePaymentFlowEvent,
id: id
};
// In order to avoid race conditions, we wait for the UI to notify that
// it has successfully closed the payment flow and has recovered the
// caller app, before notifying the parent process to fire the success
// or error event over the DOMRequest.
content.addEventListener("mozContentEvent",
function closePaymentFlowReturn(evt) {
if (evt.detail.id == id && aCallback) {
aCallback();
}
content.removeEventListener("mozContentEvent",
closePaymentFlowReturn);
});
browser.shell.sendChromeEvent(detail);
}
addEventListener("DOMContentLoaded", function(e) {
content.wrappedJSObject.paymentSuccess = paymentSuccess;
content.wrappedJSObject.paymentFailed = paymentFailed;
});

View File

@ -18,7 +18,8 @@ Cu.import('resource://gre/modules/AlarmService.jsm');
Cu.import('resource://gre/modules/ActivitiesService.jsm');
Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
Cu.import('resource://gre/modules/ObjectWrapper.jsm');
Cu.import("resource://gre/modules/accessibility/AccessFu.jsm");
Cu.import('resource://gre/modules/accessibility/AccessFu.jsm');
Cu.import('resource://gre/modules/Payment.jsm');
XPCOMUtils.defineLazyServiceGetter(Services, 'env',
'@mozilla.org/process/environment;1',

View File

@ -21,6 +21,8 @@ chrome.jar:
content/content.css (content/content.css)
content/touchcontrols.css (content/touchcontrols.css)
content/payment.js (content/payment.js)
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
% override chrome://global/skin/netError.css chrome://browser/content/netError.css
% override chrome://global/skin/media/videocontrols.css chrome://browser/content/touchcontrols.css

View File

@ -43,3 +43,6 @@ category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
component {d18d0216-d50c-11e1-ba54-efb18d0ef0ac} ContentHandler.js
contract @mozilla.org/uriloader/content-handler;1?type=application/pdf {d18d0216-d50c-11e1-ba54-efb18d0ef0ac}
# PaymentGlue.js
component {8b83eabc-7929-47f4-8b48-4dea8d887e4b} PaymentGlue.js
contract @mozilla.org/payment/ui-glue;1 {8b83eabc-7929-47f4-8b48-4dea8d887e4b}

View File

@ -26,6 +26,7 @@ EXTRA_PP_COMPONENTS = \
DirectoryProvider.js \
MozKeyboard.js \
ProcessGlobal.js \
PaymentGlue.js \
$(NULL)
ifdef MOZ_UPDATER

View File

@ -0,0 +1,134 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
// JS shim that contains the callback functions to be triggered from the
// payment provider's code in order to fire DOMRequest events.
const kPaymentShimFile = "chrome://browser/content/payment.js";
// Type of MozChromEvents to handle payment dialogs.
const kOpenPaymentConfirmationEvent = "open-payment-confirmation-dialog";
const kOpenPaymentFlowEvent = "open-payment-flow-dialog";
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
function debug (s) {
//dump("-*- PaymentGlue: " + s + "\n");
};
function PaymentUI() {
}
PaymentUI.prototype = {
confirmPaymentRequest: function confirmPaymentRequest(aRequests,
aSuccessCb,
aErrorCb) {
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.getContentWindow();
if (!content && aErrorCb) {
aErrorCb.onresult("NO_CONTENT_WINDOW");
return;
}
// The UI should listen for mozChromeEvent 'open-payment-confirmation-dialog'
// type in order to create and show the payment request confirmation frame
// embeded within a trusted dialog.
let id = kOpenPaymentConfirmationEvent + "-" + this.getRandomId();
let detail = {
type: kOpenPaymentConfirmationEvent,
id: id,
paymentRequests: aRequests
};
// Once the user confirm the payment request and makes his choice, we get
// back to the DOM part to get the appropriate payment flow information
// based on the selected payment provider.
content.addEventListener("mozContentEvent", function handleSelection(evt) {
let msg = evt.detail;
if (msg.id != id) {
debug("mozContentEvent. evt.detail.id != " + id);
content.removeEventListener("mozContentEvent", handleSelection);
return;
}
if (msg.userSelection && aSuccessCb) {
aSuccessCb.onresult(msg.userSelection);
} else if (msg.errorMsg && aErrorCb) {
aErrorCb.onresult(msg.errorMsg);
}
content.removeEventListener("mozContentEvent", handleSelection);
});
browser.shell.sendChromeEvent(detail);
},
showPaymentFlow: function showPaymentFlow(aPaymentFlowInfo, aErrorCb) {
debug("showPaymentFlow. uri " + aPaymentFlowInfo.uri);
// We ask the UI to browse to the selected payment flow.
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.getContentWindow();
if (!content && aErrorCb) {
aErrorCb.onresult("NO_CONTENT_WINDOW");
return;
}
let id = kOpenPaymentFlowEvent + "-" + this.getRandomId();
let detail = {
type: kOpenPaymentFlowEvent,
id: id,
uri: aPaymentFlowInfo.uri,
method: aPaymentFlowInfo.requestMethod,
jwt: aPaymentFlowInfo.jwt
};
// At some point the UI would send the created iframe back so the
// callbacks for firing DOMRequest events can be loaded on its
// content.
content.addEventListener("mozContentEvent", function loadPaymentShim(evt) {
if (evt.detail.id != id || !evt.detail.frame) {
content.removeEventListener("mozContentEvent", loadPaymentShim);
return;
}
// Try to load the payment shim file containing the payment callbacks
// in the content script.
let frame = evt.detail.frame;
let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner)
.frameLoader;
let mm = frameLoader.messageManager;
try {
mm.loadFrameScript(kPaymentShimFile, true);
} catch (e) {
debug("Error loading " + kPaymentShimFile + " as a frame script: " + e);
if (aErrorCb) {
aErrorCb.onresult("ERROR_LOADING_PAYMENT_SHIM");
}
} finally {
content.removeEventListener("mozContentEvent", loadPaymentShim);
}
});
browser.shell.sendChromeEvent(detail);
},
getRandomId: function getRandomId() {
return uuidgen.generateUUID().toString();
},
classID: Components.ID("{8b83eabc-7929-47f4-8b48-4dea8d887e4b}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue])
}
const NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUI]);

View File

@ -38,4 +38,6 @@ MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
MOZ_EXTENSION_MANAGER=1
MOZ_SYS_MSG=1
MOZ_PAY=1
MOZ_TOOLKIT_SEARCH=

View File

@ -182,6 +182,7 @@
@BINPATH@/components/dom_html.xpt
@BINPATH@/components/dom_indexeddb.xpt
@BINPATH@/components/dom_offline.xpt
@BINPATH@/components/dom_payment.xpt
@BINPATH@/components/dom_json.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_mms.xpt
@ -489,6 +490,11 @@
@BINPATH@/components/AppProtocolHandler.js
@BINPATH@/components/AppProtocolHandler.manifest
@BINPATH@/components/Payment.js
@BINPATH@/components/PaymentFlowInfo.js
@BINPATH@/components/PaymentRequestInfo.js
@BINPATH@/components/Payment.manifest
; Modules
@BINPATH@/modules/*
@ -690,6 +696,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
@BINPATH@/components/ActivitiesGlue.js
@BINPATH@/components/ProcessGlobal.js
@BINPATH@/components/ContentHandler.js
@BINPATH@/components/PaymentGlue.js
#ifdef XP_MACOSX
@BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@