forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			416 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			416 lines
		
	
	
	
		
			11 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/. */
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 | |
| const { XPCOMUtils } = ChromeUtils.import(
 | |
|   "resource://gre/modules/XPCOMUtils.jsm"
 | |
| );
 | |
| 
 | |
| XPCOMUtils.defineLazyServiceGetter(
 | |
|   this,
 | |
|   "ProfileService",
 | |
|   "@mozilla.org/toolkit/profile-service;1",
 | |
|   "nsIToolkitProfileService"
 | |
| );
 | |
| 
 | |
| async function flush() {
 | |
|   try {
 | |
|     ProfileService.flush();
 | |
|     rebuildProfileList();
 | |
|   } catch (e) {
 | |
|     let [title, msg, button] = await document.l10n.formatValues([
 | |
|       { id: "profiles-flush-fail-title" },
 | |
|       {
 | |
|         id:
 | |
|           e.result == Cr.NS_ERROR_DATABASE_CHANGED
 | |
|             ? "profiles-flush-conflict"
 | |
|             : "profiles-flush-failed",
 | |
|       },
 | |
|       { id: "profiles-flush-restart-button" },
 | |
|     ]);
 | |
| 
 | |
|     const PS = Ci.nsIPromptService;
 | |
|     let result = Services.prompt.confirmEx(
 | |
|       window,
 | |
|       title,
 | |
|       msg,
 | |
|       PS.BUTTON_POS_0 * PS.BUTTON_TITLE_CANCEL +
 | |
|         PS.BUTTON_POS_1 * PS.BUTTON_TITLE_IS_STRING,
 | |
|       null,
 | |
|       button,
 | |
|       null,
 | |
|       null,
 | |
|       {}
 | |
|     );
 | |
|     if (result == 1) {
 | |
|       restart(false);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function rebuildProfileList() {
 | |
|   let parent = document.getElementById("profiles");
 | |
|   while (parent.firstChild) {
 | |
|     parent.firstChild.remove();
 | |
|   }
 | |
| 
 | |
|   let defaultProfile;
 | |
|   try {
 | |
|     defaultProfile = ProfileService.defaultProfile;
 | |
|   } catch (e) {}
 | |
| 
 | |
|   let currentProfile = ProfileService.currentProfile;
 | |
| 
 | |
|   for (let profile of ProfileService.profiles) {
 | |
|     let isCurrentProfile = profile == currentProfile;
 | |
|     let isInUse = isCurrentProfile;
 | |
|     if (!isInUse) {
 | |
|       try {
 | |
|         let lock = profile.lock({});
 | |
|         lock.unlock();
 | |
|       } catch (e) {
 | |
|         if (
 | |
|           e.result != Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST &&
 | |
|           e.result != Cr.NS_ERROR_FILE_NOT_DIRECTORY &&
 | |
|           e.result != Cr.NS_ERROR_FILE_NOT_FOUND
 | |
|         ) {
 | |
|           isInUse = true;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     display({
 | |
|       profile,
 | |
|       isDefault: profile == defaultProfile,
 | |
|       isCurrentProfile,
 | |
|       isInUse,
 | |
|     });
 | |
|   }
 | |
| }
 | |
| 
 | |
| function display(profileData) {
 | |
|   let parent = document.getElementById("profiles");
 | |
| 
 | |
|   let div = document.createElement("div");
 | |
|   parent.appendChild(div);
 | |
| 
 | |
|   let name = document.createElement("h2");
 | |
| 
 | |
|   div.appendChild(name);
 | |
|   document.l10n.setAttributes(name, "profiles-name", {
 | |
|     name: profileData.profile.name,
 | |
|   });
 | |
| 
 | |
|   if (profileData.isCurrentProfile) {
 | |
|     let currentProfile = document.createElement("h3");
 | |
|     document.l10n.setAttributes(currentProfile, "profiles-current-profile");
 | |
|     div.appendChild(currentProfile);
 | |
|   } else if (profileData.isInUse) {
 | |
|     let currentProfile = document.createElement("h3");
 | |
|     document.l10n.setAttributes(currentProfile, "profiles-in-use-profile");
 | |
|     div.appendChild(currentProfile);
 | |
|   }
 | |
| 
 | |
|   let table = document.createElement("table");
 | |
|   div.appendChild(table);
 | |
| 
 | |
|   let tbody = document.createElement("tbody");
 | |
|   table.appendChild(tbody);
 | |
| 
 | |
|   function createItem(title, value, dir = false) {
 | |
|     let tr = document.createElement("tr");
 | |
|     tbody.appendChild(tr);
 | |
| 
 | |
|     let th = document.createElement("th");
 | |
|     th.setAttribute("class", "column");
 | |
|     document.l10n.setAttributes(th, title);
 | |
|     tr.appendChild(th);
 | |
| 
 | |
|     let td = document.createElement("td");
 | |
|     tr.appendChild(td);
 | |
| 
 | |
|     if (dir) {
 | |
|       td.appendChild(document.createTextNode(value.path));
 | |
| 
 | |
|       if (value.exists()) {
 | |
|         let button = document.createElement("button");
 | |
|         button.setAttribute("class", "opendir");
 | |
|         document.l10n.setAttributes(button, "profiles-opendir");
 | |
| 
 | |
|         td.appendChild(button);
 | |
| 
 | |
|         button.addEventListener("click", function(e) {
 | |
|           value.reveal();
 | |
|         });
 | |
|       }
 | |
|     } else {
 | |
|       document.l10n.setAttributes(td, value);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   createItem(
 | |
|     "profiles-is-default",
 | |
|     profileData.isDefault ? "profiles-yes" : "profiles-no"
 | |
|   );
 | |
| 
 | |
|   createItem("profiles-rootdir", profileData.profile.rootDir, true);
 | |
| 
 | |
|   if (profileData.profile.localDir.path != profileData.profile.rootDir.path) {
 | |
|     createItem("profiles-localdir", profileData.profile.localDir, true);
 | |
|   }
 | |
| 
 | |
|   let renameButton = document.createElement("button");
 | |
|   document.l10n.setAttributes(renameButton, "profiles-rename");
 | |
|   renameButton.onclick = function() {
 | |
|     renameProfile(profileData.profile);
 | |
|   };
 | |
|   div.appendChild(renameButton);
 | |
| 
 | |
|   if (!profileData.isInUse) {
 | |
|     let removeButton = document.createElement("button");
 | |
|     document.l10n.setAttributes(removeButton, "profiles-remove");
 | |
|     removeButton.onclick = function() {
 | |
|       removeProfile(profileData.profile);
 | |
|     };
 | |
| 
 | |
|     div.appendChild(removeButton);
 | |
|   }
 | |
| 
 | |
|   if (!profileData.isDefault) {
 | |
|     let defaultButton = document.createElement("button");
 | |
|     document.l10n.setAttributes(defaultButton, "profiles-set-as-default");
 | |
|     defaultButton.onclick = function() {
 | |
|       defaultProfile(profileData.profile);
 | |
|     };
 | |
|     div.appendChild(defaultButton);
 | |
|   }
 | |
| 
 | |
|   if (!profileData.isInUse) {
 | |
|     let runButton = document.createElement("button");
 | |
|     document.l10n.setAttributes(runButton, "profiles-launch-profile");
 | |
|     runButton.onclick = function() {
 | |
|       openProfile(profileData.profile);
 | |
|     };
 | |
|     div.appendChild(runButton);
 | |
|   }
 | |
| 
 | |
|   let sep = document.createElement("hr");
 | |
|   div.appendChild(sep);
 | |
| }
 | |
| 
 | |
| // This is called from the createProfileWizard.xhtml dialog.
 | |
| function CreateProfile(profile) {
 | |
|   // The wizard created a profile, just make it the default.
 | |
|   defaultProfile(profile);
 | |
| }
 | |
| 
 | |
| function createProfileWizard() {
 | |
|   // This should be rewritten in HTML eventually.
 | |
|   window.browsingContext.topChromeWindow.openDialog(
 | |
|     "chrome://mozapps/content/profile/createProfileWizard.xhtml",
 | |
|     "",
 | |
|     "centerscreen,chrome,modal,titlebar",
 | |
|     ProfileService,
 | |
|     { CreateProfile }
 | |
|   );
 | |
| }
 | |
| 
 | |
| async function renameProfile(profile) {
 | |
|   let newName = { value: profile.name };
 | |
|   let [title, msg] = await document.l10n.formatValues([
 | |
|     { id: "profiles-rename-profile-title" },
 | |
|     { id: "profiles-rename-profile", args: { name: profile.name } },
 | |
|   ]);
 | |
| 
 | |
|   if (Services.prompt.prompt(window, title, msg, newName, null, { value: 0 })) {
 | |
|     newName = newName.value;
 | |
| 
 | |
|     if (newName == profile.name) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     try {
 | |
|       profile.name = newName;
 | |
|     } catch (e) {
 | |
|       let [title, msg] = await document.l10n.formatValues([
 | |
|         { id: "profiles-invalid-profile-name-title" },
 | |
|         { id: "profiles-invalid-profile-name", args: { name: newName } },
 | |
|       ]);
 | |
| 
 | |
|       Services.prompt.alert(window, title, msg);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     flush();
 | |
|   }
 | |
| }
 | |
| 
 | |
| async function removeProfile(profile) {
 | |
|   let deleteFiles = false;
 | |
| 
 | |
|   if (profile.rootDir.exists()) {
 | |
|     let [
 | |
|       title,
 | |
|       msg,
 | |
|       dontDeleteStr,
 | |
|       deleteStr,
 | |
|     ] = await document.l10n.formatValues([
 | |
|       { id: "profiles-delete-profile-title" },
 | |
|       {
 | |
|         id: "profiles-delete-profile-confirm",
 | |
|         args: { dir: profile.rootDir.path },
 | |
|       },
 | |
|       { id: "profiles-dont-delete-files" },
 | |
|       { id: "profiles-delete-files" },
 | |
|     ]);
 | |
|     let buttonPressed = Services.prompt.confirmEx(
 | |
|       window,
 | |
|       title,
 | |
|       msg,
 | |
|       Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
 | |
|         Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 +
 | |
|         Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_2,
 | |
|       dontDeleteStr,
 | |
|       null,
 | |
|       deleteStr,
 | |
|       null,
 | |
|       { value: 0 }
 | |
|     );
 | |
|     if (buttonPressed == 1) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     if (buttonPressed == 2) {
 | |
|       deleteFiles = true;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // If we are deleting the default profile we must choose a different one.
 | |
|   let isDefault = false;
 | |
|   try {
 | |
|     isDefault = ProfileService.defaultProfile == profile;
 | |
|   } catch (e) {}
 | |
| 
 | |
|   if (isDefault) {
 | |
|     for (let p of ProfileService.profiles) {
 | |
|       if (profile == p) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if (isDefault) {
 | |
|         try {
 | |
|           ProfileService.defaultProfile = p;
 | |
|         } catch (e) {
 | |
|           // This can happen on dev-edition if a non-default profile is in use.
 | |
|           // In such a case the next time that dev-edition is started it will
 | |
|           // find no default profile and just create a new one.
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   try {
 | |
|     profile.removeInBackground(deleteFiles);
 | |
|   } catch (e) {
 | |
|     let [title, msg] = await document.l10n.formatValues([
 | |
|       { id: "profiles-delete-profile-failed-title" },
 | |
|       { id: "profiles-delete-profile-failed-message" },
 | |
|     ]);
 | |
| 
 | |
|     Services.prompt.alert(window, title, msg);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   flush();
 | |
| }
 | |
| 
 | |
| async function defaultProfile(profile) {
 | |
|   try {
 | |
|     ProfileService.defaultProfile = profile;
 | |
|     flush();
 | |
|   } catch (e) {
 | |
|     // This can happen on dev-edition.
 | |
|     let [title, msg] = await document.l10n.formatValues([
 | |
|       { id: "profiles-cannot-set-as-default-title" },
 | |
|       { id: "profiles-cannot-set-as-default-message" },
 | |
|     ]);
 | |
| 
 | |
|     Services.prompt.alert(window, title, msg);
 | |
|   }
 | |
| }
 | |
| 
 | |
| function openProfile(profile) {
 | |
|   let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
 | |
|     Ci.nsISupportsPRBool
 | |
|   );
 | |
|   Services.obs.notifyObservers(
 | |
|     cancelQuit,
 | |
|     "quit-application-requested",
 | |
|     "restart"
 | |
|   );
 | |
| 
 | |
|   if (cancelQuit.data) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Services.startup.createInstanceWithProfile(profile);
 | |
| }
 | |
| 
 | |
| function restart(safeMode) {
 | |
|   let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
 | |
|     Ci.nsISupportsPRBool
 | |
|   );
 | |
|   Services.obs.notifyObservers(
 | |
|     cancelQuit,
 | |
|     "quit-application-requested",
 | |
|     "restart"
 | |
|   );
 | |
| 
 | |
|   if (cancelQuit.data) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   let flags = Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart;
 | |
| 
 | |
|   if (safeMode) {
 | |
|     Services.startup.restartInSafeMode(flags);
 | |
|   } else {
 | |
|     Services.startup.quit(flags);
 | |
|   }
 | |
| }
 | |
| 
 | |
| window.addEventListener(
 | |
|   "DOMContentLoaded",
 | |
|   function() {
 | |
|     let createButton = document.getElementById("create-button");
 | |
|     createButton.addEventListener("click", createProfileWizard);
 | |
| 
 | |
|     let restartSafeModeButton = document.getElementById(
 | |
|       "restart-in-safe-mode-button"
 | |
|     );
 | |
|     if (!Services.policies || Services.policies.isAllowed("safeMode")) {
 | |
|       restartSafeModeButton.addEventListener("click", () => {
 | |
|         restart(true);
 | |
|       });
 | |
|     } else {
 | |
|       restartSafeModeButton.setAttribute("disabled", "true");
 | |
|     }
 | |
| 
 | |
|     let restartNormalModeButton = document.getElementById("restart-button");
 | |
|     restartNormalModeButton.addEventListener("click", () => {
 | |
|       restart(false);
 | |
|     });
 | |
| 
 | |
|     if (ProfileService.isListOutdated) {
 | |
|       document.getElementById("owned").hidden = true;
 | |
|     } else {
 | |
|       document.getElementById("conflict").hidden = true;
 | |
|       rebuildProfileList();
 | |
|     }
 | |
|   },
 | |
|   { once: true }
 | |
| );
 | 
