summaryrefslogtreecommitdiffstats
path: root/comm/mail/components/cloudfile/cloudFileAccounts.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/components/cloudfile/cloudFileAccounts.jsm')
-rw-r--r--comm/mail/components/cloudfile/cloudFileAccounts.jsm215
1 files changed, 215 insertions, 0 deletions
diff --git a/comm/mail/components/cloudfile/cloudFileAccounts.jsm b/comm/mail/components/cloudfile/cloudFileAccounts.jsm
new file mode 100644
index 0000000000..3cb478f60f
--- /dev/null
+++ b/comm/mail/components/cloudfile/cloudFileAccounts.jsm
@@ -0,0 +1,215 @@
+/* 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 EXPORTED_SYMBOLS = ["cloudFileAccounts"];
+
+var ACCOUNT_ROOT = "mail.cloud_files.accounts.";
+
+var { EventEmitter } = ChromeUtils.importESModule(
+ "resource://gre/modules/EventEmitter.sys.mjs"
+);
+
+var cloudFileAccounts = new (class extends EventEmitter {
+ get constants() {
+ return {
+ offlineErr: 0x80550014, // NS_MSG_ERROR_OFFLINE
+ authErr: 0x8055001e, // NS_MSG_USER_NOT_AUTHENTICATED
+ uploadErr: 0x8055311a, // NS_MSG_ERROR_ATTACHING_FILE
+ uploadWouldExceedQuota: 0x8055311b,
+ uploadExceedsFileLimit: 0x8055311c,
+ uploadCancelled: 0x8055311d,
+ uploadErrWithCustomMessage: 0x8055311f,
+ renameErr: 0x80553120,
+ renameErrWithCustomMessage: 0x80553121,
+ renameNotSupported: 0x80553122,
+ deleteErr: 0x80553123,
+ attachmentErr: 0x80553124,
+ accountErr: 0x80553125,
+ };
+ }
+
+ constructor() {
+ super();
+ this._providers = new Map();
+ this._accounts = new Map();
+ this._highestOrdinal = 0;
+ }
+
+ get _accountKeys() {
+ let accountKeySet = new Set();
+ let branch = Services.prefs.getBranch(ACCOUNT_ROOT);
+ let children = branch.getChildList("");
+ for (let child of children) {
+ let subbranch = child.substr(0, child.indexOf("."));
+ accountKeySet.add(subbranch);
+
+ let match = /^account(\d+)$/.exec(subbranch);
+ if (match) {
+ let ordinal = parseInt(match[1], 10);
+ this._highestOrdinal = Math.max(this._highestOrdinal, ordinal);
+ }
+ }
+
+ // TODO: sort by ordinal
+ return accountKeySet.keys();
+ }
+
+ /**
+ * Ensure that we have the account key for an account. If we already have the
+ * key, just return it. If we have the account, get the key from it.
+ *
+ * @param aKeyOrAccount the key or the account object
+ * @returns the account key
+ */
+ _ensureKey(aKeyOrAccount) {
+ if (typeof aKeyOrAccount == "string") {
+ return aKeyOrAccount;
+ }
+ if ("accountKey" in aKeyOrAccount) {
+ return aKeyOrAccount.accountKey;
+ }
+ throw new Error("String or cloud file account expected");
+ }
+
+ /**
+ * Register a cloudfile provider, e.g. from an extension.
+ *
+ * @param {object} The implementation to register
+ */
+ registerProvider(aType, aProvider) {
+ if (this._providers.has(aType)) {
+ throw new Error(`Cloudfile provider ${aType} is already registered`);
+ }
+ this._providers.set(aType, aProvider);
+ this.emit("providerRegistered", aProvider);
+ }
+
+ /**
+ * Unregister a cloudfile provider.
+ *
+ * @param {string} aType - The provider type to unregister
+ */
+ unregisterProvider(aType) {
+ if (!this._providers.has(aType)) {
+ throw new Error(`Cloudfile provider ${aType} is not registered`);
+ }
+
+ for (let account of this.getAccountsForType(aType)) {
+ this._accounts.delete(account.accountKey);
+ }
+
+ this._providers.delete(aType);
+ this.emit("providerUnregistered", aType);
+ }
+
+ get providers() {
+ return [...this._providers.values()];
+ }
+
+ getProviderForType(aType) {
+ return this._providers.get(aType);
+ }
+
+ createAccount(aType) {
+ this._highestOrdinal++;
+ let key = "account" + this._highestOrdinal;
+
+ try {
+ let provider = this.getProviderForType(aType);
+ let account = provider.initAccount(key);
+
+ Services.prefs.setCharPref(ACCOUNT_ROOT + key + ".type", aType);
+ Services.prefs.setCharPref(
+ ACCOUNT_ROOT + key + ".displayName",
+ account.displayName
+ );
+
+ this._accounts.set(key, account);
+ this.emit("accountAdded", account);
+ return account;
+ } catch (e) {
+ for (let prefName of Services.prefs.getChildList(
+ `${ACCOUNT_ROOT}${key}.`
+ )) {
+ Services.prefs.clearUserPref(prefName);
+ }
+ throw e;
+ }
+ }
+
+ removeAccount(aKeyOrAccount) {
+ let key = this._ensureKey(aKeyOrAccount);
+ let type = Services.prefs.getCharPref(ACCOUNT_ROOT + key + ".type");
+
+ this._accounts.delete(key);
+ for (let prefName of Services.prefs.getChildList(
+ `${ACCOUNT_ROOT}${key}.`
+ )) {
+ Services.prefs.clearUserPref(prefName);
+ }
+
+ this.emit("accountDeleted", key, type);
+ }
+
+ get accounts() {
+ let arr = [];
+ for (let key of this._accountKeys) {
+ let account = this.getAccount(key);
+ if (account) {
+ arr.push(account);
+ }
+ }
+ return arr;
+ }
+
+ get configuredAccounts() {
+ return this.accounts.filter(account => account.configured);
+ }
+
+ getAccount(aKey) {
+ if (this._accounts.has(aKey)) {
+ return this._accounts.get(aKey);
+ }
+
+ let type = Services.prefs.getCharPref(ACCOUNT_ROOT + aKey + ".type", "");
+ if (type) {
+ let provider = this.getProviderForType(type);
+ if (provider) {
+ let account = provider.initAccount(aKey);
+ this._accounts.set(aKey, account);
+ return account;
+ }
+ }
+ return null;
+ }
+
+ getAccountsForType(aType) {
+ let result = [];
+
+ for (let accountKey of this._accountKeys) {
+ let type = Services.prefs.getCharPref(
+ ACCOUNT_ROOT + accountKey + ".type"
+ );
+ if (type === aType) {
+ result.push(this.getAccount(accountKey));
+ }
+ }
+
+ return result;
+ }
+
+ getDisplayName(aKeyOrAccount) {
+ // If no display name has been set, we return the empty string.
+ let key = this._ensureKey(aKeyOrAccount);
+ return Services.prefs.getCharPref(ACCOUNT_ROOT + key + ".displayName", "");
+ }
+
+ setDisplayName(aKeyOrAccount, aDisplayName) {
+ let key = this._ensureKey(aKeyOrAccount);
+ Services.prefs.setCharPref(
+ ACCOUNT_ROOT + key + ".displayName",
+ aDisplayName
+ );
+ }
+})();