|
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/. */ |
|
4 |
|
5 Components.utils.import("resource://services-sync/main.js"); |
|
6 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
7 |
|
8 XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () { |
|
9 return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {}); |
|
10 }); |
|
11 |
|
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; |
|
18 |
|
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; |
|
26 |
|
27 let gSyncPane = { |
|
28 _stringBundle: null, |
|
29 prefArray: ["engine.bookmarks", "engine.passwords", "engine.prefs", |
|
30 "engine.tabs", "engine.history"], |
|
31 |
|
32 get page() { |
|
33 return document.getElementById("weavePrefsDeck").selectedIndex; |
|
34 }, |
|
35 |
|
36 set page(val) { |
|
37 document.getElementById("weavePrefsDeck").selectedIndex = val; |
|
38 }, |
|
39 |
|
40 get _usingCustomServer() { |
|
41 return Weave.Svc.Prefs.isSet("serverURL"); |
|
42 }, |
|
43 |
|
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 }, |
|
50 |
|
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; |
|
56 |
|
57 if (xps.ready) { |
|
58 this._init(); |
|
59 return; |
|
60 } |
|
61 |
|
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; |
|
65 |
|
66 let onUnload = function () { |
|
67 window.removeEventListener("unload", onUnload, false); |
|
68 try { |
|
69 Services.obs.removeObserver(onReady, "weave:service:ready"); |
|
70 } catch (e) {} |
|
71 }; |
|
72 |
|
73 let onReady = function () { |
|
74 Services.obs.removeObserver(onReady, "weave:service:ready"); |
|
75 window.removeEventListener("unload", onUnload, false); |
|
76 this._init(); |
|
77 }.bind(this); |
|
78 |
|
79 Services.obs.addObserver(onReady, "weave:service:ready", false); |
|
80 window.addEventListener("unload", onUnload, false); |
|
81 |
|
82 xps.ensureLoaded(); |
|
83 }, |
|
84 |
|
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]; |
|
92 |
|
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); |
|
104 |
|
105 this._stringBundle = |
|
106 Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties"); |
|
107 this.updateWeavePrefs(); |
|
108 }, |
|
109 |
|
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 } |
|
157 |
|
158 let checkbox = document.getElementById("fxa-pweng-chk"); |
|
159 let help = document.getElementById("fxa-pweng-help"); |
|
160 let allowPasswordsEngine = service.allowPasswordsEngine; |
|
161 |
|
162 if (!allowPasswordsEngine) { |
|
163 checkbox.checked = false; |
|
164 } |
|
165 |
|
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 }, |
|
188 |
|
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, {}); |
|
201 |
|
202 // If the user selects cancel, just bail |
|
203 if (buttonChoice == 1) |
|
204 return; |
|
205 } |
|
206 |
|
207 Weave.Service.startOver(); |
|
208 this.updateWeavePrefs(); |
|
209 }, |
|
210 |
|
211 updatePass: function () { |
|
212 if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) |
|
213 gSyncUtils.changePassword(); |
|
214 else |
|
215 gSyncUtils.updatePassphrase(); |
|
216 }, |
|
217 |
|
218 resetPass: function () { |
|
219 if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) |
|
220 gSyncUtils.resetPassword(); |
|
221 else |
|
222 gSyncUtils.resetPassphrase(); |
|
223 }, |
|
224 |
|
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; |
|
238 |
|
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 }, |
|
252 |
|
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 }, |
|
266 |
|
267 signUp: function() { |
|
268 this.openContentInBrowser("about:accounts?action=signup"); |
|
269 }, |
|
270 |
|
271 signIn: function() { |
|
272 this.openContentInBrowser("about:accounts?action=signin"); |
|
273 }, |
|
274 |
|
275 reSignIn: function() { |
|
276 this.openContentInBrowser("about:accounts?action=reauth"); |
|
277 }, |
|
278 |
|
279 manageFirefoxAccount: function() { |
|
280 let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri"); |
|
281 this.openContentInBrowser(url); |
|
282 }, |
|
283 |
|
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"); |
|
293 |
|
294 Services.prompt.alert(window, title, heading + "\n\n" + description); |
|
295 }); |
|
296 }); |
|
297 }, |
|
298 |
|
299 openOldSyncSupportPage: function() { |
|
300 let url = Services.urlFormatter.formatURLPref('app.support.baseURL') + "old-sync" |
|
301 this.openContentInBrowser(url); |
|
302 }, |
|
303 |
|
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 }, |
|
331 |
|
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 }, |
|
340 |
|
341 openAddDevice: function () { |
|
342 if (!Weave.Utils.ensureMPUnlocked()) |
|
343 return; |
|
344 |
|
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 }, |
|
352 |
|
353 resetSync: function () { |
|
354 this.openSetup("reset"); |
|
355 }, |
|
356 }; |
|
357 |