When displaying the profile selector on startup we cannot use the normal method of launching a selected profile by simply launching an new instance of Firefox. This would lose all state from the original process including any passed command line arguments. Instead we must signal back to nsAppRunner what profile it should launch. We also need to properly shut down the sqlite database before shutdown begins as our normal hook isn't in place and the process crashes if the database hasn't been shut down correctly. Differential Revision: https://phabricator.services.mozilla.com/D229921
197 lines
4.9 KiB
JavaScript
197 lines
4.9 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/. */
|
|
|
|
/**
|
|
* The selectable profile
|
|
*/
|
|
export class SelectableProfile {
|
|
// DB internal autoincremented integer ID.
|
|
// eslint-disable-next-line no-unused-private-class-members
|
|
#id;
|
|
|
|
// Path to profile on disk.
|
|
#path;
|
|
|
|
// The user-editable name
|
|
#name;
|
|
|
|
// Name of the user's chosen avatar, which corresponds to a list of built-in
|
|
// SVG avatars.
|
|
#avatar;
|
|
|
|
// Cached theme properties, used to allow displaying a SelectableProfile
|
|
// without loading the AddonManager to get theme info.
|
|
#themeId;
|
|
#themeFg;
|
|
#themeBg;
|
|
|
|
#selectableProfileService = null;
|
|
|
|
constructor(row, selectableProfileService) {
|
|
this.#id = row.getResultByName("id");
|
|
this.#path = row.getResultByName("path");
|
|
this.#name = row.getResultByName("name");
|
|
this.#avatar = row.getResultByName("avatar");
|
|
this.#themeId = row.getResultByName("themeId");
|
|
this.#themeFg = row.getResultByName("themeFg");
|
|
this.#themeBg = row.getResultByName("themeBg");
|
|
|
|
this.#selectableProfileService = selectableProfileService;
|
|
}
|
|
|
|
/**
|
|
* Get the id of the profile.
|
|
*
|
|
* @returns {number} Id of profile
|
|
*/
|
|
get id() {
|
|
return this.#id;
|
|
}
|
|
|
|
// Note: setters update the object, then ask the SelectableProfileService to save it.
|
|
|
|
/**
|
|
* Get the user-editable name for the profile.
|
|
*
|
|
* @returns {string} Name of profile
|
|
*/
|
|
get name() {
|
|
return this.#name;
|
|
}
|
|
|
|
/**
|
|
* Update the user-editable name for the profile, then trigger saving the profile,
|
|
* which will notify() other running instances.
|
|
*
|
|
* @param {string} aName The new name of the profile
|
|
*/
|
|
set name(aName) {
|
|
this.#name = aName;
|
|
|
|
this.saveUpdatesToDB();
|
|
|
|
Services.prefs.setBoolPref("browser.profiles.profile-name.updated", true);
|
|
}
|
|
|
|
/**
|
|
* Get the full path to the profile as a string.
|
|
*
|
|
* @returns {string} Path of profile
|
|
*/
|
|
get path() {
|
|
return PathUtils.joinRelative(
|
|
this.#selectableProfileService.constructor.getDirectory("UAppData").path,
|
|
this.#path
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the profile directory as an nsIFile.
|
|
*
|
|
* @returns {Promise<nsIFile>} A promise that resolves to an nsIFile for
|
|
* the profile directory
|
|
*/
|
|
get rootDir() {
|
|
return IOUtils.getDirectory(this.path);
|
|
}
|
|
|
|
/**
|
|
* Get the profile local directory as an nsIFile.
|
|
*
|
|
* @returns {Promise<nsIFile>} A promise that resolves to an nsIFile for
|
|
* the profile local directory
|
|
*/
|
|
get localDir() {
|
|
return this.rootDir.then(root => {
|
|
let relative = root.getRelativePath(
|
|
this.#selectableProfileService.constructor.getDirectory("DefProfRt")
|
|
);
|
|
let local =
|
|
this.#selectableProfileService.constructor.getDirectory("DefProfLRt");
|
|
local.appendRelativePath(relative);
|
|
return local;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get the name of the avatar for the profile.
|
|
*
|
|
* @returns {string} Name of the avatar
|
|
*/
|
|
get avatar() {
|
|
return this.#avatar;
|
|
}
|
|
|
|
/**
|
|
* Update the avatar, then trigger saving the profile, which will notify()
|
|
* other running instances.
|
|
*
|
|
* @param {string} aAvatar Name of the avatar
|
|
*/
|
|
set avatar(aAvatar) {
|
|
this.#avatar = aAvatar;
|
|
|
|
this.saveUpdatesToDB();
|
|
}
|
|
|
|
// Note, theme properties are set and returned as a group.
|
|
|
|
/**
|
|
* Get the theme l10n-id as a string, like "theme-foo-name".
|
|
* the theme foreground color as CSS style string, like "rgb(1,1,1)",
|
|
* the theme background color as CSS style string, like "rgb(0,0,0)".
|
|
*
|
|
* @returns {object} an object of the form { themeId, themeFg, themeBg }.
|
|
*/
|
|
get theme() {
|
|
return {
|
|
themeId: this.#themeId,
|
|
themeFg: this.#themeFg,
|
|
themeBg: this.#themeBg,
|
|
};
|
|
}
|
|
|
|
get iconPaintContext() {
|
|
return {
|
|
fillColor: this.#themeBg,
|
|
strokeColor: this.#themeFg,
|
|
fillOpacity: 1.0,
|
|
strokeOpacity: 1.0,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Update the theme (all three properties are required), then trigger saving
|
|
* the profile, which will notify() other running instances.
|
|
*
|
|
* @param {object} param0 The theme object
|
|
* @param {string} param0.themeId L10n id of the theme
|
|
* @param {string} param0.themeFg Foreground color of theme as CSS style string, like "rgb(1,1,1)",
|
|
* @param {string} param0.themeBg Background color of theme as CSS style string, like "rgb(0,0,0)".
|
|
*/
|
|
set theme({ themeId, themeFg, themeBg }) {
|
|
this.#themeId = themeId;
|
|
this.#themeFg = themeFg;
|
|
this.#themeBg = themeBg;
|
|
|
|
this.saveUpdatesToDB();
|
|
}
|
|
|
|
saveUpdatesToDB() {
|
|
this.#selectableProfileService.updateProfile(this);
|
|
}
|
|
|
|
toObject() {
|
|
let profileObj = {
|
|
id: this.id,
|
|
path: this.#path,
|
|
name: this.name,
|
|
avatar: this.avatar,
|
|
...this.theme,
|
|
};
|
|
|
|
return profileObj;
|
|
}
|
|
}
|