merge mozilla-central to fx-team. r=merge a=merge
merge mozilla-central to fx-team. r=merge a=merge
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -462,19 +462,16 @@ pref("dom.mozPermissionSettings.enabled"
// controls if we want camera support
pref("device.camera.enabled", true);
pref("media.realtime_decoder.enabled", true);
// TCPSocket
pref("dom.mozTCPSocket.enabled", true);
-// WebPayment
-pref("dom.mozPay.enabled", true);
-
// "Preview" landing of bug 710563, which is bogged down in analysis
// of talos regression. This is a needed change for higher-framerate
// CSS animations, and incidentally works around an apparent bug in
// our handling of requestAnimationFrame() listeners, which are
// supposed to enable this REPEATING_PRECISE_CAN_SKIP behavior. The
// secondary bug isn't really worth investigating since it's obseleted
// by bug 710563.
pref("layout.frame_rate.precise", true);
@@ -1006,19 +1003,16 @@ pref("layout.accessiblecaret.use_long_ta
// Hide carets and text selection dialog during scrolling.
pref("layout.accessiblecaret.always_show_when_scrolling", false);
// Enable sync and mozId with Firefox Accounts.
pref("services.sync.fxaccounts.enabled", true);
pref("identity.fxaccounts.enabled", true);
-// Mobile Identity API.
-pref("services.mobileid.server.uri", "https://msisdn.services.mozilla.com");
-
pref("identity.fxaccounts.remote.oauth.uri", "https://oauth.accounts.firefox.com/v1");
pref("identity.fxaccounts.remote.profile.uri", "https://profile.accounts.firefox.com/v1");
// Disable Firefox Accounts device registration until bug 1238895 is fixed.
pref("identity.fxaccounts.skipDeviceRegistration", true);
// Enable mapped array buffer.
pref("dom.mapped_arraybuffer.enabled", true);
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -4,17 +4,16 @@
* 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/. */
window.performance.mark('gecko-shell-loadstart');
Cu.import('resource://gre/modules/ContactService.jsm');
Cu.import('resource://gre/modules/AlarmService.jsm');
Cu.import('resource://gre/modules/NotificationDB.jsm');
-Cu.import('resource://gre/modules/Payment.jsm');
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
Cu.import('resource://gre/modules/Keyboard.jsm');
Cu.import('resource://gre/modules/ErrorPage.jsm');
Cu.import('resource://gre/modules/AlertsHelper.jsm');
Cu.import('resource://gre/modules/SystemUpdateService.jsm');
if (isGonk) {
@@ -23,17 +22,16 @@ if (isGonk) {
}
// Identity
Cu.import('resource://gre/modules/SignInToWebsite.jsm');
SignInToWebsiteController.init();
Cu.import('resource://gre/modules/FxAccountsMgmtService.jsm');
Cu.import('resource://gre/modules/DownloadsAPI.jsm');
-Cu.import('resource://gre/modules/MobileIdentityManager.jsm');
Cu.import('resource://gre/modules/PresentationDeviceInfoManager.jsm');
Cu.import('resource://gre/modules/AboutServiceWorkers.jsm');
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
"resource://gre/modules/SystemAppProxy.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Screenshot",
"resource://gre/modules/Screenshot.jsm");
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -32,22 +32,16 @@ component {1a94c87a-5ece-4d11-91e1-d29c2
contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
# OMAContentHandler.js
component {a6b2ab13-9037-423a-9897-dde1081be323} OMAContentHandler.js
contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.oma.drm.message {a6b2ab13-9037-423a-9897-dde1081be323}
contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.oma.dd+xml {a6b2ab13-9037-423a-9897-dde1081be323}
-# Payments
-component {8b83eabc-7929-47f4-8b48-4dea8d887e4b} PaymentGlue.js
-contract @mozilla.org/payment/ui-glue;1 {8b83eabc-7929-47f4-8b48-4dea8d887e4b}
-component {4834b2e1-2c91-44ea-b020-e2581ed279a4} PaymentProviderStrategy.js
-contract @mozilla.org/payment/provider-strategy;1 {4834b2e1-2c91-44ea-b020-e2581ed279a4}
-
# TelProtocolHandler.js
component {782775dd-7351-45ea-aff1-0ffa872cfdd2} TelProtocolHandler.js
contract @mozilla.org/network/protocol;1?name=tel {782775dd-7351-45ea-aff1-0ffa872cfdd2}
# SmsProtocolHandler.js
component {81ca20cb-0dad-4e32-8566-979c8998bd73} SmsProtocolHandler.js
contract @mozilla.org/network/protocol;1?name=sms {81ca20cb-0dad-4e32-8566-979c8998bd73}
@@ -97,20 +91,16 @@ contract @mozilla.org/commandlinehandler
category command-line-handler m-b2gcmds @mozilla.org/commandlinehandler/general-startup;1?type=b2gcmds
#endif
# BootstrapCommandLine.js
component {fd663ec8-cf3f-4c2b-aacb-17a6915ccb44} BootstrapCommandLine.js
contract @mozilla.org/commandlinehandler/general-startup;1?type=b2gbootstrap {fd663ec8-cf3f-4c2b-aacb-17a6915ccb44}
category command-line-handler m-b2gbootstrap @mozilla.org/commandlinehandler/general-startup;1?type=b2gbootstrap
-# MobileIdentityUIGlue.js
-component {83dbe26a-81f3-4a75-9541-3d0b7ca496b5} MobileIdentityUIGlue.js
-contract @mozilla.org/services/mobileid-ui-glue;1 {83dbe26a-81f3-4a75-9541-3d0b7ca496b5}
-
# B2GAppMigrator.js
component {7211ece0-b458-4635-9afc-f8d7f376ee95} B2GAppMigrator.js
contract @mozilla.org/app-migrator;1 {7211ece0-b458-4635-9afc-f8d7f376ee95}
# B2GPresentationDevicePrompt.js
component {4a300c26-e99b-4018-ab9b-c48cf9bc4de1} B2GPresentationDevicePrompt.js
contract @mozilla.org/presentation-device/prompt;1 {4a300c26-e99b-4018-ab9b-c48cf9bc4de1}
deleted file mode 100644
--- a/b2g/components/MobileIdentityUIGlue.js
+++ /dev/null
@@ -1,162 +0,0 @@
-/* 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 { interfaces: Ci, utils: Cu, classes: Cc } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/ContentRequestHelper.jsm");
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/MobileIdentityUIGlueCommon.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
- "resource://gre/modules/SystemAppProxy.jsm");
-
-const CHROME_EVENT = "mozMobileIdChromeEvent";
-const CONTENT_EVENT = "mozMobileIdContentEvent";
-const UNSOLICITED_CONTENT_EVENT = "mozMobileIdUnsolContentEvent";
-
-function MobileIdentityUIGlue() {
- SystemAppProxy.addEventListener(UNSOLICITED_CONTENT_EVENT, this);
-}
-
-MobileIdentityUIGlue.prototype = {
-
- __proto__: ContentRequestHelper.prototype,
-
- _sendChromeEvent: function(aEventName, aData) {
- SystemAppProxy._sendCustomEvent(CHROME_EVENT, {
- eventName: aEventName,
- id: uuidgen.generateUUID().toString(),
- data: aData
- });
- },
-
- _oncancel: null,
-
- get oncancel() {
- return this._oncancel;
- },
-
- set oncancel(aCallback) {
- this._oncancel = aCallback;
- },
-
- _onresendcode: null,
-
- get onresendcode() {
- return this._onresendcode;
- },
-
- set onresendcode(aCallback) {
- this._onresendcode = aCallback;
- },
-
- startFlow: function(aManifestURL, aIccInfo) {
- let phoneNumberInfo;
- if (aIccInfo) {
- phoneNumberInfo = [];
- for (var i = 0; i < aIccInfo.length; i++) {
- let iccInfo = aIccInfo[i];
- phoneNumberInfo.push({
- primary: iccInfo.primary,
- msisdn: iccInfo.msisdn,
- operator: iccInfo.operator,
- external: iccInfo.external,
- serviceId: iccInfo.serviceId,
- mcc: iccInfo.mcc
- });
- }
- }
-
- return this.contentRequest(CONTENT_EVENT,
- CHROME_EVENT,
- "onpermissionrequest",
- { phoneNumberInfo: phoneNumberInfo || [],
- manifestURL: aManifestURL })
- .then(
- (result) => {
- if (!result || !result.phoneNumber && !result.serviceId) {
- return Promise.reject(ERROR_INVALID_PROMPT_RESULT);
- }
-
- let promptResult = new MobileIdentityUIGluePromptResult(
- result.phoneNumber || null,
- result.prefix || null,
- result.mcc || null,
- result.serviceId || null
- );
- return promptResult;
- }
- );
- },
-
- verificationCodePrompt: function(aRetriesLeft, aTimeout, aTimeLeft) {
- return this.contentRequest(CONTENT_EVENT,
- CHROME_EVENT,
- "onverificationcode",
- { retriesLeft: aRetriesLeft,
- verificationTimeout: aTimeout,
- verificationTimeoutLeft: aTimeLeft })
- .then(
- (result) => {
- if (!result || !result.verificationCode) {
- return Promise.reject(ERROR_INVALID_VERIFICATION_CODE);
- }
-
- return result.verificationCode;
- }
- );
- },
-
- error: function(aError) {
- log.error("UI error " + aError);
- this._sendChromeEvent("onerror", {
- error: aError
- });
- },
-
- verify: function() {
- this._sendChromeEvent("verify");
- },
-
- verified: function(aVerifiedPhoneNumber) {
- this._sendChromeEvent("onverified", {
- verifiedPhoneNumber: aVerifiedPhoneNumber
- });
- },
-
- handleEvent: function(aEvent) {
- let msg = aEvent.detail;
- if (!msg) {
- log.warning("Got invalid event");
- return;
- }
- log.debug("Got content event ${}", msg);
-
- switch(msg.eventName) {
- case 'cancel':
- this.oncancel();
- break;
- case 'resendcode':
- this.onresendcode();
- break;
- default:
- log.warning("Invalid event name");
- break;
- }
- },
-
- classID: Components.ID("{83dbe26a-81f3-4a75-9541-3d0b7ca496b5}"),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileIdentityUIGlue])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MobileIdentityUIGlue]);
deleted file mode 100644
--- a/b2g/components/PaymentGlue.js
+++ /dev/null
@@ -1,202 +0,0 @@
-/* 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");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-// Type of MozChromEvents to handle payment dialogs.
-const kOpenPaymentConfirmationEvent = "open-payment-confirmation-dialog";
-const kOpenPaymentFlowEvent = "open-payment-flow-dialog";
-const kClosePaymentFlowEvent = "close-payment-flow-dialog";
-
-// Observer notification topic for payment flow cancelation.
-const kPaymentFlowCancelled = "payment-flow-cancelled";
-
-const PREF_DEBUG = "dom.payment.debug";
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
- "resource://gre/modules/SystemAppProxy.jsm");
-
-function PaymentUI() {
- try {
- this._debug =
- Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL
- && Services.prefs.getBoolPref(PREF_DEBUG);
- } catch(e) {
- this._debug = false;
- }
-}
-
-PaymentUI.prototype = {
-
- confirmPaymentRequest: function confirmPaymentRequest(aRequestId,
- aRequests,
- aSuccessCb,
- aErrorCb) {
- let _error = function _error(errorMsg) {
- if (aErrorCb) {
- aErrorCb.onresult(aRequestId, errorMsg);
- }
- };
-
- // 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,
- requestId: aRequestId,
- 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.
- this._handleSelection = (function _handleSelection(evt) {
- let msg = evt.detail;
- if (msg.id != id) {
- return;
- }
-
- if (msg.userSelection && aSuccessCb) {
- aSuccessCb.onresult(aRequestId, msg.userSelection);
- } else if (msg.errorMsg) {
- _error(msg.errorMsg);
- }
-
- SystemAppProxy.removeEventListener("mozContentEvent", this._handleSelection);
- this._handleSelection = null;
- }).bind(this);
- SystemAppProxy.addEventListener("mozContentEvent", this._handleSelection);
-
- SystemAppProxy.dispatchEvent(detail);
- },
-
- showPaymentFlow: function showPaymentFlow(aRequestId,
- aPaymentFlowInfo,
- aErrorCb) {
- let _error = (errorMsg) => {
- if (aErrorCb) {
- aErrorCb.onresult(aRequestId, errorMsg);
- }
- };
-
- // We ask the UI to browse to the selected payment flow.
- let id = kOpenPaymentFlowEvent + "-" + this.getRandomId();
- let detail = {
- type: kOpenPaymentFlowEvent,
- id: id,
- requestId: aRequestId
- };
-
- this._setPaymentRequest = (event) => {
- let message = event.detail;
- if (message.id != id) {
- return;
- }
-
- let frame = message.frame;
- let docshell = frame.contentWindow
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
- docshell.paymentRequestId = aRequestId;
- frame.src = aPaymentFlowInfo.uri + aPaymentFlowInfo.jwt;
- SystemAppProxy.removeEventListener("mozContentEvent",
- this._setPaymentRequest);
- };
- SystemAppProxy.addEventListener("mozContentEvent",
- this._setPaymentRequest);
-
- // We listen for UI notifications about a closed payment flow. The UI
- // should provide the reason of the closure within the 'errorMsg' parameter
- this._notifyPayFlowClosed = (evt) => {
- let msg = evt.detail;
- if (msg.id != id) {
- return;
- }
-
- if (msg.type != 'cancel') {
- return;
- }
-
- if (msg.errorMsg) {
- _error(msg.errorMsg);
- }
-
- SystemAppProxy.removeEventListener("mozContentEvent",
- this._notifyPayFlowClosed);
- this._notifyPayFlowClosed = null;
-
- Services.obs.notifyObservers(null, kPaymentFlowCancelled, null);
- };
- SystemAppProxy.addEventListener("mozContentEvent",
- this._notifyPayFlowClosed);
-
- SystemAppProxy.dispatchEvent(detail);
- },
-
- closePaymentFlow: function(aRequestId) {
- return new Promise((aResolve) => {
- // 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 id = kClosePaymentFlowEvent + "-" + uuidgen.generateUUID().toString();
-
- let detail = {
- type: kClosePaymentFlowEvent,
- id: id,
- requestId: aRequestId
- };
-
- // 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.
- SystemAppProxy.addEventListener("mozContentEvent",
- (function closePaymentFlowReturn() {
- SystemAppProxy.removeEventListener("mozContentEvent",
- closePaymentFlowReturn);
- this.cleanup();
- aResolve();
- }).bind(this));
-
- SystemAppProxy.dispatchEvent(detail);
- });
- },
-
- cleanup: function cleanup() {
- if (this._handleSelection) {
- SystemAppProxy.removeEventListener("mozContentEvent",
- this._handleSelection);
- this._handleSelection = null;
- }
-
- if (this._notifyPayFlowClosed) {
- SystemAppProxy.removeEventListener("mozContentEvent",
- this._notifyPayFlowClosed);
- this._notifyPayFlowClosed = null;
- }
- },
-
- getRandomId: function getRandomId() {
- return uuidgen.generateUUID().toString();
- },
-
- classID: Components.ID("{8b83eabc-7929-47f4-8b48-4dea8d887e4b}"),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue])
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUI]);
deleted file mode 100644
--- a/b2g/components/PaymentProviderStrategy.js
+++ /dev/null
@@ -1,178 +0,0 @@
-/* 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;
-
-const PREF_DEBUG = "dom.payment.debug";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gRil",
- "@mozilla.org/ril;1",
- "nsIRadioInterfaceLayer");
-
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
- "@mozilla.org/settingsService;1",
- "nsISettingsService");
-
-const kMozSettingsChangedObserverTopic = "mozsettings-changed";
-const kRilDefaultDataServiceId = "ril.data.defaultServiceId";
-const kRilDefaultPaymentServiceId = "ril.payment.defaultServiceId";
-
-var _debug;
-try {
- _debug = Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL
- && Services.prefs.getBoolPref(PREF_DEBUG);
-} catch(e){
- _debug = false;
-}
-
-function LOG(s) {
- if (!_debug) {
- return;
- }
- dump("== Payment Provider == " + s + "\n");
-}
-
-function LOGE(s) {
- dump("== Payment Provider ERROR == " + s + "\n");
-}
-
-function PaymentSettings() {
- Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
-
- [kRilDefaultDataServiceId, kRilDefaultPaymentServiceId].forEach(setting => {
- gSettingsService.createLock().get(setting, this);
- });
-}
-
-PaymentSettings.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISettingsServiceCallback,
- Ci.nsIObserver]),
-
- dataServiceId: 0,
- _paymentServiceId: 0,
-
- get paymentServiceId() {
- return this._paymentServiceId;
- },
-
- set paymentServiceId(serviceId) {
- // We allow the payment provider to set the service ID that will be used
- // for the payment process.
- // This service ID will be the one used by the silent SMS flow.
- // If the payment is done with an external SIM, the service ID must be set
- // to null.
- if (serviceId != null && serviceId >= gRil.numRadioInterfaces) {
- LOGE("Invalid service ID " + serviceId);
- return;
- }
-
- gSettingsService.createLock().set(kRilDefaultPaymentServiceId,
- serviceId, 0);
- this._paymentServiceId = serviceId;
- },
-
- setServiceId: function(aName, aValue) {
- switch (aName) {
- case kRilDefaultDataServiceId:
- this.dataServiceId = aValue;
- if (_debug) {
- LOG("dataServiceId " + this.dataServiceId);
- }
- break;
- case kRilDefaultPaymentServiceId:
- this._paymentServiceId = aValue;
- if (_debug) {
- LOG("paymentServiceId " + this._paymentServiceId);
- }
- break;
- }
- },
-
- handle: function(aName, aValue) {
- if (aName != kRilDefaultDataServiceId) {
- return;
- }
-
- this.setServiceId(aName, aValue);
- },
-
- observe: function(aSubject, aTopic, aData) {
- if (aTopic != kMozSettingsChangedObserverTopic) {
- return;
- }
-
- try {
- if ("wrappedJSObject" in aSubject) {
- aSubject = aSubject.wrappedJSObject;
- }
- if (!aSubject.key ||
- (aSubject.key !== kRilDefaultDataServiceId &&
- aSubject.key !== kRilDefaultPaymentServiceId)) {
- return;
- }
- this.setServiceId(aSubject.key, aSubject.value);
- } catch (e) {
- LOGE(e);
- }
- },
-
- cleanup: function() {
- Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic);
- }
-};
-
-function PaymentProviderStrategy() {
- this._settings = new PaymentSettings();
-}
-
-PaymentProviderStrategy.prototype = {
- get paymentServiceId() {
- return this._settings.paymentServiceId;
- },
-
- set paymentServiceId(aServiceId) {
- this._settings.paymentServiceId = aServiceId;
- },
-
- get iccInfo() {
- if (!this._iccInfo) {
- this._iccInfo = [];
- for (let i = 0; i < gRil.numRadioInterfaces; i++) {
- let icc = gIccService.getIccByServiceId(i);
- let info = icc && icc.iccInfo;
- if (!info) {
- LOGE("Tried to get the ICC info for an invalid service ID " + i);
- continue;
- }
-
- this._iccInfo.push({
- iccId: info.iccid,
- mcc: info.mcc,
- mnc: info.mnc,
- dataPrimary: i == this._settings.dataServiceId
- });
- }
- }
- return this._iccInfo;
- },
-
- cleanup: function() {
- this._settings.cleanup();
- },
-
- classID: Components.ID("{4834b2e1-2c91-44ea-b020-e2581ed279a4}"),
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentProviderStrategy])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentProviderStrategy]);
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -12,20 +12,17 @@ EXTRA_COMPONENTS += [
'B2GAppMigrator.js',
'B2GPresentationDevicePrompt.js',
'BootstrapCommandLine.js',
'ContentPermissionPrompt.js',
'FilePicker.js',
'FxAccountsUIGlue.js',
'HelperAppDialog.js',
'MailtoProtocolHandler.js',
- 'MobileIdentityUIGlue.js',
'OMAContentHandler.js',
- 'PaymentGlue.js',
- 'PaymentProviderStrategy.js',
'PresentationRequestUIGlue.js',
'ProcessGlobal.js',
'SmsProtocolHandler.js',
'SystemMessageInternal.js',
'TelProtocolHandler.js',
'WebappsUpdateTimer.js',
]
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -34,17 +34,16 @@ MOZ_USE_NATIVE_POPUP_WINDOWS=1
MOZ_XULRUNNER=
MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
MOZ_TIME_MANAGER=1
MOZ_SIMPLEPUSH=1
-MOZ_PAY=1
MOZ_TOOLKIT_SEARCH=
MOZ_B2G=1
MOZ_JSDOWNLOADS=1
MOZ_BUNDLED_FONTS=1
export JS_GC_SMALL_CHUNK_SIZE=1
--- a/b2g/graphene/confvars.sh
+++ b/b2g/graphene/confvars.sh
@@ -35,17 +35,16 @@ if test "$OS_TARGET" = "Android"; then
MOZ_CAPTURE=1
MOZ_RAW=1
MOZ_AUDIO_CHANNEL_MANAGER=1
fi
MOZ_APP_ID={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
MOZ_TIME_MANAGER=1
-MOZ_PAY=1
MOZ_TOOLKIT_SEARCH=
MOZ_PLACES=
MOZ_B2G=1
MOZ_JSDOWNLOADS=1
MOZ_BUNDLED_FONTS=1
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -181,17 +181,16 @@
@RESPATH@/components/dom_secureelement.xpt
#endif
#ifdef MOZ_NFC
@RESPATH@/components/dom_nfc.xpt
#endif
@RESPATH@/components/dom_notification.xpt
@RESPATH@/components/dom_html.xpt
@RESPATH@/components/dom_offline.xpt
-@RESPATH@/components/dom_payment.xpt
@RESPATH@/components/dom_json.xpt
@RESPATH@/components/dom_messages.xpt
@RESPATH@/components/dom_power.xpt
@RESPATH@/components/dom_push.xpt
@RESPATH@/components/dom_quota.xpt
@RESPATH@/components/dom_range.xpt
@RESPATH@/components/dom_security.xpt
@RESPATH@/components/dom_settings.xpt
@@ -622,21 +621,16 @@
@RESPATH@/components/HCIEventTransactionSystemMessage.manifest
@RESPATH@/components/HCIEventTransactionSystemMessageConfigurator.js
@RESPATH@/components/ActivityProxy.js
@RESPATH@/components/ActivityRequestHandler.js
@RESPATH@/components/ActivityWrapper.js
@RESPATH@/components/ActivityMessageConfigurator.js
-@RESPATH@/components/Payment.js
-@RESPATH@/components/PaymentFlowInfo.js
-@RESPATH@/components/PaymentProvider.js
-@RESPATH@/components/Payment.manifest
-
@RESPATH@/components/DownloadsAPI.js
@RESPATH@/components/DownloadsAPI.manifest
; InputMethod API
@RESPATH@/components/MozKeyboard.js
@RESPATH@/components/InputMethod.manifest
#ifdef MOZ_B2G
@RESPATH@/components/inputmethod.xpt
@@ -868,18 +862,16 @@ bin/libfreebl_32int64_3.so
@RESPATH@/components/ContentPermissionPrompt.js
#ifdef MOZ_UPDATER
@RESPATH@/components/UpdatePrompt.js
#endif
@RESPATH@/components/WebappsUpdateTimer.js
@RESPATH@/components/DirectoryProvider.js
@RESPATH@/components/ProcessGlobal.js
@RESPATH@/components/OMAContentHandler.js
-@RESPATH@/components/PaymentGlue.js
-@RESPATH@/components/PaymentProviderStrategy.js
@RESPATH@/components/RecoveryService.js
@RESPATH@/components/MailtoProtocolHandler.js
@RESPATH@/components/SmsProtocolHandler.js
@RESPATH@/components/TelProtocolHandler.js
@RESPATH@/components/B2GAboutRedirector.js
@RESPATH@/components/FilePicker.js
@RESPATH@/components/HelperAppDialog.js
@RESPATH@/components/DownloadsUI.js
@@ -890,22 +882,16 @@ bin/libfreebl_32int64_3.so
#ifndef MOZ_WIDGET_GONK
@RESPATH@/components/SimulatorScreen.js
#endif
@RESPATH@/components/FxAccountsUIGlue.js
@RESPATH@/components/services_fxaccounts.xpt
-@RESPATH@/components/MobileIdentity.manifest
-@RESPATH@/components/MobileIdentity.js
-@RESPATH@/components/dom_mobileidentity.xpt
-@RESPATH@/components/MobileIdentityUIGlue.js
-@RESPATH@/components/services_mobileidentity.xpt
-
#ifdef MOZ_WEBSPEECH
@RESPATH@/components/dom_webspeechsynth.xpt
#endif
#ifdef XP_MACOSX
@BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
#endif
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -49,18 +49,16 @@ MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3
# If more than one ID is needed, then you should use a comma separated list
# of values.
ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-central
# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t "
MAR_CHANNEL_ID=firefox-mozilla-central
MOZ_PROFILE_MIGRATOR=1
MOZ_APP_STATIC_INI=1
MOZ_WEBGL_CONFORMANT=1
-# Enable navigator.mozPay
-MOZ_PAY=1
MOZ_JSDOWNLOADS=1
MOZ_RUST_MP4PARSE=1
# Enable checking that add-ons are signed by the trusted root
MOZ_ADDON_SIGNING=1
# Include the DevTools client, not just the server (which is the default)
MOZ_DEVTOOLS=all
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -221,17 +221,16 @@
#ifdef MOZ_WEBSPEECH
@RESPATH@/components/dom_webspeechrecognition.xpt
#endif
@RESPATH@/components/dom_workers.xpt
@RESPATH@/components/dom_xbl.xpt
@RESPATH@/components/dom_xhr.xpt
@RESPATH@/components/dom_xpath.xpt
@RESPATH@/components/dom_xul.xpt
-@RESPATH@/components/dom_payment.xpt
@RESPATH@/components/dom_presentation.xpt
@RESPATH@/components/downloads.xpt
@RESPATH@/components/editor.xpt
@RESPATH@/components/embed_base.xpt
@RESPATH@/components/extensions.xpt
@RESPATH@/components/exthandler.xpt
@RESPATH@/components/exthelper.xpt
@RESPATH@/components/fastfind.xpt
@@ -540,20 +539,16 @@
@RESPATH@/components/RemoteWebNavigation.js
@RESPATH@/components/SlowScriptDebug.manifest
@RESPATH@/components/SlowScriptDebug.js
@RESPATH@/components/TVSimulatorService.js
@RESPATH@/components/TVSimulatorService.manifest
-@RESPATH@/components/Payment.js
-@RESPATH@/components/PaymentFlowInfo.js
-@RESPATH@/components/Payment.manifest
-
#ifdef MOZ_WEBRTC
@RESPATH@/components/PeerConnection.js
@RESPATH@/components/PeerConnection.manifest
#endif
@RESPATH@/chrome/marionette@JAREXT@
@RESPATH@/chrome/marionette.manifest
@RESPATH@/components/MarionetteComponents.manifest
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -14553,47 +14553,16 @@ nsDocShell::ChannelIntercepted(nsIInterc
isReload, isSubresourceLoad, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
return NS_OK;
}
-NS_IMETHODIMP
-nsDocShell::SetPaymentRequestId(const nsAString& aPaymentRequestId)
-{
- mPaymentRequestId = aPaymentRequestId;
- return NS_OK;
-}
-
-nsString
-nsDocShell::GetInheritedPaymentRequestId()
-{
- if (!mPaymentRequestId.IsEmpty()) {
- return mPaymentRequestId;
- }
-
- nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
- GetSameTypeParent(getter_AddRefs(parentAsItem));
-
- nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
- if (!parent) {
- return mPaymentRequestId;
- }
- return static_cast<nsDocShell*>(parent.get())->GetInheritedPaymentRequestId();
-}
-
-NS_IMETHODIMP
-nsDocShell::GetPaymentRequestId(nsAString& aPaymentRequestId)
-{
- aPaymentRequestId = GetInheritedPaymentRequestId();
- return NS_OK;
-}
-
bool
nsDocShell::InFrameSwap()
{
RefPtr<nsDocShell> shell = this;
do {
if (shell->mInFrameSwap) {
return true;
}
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -1012,20 +1012,16 @@ protected:
// This represents the state of private browsing in the docshell.
// Currently treated as a binary value: 1 - in private mode, 0 - not private mode
// On content docshells mPrivateBrowsingId == mOriginAttributes.mPrivateBrowsingId
// On chrome docshells this value will be set, but not have the corresponding
// origin attribute set.
uint32_t mPrivateBrowsingId;
- nsString mPaymentRequestId;
-
- nsString GetInheritedPaymentRequestId();
-
nsString mInterceptedDocumentId;
private:
nsCString mForcedCharset;
nsCString mParentCharset;
int32_t mParentCharsetSource;
nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1069,21 +1069,16 @@ interface nsIDocShell : nsIDocShellTreeI
/**
* This attribute determines whether a document which is not about:blank has
* already be loaded by this docShell.
*/
[infallible] readonly attribute boolean hasLoadedNonBlankURI;
/**
- * Holds the id of the payment request associated with this docshell if any.
- */
- attribute DOMString paymentRequestId;
-
- /**
* Allow usage of -moz-window-dragging:drag for content docshells.
* True for top level chrome docshells. Throws if set to false with
* top level chrome docshell.
*/
attribute boolean windowDraggingAllowed;
/**
* Sets/gets the current scroll restoration mode.
--- a/dom/apps/PermissionsTable.jsm
+++ b/dom/apps/PermissionsTable.jsm
@@ -410,21 +410,16 @@ this.PermissionsTable = { geolocation:
privileged: PROMPT_ACTION,
certified: ALLOW_ACTION
},
"feature-detection": {
app: DENY_ACTION,
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
- "mobileid": {
- app: DENY_ACTION,
- privileged: PROMPT_ACTION,
- certified: PROMPT_ACTION
- },
// This permission doesn't actually grant access to
// anything. It exists only to check the correctness
// of web prompt composed permissions in tests.
"test-permission": {
app: PROMPT_ACTION,
privileged: PROMPT_ACTION,
certified: ALLOW_ACTION,
access: ["read", "write", "create"]
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -55,19 +55,16 @@
#include "mozilla/dom/workers/RuntimeService.h"
#include "mozilla/Hal.h"
#include "nsISiteSpecificUserAgent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/StaticPtr.h"
#include "Connection.h"
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
#include "nsGlobalWindow.h"
-#ifdef MOZ_B2G
-#include "nsIMobileIdentityService.h"
-#endif
#ifdef MOZ_B2G_RIL
#include "mozilla/dom/MobileConnectionArray.h"
#endif
#include "nsIIdleObserver.h"
#include "nsIPermissionManager.h"
#include "nsMimeTypes.h"
#include "nsNetUtil.h"
#include "nsStringStream.h"
@@ -122,21 +119,16 @@
#include "mozilla/EMEUtils.h"
#include "mozilla/DetailedPromise.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include <cutils/properties.h>
#endif
-#ifdef MOZ_PAY
-#include "nsIPaymentContentHelperService.h"
-#include "mozilla/dom/DOMRequest.h"
-#endif
-
namespace mozilla {
namespace dom {
static bool sVibratorEnabled = false;
static uint32_t sMaxVibrateMS = 0;
static uint32_t sMaxVibrateListLen = 0;
static const char* kVibrationPermissionType = "vibration";
@@ -1778,23 +1770,16 @@ Navigator::HasFeature(const nsAString& a
return p.forget();
}
if (featureName.EqualsLiteral("Navigator.mozCameras")) {
p->MaybeResolve(true);
return p.forget();
}
-#ifdef MOZ_B2G
- if (featureName.EqualsLiteral("Navigator.getMobileIdAssertion")) {
- p->MaybeResolve(true);
- return p.forget();
- }
-#endif
-
if (featureName.EqualsLiteral("XMLHttpRequest.mozSystem")) {
p->MaybeResolve(true);
return p.forget();
}
p->MaybeResolveWithUndefined();
return p.forget();
}
@@ -1904,55 +1889,16 @@ Navigator::GetInputPortManager(ErrorResu
already_AddRefed<LegacyMozTCPSocket>
Navigator::MozTCPSocket()
{
RefPtr<LegacyMozTCPSocket> socket = new LegacyMozTCPSocket(GetWindow());
return socket.forget();
}
-#ifdef MOZ_B2G
-already_AddRefed<Promise>
-Navigator::GetMobileIdAssertion(const MobileIdOptions& aOptions,
- ErrorResult& aRv)
-{
- if (!mWindow || !mWindow->GetDocShell()) {
- aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
- }
-
- nsCOMPtr<nsIMobileIdentityService> service =
- do_GetService("@mozilla.org/mobileidentity-service;1");
- if (!service) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- JSContext *cx = nsContentUtils::GetCurrentJSContext();
- if (!cx) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- JS::Rooted<JS::Value> optionsValue(cx);
- if (!ToJSValue(cx, aOptions, &optionsValue)) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
-
- nsCOMPtr<nsISupports> promise;
- aRv = service->GetMobileIdAssertion(mWindow,
- optionsValue,
- getter_AddRefs(promise));
-
- RefPtr<Promise> p = static_cast<Promise*>(promise.get());
- return p.forget();
-}
-#endif // MOZ_B2G
-
#ifdef MOZ_B2G_RIL
MobileConnectionArray*
Navigator::GetMozMobileConnections(ErrorResult& aRv)
{
if (!mMobileConnections) {
if (!mWindow) {
aRv.Throw(NS_ERROR_UNEXPECTED);
@@ -2303,83 +2249,30 @@ bool
Navigator::HasUserMediaSupport(JSContext* /* unused */,
JSObject* /* unused */)
{
// Make enabling peerconnection enable getUserMedia() as well
return Preferences::GetBool("media.navigator.enabled", false) ||
Preferences::GetBool("media.peerconnection.enabled", false);
}
-#ifdef MOZ_B2G
-/* static */
-bool
-Navigator::HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal)
-{
- nsCOMPtr<nsPIDOMWindowInner> win = GetWindowFromGlobal(aGlobal);
- if (!win) {
- return false;
- }
-
- nsIDocument* doc = win->GetExtantDoc();
- if (!doc) {
- return false;
- }
-
- nsIPrincipal* principal = doc->NodePrincipal();
- uint32_t permission = GetPermission(principal, "mobileid");
-
- return permission == nsIPermissionManager::PROMPT_ACTION ||
- permission == nsIPermissionManager::ALLOW_ACTION;
-}
-#endif
-
/* static */
bool
Navigator::IsE10sEnabled(JSContext* aCx, JSObject* aGlobal)
{
return XRE_IsContentProcess();
}
bool
Navigator::MozE10sEnabled()
{
// This will only be called if IsE10sEnabled() is true.
return true;
}
-#ifdef MOZ_PAY
-already_AddRefed<DOMRequest>
-Navigator::MozPay(JSContext* aCx,
- JS::Handle<JS::Value> aJwts,
- ErrorResult& aRv)
-{
- if (!mWindow || !mWindow->GetDocShell()) {
- aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
- }
-
- nsresult rv;
- nsCOMPtr<nsIPaymentContentHelperService> service =
- do_GetService("@mozilla.org/payment/content-helper-service;1", &rv);
- if (!service) {
- aRv.Throw(rv);
- return nullptr;
- }
-
- RefPtr<nsIDOMDOMRequest> request;
- rv = service->Pay(mWindow, aJwts, getter_AddRefs(request));
- if (NS_FAILED(rv)) {
- aRv.Throw(rv);
- return nullptr;
- }
-
- return request.forget().downcast<DOMRequest>();
-}
-#endif // MOZ_PAY
-
/* static */
already_AddRefed<nsPIDOMWindowInner>
Navigator::GetWindowFromGlobal(JSObject* aGlobal)
{
nsCOMPtr<nsPIDOMWindowInner> win =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
MOZ_ASSERT(!win || win->IsInnerWindow());
return win.forget();
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -34,17 +34,16 @@ class nsIURI;
namespace mozilla {
namespace dom {
class Geolocation;
class systemMessageCallback;
class MediaDevices;
struct MediaStreamConstraints;
class WakeLock;
class ArrayBufferViewOrBlobOrStringOrFormData;
-struct MobileIdOptions;
class ServiceWorkerContainer;
class DOMRequest;
struct FlyWebPublishOptions;
struct FlyWebFilter;
} // namespace dom
} // namespace mozilla
//*****************************************************************************
@@ -245,20 +244,16 @@ public:
Voicemail* GetMozVoicemail(ErrorResult& aRv);
TVManager* GetTv();
InputPortManager* GetInputPortManager(ErrorResult& aRv);
already_AddRefed<LegacyMozTCPSocket> MozTCPSocket();
network::Connection* GetConnection(ErrorResult& aRv);
nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
MediaDevices* GetMediaDevices(ErrorResult& aRv);
-#ifdef MOZ_B2G
- already_AddRefed<Promise> GetMobileIdAssertion(const MobileIdOptions& options,
- ErrorResult& aRv);
-#endif
#ifdef MOZ_B2G_RIL
MobileConnectionArray* GetMozMobileConnections(ErrorResult& aRv);
#endif // MOZ_B2G_RIL
#ifdef MOZ_GAMEPAD
void GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
GamepadServiceTest* RequestGamepadServiceTest();
#endif // MOZ_GAMEPAD
already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
@@ -294,40 +289,30 @@ public:
ErrorResult& aRv);
already_AddRefed<ServiceWorkerContainer> ServiceWorker();
void GetLanguages(nsTArray<nsString>& aLanguages);
bool MozE10sEnabled();
-#ifdef MOZ_PAY
- already_AddRefed<DOMRequest> MozPay(JSContext* aCx,
- JS::Handle<JS::Value> aJwts,
- ErrorResult& aRv);
-#endif // MOZ_PAY
-
static void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
// WebIDL helper methods
static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */);
static bool HasCameraSupport(JSContext* /* unused */,
JSObject* aGlobal);
static bool HasWifiManagerSupport(JSContext* /* unused */,
JSObject* aGlobal);
#ifdef MOZ_NFC
static bool HasNFCSupport(JSContext* /* unused */, JSObject* aGlobal);
#endif // MOZ_NFC
static bool HasUserMediaSupport(JSContext* /* unused */,
JSObject* /* unused */);
-#ifdef MOZ_B2G
- static bool HasMobileIdSupport(JSContext* aCx, JSObject* aGlobal);
-#endif
-
static bool IsE10sEnabled(JSContext* aCx, JSObject* aGlobal);
nsPIDOMWindowInner* GetParentObject() const
{
return GetWindow();
}
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
--- a/dom/base/test/test_hasFeature.html
+++ b/dom/base/test/test_hasFeature.html
@@ -34,17 +34,16 @@ function testAPIs() {
{ name: "Navigator.push", enabled: pref("services.push.enabled") },
// { name: "Navigator.mozTime", enabled: b2gOnly }, // conditional on MOZ_TIME_MANAGER, tricky to test
// { name: "Navigator.mozFMRadio", enabled: b2gOnly }, // conditional on MOZ_B2G_FM, tricky to test
{ name: "Navigator.mozCameras", enabled: true },
{ name: "Navigator.mozAlarms", enabled: pref("dom.mozAlarms.enabled") },
{ name: "Navigator.mozTCPSocket", enabled: pref("dom.mozTCPSocket.enabled") },
{ name: "Navigator.mozInputMethod", enabled: pref("dom.mozInputMethod.enabled") },
{ name: "Navigator.mozMobileConnections", enabled: pref("dom.mobileconnection.enabled") },
- { name: "Navigator.getMobileIdAssertion", enabled: b2gOnly },
{ name: "XMLHttpRequest.mozSystem", enabled: true }
];
var promises = [];
APIEndPoints.forEach(function(v) {
promises.push(navigator.hasFeature("api.window." + v.name));
});
deleted file mode 100644
--- a/dom/mobileid/MobileIdentity.js
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* 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/DOMRequestHelper.jsm");
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const MOBILEIDSERVICE_CID =
- Components.ID("{6ec1806c-d61f-4724-9495-68c26d46dc53}");
-
-const IPC_MSG_NAMES = ["MobileId:GetAssertion:Return:OK",
- "MobileId:GetAssertion:Return:KO"];
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsIMessageSender");
-
-function MobileIdentityService() {
-}
-
-MobileIdentityService.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
- // TODO: this should be handled by DOMRequestIpcHelper. Bug 1020582
- _windows: {},
-
- getMobileIdAssertion: function(aWindow, aOptions) {
- log.debug("getMobileIdAssertion");
-
- if (!this.init) {
- this.initDOMRequestHelper(aWindow, IPC_MSG_NAMES);
- this.init = true;
- }
-
- return new aWindow.Promise(
- (resolve, reject) => {
- let promiseId = this.getPromiseResolverId({
- resolve: resolve,
- reject: reject
- });
-
- this._windows[promiseId] = aWindow;
-
- cpmm.sendAsyncMessage("MobileId:GetAssertion", {
- promiseId: promiseId,
- options: aOptions
- }, null, aWindow.document.nodePrincipal);
- }
- );
- },
-
- receiveMessage: function(aMessage) {
- let name = aMessage.name;
- let msg = aMessage.json;
-
- log.debug("Received message " + name + ": " + JSON.stringify(msg));
-
- let promiseId = msg.promiseId || msg.requestID;
- let promise = this.takePromiseResolver(promiseId);
- if (!promise) {
- log.error("Promise not found");
- return;
- }
-
- let _window = this._windows[promiseId];
- delete this._windows[promiseId];
- if (!_window) {
- log.error("No window object found");
- return;
- }
-
- switch (name) {
- case "MobileId:GetAssertion:Return:OK":
- if (!msg.result) {
- promise.reject(new _window.DOMError(ERROR_INTERNAL_UNEXPECTED));
- }
-
- // Return the assertion
- promise.resolve(msg.result);
- break;
- case "MobileId:GetAssertion:Return:KO":
- promise.reject(new _window.DOMError(msg.error || ERROR_UNKNOWN));
- break;
- }
- },
-
- classID: MOBILEIDSERVICE_CID,
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileIdentityService,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver]),
-
- classInfo: XPCOMUtils.generateCI({
- classID: MOBILEIDSERVICE_CID,
- contractID: "@mozilla.org/mobileidentity-service;1",
- interfaces: [Ci.nsIMobileIdentityService],
- flags: Ci.nsIClassInfo.SINGLETON
- })
-
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MobileIdentityService]);
deleted file mode 100644
--- a/dom/mobileid/MobileIdentity.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {6ec1806c-d61f-4724-9495-68c26d46dc53} MobileIdentity.js
-contract @mozilla.org/mobileidentity-service;1 {6ec1806c-d61f-4724-9495-68c26d46dc53}
deleted file mode 100644
--- a/dom/mobileid/interfaces/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-XPIDL_SOURCES += [
- 'nsIMobileIdentityService.idl',
-]
-
-XPIDL_MODULE = 'dom_mobileidentity'
deleted file mode 100644
--- a/dom/mobileid/interfaces/nsIMobileIdentityService.idl
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 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/. */
-
-#include "nsISupports.idl"
-
-interface mozIDOMWindow;
-
-[scriptable, uuid(c03d38e3-bae6-4b62-ae96-cf8acc1501ec)]
-interface nsIMobileIdentityService : nsISupports
-{
- nsISupports getMobileIdAssertion(in mozIDOMWindow window,
- in jsval options);
-};
deleted file mode 100644
--- a/dom/mobileid/moz.build
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DIRS += ['interfaces']
-
-MOCHITEST_MANIFESTS += ['test/mochitest.ini']
-
-EXTRA_COMPONENTS += [
- 'MobileIdentity.js',
- 'MobileIdentity.manifest',
-]
deleted file mode 100644
--- a/dom/mobileid/test/mochitest.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[DEFAULT]
-skip-if = (buildapp != 'b2g')
-
-[test_mobileid_basics.html]
-[test_mobileid_no_permission.html]
deleted file mode 100644
--- a/dom/mobileid/test/test_mobileid_basics.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <title>Test for navigator.getMobileIdAssertion</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-const MOCK_CID = SpecialPowers.wrap(SpecialPowers.Components)
- .ID("{4cb9b8b3-bc8c-46c0-a2b6-2eb0b1ffce94}");
-const MOBILE_ID_SERVICE_CONTRACT_ID = "@mozilla.org/mobileidentity-service;1";
-
-function finish() {
- SpecialPowers.wrap(SpecialPowers.Components).manager
- .QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar)
- .unregisterFactory(MOCK_CID, mockMobileIdService);
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-
-var mockMobileIdService = {
- QueryInterface: function(aIID) {
- if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
- SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIMobileIdentityService)) {
- return this;
- }
- throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
- },
-
- createInstance: function(aOuter, aIID) {
- if (aOuter != null) {
- throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
- }
- return this.QueryInterface(aIID);
- },
-
- getMobileIdAssertion: function(aWindow, aOptions) {
- return new Promise(function(resolve, reject) {
- resolve(aOptions);
- });
- }
-};
-mockMobileIdService = SpecialPowers.wrapCallbackObject(mockMobileIdService);
-
-SpecialPowers.wrap(SpecialPowers.Components).manager
- .QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar)
- .registerFactory(MOCK_CID, "mobileid service",
- MOBILE_ID_SERVICE_CONTRACT_ID,
- mockMobileIdService);
-
-// Tests
-
-SpecialPowers.pushPermissions([{"type": "mobileid",
- "allow": 1,
- "context": document}], function() {
- ok("getMobileIdAssertion" in navigator,
- "navigator.getMobileIdAssertion should exist");
-
- var options = { forceSelection: true };
- var promise = navigator.getMobileIdAssertion(options)
- .then(function(result) {
- ok(promise instanceof Promise, "Should return a Promise");
- is(result.forceSelection, options.forceSelection,
- "MobileIdentityService should receive correct options");
- finish();
- });
-});
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/mobileid/test/test_mobileid_no_permission.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <title>Test for navigator.getMobileIdAssertion - No permission</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-ok(!("getMobileIdAssertion" in navigator),
- "navigator.getMobileIdAssertion should NOT exist");
-
-SimpleTest.finish();
-</script>
-</pre>
-</body>
-</html>
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -127,35 +127,31 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
'wifi',
]
if CONFIG['MOZ_B2G_RIL']:
DIRS += [
'wappush',
]
-if CONFIG['MOZ_PAY']:
- DIRS += ['payment']
-
if CONFIG['MOZ_NFC']:
DIRS += ['nfc']
if CONFIG['MOZ_SIMPLEPUSH']:
DIRS += ['simplepush']
else:
DIRS += ['push']
if CONFIG['MOZ_SECUREELEMENT']:
DIRS += ['secureelement']
if CONFIG['MOZ_B2G']:
DIRS += [
'downloads',
- 'identity',
- 'mobileid'
+ 'identity'
]
DIRS += ['presentation']
TEST_DIRS += [
'tests',
'imptests',
]
deleted file mode 100644
--- a/dom/payment/Payment.js
+++ /dev/null
@@ -1,120 +0,0 @@
-/* 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");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-const PAYMENT_IPC_MSG_NAMES = ["Payment:Success",
- "Payment:Failed"];
-
-const PREF_DEBUG = "dom.payment.debug";
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsIMessageSender");
-
-var _debug;
-try {
- _debug = Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL
- && Services.prefs.getBoolPref(PREF_DEBUG);
-} catch(e) {
- _debug = false;
-}
-
-function LOG(s) {
- if (!_debug) {
- return;
- }
- dump("-*- PaymentContentHelper: " + s + "\n");
-}
-
-function PaymentContentHelper(aWindow) {
- this.initDOMRequestHelper(aWindow, PAYMENT_IPC_MSG_NAMES);
-};
-
-PaymentContentHelper.prototype = {
- __proto__: DOMRequestIpcHelper.prototype,
-
- receiveMessage: function receiveMessage(aMessage) {
- let name = aMessage.name;
- let msg = aMessage.json;
- if (_debug) {
- LOG("Received message '" + name + "': " + JSON.stringify(msg));
- }
- let requestId = msg.requestId;
- let request = this.takeRequest(requestId);
- if (!request) {
- return;
- }
- switch (name) {
- case "Payment:Success":
- Services.DOMRequest.fireSuccess(request, msg.result);
- break;
- case "Payment:Failed":
- Services.DOMRequest.fireError(request, msg.errorMsg);
- break;
- }
- },
-};
-
-function PaymentContentHelperService() {
-};
-
-PaymentContentHelperService.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentContentHelperService]),
- classID: Components.ID("{80035846-6732-4fcc-961b-f336b65218f4}"),
- contractID: "@mozilla.org/payment/content-helper-service;1",
-
- _xpcom_factory: XPCOMUtils.generateSingletonFactory(PaymentContentHelperService),
-
- // keys are windows and values are PaymentContentHelpers
- helpers: new WeakMap(),
-
- // nsINavigatorPayment
- pay: function pay(aWindow, aJwts) {
- let requestHelper = this.helpers.get(aWindow);
- if (!requestHelper) {
- requestHelper = new PaymentContentHelper(aWindow);
- this.helpers.set(aWindow, requestHelper);
- }
- let request = requestHelper.createRequest();
- let requestId = requestHelper.getRequestId(request);
-
- let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
- if (!docShell.isActive) {
- if (_debug) {
- LOG("The caller application is a background app. No request will be " +
- "sent");
- }
-
- let runnable = {
- run: function run() {
- Services.DOMRequest.fireError(request, "BACKGROUND_APP");
- }
- }
- Services.tm.currentThread.dispatch(runnable,
- Ci.nsIThread.DISPATCH_NORMAL);
- return request;
- }
-
- if (!Array.isArray(aJwts)) {
- aJwts = [aJwts];
- }
-
- cpmm.sendAsyncMessage("Payment:Pay", {
- jwts: aJwts,
- requestId: requestId
- });
- return request;
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentContentHelperService]);
deleted file mode 100644
--- a/dom/payment/Payment.jsm
+++ /dev/null
@@ -1,422 +0,0 @@
-/* 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");
-
-this.EXPORTED_SYMBOLS = [];
-
-const PAYMENT_IPC_MSG_NAMES = ["Payment:Pay",
- "Payment:Success",
- "Payment:Failed"];
-
-const PREF_PAYMENTPROVIDERS_BRANCH = "dom.payment.provider.";
-const PREF_PAYMENT_BRANCH = "dom.payment.";
-const PREF_DEBUG = "dom.payment.debug";
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageListenerManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "prefService",
- "@mozilla.org/preferences-service;1",
- "nsIPrefService");
-
-var PaymentManager = {
- init: function init() {
- // Payment providers data are stored as a preference.
- this.registeredProviders = null;
-
- this.messageManagers = {};
-
- // The dom.payment.skipHTTPSCheck pref is supposed to be used only during
- // development process. This preference should not be active for a
- // production build.
- let paymentPrefs = prefService.getBranch(PREF_PAYMENT_BRANCH);
- this.checkHttps = true;
- try {
- if (paymentPrefs.getPrefType("skipHTTPSCheck")) {
- this.checkHttps = !paymentPrefs.getBoolPref("skipHTTPSCheck");
- }
- } catch(e) {}
-
- for (let msgname of PAYMENT_IPC_MSG_NAMES) {
- ppmm.addMessageListener(msgname, this);
- }
-
- Services.obs.addObserver(this, "xpcom-shutdown", false);
-
- try {
- this._debug =
- Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL
- && Services.prefs.getBoolPref(PREF_DEBUG);
- } catch(e) {
- this._debug = false;
- }
- },
-
- /**
- * Process a message from the content process.
- */
- receiveMessage: function receiveMessage(aMessage) {
- let name = aMessage.name;
- let msg = aMessage.json;
- if (this._debug) {
- this.LOG("Received '" + name + "' message from content process");
- }
-
- switch (name) {
- case "Payment:Pay": {
- // First of all, we register the payment providers.
- if (!this.registeredProviders) {
- this.registeredProviders = {};
- this.registerPaymentProviders();
- }
-
- // We save the message target message manager so we can later dispatch
- // back messages without broadcasting to all child processes.
- let requestId = msg.requestId;
- this.messageManagers[requestId] = aMessage.target;
-
- // We check the jwt type and look for a match within the
- // registered payment providers to get the correct payment request
- // information.
- let paymentRequests = [];
- let jwtTypes = [];
- for (let i in msg.jwts) {
- let pr = this.getPaymentRequestInfo(requestId, msg.jwts[i]);
- if (!pr) {
- continue;
- }
- // We consider jwt type repetition an error.
- if (jwtTypes[pr.type]) {
- this.paymentFailed(requestId,
- "PAY_REQUEST_ERROR_DUPLICATED_JWT_TYPE");
- return;
- }
- jwtTypes[pr.type] = true;
- paymentRequests.push(pr);
- }
-
- if (!paymentRequests.length) {
- this.paymentFailed(requestId,
- "PAY_REQUEST_ERROR_NO_VALID_REQUEST_FOUND");
- return;
- }
-
- // After getting the list of valid payment requests, we ask the user
- // for confirmation before sending any request to any payment provider.
- // If there is more than one choice, we also let the user select the one
- // that he prefers.
- let glue = Cc["@mozilla.org/payment/ui-glue;1"]
- .createInstance(Ci.nsIPaymentUIGlue);
- if (!glue) {
- if (this._debug) {
- this.LOG("Could not create nsIPaymentUIGlue instance");
- }
- this.paymentFailed(requestId,
- "INTERNAL_ERROR_CREATE_PAYMENT_GLUE_FAILED");
- return;
- }
-
- let confirmPaymentSuccessCb = function successCb(aRequestId,
- aResult) {
- // Get the appropriate payment provider data based on user's choice.
- let selectedProvider = this.registeredProviders[aResult];
- if (!selectedProvider || !selectedProvider.uri) {
- if (this._debug) {
- this.LOG("Could not retrieve a valid provider based on user's " +
- "selection");
- }
- this.paymentFailed(aRequestId,
- "INTERNAL_ERROR_NO_VALID_SELECTED_PROVIDER");
- return;
- }
-
- let jwt;
- for (let i in paymentRequests) {
- if (paymentRequests[i].type == aResult) {
- jwt = paymentRequests[i].jwt;
- break;
- }
- }
- if (!jwt) {
- if (this._debug) {
- this.LOG("The selected request has no JWT information " +
- "associated");
- }
- this.paymentFailed(aRequestId,
- "INTERNAL_ERROR_NO_JWT_ASSOCIATED_TO_REQUEST");
- return;
- }
-
- this.showPaymentFlow(aRequestId, selectedProvider, jwt);
- };
-
- let confirmPaymentErrorCb = this.paymentFailed;
-
- glue.confirmPaymentRequest(requestId,
- paymentRequests,
- confirmPaymentSuccessCb.bind(this),
- confirmPaymentErrorCb.bind(this));
- break;
- }
- case "Payment:Success":
- case "Payment:Failed": {
- let mm = this.messageManagers[msg.requestId];
- mm.sendAsyncMessage(name, {
- requestId: msg.requestId,
- result: msg.result,
- errorMsg: msg.errorMsg
- });
- break;
- }
- }
- },
-
- /**
- * Helper function to register payment providers stored as preferences.
- */
- registerPaymentProviders: function registerPaymentProviders() {
- let paymentProviders = prefService
- .getBranch(PREF_PAYMENTPROVIDERS_BRANCH)
- .getChildList("");
-
- // First get the numbers of the providers by getting all ###.uri prefs.
- let nums = [];
- for (let i in paymentProviders) {
- let match = /^(\d+)\.uri$/.exec(paymentProviders[i]);
- if (!match) {
- continue;
- } else {
- nums.push(match[1]);
- }
- }
-
-#ifdef MOZ_B2G
- let appsService = Cc["@mozilla.org/AppsService;1"]
- .getService(Ci.nsIAppsService);
- let systemAppId = Ci.nsIScriptSecurityManager.NO_APP_ID;
-
- try {
- let manifestURL = Services.prefs.getCharPref("b2g.system_manifest_url");
- systemAppId = appsService.getAppLocalIdByManifestURL(manifestURL);
- this.LOG("System app id=" + systemAppId);
- } catch(e) {}
-#endif
-
- // Now register the payment providers.
- for (let i in nums) {
- let branch = prefService
- .getBranch(PREF_PAYMENTPROVIDERS_BRANCH + nums[i] + ".");
- let vals = branch.getChildList("");
- if (vals.length == 0) {
- return;
- }
- try {
- let type = branch.getCharPref("type");
- if (type in this.registeredProviders) {
- continue;
- }
- let provider = this.registeredProviders[type] = {
- name: branch.getCharPref("name"),
- uri: branch.getCharPref("uri"),
- description: branch.getCharPref("description"),
- requestMethod: branch.getCharPref("requestMethod")
- };
-
-#ifdef MOZ_B2G
- // Let this payment provider access the firefox-accounts API when
- // it's loaded in the trusted UI.
- if (systemAppId != Ci.nsIScriptSecurityManager.NO_APP_ID) {
- this.LOG("Granting firefox-accounts permission to " + provider.uri);
- let uri = Services.io.newURI(provider.uri, null, null);
- let attrs = {appId: systemAppId, inIsolatedMozBrowser: true};
- let principal =
- Services.scriptSecurityManager.createCodebasePrincipal(uri, attrs);
-
- Services.perms.addFromPrincipal(principal, "firefox-accounts",
- Ci.nsIPermissionManager.ALLOW_ACTION,
- Ci.nsIPermissionManager.EXPIRE_SESSION);
- }
-#endif
-
- if (this._debug) {
- this.LOG("Registered Payment Providers: " +
- JSON.stringify(this.registeredProviders[type]));
- }
- } catch (ex) {
- if (this._debug) {
- this.LOG("An error ocurred registering a payment provider. " + ex);
- }
- }
- }
- },
-
- /**
- * Helper for sending a Payment:Failed message to the parent process.
- */
- paymentFailed: function paymentFailed(aRequestId, aErrorMsg) {
- let mm = this.messageManagers[aRequestId];
- mm.sendAsyncMessage("Payment:Failed", {
- requestId: aRequestId,
- errorMsg: aErrorMsg
- });
- },
-
- /**
- * Helper function to get the payment request info according to the jwt
- * type. Payment provider's data is stored as a preference.
- */
- getPaymentRequestInfo: function getPaymentRequestInfo(aRequestId, aJwt) {
- if (!aJwt) {
- this.paymentFailed(aRequestId, "INTERNAL_ERROR_CALL_WITH_MISSING_JWT");
- return true;
- }
-
- // First thing, we check that the jwt type is an allowed type and has a
- // payment provider flow information associated.
-
- // A jwt string consists in three parts separated by period ('.'): header,
- // payload and signature.
- let segments = aJwt.split('.');
- if (segments.length !== 3) {
- if (this._debug) {
- this.LOG("Error getting payment provider's uri. " +
- "Not enough or too many segments");
- }
- this.paymentFailed(aRequestId,
- "PAY_REQUEST_ERROR_WRONG_SEGMENTS_COUNT");
- return true;
- }
-
- let payloadObject;
- try {
- // We only care about the payload segment, which contains the jwt type
- // that should match with any of the stored payment provider's data and
- // the payment request information to be shown to the user.
- // Before decoding the JWT string we need to normalize it to be compliant
- // with RFC 4648.
- segments[1] = segments[1].replace(/-/g, "+").replace(/_/g, "/");
- let payload = atob(segments[1]);
- if (this._debug) {
- this.LOG("Payload " + payload);
- }
- if (!payload.length) {
- this.paymentFailed(aRequestId, "PAY_REQUEST_ERROR_EMPTY_PAYLOAD");
- return true;
- }
- payloadObject = JSON.parse(payload);
- if (!payloadObject) {
- this.paymentFailed(aRequestId,
- "PAY_REQUEST_ERROR_ERROR_PARSING_JWT_PAYLOAD");
- return true;
- }
- } catch (e) {
- this.paymentFailed(aRequestId,
- "PAY_REQUEST_ERROR_ERROR_DECODING_JWT");
- return true;
- }
-
- if (!payloadObject.typ) {
- this.paymentFailed(aRequestId,
- "PAY_REQUEST_ERROR_NO_TYP_PARAMETER");
- return true;
- }
-
- if (!payloadObject.request) {
- this.paymentFailed(aRequestId,
- "PAY_REQUEST_ERROR_NO_REQUEST_PARAMETER");
- return true;
- }
-
- // Once we got the jwt 'typ' value we look for a match within the payment
- // providers stored preferences. If the jwt 'typ' is not recognized as one
- // of the allowed values for registered payment providers, we skip the jwt
- // validation but we don't fire any error. This way developers might have
- // a default set of well formed JWTs that might be used in different B2G
- // devices with a different set of allowed payment providers.
- let provider = this.registeredProviders[payloadObject.typ];
- if (!provider) {
- if (this._debug) {
- this.LOG("Not registered payment provider for jwt type: " +
- payloadObject.typ);
- }
- return false;
- }
-
- if (!provider.uri || !provider.name) {
- this.paymentFailed(aRequestId,
- "INTERNAL_ERROR_WRONG_REGISTERED_PAY_PROVIDER");
- return true;
- }
-
- // We only allow https for payment providers uris.
- if (this.checkHttps && !/^https/.exec(provider.uri.toLowerCase())) {
- // We should never get this far.
- if (this._debug) {
- this.LOG("Payment provider uris must be https: " + provider.uri);
- }
- this.paymentFailed(aRequestId,
- "INTERNAL_ERROR_NON_HTTPS_PROVIDER_URI");
- return true;
- }
-
- let pldRequest = payloadObject.request;
- return { jwt: aJwt, type: payloadObject.typ, providerName: provider.name };
- },
-
- showPaymentFlow: function showPaymentFlow(aRequestId,
- aPaymentProvider,
- aJwt) {
- let paymentFlowInfo = Cc["@mozilla.org/payment/flow-info;1"]
- .createInstance(Ci.nsIPaymentFlowInfo);
- paymentFlowInfo.uri = aPaymentProvider.uri;
- paymentFlowInfo.requestMethod = aPaymentProvider.requestMethod;
- paymentFlowInfo.jwt = aJwt;
- paymentFlowInfo.name = aPaymentProvider.name;
- paymentFlowInfo.description = aPaymentProvider.description;
-
- let glue = Cc["@mozilla.org/payment/ui-glue;1"]
- .createInstance(Ci.nsIPaymentUIGlue);
- if (!glue) {
- if (this._debug) {
- this.LOG("Could not create nsIPaymentUIGlue instance");
- }
- this.paymentFailed(aRequestId,
- "INTERNAL_ERROR_CREATE_PAYMENT_GLUE_FAILED");
- return false;
- }
- glue.showPaymentFlow(aRequestId,
- paymentFlowInfo,
- this.paymentFailed.bind(this));
- },
-
- // nsIObserver
-
- observe: function observe(subject, topic, data) {
- if (topic == "xpcom-shutdown") {
- for (let msgname of PAYMENT_IPC_MSG_NAMES) {
- ppmm.removeMessageListener(msgname, this);
- }
- this.registeredProviders = null;
- this.messageManagers = null;
-
- Services.obs.removeObserver(this, "xpcom-shutdown");
- }
- },
-
- LOG: function LOG(s) {
- if (!this._debug) {
- return;
- }
- dump("-*- PaymentManager: " + s + "\n");
- }
-};
-
-PaymentManager.init();
deleted file mode 100644
--- a/dom/payment/Payment.manifest
+++ /dev/null
@@ -1,8 +0,0 @@
-component {80035846-6732-4fcc-961b-f336b65218f4} Payment.js
-contract @mozilla.org/payment/content-helper-service;1 {80035846-6732-4fcc-961b-f336b65218f4}
-
-component {b8bce4e7-fbf0-4719-a634-b1bf9018657c} PaymentFlowInfo.js
-contract @mozilla.org/payment/flow-info;1 {b8bce4e7-fbf0-4719-a634-b1bf9018657c}
-
-component {82144756-72ab-45b7-8621-f3dad431dd2f} PaymentProvider.js
-contract @mozilla.org/payment/provider;1 {82144756-72ab-45b7-8621-f3dad431dd2f}
deleted file mode 100644
--- a/dom/payment/PaymentFlowInfo.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* 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");
-
-function PaymentFlowInfo() {
-};
-
-PaymentFlowInfo.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentFlowInfo]),
- classID: Components.ID("{b8bce4e7-fbf0-4719-a634-b1bf9018657c}"),
- uri: null,
- jwt: null,
- requestMethod: null,
- name: null,
- description: null
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentFlowInfo]);
deleted file mode 100644
--- a/dom/payment/PaymentProvider.js
+++ /dev/null
@@ -1,306 +0,0 @@
-/* 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, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
- "@mozilla.org/childprocessmessagemanager;1",
- "nsIMessageSender");
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-
-const PREF_DEBUG = "dom.payment.debug";
-
-var _debug;
-try {
- _debug = Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL
- && Services.prefs.getBoolPref(PREF_DEBUG);
-} catch(e) {
- _debug = false;
-}
-
-function DEBUG(s) {
- if (!_debug) {
- return;
- }
- dump("== Payment Provider == " + s + "\n");
-}
-
-function DEBUG_E(s) {
- dump("== Payment Provider ERROR == " + s + "\n");
-}
-
-const kPaymentFlowCancelled = "payment-flow-cancelled";
-
-function PaymentProvider() {
-}
-
-PaymentProvider.prototype = {
- init: function(aWindow) {
- let docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
- this._requestId = docshell.paymentRequestId;
- this._oncancelObserver = this.oncancel.bind(this);
- Services.obs.addObserver(this._oncancelObserver,
- kPaymentFlowCancelled,
- false);
- this._strategy = Cc["@mozilla.org/payment/provider-strategy;1"]
- .createInstance(Ci.nsIPaymentProviderStrategy);
- this._window = aWindow;
- },
-
- paymentSuccess: function(aResult) {
- _debug && DEBUG("paymentSuccess " + aResult);
- let glue = Cc["@mozilla.org/payment/ui-glue;1"]
- .createInstance(Ci.nsIPaymentUIGlue);
- glue.closePaymentFlow(this._requestId).then(() => {
- if (!this._requestId) {
- return;
- }
- cpmm.sendAsyncMessage("Payment:Success", { result: aResult,
- requestId: this._requestId });
- });
- },
-
- paymentFailed: function(aError) {
- _debug && DEBUG("paymentFailed " + aError);
- let glue = Cc["@mozilla.org/payment/ui-glue;1"]
- .createInstance(Ci.nsIPaymentUIGlue);
- glue.closePaymentFlow(this._requestId).then(() => {
- if (!this._requestId) {
- return;
- }
- cpmm.sendAsyncMessage("Payment:Failed", { errorMsg: aError,
- requestId: this._requestId });
- });
-
- },
-
- get paymentServiceId() {
- return this._strategy.paymentServiceId;
- },
-
- set paymentServiceId(aServiceId) {
- this._strategy.paymentServiceId = aServiceId;
- },
-
- /**
- * We expose to the payment provider the information of all the SIMs
- * available in the device. iccInfo is an object of this form:
- * {
- * "serviceId1": {
- * mcc: <string>,
- * mnc: <string>,
- * iccId: <string>,
- * dataPrimary: <boolean>
- * },
- * "serviceIdN": {...}
- * }
- */
- get iccInfo() {
- return this._strategy.iccInfo;
- },
-
- oncancel: function() {
- _debug && DEBUG("Cleaning up!");
-
- this._strategy.cleanup();
- Services.obs.removeObserver(this._oncancelObserver, kPaymentFlowCancelled);
- if (this._cleanup) {
- this._cleanup();
- }
- },
-
- classID: Components.ID("{82144756-72ab-45b7-8621-f3dad431dd2f}"),
-
- contractID: "@mozilla.org/payment/provider;1",
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
- Ci.nsIObserver,
- Ci.nsIDOMGlobalPropertyInitializer])
-};
-
-#if defined(MOZ_B2G_RIL) || defined(MOZ_WIDGET_ANDROID)
-
-XPCOMUtils.defineLazyServiceGetter(this, "smsService",
- "@mozilla.org/sms/smsservice;1",
- "nsISmsService");
-
-const kSilentSmsReceivedTopic = "silent-sms-received";
-
-// In order to send messages through nsISmsService, we need to implement
-// nsIMobileMessageCallback, as the WebSMS API implementation is not usable
-// from JS.
-function SilentSmsRequest(aDOMRequest) {
- this.request = aDOMRequest;
-}
-
-SilentSmsRequest.prototype = {
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileMessageCallback]),
-
- classID: Components.ID("{1d58889c-5660-4cca-a8fd-97ef63e5d3b2}"),
-
- notifyMessageSent: function notifyMessageSent(aMessage) {
- _debug && DEBUG("Silent message successfully sent");
- Services.DOMRequest.fireSuccessAsync(this.request, aMessage);
- },
-
- notifySendMessageFailed: function notifySendMessageFailed(aError) {
- DEBUG_E("Error sending silent message " + aError);
- Services.DOMRequest.fireErrorAsync(this.request, aError);
- }
-};
-
-PaymentProvider.prototype._silentNumbers = null;
-
-PaymentProvider.prototype._silentSmsObservers = null;
-
-PaymentProvider.prototype.sendSilentSms = function(aNumber, aMessage) {
- _debug && DEBUG("Sending silent message " + aNumber + " - " + aMessage);
-
- let request = Services.DOMRequest.createRequest(this._window);
-
- if (this._strategy.paymentServiceId === null) {
- DEBUG_E("No payment service ID set. Cannot send silent SMS");
- Services.DOMRequest.fireErrorAsync(request,
- "NO_PAYMENT_SERVICE_ID");
- return request;
- }
-
- let smsRequest = new SilentSmsRequest(request);
- smsService.send(this._strategy.paymentServiceId, aNumber, aMessage, true,
- smsRequest);
- return request;
-};
-
-PaymentProvider.prototype.observeSilentSms = function(aNumber, aCallback) {
- _debug && DEBUG("observeSilentSms " + aNumber);
-
- if (!this._silentSmsObservers) {
- this._silentSmsObservers = {};
- this._silentNumbers = [];
- this._onSilentSmsObserver = this._onSilentSms.bind(this);
- Services.obs.addObserver(this._onSilentSmsObserver,
- kSilentSmsReceivedTopic,
- false);
- }
-
- if (!this._silentSmsObservers[aNumber]) {
- this._silentSmsObservers[aNumber] = [];
- this._silentNumbers.push(aNumber);
- smsService.addSilentNumber(aNumber);
- }
-
- if (this._silentSmsObservers[aNumber].indexOf(aCallback) == -1) {
- this._silentSmsObservers[aNumber].push(aCallback);
- }
- return;
-};
-
-PaymentProvider.prototype.removeSilentSmsObserver = function(aNumber, aCallback) {
- _debug && DEBUG("removeSilentSmsObserver " + aNumber);
-
- if (!this._silentSmsObservers || !this._silentSmsObservers[aNumber]) {
- _debug && DEBUG("No observers for " + aNumber);
- return;
- }
-
- let index = this._silentSmsObservers[aNumber].indexOf(aCallback);
- if (index != -1) {
- this._silentSmsObservers[aNumber].splice(index, 1);
- if (this._silentSmsObservers[aNumber].length == 0) {
- this._silentSmsObservers[aNumber] = null;
- this._silentNumbers.splice(this._silentNumbers.indexOf(aNumber), 1);
- smsService.removeSilentNumber(aNumber);
- }
- } else if (_debug) {
- DEBUG("No callback found for " + aNumber);
- }
- return;
-};
-
-PaymentProvider.prototype._onSilentSms = function(aSubject, aTopic, aData) {
- if (!aSubject || !(aSubject instanceof Ci.nsISmsMessage)) {
- _debug && DEBUG("Invalid subject when receiving silent message!");
- return;
- }
-
- let message = aSubject.QueryInterface(Ci.nsISmsMessage);
-
- _debug && DEBUG("Got silent message! " + message.sender + " - " + message.body);
-
- let number = message.sender;
- if (!number || this._silentNumbers.indexOf(number) == -1) {
- _debug && DEBUG("No observers for " + number);
- return;
- }
-
- // If the service ID is null it means that the payment provider asked the
- // user for her MSISDN, so we are in a MT only SMS auth flow. In this case
- // we manually set the service ID to the one corresponding with the SIM
- // that received the SMS.
- if (this._strategy.paymentServiceId === null) {
- let i = 0;
- while(i < gRil.numRadioInterfaces) {
- if (this.iccInfo[i].iccId === message.iccId) {
- this._strategy.paymentServiceId = i;
- break;
- }
- i++;
- }
- }
-
- this._silentSmsObservers[number].forEach(function(callback) {
- callback({
- iccId: message.iccId,
- sender: message.sender,
- body: message.body,
- timestamp: message.timestamp,
- sentTimestamp: message.sentTimestamp
- });
- });
-};
-
-PaymentProvider.prototype._cleanup = function() {
- if (!this._silentNumbers) {
- return;
- }
-
- while (this._silentNumbers.length) {
- let number = this._silentNumbers.pop();
- smsService.removeSilentNumber(number);
- }
- this._silentNumbers = null;
- this._silentSmsObservers = null;
- Services.obs.removeObserver(this._onSilentSmsObserver,
- kSilentSmsReceivedTopic);
-};
-
-#else
-
-PaymentProvider.prototype.sendSilentSms = function(aNumber, aMessage) {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-};
-
-PaymentProvider.prototype.observeSilentSms = function(aNumber, aCallback) {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-};
-
-PaymentProvider.prototype.removeSilentSmsObserver = function(aNumber, aCallback) {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-};
-
-#endif
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentProvider]);
deleted file mode 100644
--- a/dom/payment/PaymentProviderUtils.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#include "mozilla/dom/NavigatorBinding.h"
-#include "PaymentProviderUtils.h"
-#include "nsGlobalWindow.h"
-#include "nsJSUtils.h"
-#include "nsIDocShell.h"
-
-using namespace mozilla::dom;
-
-/* static */ bool
-PaymentProviderUtils::EnabledForScope(JSContext* aCx,
- JSObject* aGlobal)
-{
- nsCOMPtr<nsPIDOMWindowInner> win =
- do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
- NS_ENSURE_TRUE(win, false);
-
- nsIDocShell *docShell = win->GetDocShell();
- NS_ENSURE_TRUE(docShell, false);
-
- nsString paymentRequestId;
- docShell->GetPaymentRequestId(paymentRequestId);
-
- return !paymentRequestId.IsEmpty();
-}
deleted file mode 100644
--- a/dom/payment/PaymentProviderUtils.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#ifndef mozilla_dom_payment_PaymentProviderEnabler_h
-#define mozilla_dom_payment_PaymentProviderEnabler_h
-
-#include "jsapi.h"
-
-struct JSContext;
-class JSObject;
-
-namespace mozilla {
-namespace dom {
-
-class PaymentProviderUtils
-{
-public:
- static bool EnabledForScope(JSContext*, JSObject*);
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_payment_PaymentProviderEnabler_h
deleted file mode 100644
--- a/dom/payment/interfaces/moz.build
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-XPIDL_SOURCES += [
- 'nsIPaymentContentHelperService.idl',
- 'nsIPaymentFlowInfo.idl',
- 'nsIPaymentProviderStrategy.idl',
- 'nsIPaymentUIGlue.idl',
-]
-
-XPIDL_MODULE = 'dom_payment'
-
deleted file mode 100644
--- a/dom/payment/interfaces/nsIPaymentContentHelperService.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 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/. */
-
-#include "domstubs.idl"
-
-interface nsIDOMDOMRequest;
-interface mozIDOMWindow;
-
-[scriptable, uuid(80035846-6732-4fcc-961b-f336b65218f4)]
-interface nsIPaymentContentHelperService : nsISupports
-{
- // The 'jwts' parameter can be either a single DOMString or an array of
- // DOMStrings. In both cases, it represents the base64url encoded and
- // digitally signed payment information. Each payment provider should
- // define its supported JWT format.
- nsIDOMDOMRequest pay(in mozIDOMWindow window, in jsval jwts);
-};
deleted file mode 100644
--- a/dom/payment/interfaces/nsIPaymentFlowInfo.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(f3fe3b48-fe81-4ec9-90ab-648ac9403466)]
-interface nsIPaymentFlowInfo : nsISupports
-{
- // Payment provider uri.
- attribute DOMString uri;
-
- // Base64 encoded and digitally signed payment request information.
- attribute DOMString jwt;
-
- // Payment providers expect the payment information as GET or POST
- // parameters.
- attribute DOMString requestMethod;
-
- // Payment provider name.
- attribute DOMString name;
-
- // Payment provider description.
- attribute DOMString description;
-};
deleted file mode 100644
--- a/dom/payment/interfaces/nsIPaymentProviderStrategy.idl
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 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/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(c3971bd9-0fbf-48d3-9498-0ac340d0d216)]
-interface nsIPaymentProviderStrategy : nsISupports
-{
- attribute DOMString paymentServiceId;
- readonly attribute jsval iccInfo;
-
- void cleanup();
-};
deleted file mode 100644
--- a/dom/payment/interfaces/nsIPaymentUIGlue.idl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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/. */
-
-#include "nsISupports.idl"
-
-interface nsIPaymentFlowInfo;
-
-[scriptable, function, uuid(b9afa678-71a5-4975-bcdb-0c4098730eff)]
-interface nsIPaymentUIGlueCallback : nsISupports
-{
- void onresult(in DOMString requestId, in DOMString result);
-};
-
-[scriptable, uuid(4dc09e33-d395-4e1d-acb4-e85415181270)]
-interface nsIPaymentUIGlue : nsISupports
-{
- // The 'paymentRequestsInfo' contains the payment request information
- // for each JWT provided via navigator.mozPay call.
- void confirmPaymentRequest(in DOMString requestId,
- in jsval paymentRequestsInfo,
- in nsIPaymentUIGlueCallback successCb,
- in nsIPaymentUIGlueCallback errorCb);
-
- void showPaymentFlow(in DOMString requestId,
- in nsIPaymentFlowInfo paymentFlowInfo,
- in nsIPaymentUIGlueCallback errorCb);
-
- // The promise resolves with no value as soon as the payment window is
- // closed.
- jsval /*Promise*/ closePaymentFlow(in DOMString requestId);
-};
deleted file mode 100644
--- a/dom/payment/moz.build
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DIRS += ['interfaces']
-
-EXPORTS.mozilla.dom += [
- 'PaymentProviderUtils.h',
-]
-
-SOURCES += [
- 'PaymentProviderUtils.cpp',
-]
-
-EXTRA_PP_JS_MODULES += [
- 'Payment.jsm',
-]
-
-EXTRA_COMPONENTS += [
- 'Payment.js',
- 'Payment.manifest',
- 'PaymentFlowInfo.js'
-]
-
-EXTRA_PP_COMPONENTS += [
- 'PaymentProvider.js'
-]
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
- '/dom/base'
-]
-
-XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
-
-MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
deleted file mode 100644
--- a/dom/payment/tests/mochitest/MockPaymentsUIChromeScript.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/* 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/. */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cm = Components.manager;
-const Cu = Components.utils;
-
-const CONTRACT_ID = "@mozilla.org/payment/ui-glue;1";
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
-var oldClassID, oldFactory;
-var newClassID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID();
-var newFactory = {
- createInstance: function(aOuter, aIID) {
- if (aOuter) {
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- }
- return new MockPaymentsUIGlueInstance().QueryInterface(aIID);
- },
- lockFactory: function(aLock) {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- },
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
-};
-
-addMessageListener("MockPaymentsUIGlue.init", function (message) {
- try {
- oldClassID = registrar.contractIDToCID(CONTRACT_ID);
- oldFactory = Cm.getClassObject(oldClassID, Ci.nsIFactory);
- } catch (ex) {
- oldClassID = "";
- oldFactory = null;
- dump("TEST-INFO | can't get payments ui glue registered component, " +
- "assuming there is none\n");
- }
- if (oldFactory) {
- registrar.unregisterFactory(oldClassID, oldFactory);
- }
- registrar.registerFactory(newClassID, "", CONTRACT_ID, newFactory);});
-
-addMessageListener("MockPaymentsUIGlue.cleanup", function (message) {
- if (oldClassID) {
- registrar.registerFactory(oldClassID, "", CONTRACT_ID, null);
- }
-});
-
-var payments = new Map();
-
-function MockPaymentsUIGlueInstance() {
-};
-
-MockPaymentsUIGlueInstance.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue]),
-
- confirmPaymentRequest: function(aRequestId,
- aRequests,
- aSuccessCb,
- aErrorCb) {
- aSuccessCb.onresult(aRequestId, aRequests[0].type);
- },
-
- showPaymentFlow: function(aRequestId,
- aPaymentFlowInfo,
- aErrorCb) {
- let win = Services.ww.openWindow(null,
- null,
- "_blank",
- "chrome,dialog=no,resizable,scrollbars,centerscreen",
- null);
-
- payments.set(aRequestId, win);
- let docshell = win.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
- docshell.paymentRequestId = aRequestId;
-
- win.document.location = aPaymentFlowInfo.uri + aPaymentFlowInfo.jwt;
- },
-
- closePaymentFlow: function(aRequestId) {
- payments.get(aRequestId).close();
- payments.delete(aRequestId);
-
- return Promise.resolve();
- },
-};
deleted file mode 100644
--- a/dom/payment/tests/mochitest/file_mozpayproviderchecker.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- * 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/. */
- -->
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="utf-8">
- <title>Test app for bug 1097928 - Check if MozPaymentProvider API is exposed</title>
-</head>
-<body>
-<div id='test'>
-<script type="application/javascript;version=1.8">
- function receiveMessage(event) {
- let message = JSON.parse(event.data);
- let exposed = (navigator.mozPaymentProvider != undefined);
- window.parent.postMessage(JSON.stringify({
- iframeType: message.iframeType,
- exposed: exposed
- }), "*");
- }
-
- window.addEventListener("message", receiveMessage, false, true);
-</script>
-</div>
-</body>
-</html>
deleted file mode 100644
--- a/dom/payment/tests/mochitest/file_payproviderfailure.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE HTML>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <script>
- navigator.mozPaymentProvider.paymentFailed();
- </script>
- </body>
-</html>
-
deleted file mode 100644
--- a/dom/payment/tests/mochitest/file_payprovidersuccess.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE HTML>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <script>
- navigator.mozPaymentProvider.paymentSuccess("aResult");
- </script>
- </body>
-</html>
-
deleted file mode 100644
--- a/dom/payment/tests/mochitest/mochitest.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[DEFAULT]
-skip-if=buildapp != 'b2g'
-
-support-files=
- file_mozpayproviderchecker.html
- file_payprovidersuccess.html
- file_payproviderfailure.html
- MockPaymentsUIChromeScript.js
-
-[test_mozpaymentprovider.html]
-[test_mozpay_callbacks.html]
deleted file mode 100644
--- a/dom/payment/tests/mochitest/test_mozpay_callbacks.html
+++ /dev/null
@@ -1,112 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
- https://bugzilla.mozilla.org/show_bug.cgi?id=1097928
--->
-<html>
-<head>
- <title>Test for navigator.mozPay. Bug 1097928</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script type="application/javascript;version=1.8">
-
-SimpleTest.waitForExplicitFinish();
-
-let tests = [() => {
- /*
- {
- "iss": "323d34dc-b5cf-4822-8e47-6a4515dc74db",
- "typ": "mozilla/payments/test/success",
- "request": {
- "name": "Virtual Kiwi",
- "id": "af1f960a-3f90-4e2d-a20f-d5170aee49f2",
- "postbackURL": "https://inapp-pay-test.paas.allizom.org/mozpay",
- "productData": "localTransID=14546cd1-db9b-4759-986f-2a6a295fdcc1",
- "chargebackURL": "https://inapp-pay-test.paas.allizom.org/mozpay",
- "description": "The forbidden fruit"
- }
- }
- */
- let jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIzMjNkMzRkYy1iNWNmLTQ4MjItOGU0Ny02YTQ1MTVkYzc0ZGIiLCJyZXF1ZXN0Ijp7ImRlc2NyaXB0aW9uIjoiVGhlIGZvcmJpZGRlbiBmcnVpdCIsImlkIjoiYWYxZjk2MGEtM2Y5MC00ZTJkLWEyMGYtZDUxNzBhZWU0OWYyIiwicG9zdGJhY2tVUkwiOiJodHRwczovL2luYXBwLXBheS10ZXN0LnBhYXMuYWxsaXpvbS5vcmcvbW96cGF5L3Bvc3RiYWNrIiwicHJvZHVjdERhdGEiOiJsb2NhbFRyYW5zSUQ9MTQ1NDZjZDEtZGI5Yi00NzU5LTk4NmYtMmE2YTI5NWZkY2MxIiwiY2hhcmdlYmFja1VSTCI6Imh0dHBzOi8vaW5hcHAtcGF5LXRlc3QucGFhcy5hbGxpem9tLm9yZy9tb3pwYXkvY2hhcmdlYmFjayIsIm5hbWUiOiJWaXJ0dWFsIEtpd2kifSwidHlwIjoibW96aWxsYS9wYXltZW50cy90ZXN0L3N1Y2Nlc3MifQ.8zaeYFUCwKkZWk2TFf2wEJWrmiSYQGNbpKc2ADkvL9s";
- let req = window.navigator.mozPay(jwt);
- req.onsuccess = (result) => {
- ok(true, "Expected mozPay success");
- runTest();
- };
- req.onerror = (error) => {
- ok(false, "Unexpected mozPay error " + error);
- SimpleTest.finish();
- };
-}, () => {
- /*
- {
- "iss": "323d34dc-b5cf-4822-8e47-6a4515dc74db",
- "typ": "mozilla/payments/test/failure",
- "request": {
- "name": "Virtual Kiwi",
- "id": "af1f960a-3f90-4e2d-a20f-d5170aee49f2",
- "postbackURL": "https://inapp-pay-test.paas.allizom.org/mozpay",
- "productData": "localTransID=cc3c0994-33e8-4a21-aa2c-75ee44f5fe75",
- "chargebackURL": "https://inapp-pay-test.paas.allizom.org/mozpay",
- "description": "The forbidden fruit"
- }
- }
- */
- let jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIzMjNkMzRkYy1iNWNmLTQ4MjItOGU0Ny02YTQ1MTVkYzc0ZGIiLCJyZXF1ZXN0Ijp7ImRlc2NyaXB0aW9uIjoiVGhlIGZvcmJpZGRlbiBmcnVpdCIsImlkIjoiYWYxZjk2MGEtM2Y5MC00ZTJkLWEyMGYtZDUxNzBhZWU0OWYyIiwicG9zdGJhY2tVUkwiOiJodHRwczovL2luYXBwLXBheS10ZXN0LnBhYXMuYWxsaXpvbS5vcmcvbW96cGF5L3Bvc3RiYWNrIiwicHJvZHVjdERhdGEiOiJsb2NhbFRyYW5zSUQ9Y2MzYzA5OTQtMzNlOC00YTIxLWFhMmMtNzVlZTQ0ZjVmZTc1IiwiY2hhcmdlYmFja1VSTCI6Imh0dHBzOi8vaW5hcHAtcGF5LXRlc3QucGFhcy5hbGxpem9tLm9yZy9tb3pwYXkvY2hhcmdlYmFjayIsIm5hbWUiOiJWaXJ0dWFsIEtpd2kifSwidHlwIjoibW96aWxsYS9wYXltZW50cy90ZXN0L2ZhaWx1cmUifQ.1uV4-HkmwO0oDv50wi1Ma4tNpnxoFGaw5zaPj8xkcAc";
- let req = window.navigator.mozPay(jwt);
- req.onsuccess = (result) => {
- ok(false, "Unexpected mozPay success " + result);
- SimpleTest.finish();
- };
- req.onerror = (error) => {
- ok(true, "Expected mozPay error");
- runTest();
- };
-}];
-
-function runTest() {
- if (!tests.length) {
- ok(true, "Done!");
- SimpleTest.finish();
- return;
- }
- tests.shift()();
-}
-
-const uiGlue = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('MockPaymentsUIChromeScript.js'));
-SimpleTest.registerCleanupFunction(() => {
- uiGlue.sendAsyncMessage("MockPaymentsUIGlue.cleanup", {});
-});
-uiGlue.sendAsyncMessage("MockPaymentsUIGlue.init", {});
-
-SpecialPowers.pushPrefEnv({
- "set": [
- ["dom.payment.skipHTTPSCheck", "true"],
- ["dom.payment.debug", "true"],
- ["dom.payment.provider.1.name", "SuccessProvider"],
- ["dom.payment.provider.1.description", ""],
- ["dom.payment.provider.1.uri",
- "https://example.com:443/tests/dom/payment/tests/mochitest/file_payprovidersuccess.html?req="],
- ["dom.payment.provider.1.type", "mozilla/payments/test/success"],
- ["dom.payment.provider.1.requestMethod", "GET"],
- ["dom.payment.provider.2.name", "FailureProvider"],
- ["dom.payment.provider.2.description", ""],
- ["dom.payment.provider.2.uri",
- "https://example.com:443/tests/dom/payment/tests/mochitest/file_payproviderfailure.html?req="],
- ["dom.payment.provider.2.type", "mozilla/payments/test/failure"],
- ["dom.payment.provider.2.requestMethod", "GET"],
- ]
- }, () => {
- runTest();
- });
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/payment/tests/mochitest/test_mozpaymentprovider.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
- https://bugzilla.mozilla.org/show_bug.cgi?id=1097928
--->
-<html>
-<head>
- <title>Test for navigator.mozPaymentProvider exposure. Bug 1097928</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script type="application/javascript;version=1.8">
-
-SimpleTest.waitForExplicitFinish();
-
-// We create two iframes. The first one is a regular iframe with no payment
-// information and so it should not have access to the MozPaymentProvider
-// API. For the second iframe we set a dummy payment request ID which should
-// expose the MozPaymentProvider API.
-let tests = [function() {
- // Iframe with no payment information.
- let iframe = document.createElement("iframe");
- iframe.setAttribute("mozbrowser", "true");
- iframe.src = "file_mozpayproviderchecker.html";
-
- document.getElementById("content").appendChild(iframe);
-
- iframe.addEventListener("load", function onLoad() {
- iframe.removeEventListener("load", onLoad);
- iframe.contentWindow.postMessage(JSON.stringify({
- iframeType: "regular"
- }), "*");
- }, false);
-}, function() {
- // Payment iframe.
- let paymentIframe = document.createElement("iframe");
- paymentIframe.setAttribute("mozbrowser", "true");
- paymentIframe.src = "file_mozpayproviderchecker.html";
-
- document.getElementById("content").appendChild(paymentIframe);
-
- let Ci = SpecialPowers.Ci;
- let docshell = SpecialPowers.wrap(paymentIframe.contentWindow)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
- docshell.paymentRequestId = "dummyid";
-
- paymentIframe.addEventListener("load", function onLoad() {
- paymentIframe.removeEventListener("load", onLoad);
- paymentIframe.contentWindow.postMessage(JSON.stringify({
- iframeType: "payment"
- }), "*");
- }, false);
-}];
-
-function receiveMessage(event) {
- let message = JSON.parse(event.data);
- switch (message.iframeType) {
- case "regular":
- ok(!message.exposed, "MozPaymentProvider is not exposed in regular iframe");
- break;
- case "payment":
- ok(message.exposed, "MozPaymentProvider is exposed in payment iframe");
- break;
- default:
- ok(false, "Unexpected iframe type");
- SimpleTest.finish();
- }
- runTest();
-}
-
-function runTest() {
- if (!tests.length) {
- ok(true, "Done!");
- SimpleTest.finish();
- return;
- }
- tests.shift()();
-}
-
-window.addEventListener("message", receiveMessage, false, true);
-runTest();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/payment/tests/unit/header_helper.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-var subscriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Ci.mozIJSSubScriptLoader);
-
-/**
- * Start a new payment module.
- *
- * @param custom_ns
- * Namespace with symbols to be injected into the new payment module
- * namespace.
- *
- * @return an object that represents the payment module's namespace.
- */
-function newPaymentModule(custom_ns) {
- let payment_ns = {
- importScripts: function fakeImportScripts() {
- Array.slice(arguments).forEach(function (script) {
- subscriptLoader.loadSubScript("resource://gre/modules/" + script, this);
- }, this);
- },
- };
-
- // Copy the custom definitions over.
- for (let key in custom_ns) {
- payment_ns[key] = custom_ns[key];
- }
-
- // Load the payment module itself.
- payment_ns.importScripts("Payment.jsm");
-
- return payment_ns;
-}
deleted file mode 100644
--- a/dom/payment/tests/unit/test_paymanager_get_payment_request.js
+++ /dev/null
@@ -1,348 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-function getPaymentHelper() {
- let error;
- let paym = newPaymentModule();
-
- paym.PaymentManager.paymentFailed = function paymentFailed(aRequestId,
- errorMsg) {
- error = errorMsg;
- };
-
- return {
- get paymentModule() {
- return paym;
- },
- get error() {
- return error;
- }
- };
-}
-
-function run_test() {
- run_next_test();
-}
-
-function testGetPaymentRequest(paymentProviders, test) {
- let helper = getPaymentHelper();
- let paym = helper.paymentModule;
-
- paym.PaymentManager.registeredProviders = paymentProviders;
-
- let ret = paym.PaymentManager.getPaymentRequestInfo("", test.jwt);
- if (!test.result) {
- test.ret ? do_check_true(ret) : do_check_false(ret);
- }
- if (test.error !== null) {
- do_check_eq(helper.error, test.error);
- } else {
- do_check_eq(typeof ret, "object");
- do_check_eq(ret.jwt, test.jwt);
- do_check_eq(ret.type, test.result.type);
- do_check_eq(ret.providerName, test.result.providerName);
- }
-}
-
-add_test(function test_successfull_request() {
- let providers = {};
- let type = "mock/payments/inapp/v1";
- providers[type] = {
- name: "mockprovider",
- description: "Mock Payment Provider",
- uri: "https://mockpayprovider.phpfogapp.com/?req=",
- requestMethod: "GET"
- };
-
- // Payload
- // {
- // "aud": "mockpayprovider.phpfogapp.com",
- // "iss": "Enter you app key here!",
- // "request": {
- // "name": "Piece of Cake",
- // "price": "10.50",
- // "priceTier": 1,
- // "productdata": "transaction_id=86",
- // "currencyCode": "USD",
- // "description": "Virtual chocolate cake to fill your virtual tummy"
- // },
- // "exp": 1352232792,
- // "iat": 1352229192,
- // "typ": "mock/payments/inapp/v1"
- // }
- let jwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJhdWQiOiAibW9j" +
- "a3BheXByb3ZpZGVyLnBocGZvZ2FwcC5jb20iLCAiaXNzIjogIkVudGVyI" +
- "HlvdSBhcHAga2V5IGhlcmUhIiwgInJlcXVlc3QiOiB7Im5hbWUiOiAiUG" +
- "llY2Ugb2YgQ2FrZSIsICJwcmljZSI6ICIxMC41MCIsICJwcmljZVRpZXI" +
- "iOiAxLCAicHJvZHVjdGRhdGEiOiAidHJhbnNhY3Rpb25faWQ9ODYiLCAi" +
- "Y3VycmVuY3lDb2RlIjogIlVTRCIsICJkZXNjcmlwdGlvbiI6ICJWaXJ0d" +
- "WFsIGNob2NvbGF0ZSBjYWtlIHRvIGZpbGwgeW91ciB2aXJ0dWFsIHR1bW" +
- "15In0sICJleHAiOiAxMzUyMjMyNzkyLCAiaWF0IjogMTM1MjIyOTE5Miw" +
- "gInR5cCI6ICJtb2NrL3BheW1lbnRzL2luYXBwL3YxIn0.QZxc62USCy4U" +
- "IyKIC1TKelVhNklvk-Ou1l_daKntaFI";
-
- testGetPaymentRequest(providers, {
- jwt: jwt,
- ret: true,
- error: null,
- result: {
- type: type,
- providerName: providers[type].name
- }
- });
-
- run_next_test();
-});
-
-add_test(function test_successfull_request_html_description() {
- let providers = {};
- let type = "mozilla/payments/pay/v1";
- providers[type] = {
- name: "webpay",
- description: "Mozilla Payment Provider",
- uri: "https://marketplace.firefox.com/mozpay/?req=",
- requestMethod: "GET"
- };
-
- // Payload
- // {
- // "aud": "marketplace.firefox.com",
- // "iss": "marketplace-dev.allizom.org",
- // "request": {
- // "name": "Krupa's paid app 1",
- // "chargebackURL": "http://localhost:8002/telefonica/services/webpay/"
- // "chargeback",
- // "postbackURL": "http://localhost:8002/telefonica/services/webpay/"
- // "postback",
- // "productData": "addon_id=85&seller_uuid=d4855df9-6ce0-45cd-81cb-"
- // "cf8737e1e7aa&contrib_uuid=201868b7ac2cda410a99b3"
- // "ed4c11a8ea",
- // "pricePoint": 1,
- // "id": "maude:85",
- // "description": "This app has been automatically generated by <a href="
- // "\"http://outgoing.mozilla.org/v1/ba7f373ae16789eff3ab"
- // "fd95ca8d3c15d18dc9009afa204dc43f85a55b1f6ef1/http%3A/"
- // "/testmanifest.com\" rel=\"nofollow\">testmanifest.com"
- // "</a>"
- // },
- // "exp": 1358379147,
- // "iat": 1358375547,
- // "typ": "mozilla/payments/pay/v1"
- // }
- let jwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJhdWQiOiAibWFya2V0cGx" +
- "hY2UuZmlyZWZveC5jb20iLCAiaXNzIjogIm1hcmtldHBsYWNlLWRldi5hbGxpem9" +
- "tLm9yZyIsICJyZXF1ZXN0IjogeyJuYW1lIjogIktydXBhJ3MgcGFpZCBhcHAgMSI" +
- "sICJjaGFyZ2ViYWNrVVJMIjogImh0dHA6Ly9sb2NhbGhvc3Q6ODAwMi90ZWxlZm9" +
- "uaWNhL3NlcnZpY2VzL3dlYnBheS9jaGFyZ2ViYWNrIiwgInBvc3RiYWNrVVJMIjo" +
- "gImh0dHA6Ly9sb2NhbGhvc3Q6ODAwMi90ZWxlZm9uaWNhL3NlcnZpY2VzL3dlYnB" +
- "heS9wb3N0YmFjayIsICJwcm9kdWN0RGF0YSI6ICJhZGRvbl9pZD04NSZzZWxsZXJ" +
- "fdXVpZD1kNDg1NWRmOS02Y2UwLTQ1Y2QtODFjYi1jZjg3MzdlMWU3YWEmY29udHJ" +
- "pYl91dWlkPTIwMTg2OGI3YWMyY2RhNDEwYTk5YjNlZDRjMTFhOGVhIiwgInByaWN" +
- "lUG9pbnQiOiAxLCAiaWQiOiAibWF1ZGU6ODUiLCAiZGVzY3JpcHRpb24iOiAiVGh" +
- "pcyBhcHAgaGFzIGJlZW4gYXV0b21hdGljYWxseSBnZW5lcmF0ZWQgYnkgPGEgaHJ" +
- "lZj1cImh0dHA6Ly9vdXRnb2luZy5tb3ppbGxhLm9yZy92MS9iYTdmMzczYWUxNjc" +
- "4OWVmZjNhYmZkOTVjYThkM2MxNWQxOGRjOTAwOWFmYTIwNGRjNDNmODVhNTViMWY" +
- "2ZWYxL2h0dHAlM0EvL3Rlc3RtYW5pZmVzdC5jb21cIiByZWw9XCJub2ZvbGxvd1w" +
- "iPnRlc3RtYW5pZmVzdC5jb208L2E-In0sICJleHAiOiAxMzU4Mzc5MTQ3LCAiaWF" +
- "0IjogMTM1ODM3NTU0NywgInR5cCI6ICJtb3ppbGxhL3BheW1lbnRzL3BheS92MSJ" +
- "9.kgSt636OSRBezMGtm9QLeDxlEOevL4xcOoDj8VRJyD8";
-
- testGetPaymentRequest(providers, {
- jwt: jwt,
- ret: true,
- error: null,
- result: {
- type: type,
- providerName: providers[type].name
- }
- });
-
- run_next_test();
-});
-
-add_test(function test_empty_jwt() {
- testGetPaymentRequest(null, {
- jwt: "",
- ret: true,
- error: "INTERNAL_ERROR_CALL_WITH_MISSING_JWT"
- });
-
- run_next_test();
-});
-
-add_test(function test_wrong_segments_count() {
- // 1 segment JWT
- let OneSegJwt = "eyJhbGciOiJIUzI1NiJ9";
- testGetPaymentRequest(null, {
- jwt: OneSegJwt,
- ret: true,
- error: "PAY_REQUEST_ERROR_WRONG_SEGMENTS_COUNT"
- });
-
- // 2 segments JWT
- let TwoSegJwt = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIwNTg2NDkwMTM2NTY2N" +
- "zU1ODY2MSIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZS9" +
- "wYXltZW50cy9pbmFwcC9pdGVtL3YxIiwiaWF0IjoxMzUyMjIwM" +
- "jEyLCJleHAiOjEzNTIzMDY2MTIsInJlcXVlc3QiOnsiY3VycmV" +
- "uY3lDb2RlIjoiVVNEIiwicHJpY2UiOiIzLjAwIiwibmFtZSI6I" +
- "kdvbGQgU3RhciIsInNlbGxlckRhdGEiOiJzb21lIG9wYXF1ZSB" +
- "kYXRhIiwiZGVzY3JpcHRpb24iOiJBIHNoaW5pbmcgYmFkZ2Ugb" +
- "2YgZGlzdGluY3Rpb24ifX0";
-
- testGetPaymentRequest(null, {
- jwt: TwoSegJwt,
- ret: true,
- error: "PAY_REQUEST_ERROR_WRONG_SEGMENTS_COUNT"
- });
-
- run_next_test();
-});
-
-add_test(function test_empty_payload() {
- let EmptyPayloadJwt = "eyJhbGciOiJIUzI1NiJ9..eyJpc3MiOiIwNTg2NDkwMTM2NTY2N";
-
- testGetPaymentRequest(null, {
- jwt: EmptyPayloadJwt,
- ret: true,
- error: "PAY_REQUEST_ERROR_EMPTY_PAYLOAD"
- });
-
- run_next_test();
-});
-
-add_test(function test_missing_typ_parameter() {
- // Payload
- // {
- // "iss": "640ae477-df33-45cd-83b8-6f1f910a6494",
- // "iat": 1361203745,
- // "request": {
- // "description": "detailed description",
- // "id": "799db970-7afa-4028-bdb7-8b045eb8babc",
- // "postbackURL": "http://inapp-pay-test.farmdev.com/postback",
- // "productData": "transaction_id=58",
- // "pricePoint": 1,
- // "chargebackURL": "http://inapp-pay-test.farmdev.com/chargeback",
- // "name": "The Product"
- // },
- // "aud": "marketplace-dev.allizom.org",
- // "exp": 1361207345
- // }
- let missingTypJwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9." +
- "eyJpc3MiOiAiNjQwYWU0NzctZGYzMy00NWNkLTgzY" +
- "jgtNmYxZjkxMGE2NDk0IiwgImlhdCI6IDEzNjEyMD" +
- "M3NDUsICJyZXF1ZXN0IjogeyJkZXNjcmlwdGlvbiI" +
- "6ICJkZXRhaWxlZCBkZXNjcmlwdGlvbiIsICJpZCI6" +
- "ICI3OTlkYjk3MC03YWZhLTQwMjgtYmRiNy04YjA0N" +
- "WViOGJhYmMiLCAicG9zdGJhY2tVUkwiOiAiaHR0cD" +
- "ovL2luYXBwLXBheS10ZXN0LmZhcm1kZXYuY29tL3B" +
- "vc3RiYWNrIiwgInByb2R1Y3REYXRhIjogInRyYW5z" +
- "YWN0aW9uX2lkPTU4IiwgInByaWNlUG9pbnQiOiAxL" +
- "CAiY2hhcmdlYmFja1VSTCI6ICJodHRwOi8vaW5hcH" +
- "AtcGF5LXRlc3QuZmFybWRldi5jb20vY2hhcmdlYmF" +
- "jayIsICJuYW1lIjogIlRoZSBQcm9kdWN0In0sICJh" +
- "dWQiOiAibWFya2V0cGxhY2UtZGV2LmFsbGl6b20ub" +
- "3JnIiwgImV4cCI6IDEzNjEyMDczNDV9.KAHsJX1Hy" +
- "fmwNvAckdVUqlpPvdHggpx9yX276TWacRg";
- testGetPaymentRequest(null, {
- jwt: missingTypJwt,
- ret: true,
- error: "PAY_REQUEST_ERROR_NO_TYP_PARAMETER"
- });
-
- run_next_test();
-});
-
-add_test(function test_missing_request_parameter() {
- // Payload
- // {
- // "iss": "Enter you app key here!",
- // "iat": 1352225299,
- // "typ": "mock/payments/inapp/v1",
- // "aud": "mockpayprovider.phpfogapp.com",
- // "exp": 1352228899
- // }
- let missingRequestJwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9." +
- "eyJpc3MiOiAiRW50ZXIgeW91IGFwcCBrZXkgaGVyZ" +
- "SEiLCAiaWF0IjogMTM1MjIyNTI5OSwgInR5cCI6IC" +
- "Jtb2NrL3BheW1lbnRzL2luYXBwL3YxIiwgImF1ZCI" +
- "6ICJtb2NrcGF5cHJvdmlkZXIucGhwZm9nYXBwLmNv" +
- "bSIsICJleHAiOiAxMzUyMjI4ODk5fQ.yXGinvZiUs" +
- "v9JWvdfM6zPD0iOX9DgCPcIwIbCrL4tcs";
-
- testGetPaymentRequest(null, {
- jwt: missingRequestJwt,
- ret: true,
- error: "PAY_REQUEST_ERROR_NO_REQUEST_PARAMETER"
- });
-
- run_next_test();
-});
-
-add_test(function test_jwt_decoding_error() {
- let wrongJwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.^eyJhdWQiOiAibW9" +
- "a3BheXByb3ZpZGVyLnBocGZvZ2FwcC5jb20iLCAiaXNzIjogIkVudGVyI" +
- "HlvdSBhcHAga2V5IGhlcmUhIiwgInJlcXVlc3QiOiB7Im5hbWUiOiAiUG" +
- "llY2Ugb2YgQ2FrZSIsICJwcmljZSI6ICIxMC41MCIsICJwcmljZVRpZXI" +
- "iOiAxLCAicHJvZHVjdGRhdGEiOiAidHJhbnNhY3Rpb25faWQ9ODYiLCAi" +
- "Y3VycmVuY3lDb2RlIjogIlVTRCIsICJkZXNjcmlwdGlvbiI6ICJWaXJ0d" +
- "WFsIGNob2NvbGF0ZSBjYWtlIHRvIGZpbGwgeW91ciB2aXJ0dWFsIHR1bW" +
- "15In0sICJleHAiOiAxMzUyMjMyNzkyLCAiaWF0IjogMTM1MjIyOTE5Miw" +
- "gInR5cCI6ICJtb2NrL3BheW1lbnRzL2luYXBwL3YxIn0.QZxc62USCy4U" +
- "IyKIC1TKelVhNklvk-Ou1l_daKntaFI";
-
- testGetPaymentRequest(null, {
- jwt: wrongJwt,
- ret: true,
- error: "PAY_REQUEST_ERROR_ERROR_DECODING_JWT"
- });
-
- run_next_test();
-});
-
-add_test(function test_non_https_provider() {
- let providers = {};
- let type = "mock/payments/inapp/v1";
- providers[type] = {
- name: "mockprovider",
- description: "Mock Payment Provider",
- uri: "http://mockpayprovider.phpfogapp.com/?req=",
- requestMethod: "GET"
- };
-
- // Payload
- // {
- // "aud": "mockpayprovider.phpfogapp.com",
- // "iss": "Enter you app key here!",
- // "request": {
- // "name": "Piece of Cake",
- // "price": "10.50",
- // "priceTier": 1,
- // "productdata": "transaction_id=86",
- // "currencyCode": "USD",
- // "description": "Virtual chocolate cake to fill your virtual tummy"
- // },
- // "exp": 1352232792,
- // "iat": 1352229192,
- // "typ": "mock/payments/inapp/v1"
- // }
- let jwt = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJhdWQiOiAibW9j" +
- "a3BheXByb3ZpZGVyLnBocGZvZ2FwcC5jb20iLCAiaXNzIjogIkVudGVyI" +
- "HlvdSBhcHAga2V5IGhlcmUhIiwgInJlcXVlc3QiOiB7Im5hbWUiOiAiUG" +
- "llY2Ugb2YgQ2FrZSIsICJwcmljZSI6ICIxMC41MCIsICJwcmljZVRpZXI" +
- "iOiAxLCAicHJvZHVjdGRhdGEiOiAidHJhbnNhY3Rpb25faWQ9ODYiLCAi" +
- "Y3VycmVuY3lDb2RlIjogIlVTRCIsICJkZXNjcmlwdGlvbiI6ICJWaXJ0d" +
- "WFsIGNob2NvbGF0ZSBjYWtlIHRvIGZpbGwgeW91ciB2aXJ0dWFsIHR1bW" +
- "15In0sICJleHAiOiAxMzUyMjMyNzkyLCAiaWF0IjogMTM1MjIyOTE5Miw" +
- "gInR5cCI6ICJtb2NrL3BheW1lbnRzL2luYXBwL3YxIn0.QZxc62USCy4U" +
- "IyKIC1TKelVhNklvk-Ou1l_daKntaFI";
-
- testGetPaymentRequest(providers, {
- jwt: jwt,
- ret: true,
- error: "INTERNAL_ERROR_NON_HTTPS_PROVIDER_URI"
- });
-
- run_next_test();
-});
deleted file mode 100644
--- a/dom/payment/tests/unit/xpcshell.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[DEFAULT]
-head = header_helper.js
-tail =
-skip-if = toolkit == 'gonk'
-
-[test_paymanager_get_payment_request.js]
deleted file mode 100644
--- a/dom/webidl/MozPaymentProvider.webidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/.
- */
-
-dictionary PaymentIccInfo {
- DOMString mcc;
- DOMString mnc;
- DOMString iccId;
- boolean dataPrimary;
-};
-
-dictionary PaymentSmsMessage {
- DOMString iccId;
- DOMString sender;
- DOMString body;
- DOMTimeStamp timestamp;
- DOMTimeStamp sentTimestamp;
-};
-
-callback SilentSmsCallback = void (optional PaymentSmsMessage message);
-
-[NavigatorProperty="mozPaymentProvider",
- NoInterfaceObject,
- HeaderFile="mozilla/dom/PaymentProviderUtils.h",
- Func="mozilla::dom::PaymentProviderUtils::EnabledForScope",
- JSImplementation="@mozilla.org/payment/provider;1"]
-interface PaymentProvider {
- readonly attribute DOMString? paymentServiceId;
- // We expose to the payment provider the information of all the SIMs
- // available in the device.
- [Cached, Pure] readonly attribute sequence<PaymentIccInfo>? iccInfo;
-
- void paymentSuccess(optional DOMString result);
- void paymentFailed(optional DOMString error);
-
- DOMRequest sendSilentSms(DOMString number, DOMString message);
- void observeSilentSms(DOMString number, SilentSmsCallback callback);
- void removeSilentSmsObserver(DOMString number, SilentSmsCallback callback);
-};
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -170,33 +170,16 @@ partial interface Navigator {
callback interface MozIdleObserver {
// Time is in seconds and is read only when idle observers are added
// and removed.
readonly attribute unsigned long time;
void onidle();
void onactive();
};
-#ifdef MOZ_B2G
-dictionary MobileIdOptions {
- boolean forceSelection = false;
-};
-
-[NoInterfaceObject]
-interface NavigatorMobileId {
- // Ideally we would use [CheckAnyPermissions] here, but the "mobileid"
- // permission is set to PROMPT_ACTION and [CheckAnyPermissions] only checks
- // for ALLOW_ACTION.
- // XXXbz what is this promise resolved with?
- [NewObject, Func="Navigator::HasMobileIdSupport"]
- Promise<any> getMobileIdAssertion(optional MobileIdOptions options);
-};
-Navigator implements NavigatorMobileId;
-#endif // MOZ_B2G
-
// nsIDOMNavigator
partial interface Navigator {
[Throws, Constant, Cached]
readonly attribute DOMString oscpu;
// WebKit/Blink support this; Trident/Presto do not.
readonly attribute DOMString vendor;
// WebKit/Blink supports this (hardcoded ""); Trident/Presto do not.
readonly attribute DOMString vendorSub;
@@ -451,23 +434,12 @@ partial interface Navigator {
#ifdef NIGHTLY_BUILD
partial interface Navigator {
[Func="Navigator::IsE10sEnabled"]
readonly attribute boolean mozE10sEnabled;
};
#endif
-#ifdef MOZ_PAY
-partial interface Navigator {
- [Throws, NewObject, Pref="dom.mozPay.enabled"]
- // The 'jwts' parameter can be either a single DOMString or an array of
- // DOMStrings. In both cases, it represents the base64url encoded and
- // digitally signed payment information. Each payment provider should
- // define its supported JWT format.
- DOMRequest mozPay(any jwts);
-};
-#endif
-
[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -913,21 +913,16 @@ if CONFIG['MOZ_EME']:
'MediaKeys.webidl',
'MediaKeySession.webidl',
'MediaKeysRequestStatus.webidl',
'MediaKeyStatusMap.webidl',
'MediaKeySystemAccess.webidl',
'WidevineCDMManifest.webidl',
]
-if CONFIG['MOZ_PAY']:
- WEBIDL_FILES += [
- 'MozPaymentProvider.webidl'
- ]
-
if CONFIG['MOZ_B2G']:
WEBIDL_FILES += [
'Apps.webidl',
'Identity.webidl',
'MozApplicationEvent.webidl'
]
GENERATED_EVENTS_WEBIDL_FILES += [
'MozApplicationEvent.webidl'
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -2119,17 +2119,17 @@ RuntimeService::GetWorkersForWindow(nsPI
}
}
void
RuntimeService::CancelWorkersForWindow(nsPIDOMWindowInner* aWindow)
{
AssertIsOnMainThread();
- AutoTArray<WorkerPrivate*, MAX_WORKERS_PER_DOMAIN> workers;
+ nsTArray<WorkerPrivate*> workers;
GetWorkersForWindow(aWindow, workers);
if (!workers.IsEmpty()) {
for (uint32_t index = 0; index < workers.Length(); index++) {
WorkerPrivate*& worker = workers[index];
if (worker->IsSharedWorker()) {
worker->CloseSharedWorkersForWindow(aWindow);
@@ -2141,59 +2141,59 @@ RuntimeService::CancelWorkersForWindow(n
}
void
RuntimeService::FreezeWorkersForWindow(nsPIDOMWindowInner* aWindow)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWindow);
- AutoTArray<WorkerPrivate*, MAX_WORKERS_PER_DOMAIN> workers;
+ nsTArray<WorkerPrivate*> workers;
GetWorkersForWindow(aWindow, workers);
for (uint32_t index = 0; index < workers.Length(); index++) {
workers[index]->Freeze(aWindow);
}
}
void
RuntimeService::ThawWorkersForWindow(nsPIDOMWindowInner* aWindow)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWindow);
- AutoTArray<WorkerPrivate*, MAX_WORKERS_PER_DOMAIN> workers;
+ nsTArray<WorkerPrivate*> workers;
GetWorkersForWindow(aWindow, workers);
for (uint32_t index = 0; index < workers.Length(); index++) {
workers[index]->Thaw(aWindow);
}
}
void
RuntimeService::SuspendWorkersForWindow(nsPIDOMWindowInner* aWindow)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWindow);
- AutoTArray<WorkerPrivate*, MAX_WORKERS_PER_DOMAIN> workers;
+ nsTArray<WorkerPrivate*> workers;
GetWorkersForWindow(aWindow, workers);
for (uint32_t index = 0; index < workers.Length(); index++) {
workers[index]->Suspend();
}
}
void
RuntimeService::ResumeWorkersForWindow(nsPIDOMWindowInner* aWindow)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWindow);
- AutoTArray<WorkerPrivate*, MAX_WORKERS_PER_DOMAIN> workers;
+ nsTArray<WorkerPrivate*> workers;
GetWorkersForWindow(aWindow, workers);
for (uint32_t index = 0; index < workers.Length(); index++) {
workers[index]->Resume();
}
}
nsresult
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -139,17 +139,16 @@ support-files =
[test_bug1036484.html]
[test_bug1060621.html]
[test_bug1062920.html]
[test_bug1063538.html]
[test_bug1104064.html]
[test_bug1132395.html]
skip-if = true # bug 1176225
[test_bug1132924.html]
-[test_bug1241485.html]
[test_chromeWorker.html]
[test_clearTimeouts.html]
[test_close.html]
[test_closeOnGC.html]
[test_console.html]
[test_consoleAndBlobs.html]
[test_consoleReplaceable.html]
[test_consoleSharedWorkers.html]
deleted file mode 100644
--- a/dom/workers/test/test_bug1241485.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1241485
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1241485</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript">
-
- /** Test for Bug 1241485 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestCompleteLog();
-SimpleTest.requestFlakyTimeout("requestFlakyTimeout is silly.");
-
-var limit = 10;
-
-SpecialPowers.pushPrefEnv({"set":[["dom.workers.maxPerDomain", limit]] },
-function() {
- var workers = new Array();
- var workerToWait = null;
- var url = URL.createObjectURL(new Blob(["postMessage('loaded');"]));
- var timeouts = new Array();
-
- function addTimeout(fn, time) {
- timeouts.push(setTimeout(fn, time));
- }
-
- function createWorker() {
- workerToWait = new Worker(url);
- workerToWait.onmessage = function(e) {
- if (!workers) {
- // finish() has been called already.
- return;
- }
- workers.push(workerToWait);
- info(workers.length + " workers");
- addTimeout(createWorker, 0);
- if (workers.length == limit) {
- // Just give the worker creation loop some more time to try to
- // create more workers to check that we don't go over the limit.
- addTimeout(finish, 250);
- }
- };
- }
-
- function finish() {
- for (var i = 0; i < timeouts.length; ++i) {
- clearTimeout(timeouts[i]);
- }
-
- if (workerToWait) {
- workerToWait.onmessage = null;
- }
-
- ok(workers.length <= limit, "Too many workers created!");
-
- workers = null;
- SpecialPowers.gc();
-
- SimpleTest.finish();
- }
-
- info("Expecting no more than " + limit + " workers.");
- // Make sure we finish at some point, even if creating workers takes
- // lots of time.
- addTimeout(finish, 10000);
- addTimeout(createWorker, 0);
-});
-
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1241485">Mozilla Bug 1241485</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-</body>
-</html>
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -2289,48 +2289,34 @@ HTMLEditRules::WillDeleteSelection(Selec
// Are the blocks siblings?
nsCOMPtr<nsINode> leftBlockParent = leftParent->GetParentNode();
nsCOMPtr<nsINode> rightBlockParent = rightParent->GetParentNode();
// MOOSE: this could conceivably screw up a table.. fix me.
NS_ENSURE_STATE(mHTMLEditor);
if (leftBlockParent == rightBlockParent &&
mHTMLEditor->NodesSameType(GetAsDOMNode(leftParent),
- GetAsDOMNode(rightParent))) {
- if (leftParent->IsHTMLElement(nsGkAtoms::p)) {
- // First delete the selection
- NS_ENSURE_STATE(mHTMLEditor);
- res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
- NS_ENSURE_SUCCESS(res, res);
- // Then join paragraphs, insert break
- NS_ENSURE_STATE(mHTMLEditor);
- EditorDOMPoint pt =
- mHTMLEditor->JoinNodeDeep(*leftParent, *rightParent);
- NS_ENSURE_STATE(pt.node);
- // Fix up selection
- res = aSelection->Collapse(pt.node, pt.offset);
- NS_ENSURE_SUCCESS(res, res);
- return NS_OK;
- }
- if (HTMLEditUtils::IsListItem(leftParent) ||
- HTMLEditUtils::IsHeader(*leftParent)) {
+ GetAsDOMNode(rightParent)) &&
+ // XXX What's special about these three types of block?
+ (leftParent->IsHTMLElement(nsGkAtoms::p) ||
+ HTMLEditUtils::IsListItem(leftParent) ||
+ HTMLEditUtils::IsHeader(*leftParent))) {
// First delete the selection
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
NS_ENSURE_SUCCESS(res, res);
// Join blocks
NS_ENSURE_STATE(mHTMLEditor);
EditorDOMPoint pt =
mHTMLEditor->JoinNodeDeep(*leftParent, *rightParent);
NS_ENSURE_STATE(pt.node);
// Fix up selection
res = aSelection->Collapse(pt.node, pt.offset);
NS_ENSURE_SUCCESS(res, res);
return NS_OK;
- }
}
// Else blocks not same type, or not siblings. Delete everything
// except table elements.
join = true;
uint32_t rangeCount = aSelection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
@@ -2495,28 +2481,30 @@ HTMLEditRules::InsertBRIfNeeded(Selectio
return br ? NS_OK : NS_ERROR_FAILURE;
}
}
return NS_OK;
}
/**
* GetGoodSelPointForNode() finds where at a node you would want to set the
- * selection if you were trying to have a caret next to it.
+ * selection if you were trying to have a caret next to it. Always returns a
+ * valid value (unless mHTMLEditor has gone away).
*
* @param aNode The node
* @param aAction Which edge to find: eNext indicates beginning,
* ePrevious ending.
*/
EditorDOMPoint
HTMLEditRules::GetGoodSelPointForNode(nsINode& aNode,
nsIEditor::EDirection aAction)
{
NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- if (aNode.GetAsText() || mHTMLEditor->IsContainer(&aNode)) {
+ if (aNode.GetAsText() || mHTMLEditor->IsContainer(&aNode) ||
+ NS_WARN_IF(!aNode.GetParentNode())) {
return EditorDOMPoint(&aNode,
aAction == nsIEditor::ePrevious ? aNode.Length() : 0);
}
EditorDOMPoint ret;
ret.node = aNode.GetParentNode();
ret.offset = ret.node ? ret.node->IndexOf(&aNode) : -1;
NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
@@ -4831,34 +4819,36 @@ HTMLEditRules::CheckForEmptyBlock(nsINod
res = aSelection->Collapse(listParent, listOffset);
NS_ENSURE_SUCCESS(res, res);
}
// Else just let selection percolate up. We'll adjust it in
// AfterEdit()
}
} else {
if (aAction == nsIEditor::eNext) {
- // Adjust selection to be right after it.
- res = aSelection->Collapse(blockParent, offset + 1);
- NS_ENSURE_SUCCESS(res, res);
-
- // Move to the start of the next node if it's a text.
+ // Move to the start of the next node, if any
nsCOMPtr<nsIContent> nextNode = mHTMLEditor->GetNextNode(blockParent,
offset + 1, true);
- if (nextNode && mHTMLEditor->IsTextNode(nextNode)) {
- res = aSelection->Collapse(nextNode, 0);
+ if (nextNode) {
+ EditorDOMPoint pt = GetGoodSelPointForNode(*nextNode, aAction);
+ res = aSelection->Collapse(pt.node, pt.offset);
+ NS_ENSURE_SUCCESS(res, res);
+ } else {
+ // Adjust selection to be right after it.
+ res = aSelection->Collapse(blockParent, offset + 1);
NS_ENSURE_SUCCESS(res, res);
}
} else {
- // Move to the end of the previous node if it's a text.
+ // Move to the end of the previous node
nsCOMPtr<nsIContent> priorNode = mHTMLEditor->GetPriorNode(blockParent,
offset,
true);
- if (priorNode && mHTMLEditor->IsTextNode(priorNode)) {
- res = aSelection->Collapse(priorNode, priorNode->TextLength());
+ if (priorNode) {
+ EditorDOMPoint pt = GetGoodSelPointForNode(*priorNode, aAction);
+ res = aSelection->Collapse(pt.node, pt.offset);
NS_ENSURE_SUCCESS(res, res);
} else {
res = aSelection->Collapse(blockParent, offset + 1);
NS_ENSURE_SUCCESS(res, res);
}
}
}
NS_ENSURE_STATE(mHTMLEditor);
@@ -7367,36 +7357,25 @@ HTMLEditRules::AdjustSelection(Selection
// look for a nearby text node.
// prefer the correct direction.
nsCOMPtr<nsIDOMNode> nearNodeDOM = GetAsDOMNode(nearNode);
res = FindNearSelectableNode(GetAsDOMNode(selNode), selOffset, aAction,
address_of(nearNodeDOM));
NS_ENSURE_SUCCESS(res, res);
nearNode = do_QueryInterface(nearNodeDOM);
- if (nearNode)
- {
- // is the nearnode a text node?
- textNode = do_QueryInterface(nearNode);
- if (textNode)
- {
- int32_t offset = 0;
- // put selection in right place:
- if (aAction == nsIEditor::ePrevious)
- textNode->GetLength((uint32_t*)&offset);
- res = aSelection->Collapse(nearNode,offset);
- }
- else // must be break or image
- {
- selNode = EditorBase::GetNodeLocation(nearNode, &selOffset);
- if (aAction == nsIEditor::ePrevious) selOffset++; // want to be beyond it if we backed up to it
- res = aSelection->Collapse(selNode, selOffset);
- }
- }
- return res;
+ if (!nearNode) {
+ return NS_OK;
+ }
+ EditorDOMPoint pt = GetGoodSelPointForNode(*nearNode, aAction);
+ res = aSelection->Collapse(pt.node, pt.offset);
+ if (NS_WARN_IF(NS_FAILED(res))) {
+ return res;
+ }
+ return NS_OK;
}
nsresult
HTMLEditRules::FindNearSelectableNode(nsIDOMNode* aSelNode,
int32_t aSelOffset,
nsIEditor::EDirection& aDirection,
nsCOMPtr<nsIDOMNode>* outSelectableNode)
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -948,35 +948,40 @@ HTMLEditor::IsPrevCharInNodeWhitespace(n
bool
HTMLEditor::IsVisBreak(nsINode* aNode)
{
MOZ_ASSERT(aNode);
if (!TextEditUtils::IsBreak(aNode)) {
return false;
}
// Check if there is a later node in block after br
- nsCOMPtr<nsINode> priorNode = GetPriorHTMLNode(aNode, true);
- if (priorNode && TextEditUtils::IsBreak(priorNode)) {
- return true;
- }
nsCOMPtr<nsINode> nextNode = GetNextHTMLNode(aNode, true);
if (nextNode && TextEditUtils::IsBreak(nextNode)) {
return true;
}
- // If we are right before block boundary, then br not visible
+ // A single line break before a block boundary is not displayed, so e.g.
+ // foo<p>bar<br></p> and foo<br><p>bar</p> display the same as foo<p>bar</p>.
+ // But if there are multiple <br>s in a row, all but the last are visible.
if (!nextNode) {
// This break is trailer in block, it's not visible
return false;
}
if (IsBlockNode(nextNode)) {
// Break is right before a block, it's not visible
return false;
}
+ // If there's an inline node after this one that's not a break, and also a
+ // prior break, this break must be visible.
+ nsCOMPtr<nsINode> priorNode = GetPriorHTMLNode(aNode, true);
+ if (priorNode && TextEditUtils::IsBreak(priorNode)) {
+ return true;
+ }
+
// Sigh. We have to use expensive whitespace calculation code to
// determine what is going on
int32_t selOffset;
nsCOMPtr<nsINode> selNode = GetNodeLocation(aNode, &selOffset);
// Let's look after the break
selOffset++;
WSRunObject wsObj(this, selNode, selOffset);
nsCOMPtr<nsINode> unused;
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -60,17 +60,17 @@ namespace JS {
D(ALLOC_TRIGGER) \
D(DEBUG_GC) \
D(COMPARTMENT_REVIVED) \
D(RESET) \
D(OUT_OF_NURSERY) \
D(EVICT_NURSERY) \
D(FULL_STORE_BUFFER) \
D(SHARED_MEMORY_LIMIT) \
- D(PERIODIC_FULL_GC) \
+ D(UNUSED1) \
D(INCREMENTAL_TOO_SLOW) \
D(ABORT_GC) \
\
/* These are reserved for future use. */ \
D(RESERVED0) \
D(RESERVED1) \
D(RESERVED2) \
D(RESERVED3) \
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -454,24 +454,16 @@ class GCSchedulingTunables
* phase, we have a highFrequencyGCMode that ups the growth rate to 300%
* of the current size[retained] so that we'll do fewer longer GCs at the
* end of the mutator startup rather than more, smaller GCs.
*
* Assumptions:
* -> Responsiveness is proportional to t[marking] + t[sweeping].
* -> size[retained] is proportional only to GC allocations.
*
- * PERIODIC_FULL_GC
- * ----------------
- * When we return to the event loop and it has been 20 seconds since we've
- * done a GC, we start an incremenal, all-zones, shrinking GC.
- *
- * Assumptions:
- * -> Our triggers are incomplete.
- *
* ALLOC_TRIGGER (non-incremental)
* -------------------------------
* If we do not return to the event loop before getting all the way to our
* gc trigger bytes then MAYBEGC will never fire. To avoid OOMing, we
* succeed the current allocation and set the script interrupt so that we
* will (hopefully) do a GC before we overflow our max and have to raise
* an OOM exception for the script.
*
@@ -618,18 +610,17 @@ class GCRuntime
MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock);
MOZ_MUST_USE bool triggerGC(JS::gcreason::Reason reason);
void maybeAllocTriggerZoneGC(Zone* zone, const AutoLockGC& lock);
// The return value indicates if we were able to do the GC.
bool triggerZoneGC(Zone* zone, JS::gcreason::Reason reason);
- MOZ_MUST_USE bool maybeGC(Zone* zone);
- void maybePeriodicFullGC();
+ void maybeGC(Zone* zone);
void minorGC(JS::gcreason::Reason reason,
gcstats::Phase phase = gcstats::PHASE_MINOR_GC) JS_HAZ_GC_CALL;
void evictNursery(JS::gcreason::Reason reason = JS::gcreason::EVICT_NURSERY) {
minorGC(reason, gcstats::PHASE_EVICT_NURSERY);
}
// The return value indicates whether a major GC was performed.
bool gcIfRequested();
void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason);
@@ -1067,17 +1058,16 @@ class GCRuntime
/*
* Number of the committed arenas in all GC chunks including empty chunks.
*/
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> numArenasFreeCommitted;
VerifyPreTracer* verifyPreData;
private:
bool chunkAllocationSinceLastGC;
- int64_t nextFullGCTime;
int64_t lastGCTime;
JSGCMode mode;
mozilla::Atomic<size_t, mozilla::ReleaseAcquire> numActiveZoneIters;
uint64_t decommitThreshold;
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -153,18 +153,18 @@ js::Nursery::init(uint32_t maxNurseryByt
return false;
setCurrentChunk(0);
setStartPosition();
char* env = getenv("JS_GC_PROFILE_NURSERY");
if (env) {
if (0 == strcmp(env, "help")) {
- fprintf(stderr, "JS_GC_PROFILE_NURSERY=N\n\n"
- "\tReport minor GC's taking more than N microseconds.");
+ fprintf(stderr, "JS_GC_PROFILE_NURSERY=N\n"
+ "\tReport minor GC's taking more than N microseconds.\n");
exit(0);
}
enableProfiling_ = true;
profileThreshold_ = atoi(env);
}
PodZero(&startTimes_);
PodZero(&profileTimes_);
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -753,38 +753,53 @@ Statistics::Statistics(JSRuntime* rt)
timedGCStart(0),
preBytes(0),
maxPauseInInterval(0),
phaseNestingDepth(0),
activeDagSlot(PHASE_DAG_NONE),
suspended(0),
sliceCallback(nullptr),
nurseryCollectionCallback(nullptr),
- aborted(false)
+ aborted(false),
+ enableProfiling_(false),
+ sliceCount_(0)
{
PodArrayZero(phaseTotals);
PodArrayZero(counts);
PodArrayZero(phaseStartTimes);
for (auto d : MakeRange(NumTimingArrays))
PodArrayZero(phaseTimes[d]);
- char* env = getenv("MOZ_GCTIMER");
+ const char* env = getenv("MOZ_GCTIMER");
if (env) {
if (strcmp(env, "none") == 0) {
fp = nullptr;
} else if (strcmp(env, "stdout") == 0) {
fp = stdout;
} else if (strcmp(env, "stderr") == 0) {
fp = stderr;
} else {
fp = fopen(env, "a");
if (!fp)
MOZ_CRASH("Failed to open MOZ_GCTIMER log file.");
}
}
+
+ env = getenv("JS_GC_PROFILE");
+ if (env) {
+ if (0 == strcmp(env, "help")) {
+ fprintf(stderr, "JS_GC_PROFILE=N\n"
+ "\tReport major GC's taking more than N milliseconds.\n");
+ exit(0);
+ }
+ enableProfiling_ = true;
+ profileThreshold_ = atoi(env);
+ }
+
+ PodZero(&totalTimes_);
}
Statistics::~Statistics()
{
if (fp && fp != stdout && fp != stderr)
fclose(fp);
}
@@ -1041,22 +1056,27 @@ Statistics::endSlice()
runtime->addTelemetry(JS_TELEMETRY_GC_ANIMATION_MS, t(sliceTime));
// Record any phase that goes more than 2x over its budget.
if (sliceTime > 2 * budget_ms * 1000) {
Phase longest = LongestPhase(slices.back().phaseTimes);
runtime->addTelemetry(JS_TELEMETRY_GC_SLOW_PHASE, phases[longest].telemetryBucket);
}
}
+
+ sliceCount_++;
}
bool last = !runtime->gc.isIncrementalGCInProgress();
if (last)
endGC();
+ if (enableProfiling_ && !aborted && slices.back().duration() >= profileThreshold_)
+ printSliceProfile();
+
// Slice callbacks should only fire for the outermost level.
if (gcDepth == 1 && !aborted) {
bool wasFullGC = zoneStats.isCollectingAllZones();
if (sliceCallback)
(*sliceCallback)(runtime->contextFromMainThread(),
last ? JS::GC_CYCLE_END : JS::GC_SLICE_END,
JS::GCDescription(!wasFullGC, gckind, slices.back().reason));
}
@@ -1254,8 +1274,64 @@ Statistics::computeMMU(int64_t window) c
if (slices[endIndex].end - slices[startIndex].start > window)
cur -= (slices[endIndex].end - slices[startIndex].start - window);
if (cur > gcMax)
gcMax = cur;
}
return double(window - gcMax) / window;
}
+
+/* static */ void
+Statistics::printProfileHeader()
+{
+ fprintf(stderr, " %6s", "total");
+#define PRINT_PROFILE_HEADER(name, text, phase) \
+ fprintf(stderr, " %6s", text);
+FOR_EACH_GC_PROFILE_TIME(PRINT_PROFILE_HEADER)
+#undef PRINT_PROFILE_HEADER
+ fprintf(stderr, "\n");
+}
+
+/* static */ void
+Statistics::printProfileTimes(const ProfileTimes& times)
+{
+ for (auto time : times)
+ fprintf(stderr, " %6" PRIi64, time / PRMJ_USEC_PER_MSEC);
+ fprintf(stderr, "\n");
+}
+
+void
+Statistics::printSliceProfile()
+{
+ const SliceData& slice = slices.back();
+
+ static int printedHeader = 0;
+ if ((printedHeader++ % 200) == 0) {
+ fprintf(stderr, "MajorGC: Reason States ");
+ printProfileHeader();
+ }
+
+ fprintf(stderr, "MajorGC: %20s %1d -> %1d ",
+ ExplainReason(slice.reason), slice.initialState, slice.finalState);
+
+ ProfileTimes times;
+ times[ProfileKey::Total] = slice.duration();
+ totalTimes_[ProfileKey::Total] += times[ProfileKey::Total];
+
+#define GET_PROFILE_TIME(name, text, phase) \
+ times[ProfileKey::name] = slice.phaseTimes[PHASE_DAG_NONE][phase]; \
+ totalTimes_[ProfileKey::name] += times[ProfileKey::name];
+FOR_EACH_GC_PROFILE_TIME(GET_PROFILE_TIME)
+#undef GET_PROFILE_TIME
+
+ printProfileTimes(times);
+}
+
+void
+Statistics::printTotalProfileTimes()
+{
+ if (enableProfiling_) {
+ fprintf(stderr, "MajorGC TOTALS: %7" PRIu64 " slices: ", sliceCount_);
+ printProfileTimes(totalTimes_);
+ }
+}
+
--- a/js/src/gc/Statistics.h
+++ b/js/src/gc/Statistics.h
@@ -2,16 +2,17 @@
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/. */
#ifndef gc_Statistics_h
#define gc_Statistics_h
+#include "mozilla/EnumeratedArray.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/PodOperations.h"
#include "jsalloc.h"
#include "jsgc.h"
#include "jspubtd.h"
#include "js/GCAPI.h"
@@ -129,16 +130,28 @@ struct ZoneGCStats
bool isCollectingAllZones() const { return collectedZoneCount == zoneCount; }
ZoneGCStats()
: collectedZoneCount(0), zoneCount(0), sweptZoneCount(0),
collectedCompartmentCount(0), compartmentCount(0), sweptCompartmentCount(0)
{}
};
+#define FOR_EACH_GC_PROFILE_TIME(_) \
+ _(BeginCallback, "beginCB", PHASE_GC_BEGIN) \
+ _(WaitBgThread, "waitBG", PHASE_WAIT_BACKGROUND_THREAD) \
+ _(DiscardCode, "discard", PHASE_MARK_DISCARD_CODE) \
+ _(RelazifyFunc, "relazify", PHASE_RELAZIFY_FUNCTIONS) \
+ _(Purge, "purge", PHASE_PURGE) \
+ _(Mark, "mark", PHASE_MARK) \
+ _(Sweep, "sweep", PHASE_SWEEP) \
+ _(Compact, "compact", PHASE_COMPACT) \
+ _(EndCallback, "endCB", PHASE_GC_END) \
+ _(Barriers, "barriers", PHASE_BARRIER)
+
/*
* Struct for collecting timing statistics on a "phase tree". The tree is
* specified as a limited DAG, but the timings are collected for the whole tree
* that you would get by expanding out the DAG by duplicating subtrees rooted
* at nodes with multiple parents.
*
* During execution, a child phase can be activated multiple times, and the
* total time will be accumulated. (So for example, you can start and end
@@ -275,16 +288,19 @@ struct Statistics
};
typedef Vector<SliceData, 8, SystemAllocPolicy> SliceDataVector;
typedef SliceDataVector::ConstRange SliceRange;
SliceRange sliceRange() const { return slices.all(); }
size_t slicesLength() const { return slices.length(); }
+ /* Print total profile times on shutdown. */
+ void printTotalProfileTimes();
+
private:
JSRuntime* runtime;
int64_t startupTime;
/* File pointer used for MOZ_GCTIMER output. */
FILE* fp;
@@ -346,16 +362,35 @@ struct Statistics
JS::GCNurseryCollectionCallback nurseryCollectionCallback;
/*
* True if we saw an OOM while allocating slices. The statistics for this
* GC will be invalid.
*/
bool aborted;
+ /* Profiling data. */
+
+ enum class ProfileKey
+ {
+ Total,
+#define DEFINE_TIME_KEY(name, text, phase) \
+ name,
+FOR_EACH_GC_PROFILE_TIME(DEFINE_TIME_KEY)
+#undef DEFINE_TIME_KEY
+ KeyCount
+ };
+
+ using ProfileTimes = mozilla::EnumeratedArray<ProfileKey, ProfileKey::KeyCount, int64_t>;
+
+ int64_t profileThreshold_;
+ bool enableProfiling_;
+ ProfileTimes totalTimes_;
+ uint64_t sliceCount_;
+
void beginGC(JSGCInvocationKind kind);
void endGC();
void recordPhaseEnd(Phase phase);
void gcDuration(int64_t* total, int64_t* maxPause) const;
void sccDurations(int64_t* total, int64_t* maxPause);
void printStats();
@@ -367,16 +402,20 @@ struct Statistics
UniqueChars formatDetailedPhaseTimes(const PhaseTimeTable phaseTimes);
UniqueChars formatDetailedTotals();
UniqueChars formatJsonDescription(uint64_t timestamp);
UniqueChars formatJsonSliceDescription(unsigned i, const SliceData& slice);
UniqueChars formatJsonPhaseTimes(const PhaseTimeTable phaseTimes);
double computeMMU(int64_t resolution) const;
+
+ void printSliceProfile();
+ static void printProfileHeader();
+ static void printProfileTimes(const ProfileTimes& times);
};
struct MOZ_RAII AutoGCSlice
{
AutoGCSlice(Statistics& stats, const ZoneGCStats& zoneStats, JSGCInvocationKind gckind,
SliceBudget budget, JS::gcreason::Reason reason)
: stats(stats)
{
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1334,18 +1334,17 @@ JS_GC(JSContext* cx)
JS::PrepareForFullGC(cx);
cx->gc.gc(GC_NORMAL, JS::gcreason::API);
}
JS_PUBLIC_API(void)
JS_MaybeGC(JSContext* cx)
{
GCRuntime& gc = cx->runtime()->gc;
- if (!gc.maybeGC(cx->zone()))
- gc.maybePeriodicFullGC();
+ gc.maybeGC(cx->zone());
}
JS_PUBLIC_API(void)
JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data)
{
AssertHeapIsIdle(cx);
cx->gc.setGCCallback(cb, data);
}
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -519,25 +519,25 @@ class HandleValueArray
}
};
} /* namespace JS */
/************************************************************************/
struct JSFreeOp {
- private:
+ protected:
JSRuntime* runtime_;
- protected:
explicit JSFreeOp(JSRuntime* rt)
: runtime_(rt) { }
public:
JSRuntime* runtime() const {
+ MOZ_ASSERT(runtime_);
return runtime_;
}
};
/* Callbacks and their arguments. */
/************************************************************************/
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -244,19 +244,16 @@ using namespace js::gc;
using mozilla::ArrayLength;
using mozilla::Get;
using mozilla::Maybe;
using mozilla::Swap;
using JS::AutoGCRooter;
-/* Perform a Full GC every 20 seconds if MaybeGC is called */
-static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
-
/* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
static const int IGC_MARK_SLICE_MULTIPLIER = 2;
const AllocKind gc::slotsToThingKind[] = {
/* 0 */ AllocKind::OBJECT0, AllocKind::OBJECT2, AllocKind::OBJECT2, AllocKind::OBJECT4,
/* 4 */ AllocKind::OBJECT4, AllocKind::OBJECT8, AllocKind::OBJECT8, AllocKind::OBJECT8,
/* 8 */ AllocKind::OBJECT8, AllocKind::OBJECT12, AllocKind::OBJECT12, AllocKind::OBJECT12,
/* 12 */ AllocKind::OBJECT12, AllocKind::OBJECT16, AllocKind::OBJECT16, AllocKind::OBJECT16,
@@ -489,22 +486,22 @@ FinalizeTypedArenas(FreeOp* fop,
Arena** src,
SortedArenaList& dest,
AllocKind thingKind,
SliceBudget& budget,
ArenaLists::KeepArenasEnum keepArenas)
{
// When operating in the foreground, take the lock at the top.
Maybe<AutoLockGC> maybeLock;
- if (!fop->onBackgroundThread())
+ if (fop->onMainThread())
maybeLock.emplace(fop->runtime());
// During background sweeping free arenas are released later on in
// sweepBackgroundThings().
- MOZ_ASSERT_IF(fop->onBackgroundThread(), keepArenas == ArenaLists::KEEP_ARENAS);
+ MOZ_ASSERT_IF(!fop->onMainThread(), keepArenas == ArenaLists::KEEP_ARENAS);
size_t thingSize = Arena::thingSize(thingKind);
size_t thingsPerArena = Arena::thingsPerArena(thingKind);
while (Arena* arena = *src) {
*src = arena->next;
size_t nmarked = arena->finalize<T>(fop, thingKind, thingSize);
size_t nfree = thingsPerArena - nmarked;
@@ -802,17 +799,16 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
marker(rt),
usage(nullptr),
mMemProfiler(rt),
maxMallocBytes(0),
nextCellUniqueId_(LargestTaggedNullCellPointer + 1), // Ensure disjoint from null tagged pointers.
numArenasFreeCommitted(0),
verifyPreData(nullptr),
chunkAllocationSinceLastGC(false),
- nextFullGCTime(0),
lastGCTime(PRMJ_Now()),
mode(JSGC_MODE_INCREMENTAL),
numActiveZoneIters(0),
decommitThreshold(32 * 1024 * 1024),
cleanUpEverything(false),
grayBufferState(GCRuntime::GrayBufferState::Unused),
grayBitsValid(false),
majorGCTriggerReason(JS::gcreason::NO_REASON),
@@ -1110,16 +1106,17 @@ GCRuntime::finish()
FreeChunkPool(rt, fullChunks_);
FreeChunkPool(rt, availableChunks_);
FreeChunkPool(rt, emptyChunks_);
FinishTrace();
nursery.printTotalProfileTimes();
+ stats.printTotalProfileTimes();
}
bool
GCRuntime::setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock)
{
switch (key) {
case JSGC_MAX_MALLOC_BYTES:
setMaxMallocBytes(value);
@@ -2785,17 +2782,17 @@ ArenaLists::backgroundFinalize(FreeOp* f
ArenaList finalized = finalizedSorted.toArenaList();
// We must take the GC lock to be able to safely modify the ArenaList;
// however, this does not by itself make the changes visible to all threads,
// as not all threads take the GC lock to read the ArenaLists.
// That safety is provided by the ReleaseAcquire memory ordering of the
// background finalize state, which we explicitly set as the final step.
{
- AutoLockGC lock(fop->runtime());
+ AutoLockGC lock(lists->runtime_);
MOZ_ASSERT(lists->backgroundFinalizeState[thingKind] == BFS_RUN);
// Join |al| and |finalized| into a single list.
*al = finalized.insertListWithCursorAtEnd(*al);
lists->arenaListsToSweep[thingKind] = nullptr;
}
@@ -3034,70 +3031,40 @@ GCRuntime::triggerZoneGC(Zone* zone, JS:
return true;
}
PrepareZoneForGC(zone);
requestMajorGC(reason);
return true;
}
-bool
+void
GCRuntime::maybeGC(Zone* zone)
{
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
#ifdef JS_GC_ZEAL
if (hasZealMode(ZealMode::Alloc) || hasZealMode(ZealMode::Poke)) {
JS::PrepareForFullGC(rt->contextFromMainThread());
gc(GC_NORMAL, JS::gcreason::DEBUG_GC);
- return true;
+ return;
}
#endif
if (gcIfRequested())
- return true;
+ return;
if (zone->usage.gcBytes() > 1024 * 1024 &&
zone->usage.gcBytes() >= zone->threshold.allocTrigger(schedulingState.inHighFrequencyGCMode()) &&
!isIncrementalGCInProgress() &&
!isBackgroundSweeping())
{
PrepareZoneForGC(zone);
startGC(GC_NORMAL, JS::gcreason::EAGER_ALLOC_TRIGGER);
- return true;
- }
-
- return false;
-}
-
-void
-GCRuntime::maybePeriodicFullGC()
-{
- /*
- * Trigger a periodic full GC.
- *
- * This is a source of non-determinism, but is not called from the shell.
- *
- * Access to the counters and, on 32 bit, setting gcNextFullGCTime below
- * is not atomic and a race condition could trigger or suppress the GC. We
- * tolerate this.
- */
-#ifndef JS_MORE_DETERMINISTIC
- int64_t now = PRMJ_Now();
- if (nextFullGCTime && nextFullGCTime <= now && !isIncrementalGCInProgress()) {
- if (chunkAllocationSinceLastGC ||
- numArenasFreeCommitted > decommitThreshold)
- {
- JS::PrepareForFullGC(rt->contextFromMainThread());
- startGC(GC_SHRINK, JS::gcreason::PERIODIC_FULL_GC);
- } else {
- nextFullGCTime = now + GC_IDLE_FULL_SPAN;
- }
- }
-#endif
+ }
}
// Do all possible decommit immediately from the current thread without
// releasing the GC lock or allocating any memory.
void
GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC& lock)
{
MOZ_ASSERT(emptyChunks(lock).count() == 0);
@@ -3187,17 +3154,17 @@ GCRuntime::sweepBackgroundThings(ZoneLis
{
freeBlocks.freeAll();
if (zones.isEmpty())
return;
// We must finalize thing kinds in the order specified by BackgroundFinalizePhases.
Arena* emptyArenas = nullptr;
- FreeOp fop(rt, threadType);
+ FreeOp fop(threadType == MainThread ? rt : nullptr);
for (unsigned phase = 0 ; phase < ArrayLength(BackgroundFinalizePhases) ; ++phase) {
for (Zone* zone = zones.front(); zone; zone = zone->nextZone()) {
for (auto kind : BackgroundFinalizePhases[phase].kinds) {
Arena* arenas = zone->arenas.arenaListsToSweep[kind];
MOZ_RELEASE_ASSERT(uintptr_t(arenas) != uintptr_t(-1));
if (arenas)
ArenaLists::backgroundFinalize(&fop, arenas, &emptyArenas);
}
@@ -6136,20 +6103,16 @@ GCRuntime::gcCycle(bool nonincrementalBy
/* The GC was reset, so we need a do-over. */
if (prevState != State::NotActive && !isIncrementalGCInProgress())
return true;
TraceMajorGCStart();
incrementalCollectSlice(budget, reason, session.lock);
-#ifndef JS_MORE_DETERMINISTIC
- nextFullGCTime = PRMJ_Now() + GC_IDLE_FULL_SPAN;
-#endif
-
chunkAllocationSinceLastGC = false;
#ifdef JS_GC_ZEAL
/* Keeping these around after a GC is dangerous. */
clearSelectedForMarking();
#endif
/* Clear gcMallocBytes for all zones. */
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -197,17 +197,17 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
spsProfiler(thisFromCtor()),
profilingScripts(false),
suppressProfilerSampling(false),
hadOutOfMemory(false),
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
runningOOMTest(false),
#endif
allowRelazificationForTesting(false),
- defaultFreeOp_(thisFromCtor()),
+ defaultFreeOp_(nullptr),
debuggerMutations(0),
securityCallbacks(&NullSecurityCallbacks),
DOMcallbacks(nullptr),
destroyPrincipals(nullptr),
readPrincipals(nullptr),
warningReporter(nullptr),
buildIdOp(nullptr),
propertyRemovals(0),
@@ -286,16 +286,20 @@ JSRuntime::init(uint32_t maxbytes, uint3
if (!regexpStack.init())
return false;
if (CanUseExtraThreads() && !EnsureHelperThreadsInitialized())
return false;
js::TlsPerThreadData.set(&mainThread);
+ defaultFreeOp_ = js_new<js::FreeOp>(this);
+ if (!defaultFreeOp_)
+ return false;
+
if (!gc.init(maxbytes, maxNurseryBytes))
return false;
ScopedJSDeletePtr<Zone> atomsZone(new_<Zone>(this));
if (!atomsZone || !atomsZone->init(true))
return false;
JS::CompartmentOptions options;
@@ -418,16 +422,18 @@ JSRuntime::destroyRuntime()
#if !EXPOSE_INTL_API
FinishRuntimeNumberState(this);
#endif
gc.finish();
atomsCompartment_ = nullptr;
+ js_delete(defaultFreeOp_);
+
js_free(defaultLocale);
js_delete(jitRuntime_);
js_delete(ionPcScriptCache);
gc.storeBuffer.disable();
gc.nursery.disable();
@@ -674,25 +680,37 @@ JSRuntime::triggerActivityCallback(bool
* suppression serves to inform the exact rooting hazard analysis of this
* property and ensures that it remains true in the future.
*/
AutoSuppressGC suppress(contextFromMainThread());
activityCallback(activityCallbackArg, active);
}
+FreeOp::FreeOp(JSRuntime* maybeRuntime)
+ : JSFreeOp(maybeRuntime)
+{
+ MOZ_ASSERT_IF(maybeRuntime, CurrentThreadCanAccessRuntime(maybeRuntime));
+}
+
FreeOp::~FreeOp()
{
for (size_t i = 0; i < freeLaterList.length(); i++)
free_(freeLaterList[i]);
if (!jitPoisonRanges.empty())
jit::ExecutableAllocator::poisonCode(runtime(), jitPoisonRanges);
}
+bool
+FreeOp::isDefaultFreeOp() const
+{
+ return runtime_ && runtime_->defaultFreeOp() == this;
+}
+
JSObject*
JSRuntime::getIncumbentGlobal(JSContext* cx)
{
MOZ_ASSERT(cx->runtime()->getIncumbentGlobalCallback,
"Must set a callback using JS_SetGetIncumbentGlobalCallback before using Promises");
return cx->runtime()->getIncumbentGlobalCallback(cx);
}
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -116,33 +116,31 @@ class Simulator;
*
* FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
* need to pass a JSContext to those hooks.
*/
class FreeOp : public JSFreeOp
{
Vector<void*, 0, SystemAllocPolicy> freeLaterList;
jit::JitPoisonRangeVector jitPoisonRanges;
- ThreadType threadType;
public:
static FreeOp* get(JSFreeOp* fop) {
return static_cast<FreeOp*>(fop);
}
- explicit FreeOp(JSRuntime* rt, ThreadType thread = MainThread)
- : JSFreeOp(rt), threadType(thread)
- {}
-
+ explicit FreeOp(JSRuntime* maybeRuntime);
~FreeOp();
- bool onBackgroundThread() {
- return threadType == BackgroundThread;
+ bool onMainThread() const {
+ return runtime_ != nullptr;
}
+ bool isDefaultFreeOp() const;
+
inline void free_(void* p);
inline void freeLater(void* p);
inline bool appendJitPoisonRange(const jit::JitPoisonRange& range);
template <class T>
inline void delete_(T* p) {
if (p) {
@@ -917,21 +915,22 @@ struct JSRuntime : public JS::shadow::Ru
*/
JSCList onNewGlobalObjectWatchers;
#if defined(XP_DARWIN) && defined(ASMJS_MAY_USE_SIGNAL_HANDLERS)
js::wasm::MachExceptionHandler wasmMachExceptionHandler;
#endif
private:
- js::FreeOp defaultFreeOp_;
+ js::FreeOp* defaultFreeOp_;
public:
js::FreeOp* defaultFreeOp() {
- return &defaultFreeOp_;
+ MOZ_ASSERT(defaultFreeOp_);
+ return defaultFreeOp_;
}
uint32_t debuggerMutations;
const JSSecurityCallbacks* securityCallbacks;
const js::DOMCallbacks* DOMcallbacks;
JSDestroyPrincipalsOp destroyPrincipals;
JSReadPrincipalsOp readPrincipals;
@@ -1338,29 +1337,29 @@ FreeOp::free_(void* p)
js_free(p);
}
inline void
FreeOp::freeLater(void* p)
{
// FreeOps other than the defaultFreeOp() are constructed on the stack,
// and won't hold onto the pointers to free indefinitely.
- MOZ_ASSERT(this != runtime()->defaultFreeOp());
+ MOZ_ASSERT(!isDefaultFreeOp());
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!freeLaterList.append(p))
oomUnsafe.crash("FreeOp::freeLater");
}
inline bool
FreeOp::appendJitPoisonRange(const jit::JitPoisonRange& range)
{
// FreeOps other than the defaultFreeOp() are constructed on the stack,
// and won't hold onto the pointers to free indefinitely.
- MOZ_ASSERT(this != runtime()->defaultFreeOp());
+ MOZ_ASSERT(!isDefaultFreeOp());
return jitPoisonRanges.append(range);
}
/*
* RAII class that takes the GC lock while it is live.
*
* Note that the lock may be temporarily released by use of AutoUnlockGC when
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -150,20 +150,18 @@ TypedArrayObject::finalize(FreeOp* fop,
MOZ_ASSERT(!IsInsideNursery(obj));
TypedArrayObject* curObj = &obj->as<TypedArrayObject>();
// Typed arrays with a buffer object do not need to be free'd
if (curObj->hasBuffer())
return;
// Free the data slot pointer if it does not point into the old JSObject.
- Nursery& nursery = fop->runtime()->gc.nursery;
- if (!curObj->hasInlineElements() && !nursery.isInside(curObj->elements())) {
+ if (!curObj->hasInlineElements())
js_free(curObj->elements());
- }
}
/* static */ void
TypedArrayObject::objectMoved(JSObject* obj, const JSObject* old)
{
TypedArrayObject* newObj = &obj->as<TypedArrayObject>();
const TypedArrayObject* oldObj = &old->as<TypedArrayObject>();
--- a/mobile/android/tests/browser/robocop/robocop.ini
+++ b/mobile/android/tests/browser/robocop/robocop.ini
@@ -71,17 +71,16 @@ skip-if = android_version == "18"
# [src/org/mozilla/gecko/tests/testVkbOverlap.java] # see bug 907274
# Using JavascriptTest
# (If your test can be written entirely in Javascript, consider writing
# it as a chrome test instead. See mobile/android/tests/browser/chrome.)
[src/org/mozilla/gecko/tests/testBrowserDiscovery.java]
[src/org/mozilla/gecko/tests/testFilePicker.java]
[src/org/mozilla/gecko/tests/testHistoryService.java]
-# [src/org/mozilla/gecko/tests/testMozPay.java] # see bug 945675
[src/org/mozilla/gecko/tests/testOSLocale.java]
# disabled on 4.3: Bug 1124494
skip-if = android_version == "18"
[src/org/mozilla/gecko/tests/testReadingListCache.java]
[src/org/mozilla/gecko/tests/testRestrictions.java]
[src/org/mozilla/gecko/tests/testSnackbarAPI.java]
[src/org/mozilla/gecko/tests/testTrackingProtection.java]
[src/org/mozilla/gecko/tests/testUITelemetry.java]
deleted file mode 100644
--- a/mobile/android/tests/browser/robocop/roboextender/base/paymentsUI.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<html>
- <head>
- <script type="text/javascript">
-function start() {
- if (!mozPaymentProvider)
- window.close();
-
- // We don't have a way to mock these values yet. This check just makes sure the world
- // doesn't crash if we ask for them.
- var mcc = mozPaymentProvider.mcc;
- var mnc = mozPaymentProvider.mnc;
-
- // We use the jwt passed in here to test calling paymentFailed/Success
- if (window.location.hash == "#pass")
- mozPaymentProvider.paymentSuccess("PAID CORRECTLY");
- else if (window.location.hash == "#fail")
- mozPaymentProvider.paymentFailed("FAILED CORRECTLY");
- else
- mozPaymentProvider.paymentFailed("invalid hash " + window.location.hash);
-}
-
-document.addEventListener("DOMContentLoaded", start);
- </script>
- </head>
-</html>
deleted file mode 100644
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMozPay.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/* 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/. */
-
-package org.mozilla.gecko.tests;
-
-
-
-public class testMozPay extends JavascriptTest {
- public testMozPay() {
- super("testMozPay.js");
- }
-}
deleted file mode 100644
--- a/mobile/android/tests/browser/robocop/testMozPay.js
+++ /dev/null
@@ -1,102 +0,0 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
-/* 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/. */
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-Components.utils.import("resource://gre/modules/SharedPreferences.jsm");
-Components.utils.import("resource://gre/modules/Promise.jsm");
-
-var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
-var deferred = 0;
-var shouldPass = true;
-var reqId = 0;
-function getRequestId(increment) {
- reqId += increment;
- return "Request" + reqId;
-}
-
-var paymentSuccess = {
- receiveMessage: function(aMsg) {
- let msg = aMsg.json;
- if (shouldPass) {
- do_check_eq(msg.requestId, getRequestId(0));
- } else {
- do_throw("Test should not have passed");
- }
- deferred.resolve();
- }
-}
-
-var paymentFailed = {
- receiveMessage: function(aMsg) {
- let msg = aMsg.json;
- if (shouldPass) {
- do_throw("Test should not have failed: " + msg.errorMsg);
- } else {
- do_check_eq(msg.requestId, getRequestId(0));
- do_check_eq(msg.errorMsg, "FAILED CORRECTLY");
- }
- deferred.resolve();
- }
-}
-
-add_task(function test_get_set() {
- let ui = Cc["@mozilla.org/payment/ui-glue;1"].getService(Ci.nsIPaymentUIGlue);
- deferred = Promise.defer();
- let id = getRequestId(1);
- ui.confirmPaymentRequest(id,
- [{ wrappedJSObject: { type: "Fake Provider" } }],
- function(aRequestId, type) {
- do_check_eq(type, "Fake Provider");
- deferred.resolve();
- },
- function(id, msg) {
- do_throw("confirmPaymentRequest should not have failed");
- deferred.resolve();
- });
- yield deferred.promise;
-});
-
-add_task(function test_default() {
- ppmm.addMessageListener("Payment:Success", paymentSuccess);
- ppmm.addMessageListener("Payment:Failed", paymentFailed);
-
- let ui = Cc["@mozilla.org/payment/ui-glue;1"].getService(Ci.nsIPaymentUIGlue);
- deferred = Promise.defer();
- let id = getRequestId(1);
- shouldPass = true;
- ui.showPaymentFlow(id,
- {
- uri: "chrome://roboextender/content/paymentsUI.html",
- jwt: "#pass"
- },
- function(id, msg) {
- do_throw("confirmPaymentRequest should not have failed");
- deferred.resolve();
- });
- yield deferred.promise;
-
- deferred = Promise.defer();
- id = getRequestId(1);
- shouldPass = false;
- ui.showPaymentFlow(id,
- {
- uri: "chrome://roboextender/content/paymentsUI.html",
- jwt: "#fail"
- },
- function(id, msg) {
- do_throw("confirmPaymentRequest should not have failed");
- deferred.resolve();
- });
-
- yield deferred.promise;
-
- ppmm.removeMessageListener("Payment:Success", paymentSuccess);
- ppmm.removeMessageListener("Payment:Failed", paymentFailed);
-});
-
-run_next_test();
--- a/old-configure.in
+++ b/old-configure.in
@@ -2369,17 +2369,16 @@ NECKO_COOKIES=1
NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
BUILD_CTYPES=1
MOZ_USE_NATIVE_POPUP_WINDOWS=
MOZ_EXCLUDE_HYPHENATION_DICTIONARIES=
MOZ_INSTALL_TRACKING=
ACCESSIBILITY=1
MOZ_TIME_MANAGER=
MOZ_SIMPLEPUSH=
-MOZ_PAY=
MOZ_AUDIO_CHANNEL_MANAGER=
MOZ_CONTENT_SANDBOX=
MOZ_GMP_SANDBOX=
MOZ_SANDBOX=1
MOZ_BINARY_EXTENSIONS=
MOZ_DEVTOOLS=server
case "$target_os" in
@@ -4933,24 +4932,16 @@ dnl = Enable Support for SimplePush (Gon
dnl This will disable the Push API.
dnl ========================================================
if test -n "$MOZ_SIMPLEPUSH"; then
AC_DEFINE(MOZ_SIMPLEPUSH)
fi
AC_SUBST(MOZ_SIMPLEPUSH)
dnl ========================================================
-dnl = Enable Support for Payment API
-dnl ========================================================
-if test -n "$MOZ_PAY"; then
- AC_DEFINE(MOZ_PAY)
-fi
-AC_SUBST(MOZ_PAY)
-
-dnl ========================================================
dnl = Enable Support for AudioChannelManager API
dnl ========================================================
if test -n "$MOZ_AUDIO_CHANNEL_MANAGER"; then
AC_DEFINE(MOZ_AUDIO_CHANNEL_MANAGER)
fi
AC_SUBST(MOZ_AUDIO_CHANNEL_MANAGER)
dnl ========================================================
deleted file mode 100644
--- a/services/mobileid/MobileIdentityClient.jsm
+++ /dev/null
@@ -1,158 +0,0 @@
-/* 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/. */
-
-// REST client for
-// https://github.com/mozilla-services/msisdn-gateway/blob/master/API.md
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentityClient"];
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://services-common/hawkclient.js");
-Cu.import("resource://services-common/hawkrequest.js");
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://services-crypto/utils.js");
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-this.MobileIdentityClient = function(aServerUrl) {
- let serverUrl = aServerUrl || SERVER_URL;
- let forceHttps = true;
- try {
- forceHttps = Services.prefs.getBoolPref(PREF_FORCE_HTTPS);
- } catch(e) {
- log.warn("Getting force HTTPS pref failed. If this was not intentional " +
- "check that " + PREF_FORCE_HTTPS + " is defined");
- }
-
- log.debug("Force HTTPS " + forceHttps);
-
- if (forceHttps && !/^https/.exec(serverUrl.toLowerCase())) {
- throw new Error(ERROR_INTERNAL_HTTP_NOT_ALLOWED);
- }
-
- this.hawk = new HawkClient(serverUrl);
- this.hawk.observerPrefix = "MobileId:hawk";
-};
-
-this.MobileIdentityClient.prototype = {
-
- discover: function(aMsisdn, aMcc, aMnc, aRoaming) {
- return this._request(DISCOVER, "POST", null, {
- msisdn: aMsisdn || undefined,
- mcc: aMcc,
- mnc: aMnc,
- roaming: aRoaming
- });
- },
-
- register: function() {
- return this._request(REGISTER, "POST", null, {});
- },
-
- smsMtVerify: function(aSessionToken, aMsisdn, aMcc, aMnc,
- aWantShortCode = false) {
- let credentials = this._deriveHawkCredentials(aSessionToken);
- return this._request(SMS_MT_VERIFY, "POST", credentials, {
- msisdn: aMsisdn,
- mcc: aMcc,
- mnc: aMnc,
- shortVerificationCode: aWantShortCode
- });
- },
-
- verifyCode: function(aSessionToken, aVerificationCode) {
- log.debug("verificationCode " + aVerificationCode);
- let credentials = this._deriveHawkCredentials(aSessionToken);
- return this._request(SMS_VERIFY_CODE, "POST", credentials, {
- code: aVerificationCode
- });
- },
-
- sign: function(aSessionToken, aDuration, aPublicKey) {
- let credentials = this._deriveHawkCredentials(aSessionToken);
- return this._request(SIGN, "POST", credentials, {
- duration: aDuration,
- publicKey: aPublicKey
- });
- },
-
- unregister: function(aSessionToken) {
- let credentials = this._deriveHawkCredentials(aSessionToken);
- return this._request(UNREGISTER, "POST", credentials, {});
- },
-
- /**
- * The MobileID server expects requests to certain endpoints to be
- * authorized using Hawk.
- *
- * Hawk credentials are derived using shared secrets.
- *
- * @param tokenHex
- * The current session token encoded in hex
- * @param context
- * A context for the credentials
- * @param size
- * The size in bytes of the expected derived buffer
- * @return credentials
- * Returns an object:
- * {
- * algorithm: sha256
- * id: the Hawk id (from the first 32 bytes derived)
- * key: the Hawk key (from bytes 32 to 64)
- * }
- */
- _deriveHawkCredentials: function(aSessionToken) {
- return deriveHawkCredentials(aSessionToken, CREDENTIALS_DERIVATION_INFO,
- CREDENTIALS_DERIVATION_SIZE, true /*hexKey*/);
- },
-
- /**
- * A general method for sending raw API calls to the mobile id verification
- * server.
- * All request bodies and responses are JSON.
- *
- * @param path
- * API endpoint path
- * @param method
- * The HTTP request method
- * @param credentials
- * Hawk credentials
- * @param jsonPayload
- * A JSON payload
- * @return Promise
- * Returns a promise that resolves to the JSON response of the API
- * call, or is rejected with an error.
- */
- _request: function(path, method, credentials, jsonPayload) {
- let deferred = Promise.defer();
-
- this.hawk.request(path, method, credentials, jsonPayload).then(
- (response) => {
- log.debug("MobileIdentityClient -> response.body " + response.body);
- try {
- let responseObj;
- // We parse the response body unless we are handling a 204 response,
- // which MUST NOT include a message body.
- if (response.status != 204) {
- responseObj = JSON.parse(response.body);
- }
- deferred.resolve(responseObj);
- } catch (err) {
- deferred.reject({error: err});
- }
- },
- (error) => {
- log.error("MobileIdentityClient -> Error ${}", error);
- deferred.reject(SERVER_ERRNO_TO_ERROR[error.errno] || ERROR_UNKNOWN);
- }
- );
-
- return deferred.promise;
- },
-
-};
deleted file mode 100644
--- a/services/mobileid/MobileIdentityCommon.jsm
+++ /dev/null
@@ -1,144 +0,0 @@
-/* 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/. */
-
-const { interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Log.jsm");
-
-// loglevel should be one of "Fatal", "Error", "Warn", "Info", "Config",
-// "Debug", "Trace" or "All". If none is specified, "Error" will be used by
-// default.
-const PREF_LOG_LEVEL = "services.mobileid.loglevel";
-
-XPCOMUtils.defineLazyGetter(this, "log", function() {
- let log = Log.repository.getLogger("MobileId");
- log.addAppender(new Log.DumpAppender());
- log.level = Log.Level.Error;
- try {
- let level =
- Services.prefs.getPrefType(PREF_LOG_LEVEL) == Ci.nsIPrefBranch.PREF_STRING
- && Services.prefs.getCharPref(PREF_LOG_LEVEL);
- log.level = Log.Level[level] || Log.Level.Error;
- } catch (e) {
- log.error(e);
- }
-
- return log;
-});
-
-this.PREF_FORCE_HTTPS = "services.mobileid.forcehttps";
-
-// Permission.
-this.MOBILEID_PERM = "mobileid";
-
-// IPC messages.
-this.GET_ASSERTION_IPC_MSG = "MobileId:GetAssertion";
-
-// Verification methods.
-this.SMS_MT = "sms/mt";
-this.SMS_MO_MT = "sms/momt";
-
-// Server endpoints.
-this.DISCOVER = "/discover";
-this.REGISTER = "/register";
-this.SMS_MT_VERIFY = "/" + this.SMS_MT + "/verify";
-this.SMS_MO_MT_VERIFY = "/" + this.SMS_MO_MT + "/verify";
-this.SMS_VERIFY_CODE = "/sms/verify_code";
-this.SIGN = "/certificate/sign";
-this.UNREGISTER = "/unregister";
-
-// Server consts.
-this.SERVER_URL = Services.prefs.getCharPref("services.mobileid.server.uri");
-this.CREDENTIALS_DERIVATION_INFO = "sessionToken";
-this.CREDENTIALS_DERIVATION_SIZE = 2 * 32;
-
-this.SILENT_SMS_RECEIVED_TOPIC = "silent-sms-received";
-
-this.ASSERTION_LIFETIME = 1000 * 60 * 5; // 5 minutes.
-this.CERTIFICATE_LIFETIME = 1000 * 3600 * 6; // 6 hours.
-this.KEY_LIFETIME = 1000 * 3600 * 12; // 12 hours.
-
-this.VERIFICATIONCODE_TIMEOUT = 60000;
-this.VERIFICATIONCODE_RETRIES = 3;
-
-// Internal Errors.
-this.ERROR_INTERNAL_CANNOT_CREATE_VERIFICATION_FLOW = "INTERNAL_CANNOT_CREATE_VERIFICATION_FLOW";
-this.ERROR_INTERNAL_CANNOT_GENERATE_ASSERTION = "INTERNAL_CANNOT_GENERATE_ASSERTION";
-this.ERROR_INTERNAL_CANNOT_VERIFY_SELECTION = "INTERNAL_CANNOT_VERIFY_SELECTION";
-this.ERROR_INTERNAL_DB_ERROR = "INTERNAL_DB_ERROR";
-this.ERROR_INTERNAL_HTTP_NOT_ALLOWED = "INTERNAL_HTTP_NOT_ALLOWED";
-this.ERROR_INTERNAL_INVALID_CERTIFICATE = "INTERNAL_INVALID_CERTIFICATE";
-this.ERROR_INTERNAL_INVALID_PROMPT_RESULT = "INTERNAL_INVALID_PROMPT_RESULT";
-this.ERROR_INTERNAL_INVALID_USER_SELECTION = "INTERNAL_INVALID_USER_SELECTION";
-this.ERROR_INTERNAL_INVALID_VERIFICATION_FLOW = "INTERNAL_INVALID_VERIFICATION_FLOW";
-this.ERROR_INTERNAL_INVALID_VERIFICATION_RESULT = "INTERNAL_INVALID_VERIFICATION_RESULT";
-this.ERROR_INTERNAL_UNEXPECTED = "INTERNAL_UNEXPECTED";
-
-// Errors.
-this.ERROR_ENDPOINT_NOT_SUPPORTED = "ENDPOINT_NOT_SUPPORTED";
-this.ERROR_INVALID_ASSERTION = "INVALID_ASSERTION";
-this.ERROR_INVALID_AUTH_TOKEN = "INVALID_AUTH_TOKEN";
-this.ERROR_INVALID_BODY_JSON = "INVALID_BODY_JSON";
-this.ERROR_INVALID_BODY_MISSING_PARAMS = "INVALID_BODY_MISSING_PARAMS";
-this.ERROR_INVALID_BODY_PARAMS = "INVALID_BODY_PARAMS";
-this.ERROR_INVALID_PHONE_NUMBER = "INVALID_PHONE_NUMBER";
-this.ERROR_INVALID_PROMPT_RESULT = "INVALID_PROMPT_RESULT";
-this.ERROR_INVALID_REQUEST_SIGNATURE = "INVALID_REQUEST_SIGNATURE";
-this.ERROR_INVALID_VERIFICATION_CODE = "INVALID_VERIFICATION_CODE";
-this.ERROR_MISSING_CONTENT_LENGTH_HEADER = "MISSING_CONTENT_LENGTH_HEADER";
-this.ERROR_NO_RETRIES_LEFT = "NO_RETRIES_LEFT";
-this.ERROR_OFFLINE = "OFFLINE";
-this.ERROR_PERMISSION_DENIED = "PERMISSION_DENIED";
-this.ERROR_REQUEST_BODY_TOO_LARGE = "REQUEST_BODY_TOO_LARGE";
-this.ERROR_SERVICE_TEMPORARILY_UNAVAILABLE = "SERVICE_TEMPORARILY_UNAVAILABLE";
-this.ERROR_TOO_MANY_REQUESTS_MSISDN = "TOO_MANY_REQUESTS_MSISDN";
-this.ERROR_TOO_MANY_REQUESTS_UNSPECIFIED = "TOO_MANY_REQUESTS_UNSPECIFIED";
-this.ERROR_TOO_MANY_REQUESTS_VERIFICAITON_CODE = "TOO_MANY_REQUESTS_VERIFICATION_CODE";
-this.ERROR_TOO_MANY_REQUESTS_VERIFICATION_METHOD = "TOO_MANY_REQUESTS_VERIFICATION_METHOD";
-this.ERROR_UNKNOWN = "UNKNOWN";
-this.ERROR_UNVERIFIED_ACCOUNT = "UNVERIFIED_ACCOUNT";
-this.ERROR_VERIFICATION_CODE_TIMEOUT = "VERIFICATION_CODE_TIMEOUT";
-
-// Server errno.
-// From https://github.com/mozilla-services/msisdn-gateway/blob/master/API.md#response-format
-this.ERRNO_UNVERIFIED_ACCOUNT = 104;
-this.ERRNO_INVALID_VERIFICATION_CODE = 105;
-this.ERRNO_INVALID_BODY_JSON = 106;
-this.ERRNO_INVALID_BODY_INVALID_PARAMS = 107;
-this.ERRNO_INVALID_BODY_MISSING_PARAMS = 108;
-this.ERRNO_INVALID_REQUEST_SIGNATURE = 109;
-this.ERRNO_INVALID_AUTH_TOKEN = 110;
-this.ERRNO_ENDPOINT_NOT_SUPPORTED = 111;
-this.ERRNO_MISSING_CONTENT_LENGTH_HEADER = 112;
-this.ERRNO_REQUEST_BODY_TOO_LARGE = 113;
-this.ERRNO_TOO_MANY_REQUESTS_VERIFICATION_CODE = 114;
-this.ERRNO_TOO_MANY_REQUESTS_MSISDN = 115;
-this.ERRNO_TOO_MANY_REQUESTS_VERIFICATION_METHOD = 116;
-this.ERRNO_TOO_MANY_REQUESTS_UNSPECIFIED = 117;
-this.ERRNO_SERVICE_TEMPORARILY_UNAVAILABLE = 201;
-this.ERRNO_UNKNOWN_ERROR = 999;
-
-// Error matching.
-this.SERVER_ERRNO_TO_ERROR = {};
-SERVER_ERRNO_TO_ERROR[ERRNO_UNVERIFIED_ACCOUNT] = ERROR_UNVERIFIED_ACCOUNT;
-SERVER_ERRNO_TO_ERROR[ERRNO_INVALID_VERIFICATION_CODE] = ERROR_INVALID_VERIFICATION_CODE;
-SERVER_ERRNO_TO_ERROR[ERRNO_INVALID_BODY_JSON] = ERROR_INVALID_BODY_JSON;
-SERVER_ERRNO_TO_ERROR[ERRNO_INVALID_BODY_INVALID_PARAMS] = ERROR_INVALID_BODY_PARAMS;
-SERVER_ERRNO_TO_ERROR[ERRNO_INVALID_BODY_MISSING_PARAMS] = ERROR_INVALID_BODY_MISSING_PARAMS;
-SERVER_ERRNO_TO_ERROR[ERRNO_INVALID_REQUEST_SIGNATURE] = ERROR_INVALID_REQUEST_SIGNATURE;
-SERVER_ERRNO_TO_ERROR[ERRNO_INVALID_AUTH_TOKEN] = ERROR_INVALID_AUTH_TOKEN;
-SERVER_ERRNO_TO_ERROR[ERRNO_ENDPOINT_NOT_SUPPORTED] = ERROR_ENDPOINT_NOT_SUPPORTED;
-SERVER_ERRNO_TO_ERROR[ERRNO_MISSING_CONTENT_LENGTH_HEADER] = ERROR_MISSING_CONTENT_LENGTH_HEADER;
-SERVER_ERRNO_TO_ERROR[ERRNO_REQUEST_BODY_TOO_LARGE] = ERROR_REQUEST_BODY_TOO_LARGE;
-SERVER_ERRNO_TO_ERROR[ERRNO_TOO_MANY_REQUESTS_VERIFICATION_CODE] = ERROR_TOO_MANY_REQUESTS_VERIFICAITON_CODE;
-SERVER_ERRNO_TO_ERROR[ERRNO_TOO_MANY_REQUESTS_MSISDN] = ERROR_TOO_MANY_REQUESTS_MSISDN;;
-SERVER_ERRNO_TO_ERROR[ERRNO_TOO_MANY_REQUESTS_VERIFICATION_METHOD] = ERROR_TOO_MANY_REQUESTS_VERIFICATION_METHOD;;
-SERVER_ERRNO_TO_ERROR[ERRNO_TOO_MANY_REQUESTS_UNSPECIFIED] = ERROR_TOO_MANY_REQUESTS_UNSPECIFIED;;
-SERVER_ERRNO_TO_ERROR[ERRNO_SERVICE_TEMPORARILY_UNAVAILABLE] = ERROR_SERVICE_TEMPORARILY_UNAVAILABLE;
-SERVER_ERRNO_TO_ERROR[ERRNO_UNKNOWN_ERROR] = ERROR_UNKNOWN;
-
-// Allow this file to be imported via Components.utils.import().
-this.EXPORTED_SYMBOLS = Object.keys(this);
deleted file mode 100644
--- a/services/mobileid/MobileIdentityCredentialsStore.jsm
+++ /dev/null
@@ -1,257 +0,0 @@
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentityCredentialsStore"];
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-const CREDENTIALS_DB_NAME = "mobile-id-credentials";
-const CREDENTIALS_DB_VERSION = 1;
-const CREDENTIALS_STORE_NAME = "credentials-store";
-
-this.MobileIdentityCredentialsStore = function() {
-};
-
-this.MobileIdentityCredentialsStore.prototype = {
-
- __proto__: IndexedDBHelper.prototype,
-
- init: function() {
- log.debug("MobileIdentityCredentialsStore init");
- this.initDBHelper(CREDENTIALS_DB_NAME,
- CREDENTIALS_DB_VERSION,
- [CREDENTIALS_STORE_NAME]);
- },
-
- upgradeSchema: function(aTransaction, aDb, aOldVersion, aNewVersion) {
- log.debug("upgradeSchema");
- /**
- * We will be storing objects like:
- * {
- * msisdn: <string> (key),
- * iccId: <string> (index, optional),
- * deviceIccIds: <array>,
- * origin: <array> (index),
- * msisdnSessionToken: <string>,
- * }
- */
- let objectStore = aDb.createObjectStore(CREDENTIALS_STORE_NAME, {
- keyPath: "msisdn"
- });
-
- objectStore.createIndex("iccId", "iccId", { unique: true });
- objectStore.createIndex("origin", "origin", { unique: true, multiEntry: true });
- },
-
- add: function(aIccId, aMsisdn, aOrigin, aSessionToken, aDeviceIccIds) {
- log.debug("put " + aIccId + ", " + aMsisdn + ", " + aOrigin + ", " +
- aSessionToken + ", " + aDeviceIccIds);
- if (!aOrigin || !aSessionToken) {
- return Promise.reject(ERROR_INTERNAL_DB_ERROR);
- }
-
- let deferred = Promise.defer();
-
- // We first try get an existing record for the given MSISDN.
- this.newTxn(
- "readwrite",
- CREDENTIALS_STORE_NAME,
- (aTxn, aStore) => {
- let range = IDBKeyRange.only(aMsisdn);
- let cursorReq = aStore.openCursor(range);
- cursorReq.onsuccess = function(aEvent) {
- let cursor = aEvent.target.result;
- let record;
- // If we already have a record of this MSISDN, we add the origin to
- // the list of allowed origins.
- if (cursor && cursor.value) {
- record = cursor.value;
- if (record.origin.indexOf(aOrigin) == -1) {
- record.origin.push(aOrigin);
- }
- cursor.update(record);
- } else {
- // Otherwise, we store a new record.
- record = {
- iccId: aIccId,
- msisdn: aMsisdn,
- origin: [aOrigin],
- sessionToken: aSessionToken,
- deviceIccIds: aDeviceIccIds
- };
- aStore.add(record);
- }
- deferred.resolve();
- };
- cursorReq.onerror = function(aEvent) {
- log.error(aEvent.target.error);
- deferred.reject(ERROR_INTERNAL_DB_ERROR);
- };
- }, null, deferred.reject);
-
- return deferred.promise;
- },
-
- getByMsisdn: function(aMsisdn) {
- log.debug("getByMsisdn " + aMsisdn);
- if (!aMsisdn) {
- return Promise.resolve(null);
- }
-
- let deferred = Promise.defer();
- this.newTxn(
- "readonly",
- CREDENTIALS_STORE_NAME,
- (aTxn, aStore) => {
- aStore.get(aMsisdn).onsuccess = function(aEvent) {
- aTxn.result = aEvent.target.result;
- };
- },
- function(result) {
- deferred.resolve(result);
- },
- deferred.reject
- );
- return deferred.promise;
- },
-
- getByIndex: function(aIndex, aValue) {
- log.debug("getByIndex " + aIndex + ", " + aValue);
- if (!aValue || !aIndex) {
- return Promise.resolve(null);
- }
-
- let deferred = Promise.defer();
- this.newTxn(
- "readonly",
- CREDENTIALS_STORE_NAME,
- (aTxn, aStore) => {
- let index = aStore.index(aIndex);
- index.get(aValue).onsuccess = function(aEvent) {
- aTxn.result = aEvent.target.result;
- };
- },
- function(result) {
- deferred.resolve(result);
- },
- deferred.reject
- );
- return deferred.promise;
- },
-
- getByOrigin: function(aOrigin) {
- return this.getByIndex("origin", aOrigin);
- },
-
- getByIccId: function(aIccId) {
- return this.getByIndex("iccId", aIccId);
- },
-
- delete: function(aMsisdn) {
- log.debug("delete " + aMsisdn);
- if (!aMsisdn) {
- return Promise.resolve();
- }
-
- let deferred = Promise.defer();
- this.newTxn(
- "readwrite",
- CREDENTIALS_STORE_NAME,
- (aTxn, aStore) => {
- aStore.delete(aMsisdn);
- },
- deferred.resolve,
- deferred.reject
- );
- return deferred.promise;
- },
-
- removeValue: function(aMsisdn, aKey, aValue) {
- log.debug("Removing " + aKey + " with value " + aValue);
- if (!aMsisdn || !aKey) {
- return Promise.reject();
- }
-
- let deferred = Promise.defer();
- this.newTxn(
- "readwrite",
- CREDENTIALS_STORE_NAME,
- (aTxn, aStore) => {
- let range = IDBKeyRange.only(aMsisdn);
- let cursorReq = aStore.openCursor(range);
- cursorReq.onsuccess = function(aEvent) {
- let cursor = aEvent.target.result;
- let record;
- if (!cursor || !cursor.value) {
- return Promise.resolve();
- }
- record = cursor.value;
- if (!record[aKey]) {
- return Promise.reject();
- }
- if (aValue) {
- let index = record[aKey].indexOf(aValue);
- if (index != -1) {
- record[aKey].splice(index, 1);
- }
- } else {
- record[aKey] = undefined;
- }
- log.debug("Removal done ${}", record);
- cursor.update(record);
- deferred.resolve();
- };
- cursorReq.onerror = function(aEvent) {
- log.error(aEvent.target.error);
- deferred.reject(ERROR_INTERNAL_DB_ERROR);
- };
- }, null, deferred.reject);
-
- return deferred.promise;
- },
-
- removeOrigin: function(aMsisdn, aOrigin) {
- log.debug("removeOrigin " + aMsisdn + " " + aOrigin);
- return this.removeValue(aMsisdn, "origin", aOrigin);
- },
-
- setDeviceIccIds: function(aMsisdn, aDeviceIccIds) {
- log.debug("Setting icc ids " + aDeviceIccIds + " for " + aMsisdn);
- if (!aMsisdn) {
- return Promise.reject();
- }
-
- let deferred = Promise.defer();
- this.newTxn(
- "readwrite",
- CREDENTIALS_STORE_NAME,
- (aTxn, aStore) => {
- let range = IDBKeyRange.only(aMsisdn);
- let cursorReq = aStore.openCursor(range);
- cursorReq.onsuccess = function(aEvent) {
- let cursor = aEvent.target.result;
- let record;
- if (!cursor || !cursor.value) {
- return Promise.resolve();
- }
- record = cursor.value;
- record.deviceIccIds = aDeviceIccIds;
- cursor.update(record);
- deferred.resolve();
- };
- cursorReq.onerror = function(aEvent) {
- log.error(aEvent.target.error);
- deferred.reject(ERROR_INTERNAL_DB_ERROR);
- };
- }, null, deferred.reject);
-
- return deferred.promise;
- }
-};
deleted file mode 100644
--- a/services/mobileid/MobileIdentityManager.jsm
+++ /dev/null
@@ -1,1085 +0,0 @@
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentityManager"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/AppConstants.jsm");
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/MobileIdentityUIGlueCommon.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "MobileIdentityCredentialsStore",
- "resource://gre/modules/MobileIdentityCredentialsStore.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "MobileIdentityClient",
- "resource://gre/modules/MobileIdentityClient.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "MobileIdentitySmsMtVerificationFlow",
- "resource://gre/modules/MobileIdentitySmsMtVerificationFlow.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "MobileIdentitySmsMoMtVerificationFlow",
- "resource://gre/modules/MobileIdentitySmsMoMtVerificationFlow.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PhoneNumberUtils",
- "resource://gre/modules/PhoneNumberUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
- "resource://gre/modules/identity/jwcrypto.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
- "@mozilla.org/uuid-generator;1",
- "nsIUUIDGenerator");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
- "@mozilla.org/parentprocessmessagemanager;1",
- "nsIMessageListenerManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
- "@mozilla.org/permissionmanager;1",
- "nsIPermissionManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "securityManager",
- "@mozilla.org/scriptsecuritymanager;1",
- "nsIScriptSecurityManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "appsService",
- "@mozilla.org/AppsService;1",
- "nsIAppsService");
-
-if (AppConstants.MOZ_B2G_RIL) {
- XPCOMUtils.defineLazyServiceGetter(this, "Ril",
- "@mozilla.org/ril;1",
- "nsIRadioInterfaceLayer");
-
- XPCOMUtils.defineLazyServiceGetter(this, "IccService",
- "@mozilla.org/icc/iccservice;1",
- "nsIIccService");
-
- XPCOMUtils.defineLazyServiceGetter(this, "MobileConnectionService",
- "@mozilla.org/mobileconnection/mobileconnectionservice;1",
- "nsIMobileConnectionService");
-}
-
-
-this.MobileIdentityManager = {
-
- init: function() {
- log.debug("MobileIdentityManager init");
- Services.obs.addObserver(this, "xpcom-shutdown", false);
- ppmm.addMessageListener(GET_ASSERTION_IPC_MSG, this);
- this.messageManagers = {};
- this.keyPairs = {};
- this.certificates = {};
- },
-
- receiveMessage: function(aMessage) {
- log.debug("Received " + aMessage.name);
-
- if (aMessage.name !== GET_ASSERTION_IPC_MSG) {
- return;
- }
-
- let msg = aMessage.json;
-
- // We save the message target message manager so we can later dispatch
- // back messages without broadcasting to all child processes.
- let promiseId = msg.promiseId;
- this.messageManagers[promiseId] = aMessage.target;
-
- this.getMobileIdAssertion(aMessage.principal, promiseId, msg.options);
- },
-
- observe: function(subject, topic, data) {
- if (topic != "xpcom-shutdown") {
- return;
- }
-
- ppmm.removeMessageListener(GET_ASSERTION_IPC_MSG, this);
- Services.obs.removeObserver(this, "xpcom-shutdown");
- this.messageManagers = null;
- },
-
- /*********************************************************
- * Getters
- ********************************************************/
- get iccInfo() {
- if (this._iccInfo) {
- return this._iccInfo;
- }
- if (AppConstants.MOZ_B2G_RIL) {
- let self = this;
- let iccListener = {
- notifyStkCommand: function() {},
-
- notifyStkSessionEnd: function() {},
-
- notifyCardStateChanged: function() {},
-
- notifyIccInfoChanged: function() {
- // If we receive a notification about an ICC info change, we clear
- // the ICC related caches so they can be rebuilt with the new changes.
-
- log.debug("ICC info changed observed. Clearing caches");
-
- // We don't need to keep listening for changes until we rebuild the
- // cache again.
- for (let i = 0; i < self._iccInfo.length; i++) {
- let icc = self.iccService.getIccByServiceId(i);
- if (icc) {
- icc.unregisterListener(iccListener);
- }
- }
-
- self._iccInfo = null;
- self._iccIds = null;
- }
- };
-
- // _iccInfo is a local cache containing the information about the SIM cards
- // that is interesting for the Mobile ID flow.
- // The index of this array does not necesarily need to match the real
- // identifier of the SIM card ("clientId" or "serviceId" in RIL language).
- this._iccInfo = [];
-
- for (let i = 0; i < this.ril.numRadioInterfaces; i++) {
- let icc = this.iccService.getIccByServiceId(i);
- if (!icc) {
- log.warn("Tried to get the Icc instance for an invalid service ID " + i);
- continue;
- }
-
- let info = icc.iccInfo;
- if (!info || !info.iccid ||
- !info.mcc || !info.mcc.length ||
- !info.mnc || !info.mnc.length) {
- log.warn("Absent or invalid ICC info");
- continue;
- }
-
- // GSM SIMs may have MSISDN while CDMA SIMs may have MDN
- let phoneNumber = null;
- try {
- if (info.iccType === "sim" || info.iccType === "usim") {
- let gsmInfo = info.QueryInterface(Ci.nsIGsmIccInfo);
- phoneNumber = gsmInfo.msisdn;
- } else if (info.iccType === "ruim" || info.iccType === "csim") {
- let cdmaInfo = info.QueryInterface(Ci.nsICdmaIccInfo);
- phoneNumber = cdmaInfo.mdn;
- }
- } catch (e) {
- log.error("Failed to retrieve phoneNumber: " + e);
- }
-
- let connection = this.mobileConnectionService.getItemByServiceId(i);
- let voice = connection && connection.voice;
- let data = connection && connection.data;
- let operator = null;
- if (voice &&
- voice.network &&
- voice.network.shortName &&
- voice.network.shortName.length) {
- operator = voice.network.shortName;
- } else if (data &&
- data.network &&
- data.network.shortName &&
- data.network.shortName.length) {
- operator = data.network.shortName;
- }
-
- this._iccInfo.push({
- // Because it is possible that the _iccInfo array index doesn't match
- // the real client ID, we need to store this value for later usage.
- clientId: i,
- iccId: info.iccid,
- mcc: info.mcc,
- mnc: info.mnc,
- msisdn: phoneNumber,
- operator: operator,
- roaming: voice && voice.roaming
- });
-
- // We need to subscribe to ICC change notifications so we can refresh
- // the cache if any change is observed.
- icc.registerListener(iccListener);
- }
-
- return this._iccInfo;
- } else {
- return null;
- }
- },
-
- get iccIds() {
- if (AppConstants.MOZ_B2G_RIL) {
- if (this._iccIds) {
- return this._iccIds;
- }
-
- this._iccIds = [];
- if (!this.iccInfo) {
- return this._iccIds;
- }
-
- for (let i = 0; i < this.iccInfo.length; i++) {
- this._iccIds.push(this.iccInfo[i].iccId);
- }
-
- return this._iccIds;
- } else {
- return null;
- }
- },
-
- get credStore() {
- if (!this._credStore) {
- this._credStore = new MobileIdentityCredentialsStore();
- this._credStore.init();
- }
- return this._credStore;
- },
-
- get ui() {
- if (!this._ui) {
- this._ui = Cc["@mozilla.org/services/mobileid-ui-glue;1"]
- .createInstance(Ci.nsIMobileIdentityUIGlue);
- this._ui.oncancel = this.onUICancel.bind(this);
- this._ui.onresendcode = this.onUIResendCode.bind(this);
- }
- return this._ui;
- },
-
- get client() {
- if (!this._client) {
- this._client = new MobileIdentityClient();
- }
- return this._client;
- },
-
- get isMultiSim() {
- return this.iccInfo && this.iccInfo.length > 1;
- },
-
- getVerificationOptionsForIcc: function(aServiceId) {
- log.debug("getVerificationOptionsForIcc " + aServiceId);
- log.debug("iccInfo ${}", this.iccInfo[aServiceId]);
- // First of all we need to check if we already have existing credentials
- // for the given SIM information (ICC ID or MSISDN). If we have no valid
- // credentials, we have to check with the server which options do we have
- // to verify the associated phone number.
- return this.credStore.getByIccId(this.iccInfo[aServiceId].iccId)
- .then(
- (creds) => {
- if (creds) {
- return creds;
- }
- return this.credStore.getByMsisdn(this.iccInfo[aServiceId].msisdn);
- }
- )
- .then(
- (creds) => {
- if (creds) {
- this.iccInfo[aServiceId].credentials = creds;
- return;
- }
- // We have no credentials for this SIM, so we need to ask the server
- // which options do we have to verify the phone number.
- // But we need to be online...
- if (Services.io.offline) {
- return Promise.reject(ERROR_OFFLINE);
- }
- return this.client.discover(this.iccInfo[aServiceId].msisdn,
- this.iccInfo[aServiceId].mcc,
- this.iccInfo[aServiceId].mnc,
- this.iccInfo[aServiceId].roaming);
- }
- )
- .then(
- (result) => {
- // If we already have credentials for this ICC and no discover request
- // is done, we just bail out.
- if (!result || !result.verificationMethods) {
- return;
- }
- log.debug("Discover result ${}", result);
- this.iccInfo[aServiceId].verificationMethods = result.verificationMethods;
- this.iccInfo[aServiceId].verificationDetails = result.verificationDetails;
- this.iccInfo[aServiceId].canDoSilentVerification =
- (result.verificationMethods.indexOf(SMS_MO_MT) != -1);
- return;
- }
- );
- },
-
- getVerificationOptions: function() {
- log.debug("getVerificationOptions");
- // We try to get if we already have credentials for any of the inserted
- // SIM cards if any is available and we try to get the possible
- // verification mechanisms for these SIM cards.
- // All this information will be stored in iccInfo.
- if (!this.iccInfo || !this.iccInfo.length) {
- let deferred = Promise.defer();
- deferred.resolve(null);
- return deferred.promise;
- }
-
- let promises = [];
- for (let i = 0; i < this.iccInfo.length; i++) {
- promises.push(this.getVerificationOptionsForIcc(i));
- }
- return Promise.all(promises);
- },
-
- getKeyPair: function(aSessionToken) {
- if (this.keyPairs[aSessionToken] &&
- this.keyPairs[aSessionToken].validUntil > this.client.hawk.now()) {
- return Promise.resolve(this.keyPairs[aSessionToken].keyPair);
- }
-
- let validUntil = this.client.hawk.now() + KEY_LIFETIME;
- let deferred = Promise.defer();
- jwcrypto.generateKeyPair("DS160", (error, kp) => {
- if (error) {
- return deferred.reject(error);
- }
- this.keyPairs[aSessionToken] = {
- keyPair: kp,
- validUntil: validUntil
- };
- delete this.certificates[aSessionToken];
- deferred.resolve(kp);
- });
-
- return deferred.promise;
- },
-
- getCertificate: function(aSessionToken, aPublicKey) {
- log.debug("getCertificate");
- if (this.certificates[aSessionToken] &&
- this.certificates[aSessionToken].validUntil > this.client.hawk.now()) {
- return Promise.resolve(this.certificates[aSessionToken].cert);
- }
-
- if (Services.io.offline) {
- return Promise.reject(ERROR_OFFLINE);
- }
-
- let validUntil = this.client.hawk.now() + KEY_LIFETIME;
- let deferred = Promise.defer();
- this.client.sign(aSessionToken, CERTIFICATE_LIFETIME,
- aPublicKey)
- .then(
- (signedCert) => {
- log.debug("Got signed certificate");
- this.certificates[aSessionToken] = {
- cert: signedCert.cert,
- validUntil: validUntil
- };
- deferred.resolve(signedCert.cert);
- },
- deferred.reject
- );
- return deferred.promise;
- },
-
- /*********************************************************
- * Setters (for test only purposes)
- ********************************************************/
- set ui(aUi) {
- this._ui = aUi;
- },
-
- set credStore(aCredStore) {
- this._credStore = aCredStore;
- },
-
- set client(aClient) {
- this._client = aClient;
- },
-
- set iccInfo(aIccInfo) {
- this._iccInfo = aIccInfo;
- },
-
- /*********************************************************
- * UI callbacks
- ********************************************************/
-
- onUICancel: function() {
- log.debug("UI cancel");
- if (this.activeVerificationFlow) {
- this.rejectVerification();
- }
- },
-
- onUIResendCode: function() {
- log.debug("UI resend code");
- if (!this.activeVerificationFlow) {
- return;
- }
- this.doVerification();
- },
-
- /*********************************************************
- * Result helpers
- *********************************************************/
- success: function(aPromiseId, aResult) {
- let mm = this.messageManagers[aPromiseId];
- mm.sendAsyncMessage("MobileId:GetAssertion:Return:OK", {
- promiseId: aPromiseId,
- result: aResult
- });
- },
-
- error: function(aPromiseId, aError) {
- let mm = this.messageManagers[aPromiseId];
- mm.sendAsyncMessage("MobileId:GetAssertion:Return:KO", {
- promiseId: aPromiseId,
- error: aError
- });
- },
-
- /*********************************************************
- * Permissions helper
- ********************************************************/
-
- addPermission: function(aPrincipal) {
- permissionManager.addFromPrincipal(aPrincipal, MOBILEID_PERM,
- Ci.nsIPermissionManager.ALLOW_ACTION);
- },
-
- /*********************************************************
- * Phone number verification
- ********************************************************/
-
- rejectVerification: function(aReason) {
- if (!this.activeVerificationDeferred) {
- return;
- }
- this.activeVerificationDeferred.reject(aReason);
- this.activeVerificationDeferred = null;
- this.cleanupVerification(true /* unregister */);
- },
-
- resolveVerification: function(aResult) {
- if (!this.activeVerificationDeferred) {
- return;
- }
- this.activeVerificationDeferred.resolve(aResult);
- this.activeVerificationDeferred = null;
- this.cleanupVerification();
- },
-
- cleanupVerification: function(aUnregister = false) {
- if (!this.activeVerificationFlow) {
- return;
- }
- this.activeVerificationFlow.cleanup(aUnregister);
- this.activeVerificationFlow = null;
- },
-
- doVerification: function() {
- this.activeVerificationFlow.doVerification()
- .then(
- (verificationResult) => {
- log.debug("onVerificationResult ");
- if (!verificationResult || !verificationResult.sessionToken ||
- !verificationResult.msisdn) {
- return this.rejectVerification(
- ERROR_INTERNAL_INVALID_VERIFICATION_RESULT
- );
- }
- this.resolveVerification(verificationResult);
- }
- )
- .then(
- null,
- reason => {
- // Verification timeout.
- log.warn("doVerification " + reason);
- }
- );
- },
-
- _verificationFlow: function(aToVerify, aOrigin) {
- log.debug("toVerify ${}", aToVerify);
-
- // We create the corresponding verification flow and save its instance
- // in case that we need to cancel it or retrigger it because the user
- // requested its cancelation or a resend of the verification code.
- if (aToVerify.verificationMethod.indexOf(SMS_MT) != -1 &&
- aToVerify.msisdn &&
- aToVerify.verificationDetails &&
- aToVerify.verificationDetails.mtSender) {
- this.activeVerificationFlow = new MobileIdentitySmsMtVerificationFlow({
- origin: aOrigin,
- msisdn: aToVerify.msisdn,
- mcc: aToVerify.mcc,
- mnc: aToVerify.mnc,
- iccId: aToVerify.iccId,
- external: aToVerify.serviceId === undefined,
- mtSender: aToVerify.verificationDetails.mtSender
- },
- this.ui,
- this.client
- );
- } else if (AppConstants.MOZ_B2G_RIL &&
- aToVerify.verificationMethod.indexOf(SMS_MO_MT) != -1 &&
- aToVerify.serviceId &&
- aToVerify.verificationDetails &&
- aToVerify.verificationDetails.moVerifier &&
- aToVerify.verificationDetails.mtSender) {
- this.activeVerificationFlow = new MobileIdentitySmsMoMtVerificationFlow({
- origin: aOrigin,
- serviceId: aToVerify.serviceId,
- iccId: aToVerify.iccId,
- mtSender: aToVerify.verificationDetails.mtSender,
- moVerifier: aToVerify.verificationDetails.moVerifier
- },
- this.ui,
- this.client
- );
- } else {
- return Promise.reject(ERROR_INTERNAL_CANNOT_VERIFY_SELECTION);
- }
-
- if (!this.activeVerificationFlow) {
- return Promise.reject(ERROR_INTERNAL_CANNOT_CREATE_VERIFICATION_FLOW);
- }
-
- this.activeVerificationDeferred = Promise.defer();
- this.doVerification();
- return this.activeVerificationDeferred.promise;
- },
-
- verificationFlow: function(aUserSelection, aOrigin) {
- log.debug("verificationFlow ${}", aUserSelection);
-
- if (!aUserSelection) {
- return Promise.reject(ERROR_INTERNAL_INVALID_USER_SELECTION);
- }
-
- let serviceId = aUserSelection.serviceId || undefined;
- // We check if the user entered phone number corresponds with any of the
- // inserted SIMs known phone numbers.
- if (aUserSelection.msisdn && this.iccInfo) {
- for (let i = 0; i < this.iccInfo.length; i++) {
- if (aUserSelection.msisdn == this.iccInfo[i].msisdn) {
- serviceId = i;
- break;
- }
- }
- }
-
- let toVerify = {};
-
- if (serviceId !== undefined) {
- log.debug("iccInfo ${}", this.iccInfo[serviceId]);
- toVerify.serviceId = serviceId;
- toVerify.iccId = this.iccInfo[serviceId].iccId;
- toVerify.msisdn = this.iccInfo[serviceId].msisdn;
- toVerify.mcc = this.iccInfo[serviceId].mcc;
- toVerify.mnc = this.iccInfo[serviceId].mnc;
- toVerify.verificationMethod =
- this.iccInfo[serviceId].verificationMethods[0];
- toVerify.verificationDetails =
- this.iccInfo[serviceId].verificationDetails[toVerify.verificationMethod];
- return this._verificationFlow(toVerify, aOrigin);
- } else {
- toVerify.msisdn = aUserSelection.msisdn;
- toVerify.mcc = aUserSelection.mcc;
- return this.client.discover(aUserSelection.msisdn,
- aUserSelection.mcc)
- .then(
- (discoverResult) => {
- if (!discoverResult || !discoverResult.verificationMethods) {
- return Promise.reject(ERROR_INTERNAL_UNEXPECTED);
- }
- log.debug("discoverResult ${}", discoverResult);
- toVerify.verificationMethod = discoverResult.verificationMethods[0];
- toVerify.verificationDetails =
- discoverResult.verificationDetails[toVerify.verificationMethod];
- return this._verificationFlow(toVerify, aOrigin);
- }
- );
- }
- },
-
-
- /*********************************************************
- * UI prompt functions.
- ********************************************************/
-
- // The phone number prompt will be used to confirm that the user wants to
- // verify and share a known phone number and to allow her to introduce an
- // external phone or to select between phone numbers or SIM cards (if the
- // phones are not known) in a multi-SIM scenario.
- // This prompt will be considered as the permission prompt and its choice
- // will be remembered per origin by default.
- prompt: function prompt(aPrincipal, aManifestURL, aPhoneInfo) {
- log.debug("prompt ${principal} ${manifest} ${phoneInfo}", {
- principal: aPrincipal,
- manifest: aManifestURL,
- phoneInfo: aPhoneInfo
- });
-
- let phoneInfoArray = [];
-
- if (aPhoneInfo) {
- phoneInfoArray.push(aPhoneInfo);
- }
-
- if (this.iccInfo) {
- for (let i = 0; i < this.iccInfo.length; i++) {
- // If we don't know the msisdn, there is no previous credentials and
- // a silent verification is not possible or if the msisdn is the one
- // that is already chosen, we don't list this SIM as an option.
- if ((!this.iccInfo[i].msisdn && !this.iccInfo[i].credentials &&
- !this.iccInfo[i].canDoSilentVerification) ||
- ((aPhoneInfo) &&
- (this.iccInfo[i].msisdn == aPhoneInfo.msisdn ||
- this.iccInfo[i].iccId == aPhoneInfo.iccId))) {
- continue;
- }
-
- let phoneInfo = new MobileIdentityUIGluePhoneInfo(
- this.iccInfo[i].msisdn,
- this.iccInfo[i].operator,
- i, // service ID
- this.iccInfo[i].iccId, // iccId
- false // primary
- );
- phoneInfoArray.push(phoneInfo);
- }
- }
-
- return this.ui.startFlow(aManifestURL, phoneInfoArray)
- .then(
- (result) => {
- log.debug("startFlow result ${} ", result);
- if (!result ||
- (!result.phoneNumber && (result.serviceId === undefined))) {
- return Promise.reject(ERROR_INTERNAL_INVALID_PROMPT_RESULT);
- }
-
- let msisdn;
- let mcc;
-
- // If the user selected one of the existing SIM cards we have to check
- // that we either have the MSISDN for that SIM, we have already existing
- // credentials or we can do a silent verification that does not require
- // us to have the MSISDN in advance.
- // result.serviceId can be "0".
- if (result.serviceId !== undefined &&
- result.serviceId !== null) {
- let icc = this.iccInfo[result.serviceId];
- log.debug("icc ${}", icc);
- if (!icc || !icc.msisdn && !icc.canDoSilentVerification &&
- !icc.credentials) {
- return Promise.reject(ERROR_INTERNAL_CANNOT_VERIFY_SELECTION);
- }
- msisdn = icc.msisdn;
- mcc = icc.mcc;
- } else {
- msisdn = result.prefix ? result.prefix + result.phoneNumber
- : result.phoneNumber;
- mcc = result.mcc;
- }
-
- // We need to check that the selected phone number is valid and
- // if it is not notify the UI about the error and allow the user to
- // retry.
- if (msisdn && mcc &&
- !PhoneNumberUtils.parseWithMCC(msisdn, mcc)) {
- this.ui.error(ERROR_INVALID_PHONE_NUMBER);
- return this.prompt(aPrincipal, aManifestURL, aPhoneInfo);
- }
-
- log.debug("Selected msisdn (if any): " + msisdn + " - " + mcc);
-
- // The user gave permission for the requester origin, so we store it.
- this.addPermission(aPrincipal);
-
- return {
- msisdn: msisdn,
- mcc: mcc,
- serviceId: result.serviceId
- };
- }
- );
- },
-
- promptAndVerify: function(aPrincipal, aManifestURL, aCreds) {
- log.debug("promptAndVerify " + aPrincipal + ", " + aManifestURL +
- ", ${}", aCreds);
- let userSelection;
-
- if (Services.io.offline) {
- return Promise.reject(ERROR_OFFLINE);
- }
-
- // Before prompting the user we need to check with the server the
- // phone number verification methods that are possible with the
- // SIMs inserted in the device.
- return this.getVerificationOptions()
- .then(
- () => {
- // If we have an exisiting credentials, we add its associated
- // phone number information to the list of choices to present
- // to the user within the selection prompt.
- let phoneInfo;
- if (aCreds) {
- phoneInfo = new MobileIdentityUIGluePhoneInfo(
- aCreds.msisdn,
- null, // operator
- undefined, // service ID
- aCreds.iccId, // iccId
- true // primary
- );
- }
- return this.prompt(aPrincipal, aManifestURL, phoneInfo);
- }
- )
- .then(
- (promptResult) => {
- log.debug("promptResult ${}", promptResult);
- // If we had credentials and the user didn't change her
- // selection we return them. Otherwise, we need to verify
- // the new number.
- if (promptResult.msisdn && aCreds &&
- promptResult.msisdn == aCreds.msisdn) {
- return aCreds;
- }
-
- // We might already have credentials for the user selected icc. In
- // that case, we update the credentials store with the new origin and
- // return the credentials.
- if (promptResult.serviceId) {
- let creds = this.iccInfo[promptResult.serviceId].credentials;
- if (creds) {
- this.credStore.add(creds.iccId, creds.msisdn, aPrincipal.originNoSuffix,
- creds.sessionToken, this.iccIds);
- return creds;
- }
- }
-
- // Or we might already have credentials for the selected phone
- // number and so we do the same: update the credentials store with the
- // new origin and return the credentials.
- return this.credStore.getByMsisdn(promptResult.msisdn)
- .then(
- (creds) => {
- if (creds) {
- this.credStore.add(creds.iccId, creds.msisdn, aPrincipal.originNoSuffix,
- creds.sessionToken, this.iccIds);
- return creds;
- }
- // Otherwise, we need to verify the new number selected by the
- // user.
- return this.verificationFlow(promptResult, aPrincipal.originNoSuffix);
- }
- );
- }
- );
- },
-
- /*********************************************************
- * Credentials check
- *********************************************************/
-
- checkNewCredentials: function(aOldCreds, aNewCreds, aOrigin) {
- // If there were previous credentials and the user changed her
- // choice, we need to remove the origin from the old credentials.
- if (aNewCreds.msisdn != aOldCreds.msisdn) {
- return this.credStore.removeOrigin(aOldCreds.msisdn,
- aOrigin)
- .then(
- () => {
- return aNewCreds;
- }
- );
- } else {
- // Otherwise, we update the status of the SIM cards in the device
- // so we know that the user decided not to take the chance to change
- // her selection. We won't bother her again until a new SIM card
- // change is detected.
- return this.credStore.setDeviceIccIds(aOldCreds.msisdn, this.iccIds)
- .then(
- () => {
- return aOldCreds;
- }
- );
- }
- },
-
- /*********************************************************
- * Assertion generation
- ********************************************************/
-
- generateAssertion: function(aCredentials, aOrigin) {
- if (!aCredentials.sessionToken) {
- return Promise.reject(ERROR_INTERNAL_INVALID_TOKEN);
- }
-
- let deferred = Promise.defer();
-
- this.getKeyPair(aCredentials.sessionToken)
- .then(
- (keyPair) => {
- log.debug("keyPair " + keyPair.serializedPublicKey);
- let options = {
- duration: ASSERTION_LIFETIME,
- now: this.client.hawk.now(),
- localtimeOffsetMsec: this.client.hawk.localtimeOffsetMsec
- };
-
- this.getCertificate(aCredentials.sessionToken,
- keyPair.serializedPublicKey)
- .then(
- (signedCert) => {
- log.debug("generateAssertion " + signedCert);
- jwcrypto.generateAssertion(signedCert, keyPair,
- aOrigin, options,
- (error, assertion) => {
- if (error) {
- log.error("Error generating assertion " + err);
- deferred.reject(error);
- return;
- }
- this.credStore.add(aCredentials.iccId,
- aCredentials.msisdn,
- aOrigin,
- aCredentials.sessionToken,
- this.iccIds)
- .then(
- () => {
- deferred.resolve(assertion);
- }
- );
- });
- }, deferred.reject
- );
- }
- );
-
- return deferred.promise;
- },
-
- getMobileIdAssertion: function(aPrincipal, aPromiseId, aOptions) {
- log.debug("getMobileIdAssertion ${}", aPrincipal);
-
- let principal = aPrincipal;
- let manifestURL = appsService.getManifestURLByLocalId(aPrincipal.appId);
-
- let permission = permissionManager.testPermissionFromPrincipal(
- principal,
- MOBILEID_PERM
- );
-
- if (permission == Ci.nsIPermissionManager.DENY_ACTION ||
- permission == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
- this.error(aPromiseId, ERROR_PERMISSION_DENIED);
- return;
- }
-
- let _creds;
-
- // First of all we look if we already have credentials for this origin.
- // If we don't have credentials it means that it is the first time that
- // the caller requested an assertion.
- this.credStore.getByOrigin(aPrincipal.originNoSuffix)
- .then(
- (creds) => {
- log.debug("creds ${creds} - ${origin}", { creds: creds,
- origin: aPrincipal.originNoSuffix });
- if (!creds || !creds.sessionToken) {
- log.debug("No credentials");
- return;
- }
-
- _creds = creds;
-
- // Even if we already have credentials for this origin, the consumer
- // of the API might want to force the identity selection dialog.
- if (aOptions.forceSelection || aOptions.refreshCredentials) {
- return this.promptAndVerify(principal, manifestURL, creds)
- .then(
- (newCreds) => {
- return this.checkNewCredentials(creds, newCreds,
- principal.originNoSuffix);
- }
- );
- }
-
- // SIM change scenario.
-
- // It is possible that the SIM cards inserted in the device at the
- // moment of the previous verification where we obtained the credentials
- // has changed. In that case, we need to let the user knowabout this
- // situation. Otherwise, we just return the credentials.
- log.debug("Looking for SIM changes. Credentials ICCS ${creds} " +
- "Device ICCS ${device}", { creds: creds.deviceIccIds,
- device: this.iccIds });
- let simChanged = (creds.deviceIccIds == null && this.iccIds != null) ||
- (creds.deviceIccIds != null && this.iccIds == null);
-
- if (!simChanged &&
- creds.deviceIccIds != null &&
- this.iccIds != null) {
- simChanged = creds.deviceIccIds.length != this.iccIds.length;
- }
-
- if (!simChanged &&
- creds.deviceIccIds != null &&
- this.iccIds != null) {
- let intersection = creds.deviceIccIds.filter((n) => {
- return this.iccIds.indexOf(n) != -1;
- });
- simChanged = intersection.length != creds.deviceIccIds.length ||
- intersection.length != this.iccIds.length;
- }
-
- if (!simChanged) {
- return creds;
- }
-
- // At this point we know that the SIM associated with the credentials
- // is not present in the device any more or a new SIM has been detected,
- // so we need to ask the user what to do.
- return this.promptAndVerify(principal, manifestURL, creds)
- .then(
- (newCreds) => {
- return this.checkNewCredentials(creds, newCreds,
- principal.originNoSuffix);
- }
- );
- }
- )
- .then(
- (creds) => {
- // Even if we have credentails it is possible that the user has
- // removed the permission to share its mobile id with this origin, so
- // we check the permission and if it is not granted, we ask the user
- // before generating and sharing the assertion.
- // If we've just prompted the user in the previous step, the permission
- // is already granted and stored so we just progress the credentials.
- // But we have to refresh the cached permission before checking.
- if (creds) {
- permission = permissionManager.testPermissionFromPrincipal(
- principal,
- MOBILEID_PERM
- );
- if (permission == Ci.nsIPermissionManager.ALLOW_ACTION) {
- return creds;
- }
- return this.promptAndVerify(principal, manifestURL, creds);
- }
- return this.promptAndVerify(principal, manifestURL);
- }
- )
- .then(
- (creds) => {
- if (creds) {
- return this.generateAssertion(creds, principal.originNoSuffix);
- }
- return Promise.reject(ERROR_INTERNAL_CANNOT_GENERATE_ASSERTION);
- }
- )
- .then(
- (assertion) => {
- if (!assertion) {
- return Promise.reject(ERROR_INTERNAL_CANNOT_GENERATE_ASSERTION);
- }
-
- // Get the verified phone number from the assertion.
- let segments = assertion.split(".");
- if (!segments) {
- return Promise.reject(ERROR_INVALID_ASSERTION);
- }
-
- let payloadBuffer = ChromeUtils.base64URLDecode(segments[1], {
- // `IdentityCryptoService` pads output.
- padding: "require",
- });
- let textDecoder = new TextDecoder("utf-8");
- let decodedPayload = JSON.parse(textDecoder.decode(payloadBuffer));
-
- if (!decodedPayload || !decodedPayload.verifiedMSISDN) {
- return Promise.reject(ERROR_INVALID_ASSERTION);
- }
-
- this.ui.verified(decodedPayload.verifiedMSISDN);
-
- this.success(aPromiseId, assertion);
- }
- )
- .then(
- null,
- (error) => {
- log.error("getMobileIdAssertion rejected with ${}", error);
-
- // If we got an invalid token error means that the credentials that
- // we have are not valid anymore and so we need to refresh them. We
- // do that removing the stored credentials and starting over. We also
- // make sure that we do this only once.
- if (error === ERROR_INVALID_AUTH_TOKEN &&
- !aOptions.refreshCredentials) {
- log.debug("Need to get new credentials");
- aOptions.refreshCredentials = true;
- _creds && this.credStore.delete(_creds.msisdn);
- this.getMobileIdAssertion(aPrincipal, aPromiseId, aOptions);
- return;
- }
-
- // Notify the error to the UI.
- this.ui.error(error);
-
- this.error(aPromiseId, error);
- }
- );
- },
-
-};
-
-if (AppConstants.MOZ_B2G_RIL) {
- // We have these getters to allow mocking RIL stuff from the tests.
- Object.defineProperties(MobileIdentityManager, {
- "ril": {
- configurable: true,
- enumerable: true,
- get() {
- if (this._ril) {
- return this._ril;
- }
- return Ril;
- }
- },
- "iccService": {
- configurable: true,
- enumerable: true,
- get() {
- if (this._iccService) {
- return this._iccService;
- }
- return IccService;
- }
- },
- "mobileConnectionService": {
- configurable: true,
- enumerable: true,
- get() {
- if (this._mobileConnectionService) {
- return this._mobileConnectionService;
- }
- return MobileConnectionService;
- }
- }
- });
-}
-
-MobileIdentityManager.init();
deleted file mode 100644
--- a/services/mobileid/MobileIdentitySmsMoMtVerificationFlow.jsm
+++ /dev/null
@@ -1,79 +0,0 @@
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentitySmsMoMtVerificationFlow"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/MobileIdentitySmsVerificationFlow.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "smsService",
- "@mozilla.org/sms/smsservice;1",
- "nsISmsService");
-
-// In order to send messages through nsISmsService, we need to implement
-// nsIMobileMessageCallback, as the WebSMS API implementation is not usable
-// from JS.
-function SilentSmsRequest(aDeferred) {
- this.deferred = aDeferred;
-}
-SilentSmsRequest.prototype = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileMessageCallback]),
-
- classID: Components.ID("{ff46f1a8-e040-4ff4-98a7-d5a5b86a2c3e}"),
-
- notifyMessageSent: function notifyMessageSent(aMessage) {
- log.debug("Silent message successfully sent");
- this.deferred.resolve(aMessage);
- },
-
- notifySendMessageFailed: function notifySendMessageFailed(aError) {
- log.error("Error sending silent message " + aError);
- this.deferred.reject(aError);
- }
-};
-
-this.MobileIdentitySmsMoMtVerificationFlow = function(aVerificationOptions,
- aUI,
- aClient) {
-
- log.debug("MobileIdentitySmsMoMtVerificationFlow ${}", aVerificationOptions);
-
- MobileIdentitySmsVerificationFlow.call(this,
- aVerificationOptions,
- aUI,
- aClient,
- this.smsVerifyStrategy);
-};
-
-this.MobileIdentitySmsMoMtVerificationFlow.prototype = {
-
- __proto__: MobileIdentitySmsVerificationFlow.prototype,
-
- smsVerifyStrategy: function() {
- // In the MO+MT flow we need to send an SMS to the given moVerifier number
- // so the server can find out our phone number to send an SMS back with a
- // verification code.
- let deferred = Promise.defer();
- let silentSmsRequest = new SilentSmsRequest(deferred);
-
- // The MO SMS body that the server expects contains the API endpoint for
- // the MO verify request and the HAWK ID parameter derived via HKDF from
- // the session token. These parameters should go unnamed and space limited.
- let body = SMS_MO_MT_VERIFY + " " +
- this.client._deriveHawkCredentials(this.sessionToken).id;
- smsService.send(this.verificationOptions.serviceId,
- this.verificationOptions.moVerifier,
- body,
- true, // silent
- silentSmsRequest);
- log.debug("Sending " + body + " to " + this.verificationOptions.moVerifier);
- return deferred.promise;
- }
-};
deleted file mode 100644
--- a/services/mobileid/MobileIdentitySmsMtVerificationFlow.jsm
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentitySmsMtVerificationFlow"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/MobileIdentitySmsVerificationFlow.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-this.MobileIdentitySmsMtVerificationFlow = function(aVerificationOptions,
- aUI,
- aClient) {
-
- log.debug("MobileIdentitySmsVerificationFlow ${}", aVerificationOptions);
-
- MobileIdentitySmsVerificationFlow.call(this,
- aVerificationOptions,
- aUI,
- aClient,
- this.smsVerifyStrategy);
-};
-
-this.MobileIdentitySmsMtVerificationFlow.prototype = {
-
- __proto__: MobileIdentitySmsVerificationFlow.prototype,
-
- smsVerifyStrategy: function() {
- return this.client.smsMtVerify(this.sessionToken,
- this.verificationOptions.msisdn,
- this.verificationOptions.mcc,
- this.verificationOptions.mnc,
- this.verificationOptions.external);
- }
-};
deleted file mode 100644
--- a/services/mobileid/MobileIdentitySmsVerificationFlow.jsm
+++ /dev/null
@@ -1,109 +0,0 @@
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentitySmsVerificationFlow"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/AppConstants.jsm");
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/MobileIdentityVerificationFlow.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-if (AppConstants.MOZ_B2G_RIL) {
- XPCOMUtils.defineLazyServiceGetter(this, "smsService",
- "@mozilla.org/sms/smsservice;1",
- "nsISmsService");
-}
-
-this.MobileIdentitySmsVerificationFlow = function(aVerificationOptions,
- aUI,
- aClient,
- aVerifyStrategy) {
-
- // SMS MT or SMS MO+MT specific verify strategy.
- this.smsVerifyStrategy = aVerifyStrategy;
-
- log.debug("aVerificationOptions ${}", aVerificationOptions);
- MobileIdentityVerificationFlow.call(this, aVerificationOptions, aUI, aClient,
- this._verifyStrategy, this._cleanupStrategy);
-};
-
-this.MobileIdentitySmsVerificationFlow.prototype = {
-
- __proto__: MobileIdentityVerificationFlow.prototype,
-
- observedSilentNumber: null,
-
- onSilentSms: null,
-
- _verifyStrategy: function() {
- if (!this.smsVerifyStrategy) {
- return Promise.reject(ERROR_INTERNAL_UNEXPECTED);
- }
-
- // Even if the user selection is given to us as a possible external phone
- // number, it is also possible that the phone number introduced by the
- // user belongs to one of the SIMs inserted in the device which MSISDN
- // is unknown for us, so we always observe for incoming messages coming
- // from the given mtSender.
-
- if (AppConstants.MOZ_B2G_RIL) {
- this.observedSilentNumber = this.verificationOptions.mtSender;
- try {
- smsService.addSilentNumber(this.observedSilentNumber);
- } catch (e) {
- log.warn("We are already listening for that number");
- }
-
- this.onSilentSms = (function(aSubject, aTopic, aData) {
- log.debug("Got silent message " + aSubject.sender + " - " + aSubject.body);
- // We might have observed a notification of an incoming silent message
- // for other number. In that case, we just bail out.
- if (aSubject.sender != this.observedSilentNumber) {
- return;
- }
-
- // We got the SMS containing the verification code.
-
- // If the phone number we are trying to verify is or can be an external
- // phone number (meaning that it doesn't belong to any of the inserted
- // SIMs) we will be receiving an human readable SMS containing a short
- // verification code. In this case we need to parse the SMS body to
- // extract the verification code.
- // Otherwise, we just use the whole SMS body as it should contain a long
- // verification code.
- let verificationCode = aSubject.body;
- if (this.verificationOptions.external) {
- // We just take the numerical characters from the body.
- verificationCode = aSubject.body.replace(/[^0-9]/g,'');
- }
-
- log.debug("Verification code: " + verificationCode);
-
- this.verificationCodeDeferred.resolve(verificationCode);
- }).bind(this);
-
- Services.obs.addObserver(this.onSilentSms,
- SILENT_SMS_RECEIVED_TOPIC,
- false);
- log.debug("Observing messages from " + this.observedSilentNumber);
- }
-
- return this.smsVerifyStrategy();
- },
-
- _cleanupStrategy: function() {
- if (AppConstants.MOZ_B2G_RIL) {
- smsService.removeSilentNumber(this.observedSilentNumber);
- Services.obs.removeObserver(this.onSilentSms,
- SILENT_SMS_RECEIVED_TOPIC);
- this.observedSilentNumber = null;
- this.onSilentSms = null;
- }
- }
-};
deleted file mode 100644
--- a/services/mobileid/MobileIdentityUIGlueCommon.jsm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentityUIGluePhoneInfo",
- "MobileIdentityUIGluePromptResult"];
-
-this.MobileIdentityUIGluePhoneInfo = function (aMsisdn, aOperator, aServiceId,
- aIccId, aPrimary) {
- this.msisdn = aMsisdn;
- this.operator = aOperator;
- this.serviceId = aServiceId;
- this.iccId = aIccId;
- // A phone number is considered "external" when it doesn't or we don't know
- // if it does belong to any of the device SIM cards.
- this.external = !!aIccId;
- this.primary = aPrimary;
-}
-
-this.MobileIdentityUIGluePhoneInfo.prototype = {};
-
-this.MobileIdentityUIGluePromptResult = function (aPhoneNumber, aPrefix, aMcc,
- aServiceId) {
- this.phoneNumber = aPhoneNumber;
- this.prefix = aPrefix;
- this.mcc = aMcc;
- this.serviceId = aServiceId;
-}
-
-this.MobileIdentityUIGluePromptResult.prototype = {};
deleted file mode 100644
--- a/services/mobileid/MobileIdentityVerificationFlow.jsm
+++ /dev/null
@@ -1,215 +0,0 @@
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["MobileIdentityVerificationFlow"];
-
-const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
-
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-this.MobileIdentityVerificationFlow = function(aVerificationOptions,
- aUI,
- aClient,
- aVerifyStrategy,
- aCleanupStrategy) {
- this.verificationOptions = aVerificationOptions;
- this.ui = aUI;
- this.client = aClient;
- this.retries = VERIFICATIONCODE_RETRIES;
- this.verifyStrategy = aVerifyStrategy;
- this.cleanupStrategy = aCleanupStrategy;
-};
-
-MobileIdentityVerificationFlow.prototype = {
-
- doVerification: function() {
- log.debug("Start verification flow");
- return this.register()
- .then(
- (registerResult) => {
- log.debug("Register result ${}", registerResult);
- if (!registerResult || !registerResult.msisdnSessionToken) {
- return Promise.reject(ERROR_INTERNAL_UNEXPECTED);
- }
- this.sessionToken = registerResult.msisdnSessionToken;
- // We save the timestamp of the start of the verification timeout to be
- // able to provide to the UI the remaining time on each retry.
- if (!this.timer) {
- log.debug("Creating verification code timer");
- this.timerCreation = Date.now();
- this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- this.timer.initWithCallback(this.onVerificationCodeTimeout.bind(this),
- VERIFICATIONCODE_TIMEOUT,
- this.timer.TYPE_ONE_SHOT);
- }
-
- if (!this.verifyStrategy) {
- return Promise.reject(ERROR_INTERNAL_INVALID_VERIFICATION_FLOW);
- }
-
- return this.verifyStrategy()
- .then(() => {
- return this._doVerification();
- }, (reason) => {
- this.verificationCodeDeferred.reject(reason);
- });
- }
- )
- },
-
- _doVerification: function() {
- log.debug("_doVerification");
-
- this.verificationCodeDeferred = Promise.defer();
-
- // If the verification flow can be for an external phone number,
- // we need to ask the user for the verification code.
- // In that case we don't do a notification about the verification
- // process being done until the user enters the verification code
- // in the UI.
- if (this.verificationOptions.external) {
- let timeLeft = 0;
- if (this.timer) {
- timeLeft = this.timerCreation + VERIFICATIONCODE_TIMEOUT -
- Date.now();
- }
- this.ui.verificationCodePrompt(this.retries,
- VERIFICATIONCODE_TIMEOUT / 1000,
- timeLeft / 1000)
- .then(
- (verificationCode) => {
- if (!verificationCode) {
- return this.verificationCodeDeferred.reject(
- ERROR_INTERNAL_INVALID_PROMPT_RESULT);
- }
- // If the user got the verification code that means that the
- // introduced phone number didn't belong to any of the inserted
- // SIMs.
- this.ui.verify();
- this.verificationCodeDeferred.resolve(verificationCode);
- }
- );
- } else {
- this.ui.verify();
- }
-
- return this.verificationCodeDeferred.promise.then(
- this.onVerificationCode.bind(this)
- );
- },
-
- // When we receive a verification code from the UI, we check it against
- // the server. If the verification code is incorrect, we decrease the
- // number of retries left and allow the user to try again. If there is no
- // possible retry left, we notify about this error so the UI can allow the
- // user to request the resend of a new verification code.
- onVerificationCode: function(aVerificationCode) {
- log.debug("onVerificationCode " + aVerificationCode);
- if (!aVerificationCode) {
- this.ui.error(ERROR_INVALID_VERIFICATION_CODE);
- return this._doVerification();
- }
-
- // Before checking the verification code against the server we set the
- // "verifying" flag to queue timeout expiration events received before
- // the server request is completed. If the server request is positive
- // we will discard the timeout event, otherwise we will progress the
- // event to the UI to allow the user to retry.
- this.verifying = true;
-
- return this.verifyCode(aVerificationCode)
- .then(
- (result) => {
- if (!result) {
- return Promise.reject(INTERNAL_UNEXPECTED);
- }
- // The code was correct!
- // At this point the phone number is verified.
- // We return the given verification options with the session token
- // to be stored in the credentials store. With this data we will be
- // asking the server to give us a certificate to generate assertions.
- this.verificationOptions.sessionToken = this.sessionToken;
- this.verificationOptions.msisdn = result.msisdn ||
- this.verificationOptions.msisdn;
- return this.verificationOptions;
- },
- (error) => {
- log.error("Verification code error " + error);
- this.retries--;
- log.error("Retries left " + this.retries);
- if (!this.retries) {
- this.ui.error(ERROR_NO_RETRIES_LEFT);
- this.timer.cancel();
- this.timer = null;
- return Promise.reject(ERROR_NO_RETRIES_LEFT);
- }
- this.ui.error(ERROR_INVALID_VERIFICATION_CODE);
- this.verifying = false;
- if (this.queuedTimeout) {
- this.onVerificationCodeTimeout();
- }
- return this._doVerification();
- }
- );
- },
-
- onVerificationCodeTimeout: function() {
- // It is possible that we get the timeout when we are checking a
- // verification code with the server. In that case, we queue the
- // timeout to be triggered after we receive the reply from the server
- // if needed.
- if (this.verifying) {
- this.queuedTimeout = true;
- return;
- }
-
- // When the verification process times out we do a clean up, reject
- // the corresponding promise and notify the UI about the timeout.
- if (this.verificationCodeDeferred) {
- this.verificationCodeDeferred.reject(ERROR_VERIFICATION_CODE_TIMEOUT);
- }
- this.ui.error(ERROR_VERIFICATION_CODE_TIMEOUT);
- },
-
- register: function() {
- return this.client.register();
- },
-
- verifyCode: function(aVerificationCode) {
- return this.client.verifyCode(this.sessionToken, aVerificationCode);
- },
-
- unregister: function() {
- return this.client.unregister(this.sessionToken);
- },
-
- cleanup: function(aUnregister = false) {
- log.debug("Verification flow cleanup");
-
- this.queuedTimeout = false;
- this.retries = VERIFICATIONCODE_RETRIES;
-
- if (this.timer) {
- this.timer.cancel();
- this.timer = null;
- }
-
- if (aUnregister) {
- this.unregister().
- then(
- () => {
- this.sessionToken = null;
- }
- );
- }
-
- if (this.cleanupStrategy) {
- this.cleanupStrategy();
- }
- }
-};
deleted file mode 100644
--- a/services/mobileid/interfaces/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-XPIDL_SOURCES += [
- 'nsIMobileIdentityUIGlue.idl'
-]
-
-XPIDL_MODULE = 'services_mobileidentity'
deleted file mode 100644
--- a/services/mobileid/interfaces/nsIMobileIdentityUIGlue.idl
+++ /dev/null
@@ -1,77 +0,0 @@
-/* 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/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(6c4c5758-e041-4e0d-98da-67bb552f8018)]
-interface nsIMobileIdentityUIGlue : nsISupports
-{
- /**
- * Request the creation of a Mobile ID UI flow.
- *
- * The permission prompt starts the verification flow asking the user
- * for permission to share her phone number and allowing her to choose
- * an already known phone number, a SIM which phone number is unknown
- * (even in a multi-SIM scenario) or an external phone number.
- * Selecting a phone number implies giving permission to share it with the
- * API caller, so the UI should be clear about this.
- *
- * @manifestURL manifest URL of the mobile ID requester.
- * @iccInfo array of objects containing the information about the
- * SIM cards available in the device and that can be used for the
- * phone number verification and share process.
- *
- * Returns a Promise. An instance of nsIMobileIdentityUIGluePromptResult will
- * be returned as result of the Promise or a single string containing an error
- * in case of rejection.
- */
- jsval startFlow(in DOMString manifestURL, in jsval iccInfo);
-
- /**
- * Will prompt the user to enter a code used to verify a phone number.
- * This will only be called if an external phone number is selected in
- * startFlow().
- *
- * @retries number of retries left to validate a verification code.
- * @timeout the verification code expires after the timeout fires. This is
- * the total life time of the verification code.
- * @timeLeft we might call verificationCodePrompt more than once for the
- * same verification flow (i.e. when the verification code entered
- * by the user is incorrect) so we give to the UI the amount of
- * time left before the verification code expires.
- *
- * Returns a Promise. The value of the resolved promise will be the
- * verification code introduced through the UI or an error in case of
- * rejection of the promise.
- */
- jsval verificationCodePrompt(in short retries,
- in long timeout,
- in long timeLeft);
-
- /**
- * Notify the UI about the start of the verification process.
- */
- void verify();
-
- /**
- * Notify the UI about an error in the verification process.
- */
- void error(in DOMString error);
-
- /**
- * Notify the UI about the succesful phone number verification.
- */
- void verified(in DOMString verifiedPhoneNumber);
-
- /**
- * Callback to be called when the user cancels the verification flow via UI.
- */
- attribute jsval oncancel;
-
- /**
- * Callback to be called when the user requests a resend of a verification
- * code.
- */
- attribute jsval onresendcode;
-};
deleted file mode 100644
--- a/services/mobileid/moz.build
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-DIRS += ['interfaces']
-
-XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
-
-EXTRA_JS_MODULES += [
- 'MobileIdentityClient.jsm',
- 'MobileIdentityCommon.jsm',
- 'MobileIdentityCredentialsStore.jsm',
- 'MobileIdentityManager.jsm',
- 'MobileIdentitySmsMoMtVerificationFlow.jsm',
- 'MobileIdentitySmsMtVerificationFlow.jsm',
- 'MobileIdentitySmsVerificationFlow.jsm',
- 'MobileIdentityUIGlueCommon.jsm',
- 'MobileIdentityVerificationFlow.jsm'
-]
deleted file mode 100644
--- a/services/mobileid/tests/xpcshell/head.js
+++ /dev/null
@@ -1,439 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
-
-var Cm = Components.manager;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-(function initMobileIdTestingInfrastructure() {
- do_get_profile();
-
- const PREF_FORCE_HTTPS = "services.mobileid.forcehttps";
- Services.prefs.setBoolPref(PREF_FORCE_HTTPS, false);
- Services.prefs.setCharPref("services.mobileid.loglevel", "Debug");
- Services.prefs.setCharPref("services.mobileid.server.uri",
- "https://dummyurl.com");
-}).call(this);
-
-const DEBUG = false;
-
-const GET_ASSERTION_IPC_MSG = "MobileId:GetAssertion";
-const GET_ASSERTION_RETURN_OK = "MobileId:GetAssertion:Return:OK";
-const GET_ASSERTION_RETURN_KO = "MobileId:GetAssertion:Return:KO";
-
-// === Globals ===
-
-const ORIGIN = "app://afakeorigin";
-const APP_ID = 1;
-const PRINCIPAL = {
- origin: ORIGIN,
- appId: APP_ID
-};
-const PHONE_NUMBER = "+34666555444";
-const ANOTHER_PHONE_NUMBER = "+44123123123";
-const VERIFICATION_CODE = "123456";
-const SESSION_TOKEN = "aSessionToken";
-const ICC_ID = "aIccId";
-const ANOTHER_ICC_ID = "anotherIccId";
-const MNC = "aMnc";
-const ANOTHER_MNC = "anotherMnc";
-const MCC = "aMcc";
-const ANOTHER_MCC = "anotherMcc";
-const OPERATOR = "aOperator";
-const ANOTHER_OPERATOR = "anotherOperator";
-const ICC_INFO = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
- Ci.nsIIccInfo]),
- iccType: "usim",
- iccid: ICC_ID,
- mcc: MCC,
- mnc: MNC,
- msisdn: PHONE_NUMBER,
- operator: OPERATOR
-};
-const ANOTHER_ICC_INFO = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
- Ci.nsIIccInfo]),
- iccType: "usim",
- iccid: ANOTHER_ICC_ID,
- mcc: ANOTHER_MCC,
- mnc: ANOTHER_MNC,
- msisdn: ANOTHER_PHONE_NUMBER,
- operator: ANOTHER_OPERATOR
-};
-const INVALID_ICC_INFO = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
- Ci.nsIIccInfo]),
- iccType: "usim",
- iccid: null,
- mcc: "",
- mnc: "",
- msisdn: "",
- operator: ""
-};
-const RADIO_INTERFACE = {
- voice: {
- network: {
- shortName: OPERATOR
- },
- roaming: false
- },
- data: {
- network: {
- shortName: OPERATOR
- }
- }
-};
-const ANOTHER_RADIO_INTERFACE = {
- voice: {
- network: {
- shortName: ANOTHER_OPERATOR
- },
- roaming: false
- },
- data: {
- network: {
- shortName: ANOTHER_OPERATOR
- }
- }
-};
-
-const INVALID_RADIO_INTERFACE = {
- voice: {
- network: {
- shortName: ""
- },
- roaming: undefined
- },
- data: {
- network: {
- shortName: ""
- }
- }
-};
-
-const CERTIFICATE = "eyJhbGciOiJEUzI1NiJ9.eyJsYXN0QXV0aEF0IjoxNDA0NDY5NzkyODc3LCJ2ZXJpZmllZE1TSVNETiI6IiszMTYxNzgxNTc1OCIsInB1YmxpYy1rZXkiOnsiYWxnb3JpdGhtIjoiRFMiLCJ5IjoiNGE5YzkzNDY3MWZhNzQ3YmM2ZjMyNjE0YTg1MzUyZjY5NDcwMDdhNTRkMDAxMDY4OWU5ZjJjZjc0ZGUwYTEwZTRlYjlmNDk1ZGFmZTA0NGVjZmVlNDlkN2YwOGU4ODQyMDJiOTE5OGRhNWZhZWE5MGUzZjRmNzE1YzZjNGY4Yjc3MGYxZTU4YWZhNDM0NzVhYmFiN2VlZGE1MmUyNjk2YzFmNTljNzMzYjFlYzBhNGNkOTM1YWIxYzkyNzAxYjNiYTA5ZDRhM2E2MzNjNTJmZjE2NGYxMWY3OTg1YzlmZjY3ZThmZDFlYzA2NDU3MTdkMjBiNDE4YmM5M2YzYzVkNCIsInAiOiJmZjYwMDQ4M2RiNmFiZmM1YjQ1ZWFiNzg1OTRiMzUzM2Q1NTBkOWYxYmYyYTk5MmE3YThkYWE2ZGMzNGY4MDQ1YWQ0ZTZlMGM0MjlkMzM0ZWVlYWFlZmQ3ZTIzZDQ4MTBiZTAwZTRjYzE0OTJjYmEzMjViYTgxZmYyZDVhNWIzMDVhOGQxN2ViM2JmNGEwNmEzNDlkMzkyZTAwZDMyOTc0NGE1MTc5MzgwMzQ0ZTgyYTE4YzQ3OTMzNDM4Zjg5MWUyMmFlZWY4MTJkNjljOGY3NWUzMjZjYjcwZWEwMDBjM2Y3NzZkZmRiZDYwNDYzOGMyZWY3MTdmYzI2ZDAyZTE3IiwicSI6ImUyMWUwNGY5MTFkMWVkNzk5MTAwOGVjYWFiM2JmNzc1OTg0MzA5YzMiLCJnIjoiYzUyYTRhMGZmM2I3ZTYxZmRmMTg2N2NlODQxMzgzNjlhNjE1NGY0YWZhOTI5NjZlM2M4MjdlMjVjZmE2Y2Y1MDhiOTBlNWRlNDE5ZTEzMzdlMDdhMmU5ZTJhM2NkNWRlYTcwNGQxNzVmOGViZjZhZjM5N2Q2OWUxMTBiOTZhZmIxN2M3YTAzMjU5MzI5ZTQ4MjliMGQwM2JiYzc4OTZiMTViNGFkZTUzZTEzMDg1OGNjMzRkOTYyNjlhYTg5MDQxZjQwOTEzNmM3MjQyYTM4ODk1YzlkNWJjY2FkNGYzODlhZjFkN2E0YmQxMzk4YmQwNzJkZmZhODk2MjMzMzk3YSJ9LCJwcmluY2lwYWwiOiIwMzgxOTgyYS0xZTgzLTI1NjYtNjgzZS05MDRmNDA0NGM1MGRAbXNpc2RuLWRldi5zdGFnZS5tb3phd3MubmV0IiwiaWF0IjoxNDA0NDY5NzgyODc3LCJleHAiOjE0MDQ0OTEzOTI4NzcsImlzcyI6Im1zaXNkbi1kZXYuc3RhZ2UubW96YXdzLm5ldCJ9."
-
-// === Helpers ===
-
-function addPermission(aAction) {
- let uri = Cc["@mozilla.org/network/io-service;1"]
- .getService(Ci.nsIIOService)
- .newURI(ORIGIN, null, null);
- let attrs = {appId: APP_ID};
- let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
- .getService(Ci.nsIScriptSecurityManager)
- .createCodebasePrincipal(uri, attrs);
- let pm = Cc["@mozilla.org/permissionmanager;1"]
- .getService(Ci.nsIPermissionManager);
- pm.addFromPrincipal(_principal, MOBILEID_PERM, aAction);
-}
-
-function removePermission() {
- let uri = Cc["@mozilla.org/network/io-service;1"]
- .getService(Ci.nsIIOService)
- .newURI(ORIGIN, null, null);
- let attrs = {appId: APP_ID};
- let _principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
- .getService(Ci.nsIScriptSecurityManager)
- .createCodebasePrincipal(uri, attrs);
- let pm = Cc["@mozilla.org/permissionmanager;1"]
- .getService(Ci.nsIPermissionManager);
- pm.removeFromPrincipal(_principal, MOBILEID_PERM);
-}
-
-// === Mocks ===
-
-var Mock = function(aOptions) {
- if (!aOptions) {
- aOptions = {};
- }
- this._options = aOptions;
- this._spied = {};
-};
-
-Mock.prototype = {
- _: function(aMethod) {
- DEBUG && do_print("_ " + aMethod + JSON.stringify(this._spied));
- let self = this;
- return {
- callsLength: function(aNumberOfCalls) {
- if (aNumberOfCalls == 0) {
- do_check_eq(self._spied[aMethod], undefined);
- return;
- }
- do_check_eq(self._spied[aMethod].length, aNumberOfCalls);
- },
- call: function(aCallNumber) {
- return {
- arg: function(aArgNumber, aValue) {
- let _arg = self._spied[aMethod][aCallNumber - 1][aArgNumber - 1];
- if (Array.isArray(aValue)) {
- do_check_eq(_arg.length, aValue.length)
- for (let i = 0; i < _arg.length; i++) {
- do_check_eq(_arg[i], aValue[i]);
- }
- return;
- }
-
- if (typeof aValue === 'object') {
- do_check_eq(JSON.stringify(_arg), JSON.stringify(aValue));
- return;
- }
-
- do_check_eq(_arg, aValue);
- }
- }
- }
- }
- },
-
- _spy: function(aMethod, aArgs) {
- DEBUG && do_print(aMethod + " - " + JSON.stringify(aArgs));
- if (!this._spied[aMethod]) {
- this._spied[aMethod] = [];
- }
- this._spied[aMethod].push(aArgs);
- },
-
- getSpiedCalls: function(aMethod) {
- return this._spied[aMethod];
- }
-};
-
-// UI Glue mock up.
-var MockUi = function(aOptions) {
- Mock.call(this, aOptions);
-};
-
-MockUi.prototype = {
- __proto__: Mock.prototype,
-
- _startFlowResult: {
- phoneNumber: PHONE_NUMBER,
- mcc: MNC
- },
-
- _verifyCodePromptResult: {
- verificationCode: VERIFICATION_CODE
- },
-
- startFlow: function() {
- this._spy("startFlow", arguments);
- return Promise.resolve(this._options.startFlowResult ||
- this._startFlowResult);
- },
-
- verificationCodePrompt: function() {
- this._spy("verifyCodePrompt", arguments);
- return Promise.resolve(this._options.verificationCodePromptResult ||
- this._verifyCodePromptResult);
- },
-
- verify: function() {
- this._spy("verify", arguments);
- },
-
- error: function() {
- this._spy("error", arguments);
- },
-
- verified: function() {
- this._spy("verified", arguments);
- },
-
- set oncancel(aCallback) {
- },
-
- set onresendcode(aCallback) {
- }
-};
-
-// Credentials store mock up.
-var MockCredStore = function(aOptions) {
- Mock.call(this, aOptions);
-};
-
-MockCredStore.prototype = {
- __proto__: Mock.prototype,
-
- _getByOriginResult: null,
-
- _getByMsisdnResult: null,
-
- _getByIccIdResult: null,
-
- getByOrigin: function() {
- this._spy("getByOrigin", arguments);
- let result = this._getByOriginResult;
- if (this._options.getByOriginResult) {
- if (Array.isArray(this._options.getByOriginResult)) {
- result = this._options.getByOriginResult.length ?
- this._options.getByOriginResult.shift() : null;
- } else {
- result = this._options.getByOriginResult;
- }
- }
- return Promise.resolve(result);
- },
-
- getByMsisdn: function() {
- this._spy("getByMsisdn", arguments);
- return Promise.resolve(this._options.getByMsisdnResult ||
- this._getByMsisdnResult);
- },
-
- getByIccId: function()Â {
- this._spy("getByIccId", arguments);
- return Promise.resolve(this._options.getByIccIdResult ||
- this._getByIccIdResult);
- },
-
- add: function() {
- this._spy("add", arguments);
- return Promise.resolve();
- },
-
- setDeviceIccIds: function() {
- this._spy("setDeviceIccIds", arguments);
- return Promise.resolve();
- },
-
- removeOrigin: function() {
- this._spy("removeOrigin", arguments);
- return Promise.resolve();
- },
-
- delete: function() {
- this._spy("delete", arguments);
- return Promise.resolve();
- }
-};
-
-// Client mock up.
-var MockClient = function(aOptions) {
- Mock.call(this, aOptions);
-};
-
-MockClient.prototype = {
-
- __proto__: Mock.prototype,
-
- _discoverResult: {
- verificationMethods: ["sms/mt"],
- verificationDetails: {
- "sms/mt": {
- mtSender: "123",
- url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
- }
- }
- },
-
- _registerResult: {
- msisdnSessionToken: SESSION_TOKEN
- },
-
- _smsMtVerifyResult: {},
-
- _verifyCodeResult: {
- msisdn: PHONE_NUMBER
- },
-
- _signResult: {
- cert: CERTIFICATE
- },
-
- hawk: {
- now: function() {
- return Date.now();
- }
- },
-
- discover: function() {
- this._spy("discover", arguments);
- return Promise.resolve(this._options.discoverResult ||
- this._discoverResult);
- },
-
- register: function() {
- this._spy("register", arguments);
- return Promise.resolve(this._options.registerResult ||
- this._registerResult);
- },
-
- smsMtVerify: function() {
- this._spy("smsMtVerify", arguments);
- return Promise.resolve(this._options.smsMtVerifyResult ||
- this._smsMtVerifyResult);
- },
-
- verifyCode: function() {
- this._spy("verifyCode", arguments);
- if (this._options.verifyCodeError) {
- let error = Array.isArray(this._options.verifyCodeError) ?
- this._options.verifyCodeError.shift() :
- this._options.verifyCodeError;
- if (!this._options.verifyCodeError.length) {
- this._options.verifyCodeError = null;
- }
- return Promise.reject(error);
- }
- return Promise.resolve(this._options.verifyCodeResult ||
- this._verifyCodeResult);
- },
-
- sign: function() {
- this._spy("sign", arguments);
- if (this._options.signError) {
- let error = Array.isArray(this._options.signError) ?
- this._options.signError.shift() :
- this._options.signError;
- return Promise.reject(error);
- }
- return Promise.resolve(this._options.signResult || this._signResult);
- }
-};
-
-// Override MobileIdentityUIGlue.
-const kMobileIdentityUIGlueUUID = "{05df0566-ca8a-4ec7-bc76-78626ebfbe9a}";
-const kMobileIdentityUIGlueContractID =
- "@mozilla.org/services/mobileid-ui-glue;1";
-
-// Save original factory.
-/*const kMobileIdentityUIGlueFactory =
- Cm.getClassObject(Cc[kMobileIdentityUIGlueContractID], Ci.nsIFactory);*/
-
-var fakeMobileIdentityUIGlueFactory = {
- createInstance: function(aOuter, aIid) {
- return MobileIdentityUIGlue.QueryInterface(aIid);
- }
-};
-
-// MobileIdentityUIGlue fake component.
-var MobileIdentityUIGlue = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileIdentityUIGlue]),
-
-};
-
-(function registerFakeMobileIdentityUIGlue() {
- Cm.QueryInterface(Ci.nsIComponentRegistrar)
- .registerFactory(Components.ID(kMobileIdentityUIGlueUUID),
- "MobileIdentityUIGlue",
- kMobileIdentityUIGlueContractID,
- fakeMobileIdentityUIGlueFactory);
-})();
-
-// The tests rely on having an app registered. Otherwise, it will throw.
-// Override XULAppInfo.
-Cu.import("resource://testing-common/AppInfo.jsm", this);
-updateAppInfo({
- name: "MobileIdTest",
- ID: "{230de50e-4cd1-11dc-8314-0800200b9a66}",
- version: "1",
- platformVersion: "",
-});
deleted file mode 100644
--- a/services/mobileid/tests/xpcshell/test_mobileid_client.js
+++ /dev/null
@@ -1,247 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://testing-common/httpd.js");
-Cu.import("resource://gre/modules/MobileIdentityClient.jsm");
-
-/* Setup */
-
-var client;
-var server = new HttpServer();
-
-function httpd_setup(handlers, port = -1) {
- for (let path in handlers) {
- server.registerPathHandler(path, handlers[path]);
- }
-
- try {
- server.start(port);
- } catch (ex) {
- dump("ERROR starting server on port " + port + ". Already a process listening?");
- do_throw(ex);
- }
-
- // Set the base URI for convenience.
- let i = server.identity;
- server.baseURI = i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort;
-
- return server;
-}
-
-function writeResp(response, msg) {
- if (typeof msg === "object") {
- msg = JSON.stringify(msg);
- }
- response.bodyOutputStream.write(msg, msg.length);
-}
-
-function getBody(request) {
- let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream);
- return JSON.parse(body);
-}
-
-function run_test() {
- httpd_setup({
- "/discover": function(request, response) {
- let body = getBody(request);
- response.setStatusLine(null, 200, "Ok");
- writeResp(response, {
- msisdn: body.msisdn,
- mcc: body.mcc,
- mnc: body.mnc,
- roaming: body.roaming
- });
- },
- "/register": function(request, response) {
- response.setStatusLine(null, 204);
- },
- "/sms/mt/verify": function(request, response) {
- let body = getBody(request);
- response.setStatusLine(null, 200, "Ok");
- writeResp(response, {
- msisdn: body.msisdn,
- mcc: body.mcc,
- mnc: body.mnc,
- shortVerificationCode: body.shortVerificationCode
- });
- },
- "/sms/verify_code": function(request, response) {
- let body = getBody(request);
- response.setStatusLine(null, 200, "Ok");
- writeResp(response, {
- code: body.code
- });
- },
- "/certificate/sign": function(request, response) {
- let body = getBody(request);
- response.setStatusLine(null, 200, "Ok");
- writeResp(response, {
- duration: body.duration,
- publicKey: body.publicKey
- });
- },
- "/unregister": function(request, response) {
- response.setStatusLine(null, 500);
- }
- });
-
-
- client = new MobileIdentityClient(server.baseURI);
-
- run_next_test();
-}
-
-/* Tests */
-
-add_test(function test_discover() {
- do_print("= Test /discover =");
-
- do_test_pending();
-
- let msisdn = "msisdn";
- let mcc = "mcc";
- let mnc = "mnc";
- let roaming = true;
-
- client.discover(msisdn, mcc, mnc, roaming).then(
- (response) => {
- // The request should succeed and a response should be given.
- // We simply check that the parameters given with the request are
- // successfully progressed to the server.
- do_check_eq(response.msisdn, msisdn);
- do_check_eq(response.mcc, mcc);
- do_check_eq(response.mnc, mnc);
- do_check_eq(response.roaming, roaming);
- do_test_finished();
- run_next_test();
- },
- (error) => {
- do_throw("Should not throw error when handling a 200 response");
- do_test_finished();
- run_next_test();
- }
- );
-});
-
-add_test(function test_sms_mt_verify() {
- do_print("= Test /sms/mt/verify =");
-
- do_test_pending();
-
- let msisdn = "msisdn";
- let mcc = "mcc";
- let mnc = "mnc";
- let shortCode = true;
-
- client.smsMtVerify("aToken", msisdn, mcc, mnc, shortCode).then(
- (response) => {
- // The request should succeed and a response should be given.
- // We simply check that the parameters given with the request are
- // successfully progressed to the server.
- do_check_eq(response.msisdn, msisdn);
- do_check_eq(response.mcc, mcc);
- do_check_eq(response.mnc, mnc);
- do_check_eq(response.shortVerificationCode, shortCode);
- do_test_finished();
- run_next_test();
- },
- (error) => {
- do_throw("Should not throw error when handling a 200 response");
- do_test_finished();
- run_next_test();
- }
- );
-});
-
-add_test(function test_verify_code() {
- do_print("= Test /sms/verify_code =");
-
- do_test_pending();
-
- let code = "code";
-
- client.verifyCode("aToken", code).then(
- (response) => {
- // The request should succeed and a response should be given.
- // We simply check that the parameters given with the request are
- // successfully progressed to the server.
- do_check_eq(response.code, code);
- do_test_finished();
- run_next_test();
- },
- (error) => {
- do_throw("Should not throw error when handling a 200 response");
- do_test_finished();
- run_next_test();
- }
- );
-});
-
-add_test(function test_certificate_sign() {
- do_print("= Test /certificate/sign =");
-
- do_test_pending();
-
- let duration = "duration";
- let publicKey = "publicKey";
-
- client.sign("aToken", duration, publicKey).then(
- (response) => {
- // The request should succeed and a response should be given.
- // We simply check that the parameters given with the request are
- // successfully progressed to the server.
- do_check_eq(response.duration, duration);
- do_check_eq(response.publicKey, publicKey);
- do_test_finished();
- run_next_test();
- },
- (error) => {
- do_throw("Should not throw error when handling a 200 response");
- do_test_finished();
- run_next_test();
- }
- );
-});
-
-add_test(function test_204_response() {
- do_print("= Test /register and 204 No Content response =");
-
- do_test_pending();
-
- client.register().then(
- (response) => {
- // The request should succeed but no response body should be returned.
- do_check_eq(response, undefined);
- do_test_finished();
- run_next_test();
- },
- (error) => {
- do_throw("Should not throw error when handling a 204 response");
- do_test_finished();
- run_next_test();
- }
- );
-});
-
-add_test(function test_500_response() {
- do_print("= Test /unregister and 500 response =");
-
- do_test_pending();
-
- client.unregister("aToken").then(
- (response) => {
- // The request shouldn't succeed.
- do_throw("We are supposed to get an error");
- do_test_finished();
- run_next_test();
- },
- (error) => {
- do_check_eq(error, "UNKNOWN");
- do_test_finished();
- run_next_test();
- }
- );
-});
deleted file mode 100644
--- a/services/mobileid/tests/xpcshell/test_mobileid_manager.js
+++ /dev/null
@@ -1,1227 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/MobileIdentityManager.jsm");
-Cu.import("resource://gre/modules/MobileIdentityCommon.jsm");
-
-// Save original credential store instance.
-const kMobileIdentityCredStore = MobileIdentityManager.credStore;
-// Save original client instance.
-const kMobileIdentityClient = MobileIdentityManager.client;
-
-// === Global cleanup ===
-function cleanup() {
- MobileIdentityManager.credStore = kMobileIdentityCredStore;
- MobileIdentityManager.client = kMobileIdentityClient;
- MobileIdentityManager.ui = null;
- MobileIdentityManager._iccInfo = [];
- removePermission(ORIGIN);
-}
-
-// Unregister mocks and restore original code.
-do_register_cleanup(cleanup);
-// === Tests ===
-function run_test() {
- run_next_test();
-}
-
-add_test(function() {
- do_print("= Initial state =");
- do_check_neq(MobileIdentityManager, undefined);
- run_next_test();
-});
-
-add_test(function() {
- do_print("= No credentials - No ICC - User MSISDN - External - OK result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let ui = new MockUi();
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore();
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient();
- MobileIdentityManager.client = client;
- MobileIdentityManager._iccInfo = [];
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(1);
- credStore._("getByMsisdn").call(1).arg(1, PHONE_NUMBER);
- credStore._("add").callsLength(1);
- credStore._("add").call(1).arg(1, undefined);
- credStore._("add").call(1).arg(2, PHONE_NUMBER);
- credStore._("add").call(1).arg(3, ORIGIN);
- credStore._("add").call(1).arg(4, SESSION_TOKEN);
- credStore._("add").call(1).arg(5, []);
-
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("startFlow").call(1).arg(1, "");
- ui._("startFlow").call(1).arg(2, []);
- ui._("verifyCodePrompt").callsLength(1);
- ui._("verifyCodePrompt").call(1).arg(1, 3);
- ui._("verify").callsLength(1);
-
- // MockClient.
- client._("discover").callsLength(1);
- client._("discover").call(1).arg(1, PHONE_NUMBER);
- client._("register").callsLength(1);
- client._("smsMtVerify").callsLength(1);
- client._("smsMtVerify").call(1).arg(1, SESSION_TOKEN);
- client._("smsMtVerify").call(1).arg(2, PHONE_NUMBER);
- client._("smsMtVerify").call(1).arg(3, MNC);
- client._("smsMtVerify").call(1).arg(4, undefined);
- client._("smsMtVerify").call(1).arg(5, true);
- client._("verifyCode").callsLength(1);
- client._("verifyCode").call(1).arg(1, SESSION_TOKEN);
- client._("verifyCode").call(1).arg(2, {
- verificationCode: VERIFICATION_CODE
- });
- client._("sign").callsLength(1);
- client._("sign").call(1).arg(1, SESSION_TOKEN);
- client._("sign").call(1).arg(2, CERTIFICATE_LIFETIME);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId
- }
- });
-});
-
-add_test(function() {
- do_print("= No credentials - No icc - User MSISDN - External - KO -" +
- " ERROR_INTERNAL_CANNOT_VERIFY_SELECTION =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let ui = new MockUi();
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore();
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient({
- discoverResult: {
- verificationMethods: ["other"],
- verificationDetails: {
- "other": {}
- }
- },
- registerResult: {
- msisdnSessionToken: _sessionToken
- }
- });
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_KO);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
- do_check_eq(aData.error, ERROR_INTERNAL_CANNOT_VERIFY_SELECTION);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(1);
- credStore._("getByMsisdn").call(1).arg(1, PHONE_NUMBER);
- credStore._("add").callsLength(0);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("startFlow").call(1).arg(1, "");
- ui._("startFlow").call(1).arg(2, []);
- ui._("verifyCodePrompt").callsLength(0);
- ui._("verify").callsLength(0);
- ui._("error").callsLength(1);
- ui._("error").call(1).arg(1, ERROR_INTERNAL_CANNOT_VERIFY_SELECTION);
-
- // MockClient.
- client._("discover").callsLength(1);
- client._("discover").call(1).arg(1, PHONE_NUMBER);
- client._("register").callsLength(0);
- client._("smsMtVerify").callsLength(0);
- client._("verifyCode").callsLength(0);
- client._("sign").callsLength(0);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId
- }
- });
-});
-
-add_test(function() {
- do_print("= No credentials - No icc - User MSISDN - External - KO -" +
- " INTERNAL_INVALID_PROMPT_RESULT =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let ui = new MockUi({
- startFlowResult: {}
- });
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore();
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_KO);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
- do_check_eq(aData.error, ERROR_INTERNAL_INVALID_PROMPT_RESULT);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(0);
- credStore._("add").callsLength(0);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("startFlow").call(1).arg(1, "");
- ui._("startFlow").call(1).arg(2, []);
- ui._("verifyCodePrompt").callsLength(0);
- ui._("verify").callsLength(0);
- ui._("error").callsLength(1);
- ui._("error").call(1).arg(1, ERROR_INTERNAL_INVALID_PROMPT_RESULT);
-
- // MockClient.
- client._("discover").callsLength(0);
- client._("register").callsLength(0);
- client._("smsMtVerify").callsLength(0);
- client._("verifyCode").callsLength(0);
- client._("sign").callsLength(0);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId
- }
- });
-});
-
-add_test(function() {
- do_print("= No credentials - No icc - User MSISDN - External - KO -" +
- " ERROR_INVALID_ASSERTION =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let ui = new MockUi();
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore();
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient({
- signResult: {
- cert: "aInvalidCert"
- },
- registerResult: {
- msisdnSessionToken: _sessionToken
- }
- });
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_KO);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
- do_check_eq(aData.error, ERROR_INVALID_ASSERTION);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(1);
- credStore._("getByMsisdn").call(1).arg(1, PHONE_NUMBER);
- credStore._("add").callsLength(1);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("startFlow").call(1).arg(1, "");
- ui._("startFlow").call(1).arg(2, []);
- ui._("verifyCodePrompt").callsLength(1);
- ui._("verifyCodePrompt").call(1).arg(1, 3);
- ui._("verify").callsLength(1);
- ui._("error").callsLength(1);
- ui._("error").call(1).arg(1, ERROR_INVALID_ASSERTION);
-
- // MockClient.
- client._("discover").callsLength(1);
- client._("discover").call(1).arg(1, PHONE_NUMBER);
- client._("register").callsLength(1);
- client._("smsMtVerify").callsLength(1);
- client._("smsMtVerify").call(1).arg(1, _sessionToken);
- client._("smsMtVerify").call(1).arg(2, PHONE_NUMBER);
- client._("smsMtVerify").call(1).arg(3, MNC);
- client._("smsMtVerify").call(1).arg(4, undefined);
- client._("smsMtVerify").call(1).arg(5, true);
- client._("verifyCode").callsLength(1);
- client._("verifyCode").call(1).arg(1, _sessionToken);
- client._("verifyCode").call(1).arg(2, {
- verificationCode: VERIFICATION_CODE
- });
- client._("sign").callsLength(1);
- client._("sign").call(1).arg(1, _sessionToken);
- client._("sign").call(1).arg(2, CERTIFICATE_LIFETIME);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId
- }
- });
-});
-
-add_test(function() {
- do_print("= Existing credentials - No Icc - Permission - OK result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let ui = new MockUi();
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: {
- sessionToken: SESSION_TOKEN,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: null
- }
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
-
- removePermission(ORIGIN);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= Existing credentials - No Icc - Prompt permission - OK result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let ui = new MockUi();
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: {
- sessionToken: SESSION_TOKEN,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: null
- }
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
-
- removePermission(ORIGIN);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- addPermission(Ci.nsIPermissionManager.PROMPT_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= Existing credentials - No Icc - Permission denied - KO result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let ui = new MockUi();
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: {
- sessionToken: SESSION_TOKEN,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: null
- }
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_KO);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
- do_check_eq(aData.error, ERROR_PERMISSION_DENIED);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(0);
-
- // MockUI.
- ui._("startFlow").callsLength(0);
- ui._("error").callsLength(0);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- removePermission(ORIGIN);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= Existing credentials - No Icc - SIM change/Same choice - " +
- "OK result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let ui = new MockUi();
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: {
- sessionToken: SESSION_TOKEN,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: [ICC_ID]
- }
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- MobileIdentityManager._iccInfo = [];
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("add").callsLength(1);
- credStore._("add").call(1).arg(1, undefined);
- credStore._("add").call(1).arg(2, PHONE_NUMBER);
- credStore._("add").call(1).arg(3, ORIGIN);
- credStore._("add").call(1).arg(4, SESSION_TOKEN);
- credStore._("add").call(1).arg(5, []);
- credStore._("setDeviceIccIds").callsLength(1);
- credStore._("setDeviceIccIds").call(1).arg(1, PHONE_NUMBER);
- credStore._("setDeviceIccIds").call(1).arg(2, []);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("verifyCodePrompt").callsLength(0);
- ui._("verify").callsLength(0);
-
- // MockClient.
- client._("discover").callsLength(0);
- client._("register").callsLength(0);
- client._("smsMtVerify").callsLength(0);
- client._("verifyCode").callsLength(0);
- client._("sign").callsLength(0);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= Existing credentials - No Icc - SIM change/Different choice - " +
- "OK result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let existingCredentials = {
- sessionToken: SESSION_TOKEN,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: [ICC_ID]
- };
-
- let ui = new MockUi({
- startFlowResult: {
- phoneNumber: ANOTHER_PHONE_NUMBER
- }
- });
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: existingCredentials
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient({
- verifyCodeResult: ANOTHER_PHONE_NUMBER,
- registerResult: {
- msisdnSessionToken: _sessionToken
- }
- });
- MobileIdentityManager.client = client;
-
- MobileIdentityManager._iccInfo = [];
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(1);
- credStore._("getByMsisdn").call(1).arg(1, ANOTHER_PHONE_NUMBER);
- credStore._("add").callsLength(1);
- credStore._("add").call(1).arg(1, undefined);
- credStore._("add").call(1).arg(2, ANOTHER_PHONE_NUMBER);
- credStore._("add").call(1).arg(3, ORIGIN);
- credStore._("add").call(1).arg(4, _sessionToken);
- credStore._("add").call(1).arg(5, []);
- credStore._("setDeviceIccIds").callsLength(0);
- credStore._("removeOrigin").callsLength(1);
- credStore._("removeOrigin").call(1).arg(1, PHONE_NUMBER);
- credStore._("removeOrigin").call(1).arg(2, ORIGIN);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("verifyCodePrompt").callsLength(1);
- ui._("verify").callsLength(1);
-
- // MockClient.
- client._("discover").callsLength(1);
- client._("register").callsLength(1);
- client._("smsMtVerify").callsLength(1);
- client._("verifyCode").callsLength(1);
- client._("sign").callsLength(1);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= Existing credentials - No Icc - forceSelection/same - " +
- "OK result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let existingCredentials = {
- sessionToken: _sessionToken,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: []
- };
-
- let ui = new MockUi({
- startFlowResult: {
- phoneNumber: PHONE_NUMBER
- }
- });
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: existingCredentials
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(0);
- credStore._("add").callsLength(1);
- credStore._("add").call(1).arg(1, undefined);
- credStore._("add").call(1).arg(2, PHONE_NUMBER);
- credStore._("add").call(1).arg(3, ORIGIN);
- credStore._("add").call(1).arg(4, _sessionToken);
- credStore._("add").call(1).arg(5, []);
- credStore._("setDeviceIccIds").callsLength(1);
- credStore._("removeOrigin").callsLength(0);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("verifyCodePrompt").callsLength(0);
- ui._("verify").callsLength(0);
-
- // MockClient.
- client._("discover").callsLength(0);
- client._("register").callsLength(0);
- client._("smsMtVerify").callsLength(0);
- client._("verifyCode").callsLength(0);
- client._("sign").callsLength(1);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {
- forceSelection: true
- }
- }
- });
-});
-add_test(function() {
- do_print("= Existing credentials - No Icc - forceSelection/different - " +
- "OK result =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let existingCredentials = {
- sessionToken: SESSION_TOKEN,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: []
- };
-
- let ui = new MockUi({
- startFlowResult: {
- phoneNumber: ANOTHER_PHONE_NUMBER
- }
- });
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: existingCredentials
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient({
- verifyCodeResult: ANOTHER_PHONE_NUMBER,
- registerResult: {
- msisdnSessionToken: _sessionToken
- }
- });
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(1);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(1);
- credStore._("getByMsisdn").call(1).arg(1, ANOTHER_PHONE_NUMBER);
- credStore._("add").callsLength(1);
- credStore._("add").call(1).arg(1, undefined);
- credStore._("add").call(1).arg(2, ANOTHER_PHONE_NUMBER);
- credStore._("add").call(1).arg(3, ORIGIN);
- credStore._("add").call(1).arg(4, _sessionToken);
- credStore._("add").call(1).arg(5, []);
- credStore._("setDeviceIccIds").callsLength(0);
- credStore._("removeOrigin").callsLength(1);
- credStore._("removeOrigin").call(1).arg(1, PHONE_NUMBER);
- credStore._("removeOrigin").call(1).arg(2, ORIGIN);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("verifyCodePrompt").callsLength(1);
- ui._("verify").callsLength(1);
-
- // MockClient.
- client._("discover").callsLength(1);
- client._("register").callsLength(1);
- client._("smsMtVerify").callsLength(1);
- client._("verifyCode").callsLength(1);
- client._("sign").callsLength(1);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {
- forceSelection: true
- }
- }
- });
-});
-
-add_test(function() {
- do_print("= Existing credentials - No Icc - INVALID_AUTH_TOKEN - OK =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let existingCredentials = {
- sessionToken: _sessionToken,
- msisdn: PHONE_NUMBER,
- origin: ORIGIN,
- deviceIccIds: []
- };
-
- let ui = new MockUi({
- startFlowResult: {
- phoneNumber: PHONE_NUMBER
- }
- });
- MobileIdentityManager.ui = ui;
- let credStore = new MockCredStore({
- getByOriginResult: [existingCredentials, null]
- });
- MobileIdentityManager.credStore = credStore;
- let client = new MockClient({
- signError: [ERROR_INVALID_AUTH_TOKEN],
- verifyCodeResult: PHONE_NUMBER,
- registerResult: {
- msisdnSessionToken: SESSION_TOKEN
- }
- });
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
-
- // Check spied calls.
-
- // MockCredStore.
- credStore._("getByOrigin").callsLength(2);
- credStore._("getByOrigin").call(1).arg(1, ORIGIN);
- credStore._("getByOrigin").call(2).arg(1, ORIGIN);
- credStore._("getByMsisdn").callsLength(1);
- credStore._("getByMsisdn").call(1).arg(1, PHONE_NUMBER);
- credStore._("add").callsLength(1);
- credStore._("add").call(1).arg(1, undefined);
- credStore._("add").call(1).arg(2, PHONE_NUMBER);
- credStore._("add").call(1).arg(3, ORIGIN);
- credStore._("add").call(1).arg(4, SESSION_TOKEN);
- credStore._("add").call(1).arg(5, []);
- credStore._("setDeviceIccIds").callsLength(0);
- credStore._("delete").callsLength(1);
- credStore._("delete").call(1).arg(1, PHONE_NUMBER);
-
- // MockUI.
- ui._("startFlow").callsLength(1);
- ui._("verifyCodePrompt").callsLength(1);
- ui._("verify").callsLength(1);
-
- // MockClient.
- client._("discover").callsLength(1);
- client._("register").callsLength(1);
- client._("smsMtVerify").callsLength(1);
- client._("verifyCode").callsLength(1);
- client._("sign").callsLength(1);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= ICC info change =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- MobileIdentityManager._iccInfo = null;
- MobileIdentityManager._iccIds = null;
-
- MobileIdentityManager._ril = {
- _interfaces: [RADIO_INTERFACE, ANOTHER_RADIO_INTERFACE],
- get numRadioInterfaces() {
- return this._interfaces.length;
- },
-
- getRadioInterface: function(aIndex) {
- return this._interfaces[aIndex];
- }
- };
-
- MobileIdentityManager._mobileConnectionService = {
- _interfaces: [RADIO_INTERFACE, ANOTHER_RADIO_INTERFACE],
- getItemByServiceId: function(aIndex) {
- return this._interfaces[aIndex];
- }
- };
-
- MobileIdentityManager._iccService = {
- _listeners: [],
- _iccInfos: [ICC_INFO, ANOTHER_ICC_INFO],
- getIccByServiceId: function(aClientId) {
- let self = this;
- return {
- get iccInfo() {
- return self._iccInfos[aClientId];
- },
- registerListener: function(aIccListener) {
- self._listeners.push(aIccListener);
- },
- unregisterListener: function() {
- self._listeners.pop();
- }
- };
- }
- };
-
- let ui = new MockUi();
- ui.startFlow = function() {
- // At this point we've already built the ICC cache.
- let mockIccInfo = [ICC_INFO, ANOTHER_ICC_INFO];
- for (let i = 0; i < mockIccInfo.length; i++) {
- let mIdIccInfo = MobileIdentityManager._iccInfo[i];
- do_check_eq(mockIccInfo[i].iccid, mIdIccInfo.iccId);
- do_check_eq(mockIccInfo[i].mcc, mIdIccInfo.mcc);
- do_check_eq(mockIccInfo[i].mnc, mIdIccInfo.mnc);
- do_check_eq(mockIccInfo[i].msisdn, mIdIccInfo.msisdn);
- do_check_eq(mockIccInfo[i].operator, mIdIccInfo.operator);
- }
-
- // We should have listeners for each valid icc.
- do_check_eq(MobileIdentityManager._iccService._listeners.length, 2);
-
- // We can mock an ICC change event at this point.
- MobileIdentityManager._iccService._listeners[0].notifyIccInfoChanged();
-
- // After the ICC change event the caches should be null.
- do_check_null(MobileIdentityManager._iccInfo);
- do_check_null(MobileIdentityManager._iccIds);
-
- // And we should have unregistered all listeners for ICC change events.
- do_check_eq(MobileIdentityManager._iccService._listeners.length, 0);
-
- do_test_finished();
- run_next_test();
- };
- MobileIdentityManager.ui = ui;
-
- let credStore = new MockCredStore();
- credStore.getByOrigin = function() {
- // Initially the ICC caches should be null.
- do_check_null(MobileIdentityManager._iccInfo);
- do_check_null(MobileIdentityManager._iccIds);
- return Promise.resolve(null);
- };
- MobileIdentityManager.credStore = credStore;
-
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function() {}
- };
-
- addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= Invalid ICC Info =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- MobileIdentityManager._iccInfo = null;
- MobileIdentityManager._iccIds = null;
-
- MobileIdentityManager._ril = {
- _interfaces: [INVALID_RADIO_INTERFACE],
- get numRadioInterfaces() {
- return this._interfaces.length;
- },
-
- getRadioInterface: function(aIndex) {
- return this._interfaces[aIndex];
- }
- };
-
- MobileIdentityManager._mobileConnectionService = {
- _interfaces: [INVALID_RADIO_INTERFACE],
- getItemByServiceId: function(aIndex) {
- return this._interfaces[aIndex];
- }
- };
-
- MobileIdentityManager._iccService = {
- _listeners: [],
- _iccInfos: [INVALID_ICC_INFO],
- getIccByServiceId: function(aClientId) {
- let self = this;
- return {
- get iccInfo() {
- return self._iccInfos[aClientId];
- },
- registerListener: function(aIccListener) {
- self._listeners.push(aIccListener);
- },
- unregisterListener: function() {
- self._listeners.pop();
- }
- };
- }
- };
-
- let ui = new MockUi();
- ui.startFlow = function() {
- // At this point we've already built the ICC cache.
- do_check_eq(MobileIdentityManager._iccInfo.length, 0);
- do_check_eq(MobileIdentityManager._iccIds.length, 0);
-
- // We should have listeners for each valid icc.
- do_check_eq(MobileIdentityManager._iccService._listeners.length, 0);
-
- do_test_finished();
- run_next_test();
- };
- MobileIdentityManager.ui = ui;
-
- let credStore = new MockCredStore();
- credStore.getByOrigin = function() {
- // Initially the ICC caches should be null.
- do_check_null(MobileIdentityManager._iccInfo);
- do_check_null(MobileIdentityManager._iccIds);
- return Promise.resolve(null);
- };
- MobileIdentityManager.credStore = credStore;
-
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function() {}
- };
-
- addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
-add_test(function() {
- do_print("= Cancel verification flow =");
-
- do_register_cleanup(cleanup);
-
- do_test_pending();
-
- let _sessionToken = Date.now();
-
- let ui = new MockUi();
- ui.verificationCodePrompt = function() {
- MobileIdentityManager.onUICancel();
- };
- MobileIdentityManager.ui = ui;
-
- let credStore = new MockCredStore();
- MobileIdentityManager.credStore = credStore;
-
- let client = new MockClient();
- MobileIdentityManager.client = client;
-
- let promiseId = Date.now();
- let mm = {
- sendAsyncMessage: function(aMsg, aData) {
- do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
-
- // Check result.
- do_check_eq(aMsg, GET_ASSERTION_RETURN_KO);
- do_check_eq(typeof aData, "object");
- do_check_eq(aData.promiseId, promiseId);
- do_check_eq(aData.error, DIALOG_CLOSED_BY_USER);
-
- do_test_finished();
- run_next_test();
- }
- };
-
- addPermission(Ci.nsIPermissionManager.ALLOW_ACTION);
-
- MobileIdentityManager.receiveMessage({
- name: GET_ASSERTION_IPC_MSG,
- principal: PRINCIPAL,
- target: mm,
- json: {
- promiseId: promiseId,
- options: {}
- }
- });
-});
-
deleted file mode 100644
--- a/services/mobileid/tests/xpcshell/test_mobileid_verification_flow.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Cu.import("resource://gre/modules/MobileIdentityVerificationFlow.jsm");
-
-function verifyStrategy() {
- return Promise.resolve();
-}
-
-function cleanupStrategy() {
-}
-
-function run_test() {
- do_print("= Bug 1101444: Invalid verification code shouldn't restart " +
- "verification flow =");
-
- let client = new MockClient({
- // This will emulate two invalid attempts. The third time it will work.
- verifyCodeError: ["INVALID", "INVALID"]
- });
- let ui = new MockUi();
-
- let verificationFlow = new MobileIdentityVerificationFlow({
- external: true,
- sessionToken: SESSION_TOKEN,
- msisdn: PHONE_NUMBER
- }, ui, client, verifyStrategy, cleanupStrategy);
-
- verificationFlow.doVerification().then(() => {
- // We should only do the registration process once. We only try registering
- // again when the timeout fires, but not when we enter an invalid
- // verification code.
- client._("register").callsLength(1);
- client._("verifyCode").callsLength(3);
- // Because we do two invalid attempts, we should show the invalid code error twice.
- ui._("error").callsLength(2);
- });
-
- do_test_finished();
-};
deleted file mode 100644
--- a/services/mobileid/tests/xpcshell/xpcshell.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[DEFAULT]
-head = head.js
-tail =
-
-[test_mobileid_manager.js]
-skip-if = 1
-[test_mobileid_client.js]
-[test_mobileid_verification_flow.js]
--- a/services/moz.build
+++ b/services/moz.build
@@ -10,13 +10,10 @@ DIRS += [
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
DIRS += ['fxaccounts']
if CONFIG['MOZ_SERVICES_SYNC']:
DIRS += ['sync']
-if CONFIG['MOZ_B2G']:
- DIRS += ['mobileid']
-
if CONFIG['MOZ_SERVICES_CLOUDSYNC']:
DIRS += ['cloudsync']
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -37651,16 +37651,22 @@
}
],
"domparsing/style_attribute_html.html": [
{
"path": "domparsing/style_attribute_html.html",
"url": "/domparsing/style_attribute_html.html"
}
],
+ "editing/other/delete.html": [
+ {
+ "path": "editing/other/delete.html",
+ "url": "/editing/other/delete.html"
+ }
+ ],
"html/semantics/forms/the-form-element/form-submission-sandbox.html": [
{
"path": "html/semantics/forms/the-form-element/form-submission-sandbox.html",
"url": "/html/semantics/forms/the-form-element/form-submission-sandbox.html"
}
],
"web-animations/timing-model/animation-effects/phases-and-states.html": [
{
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/editing/other/delete.html.ini
@@ -0,0 +1,14 @@
+[delete.html]
+ type: testharness
+ [2: "<p><br></p><p><br></p>" 0,0-1,0 delete]
+ expected: FAIL
+
+ [3: "<p><br></p><p><br></p>" 0,0-1,0 forwarddelete]
+ expected: FAIL
+
+ [4: "<p><br></p><p><br></p>" 1,0-0,0 delete]
+ expected: FAIL
+
+ [5: "<p><br></p><p><br></p>" 1,0-0,0 forwarddelete]
+ expected: FAIL
+
--- a/testing/web-platform/tests/editing/README
+++ b/testing/web-platform/tests/editing/README
@@ -1,9 +1,14 @@
-This suite tests conformance to the editing spec written long ago by Aryeh
-Gregor. Nobody actually implements the spec, but the tests are still useful
-for regression testing. The files in data/ were generated from a JavaScript
-implementation of the specification using a complex procedure that can't
-actually be replicated right now as-is. Editing them manually is possible, but
-they're not really meant to be human-readable. If anyone is interested, it
-would be possible for Aryeh to get the test generation procedure working again.
-Or you could look into the repository history and figure out how to do it
-yourself, if you're brave.
+Most of this directory tests conformance to the editing spec written long ago
+by Aryeh Gregor. Nobody actually implements the spec, but the tests are still
+useful for regression testing. The files in data/ were generated from a
+JavaScript implementation of the specification using a complex procedure that
+can't actually be replicated right now as-is. Editing them manually is
+possible, but they're not really meant to be human-readable. If anyone is
+interested, it would be possible for Aryeh to get the test generation procedure
+working again. Or you could look into the repository history and figure out
+how to do it yourself, if you're brave.
+
+There is also a directory other/ that contains additional editor-related tests.
+They aren't necessarily based on any specification, but try to specify sensible
+behavior, and are meant to be helpful with regression testing for existing
+implementations and finding bugs in new implementations.
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/editing/other/delete.html
@@ -0,0 +1,149 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Deletion tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div contenteditable></div>
+<script>
+var div = document.querySelector("div");
+
+// Format: [start html, start pos, expected html, expected pos, command]
+// Positions are a sequence of offsets starting from div, e.g., "1,2,0"
+// translates to node = div.childNodes[1].childNodes[2], offset = 0. For a
+// non-collapsed selection, use a hyphen, like "0,0-1,0". The selections are
+// created with collapse() followed by extend() to allow reverse selections, so
+// order is significant.
+//
+// Expected values can be arrays, in which case any is acceptable.
+var tests = [
+ ["<p><br></p><p><br></p>", "1,0", "<p><br></p>", "0,0", "delete"],
+ ["<p><br></p><p><br></p>", "0,0", "<p><br></p>", "0,0", "forwarddelete"],
+
+ // Range
+ ["<p><br></p><p><br></p>", "0,0-1,0", "<p><br></p>", "0,0", "delete"],
+ ["<p><br></p><p><br></p>", "0,0-1,0", "<p><br></p>", "0,0", "forwarddelete"],
+ ["<p><br></p><p><br></p>", "1,0-0,0", "<p><br></p>", "0,0", "delete"],
+ ["<p><br></p><p><br></p>", "1,0-0,0", "<p><br></p>", "0,0", "forwarddelete"],
+
+ // Different start values
+ ["<p>x<br></p><p><br></p>", "1,0",
+ // WebKit/Blink like to get rid of the extra <br>
+ ["<p>x<br></p>", "<p>x</p>"],
+ // The selection should really be collapsed inside the text node, but in the
+ // parent is close enough.
+ ["0,0,1", "0,1"], "delete"],
+ ["<p><br><br></p><p><br></p>", "1,0", "<p><br><br></p>", "0,1", "delete"],
+ ["<p><br></p><p><br><br></p>", "1,1",
+ "<p><br></p><p><br></p>", "1,0", "delete"],
+ ["<p><br><br><br></p>", "0,2", "<p><br><br></p>", "0,1", "delete"],
+ ["<p><br></p><p><br><br><br></p>", "1,2",
+ "<p><br></p><p><br><br></p>", "1,1", "delete"],
+ ["<p><br><br></p><p><br><br></p>", "1,1",
+ "<p><br><br></p><p><br></p>", "1,0", "delete"],
+ ["<p><br></p><br>", "1", "<p><br></p>", "0,0", "delete"],
+
+ // The trailing \n in these cases is actually significant, because it was
+ // necessary to trigger an actual Gecko bug (somehow!).
+ ["<p><br></p><p><br></p>\n", "1,0", "<p><br></p>\n", "0,0", "delete"],
+ ["<p><br></p><p><br></p>\n", "0,0", "<p><br></p>\n", "0,0", "forwarddelete"],
+ ["\n<p><tt>x</tt></p><p><tt><br></tt></p><p><tt><br></tt></p>\n", "3,0,0",
+ "\n<p><tt>x</tt></p><p><tt><br></tt></p>\n", "2,0,0", "delete"],
+];
+
+div.focus();
+
+for (var i = 0; i < tests.length; i++) {
+ test(function() {
+ var test = tests[i];
+ div.innerHTML = test[0];
+ setSelection(test[1]);
+
+ document.execCommand(test[4], false, "");
+
+ if (typeof test[2] == "string") {
+ assert_equals(div.innerHTML, test[2], "innerHTML");
+ } else {
+ assert_in_array(div.innerHTML, test[2], "innerHTML");
+ }
+
+ var actualSel = recordSelection();
+ var expectedSel = [];
+ if (typeof test[3] == "string") {
+ test[3] = [test[3]];
+ }
+ for (var j = 0; j < test[3].length; j++) {
+ setSelection(test[3][j]);
+ expectedSel.push(recordSelection());
+ }
+ assertSelectionEquals(actualSel, expectedSel, test[2]);
+ }, i + ": " + format_value(tests[i][0]) + " " + tests[i][1] +
+ " " + tests[i][4]);
+}
+
+function setSelection(selstr) {
+ var parts = selstr.split("-");
+ var collapsePoint = getPointFromArray(parts[0].split(","));
+ getSelection().collapse(collapsePoint[0], collapsePoint[1]);
+
+ if (parts[1]) {
+ var extendPoint = getPointFromArray(parts[1].split(","));
+ getSelection().extend(extendPoint[0], extendPoint[1]);
+ }
+}
+
+function getPointFromArray(offsets) {
+ var retNode = div, retOffset;
+ var offset;
+ while (offset = offsets.shift()) {
+ if (!offsets.length) {
+ retOffset = offset;
+ } else {
+ retNode = retNode.childNodes[offset];
+ }
+ }
+ return [retNode, retOffset];
+}
+
+function recordSelection() {
+ return [getSelection().anchorNode, getSelection().anchorOffset,
+ getSelection().focusNode, getSelection().focusOffset];
+}
+
+function assertSelectionEquals(actual, expected, html) {
+ if (typeof expected == "string") {
+ expected = [expected];
+ }
+ var pass = false;
+ for (var i = 0; i < expected.length; i++) {
+ if (expected[i][0] === actual[0] &&
+ expected[i][1] === actual[1] &&
+ expected[i][2] === actual[2] &&
+ expected[i][3] === actual[3]) {
+ pass = true;
+ break;
+ }
+ }
+
+ assert_true(pass, "Wrong selection, expected " + formatSel(expected) +
+ ", got " + formatSel(actual) +
+ " (in HTML " + format_value(html) + ")");
+}
+
+function formatSel(arr) {
+ if (arr.length == 1) {
+ arr = arr[0];
+ }
+ if (Array.isArray(arr[0])) {
+ var ret = [];
+ for (var i = 0; i < arr.length; i++) {
+ ret.push(formatSel(arr[i]));
+ }
+ return ret.join(" or ");
+ }
+ if (arr[0] == arr[2] && arr[1] == arr[3]) {
+ return "collapsed (" + format_value(arr[0]) + ", " + arr[1] + ")";
+ }
+ return "(" + format_value(arr[0]) + ", " + arr[1] +
+ ")-(" + format_value(arr[2]) + ", " + arr[3] + ")";
+}
+</script>