Bug 1599873 - [1.3] Implement Login Storage prompt backend for save requests. r=MattN,geckoview-reviewers,snorp

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Eugen Sawin 2019-12-20 16:26:53 +00:00
Родитель 0ce2d82896
Коммит 0127aa97c4
3 изменённых файлов: 175 добавлений и 2 удалений

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

@ -11,17 +11,27 @@ category profile-after-change GeckoViewStartup @mozilla.org/geckoview/startup;1
component {42f3c238-e8e8-4015-9ca2-148723a8afcf} GeckoViewPermission.js
contract @mozilla.org/content-permission/prompt;1 {42f3c238-e8e8-4015-9ca2-148723a8afcf}
# GeckoViewPrompt.js
# GeckoViewPrompt.js PromptFactory
component {076ac188-23c1-4390-aa08-7ef1f78ca5d9} GeckoViewPrompt.js
contract @mozilla.org/embedcomp/prompt-service;1 {076ac188-23c1-4390-aa08-7ef1f78ca5d9}
contract @mozilla.org/prompter;1 {076ac188-23c1-4390-aa08-7ef1f78ca5d9}
# GeckoViewPrompt.js ColorPickerDelegate
component {aa0dd6fc-73dd-4621-8385-c0b377e02cee} GeckoViewPrompt.js process=main
contract @mozilla.org/colorpicker;1 {aa0dd6fc-73dd-4621-8385-c0b377e02cee} process=main
# GeckoViewPrompt.js FilePickerDelegate
component {e4565e36-f101-4bf5-950b-4be0887785a9} GeckoViewPrompt.js process=main
contract @mozilla.org/filepicker;1 {e4565e36-f101-4bf5-950b-4be0887785a9} process=main
# GeckoViewPrompt.js ShareDelegate
component {1201d357-8417-4926-a694-e6408fbedcf8} GeckoViewPrompt.js process=main
contract @mozilla.org/sharepicker;1 {1201d357-8417-4926-a694-e6408fbedcf8} process=main
# GeckoViewPrompt.js LoginStorageDelegate
component {3d765750-1c3d-11ea-aaef-0800200c9a66} GeckoViewPrompt.js process=main
contract @mozilla.org/login-manager/prompter;1 {3d765750-1c3d-11ea-aaef-0800200c9a66} process=main
# GeckoViewExternalAppService.js
component {a89eeec6-6608-42ee-a4f8-04d425992f45} GeckoViewExternalAppService.js
contract @mozilla.org/uriloader/external-helper-app-service;1 {a89eeec6-6608-42ee-a4f8-04d425992f45}

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

