diff options
Diffstat (limited to 'toolkit/profile/content')
-rw-r--r-- | toolkit/profile/content/createProfileWizard.js | 225 | ||||
-rw-r--r-- | toolkit/profile/content/createProfileWizard.xul | 74 | ||||
-rw-r--r-- | toolkit/profile/content/profileSelection.js | 269 | ||||
-rw-r--r-- | toolkit/profile/content/profileSelection.xul | 70 |
4 files changed, 638 insertions, 0 deletions
diff --git a/toolkit/profile/content/createProfileWizard.js b/toolkit/profile/content/createProfileWizard.js new file mode 100644 index 000000000..1963f66bc --- /dev/null +++ b/toolkit/profile/content/createProfileWizard.js @@ -0,0 +1,225 @@ +/* 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 = Components.classes; +const I = Components.interfaces; + +Components.utils.import("resource://gre/modules/AppConstants.jsm"); + +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"); + + var dirService = C["@mozilla.org/file/directory_service;1"].getService(I.nsIProperties); + gDefaultProfileParent = dirService.get("DefProfRt", I.nsIFile); + + // Initialize the profile location display. + gProfileDisplay = document.getElementById("profileDisplay").firstChild; + 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.show(); + 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) +{ + var finishButton = document.documentElement.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; + } + + document.documentElement.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) +{ + var profiles = gProfileService.profiles; + while (profiles.hasMoreElements()) { + var profile = profiles.getNext().QueryInterface(I.nsIToolkitProfile); + if (profile.name.toLowerCase() == aName.toLowerCase()) + return true; + } + + return false; +} + +// Called when the first wizard page is shown. +function enableNextButton() +{ + document.documentElement.canAdvance = true; +} + +function onFinish() +{ + 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"); + var promptService = C["@mozilla.org/embedcomp/prompt-service;1"]. + getService(I.nsIPromptService); + promptService.alert(window, profileCreationFailedTitle, + profileCreationFailed + "\n" + e); + + return false; + } + + // window.opener is false if the Create Profile Wizard was opened from the + // command line. + if (window.opener) { + // Add new profile to the list in the Profile Manager. + window.opener.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, false); + } + + // Exit the wizard. + return true; +} diff --git a/toolkit/profile/content/createProfileWizard.xul b/toolkit/profile/content/createProfileWizard.xul new file mode 100644 index 000000000..eab1a9341 --- /dev/null +++ b/toolkit/profile/content/createProfileWizard.xul @@ -0,0 +1,74 @@ +<?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/" type="text/css"?> + +<!DOCTYPE wizard [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % profileDTD SYSTEM "chrome://mozapps/locale/profile/createProfileWizard.dtd"> +%profileDTD; +]> + +<wizard id="createProfileWizard" + title="&newprofile.title;" + 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" + onwizardfinish="return onFinish();" + onload="initWizard();" + style="&window.size;"> + + <stringbundle id="bundle_profileManager" + src="chrome://mozapps/locale/profile/profileSelection.properties"/> + + <script type="application/javascript" src="chrome://mozapps/content/profile/createProfileWizard.js"/> + + <wizardpage id="explanation" onpageshow="enableNextButton();"> + <description>&profileCreationExplanation_1.text;</description> + <description>&profileCreationExplanation_2.text;</description> + <description>&profileCreationExplanation_3.text;</description> + <spacer flex="1"/> +#ifdef XP_MACOSX + <description>&profileCreationExplanation_4Mac.text;</description> +#else +#ifdef XP_UNIX + <description>&profileCreationExplanation_4Gnome.text;</description> +#else + <description>&profileCreationExplanation_4.text;</description> +#endif +#endif + </wizardpage> + + <wizardpage id="createProfile" onpageshow="initSecondWizardPage();"> + <description>&profileCreationIntro.text;</description> + + <label accesskey="&profilePrompt.accesskey;" control="ProfileName">&profilePrompt.label;</label> + <textbox id="profileName" value="&profileDefaultName;" + oninput="updateProfileName(this.value);"/> + + <separator/> + + <description>&profileDirectoryExplanation.text;</description> + + <vbox class="indent" flex="1" style="overflow: auto;"> + <description id="profileDisplay">*</description> + </vbox> + + <hbox> + <button label="&button.choosefolder.label;" oncommand="chooseProfileFolder();" + accesskey="&button.choosefolder.accesskey;"/> + + <button id="useDefault" label="&button.usedefault.label;" + oncommand="setDisplayToDefaultFolder(); updateProfileDisplay();" + accesskey="&button.usedefault.accesskey;" disabled="true"/> + </hbox> + + <separator/> + + <description id="finishText">*</description> + </wizardpage> + +</wizard> diff --git a/toolkit/profile/content/profileSelection.js b/toolkit/profile/content/profileSelection.js new file mode 100644 index 000000000..02b9d6873 --- /dev/null +++ b/toolkit/profile/content/profileSelection.js @@ -0,0 +1,269 @@ +/* -*- 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/. */ + +Components.utils.import("resource://gre/modules/AppConstants.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +const C = Components.classes; +const I = Components.interfaces; + +const ToolkitProfileService = "@mozilla.org/toolkit/profile-service;1"; + +var gDialogParams; +var gProfileManagerBundle; +var gBrandBundle; +var gProfileService; + +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.documentElement.centerWindowOnScreen(); + + var profilesElement = document.getElementById("profiles"); + + var profileList = gProfileService.profiles; + while (profileList.hasMoreElements()) { + var profile = profileList.getNext().QueryInterface(I.nsIToolkitProfile); + + var listitem = profilesElement.appendItem(profile.name, ""); + + var tooltiptext = + gProfileManagerBundle.getFormattedString("profileTooltip", [profile.name, profile.rootDir.path]); + listitem.setAttribute("tooltiptext", tooltiptext); + listitem.setAttribute("class", "listitem-iconic"); + listitem.profile = profile; + try { + if (profile === gProfileService.selectedProfile) { + 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); + } +} + +function acceptDialog() +{ + 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); + + return false; + } + + var profileLock; + + try { + profileLock = selectedProfile.profile.lock({ value: null }); + } + catch (e) { + if (!selectedProfile.profile.rootDir.exists()) { + var missingTitle = gProfileManagerBundle.getString("profileMissingTitle"); + var missing = + gProfileManagerBundle.getFormattedString("profileMissing", [appName]); + Services.prompt.alert(window, missingTitle, missing); + return false; + } + + var lockedTitle = gProfileManagerBundle.getString("profileLockedTitle"); + var locked = + gProfileManagerBundle.getFormattedString("profileLocked2", [appName, selectedProfile.profile.name, appName]); + Services.prompt.alert(window, lockedTitle, locked); + + return false; + } + gDialogParams.objects.insertElementAt(profileLock.nsIProfileLock, 0, false); + + gProfileService.selectedProfile = selectedProfile.profile; + gProfileService.defaultProfile = selectedProfile.profile; + updateStartupPrefs(); + + gDialogParams.SetInt(0, 1); + + gDialogParams.SetString(0, selectedProfile.profile.name); + + return true; +} + +function exitDialog() +{ + updateStartupPrefs(); + + return true; +} + +function updateStartupPrefs() +{ + var autoSelectLastProfile = document.getElementById("autoSelectLastProfile"); + gProfileService.startWithLastProfile = autoSelectLastProfile.checked; + + /* Bug 257777 */ + gProfileService.startOffline = document.getElementById("offlineState").checked; +} + +// handle key event on listboxes +function onProfilesKey(aEvent) +{ + switch ( aEvent.keyCode ) + { + case KeyEvent.DOM_VK_BACK_SPACE: + if (AppConstants.platform != "macosx") + break; + case KeyEvent.DOM_VK_DELETE: + ConfirmDelete(); + break; + case KeyEvent.DOM_VK_F2: + RenameProfile(); + break; + } +} + +function onProfilesDblClick(aEvent) +{ + if (aEvent.target.localName == "listitem") + document.documentElement.acceptDialog(); +} + +// invoke the createProfile Wizard +function CreateProfileWizard() +{ + window.openDialog('chrome://mozapps/content/profile/createProfileWizard.xul', + '', 'centerscreen,chrome,modal,titlebar', gProfileService); +} + +/** + * 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.setAttribute("class", "listitem-iconic"); + listitem.profile = aProfile; + + profilesElement.ensureElementIsVisible(listitem); + profilesElement.selectItem(listitem); +} + +// 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; + } + catch (e) { + var alTitle = gProfileManagerBundle.getString("profileNameInvalidTitle"); + var alMsg = gProfileManagerBundle.getFormattedString("profileNameInvalid", [newName]); + Services.prompt.alert(window, alTitle, alMsg); + return false; + } + + selectedItem.label = newName; + var tiptext = gProfileManagerBundle. + getFormattedString("profileTooltip", + [newName, selectedProfile.rootDir.path]); + selectedItem.setAttribute("tooltiptext", tiptext); + + return true; + } + + return false; +} + +function ConfirmDelete() +{ + var deleteButton = document.getElementById("delbutton"); + 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; + } + + selectedProfile.remove(deleteFiles); + profileList.removeChild(selectedItem); + if (profileList.firstChild != undefined) { + profileList.selectItem(profileList.firstChild); + } + + return true; +} diff --git a/toolkit/profile/content/profileSelection.xul b/toolkit/profile/content/profileSelection.xul new file mode 100644 index 000000000..e5dfabb42 --- /dev/null +++ b/toolkit/profile/content/profileSelection.xul @@ -0,0 +1,70 @@ +<?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/profile/profileSelection.css" type="text/css"?> + +<!DOCTYPE window [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % profileDTD SYSTEM "chrome://mozapps/locale/profile/profileSelection.dtd"> +%profileDTD; +]> + +<dialog + id="profileWindow" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + class="non-resizable" + title="&windowtitle.label;" + orient="vertical" + buttons="accept,cancel" + style="width: 30em;" + onload="startup();" + ondialogaccept="return acceptDialog()" + ondialogcancel="return exitDialog()" + buttonlabelaccept="&start.label;" + buttonlabelcancel="&exit.label;"> + + <stringbundle id="bundle_profileManager" + src="chrome://mozapps/locale/profile/profileSelection.properties"/> + <stringbundle id="bundle_brand" + src="chrome://branding/locale/brand.properties"/> + + <script type="application/javascript" src="chrome://mozapps/content/profile/profileSelection.js"/> + + <description class="label">&pmDescription.label;</description> + + <separator class="thin"/> + + <hbox class="profile-box indent" flex="1"> + + <vbox id="managebuttons"> + <button id="newbutton" label="&newButton.label;" + accesskey="&newButton.accesskey;" oncommand="CreateProfileWizard();"/> + <button id="renbutton" label="&renameButton.label;" + accesskey="&renameButton.accesskey;" oncommand="RenameProfile();"/> + <button id="delbutton" label="&deleteButton.label;" + accesskey="&deleteButton.accesskey;" oncommand="ConfirmDelete();"/> + </vbox> + + <separator flex="1"/> + + <vbox flex="1"> + <listbox id="profiles" rows="5" seltype="single" + ondblclick="onProfilesDblClick(event)" + onkeypress="onProfilesKey(event);"> + </listbox> + + <!-- Bug 257777 --> + <checkbox id="offlineState" label="&offlineState.label;" accesskey="&offlineState.accesskey;"/> + + <checkbox id="autoSelectLastProfile" label="&useSelected.label;" + accesskey="&useSelected.accesskey;"/> + </vbox> + + </hbox> +</dialog> |