mirror of
https://github.com/roytam1/boc-uxp.git
synced 2021-11-05 16:13:16 +00:00
298 lines
9.2 KiB
JavaScript
298 lines
9.2 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
this.EXPORTED_SYMBOLS = ["cloudFileAccounts"];
|
|
|
|
var Cc = Components.classes;
|
|
var Ci = Components.interfaces;
|
|
var Cu = Components.utils;
|
|
var Cr = Components.results;
|
|
|
|
var CATEGORY = "cloud-files";
|
|
var PREF_ROOT = "mail.cloud_files.";
|
|
var ACCOUNT_ROOT = PREF_ROOT + "accounts.";
|
|
|
|
// The following constants are used to query and insert entries
|
|
// into the nsILoginManager.
|
|
var PWDMGR_HOST = "chrome://messenger/cloudfile";
|
|
var PWDMGR_REALM = "BigFiles Auth Token";
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource:///modules/iteratorUtils.jsm");
|
|
|
|
var cloudFileAccounts = {
|
|
get kTokenRealm() {
|
|
return PWDMGR_REALM;
|
|
},
|
|
|
|
get _accountKeys() {
|
|
let accountKeySet = {};
|
|
let branch = Services.prefs.getBranch(ACCOUNT_ROOT);
|
|
let children = branch.getChildList("", {});
|
|
for (let child of children) {
|
|
let subbranch = child.substr(0, child.indexOf("."));
|
|
accountKeySet[subbranch] = 1;
|
|
}
|
|
|
|
// TODO: sort by ordinal
|
|
return Object.keys(accountKeySet);
|
|
},
|
|
|
|
_getInitedProviderForType: function(aAccountKey, aType) {
|
|
let provider = this.getProviderForType(aType);
|
|
if (provider) {
|
|
try {
|
|
provider.init(aAccountKey);
|
|
} catch (e) {
|
|
Components.utils.reportError(e);
|
|
provider = null;
|
|
}
|
|
}
|
|
return provider;
|
|
},
|
|
|
|
_createUniqueAccountKey: function() {
|
|
// Pick a unique account key (TODO: this is a dumb way to do it, probably)
|
|
let existingKeys = this._accountKeys;
|
|
for (let n = 1; ; n++) {
|
|
|
|
if (!existingKeys.includes("account" + n))
|
|
return "account" + n;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Ensure that we have the account key for an account. If we already have the
|
|
* key, just return it. If we have the nsIMsgCloudFileProvider, get the key
|
|
* from it.
|
|
*
|
|
* @param aKeyOrAccount the key or the account object
|
|
* @return the account key
|
|
*/
|
|
_ensureKey: function(aKeyOrAccount) {
|
|
if (typeof aKeyOrAccount == "string")
|
|
return aKeyOrAccount;
|
|
else if ("accountKey" in aKeyOrAccount)
|
|
return aKeyOrAccount.accountKey;
|
|
else
|
|
throw new Error("string or nsIMsgCloudFileProvider expected");
|
|
},
|
|
|
|
getProviderForType: function(aType) {
|
|
try {
|
|
let className = categoryManager.getCategoryEntry(CATEGORY, aType);
|
|
let provider = Cc[className].createInstance(Ci.nsIMsgCloudFileProvider);
|
|
return provider;
|
|
} catch (e) {
|
|
if (e.result != Cr.NS_ERROR_NOT_AVAILABLE) {
|
|
// If a provider is not available we swallow the error message.
|
|
// Otherwise at least notify, so developers can fix things.
|
|
Cu.reportError("Getting provider for type=" + aType + " FAILED; " + e);
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
// aExtraPrefs are prefs specific to an account provider.
|
|
createAccount: function(aType, aRequestObserver, aExtraPrefs) {
|
|
let key = this._createUniqueAccountKey();
|
|
|
|
try {
|
|
Services.prefs
|
|
.setCharPref(ACCOUNT_ROOT + key + ".type", aType);
|
|
|
|
if (aExtraPrefs !== undefined)
|
|
this._processExtraPrefs(key, aExtraPrefs);
|
|
|
|
let provider = this._getInitedProviderForType(key, aType);
|
|
if (provider)
|
|
provider.createExistingAccount(aRequestObserver);
|
|
|
|
return provider;
|
|
}
|
|
catch(e) {
|
|
Services.prefs.deleteBranch(ACCOUNT_ROOT + key);
|
|
throw e;
|
|
}
|
|
},
|
|
|
|
// Set provider-specific prefs
|
|
_processExtraPrefs: function CFA__processExtraPrefs(aAccountKey,
|
|
aExtraPrefs) {
|
|
const kFuncMap = {
|
|
"int": "setIntPref",
|
|
"bool": "setBoolPref",
|
|
"char": "setCharPref",
|
|
};
|
|
|
|
for (let prefKey in aExtraPrefs) {
|
|
let type = aExtraPrefs[prefKey].type;
|
|
let value = aExtraPrefs[prefKey].value;
|
|
|
|
if (!(type in kFuncMap)) {
|
|
Components.utils.reportError("Did not recognize type: " + type);
|
|
continue;
|
|
}
|
|
|
|
let func = kFuncMap[type];
|
|
Services.prefs[func](ACCOUNT_ROOT + aAccountKey + "." + prefKey,
|
|
value);
|
|
}
|
|
},
|
|
|
|
enumerateProviders: function*() {
|
|
for (let entry in fixIterator(categoryManager.enumerateCategory(CATEGORY),
|
|
Ci.nsISupportsCString)) {
|
|
let provider = this.getProviderForType(entry.data);
|
|
yield [entry.data, provider];
|
|
}
|
|
},
|
|
|
|
getAccount: function(aKey) {
|
|
let type = Services.prefs.QueryInterface(Ci.nsIPrefBranch)
|
|
.getCharPref(ACCOUNT_ROOT + aKey + ".type");
|
|
return this._getInitedProviderForType(aKey, type);
|
|
},
|
|
|
|
removeAccount: function(aKeyOrAccount) {
|
|
let key = this._ensureKey(aKeyOrAccount);
|
|
|
|
let type = Services.prefs.QueryInterface(Ci.nsIPrefBranch)
|
|
.deleteBranch(ACCOUNT_ROOT + key);
|
|
|
|
// Destroy any secret tokens for this accountKey.
|
|
let logins = Services.logins
|
|
.findLogins({}, PWDMGR_HOST, null, "");
|
|
for (let login of logins) {
|
|
if (login.username == key)
|
|
Services.logins.removeLogin(login);
|
|
}
|
|
},
|
|
|
|
get accounts() {
|
|
return this._accountKeys.filter(key => this.getAccount(key) != null).
|
|
map(key => this.getAccount(key));
|
|
},
|
|
|
|
getAccountsForType: function CFA_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;
|
|
},
|
|
|
|
addAccountDialog: function CFA_addAccountDialog() {
|
|
let params = {accountKey: null};
|
|
Services.wm
|
|
.getMostRecentWindow(null)
|
|
.openDialog("chrome://messenger/content/cloudfile/"
|
|
+ "addAccountDialog.xul",
|
|
"", "chrome, dialog, modal, resizable=yes",
|
|
params).focus();
|
|
return params.accountKey;
|
|
},
|
|
|
|
getDisplayName: function(aKeyOrAccount) {
|
|
try {
|
|
let key = this._ensureKey(aKeyOrAccount);
|
|
return Services.prefs.getCharPref(ACCOUNT_ROOT +
|
|
key + ".displayName");
|
|
} catch(e) {
|
|
// If no display name has been set, we return the empty string.
|
|
Components.utils.reportError(e);
|
|
return "";
|
|
}
|
|
},
|
|
|
|
setDisplayName: function(aKeyOrAccount, aDisplayName) {
|
|
let key = this._ensureKey(aKeyOrAccount);
|
|
Services.prefs.setCharPref(ACCOUNT_ROOT + key +
|
|
".displayName", aDisplayName);
|
|
},
|
|
|
|
/**
|
|
* Retrieve a secret value, like an authorization token, for an account.
|
|
*
|
|
* @param aKeyOrAccount an nsIMsgCloudFileProvider, or an accountKey
|
|
* for a provider.
|
|
* @param aRealm a human-readable string describing what exactly
|
|
* was being stored. Should match the realm used when setting
|
|
* the value.
|
|
*/
|
|
getSecretValue: function(aKeyOrAccount, aRealm) {
|
|
let key = this._ensureKey(aKeyOrAccount);
|
|
|
|
let loginInfo = this._getLoginInfoForKey(key, aRealm);
|
|
|
|
if (loginInfo)
|
|
return loginInfo.password;
|
|
|
|
return null;
|
|
},
|
|
|
|
/**
|
|
* Store a secret value, like an authorization token, for an account
|
|
* in nsILoginManager.
|
|
*
|
|
* @param aKeyOrAccount an nsIMsgCloudFileProvider, or an accountKey
|
|
* for a provider.
|
|
* @param aRealm a human-readable string describing what exactly
|
|
* is being stored here. To reduce magic strings, you can use
|
|
* cloudFileAccounts.kTokenRealm for simple auth tokens, and
|
|
* anything else for custom secret values.
|
|
* @param aToken The token to be saved. If this is set to null or the
|
|
* empty string, then the entry for this key will be removed.
|
|
*/
|
|
setSecretValue: function(aKeyOrAccount, aRealm, aToken) {
|
|
let key = this._ensureKey(aKeyOrAccount);
|
|
let loginInfo = this._getLoginInfoForKey(key, aRealm);
|
|
|
|
if (!aToken) {
|
|
if (!loginInfo)
|
|
return;
|
|
|
|
Services.logins.removeLogin(loginInfo);
|
|
return;
|
|
}
|
|
|
|
let newLoginInfo = Cc["@mozilla.org/login-manager/loginInfo;1"]
|
|
.createInstance(Ci.nsILoginInfo);
|
|
newLoginInfo.init(PWDMGR_HOST, null, aRealm, key,
|
|
aToken, "", "");
|
|
|
|
if (loginInfo)
|
|
Services.logins.modifyLogin(loginInfo, newLoginInfo);
|
|
else
|
|
Services.logins.addLogin(newLoginInfo);
|
|
},
|
|
|
|
/**
|
|
* Searches the nsILoginManager for an nsILoginInfo for BigFiles with
|
|
* the username set to aKey, and the realm set to aRealm.
|
|
*
|
|
* @param aKey a key for an nsIMsgCloudFileProvider that we're searching
|
|
* for login info for.
|
|
* @param aRealm the realm that the login info was stored under.
|
|
*/
|
|
_getLoginInfoForKey: function(aKey, aRealm) {
|
|
let logins = Services.logins
|
|
.findLogins({}, PWDMGR_HOST, null, aRealm);
|
|
for (let login of logins) {
|
|
if (login.username == aKey)
|
|
return login;
|
|
}
|
|
return null;
|
|
},
|
|
};
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, "categoryManager",
|
|
"@mozilla.org/categorymanager;1",
|
|
"nsICategoryManager");
|