Backed out changeset f55480885aeb (bug 1918702) Backed out changeset db1eaf09430d (bug 1918702) Backed out changeset a9179f6e684d (bug 1918702) Backed out changeset f9d3349e6fe3 (bug 1918702) Backed out changeset 10d2957bbfe8 (bug 1918702)
310 lines
8.6 KiB
JavaScript
310 lines
8.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/. */
|
|
|
|
import { LoginHelper } from "resource://gre/modules/LoginHelper.sys.mjs";
|
|
|
|
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
|
|
|
const lazy = {};
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(
|
|
lazy,
|
|
"ClipboardHelper",
|
|
"@mozilla.org/widget/clipboardhelper;1",
|
|
"nsIClipboardHelper"
|
|
);
|
|
|
|
const TELEMETRY_EVENT_CATEGORY = "pwmgr";
|
|
const TELEMETRY_MIN_MS_BETWEEN_OPEN_MANAGEMENT = 5000;
|
|
|
|
let gLastOpenManagementBrowserId = null;
|
|
let gLastOpenManagementEventTime = Number.NEGATIVE_INFINITY;
|
|
let gPrimaryPasswordPromise;
|
|
|
|
function recordTelemetryEvent(event) {
|
|
try {
|
|
let { method, object, extra = {}, value = null } = event;
|
|
Services.telemetry.recordEvent(
|
|
TELEMETRY_EVENT_CATEGORY,
|
|
method,
|
|
object,
|
|
value,
|
|
extra
|
|
);
|
|
} catch (ex) {
|
|
console.error("AboutLoginsChild: error recording telemetry event:", ex);
|
|
}
|
|
}
|
|
|
|
export class AboutLoginsChild extends JSWindowActorChild {
|
|
handleEvent(event) {
|
|
switch (event.type) {
|
|
case "AboutLoginsInit": {
|
|
this.#aboutLoginsInit();
|
|
break;
|
|
}
|
|
case "AboutLoginsImportReportInit": {
|
|
this.#aboutLoginsImportReportInit();
|
|
break;
|
|
}
|
|
case "AboutLoginsCopyLoginDetail": {
|
|
this.#aboutLoginsCopyLoginDetail(event.detail);
|
|
break;
|
|
}
|
|
case "AboutLoginsCreateLogin": {
|
|
this.#aboutLoginsCreateLogin(event.detail);
|
|
break;
|
|
}
|
|
case "AboutLoginsDeleteLogin": {
|
|
this.#aboutLoginsDeleteLogin(event.detail);
|
|
break;
|
|
}
|
|
case "AboutLoginsExportPasswords": {
|
|
this.#aboutLoginsExportPasswords();
|
|
break;
|
|
}
|
|
case "AboutLoginsGetHelp": {
|
|
this.#aboutLoginsGetHelp();
|
|
break;
|
|
}
|
|
case "AboutLoginsImportFromBrowser": {
|
|
this.#aboutLoginsImportFromBrowser();
|
|
break;
|
|
}
|
|
case "AboutLoginsImportFromFile": {
|
|
this.#aboutLoginsImportFromFile();
|
|
break;
|
|
}
|
|
case "AboutLoginsOpenPreferences": {
|
|
this.#aboutLoginsOpenPreferences();
|
|
break;
|
|
}
|
|
case "AboutLoginsRecordTelemetryEvent": {
|
|
this.#aboutLoginsRecordTelemetryEvent(event);
|
|
break;
|
|
}
|
|
case "AboutLoginsRemoveAllLogins": {
|
|
this.#aboutLoginsRemoveAllLogins();
|
|
break;
|
|
}
|
|
case "AboutLoginsSortChanged": {
|
|
this.#aboutLoginsSortChanged(event.detail);
|
|
break;
|
|
}
|
|
case "AboutLoginsSyncEnable": {
|
|
this.#aboutLoginsSyncEnable();
|
|
break;
|
|
}
|
|
case "AboutLoginsUpdateLogin": {
|
|
this.#aboutLoginsUpdateLogin(event.detail);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#aboutLoginsInit() {
|
|
this.sendAsyncMessage("AboutLogins:Subscribe");
|
|
|
|
let win = this.browsingContext.window;
|
|
let waivedContent = Cu.waiveXrays(win);
|
|
let that = this;
|
|
let AboutLoginsUtils = {
|
|
doLoginsMatch(loginA, loginB) {
|
|
return LoginHelper.doLoginsMatch(loginA, loginB, {});
|
|
},
|
|
getLoginOrigin(uriString) {
|
|
return LoginHelper.getLoginOrigin(uriString);
|
|
},
|
|
setFocus(element) {
|
|
Services.focus.setFocus(element, Services.focus.FLAG_BYKEY);
|
|
},
|
|
/**
|
|
* Shows the Primary Password prompt if enabled, or the
|
|
* OS auth dialog otherwise.
|
|
* @param resolve Callback that is called with result of authentication.
|
|
* @param messageId The string ID that corresponds to a string stored in aboutLogins.ftl.
|
|
* This string will be displayed only when the OS auth dialog is used.
|
|
*/
|
|
async promptForPrimaryPassword(resolve, messageId) {
|
|
gPrimaryPasswordPromise = {
|
|
resolve,
|
|
};
|
|
|
|
that.sendAsyncMessage("AboutLogins:PrimaryPasswordRequest", messageId);
|
|
|
|
return gPrimaryPasswordPromise;
|
|
},
|
|
fileImportEnabled: Services.prefs.getBoolPref(
|
|
"signon.management.page.fileImport.enabled"
|
|
),
|
|
// Default to enabled just in case a search is attempted before we get a response.
|
|
primaryPasswordEnabled: true,
|
|
passwordRevealVisible: true,
|
|
};
|
|
waivedContent.AboutLoginsUtils = Cu.cloneInto(
|
|
AboutLoginsUtils,
|
|
waivedContent,
|
|
{
|
|
cloneFunctions: true,
|
|
}
|
|
);
|
|
}
|
|
|
|
#aboutLoginsImportReportInit() {
|
|
this.sendAsyncMessage("AboutLogins:ImportReportInit");
|
|
}
|
|
|
|
#aboutLoginsCopyLoginDetail(detail) {
|
|
lazy.ClipboardHelper.copyString(
|
|
detail,
|
|
this.windowContext,
|
|
lazy.ClipboardHelper.Sensitive
|
|
);
|
|
}
|
|
|
|
#aboutLoginsCreateLogin(login) {
|
|
this.sendAsyncMessage("AboutLogins:CreateLogin", {
|
|
login,
|
|
});
|
|
}
|
|
|
|
#aboutLoginsDeleteLogin(login) {
|
|
this.sendAsyncMessage("AboutLogins:DeleteLogin", {
|
|
login,
|
|
});
|
|
}
|
|
|
|
#aboutLoginsExportPasswords() {
|
|
this.sendAsyncMessage("AboutLogins:ExportPasswords");
|
|
}
|
|
|
|
#aboutLoginsGetHelp() {
|
|
this.sendAsyncMessage("AboutLogins:GetHelp");
|
|
}
|
|
|
|
#aboutLoginsImportFromBrowser() {
|
|
this.sendAsyncMessage("AboutLogins:ImportFromBrowser");
|
|
recordTelemetryEvent({
|
|
object: "import_from_browser",
|
|
method: "mgmt_menu_item_used",
|
|
});
|
|
}
|
|
|
|
#aboutLoginsImportFromFile() {
|
|
this.sendAsyncMessage("AboutLogins:ImportFromFile");
|
|
recordTelemetryEvent({
|
|
object: "import_from_csv",
|
|
method: "mgmt_menu_item_used",
|
|
});
|
|
}
|
|
|
|
#aboutLoginsOpenPreferences() {
|
|
this.sendAsyncMessage("AboutLogins:OpenPreferences");
|
|
recordTelemetryEvent({
|
|
object: "preferences",
|
|
method: "mgmt_menu_item_used",
|
|
});
|
|
}
|
|
|
|
#aboutLoginsRecordTelemetryEvent(event) {
|
|
let { method } = event.detail;
|
|
|
|
if (method == "open_management") {
|
|
let { docShell } = this.browsingContext;
|
|
// Compare to the last time open_management was recorded for the same
|
|
// outerWindowID to not double-count them due to a redirect to remove
|
|
// the entryPoint query param (since replaceState isn't allowed for
|
|
// about:). Don't use performance.now for the tab since you can't
|
|
// compare that number between different tabs and this JSM is shared.
|
|
let now = docShell.now();
|
|
if (
|
|
this.browsingContext.browserId == gLastOpenManagementBrowserId &&
|
|
now - gLastOpenManagementEventTime <
|
|
TELEMETRY_MIN_MS_BETWEEN_OPEN_MANAGEMENT
|
|
) {
|
|
return;
|
|
}
|
|
gLastOpenManagementEventTime = now;
|
|
gLastOpenManagementBrowserId = this.browsingContext.browserId;
|
|
}
|
|
recordTelemetryEvent(event.detail);
|
|
}
|
|
|
|
#aboutLoginsRemoveAllLogins() {
|
|
this.sendAsyncMessage("AboutLogins:RemoveAllLogins");
|
|
}
|
|
|
|
#aboutLoginsSortChanged(detail) {
|
|
this.sendAsyncMessage("AboutLogins:SortChanged", detail);
|
|
}
|
|
|
|
#aboutLoginsSyncEnable() {
|
|
this.sendAsyncMessage("AboutLogins:SyncEnable");
|
|
}
|
|
|
|
#aboutLoginsUpdateLogin(login) {
|
|
this.sendAsyncMessage("AboutLogins:UpdateLogin", {
|
|
login,
|
|
});
|
|
}
|
|
|
|
receiveMessage(message) {
|
|
switch (message.name) {
|
|
case "AboutLogins:ImportReportData":
|
|
this.#importReportData(message.data);
|
|
break;
|
|
case "AboutLogins:PrimaryPasswordResponse":
|
|
this.#primaryPasswordResponse(message.data);
|
|
break;
|
|
case "AboutLogins:RemaskPassword":
|
|
this.#remaskPassword(message.data);
|
|
break;
|
|
case "AboutLogins:Setup":
|
|
this.#setup(message.data);
|
|
break;
|
|
default:
|
|
this.#passMessageDataToContent(message);
|
|
}
|
|
}
|
|
|
|
#importReportData(data) {
|
|
this.sendToContent("ImportReportData", data);
|
|
}
|
|
|
|
#primaryPasswordResponse(data) {
|
|
if (gPrimaryPasswordPromise) {
|
|
gPrimaryPasswordPromise.resolve(data.result);
|
|
recordTelemetryEvent(data.telemetryEvent);
|
|
}
|
|
}
|
|
|
|
#remaskPassword(data) {
|
|
this.sendToContent("RemaskPassword", data);
|
|
}
|
|
|
|
#setup(data) {
|
|
let utils = Cu.waiveXrays(this.browsingContext.window).AboutLoginsUtils;
|
|
utils.primaryPasswordEnabled = data.primaryPasswordEnabled;
|
|
utils.passwordRevealVisible = data.passwordRevealVisible;
|
|
utils.importVisible = data.importVisible;
|
|
utils.supportBaseURL = Services.urlFormatter.formatURLPref(
|
|
"app.support.baseURL"
|
|
);
|
|
this.sendToContent("Setup", data);
|
|
}
|
|
|
|
#passMessageDataToContent(message) {
|
|
this.sendToContent(message.name.replace("AboutLogins:", ""), message.data);
|
|
}
|
|
|
|
sendToContent(messageType, detail) {
|
|
let win = this.document.defaultView;
|
|
let message = Object.assign({ messageType }, { value: detail });
|
|
let event = new win.CustomEvent("AboutLoginsChromeToContent", {
|
|
detail: Cu.cloneInto(message, win),
|
|
});
|
|
win.dispatchEvent(event);
|
|
}
|
|
}
|