1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 const { XPCOMUtils } = ChromeUtils.importESModule(
8 "resource://gre/modules/XPCOMUtils.sys.mjs"
11 XPCOMUtils.defineLazyServiceGetter(
14 "@mozilla.org/toolkit/profile-service;1",
15 "nsIToolkitProfileService"
18 async function flush() {
20 ProfileService.flush();
23 let [title, msg, button] = await document.l10n.formatValues([
24 { id: "profiles-flush-fail-title" },
27 e.result == Cr.NS_ERROR_DATABASE_CHANGED
28 ? "profiles-flush-conflict"
29 : "profiles-flush-failed",
31 { id: "profiles-flush-restart-button" },
34 const PS = Ci.nsIPromptService;
35 let result = Services.prompt.confirmEx(
39 PS.BUTTON_POS_0 * PS.BUTTON_TITLE_CANCEL +
40 PS.BUTTON_POS_1 * PS.BUTTON_TITLE_IS_STRING,
53 function rebuildProfileList() {
54 let parent = document.getElementById("profiles");
55 while (parent.firstChild) {
56 parent.firstChild.remove();
61 defaultProfile = ProfileService.defaultProfile;
64 let currentProfile = ProfileService.currentProfile;
66 for (let profile of ProfileService.profiles) {
67 let isCurrentProfile = profile == currentProfile;
68 let isInUse = isCurrentProfile;
71 let lock = profile.lock({});
75 e.result != Cr.NS_ERROR_FILE_NOT_DIRECTORY &&
76 e.result != Cr.NS_ERROR_FILE_NOT_FOUND
84 isDefault: profile == defaultProfile,
91 function display(profileData) {
92 let parent = document.getElementById("profiles");
94 let div = document.createElement("div");
95 parent.appendChild(div);
97 let name = document.createElement("h2");
99 div.appendChild(name);
100 document.l10n.setAttributes(name, "profiles-name", {
101 name: profileData.profile.name,
104 if (profileData.isCurrentProfile) {
105 let currentProfile = document.createElement("h3");
106 document.l10n.setAttributes(currentProfile, "profiles-current-profile");
107 div.appendChild(currentProfile);
108 } else if (profileData.isInUse) {
109 let currentProfile = document.createElement("h3");
110 document.l10n.setAttributes(currentProfile, "profiles-in-use-profile");
111 div.appendChild(currentProfile);
114 let table = document.createElement("table");
115 div.appendChild(table);
117 let tbody = document.createElement("tbody");
118 table.appendChild(tbody);
120 function createItem(title, value, dir = false) {
121 let tr = document.createElement("tr");
122 tbody.appendChild(tr);
124 let th = document.createElement("th");
125 th.setAttribute("class", "column");
126 document.l10n.setAttributes(th, title);
129 let td = document.createElement("td");
133 td.appendChild(document.createTextNode(value.path));
135 if (value.exists()) {
136 let button = document.createElement("button");
137 button.setAttribute("class", "opendir");
138 document.l10n.setAttributes(button, "profiles-opendir");
140 td.appendChild(button);
142 button.addEventListener("click", function () {
147 document.l10n.setAttributes(td, value);
152 "profiles-is-default",
153 profileData.isDefault ? "profiles-yes" : "profiles-no"
156 createItem("profiles-rootdir", profileData.profile.rootDir, true);
158 if (profileData.profile.localDir.path != profileData.profile.rootDir.path) {
159 createItem("profiles-localdir", profileData.profile.localDir, true);
162 let renameButton = document.createElement("button");
163 document.l10n.setAttributes(renameButton, "profiles-rename");
164 renameButton.onclick = function () {
165 renameProfile(profileData.profile);
167 div.appendChild(renameButton);
169 if (!profileData.isInUse) {
170 let removeButton = document.createElement("button");
171 document.l10n.setAttributes(removeButton, "profiles-remove");
172 removeButton.onclick = function () {
173 removeProfile(profileData.profile);
176 div.appendChild(removeButton);
179 if (!profileData.isDefault) {
180 let defaultButton = document.createElement("button");
181 document.l10n.setAttributes(defaultButton, "profiles-set-as-default");
182 defaultButton.onclick = function () {
183 defaultProfile(profileData.profile);
185 div.appendChild(defaultButton);
188 if (!profileData.isInUse) {
189 let runButton = document.createElement("button");
190 document.l10n.setAttributes(runButton, "profiles-launch-profile");
191 runButton.onclick = function () {
192 openProfile(profileData.profile);
194 div.appendChild(runButton);
197 let sep = document.createElement("hr");
198 div.appendChild(sep);
201 // This is called from the createProfileWizard.xhtml dialog.
202 function CreateProfile(profile) {
203 // The wizard created a profile, just make it the default.
204 defaultProfile(profile);
207 function createProfileWizard() {
208 // This should be rewritten in HTML eventually.
209 window.browsingContext.topChromeWindow.openDialog(
210 "chrome://mozapps/content/profile/createProfileWizard.xhtml",
212 "centerscreen,chrome,modal,titlebar",
218 async function renameProfile(profile) {
219 let newName = { value: profile.name };
220 let [title, msg] = await document.l10n.formatValues([
221 { id: "profiles-rename-profile-title" },
222 { id: "profiles-rename-profile", args: { name: profile.name } },
225 if (Services.prompt.prompt(window, title, msg, newName, null, { value: 0 })) {
226 newName = newName.value;
228 if (newName == profile.name) {
233 profile.name = newName;
235 let [title, msg] = await document.l10n.formatValues([
236 { id: "profiles-invalid-profile-name-title" },
237 { id: "profiles-invalid-profile-name", args: { name: newName } },
240 Services.prompt.alert(window, title, msg);
248 async function removeProfile(profile) {
249 let deleteFiles = false;
251 if (profile.rootDir.exists()) {
252 let [title, msg, dontDeleteStr, deleteStr] =
253 await document.l10n.formatValues([
254 { id: "profiles-delete-profile-title" },
256 id: "profiles-delete-profile-confirm",
257 args: { dir: profile.rootDir.path },
259 { id: "profiles-dont-delete-files" },
260 { id: "profiles-delete-files" },
262 let buttonPressed = Services.prompt.confirmEx(
266 Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
267 Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 +
268 Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_2,
275 if (buttonPressed == 1) {
279 if (buttonPressed == 2) {
284 // If we are deleting the default profile we must choose a different one.
285 let isDefault = false;
287 isDefault = ProfileService.defaultProfile == profile;
291 for (let p of ProfileService.profiles) {
298 ProfileService.defaultProfile = p;
300 // This can happen on dev-edition if a non-default profile is in use.
301 // In such a case the next time that dev-edition is started it will
302 // find no default profile and just create a new one.
311 profile.removeInBackground(deleteFiles);
313 let [title, msg] = await document.l10n.formatValues([
314 { id: "profiles-delete-profile-failed-title" },
315 { id: "profiles-delete-profile-failed-message" },
318 Services.prompt.alert(window, title, msg);
325 async function defaultProfile(profile) {
327 ProfileService.defaultProfile = profile;
330 // This can happen on dev-edition.
331 let [title, msg] = await document.l10n.formatValues([
332 { id: "profiles-cannot-set-as-default-title" },
333 { id: "profiles-cannot-set-as-default-message" },
336 Services.prompt.alert(window, title, msg);
340 function openProfile(profile) {
341 Services.startup.createInstanceWithProfile(profile);
344 function restart(safeMode) {
345 let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
348 Services.obs.notifyObservers(
350 "quit-application-requested",
354 if (cancelQuit.data) {
358 let flags = Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart;
361 Services.startup.restartInSafeMode(flags);
363 Services.startup.quit(flags);
367 window.addEventListener(
370 let createButton = document.getElementById("create-button");
371 createButton.addEventListener("click", createProfileWizard);
373 let restartSafeModeButton = document.getElementById(
374 "restart-in-safe-mode-button"
376 if (!Services.policies || Services.policies.isAllowed("safeMode")) {
377 restartSafeModeButton.addEventListener("click", () => {
381 restartSafeModeButton.setAttribute("disabled", "true");
384 let restartNormalModeButton = document.getElementById("restart-button");
385 restartNormalModeButton.addEventListener("click", () => {
389 if (ProfileService.isListOutdated) {
390 document.getElementById("owned").hidden = true;
392 document.getElementById("conflict").hidden = true;
393 rebuildProfileList();