|
1 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 "use strict"; |
|
6 |
|
7 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
8 |
|
9 let SyncFlyoutPanel = { |
|
10 init: function() { |
|
11 if (this._isInitialized) { |
|
12 Cu.reportError("Attempted to initialize SyncFlyoutPanel more than once"); |
|
13 return; |
|
14 } |
|
15 |
|
16 this._isInitialized = true; |
|
17 this._bundle = Services.strings.createBundle("chrome://browser/locale/sync.properties"); |
|
18 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
19 let self = this; |
|
20 |
|
21 this._elements = {}; |
|
22 [ |
|
23 ['outer', 'sync-flyoutpanel'], |
|
24 ['preSetup', 'sync-presetup-container'], |
|
25 ['easySetup', 'sync-setup-container'], |
|
26 ['manualSetup', 'sync-manualsetup-container'], |
|
27 ['setupSuccess', 'sync-setupsuccess-container'], |
|
28 ['setupFailure', 'sync-setupfailure-container'], |
|
29 ['connected', 'sync-connected-container'], |
|
30 ['pairNewDevice', 'sync-pair-container'], |
|
31 ['pairSuccess', 'sync-pair-success-container'], |
|
32 ['setupCode1', 'sync-setup-code1'], |
|
33 ['setupCode2', 'sync-setup-code2'], |
|
34 ['setupCode3', 'sync-setup-code3'], |
|
35 ['setupThrobber', 'sync-setup-throbber'], |
|
36 ['account', 'sync-manualsetup-account'], |
|
37 ['password', 'sync-manualsetup-password'], |
|
38 ['syncKey', 'sync-manualsetup-syncKey'], |
|
39 ['manualSetupConnect', 'sync-manualsetup-connect'], |
|
40 ['manualSetupFailure', 'sync-manualsetup-failure'], |
|
41 ['connectedAccount', 'sync-connected-account'], |
|
42 ['deviceName', 'sync-connected-device'], |
|
43 ['lastSync', 'sync-connected-lastSynced'], |
|
44 ['connectedThrobber', 'sync-connected-throbber'], |
|
45 ['disconnectLink', 'sync-disconnect-label'], |
|
46 ['disconnectWarning', 'sync-disconnect-warning'], |
|
47 ['pairCode1', 'sync-pair-entry1'], |
|
48 ['pairCode2', 'sync-pair-entry2'], |
|
49 ['pairCode3', 'sync-pair-entry3'], |
|
50 ['pairButton', 'sync-pair-button'], |
|
51 ['pairFailureMessage', 'sync-pair-failure'], |
|
52 ].forEach(function (aContainer) { |
|
53 let [name, id] = aContainer; |
|
54 XPCOMUtils.defineLazyGetter(self._elements, name, function() { |
|
55 return document.getElementById(id); |
|
56 }); |
|
57 }); |
|
58 |
|
59 this._topmostElement = this._elements.outer; |
|
60 |
|
61 let xps = Components.classes["@mozilla.org/weave/service;1"] |
|
62 .getService(Components.interfaces.nsISupports) |
|
63 .wrappedJSObject; |
|
64 |
|
65 if (xps.ready) { |
|
66 this._onServiceReady(); |
|
67 } else { |
|
68 Services.obs.addObserver(this._onServiceReady.bind(this), |
|
69 "weave:service:ready", |
|
70 false); |
|
71 xps.ensureLoaded(); |
|
72 } |
|
73 }, |
|
74 |
|
75 _hide: function() { |
|
76 this._elements.outer.hide(); |
|
77 this.showInitialScreen(); |
|
78 }, |
|
79 |
|
80 _hideVisibleContainer: function() { |
|
81 if (this._currentlyVisibleContainer) { |
|
82 this._currentlyVisibleContainer.collapsed = true; |
|
83 delete this._currentlyVisibleContainer; |
|
84 delete this._onBackButton; |
|
85 } |
|
86 }, |
|
87 |
|
88 _onServiceReady: function(aEvent) { |
|
89 if (aEvent) { |
|
90 Services.obs.removeObserver(this._onServiceReady, "weave:service:ready"); |
|
91 } |
|
92 |
|
93 this.showInitialScreen(); |
|
94 Services.obs.addObserver(this._onSyncStart.bind(this), "weave:service:sync:start", false); |
|
95 Services.obs.addObserver(this._onSyncEnd.bind(this), "weave:ui:sync:finish", false); |
|
96 Services.obs.addObserver(this._onSyncEnd.bind(this), "weave:ui:sync:error", false); |
|
97 Weave.Service.scheduler.scheduleNextSync(10*1000); |
|
98 }, |
|
99 |
|
100 _onSyncStart: function() { |
|
101 this._isSyncing = true; |
|
102 this._updateConnectedPage(); |
|
103 }, |
|
104 |
|
105 _onSyncEnd: function() { |
|
106 this._isSyncing = false; |
|
107 this._updateConnectedPage(); |
|
108 }, |
|
109 |
|
110 showInitialScreen: function() { |
|
111 if (Weave.Status.login == Weave.LOGIN_SUCCEEDED) { |
|
112 this.showConnected(); |
|
113 } else { |
|
114 this.showPreSetup(); |
|
115 } |
|
116 }, |
|
117 |
|
118 abortEasySetup: function() { |
|
119 if (this._setupJpake) { |
|
120 this._setupJpake.abort(); |
|
121 } |
|
122 this._cleanUpEasySetup(); |
|
123 }, |
|
124 |
|
125 _cleanUpEasySetup: function() { |
|
126 this._elements.setupCode1.value = ""; |
|
127 this._elements.setupCode2.value = ""; |
|
128 this._elements.setupCode3.value = ""; |
|
129 delete this._setupJpake; |
|
130 this._elements.setupThrobber.collapsed = true; |
|
131 this._elements.setupThrobber.enabled = false; |
|
132 }, |
|
133 |
|
134 _updateConnectedPage: function() { |
|
135 // Show the day-of-week and time (HH:MM) of last sync |
|
136 let lastSync = Weave.Svc.Prefs.get("lastSync"); |
|
137 let syncDate = ''; |
|
138 if (lastSync != null) { |
|
139 syncDate = new Date(lastSync).toLocaleFormat("%A %I:%M %p"); |
|
140 } |
|
141 |
|
142 let device = Weave.Service.clientsEngine.localName; |
|
143 let account = Weave.Service.identity.account; |
|
144 this._elements.deviceName.textContent = |
|
145 this._bundle.formatStringFromName("sync.flyout.connected.device", |
|
146 [device], 1); |
|
147 this._elements.connectedAccount.textContent = |
|
148 this._bundle.formatStringFromName("sync.flyout.connected.account", |
|
149 [account], 1); |
|
150 this._elements.lastSync.textContent = |
|
151 this._bundle.formatStringFromName("sync.flyout.connected.lastSynced", |
|
152 [syncDate], 1); |
|
153 |
|
154 if (this._currentlyVisibleContainer == this._elements.connected |
|
155 && this._isSyncing) { |
|
156 this._elements.connectedThrobber.collapsed = false; |
|
157 this._elements.connectedThrobber.enabled = true; |
|
158 } else { |
|
159 this._elements.connectedThrobber.collapsed = true; |
|
160 this._elements.connectedThrobber.enabled = false; |
|
161 } |
|
162 }, |
|
163 |
|
164 showConnected: function() { |
|
165 // Reset state of the connected screen |
|
166 this._elements.disconnectWarning.collapsed = true; |
|
167 this._elements.disconnectLink.collapsed = false; |
|
168 |
|
169 this._updateConnectedPage(); |
|
170 this._showContainer(this._elements.connected); |
|
171 }, |
|
172 |
|
173 startEasySetup: function() { |
|
174 let self = this; |
|
175 |
|
176 this._showContainer(this._elements.easySetup); |
|
177 |
|
178 // Set up our back button to do the appropriate action |
|
179 this._onBackButton = function() { |
|
180 self.abortEasySetup(); |
|
181 self.showInitialScreen(); |
|
182 }; |
|
183 |
|
184 this._setupJpake = new Weave.JPAKEClient({ |
|
185 displayPIN: function displayPIN(aPin) { |
|
186 self._elements.setupCode1.value = aPin.slice(0, 4); |
|
187 self._elements.setupCode2.value = aPin.slice(4, 8); |
|
188 self._elements.setupCode3.value = aPin.slice(8); |
|
189 }, |
|
190 |
|
191 onPairingStart: function onPairingStart() { |
|
192 self._elements.setupThrobber.collapsed = false; |
|
193 self._elements.setupThrobber.enabled = true; |
|
194 }, |
|
195 |
|
196 onComplete: function onComplete(aCredentials) { |
|
197 Weave.Service.identity.account = aCredentials.account; |
|
198 Weave.Service.identity.basicPassword = aCredentials.password; |
|
199 Weave.Service.identity.syncKey = aCredentials.synckey; |
|
200 Weave.Service.serverURL = aCredentials.serverURL; |
|
201 Weave.Service.persistLogin(); |
|
202 Weave.Service.scheduler.scheduleNextSync(0); |
|
203 |
|
204 if (self._currentlyVisibleContainer == self._elements.easySetup) { |
|
205 self.showSetupSuccess(); |
|
206 } |
|
207 self._cleanUpEasySetup(); |
|
208 }, |
|
209 |
|
210 onAbort: function onAbort(aError) { |
|
211 if (aError == "jpake.error.userabort") { |
|
212 Services.obs.notifyObservers(null, "browser:sync:setup:userabort", ""); |
|
213 self._cleanUpEasySetup(); |
|
214 return; |
|
215 } else if (aError == "jpake.error.network") { |
|
216 Services.obs.notifyObservers(null, "browser:sync:setup:networkerror", ""); |
|
217 } |
|
218 |
|
219 if (self._currentlyVisibleContainer == self._elements.easySetup) { |
|
220 self.showSetupFailure(); |
|
221 self._cleanUpEasySetup(); |
|
222 } |
|
223 } |
|
224 }); |
|
225 |
|
226 this._setupJpake.receiveNoPIN(); |
|
227 }, |
|
228 |
|
229 _showContainer: function(aContainer) { |
|
230 this._hideVisibleContainer(); |
|
231 this._currentlyVisibleContainer = aContainer; |
|
232 this._currentlyVisibleContainer.collapsed = false; |
|
233 }, |
|
234 |
|
235 showSetupSuccess: function() { |
|
236 this._showContainer(this._elements.setupSuccess); |
|
237 this._onBackButton = this.showInitialScreen; |
|
238 }, |
|
239 |
|
240 showSetupFailure: function() { |
|
241 this._showContainer(this._elements.setupFailure); |
|
242 this._onBackButton = this.showInitialScreen; |
|
243 }, |
|
244 |
|
245 showPreSetup: function() { |
|
246 this._showContainer(this._elements.preSetup); |
|
247 delete this._onBackButton; |
|
248 }, |
|
249 |
|
250 showManualSetup: function() { |
|
251 this._showContainer(this._elements.manualSetup); |
|
252 this._onBackButton = this.showInitialScreen; |
|
253 |
|
254 this._elements.account.value = Weave.Service.identity.account; |
|
255 this._elements.password.value = Weave.Service.identity.basicPassword; |
|
256 this._elements.syncKey.value = |
|
257 Weave.Utils.hyphenatePassphrase(Weave.Service.identity.syncKey); |
|
258 this.updateManualSetupConnectButtonState(); |
|
259 }, |
|
260 |
|
261 updateManualSetupConnectButtonState: function() { |
|
262 this._elements.manualSetupConnect.disabled = !this._elements.account.value |
|
263 || !this._elements.password.value |
|
264 || !this._elements.syncKey.value; |
|
265 }, |
|
266 |
|
267 manualSetupConnect: function() { |
|
268 delete this._onBackButton; |
|
269 this._elements.manualSetupConnect.disabled = true; |
|
270 Weave.Service.identity.account = this._elements.account.value; |
|
271 Weave.Service.identity.basicPassword = this._elements.password.value; |
|
272 Weave.Service.identity.syncKey = Weave.Utils.normalizePassphrase(this._elements.syncKey.value); |
|
273 if (Weave.Service.login()) { |
|
274 Weave.Service.persistLogin(); |
|
275 if (this._currentlyVisibleContainer == this._elements.manualSetup) { |
|
276 this.showSetupSuccess(); |
|
277 } |
|
278 Weave.Service.scheduler.scheduleNextSync(0); |
|
279 } else { |
|
280 this._elements.manualSetupFailure.textContent = Weave.Utils.getErrorString(Weave.Status.login); |
|
281 this._elements.manualSetupFailure.collapsed = false; |
|
282 this.updateManualSetupConnectButtonState(); |
|
283 } |
|
284 }, |
|
285 |
|
286 onDisconnectLink: function() { |
|
287 this._elements.disconnectWarning.collapsed = false; |
|
288 this._elements.disconnectLink.collapsed = true; |
|
289 }, |
|
290 |
|
291 onDisconnectCancel: function() { |
|
292 this._elements.disconnectWarning.collapsed = true; |
|
293 this._elements.disconnectLink.collapsed = false; |
|
294 }, |
|
295 |
|
296 onDisconnectButton: function() { |
|
297 Weave.Service.startOver(); |
|
298 this.showInitialScreen(); |
|
299 }, |
|
300 |
|
301 onPairDeviceLink: function() { |
|
302 // Reset state |
|
303 this._elements.pairCode1.value = ""; |
|
304 this._elements.pairCode2.value = ""; |
|
305 this._elements.pairCode3.value = ""; |
|
306 this.updatePairButtonState(); |
|
307 this._elements.pairFailureMessage.collapsed = true; |
|
308 this._elements.pairNewDevice.collapsed = false; |
|
309 |
|
310 this._showContainer(this._elements.pairNewDevice); |
|
311 this._onBackButton = this.showInitialScreen; |
|
312 }, |
|
313 |
|
314 updatePairButtonState: function () { |
|
315 this._elements.pairButton.disabled = !this._elements.pairCode1.value |
|
316 || !this._elements.pairCode2.value |
|
317 || !this._elements.pairCode3.value; |
|
318 }, |
|
319 |
|
320 onCancelButton: function() { |
|
321 this.showInitialContainer(); |
|
322 }, |
|
323 |
|
324 onTryAgainButton: function() { |
|
325 this.startEasySetup(); |
|
326 }, |
|
327 |
|
328 onPairButton: function() { |
|
329 this._elements.pairButton.disabled = true; |
|
330 this._elements.pairFailureMessage.collapsed = true; |
|
331 let self = this; |
|
332 this._pairJpake = new Weave.JPAKEClient({ |
|
333 onPaired: function() { |
|
334 self._pairJpake.sendAndComplete({ |
|
335 account: Weave.Service.identity.account, |
|
336 password: Weave.Service.identity.basicPassword, |
|
337 synckey: Weave.Service.identity.syncKey, |
|
338 serverURL: Weave.Service.serverURL |
|
339 }); |
|
340 }, |
|
341 |
|
342 onComplete: function() { |
|
343 delete self._pairJpake; |
|
344 Weave.Service.persistLogin(); |
|
345 if (self._currentlyVisibleContainer == self._elements.pairNewDevice) { |
|
346 self._showContainer(self._elements.pairSuccess); |
|
347 } |
|
348 Weave.Service.scheduler.scheduleNextSync(Weave.Service.scheduler.activeInterval); |
|
349 }, |
|
350 |
|
351 onAbort: function(error) { |
|
352 delete self._pairJpake; |
|
353 if (error == Weave.JPAKE_ERROR_USERABORT) { |
|
354 return; |
|
355 } |
|
356 |
|
357 self._elements.pairFailureMessage.collapsed = false; |
|
358 self.updatePairButtonState(); |
|
359 } |
|
360 }); |
|
361 |
|
362 this._pairJpake.pairWithPIN(this._elements.pairCode1.value |
|
363 + this._elements.pairCode2.value |
|
364 + this._elements.pairCode3.value, |
|
365 false); |
|
366 }, |
|
367 }; |