Bug 1880211 - Convert the OAuth2 code to use Promises instead of callbacks. r=leftmostcat,mkmelin

This is a prerequisite for the next patch (and a tidy up of some quite ugly code, frankly) – using
Promises instead of callbacks, it's much easier to have two things waiting on the same result.

Differential Revision: https://phabricator.services.mozilla.com/D201795

--HG--
extra : rebase_source : 2f0eaac2bba5302588bfa540143b53e5ba9fd0c1
extra : amend_source : e6e96f0ea3f1eddf664ff3865ab1bafdbc9cffab
This commit is contained in:
Geoff Lankow 2024-02-14 12:06:09 +13:00
Родитель 1d3141d68e
Коммит 990daa6277
6 изменённых файлов: 47 добавлений и 56 удалений

Просмотреть файл

@ -1424,21 +1424,15 @@ CalDavCalendar.prototype = {
this.onPromptAuthAvailable(callback);
},
onPromptAuthAvailable(callback) {
self.oauth.connect(
self.oauth.connect(true, aRefresh).then(
() => {
authSuccessCb();
if (callback) {
callback.onAuthResult(true);
}
callback?.onAuthResult(true);
},
() => {
authFailureCb();
if (callback) {
callback.onAuthResult(false);
}
},
true,
aRefresh
callback?.onAuthResult(false);
}
);
},
onPromptCanceled: authFailureCb,

Просмотреть файл

@ -114,21 +114,15 @@ class CalDavOAuth extends OAuth2 {
},
onPromptAuthAvailable(callback) {
self.connect(
self.connect(aWithUI, aRefresh).then(
() => {
if (callback) {
callback.onAuthResult(true);
}
callback?.onAuthResult(true);
resolve();
},
() => {
if (callback) {
callback.onAuthResult(false);
}
reject();
},
aWithUI,
aRefresh
error => {
callback?.onAuthResult(false);
reject(Cr.NS_ERROR_ABORT);
}
);
},
onPromptCanceled: reject,

Просмотреть файл

@ -29,6 +29,7 @@ tags = calendar
[test_bug668222.js]
[test_bug759324.js]
[test_caldav_requests.js]
tags = oauth
[test_CalendarFileImporter.js]
[test_calIteratorUtils.js]
[test_calmgr.js]

Просмотреть файл

@ -378,15 +378,13 @@ var CardDAVUtils = {
requestParams.oAuth = {
QueryInterface: ChromeUtils.generateQI(["msgIOAuth2Module"]),
connect(withUI, listener) {
oAuth.connect(
oAuth.connect(withUI, false).then(
() =>
listener.onSuccess(
// String format based on what OAuth2Module has.
btoa(`\x01auth=Bearer ${oAuth.accessToken}`)
),
() => listener.onFailure(Cr.NS_ERROR_ABORT),
withUI,
false
() => listener.onFailure(Cr.NS_ERROR_ABORT)
);
},
};

Просмотреть файл

@ -69,25 +69,37 @@ OAuth2.prototype = {
refreshToken: null,
tokenExpires: 0,
connect(aSuccess, aFailure, aWithUI, aRefresh) {
this.connectSuccessCallback = aSuccess;
this.connectFailureCallback = aFailure;
/**
* Obtain an access token for this endpoint. If an access token has already
* been obtained, it will be reused unless `aRefresh` is true.
*
* @param {boolean} aWithUI - If UI can be shown to the user for logging in.
* @param {boolean} aRefresh - If any existing access token should be
* ignored and a new one obtained.
* @returns {Promise} - Resolves when authorisation is complete and an
* access token is available.
*/
connect(aWithUI, aRefresh) {
if (this.accessToken && !this.tokenExpired && !aRefresh) {
aSuccess();
} else if (this.refreshToken) {
return this._promise;
}
const { promise, resolve, reject } = Promise.withResolvers();
this._promise = promise;
this._resolve = resolve;
this._reject = reject;
if (this.refreshToken) {
this.requestAccessToken(this.refreshToken, true);
} else if (!aWithUI) {
this._reject('{ "error": "auth_noui" }');
} else if (gConnecting[this.authorizationEndpoint]) {
this._reject("Window already open");
} else {
if (!aWithUI) {
aFailure('{ "error": "auth_noui" }');
return;
}
if (gConnecting[this.authorizationEndpoint]) {
aFailure("Window already open");
return;
}
this.requestAuthorization();
}
return this._promise;
},
/**
@ -272,7 +284,7 @@ OAuth2.prototype = {
},
onAuthorizationFailed(aError, aData) {
this.connectFailureCallback(aData);
this._reject(aData);
},
/**
@ -334,11 +346,9 @@ OAuth2.prototype = {
// Typically in production this would be {"error": "invalid_grant"}.
// That is, the token expired or was revoked (user changed password?).
// Reset the tokens we have and call success so that the auth flow
// will be re-triggered.
this.accessToken = null;
this.refreshToken = null;
this.connectSuccessCallback();
this._reject(err);
return;
}
@ -355,11 +365,11 @@ OAuth2.prototype = {
} else {
this.tokenExpires = Number.MAX_VALUE;
}
this.connectSuccessCallback();
this._resolve();
})
.catch(err => {
this.log.info(`Connection to authorization server failed: ${err}`);
this.connectFailureCallback(err);
this._reject(err);
});
},
};

Просмотреть файл

@ -170,25 +170,19 @@ OAuth2Module.prototype = {
},
onPromptAuthAvailable: callback => {
oauth.connect(
oauth.connect(aWithUI, false).then(
() => {
aListener.onSuccess(
btoa(
`user=${this._username}\x01auth=Bearer ${oauth.accessToken}\x01\x01`
)
);
if (callback) {
callback.onAuthResult(true);
}
callback?.onAuthResult(true);
},
() => {
aListener.onFailure(Cr.NS_ERROR_ABORT);
if (callback) {
callback.onAuthResult(false);
}
},
aWithUI,
false
callback?.onAuthResult(false);
}
);
},
onPromptCanceled() {