diff options
Diffstat (limited to 'toolkit/profile/content')
-rw-r--r-- | toolkit/profile/content/createProfileWizard.js | 266 | ||||
-rw-r--r-- | toolkit/profile/content/createProfileWizard.xhtml | 90 | ||||
-rw-r--r-- | toolkit/profile/content/profileDowngrade.js | 39 | ||||
-rw-r--r-- | toolkit/profile/content/profileDowngrade.xhtml | 40 | ||||
-rw-r--r-- | toolkit/profile/content/profileSelection.js | 355 | ||||
-rw-r--r-- | toolkit/profile/content/profileSelection.xhtml | 101 |
6 files changed, 891 insertions, 0 deletions
diff --git a/toolkit/profile/content/createProfileWizard.js b/toolkit/profile/content/createProfileWizard.js new file mode 100644 index 0000000000..9e87fb4220 --- /dev/null +++ b/toolkit/profile/content/createProfileWizard.js @@ -0,0 +1,266 @@ +/* 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/. */ + +const C = Cc; +const I = Ci; + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +const ToolkitProfileService = "@mozilla.org/toolkit/profile-service;1"; + +var gProfileService; +var gProfileManagerBundle; + +var gDefaultProfileParent; + +// The directory where the profile will be created. +var gProfileRoot; + +// Text node to display the location and name of the profile to create. +var gProfileDisplay; + +// Called once when the wizard is opened. +function initWizard() { + try { + gProfileService = C[ToolkitProfileService].getService( + I.nsIToolkitProfileService + ); + gProfileManagerBundle = document.getElementById("bundle_profileManager"); + + gDefaultProfileParent = Services.dirsvc.get("DefProfRt", I.nsIFile); + + // Initialize the profile location display. + gProfileDisplay = document.getElementById("profileDisplay").firstChild; + document.addEventListener("wizardfinish", onFinish); + document + .getElementById("explanation") + .addEventListener("pageshow", enableNextButton); + document + .getElementById("createProfile") + .addEventListener("pageshow", initSecondWizardPage); + setDisplayToDefaultFolder(); + } catch (e) { + window.close(); + throw e; + } +} + +// Called every time the second wizard page is displayed. +function initSecondWizardPage() { + var profileName = document.getElementById("profileName"); + profileName.select(); + profileName.focus(); + + // Initialize profile name validation. + checkCurrentInput(profileName.value); +} + +const kSaltTable = [ + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "0", +]; + +var kSaltString = ""; +for (var i = 0; i < 8; ++i) { + kSaltString += kSaltTable[Math.floor(Math.random() * kSaltTable.length)]; +} + +function saltName(aName) { + return kSaltString + "." + aName; +} + +function setDisplayToDefaultFolder() { + var defaultProfileDir = gDefaultProfileParent.clone(); + defaultProfileDir.append( + saltName(document.getElementById("profileName").value) + ); + gProfileRoot = defaultProfileDir; + document.getElementById("useDefault").disabled = true; +} + +function updateProfileDisplay() { + gProfileDisplay.data = gProfileRoot.path; +} + +// Invoke a folder selection dialog for choosing the directory of profile storage. +function chooseProfileFolder() { + var newProfileRoot; + + var dirChooser = C["@mozilla.org/filepicker;1"].createInstance( + I.nsIFilePicker + ); + dirChooser.init( + window, + gProfileManagerBundle.getString("chooseFolder"), + I.nsIFilePicker.modeGetFolder + ); + dirChooser.appendFilters(I.nsIFilePicker.filterAll); + + // default to the Profiles folder + dirChooser.displayDirectory = gDefaultProfileParent; + + dirChooser.open(() => { + newProfileRoot = dirChooser.file; + + // Disable the "Default Folder..." button when the default profile folder + // was selected manually in the File Picker. + document.getElementById("useDefault").disabled = + newProfileRoot.parent.equals(gDefaultProfileParent); + + gProfileRoot = newProfileRoot; + updateProfileDisplay(); + }); +} + +// Checks the current user input for validity and triggers an error message accordingly. +function checkCurrentInput(currentInput) { + let wizard = document.querySelector("wizard"); + var finishButton = wizard.getButton("finish"); + var finishText = document.getElementById("finishText"); + var canAdvance; + + var errorMessage = checkProfileName(currentInput); + + if (!errorMessage) { + finishText.className = ""; + if (AppConstants.platform == "macosx") { + finishText.firstChild.data = gProfileManagerBundle.getString( + "profileFinishTextMac" + ); + } else { + finishText.firstChild.data = + gProfileManagerBundle.getString("profileFinishText"); + } + canAdvance = true; + } else { + finishText.className = "error"; + finishText.firstChild.data = errorMessage; + canAdvance = false; + } + + wizard.canAdvance = canAdvance; + finishButton.disabled = !canAdvance; + + updateProfileDisplay(); + + return canAdvance; +} + +function updateProfileName(aNewName) { + if (checkCurrentInput(aNewName)) { + gProfileRoot.leafName = saltName(aNewName); + updateProfileDisplay(); + } +} + +// Checks whether the given string is a valid profile name. +// Returns an error message describing the error in the name or "" when it's valid. +function checkProfileName(profileNameToCheck) { + // Check for emtpy profile name. + if (!/\S/.test(profileNameToCheck)) { + return gProfileManagerBundle.getString("profileNameEmpty"); + } + + // Check whether all characters in the profile name are allowed. + if (/([\\*:?<>|\/\"])/.test(profileNameToCheck)) { + return gProfileManagerBundle.getFormattedString("invalidChar", [RegExp.$1]); + } + + // Check whether a profile with the same name already exists. + if (profileExists(profileNameToCheck)) { + return gProfileManagerBundle.getString("profileExists"); + } + + // profileNameToCheck is valid. + return ""; +} + +function profileExists(aName) { + for (let profile of gProfileService.profiles) { + if (profile.name.toLowerCase() == aName.toLowerCase()) { + return true; + } + } + + return false; +} + +// Called when the first wizard page is shown. +function enableNextButton() { + document.querySelector("wizard").canAdvance = true; +} + +function onFinish(event) { + var profileName = document.getElementById("profileName").value; + var profile; + + // Create profile named profileName in profileRoot. + try { + profile = gProfileService.createProfile(gProfileRoot, profileName); + } catch (e) { + var profileCreationFailed = gProfileManagerBundle.getString( + "profileCreationFailed" + ); + var profileCreationFailedTitle = gProfileManagerBundle.getString( + "profileCreationFailedTitle" + ); + Services.prompt.alert( + window, + profileCreationFailedTitle, + profileCreationFailed + "\n" + e + ); + + event.preventDefault(); + return; + } + + if (window.arguments && window.arguments[1]) { + // Add new profile to the list in the Profile Manager. + window.arguments[1].CreateProfile(profile); + } else { + // Use the newly created Profile. + var profileLock = profile.lock(null); + + var dialogParams = window.arguments[0].QueryInterface( + I.nsIDialogParamBlock + ); + dialogParams.objects.insertElementAt(profileLock, 0); + } +} diff --git a/toolkit/profile/content/createProfileWizard.xhtml b/toolkit/profile/content/createProfileWizard.xhtml new file mode 100644 index 0000000000..34db95db1e --- /dev/null +++ b/toolkit/profile/content/createProfileWizard.xhtml @@ -0,0 +1,90 @@ +<?xml version="1.0"?> +<!-- 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/. --> + +<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> + +<!DOCTYPE wizard> + +<window + id="createProfileWizard" + data-l10n-id="create-profile-window2" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + onload="initWizard();" + data-l10n-attrs="style" +> + <linkset> + <html:link rel="localization" href="branding/brand.ftl" /> + <html:link + rel="localization" + href="toolkit/global/createProfileWizard.ftl" + /> + </linkset> + + <script src="chrome://global/content/customElements.js" /> + <script src="chrome://global/content/globalOverlay.js" /> + <script src="chrome://global/content/editMenuOverlay.js" /> + <script src="chrome://mozapps/content/profile/createProfileWizard.js" /> + + <wizard> + <stringbundle + id="bundle_profileManager" + src="chrome://mozapps/locale/profile/profileSelection.properties" + /> + + <wizardpage + id="explanation" + data-header-label-id="create-profile-first-page-header2" + > + <description data-l10n-id="profile-creation-explanation-1"></description> + <description data-l10n-id="profile-creation-explanation-2"></description> + <description data-l10n-id="profile-creation-explanation-3"></description> + <spacer flex="1" /> + <description data-l10n-id="profile-creation-explanation-4"></description> + </wizardpage> + + <wizardpage + id="createProfile" + data-header-label-id="create-profile-last-page-header2" + > + <description data-l10n-id="profile-creation-intro"></description> + + <label data-l10n-id="profile-prompt" control="ProfileName"></label> + <html:input + id="profileName" + data-l10n-id="profile-default-name" + data-l10n-attrs="value" + oninput="updateProfileName(this.value);" + /> + + <separator /> + + <description data-l10n-id="profile-directory-explanation"></description> + + <vbox class="indent" flex="1" style="overflow: auto"> + <description id="profileDisplay">*</description> + </vbox> + + <hbox> + <button + data-l10n-id="create-profile-choose-folder" + oncommand="chooseProfileFolder();" + /> + + <button + id="useDefault" + data-l10n-id="create-profile-use-default" + oncommand="setDisplayToDefaultFolder(); updateProfileDisplay();" + disabled="true" + /> + </hbox> + + <separator /> + + <description id="finishText">*</description> + </wizardpage> + </wizard> +</window> diff --git a/toolkit/profile/content/profileDowngrade.js b/toolkit/profile/content/profileDowngrade.js new file mode 100644 index 0000000000..ba1f723ec2 --- /dev/null +++ b/toolkit/profile/content/profileDowngrade.js @@ -0,0 +1,39 @@ +/* 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/. */ + +let gParams; + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +function init() { + /* + * The C++ code passes a dialog param block using its integers as in and out + * arguments for this UI. The following are the uses of the integers: + * + * 0: A set of flags from nsIToolkitProfileService.downgradeUIFlags. + * 1: A return argument, one of nsIToolkitProfileService.downgradeUIChoice. + */ + gParams = window.arguments[0].QueryInterface(Ci.nsIDialogParamBlock); + if (AppConstants.MOZ_SERVICES_SYNC) { + let hasSync = gParams.GetInt(0) & Ci.nsIToolkitProfileService.hasSync; + + document.getElementById("sync").hidden = !hasSync; + document.getElementById("nosync").hidden = hasSync; + } + + document.addEventListener("dialogextra1", createProfile); + document.addEventListener("dialogaccept", quit); + document.addEventListener("dialogcancel", quit); +} + +function quit() { + gParams.SetInt(1, Ci.nsIToolkitProfileService.quit); +} + +function createProfile() { + gParams.SetInt(1, Ci.nsIToolkitProfileService.createNewProfile); + window.close(); +} diff --git a/toolkit/profile/content/profileDowngrade.xhtml b/toolkit/profile/content/profileDowngrade.xhtml new file mode 100644 index 0000000000..3e1c22f832 --- /dev/null +++ b/toolkit/profile/content/profileDowngrade.xhtml @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<!-- 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/. --> + +<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> +<?xml-stylesheet href="chrome://mozapps/skin/profileDowngrade.css" type="text/css"?> + +<!DOCTYPE window> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + prefwidth="min-width" + data-l10n-id="profiledowngrade-window2" + data-l10n-attrs="title,style" + onload="init()"> +<linkset> + <html:link rel="localization" href="branding/brand.ftl"/> + <html:link rel="localization" href="toolkit/branding/accounts.ftl"/> + <html:link rel="localization" href="toolkit/global/profileDowngrade.ftl"/> +</linkset> +<dialog buttons="accept,extra1" buttonpack="end" + buttonidextra1="profiledowngrade-window-create" + buttonidaccept="profiledowngrade-quit"> + + <script src="profileDowngrade.js"/> + <script src="chrome://global/content/customElements.js"/> + + <hbox flex="1" align="start"> + <image id="info" role="presentation"/> + <vbox flex="1"> + <description data-l10n-id="profiledowngrade-nosync"></description> +#ifdef MOZ_SERVICES_SYNC + <description data-l10n-id="profiledowngrade-sync"></description> +#endif + </vbox> + </hbox> + +</dialog> +</window> diff --git a/toolkit/profile/content/profileSelection.js b/toolkit/profile/content/profileSelection.js new file mode 100644 index 0000000000..b5bbfd5ab1 --- /dev/null +++ b/toolkit/profile/content/profileSelection.js @@ -0,0 +1,355 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * + * 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/. */ + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +const C = Cc; +const I = Ci; + +const ToolkitProfileService = "@mozilla.org/toolkit/profile-service;1"; + +const fluentStrings = new Localization([ + "branding/brand.ftl", + "toolkit/global/profileSelection.ftl", +]); + +var gDialogParams; +var gProfileManagerBundle; +var gBrandBundle; +var gProfileService; +var gNeedsFlush = false; + +function getFluentString(str) { + return fluentStrings.formatValue(str); +} + +function startup() { + try { + gDialogParams = window.arguments[0].QueryInterface(I.nsIDialogParamBlock); + + gProfileService = C[ToolkitProfileService].getService( + I.nsIToolkitProfileService + ); + + gProfileManagerBundle = document.getElementById("bundle_profileManager"); + gBrandBundle = document.getElementById("bundle_brand"); + + document.getElementById("profileWindow").centerWindowOnScreen(); + + var profilesElement = document.getElementById("profiles"); + + for (let profile of gProfileService.profiles.entries(I.nsIToolkitProfile)) { + var listitem = profilesElement.appendItem(profile.name, ""); + + var tooltiptext = gProfileManagerBundle.getFormattedString( + "profileTooltip", + [profile.name, profile.rootDir.path] + ); + listitem.setAttribute("tooltiptext", tooltiptext); + listitem.profile = profile; + try { + if (profile === gProfileService.defaultProfile) { + setTimeout( + function (a) { + profilesElement.ensureElementIsVisible(a); + profilesElement.selectItem(a); + }, + 0, + listitem + ); + } + } catch (e) {} + } + + var autoSelectLastProfile = document.getElementById( + "autoSelectLastProfile" + ); + autoSelectLastProfile.checked = gProfileService.startWithLastProfile; + profilesElement.focus(); + } catch (e) { + window.close(); + throw e; + } + document.addEventListener("dialogaccept", acceptDialog); + document.addEventListener("dialogcancel", exitDialog); +} + +async function flush(cancelled) { + updateStartupPrefs(); + + gDialogParams.SetInt( + 1, + document.getElementById("offlineState").checked ? 1 : 0 + ); + + if (gNeedsFlush) { + try { + gProfileService.flush(); + } catch (e) { + let appName = gBrandBundle.getString("brandShortName"); + + let title = gProfileManagerBundle.getString("flushFailTitle"); + let restartButton = gProfileManagerBundle.getFormattedString( + "flushFailRestartButton", + [appName] + ); + let exitButton = gProfileManagerBundle.getString("flushFailExitButton"); + + let message; + if (e.result == undefined) { + message = await getFluentString("profile-selection-conflict-message"); + } else { + message = gProfileManagerBundle.getString("flushFailMessage"); + } + + const PS = Ci.nsIPromptService; + let result = Services.prompt.confirmEx( + window, + title, + message, + PS.BUTTON_POS_0 * PS.BUTTON_TITLE_IS_STRING + + PS.BUTTON_POS_1 * PS.BUTTON_TITLE_IS_STRING, + restartButton, + exitButton, + null, + null, + {} + ); + + gDialogParams.SetInt( + 0, + result == 0 + ? Ci.nsIToolkitProfileService.restart + : Ci.nsIToolkitProfileService.exit + ); + return; + } + gNeedsFlush = false; + } + + gDialogParams.SetInt( + 0, + cancelled + ? Ci.nsIToolkitProfileService.exit + : Ci.nsIToolkitProfileService.launchWithProfile + ); +} + +function acceptDialog(event) { + var appName = gBrandBundle.getString("brandShortName"); + + var profilesElement = document.getElementById("profiles"); + var selectedProfile = profilesElement.selectedItem; + if (!selectedProfile) { + var pleaseSelectTitle = + gProfileManagerBundle.getString("pleaseSelectTitle"); + var pleaseSelect = gProfileManagerBundle.getFormattedString( + "pleaseSelect", + [appName] + ); + Services.prompt.alert(window, pleaseSelectTitle, pleaseSelect); + event.preventDefault(); + return; + } + + gDialogParams.objects.insertElementAt(selectedProfile.profile.rootDir, 0); + gDialogParams.objects.insertElementAt(selectedProfile.profile.localDir, 1); + + if (gProfileService.defaultProfile != selectedProfile.profile) { + try { + gProfileService.defaultProfile = selectedProfile.profile; + gNeedsFlush = true; + } catch (e) { + // This can happen on dev-edition. We'll still restart with the selected + // profile based on the lock's directories. + } + } + flush(false); +} + +function exitDialog() { + flush(true); +} + +function updateStartupPrefs() { + var autoSelectLastProfile = document.getElementById("autoSelectLastProfile"); + if (gProfileService.startWithLastProfile != autoSelectLastProfile.checked) { + gProfileService.startWithLastProfile = autoSelectLastProfile.checked; + gNeedsFlush = true; + } +} + +// handle key event on listboxes +function onProfilesKey(aEvent) { + switch (aEvent.keyCode) { + case KeyEvent.DOM_VK_BACK_SPACE: + if (AppConstants.platform != "macosx") { + break; + } + // fall through + case KeyEvent.DOM_VK_DELETE: + ConfirmDelete(); + break; + case KeyEvent.DOM_VK_F2: + RenameProfile(); + break; + } +} + +function onProfilesDblClick(aEvent) { + if (aEvent.target.closest("richlistitem")) { + document.getElementById("profileWindow").acceptDialog(); + } +} + +// invoke the createProfile Wizard +function CreateProfileWizard() { + window.openDialog( + "chrome://mozapps/content/profile/createProfileWizard.xhtml", + "", + "centerscreen,chrome,modal,titlebar", + gProfileService, + { CreateProfile } + ); +} + +/** + * Called from createProfileWizard to update the display. + */ +function CreateProfile(aProfile) { + var profilesElement = document.getElementById("profiles"); + + var listitem = profilesElement.appendItem(aProfile.name, ""); + + var tooltiptext = gProfileManagerBundle.getFormattedString("profileTooltip", [ + aProfile.name, + aProfile.rootDir.path, + ]); + listitem.setAttribute("tooltiptext", tooltiptext); + listitem.profile = aProfile; + + profilesElement.ensureElementIsVisible(listitem); + profilesElement.selectItem(listitem); + + gNeedsFlush = true; +} + +// rename the selected profile +function RenameProfile() { + var profilesElement = document.getElementById("profiles"); + var selectedItem = profilesElement.selectedItem; + if (!selectedItem) { + return false; + } + + var selectedProfile = selectedItem.profile; + + var oldName = selectedProfile.name; + var newName = { value: oldName }; + + var dialogTitle = gProfileManagerBundle.getString("renameProfileTitle"); + var msg = gProfileManagerBundle.getFormattedString("renameProfilePrompt", [ + oldName, + ]); + + if ( + Services.prompt.prompt(window, dialogTitle, msg, newName, null, { + value: 0, + }) + ) { + newName = newName.value; + + // User hasn't changed the profile name. Treat as if cancel was pressed. + if (newName == oldName) { + return false; + } + + try { + selectedProfile.name = newName; + gNeedsFlush = true; + } catch (e) { + var alTitle = gProfileManagerBundle.getString("profileNameInvalidTitle"); + var alMsg = gProfileManagerBundle.getFormattedString( + "profileNameInvalid", + [newName] + ); + Services.prompt.alert(window, alTitle, alMsg); + return false; + } + + selectedItem.firstChild.setAttribute("value", newName); + var tiptext = gProfileManagerBundle.getFormattedString("profileTooltip", [ + newName, + selectedProfile.rootDir.path, + ]); + selectedItem.setAttribute("tooltiptext", tiptext); + + return true; + } + + return false; +} + +function ConfirmDelete() { + var profileList = document.getElementById("profiles"); + + var selectedItem = profileList.selectedItem; + if (!selectedItem) { + return false; + } + + var selectedProfile = selectedItem.profile; + var deleteFiles = false; + + if (selectedProfile.rootDir.exists()) { + var dialogTitle = gProfileManagerBundle.getString("deleteTitle"); + var dialogText = gProfileManagerBundle.getFormattedString( + "deleteProfileConfirm", + [selectedProfile.rootDir.path] + ); + + var buttonPressed = Services.prompt.confirmEx( + window, + dialogTitle, + dialogText, + 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, + gProfileManagerBundle.getString("dontDeleteFiles"), + null, + gProfileManagerBundle.getString("deleteFiles"), + null, + { value: 0 } + ); + if (buttonPressed == 1) { + return false; + } + + if (buttonPressed == 2) { + deleteFiles = true; + } + } + + try { + selectedProfile.remove(deleteFiles); + gNeedsFlush = true; + } catch (e) { + let title = gProfileManagerBundle.getString("profileDeletionFailedTitle"); + let msg = gProfileManagerBundle.getString("profileDeletionFailed"); + Services.prompt.alert(window, title, msg); + + return true; + } + + profileList.removeChild(selectedItem); + if (profileList.firstChild != undefined) { + profileList.selectItem(profileList.firstChild); + } + + return true; +} diff --git a/toolkit/profile/content/profileSelection.xhtml b/toolkit/profile/content/profileSelection.xhtml new file mode 100644 index 0000000000..0351295b22 --- /dev/null +++ b/toolkit/profile/content/profileSelection.xhtml @@ -0,0 +1,101 @@ +<?xml version="1.0"?> +<!-- -*- Mode: SGML; indent-tabs-mode: nil; -*- --> +<!-- + + 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/. --> + +<?xml-stylesheet href="chrome://mozapps/skin/profileSelection.css" type="text/css"?> + +<!DOCTYPE window> + +<window + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml" + class="non-resizable" + data-l10n-id="profile-selection-window" + orient="vertical" + prefwidth="min-width" + style="min-width: 30em" + onload="startup();" +> + <dialog + id="profileWindow" + buttons="accept,cancel" + buttonidaccept="profile-selection-button-accept" + buttonidcancel="profile-selection-button-cancel" + > + <linkset> + <html:link rel="localization" href="branding/brand.ftl" /> + <html:link + rel="localization" + href="toolkit/global/profileSelection.ftl" + /> + </linkset> + + <script src="chrome://global/content/customElements.js" /> + + <stringbundle + id="bundle_profileManager" + src="chrome://mozapps/locale/profile/profileSelection.properties" + /> + <stringbundle + id="bundle_brand" + src="chrome://branding/locale/brand.properties" + /> + + <script src="chrome://mozapps/content/profile/profileSelection.js" /> + + <description + class="label" + data-l10n-id="profile-manager-description" + ></description> + + <separator class="thin" /> + + <hbox class="indent"> + <vbox id="managebuttons"> + <button + id="newbutton" + data-l10n-id="profile-selection-new-button" + oncommand="CreateProfileWizard();" + /> + <button + id="renbutton" + data-l10n-id="profile-selection-rename-button" + oncommand="RenameProfile();" + /> + <button + id="delbutton" + data-l10n-id="profile-selection-delete-button" + oncommand="ConfirmDelete();" + /> + </vbox> + + <vbox id="profilesContainer"> + <richlistbox + id="profiles" + class="theme-listbox" + seltype="single" + ondblclick="onProfilesDblClick(event)" + onkeypress="onProfilesKey(event);" + > + </richlistbox> + + <!-- Bug 257777 --> + <checkbox + id="offlineState" + data-l10n-id="profile-manager-work-offline" + native="true" + /> + + <checkbox + id="autoSelectLastProfile" + data-l10n-id="profile-manager-use-selected" + native="true" + /> + </vbox> + </hbox> + </dialog> +</window> |