1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/preferences/sync.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,363 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +Components.utils.import("resource://services-sync/main.js"); 1.9 +Components.utils.import("resource://gre/modules/Services.jsm"); 1.10 + 1.11 +XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () { 1.12 + return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {}); 1.13 +}); 1.14 + 1.15 +const PAGE_NO_ACCOUNT = 0; 1.16 +const PAGE_HAS_ACCOUNT = 1; 1.17 +const PAGE_NEEDS_UPDATE = 2; 1.18 +const PAGE_PLEASE_WAIT = 3; 1.19 +const FXA_PAGE_LOGGED_OUT = 4; 1.20 +const FXA_PAGE_LOGGED_IN = 5; 1.21 + 1.22 +// Indexes into the "login status" deck. 1.23 +// We are in a successful verified state - everything should work! 1.24 +const FXA_LOGIN_VERIFIED = 0; 1.25 +// We have logged in to an unverified account. 1.26 +const FXA_LOGIN_UNVERIFIED = 1; 1.27 +// We are logged in locally, but the server rejected our credentials. 1.28 +const FXA_LOGIN_FAILED = 2; 1.29 + 1.30 +let gSyncPane = { 1.31 + _stringBundle: null, 1.32 + prefArray: ["engine.bookmarks", "engine.passwords", "engine.prefs", 1.33 + "engine.tabs", "engine.history"], 1.34 + 1.35 + get page() { 1.36 + return document.getElementById("weavePrefsDeck").selectedIndex; 1.37 + }, 1.38 + 1.39 + set page(val) { 1.40 + document.getElementById("weavePrefsDeck").selectedIndex = val; 1.41 + }, 1.42 + 1.43 + get _usingCustomServer() { 1.44 + return Weave.Svc.Prefs.isSet("serverURL"); 1.45 + }, 1.46 + 1.47 + needsUpdate: function () { 1.48 + this.page = PAGE_NEEDS_UPDATE; 1.49 + let label = document.getElementById("loginError"); 1.50 + label.value = Weave.Utils.getErrorString(Weave.Status.login); 1.51 + label.className = "error"; 1.52 + }, 1.53 + 1.54 + init: function () { 1.55 + // If the Service hasn't finished initializing, wait for it. 1.56 + let xps = Components.classes["@mozilla.org/weave/service;1"] 1.57 + .getService(Components.interfaces.nsISupports) 1.58 + .wrappedJSObject; 1.59 + 1.60 + if (xps.ready) { 1.61 + this._init(); 1.62 + return; 1.63 + } 1.64 + 1.65 + // it may take some time before we can determine what provider to use 1.66 + // and the state of that provider, so show the "please wait" page. 1.67 + this.page = PAGE_PLEASE_WAIT; 1.68 + 1.69 + let onUnload = function () { 1.70 + window.removeEventListener("unload", onUnload, false); 1.71 + try { 1.72 + Services.obs.removeObserver(onReady, "weave:service:ready"); 1.73 + } catch (e) {} 1.74 + }; 1.75 + 1.76 + let onReady = function () { 1.77 + Services.obs.removeObserver(onReady, "weave:service:ready"); 1.78 + window.removeEventListener("unload", onUnload, false); 1.79 + this._init(); 1.80 + }.bind(this); 1.81 + 1.82 + Services.obs.addObserver(onReady, "weave:service:ready", false); 1.83 + window.addEventListener("unload", onUnload, false); 1.84 + 1.85 + xps.ensureLoaded(); 1.86 + }, 1.87 + 1.88 + _init: function () { 1.89 + let topics = ["weave:service:login:error", 1.90 + "weave:service:login:finish", 1.91 + "weave:service:start-over:finish", 1.92 + "weave:service:setup-complete", 1.93 + "weave:service:logout:finish", 1.94 + FxAccountsCommon.ONVERIFIED_NOTIFICATION]; 1.95 + 1.96 + // Add the observers now and remove them on unload 1.97 + //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling 1.98 + // of `this`. Fix in a followup. (bug 583347) 1.99 + topics.forEach(function (topic) { 1.100 + Weave.Svc.Obs.add(topic, this.updateWeavePrefs, this); 1.101 + }, this); 1.102 + window.addEventListener("unload", function() { 1.103 + topics.forEach(function (topic) { 1.104 + Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this); 1.105 + }, gSyncPane); 1.106 + }, false); 1.107 + 1.108 + this._stringBundle = 1.109 + Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties"); 1.110 + this.updateWeavePrefs(); 1.111 + }, 1.112 + 1.113 + updateWeavePrefs: function () { 1.114 + let service = Components.classes["@mozilla.org/weave/service;1"] 1.115 + .getService(Components.interfaces.nsISupports) 1.116 + .wrappedJSObject; 1.117 + // service.fxAccountsEnabled is false iff sync is already configured for 1.118 + // the legacy provider. 1.119 + if (service.fxAccountsEnabled) { 1.120 + // determine the fxa status... 1.121 + this.page = PAGE_PLEASE_WAIT; 1.122 + Components.utils.import("resource://gre/modules/FxAccounts.jsm"); 1.123 + fxAccounts.getSignedInUser().then(data => { 1.124 + if (!data) { 1.125 + this.page = FXA_PAGE_LOGGED_OUT; 1.126 + return; 1.127 + } 1.128 + this.page = FXA_PAGE_LOGGED_IN; 1.129 + // We are logged in locally, but maybe we are in a state where the 1.130 + // server rejected our credentials (eg, password changed on the server) 1.131 + let fxaLoginStatus = document.getElementById("fxaLoginStatus"); 1.132 + let enginesListDisabled; 1.133 + // Not Verfied implies login error state, so check that first. 1.134 + if (!data.verified) { 1.135 + fxaLoginStatus.selectedIndex = FXA_LOGIN_UNVERIFIED; 1.136 + enginesListDisabled = true; 1.137 + // So we think we are logged in, so login problems are next. 1.138 + // (Although if the Sync identity manager is still initializing, we 1.139 + // ignore login errors and assume all will eventually be good.) 1.140 + // LOGIN_FAILED_LOGIN_REJECTED explicitly means "you must log back in". 1.141 + // All other login failures are assumed to be transient and should go 1.142 + // away by themselves, so aren't reflected here. 1.143 + } else if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) { 1.144 + fxaLoginStatus.selectedIndex = FXA_LOGIN_FAILED; 1.145 + enginesListDisabled = true; 1.146 + // Else we must be golden (or in an error state we expect to magically 1.147 + // resolve itself) 1.148 + } else { 1.149 + fxaLoginStatus.selectedIndex = FXA_LOGIN_VERIFIED; 1.150 + enginesListDisabled = false; 1.151 + } 1.152 + document.getElementById("fxaEmailAddress1").textContent = data.email; 1.153 + document.getElementById("fxaEmailAddress2").textContent = data.email; 1.154 + document.getElementById("fxaEmailAddress3").textContent = data.email; 1.155 + document.getElementById("fxaSyncComputerName").value = Weave.Service.clientsEngine.localName; 1.156 + let engines = document.getElementById("fxaSyncEngines") 1.157 + for (let checkbox of engines.querySelectorAll("checkbox")) { 1.158 + checkbox.disabled = enginesListDisabled; 1.159 + } 1.160 + 1.161 + let checkbox = document.getElementById("fxa-pweng-chk"); 1.162 + let help = document.getElementById("fxa-pweng-help"); 1.163 + let allowPasswordsEngine = service.allowPasswordsEngine; 1.164 + 1.165 + if (!allowPasswordsEngine) { 1.166 + checkbox.checked = false; 1.167 + } 1.168 + 1.169 + checkbox.disabled = !allowPasswordsEngine || enginesListDisabled; 1.170 + help.hidden = allowPasswordsEngine || enginesListDisabled; 1.171 + }); 1.172 + // If fxAccountEnabled is false and we are in a "not configured" state, 1.173 + // then fxAccounts is probably fully disabled rather than just unconfigured, 1.174 + // so handle this case. This block can be removed once we remove support 1.175 + // for fxAccounts being disabled. 1.176 + } else if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED || 1.177 + Weave.Svc.Prefs.get("firstSync", "") == "notReady") { 1.178 + this.page = PAGE_NO_ACCOUNT; 1.179 + // else: sync was previously configured for the legacy provider, so we 1.180 + // make the "old" panels available. 1.181 + } else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE || 1.182 + Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) { 1.183 + this.needsUpdate(); 1.184 + } else { 1.185 + this.page = PAGE_HAS_ACCOUNT; 1.186 + document.getElementById("accountName").value = Weave.Service.identity.account; 1.187 + document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName; 1.188 + document.getElementById("tosPP").hidden = this._usingCustomServer; 1.189 + } 1.190 + }, 1.191 + 1.192 + startOver: function (showDialog) { 1.193 + if (showDialog) { 1.194 + let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING + 1.195 + Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL + 1.196 + Services.prompt.BUTTON_POS_1_DEFAULT; 1.197 + let buttonChoice = 1.198 + Services.prompt.confirmEx(window, 1.199 + this._stringBundle.GetStringFromName("syncUnlink.title"), 1.200 + this._stringBundle.GetStringFromName("syncUnlink.label"), 1.201 + flags, 1.202 + this._stringBundle.GetStringFromName("syncUnlinkConfirm.label"), 1.203 + null, null, null, {}); 1.204 + 1.205 + // If the user selects cancel, just bail 1.206 + if (buttonChoice == 1) { 1.207 + return; 1.208 + } 1.209 + } 1.210 + 1.211 + Weave.Service.startOver(); 1.212 + this.updateWeavePrefs(); 1.213 + }, 1.214 + 1.215 + updatePass: function () { 1.216 + if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) { 1.217 + gSyncUtils.changePassword(); 1.218 + } else { 1.219 + gSyncUtils.updatePassphrase(); 1.220 + } 1.221 + }, 1.222 + 1.223 + resetPass: function () { 1.224 + if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) { 1.225 + gSyncUtils.resetPassword(); 1.226 + } else { 1.227 + gSyncUtils.resetPassphrase(); 1.228 + } 1.229 + }, 1.230 + 1.231 + /** 1.232 + * Invoke the Sync setup wizard. 1.233 + * 1.234 + * @param wizardType 1.235 + * Indicates type of wizard to launch: 1.236 + * null -- regular set up wizard 1.237 + * "pair" -- pair a device first 1.238 + * "reset" -- reset sync 1.239 + */ 1.240 + openSetup: function (wizardType) { 1.241 + let service = Components.classes["@mozilla.org/weave/service;1"] 1.242 + .getService(Components.interfaces.nsISupports) 1.243 + .wrappedJSObject; 1.244 + 1.245 + if (service.fxAccountsEnabled) { 1.246 + this.openContentInBrowser("about:accounts"); 1.247 + } else { 1.248 + let win = Services.wm.getMostRecentWindow("Weave:AccountSetup"); 1.249 + if (win) { 1.250 + win.focus(); 1.251 + } else { 1.252 + window.openDialog("chrome://browser/content/sync/setup.xul", 1.253 + "weaveSetup", "centerscreen,chrome,resizable=no", 1.254 + wizardType); 1.255 + } 1.256 + } 1.257 + }, 1.258 + 1.259 + openContentInBrowser: function(url) { 1.260 + let win = Services.wm.getMostRecentWindow("navigator:browser"); 1.261 + if (!win) { 1.262 + // no window to use, so use _openLink to create a new one. We don't 1.263 + // always use that as it prefers to open a new window rather than use 1.264 + // an existing one. 1.265 + gSyncUtils._openLink(url); 1.266 + return; 1.267 + } 1.268 + win.switchToTabHavingURI(url, true); 1.269 + // seeing as we are doing this in a tab we close the prefs dialog. 1.270 + window.close(); 1.271 + }, 1.272 + 1.273 + signUp: function() { 1.274 + this.openContentInBrowser("about:accounts?action=signup"); 1.275 + }, 1.276 + 1.277 + signIn: function() { 1.278 + this.openContentInBrowser("about:accounts?action=signin"); 1.279 + }, 1.280 + 1.281 + reSignIn: function() { 1.282 + this.openContentInBrowser("about:accounts?action=reauth"); 1.283 + }, 1.284 + 1.285 + manageFirefoxAccount: function() { 1.286 + let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri"); 1.287 + this.openContentInBrowser(url); 1.288 + }, 1.289 + 1.290 + verifyFirefoxAccount: function() { 1.291 + Components.utils.import("resource://gre/modules/FxAccounts.jsm"); 1.292 + fxAccounts.resendVerificationEmail().then(() => { 1.293 + fxAccounts.getSignedInUser().then(data => { 1.294 + let sb = this._stringBundle; 1.295 + let title = sb.GetStringFromName("firefoxAccountsVerificationSentTitle"); 1.296 + let heading = sb.formatStringFromName("firefoxAccountsVerificationSentHeading", 1.297 + [data.email], 1); 1.298 + let description = sb.GetStringFromName("firefoxAccountVerificationSentDescription"); 1.299 + 1.300 + Services.prompt.alert(window, title, heading + "\n\n" + description); 1.301 + }); 1.302 + }); 1.303 + }, 1.304 + 1.305 + openOldSyncSupportPage: function() { 1.306 + let url = Services.urlFormatter.formatURLPref('app.support.baseURL') + "old-sync" 1.307 + this.openContentInBrowser(url); 1.308 + }, 1.309 + 1.310 + unlinkFirefoxAccount: function(confirm) { 1.311 + if (confirm) { 1.312 + // We use a string bundle shared with aboutAccounts. 1.313 + let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties"); 1.314 + let continueLabel = sb.GetStringFromName("continue.label"); 1.315 + let title = sb.GetStringFromName("disconnect.verify.title"); 1.316 + let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); 1.317 + let brandShortName = brandBundle.GetStringFromName("brandShortName"); 1.318 + let body = sb.GetStringFromName("disconnect.verify.heading") + 1.319 + "\n\n" + 1.320 + sb.formatStringFromName("disconnect.verify.description", 1.321 + [brandShortName], 1); 1.322 + let ps = Services.prompt; 1.323 + let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) + 1.324 + (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) + 1.325 + ps.BUTTON_POS_1_DEFAULT; 1.326 + let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags, 1.327 + continueLabel, null, null, null, {}); 1.328 + if (pressed != 0) { // 0 is the "continue" button 1.329 + return; 1.330 + } 1.331 + } 1.332 + Components.utils.import('resource://gre/modules/FxAccounts.jsm'); 1.333 + fxAccounts.signOut().then(() => { 1.334 + this.updateWeavePrefs(); 1.335 + }); 1.336 + }, 1.337 + 1.338 + openQuotaDialog: function () { 1.339 + let win = Services.wm.getMostRecentWindow("Sync:ViewQuota"); 1.340 + if (win) { 1.341 + win.focus(); 1.342 + } else { 1.343 + window.openDialog("chrome://browser/content/sync/quota.xul", "", 1.344 + "centerscreen,chrome,dialog,modal"); 1.345 + } 1.346 + }, 1.347 + 1.348 + openAddDevice: function () { 1.349 + if (!Weave.Utils.ensureMPUnlocked()) { 1.350 + return; 1.351 + } 1.352 + 1.353 + let win = Services.wm.getMostRecentWindow("Sync:AddDevice"); 1.354 + if (win) { 1.355 + win.focus(); 1.356 + } else { 1.357 + window.openDialog("chrome://browser/content/sync/addDevice.xul", 1.358 + "syncAddDevice", "centerscreen,chrome,resizable=no"); 1.359 + } 1.360 + }, 1.361 + 1.362 + resetSync: function () { 1.363 + this.openSetup("reset"); 1.364 + }, 1.365 +}; 1.366 +