Bug 1867925 - Mark some storage-access-api tests as intermittent after wpt-sync....
[gecko.git] / toolkit / profile / content / createProfileWizard.js
blob9e87fb42207d6d8e2cb054562bf50080fe9bb929
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/. */
5 const C = Cc;
6 const I = Ci;
8 const { AppConstants } = ChromeUtils.importESModule(
9   "resource://gre/modules/AppConstants.sys.mjs"
12 const ToolkitProfileService = "@mozilla.org/toolkit/profile-service;1";
14 var gProfileService;
15 var gProfileManagerBundle;
17 var gDefaultProfileParent;
19 // The directory where the profile will be created.
20 var gProfileRoot;
22 // Text node to display the location and name of the profile to create.
23 var gProfileDisplay;
25 // Called once when the wizard is opened.
26 function initWizard() {
27   try {
28     gProfileService = C[ToolkitProfileService].getService(
29       I.nsIToolkitProfileService
30     );
31     gProfileManagerBundle = document.getElementById("bundle_profileManager");
33     gDefaultProfileParent = Services.dirsvc.get("DefProfRt", I.nsIFile);
35     // Initialize the profile location display.
36     gProfileDisplay = document.getElementById("profileDisplay").firstChild;
37     document.addEventListener("wizardfinish", onFinish);
38     document
39       .getElementById("explanation")
40       .addEventListener("pageshow", enableNextButton);
41     document
42       .getElementById("createProfile")
43       .addEventListener("pageshow", initSecondWizardPage);
44     setDisplayToDefaultFolder();
45   } catch (e) {
46     window.close();
47     throw e;
48   }
51 // Called every time the second wizard page is displayed.
52 function initSecondWizardPage() {
53   var profileName = document.getElementById("profileName");
54   profileName.select();
55   profileName.focus();
57   // Initialize profile name validation.
58   checkCurrentInput(profileName.value);
61 const kSaltTable = [
62   "a",
63   "b",
64   "c",
65   "d",
66   "e",
67   "f",
68   "g",
69   "h",
70   "i",
71   "j",
72   "k",
73   "l",
74   "m",
75   "n",
76   "o",
77   "p",
78   "q",
79   "r",
80   "s",
81   "t",
82   "u",
83   "v",
84   "w",
85   "x",
86   "y",
87   "z",
88   "1",
89   "2",
90   "3",
91   "4",
92   "5",
93   "6",
94   "7",
95   "8",
96   "9",
97   "0",
100 var kSaltString = "";
101 for (var i = 0; i < 8; ++i) {
102   kSaltString += kSaltTable[Math.floor(Math.random() * kSaltTable.length)];
105 function saltName(aName) {
106   return kSaltString + "." + aName;
109 function setDisplayToDefaultFolder() {
110   var defaultProfileDir = gDefaultProfileParent.clone();
111   defaultProfileDir.append(
112     saltName(document.getElementById("profileName").value)
113   );
114   gProfileRoot = defaultProfileDir;
115   document.getElementById("useDefault").disabled = true;
118 function updateProfileDisplay() {
119   gProfileDisplay.data = gProfileRoot.path;
122 // Invoke a folder selection dialog for choosing the directory of profile storage.
123 function chooseProfileFolder() {
124   var newProfileRoot;
126   var dirChooser = C["@mozilla.org/filepicker;1"].createInstance(
127     I.nsIFilePicker
128   );
129   dirChooser.init(
130     window,
131     gProfileManagerBundle.getString("chooseFolder"),
132     I.nsIFilePicker.modeGetFolder
133   );
134   dirChooser.appendFilters(I.nsIFilePicker.filterAll);
136   // default to the Profiles folder
137   dirChooser.displayDirectory = gDefaultProfileParent;
139   dirChooser.open(() => {
140     newProfileRoot = dirChooser.file;
142     // Disable the "Default Folder..." button when the default profile folder
143     // was selected manually in the File Picker.
144     document.getElementById("useDefault").disabled =
145       newProfileRoot.parent.equals(gDefaultProfileParent);
147     gProfileRoot = newProfileRoot;
148     updateProfileDisplay();
149   });
152 // Checks the current user input for validity and triggers an error message accordingly.
153 function checkCurrentInput(currentInput) {
154   let wizard = document.querySelector("wizard");
155   var finishButton = wizard.getButton("finish");
156   var finishText = document.getElementById("finishText");
157   var canAdvance;
159   var errorMessage = checkProfileName(currentInput);
161   if (!errorMessage) {
162     finishText.className = "";
163     if (AppConstants.platform == "macosx") {
164       finishText.firstChild.data = gProfileManagerBundle.getString(
165         "profileFinishTextMac"
166       );
167     } else {
168       finishText.firstChild.data =
169         gProfileManagerBundle.getString("profileFinishText");
170     }
171     canAdvance = true;
172   } else {
173     finishText.className = "error";
174     finishText.firstChild.data = errorMessage;
175     canAdvance = false;
176   }
178   wizard.canAdvance = canAdvance;
179   finishButton.disabled = !canAdvance;
181   updateProfileDisplay();
183   return canAdvance;
186 function updateProfileName(aNewName) {
187   if (checkCurrentInput(aNewName)) {
188     gProfileRoot.leafName = saltName(aNewName);
189     updateProfileDisplay();
190   }
193 // Checks whether the given string is a valid profile name.
194 // Returns an error message describing the error in the name or "" when it's valid.
195 function checkProfileName(profileNameToCheck) {
196   // Check for emtpy profile name.
197   if (!/\S/.test(profileNameToCheck)) {
198     return gProfileManagerBundle.getString("profileNameEmpty");
199   }
201   // Check whether all characters in the profile name are allowed.
202   if (/([\\*:?<>|\/\"])/.test(profileNameToCheck)) {
203     return gProfileManagerBundle.getFormattedString("invalidChar", [RegExp.$1]);
204   }
206   // Check whether a profile with the same name already exists.
207   if (profileExists(profileNameToCheck)) {
208     return gProfileManagerBundle.getString("profileExists");
209   }
211   // profileNameToCheck is valid.
212   return "";
215 function profileExists(aName) {
216   for (let profile of gProfileService.profiles) {
217     if (profile.name.toLowerCase() == aName.toLowerCase()) {
218       return true;
219     }
220   }
222   return false;
225 // Called when the first wizard page is shown.
226 function enableNextButton() {
227   document.querySelector("wizard").canAdvance = true;
230 function onFinish(event) {
231   var profileName = document.getElementById("profileName").value;
232   var profile;
234   // Create profile named profileName in profileRoot.
235   try {
236     profile = gProfileService.createProfile(gProfileRoot, profileName);
237   } catch (e) {
238     var profileCreationFailed = gProfileManagerBundle.getString(
239       "profileCreationFailed"
240     );
241     var profileCreationFailedTitle = gProfileManagerBundle.getString(
242       "profileCreationFailedTitle"
243     );
244     Services.prompt.alert(
245       window,
246       profileCreationFailedTitle,
247       profileCreationFailed + "\n" + e
248     );
250     event.preventDefault();
251     return;
252   }
254   if (window.arguments && window.arguments[1]) {
255     // Add new profile to the list in the Profile Manager.
256     window.arguments[1].CreateProfile(profile);
257   } else {
258     // Use the newly created Profile.
259     var profileLock = profile.lock(null);
261     var dialogParams = window.arguments[0].QueryInterface(
262       I.nsIDialogParamBlock
263     );
264     dialogParams.objects.insertElementAt(profileLock, 0);
265   }