Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
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 Components.utils.import("resource://services-sync/main.js");
6 Components.utils.import("resource://gre/modules/Services.jsm");
8 XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
9 return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
10 });
12 const PAGE_NO_ACCOUNT = 0;
13 const PAGE_HAS_ACCOUNT = 1;
14 const PAGE_NEEDS_UPDATE = 2;
15 const PAGE_PLEASE_WAIT = 3;
16 const FXA_PAGE_LOGGED_OUT = 4;
17 const FXA_PAGE_LOGGED_IN = 5;
19 // Indexes into the "login status" deck.
20 // We are in a successful verified state - everything should work!
21 const FXA_LOGIN_VERIFIED = 0;
22 // We have logged in to an unverified account.
23 const FXA_LOGIN_UNVERIFIED = 1;
24 // We are logged in locally, but the server rejected our credentials.
25 const FXA_LOGIN_FAILED = 2;
27 let gSyncPane = {
28 _stringBundle: null,
29 prefArray: ["engine.bookmarks", "engine.passwords", "engine.prefs",
30 "engine.tabs", "engine.history"],
32 get page() {
33 return document.getElementById("weavePrefsDeck").selectedIndex;
34 },
36 set page(val) {
37 document.getElementById("weavePrefsDeck").selectedIndex = val;
38 },
40 get _usingCustomServer() {
41 return Weave.Svc.Prefs.isSet("serverURL");
42 },
44 needsUpdate: function () {
45 this.page = PAGE_NEEDS_UPDATE;
46 let label = document.getElementById("loginError");
47 label.value = Weave.Utils.getErrorString(Weave.Status.login);
48 label.className = "error";
49 },
51 init: function () {
52 // If the Service hasn't finished initializing, wait for it.
53 let xps = Components.classes["@mozilla.org/weave/service;1"]
54 .getService(Components.interfaces.nsISupports)
55 .wrappedJSObject;
57 if (xps.ready) {
58 this._init();
59 return;
60 }
62 // it may take some time before we can determine what provider to use
63 // and the state of that provider, so show the "please wait" page.
64 this.page = PAGE_PLEASE_WAIT;
66 let onUnload = function () {
67 window.removeEventListener("unload", onUnload, false);
68 try {
69 Services.obs.removeObserver(onReady, "weave:service:ready");
70 } catch (e) {}
71 };
73 let onReady = function () {
74 Services.obs.removeObserver(onReady, "weave:service:ready");
75 window.removeEventListener("unload", onUnload, false);
76 this._init();
77 }.bind(this);
79 Services.obs.addObserver(onReady, "weave:service:ready", false);
80 window.addEventListener("unload", onUnload, false);
82 xps.ensureLoaded();
83 },
85 _init: function () {
86 let topics = ["weave:service:login:error",
87 "weave:service:login:finish",
88 "weave:service:start-over:finish",
89 "weave:service:setup-complete",
90 "weave:service:logout:finish",
91 FxAccountsCommon.ONVERIFIED_NOTIFICATION];
93 // Add the observers now and remove them on unload
94 //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
95 // of `this`. Fix in a followup. (bug 583347)
96 topics.forEach(function (topic) {
97 Weave.Svc.Obs.add(topic, this.updateWeavePrefs, this);
98 }, this);
99 window.addEventListener("unload", function() {
100 topics.forEach(function (topic) {
101 Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this);
102 }, gSyncPane);
103 }, false);
105 this._stringBundle =
106 Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties");
107 this.updateWeavePrefs();
108 },
110 updateWeavePrefs: function () {
111 let service = Components.classes["@mozilla.org/weave/service;1"]
112 .getService(Components.interfaces.nsISupports)
113 .wrappedJSObject;
114 // service.fxAccountsEnabled is false iff sync is already configured for
115 // the legacy provider.
116 if (service.fxAccountsEnabled) {
117 // determine the fxa status...
118 this.page = PAGE_PLEASE_WAIT;
119 Components.utils.import("resource://gre/modules/FxAccounts.jsm");
120 fxAccounts.getSignedInUser().then(data => {
121 if (!data) {
122 this.page = FXA_PAGE_LOGGED_OUT;
123 return;
124 }
125 this.page = FXA_PAGE_LOGGED_IN;
126 // We are logged in locally, but maybe we are in a state where the
127 // server rejected our credentials (eg, password changed on the server)
128 let fxaLoginStatus = document.getElementById("fxaLoginStatus");
129 let enginesListDisabled;
130 // Not Verfied implies login error state, so check that first.
131 if (!data.verified) {
132 fxaLoginStatus.selectedIndex = FXA_LOGIN_UNVERIFIED;
133 enginesListDisabled = true;
134 // So we think we are logged in, so login problems are next.
135 // (Although if the Sync identity manager is still initializing, we
136 // ignore login errors and assume all will eventually be good.)
137 // LOGIN_FAILED_LOGIN_REJECTED explicitly means "you must log back in".
138 // All other login failures are assumed to be transient and should go
139 // away by themselves, so aren't reflected here.
140 } else if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
141 fxaLoginStatus.selectedIndex = FXA_LOGIN_FAILED;
142 enginesListDisabled = true;
143 // Else we must be golden (or in an error state we expect to magically
144 // resolve itself)
145 } else {
146 fxaLoginStatus.selectedIndex = FXA_LOGIN_VERIFIED;
147 enginesListDisabled = false;
148 }
149 document.getElementById("fxaEmailAddress1").textContent = data.email;
150 document.getElementById("fxaEmailAddress2").textContent = data.email;
151 document.getElementById("fxaEmailAddress3").textContent = data.email;
152 document.getElementById("fxaSyncComputerName").value = Weave.Service.clientsEngine.localName;
153 let engines = document.getElementById("fxaSyncEngines")
154 for (let checkbox of engines.querySelectorAll("checkbox")) {
155 checkbox.disabled = enginesListDisabled;
156 }
158 let checkbox = document.getElementById("fxa-pweng-chk");
159 let help = document.getElementById("fxa-pweng-help");
160 let allowPasswordsEngine = service.allowPasswordsEngine;
162 if (!allowPasswordsEngine) {
163 checkbox.checked = false;
164 }
166 checkbox.disabled = !allowPasswordsEngine || enginesListDisabled;
167 help.hidden = allowPasswordsEngine || enginesListDisabled;
168 });
169 // If fxAccountEnabled is false and we are in a "not configured" state,
170 // then fxAccounts is probably fully disabled rather than just unconfigured,
171 // so handle this case. This block can be removed once we remove support
172 // for fxAccounts being disabled.
173 } else if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED ||
174 Weave.Svc.Prefs.get("firstSync", "") == "notReady") {
175 this.page = PAGE_NO_ACCOUNT;
176 // else: sync was previously configured for the legacy provider, so we
177 // make the "old" panels available.
178 } else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE ||
179 Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
180 this.needsUpdate();
181 } else {
182 this.page = PAGE_HAS_ACCOUNT;
183 document.getElementById("accountName").value = Weave.Service.identity.account;
184 document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName;
185 document.getElementById("tosPP").hidden = this._usingCustomServer;
186 }
187 },
189 startOver: function (showDialog) {
190 if (showDialog) {
191 let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
192 Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL +
193 Services.prompt.BUTTON_POS_1_DEFAULT;
194 let buttonChoice =
195 Services.prompt.confirmEx(window,
196 this._stringBundle.GetStringFromName("syncUnlink.title"),
197 this._stringBundle.GetStringFromName("syncUnlink.label"),
198 flags,
199 this._stringBundle.GetStringFromName("syncUnlinkConfirm.label"),
200 null, null, null, {});
202 // If the user selects cancel, just bail
203 if (buttonChoice == 1) {
204 return;
205 }
206 }
208 Weave.Service.startOver();
209 this.updateWeavePrefs();
210 },
212 updatePass: function () {
213 if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
214 gSyncUtils.changePassword();
215 } else {
216 gSyncUtils.updatePassphrase();
217 }
218 },
220 resetPass: function () {
221 if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
222 gSyncUtils.resetPassword();
223 } else {
224 gSyncUtils.resetPassphrase();
225 }
226 },
228 /**
229 * Invoke the Sync setup wizard.
230 *
231 * @param wizardType
232 * Indicates type of wizard to launch:
233 * null -- regular set up wizard
234 * "pair" -- pair a device first
235 * "reset" -- reset sync
236 */
237 openSetup: function (wizardType) {
238 let service = Components.classes["@mozilla.org/weave/service;1"]
239 .getService(Components.interfaces.nsISupports)
240 .wrappedJSObject;
242 if (service.fxAccountsEnabled) {
243 this.openContentInBrowser("about:accounts");
244 } else {
245 let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
246 if (win) {
247 win.focus();
248 } else {
249 window.openDialog("chrome://browser/content/sync/setup.xul",
250 "weaveSetup", "centerscreen,chrome,resizable=no",
251 wizardType);
252 }
253 }
254 },
256 openContentInBrowser: function(url) {
257 let win = Services.wm.getMostRecentWindow("navigator:browser");
258 if (!win) {
259 // no window to use, so use _openLink to create a new one. We don't
260 // always use that as it prefers to open a new window rather than use
261 // an existing one.
262 gSyncUtils._openLink(url);
263 return;
264 }
265 win.switchToTabHavingURI(url, true);
266 // seeing as we are doing this in a tab we close the prefs dialog.
267 window.close();
268 },
270 signUp: function() {
271 this.openContentInBrowser("about:accounts?action=signup");
272 },
274 signIn: function() {
275 this.openContentInBrowser("about:accounts?action=signin");
276 },
278 reSignIn: function() {
279 this.openContentInBrowser("about:accounts?action=reauth");
280 },
282 manageFirefoxAccount: function() {
283 let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri");
284 this.openContentInBrowser(url);
285 },
287 verifyFirefoxAccount: function() {
288 Components.utils.import("resource://gre/modules/FxAccounts.jsm");
289 fxAccounts.resendVerificationEmail().then(() => {
290 fxAccounts.getSignedInUser().then(data => {
291 let sb = this._stringBundle;
292 let title = sb.GetStringFromName("firefoxAccountsVerificationSentTitle");
293 let heading = sb.formatStringFromName("firefoxAccountsVerificationSentHeading",
294 [data.email], 1);
295 let description = sb.GetStringFromName("firefoxAccountVerificationSentDescription");
297 Services.prompt.alert(window, title, heading + "\n\n" + description);
298 });
299 });
300 },
302 openOldSyncSupportPage: function() {
303 let url = Services.urlFormatter.formatURLPref('app.support.baseURL') + "old-sync"
304 this.openContentInBrowser(url);
305 },
307 unlinkFirefoxAccount: function(confirm) {
308 if (confirm) {
309 // We use a string bundle shared with aboutAccounts.
310 let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
311 let continueLabel = sb.GetStringFromName("continue.label");
312 let title = sb.GetStringFromName("disconnect.verify.title");
313 let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
314 let brandShortName = brandBundle.GetStringFromName("brandShortName");
315 let body = sb.GetStringFromName("disconnect.verify.heading") +
316 "\n\n" +
317 sb.formatStringFromName("disconnect.verify.description",
318 [brandShortName], 1);
319 let ps = Services.prompt;
320 let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
321 (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
322 ps.BUTTON_POS_1_DEFAULT;
323 let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
324 continueLabel, null, null, null, {});
325 if (pressed != 0) { // 0 is the "continue" button
326 return;
327 }
328 }
329 Components.utils.import('resource://gre/modules/FxAccounts.jsm');
330 fxAccounts.signOut().then(() => {
331 this.updateWeavePrefs();
332 });
333 },
335 openQuotaDialog: function () {
336 let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
337 if (win) {
338 win.focus();
339 } else {
340 window.openDialog("chrome://browser/content/sync/quota.xul", "",
341 "centerscreen,chrome,dialog,modal");
342 }
343 },
345 openAddDevice: function () {
346 if (!Weave.Utils.ensureMPUnlocked()) {
347 return;
348 }
350 let win = Services.wm.getMostRecentWindow("Sync:AddDevice");
351 if (win) {
352 win.focus();
353 } else {
354 window.openDialog("chrome://browser/content/sync/addDevice.xul",
355 "syncAddDevice", "centerscreen,chrome,resizable=no");
356 }
357 },
359 resetSync: function () {
360 this.openSetup("reset");
361 },
362 };