mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
174 lines
6 KiB
JavaScript
174 lines
6 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/. */
|
|
|
|
"use strict";
|
|
|
|
var Cc = Components.classes;
|
|
var Ci = Components.interfaces;
|
|
var Cr = Components.results;
|
|
|
|
Components.utils.import("resource://gre/modules/OAuth2.jsm");
|
|
Components.utils.import("resource://gre/modules/OAuth2Providers.jsm");
|
|
Components.utils.import("resource://gre/modules/Preferences.jsm");
|
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
function OAuth2Module() {
|
|
this._refreshToken = '';
|
|
}
|
|
OAuth2Module.prototype = {
|
|
// XPCOM registration stuff
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.msgIOAuth2Module]),
|
|
classID: Components.ID("{b63d8e4c-bf60-439b-be0e-7c9f67291042}"),
|
|
|
|
_loadOAuthClientDetails(aIssuer) {
|
|
let details = OAuth2Providers.getIssuerDetails(aIssuer);
|
|
if (details)
|
|
[this._appKey, this._appSecret, this._authURI, this._tokenURI] = details;
|
|
else
|
|
throw Cr.NS_ERROR_INVALID_ARGUMENT;
|
|
},
|
|
initFromSmtp(aServer) {
|
|
return this._initPrefs("mail.smtpserver." + aServer.key + ".",
|
|
aServer.username, aServer.hostname);
|
|
},
|
|
initFromMail(aServer) {
|
|
return this._initPrefs("mail.server." + aServer.key + ".",
|
|
aServer.username, aServer.realHostName);
|
|
},
|
|
_initPrefs(root, aUsername, aHostname) {
|
|
// Load all of the parameters from preferences.
|
|
let issuer = Preferences.get(root + "oauth2.issuer", "");
|
|
let scope = Preferences.get(root + "oauth2.scope", "");
|
|
|
|
// These properties are absolutely essential to OAuth2 support. If we don't
|
|
// have them, we don't support OAuth2.
|
|
if (!issuer || !scope) {
|
|
// Since we currently only support gmail, init values if server matches.
|
|
let details = OAuth2Providers.getHostnameDetails(aHostname);
|
|
if (details)
|
|
{
|
|
[issuer, scope] = details;
|
|
Preferences.set(root + "oauth2.issuer", issuer);
|
|
Preferences.set(root + "oauth2.scope", scope);
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// Find the app key we need for the OAuth2 string. Eventually, this should
|
|
// be using dynamic client registration, but there are no current
|
|
// implementations that we can test this with.
|
|
this._loadOAuthClientDetails(issuer);
|
|
|
|
// Username is needed to generate the XOAUTH2 string.
|
|
this._username = aUsername;
|
|
// LoginURL is needed to save the refresh token in the password manager.
|
|
this._loginUrl = "oauth://" + issuer;
|
|
// We use the scope to indicate the realm.
|
|
this._scope = scope;
|
|
|
|
// Define the OAuth property and store it.
|
|
this._oauth = new OAuth2(this._authURI, scope, this._appKey,
|
|
this._appSecret);
|
|
this._oauth.authURI = this._authURI;
|
|
this._oauth.tokenURI = this._tokenURI;
|
|
|
|
// Try hinting the username...
|
|
this._oauth.extraAuthParams = [
|
|
["login_hint", aUsername]
|
|
];
|
|
|
|
// Set the window title to something more useful than "Unnamed"
|
|
this._oauth.requestWindowTitle =
|
|
Services.strings.createBundle("chrome://messenger/locale/messenger.properties")
|
|
.formatStringFromName("oauth2WindowTitle",
|
|
[aUsername, aHostname], 2);
|
|
|
|
// This stores the refresh token in the login manager.
|
|
Object.defineProperty(this._oauth, "refreshToken", {
|
|
get: () => this.refreshToken,
|
|
set: (token) => this.refreshToken = token
|
|
});
|
|
|
|
return true;
|
|
},
|
|
|
|
get refreshToken() {
|
|
let loginMgr = Cc["@mozilla.org/login-manager;1"]
|
|
.getService(Ci.nsILoginManager);
|
|
let logins = loginMgr.findLogins({}, this._loginUrl, null, this._scope);
|
|
for (let login of logins) {
|
|
if (login.username == this._username)
|
|
return login.password;
|
|
}
|
|
return '';
|
|
},
|
|
set refreshToken(token) {
|
|
let loginMgr = Cc["@mozilla.org/login-manager;1"]
|
|
.getService(Ci.nsILoginManager);
|
|
|
|
// Check if we already have a login with this username, and modify the
|
|
// password on that, if we do.
|
|
let logins = loginMgr.findLogins({}, this._loginUrl, null, this._scope);
|
|
for (let login of logins) {
|
|
if (login.username == this._username) {
|
|
if (token) {
|
|
let propBag = Cc["@mozilla.org/hash-property-bag;1"].
|
|
createInstance(Ci.nsIWritablePropertyBag);
|
|
propBag.setProperty("password", token);
|
|
loginMgr.modifyLogin(login, propBag);
|
|
}
|
|
else
|
|
loginMgr.removeLogin(login);
|
|
return token;
|
|
}
|
|
}
|
|
|
|
// Unless the token is null, we need to create and fill in a new login
|
|
if (token) {
|
|
let login = Cc["@mozilla.org/login-manager/loginInfo;1"]
|
|
.createInstance(Ci.nsILoginInfo);
|
|
login.init(this._loginUrl, null, this._scope, this._username, token,
|
|
'', '');
|
|
loginMgr.addLogin(login);
|
|
}
|
|
return token;
|
|
},
|
|
|
|
connect(aWithUI, aListener) {
|
|
let oauth = this._oauth;
|
|
let promptlistener = {
|
|
onPromptStartAsync: function(callback) {
|
|
oauth.connect(() => {
|
|
this.onPromptAuthAvailable();
|
|
callback.onAuthResult(true);
|
|
}, (err) => {
|
|
this.onPromptCanceled();
|
|
callback.onAuthResult(false);
|
|
}, aWithUI, false);
|
|
},
|
|
|
|
onPromptAuthAvailable: function() {
|
|
aListener.onSuccess(oauth.accessToken);
|
|
},
|
|
onPromptCanceled: function() {
|
|
aListener.onFailure(Components.results.NS_ERROR_ABORT);
|
|
},
|
|
onPromptStart: function() {}
|
|
};
|
|
|
|
let asyncprompter = Components.classes["@mozilla.org/messenger/msgAsyncPrompter;1"]
|
|
.getService(Components.interfaces.nsIMsgAsyncPrompter);
|
|
let promptkey = this._loginUrl + "/" + this._username;
|
|
asyncprompter.queueAsyncAuthPrompt(promptkey, false, promptlistener);
|
|
},
|
|
|
|
buildXOAuth2String() {
|
|
return btoa("user=" + this._username + "\x01auth=Bearer " +
|
|
this._oauth.accessToken + "\x01\x01");
|
|
},
|
|
};
|
|
|
|
var NSGetFactory = XPCOMUtils.generateNSGetFactory([OAuth2Module]);
|