@ -10,6 +10,8 @@ XPCOMUtils.defineLazyModuleGetters(this, {
EventDispatcher: "resource://gre/modules/Messaging.jsm",
FileUtils: "resource://gre/modules/FileUtils.jsm",
GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
GeckoViewLoginStorage: "resource://gre/modules/GeckoViewLoginStorage.jsm",
LoginEntry: "resource://gre/modules/GeckoViewLoginStorage.jsm",
Services: "resource://gre/modules/Services.jsm",
});
@ -1189,9 +1191,98 @@ ShareDelegate.prototype = {
},
};
// Sync with LoginStoragePrompt.Type in GeckoSession.java.
const LoginStorageType = { SAVE: 1 };
// Sync with LoginStoragePrompt.Hint in GeckoSession.java.
const LoginStorageHint = { NONE: 0 };
class LoginStorageDelegate {
get classID() {
return Components.ID("{3d765750-1c3d-11ea-aaef-0800200c9a66}");
}
get QueryInterface() {
return ChromeUtils.generateQI([Ci.nsILoginManagerPrompter]);
}
_createMessage(aType, aHint, aLogins) {
return {
// Sync with GeckoSession.handlePromptEvent.
type: "loginStorage",
lsType: aType,
hint: aHint,
logins: aLogins,
};
}
promptToSavePassword(
aBrowser,
aLogin,
dismissed = false,
notifySaved = false
) {
const prompt = new PromptDelegate(aBrowser.ownerGlobal);
prompt.asyncShowPrompt(
this._createMessage(LoginStorageType.SAVE, LoginStorageHint.NONE, [
LoginEntry.fromLoginInfo(aLogin),
]),
result => {
if (!result || result.login === undefined) {
return;
}
const loginInfo = LoginEntry.fromBundle(result.login).toLoginInfo();
Services.obs.notifyObservers(loginInfo, "passwordmgr-prompt-save");
}
);
}
promptToChangePassword(
aBrowser,
aOldLogin,
aNewLogin,
dismissed = false,
notifySaved = false,
autoSavedLoginGuid = ""
) {
const newLogin = LoginEntry.fromLoginInfo(aOldLogin || aNewLogin);
const oldGuid = (aOldLogin && newLogin.guid) || null;
newLogin.origin = aNewLogin.origin;
newLogin.formActionOrigin = aNewLogin.formActionOrigin;
newLogin.password = aNewLogin.password;
newLogin.username = aNewLogin.username;
const prompt = new PromptDelegate(aBrowser.ownerGlobal);
prompt.asyncShowPrompt(
this._createMessage(LoginStorageType.SAVE, LoginStorageHint.NONE, [
newLogin,
]),
result => {
if (!result || result.login === undefined) {
return;
}
GeckoViewLoginStorage.onLoginSave(result.login);
const loginInfo = LoginEntry.fromBundle(result.login).toLoginInfo();
Services.obs.notifyObservers(
loginInfo,
"passwordmgr-prompt-change",
oldGuid
);
}
);
}
promptToChangePasswordWithUsernames(aBrowser, aLogins, aNewLogin) {
this.promptToChangePassword(aBrowser, null /* oldLogin */, aNewLogin);
}
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
ColorPickerDelegate,
FilePickerDelegate,
PromptFactory,
ShareDelegate,
LoginStorageDelegate,
]);

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

@ -4,7 +4,7 @@
"use strict";
const EXPORTED_SYMBOLS = ["GeckoViewLoginStorage"];
const EXPORTED_SYMBOLS = ["GeckoViewLoginStorage", "LoginEntry"];
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
@ -18,6 +18,78 @@ XPCOMUtils.defineLazyModuleGetters(this, {
EventDispatcher: "resource://gre/modules/Messaging.jsm",
});
XPCOMUtils.defineLazyGetter(this, "LoginInfo", () =>
Components.Constructor(
"@mozilla.org/login-manager/loginInfo;1",
"nsILoginInfo",
"init"
)
);
class LoginEntry {
constructor() {
this.origin = null;
this.formActionOrigin = null;
this.httpRealm = null;
this.username = null;
this.password = null;
// Metadata.
this.guid = null;
// TODO: Not supported by GV.
this.timeCreated = null;
this.timeLastUsed = null;
this.timePasswordChanged = null;
this.timesUsed = null;
}
toLoginInfo() {
const info = new LoginInfo(
this.origin,
this.formActionOrigin,
this.httpRealm,
this.username,
this.password
);
// Metadata.
info.QueryInterface(Ci.nsILoginMetaInfo);
info.guid = this.guid;
info.timeCreated = this.timeCreated;
info.timeLastUsed = this.timeLastUsed;
info.timePasswordChanged = this.timePasswordChanged;
info.timesUsed = this.timesUsed;
return info;
}
static fromBundle(aObj) {
const entry = new LoginEntry();
Object.assign(entry, aObj);
return entry;
}
static fromLoginInfo(aInfo) {
const entry = new LoginEntry();
entry.origin = aInfo.origin;
entry.formActionOrigin = aInfo.formActionOrigin;
entry.httpRealm = aInfo.httpRealm;
entry.username = aInfo.username;
entry.password = aInfo.password;
// Metadata.
aInfo.QueryInterface(Ci.nsILoginMetaInfo);
entry.guid = aInfo.guid;
entry.timeCreated = aInfo.timeCreated;
entry.timeLastUsed = aInfo.timeLastUsed;
entry.timePasswordChanged = aInfo.timePasswordChanged;
entry.timesUsed = aInfo.timesUsed;
return entry;
}
}
const GeckoViewLoginStorage = {
/**
* Delegates login entry fetching for the given domain to the attached