VulpesOS/gaia/shared/js/fxa_iac_client.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

243 lines
6.3 KiB
JavaScript
Executable file

/* exported FxAccountsIACHelper */
'use strict';
// Firefox Accounts IAC client
var FxAccountsIACHelper = function FxAccountsIACHelper() {
var DEFAULT_CONNECTION_STRING = 'fxa-mgmt';
var default_rules = {
'manifestURLs': ['app://system.gaiamobile.org/manifest.webapp',
'app://smart-system.gaiamobile.org/manifest.webapp']
};
var CONNECTION_STRING = DEFAULT_CONNECTION_STRING;
var rules = default_rules;
var port;
// callbacks is a set of arrays containing {successCb, errorCb} pairs,
// keyed on the method name, for example, callbacks.getAccount.
var callbacks = {};
var eventListeners = {};
// Overrides the default configuration, if needed
var init = function init(options) {
if (!options) {
return;
}
if (options.keyword &&
typeof(options.keyword) == 'string' &&
options.keyword.length > 0) {
CONNECTION_STRING = options.keyword;
}
if (options.rules && typeof(options.rules) == 'object') {
rules = options.rules;
}
};
var addEventListener = function addEventListener(eventName, listener) {
if (!eventListeners[eventName]) {
eventListeners[eventName] = [];
}
eventListeners[eventName].push(listener);
};
var removeEventListener = function removeEventListener(eventName, listener) {
var listeners = eventListeners[eventName];
if (!listeners) {
return;
}
var index = listeners.indexOf(listener);
if (index === -1) {
return;
}
listeners.splice(index, 1);
};
// Reset to default values, could clean any future option
var reset = function reset() {
CONNECTION_STRING = DEFAULT_CONNECTION_STRING;
rules = default_rules;
eventListeners = {};
callbacks = {};
port = null;
};
var onMessage = function onMessage(evt) {
if (evt && evt.data) {
var message = evt.data;
if (message.eventName) {
var listeners = eventListeners[message.eventName];
if (!listeners) {
return;
}
for (var listener in listeners) {
if (listeners[listener] &&
typeof listeners[listener] === 'function') {
listeners[listener]();
}
}
return;
}
var cbs, cb;
if (message.methodName) {
cbs = callbacks[message.methodName];
if (!cbs || !cbs.length) {
console.warn('No callbacks for method ' + message.methodName);
return;
}
while (cbs.length) {
cb = cbs.shift();
if (!message.error) {
cb.successCb(message.data);
} else {
cb.errorCb(message.error);
}
}
}
} else {
console.error('Unknown');
}
};
// Get a reference to the application object to be able to invoke IAC.
var getSelf = function getSelf(cb, error) {
var request = navigator.mozApps.getSelf();
request.onsuccess = function onSuccess(evt) {
cb(evt.target.result);
};
request.onerror = function onError() {
if (error && typeof(error) === 'function') {
error();
}
};
};
var requestQueue = [];
var isConnecting = false;
var connect = function connect(cb) {
if (isConnecting) {
return requestQueue.push(cb);
}
isConnecting = true;
_connect(function onConnect(err) {
var next;
isConnecting = false;
if (typeof cb === 'function') {
cb(err);
}
while (!!(next = requestQueue.shift())) {
next && next(err);
}
});
};
var _connect = function _connect(callback) {
getSelf(function onApp(app) {
if (!app) {
return;
}
app.connect(CONNECTION_STRING, rules).then(function(ports) {
if (!ports || ports.length !== 1) {
return;
}
port = ports[0];
callback && callback();
}).catch(function(error) { callback && callback(error); });
});
};
var sendMessage = function sendMessage(message, successCb, errorCb) {
if (port) {
_sendMessage(message, successCb, errorCb);
return;
}
connect(function(error) {
if (error) { errorCb && errorCb(error); return; }
_sendMessage(message, successCb, errorCb);
});
};
// Sends the specific message via IAC to the system app.
// Will be always using the default keyword and forcing it
// to a single manifest.
var _sendMessage = function _sendMessage(message, successCb, errorCb) {
var name = message.name;
if (!name) {
return;
}
if (!callbacks[name]) {
callbacks[name] = [];
}
callbacks[name].push({
successCb: successCb,
errorCb: errorCb
});
// We set onmessage here again cause it is the only way that we have to
// trigger it during the tests. It sucks but it is harmless.
port.onmessage = onMessage;
port.postMessage(message);
};
var getAccount = function getAccount(successCb, errorCb) {
sendMessage({
'name': 'getAccount'
}, successCb, errorCb);
};
var openFlow = function openFlow(successCb, errorCb) {
sendMessage({
'name': 'openFlow'
}, successCb, errorCb);
};
var logout = function logout(successCb, errorCb) {
sendMessage({
'name': 'logout'
}, successCb, errorCb);
};
var refreshAuthentication = function refreshAuthentication(email,
successCb,
errorCb) {
sendMessage({
'name': 'refreshAuthentication',
'email': email
}, successCb, errorCb);
};
var resendVerificationEmail = function resendVerificationEmail(email,
successCb,
errorCb) {
sendMessage({
'name': 'resendVerificationEmail',
'email': email
}, successCb, errorCb);
};
// We do an early connection to be able to get the unsolicited events coming
// from the platform (onlogin, onverifiedlogin, onlogout).
connect();
return {
'addEventListener': addEventListener,
'getAccount': getAccount,
'init': init,
'logout': logout,
'openFlow': openFlow,
'refreshAuthentication': refreshAuthentication,
'removeEventListener': removeEventListener,
'resendVerificationEmail': resendVerificationEmail,
'reset': reset
};
}();