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 file,
3 * 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 }
207 Weave.Service.startOver();
208 this.updateWeavePrefs();
209 },
211 updatePass: function () {
212 if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED)
213 gSyncUtils.changePassword();
214 else
215 gSyncUtils.updatePassphrase();
216 },
218 resetPass: function () {
219 if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED)
220 gSyncUtils.resetPassword();
221 else
222 gSyncUtils.resetPassphrase();
223 },
225 /**
226 * Invoke the Sync setup wizard.
227 *
228 * @param wizardType
229 * Indicates type of wizard to launch:
230 * null -- regular set up wizard
231 * "pair" -- pair a device first
232 * "reset" -- reset sync
233 */
234 openSetup: function (wizardType) {
235 let service = Components.classes["@mozilla.org/weave/service;1"]
236 .getService(Components.interfaces.nsISupports)
237 .wrappedJSObject;
239 if (service.fxAccountsEnabled) {
240 this.openContentInBrowser("about:accounts");
241 } else {
242 let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
243 if (win)
244 win.focus();
245 else {
246 window.openDialog("chrome://browser/content/sync/setup.xul",
247 "weaveSetup", "centerscreen,chrome,resizable=no",
248 wizardType);
249 }
250 }
251 },
253 openContentInBrowser: function(url) {
254 let win = Services.wm.getMostRecentWindow("navigator:browser");
255 if (!win) {
256 // no window to use, so use _openLink to create a new one. We don't
257 // always use that as it prefers to open a new window rather than use
258 // an existing one.
259 gSyncUtils._openLink(url);
260 return;
261 }
262 win.switchToTabHavingURI(url, true);
263 // seeing as we are doing this in a tab we close the prefs dialog.
264 window.close();
265 },
267 signUp: function() {
268 this.openContentInBrowser("about:accounts?action=signup");
269 },
271 signIn: function() {
272 this.openContentInBrowser("about:accounts?action=signin");
273 },
275 reSignIn: function() {
276 this.openContentInBrowser("about:accounts?action=reauth");
277 },
279 manageFirefoxAccount: function() {
280 let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri");
281 this.openContentInBrowser(url);
282 },
284 verifyFirefoxAccount: function() {
285 Components.utils.import("resource://gre/modules/FxAccounts.jsm");
286 fxAccounts.resendVerificationEmail().then(() => {
287 fxAccounts.getSignedInUser().then(data => {
288 let sb = this._stringBundle;
289 let title = sb.GetStringFromName("firefoxAccountsVerificationSentTitle");
290 let heading = sb.formatStringFromName("firefoxAccountsVerificationSentHeading",
291 [data.email], 1);
292 let description = sb.GetStringFromName("firefoxAccountVerificationSentDescription");
294 Services.prompt.alert(window, title, heading + "\n\n" + description);
295 });
296 });
297 },
299 openOldSyncSupportPage: function() {
300 let url = Services.urlFormatter.formatURLPref('app.support.baseURL') + "old-sync"
301 this.openContentInBrowser(url);
302 },
304 unlinkFirefoxAccount: function(confirm) {
305 if (confirm) {
306 // We use a string bundle shared with aboutAccounts.
307 let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
308 let continueLabel = sb.GetStringFromName("continue.label");
309 let title = sb.GetStringFromName("disconnect.verify.title");
310 let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
311 let brandShortName = brandBundle.GetStringFromName("brandShortName");
312 let body = sb.GetStringFromName("disconnect.verify.heading") +
313 "\n\n" +
314 sb.formatStringFromName("disconnect.verify.description",
315 [brandShortName], 1);
316 let ps = Services.prompt;
317 let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
318 (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
319 ps.BUTTON_POS_1_DEFAULT;
320 let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
321 continueLabel, null, null, null, {});
322 if (pressed != 0) { // 0 is the "continue" button
323 return;
324 }
325 }
326 Components.utils.import('resource://gre/modules/FxAccounts.jsm');
327 fxAccounts.signOut().then(() => {
328 this.updateWeavePrefs();
329 });
330 },
332 openQuotaDialog: function () {
333 let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
334 if (win)
335 win.focus();
336 else
337 window.openDialog("chrome://browser/content/sync/quota.xul", "",
338 "centerscreen,chrome,dialog,modal");
339 },
341 openAddDevice: function () {
342 if (!Weave.Utils.ensureMPUnlocked())
343 return;
345 let win = Services.wm.getMostRecentWindow("Sync:AddDevice");
346 if (win)
347 win.focus();
348 else
349 window.openDialog("chrome://browser/content/sync/addDevice.xul",
350 "syncAddDevice", "centerscreen,chrome,resizable=no");
351 },
353 resetSync: function () {
354 this.openSetup("reset");
355 },
356 };