browser/base/content/sync/setup.js

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

michael@0 1 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 const Ci = Components.interfaces;
michael@0 7 const Cc = Components.classes;
michael@0 8 const Cr = Components.results;
michael@0 9 const Cu = Components.utils;
michael@0 10
michael@0 11 // page consts
michael@0 12
michael@0 13 const PAIR_PAGE = 0;
michael@0 14 const INTRO_PAGE = 1;
michael@0 15 const NEW_ACCOUNT_START_PAGE = 2;
michael@0 16 const EXISTING_ACCOUNT_CONNECT_PAGE = 3;
michael@0 17 const EXISTING_ACCOUNT_LOGIN_PAGE = 4;
michael@0 18 const OPTIONS_PAGE = 5;
michael@0 19 const OPTIONS_CONFIRM_PAGE = 6;
michael@0 20
michael@0 21 // Broader than we'd like, but after this changed from api-secure.recaptcha.net
michael@0 22 // we had no choice. At least we only do this for the duration of setup.
michael@0 23 // See discussion in Bugs 508112 and 653307.
michael@0 24 const RECAPTCHA_DOMAIN = "https://www.google.com";
michael@0 25
michael@0 26 const PIN_PART_LENGTH = 4;
michael@0 27
michael@0 28 Cu.import("resource://services-sync/main.js");
michael@0 29 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 30 Cu.import("resource://gre/modules/Services.jsm");
michael@0 31 Cu.import("resource://gre/modules/PlacesUtils.jsm");
michael@0 32 Cu.import("resource://gre/modules/PluralForm.jsm");
michael@0 33
michael@0 34
michael@0 35 function setVisibility(element, visible) {
michael@0 36 element.style.visibility = visible ? "visible" : "hidden";
michael@0 37 }
michael@0 38
michael@0 39 var gSyncSetup = {
michael@0 40 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
michael@0 41 Ci.nsIWebProgressListener,
michael@0 42 Ci.nsISupportsWeakReference]),
michael@0 43
michael@0 44 captchaBrowser: null,
michael@0 45 wizard: null,
michael@0 46 _disabledSites: [],
michael@0 47
michael@0 48 status: {
michael@0 49 password: false,
michael@0 50 email: false,
michael@0 51 server: false
michael@0 52 },
michael@0 53
michael@0 54 get _remoteSites() [Weave.Service.serverURL, RECAPTCHA_DOMAIN],
michael@0 55
michael@0 56 get _usingMainServers() {
michael@0 57 if (this._settingUpNew)
michael@0 58 return document.getElementById("server").selectedIndex == 0;
michael@0 59 return document.getElementById("existingServer").selectedIndex == 0;
michael@0 60 },
michael@0 61
michael@0 62 init: function () {
michael@0 63 let obs = [
michael@0 64 ["weave:service:change-passphrase", "onResetPassphrase"],
michael@0 65 ["weave:service:login:start", "onLoginStart"],
michael@0 66 ["weave:service:login:error", "onLoginEnd"],
michael@0 67 ["weave:service:login:finish", "onLoginEnd"]];
michael@0 68
michael@0 69 // Add the observers now and remove them on unload
michael@0 70 let self = this;
michael@0 71 let addRem = function(add) {
michael@0 72 obs.forEach(function([topic, func]) {
michael@0 73 //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
michael@0 74 // of `this`. Fix in a followup. (bug 583347)
michael@0 75 if (add)
michael@0 76 Weave.Svc.Obs.add(topic, self[func], self);
michael@0 77 else
michael@0 78 Weave.Svc.Obs.remove(topic, self[func], self);
michael@0 79 });
michael@0 80 };
michael@0 81 addRem(true);
michael@0 82 window.addEventListener("unload", function() addRem(false), false);
michael@0 83
michael@0 84 window.setTimeout(function () {
michael@0 85 // Force Service to be loaded so that engines are registered.
michael@0 86 // See Bug 670082.
michael@0 87 Weave.Service;
michael@0 88 }, 0);
michael@0 89
michael@0 90 this.captchaBrowser = document.getElementById("captcha");
michael@0 91
michael@0 92 this.wizardType = null;
michael@0 93 if (window.arguments && window.arguments[0]) {
michael@0 94 this.wizardType = window.arguments[0];
michael@0 95 }
michael@0 96 switch (this.wizardType) {
michael@0 97 case null:
michael@0 98 this.wizard.pageIndex = INTRO_PAGE;
michael@0 99 // Fall through!
michael@0 100 case "pair":
michael@0 101 this.captchaBrowser.addProgressListener(this);
michael@0 102 Weave.Svc.Prefs.set("firstSync", "notReady");
michael@0 103 break;
michael@0 104 case "reset":
michael@0 105 this._resettingSync = true;
michael@0 106 this.wizard.pageIndex = OPTIONS_PAGE;
michael@0 107 break;
michael@0 108 }
michael@0 109
michael@0 110 this.wizard.getButton("extra1").label =
michael@0 111 this._stringBundle.GetStringFromName("button.syncOptions.label");
michael@0 112
michael@0 113 // Remember these values because the options pages change them temporarily.
michael@0 114 this._nextButtonLabel = this.wizard.getButton("next").label;
michael@0 115 this._nextButtonAccesskey = this.wizard.getButton("next")
michael@0 116 .getAttribute("accesskey");
michael@0 117 this._backButtonLabel = this.wizard.getButton("back").label;
michael@0 118 this._backButtonAccesskey = this.wizard.getButton("back")
michael@0 119 .getAttribute("accesskey");
michael@0 120 },
michael@0 121
michael@0 122 startNewAccountSetup: function () {
michael@0 123 if (!Weave.Utils.ensureMPUnlocked())
michael@0 124 return false;
michael@0 125 this._settingUpNew = true;
michael@0 126 this.wizard.pageIndex = NEW_ACCOUNT_START_PAGE;
michael@0 127 },
michael@0 128
michael@0 129 useExistingAccount: function () {
michael@0 130 if (!Weave.Utils.ensureMPUnlocked())
michael@0 131 return false;
michael@0 132 this._settingUpNew = false;
michael@0 133 if (this.wizardType == "pair") {
michael@0 134 // We're already pairing, so there's no point in pairing again.
michael@0 135 // Go straight to the manual login page.
michael@0 136 this.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE;
michael@0 137 } else {
michael@0 138 this.wizard.pageIndex = EXISTING_ACCOUNT_CONNECT_PAGE;
michael@0 139 }
michael@0 140 },
michael@0 141
michael@0 142 resetPassphrase: function resetPassphrase() {
michael@0 143 // Apply the existing form fields so that
michael@0 144 // Weave.Service.changePassphrase() has the necessary credentials.
michael@0 145 Weave.Service.identity.account = document.getElementById("existingAccountName").value;
michael@0 146 Weave.Service.identity.basicPassword = document.getElementById("existingPassword").value;
michael@0 147
michael@0 148 // Generate a new passphrase so that Weave.Service.login() will
michael@0 149 // actually do something.
michael@0 150 let passphrase = Weave.Utils.generatePassphrase();
michael@0 151 Weave.Service.identity.syncKey = passphrase;
michael@0 152
michael@0 153 // Only open the dialog if username + password are actually correct.
michael@0 154 Weave.Service.login();
michael@0 155 if ([Weave.LOGIN_FAILED_INVALID_PASSPHRASE,
michael@0 156 Weave.LOGIN_FAILED_NO_PASSPHRASE,
michael@0 157 Weave.LOGIN_SUCCEEDED].indexOf(Weave.Status.login) == -1) {
michael@0 158 return;
michael@0 159 }
michael@0 160
michael@0 161 // Hide any errors about the passphrase, we know it's not right.
michael@0 162 let feedback = document.getElementById("existingPassphraseFeedbackRow");
michael@0 163 feedback.hidden = true;
michael@0 164 let el = document.getElementById("existingPassphrase");
michael@0 165 el.value = Weave.Utils.hyphenatePassphrase(passphrase);
michael@0 166
michael@0 167 // changePassphrase() will sync, make sure we set the "firstSync" pref
michael@0 168 // according to the user's pref.
michael@0 169 Weave.Svc.Prefs.reset("firstSync");
michael@0 170 this.setupInitialSync();
michael@0 171 gSyncUtils.resetPassphrase(true);
michael@0 172 },
michael@0 173
michael@0 174 onResetPassphrase: function () {
michael@0 175 document.getElementById("existingPassphrase").value =
michael@0 176 Weave.Utils.hyphenatePassphrase(Weave.Service.identity.syncKey);
michael@0 177 this.checkFields();
michael@0 178 this.wizard.advance();
michael@0 179 },
michael@0 180
michael@0 181 onLoginStart: function () {
michael@0 182 this.toggleLoginFeedback(false);
michael@0 183 },
michael@0 184
michael@0 185 onLoginEnd: function () {
michael@0 186 this.toggleLoginFeedback(true);
michael@0 187 },
michael@0 188
michael@0 189 sendCredentialsAfterSync: function () {
michael@0 190 let send = function() {
michael@0 191 Services.obs.removeObserver("weave:service:sync:finish", send);
michael@0 192 Services.obs.removeObserver("weave:service:sync:error", send);
michael@0 193 let credentials = {account: Weave.Service.identity.account,
michael@0 194 password: Weave.Service.identity.basicPassword,
michael@0 195 synckey: Weave.Service.identity.syncKey,
michael@0 196 serverURL: Weave.Service.serverURL};
michael@0 197 this._jpakeclient.sendAndComplete(credentials);
michael@0 198 }.bind(this);
michael@0 199 Services.obs.addObserver("weave:service:sync:finish", send, false);
michael@0 200 Services.obs.addObserver("weave:service:sync:error", send, false);
michael@0 201 },
michael@0 202
michael@0 203 toggleLoginFeedback: function (stop) {
michael@0 204 document.getElementById("login-throbber").hidden = stop;
michael@0 205 let password = document.getElementById("existingPasswordFeedbackRow");
michael@0 206 let server = document.getElementById("existingServerFeedbackRow");
michael@0 207 let passphrase = document.getElementById("existingPassphraseFeedbackRow");
michael@0 208
michael@0 209 if (!stop || (Weave.Status.login == Weave.LOGIN_SUCCEEDED)) {
michael@0 210 password.hidden = server.hidden = passphrase.hidden = true;
michael@0 211 return;
michael@0 212 }
michael@0 213
michael@0 214 let feedback;
michael@0 215 switch (Weave.Status.login) {
michael@0 216 case Weave.LOGIN_FAILED_NETWORK_ERROR:
michael@0 217 case Weave.LOGIN_FAILED_SERVER_ERROR:
michael@0 218 feedback = server;
michael@0 219 break;
michael@0 220 case Weave.LOGIN_FAILED_LOGIN_REJECTED:
michael@0 221 case Weave.LOGIN_FAILED_NO_USERNAME:
michael@0 222 case Weave.LOGIN_FAILED_NO_PASSWORD:
michael@0 223 feedback = password;
michael@0 224 break;
michael@0 225 case Weave.LOGIN_FAILED_INVALID_PASSPHRASE:
michael@0 226 feedback = passphrase;
michael@0 227 break;
michael@0 228 }
michael@0 229 this._setFeedbackMessage(feedback, false, Weave.Status.login);
michael@0 230 },
michael@0 231
michael@0 232 setupInitialSync: function () {
michael@0 233 let action = document.getElementById("mergeChoiceRadio").selectedItem.id;
michael@0 234 switch (action) {
michael@0 235 case "resetClient":
michael@0 236 // if we're not resetting sync, we don't need to explicitly
michael@0 237 // call resetClient
michael@0 238 if (!this._resettingSync)
michael@0 239 return;
michael@0 240 // otherwise, fall through
michael@0 241 case "wipeClient":
michael@0 242 case "wipeRemote":
michael@0 243 Weave.Svc.Prefs.set("firstSync", action);
michael@0 244 break;
michael@0 245 }
michael@0 246 },
michael@0 247
michael@0 248 // fun with validation!
michael@0 249 checkFields: function () {
michael@0 250 this.wizard.canAdvance = this.readyToAdvance();
michael@0 251 },
michael@0 252
michael@0 253 readyToAdvance: function () {
michael@0 254 switch (this.wizard.pageIndex) {
michael@0 255 case INTRO_PAGE:
michael@0 256 return false;
michael@0 257 case NEW_ACCOUNT_START_PAGE:
michael@0 258 for (let i in this.status) {
michael@0 259 if (!this.status[i])
michael@0 260 return false;
michael@0 261 }
michael@0 262 if (this._usingMainServers)
michael@0 263 return document.getElementById("tos").checked;
michael@0 264
michael@0 265 return true;
michael@0 266 case EXISTING_ACCOUNT_LOGIN_PAGE:
michael@0 267 let hasUser = document.getElementById("existingAccountName").value != "";
michael@0 268 let hasPass = document.getElementById("existingPassword").value != "";
michael@0 269 let hasKey = document.getElementById("existingPassphrase").value != "";
michael@0 270
michael@0 271 if (hasUser && hasPass && hasKey) {
michael@0 272 if (this._usingMainServers)
michael@0 273 return true;
michael@0 274
michael@0 275 if (this._validateServer(document.getElementById("existingServer"))) {
michael@0 276 return true;
michael@0 277 }
michael@0 278 }
michael@0 279 return false;
michael@0 280 }
michael@0 281 // Default, e.g. wizard's special page -1 etc.
michael@0 282 return true;
michael@0 283 },
michael@0 284
michael@0 285 onPINInput: function onPINInput(textbox) {
michael@0 286 if (textbox && textbox.value.length == PIN_PART_LENGTH) {
michael@0 287 this.nextFocusEl[textbox.id].focus();
michael@0 288 }
michael@0 289 this.wizard.canAdvance = (this.pin1.value.length == PIN_PART_LENGTH &&
michael@0 290 this.pin2.value.length == PIN_PART_LENGTH &&
michael@0 291 this.pin3.value.length == PIN_PART_LENGTH);
michael@0 292 },
michael@0 293
michael@0 294 onEmailInput: function () {
michael@0 295 // Check account validity when the user stops typing for 1 second.
michael@0 296 if (this._checkAccountTimer)
michael@0 297 window.clearTimeout(this._checkAccountTimer);
michael@0 298 this._checkAccountTimer = window.setTimeout(function () {
michael@0 299 gSyncSetup.checkAccount();
michael@0 300 }, 1000);
michael@0 301 },
michael@0 302
michael@0 303 checkAccount: function() {
michael@0 304 delete this._checkAccountTimer;
michael@0 305 let value = Weave.Utils.normalizeAccount(
michael@0 306 document.getElementById("weaveEmail").value);
michael@0 307 if (!value) {
michael@0 308 this.status.email = false;
michael@0 309 this.checkFields();
michael@0 310 return;
michael@0 311 }
michael@0 312
michael@0 313 let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
michael@0 314 let feedback = document.getElementById("emailFeedbackRow");
michael@0 315 let valid = re.test(value);
michael@0 316
michael@0 317 let str = "";
michael@0 318 if (!valid) {
michael@0 319 str = "invalidEmail.label";
michael@0 320 } else {
michael@0 321 let availCheck = Weave.Service.checkAccount(value);
michael@0 322 valid = availCheck == "available";
michael@0 323 if (!valid) {
michael@0 324 if (availCheck == "notAvailable")
michael@0 325 str = "usernameNotAvailable.label";
michael@0 326 else
michael@0 327 str = availCheck;
michael@0 328 }
michael@0 329 }
michael@0 330
michael@0 331 this._setFeedbackMessage(feedback, valid, str);
michael@0 332 this.status.email = valid;
michael@0 333 if (valid)
michael@0 334 Weave.Service.identity.account = value;
michael@0 335 this.checkFields();
michael@0 336 },
michael@0 337
michael@0 338 onPasswordChange: function () {
michael@0 339 let password = document.getElementById("weavePassword");
michael@0 340 let pwconfirm = document.getElementById("weavePasswordConfirm");
michael@0 341 let [valid, errorString] = gSyncUtils.validatePassword(password, pwconfirm);
michael@0 342
michael@0 343 let feedback = document.getElementById("passwordFeedbackRow");
michael@0 344 this._setFeedback(feedback, valid, errorString);
michael@0 345
michael@0 346 this.status.password = valid;
michael@0 347 this.checkFields();
michael@0 348 },
michael@0 349
michael@0 350 onPageShow: function() {
michael@0 351 switch (this.wizard.pageIndex) {
michael@0 352 case PAIR_PAGE:
michael@0 353 this.wizard.getButton("back").hidden = true;
michael@0 354 this.wizard.getButton("extra1").hidden = true;
michael@0 355 this.onPINInput();
michael@0 356 this.pin1.focus();
michael@0 357 break;
michael@0 358 case INTRO_PAGE:
michael@0 359 // We may not need the captcha in the Existing Account branch of the
michael@0 360 // wizard. However, we want to preload it to avoid any flickering while
michael@0 361 // the Create Account page is shown.
michael@0 362 this.loadCaptcha();
michael@0 363 this.wizard.getButton("next").hidden = true;
michael@0 364 this.wizard.getButton("back").hidden = true;
michael@0 365 this.wizard.getButton("extra1").hidden = true;
michael@0 366 this.checkFields();
michael@0 367 break;
michael@0 368 case NEW_ACCOUNT_START_PAGE:
michael@0 369 this.wizard.getButton("extra1").hidden = false;
michael@0 370 this.wizard.getButton("next").hidden = false;
michael@0 371 this.wizard.getButton("back").hidden = false;
michael@0 372 this.onServerCommand();
michael@0 373 this.wizard.canRewind = true;
michael@0 374 this.checkFields();
michael@0 375 break;
michael@0 376 case EXISTING_ACCOUNT_CONNECT_PAGE:
michael@0 377 Weave.Svc.Prefs.set("firstSync", "existingAccount");
michael@0 378 this.wizard.getButton("next").hidden = false;
michael@0 379 this.wizard.getButton("back").hidden = false;
michael@0 380 this.wizard.getButton("extra1").hidden = false;
michael@0 381 this.wizard.canAdvance = false;
michael@0 382 this.wizard.canRewind = true;
michael@0 383 this.startEasySetup();
michael@0 384 break;
michael@0 385 case EXISTING_ACCOUNT_LOGIN_PAGE:
michael@0 386 this.wizard.getButton("next").hidden = false;
michael@0 387 this.wizard.getButton("back").hidden = false;
michael@0 388 this.wizard.getButton("extra1").hidden = false;
michael@0 389 this.wizard.canRewind = true;
michael@0 390 this.checkFields();
michael@0 391 break;
michael@0 392 case OPTIONS_PAGE:
michael@0 393 this.wizard.canRewind = false;
michael@0 394 this.wizard.canAdvance = true;
michael@0 395 if (!this._resettingSync) {
michael@0 396 this.wizard.getButton("next").label =
michael@0 397 this._stringBundle.GetStringFromName("button.syncOptionsDone.label");
michael@0 398 this.wizard.getButton("next").removeAttribute("accesskey");
michael@0 399 }
michael@0 400 this.wizard.getButton("next").hidden = false;
michael@0 401 this.wizard.getButton("back").hidden = true;
michael@0 402 this.wizard.getButton("cancel").hidden = !this._resettingSync;
michael@0 403 this.wizard.getButton("extra1").hidden = true;
michael@0 404 document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName;
michael@0 405 document.getElementById("syncOptions").collapsed = this._resettingSync;
michael@0 406 document.getElementById("mergeOptions").collapsed = this._settingUpNew;
michael@0 407 break;
michael@0 408 case OPTIONS_CONFIRM_PAGE:
michael@0 409 this.wizard.canRewind = true;
michael@0 410 this.wizard.canAdvance = true;
michael@0 411 this.wizard.getButton("back").label =
michael@0 412 this._stringBundle.GetStringFromName("button.syncOptionsCancel.label");
michael@0 413 this.wizard.getButton("back").removeAttribute("accesskey");
michael@0 414 this.wizard.getButton("back").hidden = this._resettingSync;
michael@0 415 this.wizard.getButton("next").hidden = false;
michael@0 416 this.wizard.getButton("finish").hidden = true;
michael@0 417 break;
michael@0 418 }
michael@0 419 },
michael@0 420
michael@0 421 onWizardAdvance: function () {
michael@0 422 // Check pageIndex so we don't prompt before the Sync setup wizard appears.
michael@0 423 // This is a fallback in case the Master Password gets locked mid-wizard.
michael@0 424 if ((this.wizard.pageIndex >= 0) &&
michael@0 425 !Weave.Utils.ensureMPUnlocked()) {
michael@0 426 return false;
michael@0 427 }
michael@0 428
michael@0 429 switch (this.wizard.pageIndex) {
michael@0 430 case PAIR_PAGE:
michael@0 431 this.startPairing();
michael@0 432 return false;
michael@0 433 case NEW_ACCOUNT_START_PAGE:
michael@0 434 // If the user selects Next (e.g. by hitting enter) when we haven't
michael@0 435 // executed the delayed checks yet, execute them immediately.
michael@0 436 if (this._checkAccountTimer) {
michael@0 437 this.checkAccount();
michael@0 438 }
michael@0 439 if (this._checkServerTimer) {
michael@0 440 this.checkServer();
michael@0 441 }
michael@0 442 if (!this.wizard.canAdvance) {
michael@0 443 return false;
michael@0 444 }
michael@0 445
michael@0 446 let doc = this.captchaBrowser.contentDocument;
michael@0 447 let getField = function getField(field) {
michael@0 448 let node = doc.getElementById("recaptcha_" + field + "_field");
michael@0 449 return node && node.value;
michael@0 450 };
michael@0 451
michael@0 452 // Display throbber
michael@0 453 let feedback = document.getElementById("captchaFeedback");
michael@0 454 let image = feedback.firstChild;
michael@0 455 let label = image.nextSibling;
michael@0 456 image.setAttribute("status", "active");
michael@0 457 label.value = this._stringBundle.GetStringFromName("verifying.label");
michael@0 458 setVisibility(feedback, true);
michael@0 459
michael@0 460 let password = document.getElementById("weavePassword").value;
michael@0 461 let email = Weave.Utils.normalizeAccount(
michael@0 462 document.getElementById("weaveEmail").value);
michael@0 463 let challenge = getField("challenge");
michael@0 464 let response = getField("response");
michael@0 465
michael@0 466 let error = Weave.Service.createAccount(email, password,
michael@0 467 challenge, response);
michael@0 468
michael@0 469 if (error == null) {
michael@0 470 Weave.Service.identity.account = email;
michael@0 471 Weave.Service.identity.basicPassword = password;
michael@0 472 Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase();
michael@0 473 this._handleNoScript(false);
michael@0 474 Weave.Svc.Prefs.set("firstSync", "newAccount");
michael@0 475 #ifdef XP_WIN
michael@0 476 #ifdef MOZ_METRO
michael@0 477 if (document.getElementById("metroSetupCheckbox").checked) {
michael@0 478 Services.metro.storeSyncInfo(email, password, Weave.Service.identity.syncKey);
michael@0 479 }
michael@0 480 #endif
michael@0 481 #endif
michael@0 482 this.wizardFinish();
michael@0 483 return false;
michael@0 484 }
michael@0 485
michael@0 486 image.setAttribute("status", "error");
michael@0 487 label.value = Weave.Utils.getErrorString(error);
michael@0 488 return false;
michael@0 489 case EXISTING_ACCOUNT_LOGIN_PAGE:
michael@0 490 Weave.Service.identity.account = Weave.Utils.normalizeAccount(
michael@0 491 document.getElementById("existingAccountName").value);
michael@0 492 Weave.Service.identity.basicPassword =
michael@0 493 document.getElementById("existingPassword").value;
michael@0 494 let pp = document.getElementById("existingPassphrase").value;
michael@0 495 Weave.Service.identity.syncKey = Weave.Utils.normalizePassphrase(pp);
michael@0 496 if (Weave.Service.login()) {
michael@0 497 this.wizardFinish();
michael@0 498 }
michael@0 499 return false;
michael@0 500 case OPTIONS_PAGE:
michael@0 501 let desc = document.getElementById("mergeChoiceRadio").selectedIndex;
michael@0 502 // No confirmation needed on new account setup or merge option
michael@0 503 // with existing account.
michael@0 504 if (this._settingUpNew || (!this._resettingSync && desc == 0))
michael@0 505 return this.returnFromOptions();
michael@0 506 return this._handleChoice();
michael@0 507 case OPTIONS_CONFIRM_PAGE:
michael@0 508 if (this._resettingSync) {
michael@0 509 this.wizardFinish();
michael@0 510 return false;
michael@0 511 }
michael@0 512 return this.returnFromOptions();
michael@0 513 }
michael@0 514 return true;
michael@0 515 },
michael@0 516
michael@0 517 onWizardBack: function () {
michael@0 518 switch (this.wizard.pageIndex) {
michael@0 519 case NEW_ACCOUNT_START_PAGE:
michael@0 520 case EXISTING_ACCOUNT_LOGIN_PAGE:
michael@0 521 this.wizard.pageIndex = INTRO_PAGE;
michael@0 522 return false;
michael@0 523 case EXISTING_ACCOUNT_CONNECT_PAGE:
michael@0 524 this.abortEasySetup();
michael@0 525 this.wizard.pageIndex = INTRO_PAGE;
michael@0 526 return false;
michael@0 527 case EXISTING_ACCOUNT_LOGIN_PAGE:
michael@0 528 // If we were already pairing on entry, we went straight to the manual
michael@0 529 // login page. If subsequently we go back, return to the page that lets
michael@0 530 // us choose whether we already have an account.
michael@0 531 if (this.wizardType == "pair") {
michael@0 532 this.wizard.pageIndex = INTRO_PAGE;
michael@0 533 return false;
michael@0 534 }
michael@0 535 return true;
michael@0 536 case OPTIONS_CONFIRM_PAGE:
michael@0 537 // Backing up from the confirmation page = resetting first sync to merge.
michael@0 538 document.getElementById("mergeChoiceRadio").selectedIndex = 0;
michael@0 539 return this.returnFromOptions();
michael@0 540 }
michael@0 541 return true;
michael@0 542 },
michael@0 543
michael@0 544 wizardFinish: function () {
michael@0 545 this.setupInitialSync();
michael@0 546
michael@0 547 if (this.wizardType == "pair") {
michael@0 548 this.completePairing();
michael@0 549 }
michael@0 550
michael@0 551 if (!this._resettingSync) {
michael@0 552 function isChecked(element) {
michael@0 553 return document.getElementById(element).hasAttribute("checked");
michael@0 554 }
michael@0 555
michael@0 556 let prefs = ["engine.bookmarks", "engine.passwords", "engine.history",
michael@0 557 "engine.tabs", "engine.prefs", "engine.addons"];
michael@0 558 for (let i = 0;i < prefs.length;i++) {
michael@0 559 Weave.Svc.Prefs.set(prefs[i], isChecked(prefs[i]));
michael@0 560 }
michael@0 561 this._handleNoScript(false);
michael@0 562 if (Weave.Svc.Prefs.get("firstSync", "") == "notReady")
michael@0 563 Weave.Svc.Prefs.reset("firstSync");
michael@0 564
michael@0 565 Weave.Service.persistLogin();
michael@0 566 Weave.Svc.Obs.notify("weave:service:setup-complete");
michael@0 567
michael@0 568 gSyncUtils.openFirstSyncProgressPage();
michael@0 569 }
michael@0 570 Weave.Utils.nextTick(Weave.Service.sync, Weave.Service);
michael@0 571 window.close();
michael@0 572 },
michael@0 573
michael@0 574 onWizardCancel: function () {
michael@0 575 if (this._resettingSync)
michael@0 576 return;
michael@0 577
michael@0 578 this.abortEasySetup();
michael@0 579 this._handleNoScript(false);
michael@0 580 Weave.Service.startOver();
michael@0 581 },
michael@0 582
michael@0 583 onSyncOptions: function () {
michael@0 584 this._beforeOptionsPage = this.wizard.pageIndex;
michael@0 585 this.wizard.pageIndex = OPTIONS_PAGE;
michael@0 586 },
michael@0 587
michael@0 588 returnFromOptions: function() {
michael@0 589 this.wizard.getButton("next").label = this._nextButtonLabel;
michael@0 590 this.wizard.getButton("next").setAttribute("accesskey",
michael@0 591 this._nextButtonAccesskey);
michael@0 592 this.wizard.getButton("back").label = this._backButtonLabel;
michael@0 593 this.wizard.getButton("back").setAttribute("accesskey",
michael@0 594 this._backButtonAccesskey);
michael@0 595 this.wizard.getButton("cancel").hidden = false;
michael@0 596 this.wizard.getButton("extra1").hidden = false;
michael@0 597 this.wizard.pageIndex = this._beforeOptionsPage;
michael@0 598 return false;
michael@0 599 },
michael@0 600
michael@0 601 startPairing: function startPairing() {
michael@0 602 this.pairDeviceErrorRow.hidden = true;
michael@0 603 // When onAbort is called, Weave may already be gone.
michael@0 604 const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT;
michael@0 605
michael@0 606 let self = this;
michael@0 607 let jpakeclient = this._jpakeclient = new Weave.JPAKEClient({
michael@0 608 onPaired: function onPaired() {
michael@0 609 self.wizard.pageIndex = INTRO_PAGE;
michael@0 610 },
michael@0 611 onComplete: function onComplete() {
michael@0 612 // This method will never be called since SendCredentialsController
michael@0 613 // will take over after the wizard completes.
michael@0 614 },
michael@0 615 onAbort: function onAbort(error) {
michael@0 616 delete self._jpakeclient;
michael@0 617
michael@0 618 // Aborted by user, ignore. The window is almost certainly going to close
michael@0 619 // or is already closed.
michael@0 620 if (error == JPAKE_ERROR_USERABORT) {
michael@0 621 return;
michael@0 622 }
michael@0 623
michael@0 624 self.pairDeviceErrorRow.hidden = false;
michael@0 625 self.pairDeviceThrobber.hidden = true;
michael@0 626 self.pin1.value = self.pin2.value = self.pin3.value = "";
michael@0 627 self.pin1.disabled = self.pin2.disabled = self.pin3.disabled = false;
michael@0 628 if (self.wizard.pageIndex == PAIR_PAGE) {
michael@0 629 self.pin1.focus();
michael@0 630 }
michael@0 631 }
michael@0 632 });
michael@0 633 this.pairDeviceThrobber.hidden = false;
michael@0 634 this.pin1.disabled = this.pin2.disabled = this.pin3.disabled = true;
michael@0 635 this.wizard.canAdvance = false;
michael@0 636
michael@0 637 let pin = this.pin1.value + this.pin2.value + this.pin3.value;
michael@0 638 let expectDelay = true;
michael@0 639 jpakeclient.pairWithPIN(pin, expectDelay);
michael@0 640 },
michael@0 641
michael@0 642 completePairing: function completePairing() {
michael@0 643 if (!this._jpakeclient) {
michael@0 644 // The channel was aborted while we were setting up the account
michael@0 645 // locally. XXX TODO should we do anything here, e.g. tell
michael@0 646 // the user on the last wizard page that it's ok, they just
michael@0 647 // have to pair again?
michael@0 648 return;
michael@0 649 }
michael@0 650 let controller = new Weave.SendCredentialsController(this._jpakeclient,
michael@0 651 Weave.Service);
michael@0 652 this._jpakeclient.controller = controller;
michael@0 653 },
michael@0 654
michael@0 655 startEasySetup: function () {
michael@0 656 // Don't do anything if we have a client already (e.g. we went to
michael@0 657 // Sync Options and just came back).
michael@0 658 if (this._jpakeclient)
michael@0 659 return;
michael@0 660
michael@0 661 // When onAbort is called, Weave may already be gone
michael@0 662 const JPAKE_ERROR_USERABORT = Weave.JPAKE_ERROR_USERABORT;
michael@0 663
michael@0 664 let self = this;
michael@0 665 this._jpakeclient = new Weave.JPAKEClient({
michael@0 666 displayPIN: function displayPIN(pin) {
michael@0 667 document.getElementById("easySetupPIN1").value = pin.slice(0, 4);
michael@0 668 document.getElementById("easySetupPIN2").value = pin.slice(4, 8);
michael@0 669 document.getElementById("easySetupPIN3").value = pin.slice(8);
michael@0 670 },
michael@0 671
michael@0 672 onPairingStart: function onPairingStart() {},
michael@0 673
michael@0 674 onComplete: function onComplete(credentials) {
michael@0 675 Weave.Service.identity.account = credentials.account;
michael@0 676 Weave.Service.identity.basicPassword = credentials.password;
michael@0 677 Weave.Service.identity.syncKey = credentials.synckey;
michael@0 678 Weave.Service.serverURL = credentials.serverURL;
michael@0 679 gSyncSetup.wizardFinish();
michael@0 680 },
michael@0 681
michael@0 682 onAbort: function onAbort(error) {
michael@0 683 delete self._jpakeclient;
michael@0 684
michael@0 685 // Ignore if wizard is aborted.
michael@0 686 if (error == JPAKE_ERROR_USERABORT)
michael@0 687 return;
michael@0 688
michael@0 689 // Automatically go to manual setup if we couldn't acquire a channel.
michael@0 690 if (error == Weave.JPAKE_ERROR_CHANNEL) {
michael@0 691 self.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE;
michael@0 692 return;
michael@0 693 }
michael@0 694
michael@0 695 // Restart on all other errors.
michael@0 696 self.startEasySetup();
michael@0 697 }
michael@0 698 });
michael@0 699 this._jpakeclient.receiveNoPIN();
michael@0 700 },
michael@0 701
michael@0 702 abortEasySetup: function () {
michael@0 703 document.getElementById("easySetupPIN1").value = "";
michael@0 704 document.getElementById("easySetupPIN2").value = "";
michael@0 705 document.getElementById("easySetupPIN3").value = "";
michael@0 706 if (!this._jpakeclient)
michael@0 707 return;
michael@0 708
michael@0 709 this._jpakeclient.abort();
michael@0 710 delete this._jpakeclient;
michael@0 711 },
michael@0 712
michael@0 713 manualSetup: function () {
michael@0 714 this.abortEasySetup();
michael@0 715 this.wizard.pageIndex = EXISTING_ACCOUNT_LOGIN_PAGE;
michael@0 716 },
michael@0 717
michael@0 718 // _handleNoScript is needed because it blocks the captcha. So we temporarily
michael@0 719 // allow the necessary sites so that we can verify the user is in fact a human.
michael@0 720 // This was done with the help of Giorgio (NoScript author). See bug 508112.
michael@0 721 _handleNoScript: function (addExceptions) {
michael@0 722 // if NoScript isn't installed, or is disabled, bail out.
michael@0 723 let ns = Cc["@maone.net/noscript-service;1"];
michael@0 724 if (ns == null)
michael@0 725 return;
michael@0 726
michael@0 727 ns = ns.getService().wrappedJSObject;
michael@0 728 if (addExceptions) {
michael@0 729 this._remoteSites.forEach(function(site) {
michael@0 730 site = ns.getSite(site);
michael@0 731 if (!ns.isJSEnabled(site)) {
michael@0 732 this._disabledSites.push(site); // save status
michael@0 733 ns.setJSEnabled(site, true); // allow site
michael@0 734 }
michael@0 735 }, this);
michael@0 736 }
michael@0 737 else {
michael@0 738 this._disabledSites.forEach(function(site) {
michael@0 739 ns.setJSEnabled(site, false);
michael@0 740 });
michael@0 741 this._disabledSites = [];
michael@0 742 }
michael@0 743 },
michael@0 744
michael@0 745 onExistingServerCommand: function () {
michael@0 746 let control = document.getElementById("existingServer");
michael@0 747 if (control.selectedIndex == 0) {
michael@0 748 control.removeAttribute("editable");
michael@0 749 Weave.Svc.Prefs.reset("serverURL");
michael@0 750 } else {
michael@0 751 control.setAttribute("editable", "true");
michael@0 752 // Force a style flush to ensure that the binding is attached.
michael@0 753 control.clientTop;
michael@0 754 control.value = "";
michael@0 755 control.inputField.focus();
michael@0 756 }
michael@0 757 document.getElementById("existingServerFeedbackRow").hidden = true;
michael@0 758 this.checkFields();
michael@0 759 },
michael@0 760
michael@0 761 onExistingServerInput: function () {
michael@0 762 // Check custom server validity when the user stops typing for 1 second.
michael@0 763 if (this._existingServerTimer)
michael@0 764 window.clearTimeout(this._existingServerTimer);
michael@0 765 this._existingServerTimer = window.setTimeout(function () {
michael@0 766 gSyncSetup.checkFields();
michael@0 767 }, 1000);
michael@0 768 },
michael@0 769
michael@0 770 onServerCommand: function () {
michael@0 771 setVisibility(document.getElementById("TOSRow"), this._usingMainServers);
michael@0 772 let control = document.getElementById("server");
michael@0 773 if (!this._usingMainServers) {
michael@0 774 control.setAttribute("editable", "true");
michael@0 775 // Force a style flush to ensure that the binding is attached.
michael@0 776 control.clientTop;
michael@0 777 control.value = "";
michael@0 778 control.inputField.focus();
michael@0 779 // checkServer() will call checkAccount() and checkFields().
michael@0 780 this.checkServer();
michael@0 781 return;
michael@0 782 }
michael@0 783 control.removeAttribute("editable");
michael@0 784 Weave.Svc.Prefs.reset("serverURL");
michael@0 785 if (this._settingUpNew) {
michael@0 786 this.loadCaptcha();
michael@0 787 }
michael@0 788 this.checkAccount();
michael@0 789 this.status.server = true;
michael@0 790 document.getElementById("serverFeedbackRow").hidden = true;
michael@0 791 this.checkFields();
michael@0 792 },
michael@0 793
michael@0 794 onServerInput: function () {
michael@0 795 // Check custom server validity when the user stops typing for 1 second.
michael@0 796 if (this._checkServerTimer)
michael@0 797 window.clearTimeout(this._checkServerTimer);
michael@0 798 this._checkServerTimer = window.setTimeout(function () {
michael@0 799 gSyncSetup.checkServer();
michael@0 800 }, 1000);
michael@0 801 },
michael@0 802
michael@0 803 checkServer: function () {
michael@0 804 delete this._checkServerTimer;
michael@0 805 let el = document.getElementById("server");
michael@0 806 let valid = false;
michael@0 807 let feedback = document.getElementById("serverFeedbackRow");
michael@0 808 let str = "";
michael@0 809 if (el.value) {
michael@0 810 valid = this._validateServer(el);
michael@0 811 let str = valid ? "" : "serverInvalid.label";
michael@0 812 this._setFeedbackMessage(feedback, valid, str);
michael@0 813 }
michael@0 814 else
michael@0 815 this._setFeedbackMessage(feedback, true);
michael@0 816
michael@0 817 // Recheck account against the new server.
michael@0 818 if (valid)
michael@0 819 this.checkAccount();
michael@0 820
michael@0 821 this.status.server = valid;
michael@0 822 this.checkFields();
michael@0 823 },
michael@0 824
michael@0 825 _validateServer: function (element) {
michael@0 826 let valid = false;
michael@0 827 let val = element.value;
michael@0 828 if (!val)
michael@0 829 return false;
michael@0 830
michael@0 831 let uri = Weave.Utils.makeURI(val);
michael@0 832
michael@0 833 if (!uri)
michael@0 834 uri = Weave.Utils.makeURI("https://" + val);
michael@0 835
michael@0 836 if (uri && this._settingUpNew) {
michael@0 837 function isValid(uri) {
michael@0 838 Weave.Service.serverURL = uri.spec;
michael@0 839 let check = Weave.Service.checkAccount("a");
michael@0 840 return (check == "available" || check == "notAvailable");
michael@0 841 }
michael@0 842
michael@0 843 if (uri.schemeIs("http")) {
michael@0 844 uri.scheme = "https";
michael@0 845 if (isValid(uri))
michael@0 846 valid = true;
michael@0 847 else
michael@0 848 // setting the scheme back to http
michael@0 849 uri.scheme = "http";
michael@0 850 }
michael@0 851 if (!valid)
michael@0 852 valid = isValid(uri);
michael@0 853
michael@0 854 if (valid) {
michael@0 855 this.loadCaptcha();
michael@0 856 }
michael@0 857 }
michael@0 858 else if (uri) {
michael@0 859 valid = true;
michael@0 860 Weave.Service.serverURL = uri.spec;
michael@0 861 }
michael@0 862
michael@0 863 if (valid)
michael@0 864 element.value = Weave.Service.serverURL;
michael@0 865 else
michael@0 866 Weave.Svc.Prefs.reset("serverURL");
michael@0 867
michael@0 868 return valid;
michael@0 869 },
michael@0 870
michael@0 871 _handleChoice: function () {
michael@0 872 let desc = document.getElementById("mergeChoiceRadio").selectedIndex;
michael@0 873 document.getElementById("chosenActionDeck").selectedIndex = desc;
michael@0 874 switch (desc) {
michael@0 875 case 1:
michael@0 876 if (this._case1Setup)
michael@0 877 break;
michael@0 878
michael@0 879 let places_db = PlacesUtils.history
michael@0 880 .QueryInterface(Ci.nsPIPlacesDatabase)
michael@0 881 .DBConnection;
michael@0 882 if (Weave.Service.engineManager.get("history").enabled) {
michael@0 883 let daysOfHistory = 0;
michael@0 884 let stm = places_db.createStatement(
michael@0 885 "SELECT ROUND(( " +
michael@0 886 "strftime('%s','now','localtime','utc') - " +
michael@0 887 "( " +
michael@0 888 "SELECT visit_date FROM moz_historyvisits " +
michael@0 889 "ORDER BY visit_date ASC LIMIT 1 " +
michael@0 890 ")/1000000 " +
michael@0 891 ")/86400) AS daysOfHistory ");
michael@0 892
michael@0 893 if (stm.step())
michael@0 894 daysOfHistory = stm.getInt32(0);
michael@0 895 // Support %S for historical reasons (see bug 600141)
michael@0 896 document.getElementById("historyCount").value =
michael@0 897 PluralForm.get(daysOfHistory,
michael@0 898 this._stringBundle.GetStringFromName("historyDaysCount.label"))
michael@0 899 .replace("%S", daysOfHistory)
michael@0 900 .replace("#1", daysOfHistory);
michael@0 901 } else {
michael@0 902 document.getElementById("historyCount").hidden = true;
michael@0 903 }
michael@0 904
michael@0 905 if (Weave.Service.engineManager.get("bookmarks").enabled) {
michael@0 906 let bookmarks = 0;
michael@0 907 let stm = places_db.createStatement(
michael@0 908 "SELECT count(*) AS bookmarks " +
michael@0 909 "FROM moz_bookmarks b " +
michael@0 910 "LEFT JOIN moz_bookmarks t ON " +
michael@0 911 "b.parent = t.id WHERE b.type = 1 AND t.parent <> :tag");
michael@0 912 stm.params.tag = PlacesUtils.tagsFolderId;
michael@0 913 if (stm.executeStep())
michael@0 914 bookmarks = stm.row.bookmarks;
michael@0 915 // Support %S for historical reasons (see bug 600141)
michael@0 916 document.getElementById("bookmarkCount").value =
michael@0 917 PluralForm.get(bookmarks,
michael@0 918 this._stringBundle.GetStringFromName("bookmarksCount.label"))
michael@0 919 .replace("%S", bookmarks)
michael@0 920 .replace("#1", bookmarks);
michael@0 921 } else {
michael@0 922 document.getElementById("bookmarkCount").hidden = true;
michael@0 923 }
michael@0 924
michael@0 925 if (Weave.Service.engineManager.get("passwords").enabled) {
michael@0 926 let logins = Services.logins.getAllLogins({});
michael@0 927 // Support %S for historical reasons (see bug 600141)
michael@0 928 document.getElementById("passwordCount").value =
michael@0 929 PluralForm.get(logins.length,
michael@0 930 this._stringBundle.GetStringFromName("passwordsCount.label"))
michael@0 931 .replace("%S", logins.length)
michael@0 932 .replace("#1", logins.length);
michael@0 933 } else {
michael@0 934 document.getElementById("passwordCount").hidden = true;
michael@0 935 }
michael@0 936
michael@0 937 if (!Weave.Service.engineManager.get("prefs").enabled) {
michael@0 938 document.getElementById("prefsWipe").hidden = true;
michael@0 939 }
michael@0 940
michael@0 941 let addonsEngine = Weave.Service.engineManager.get("addons");
michael@0 942 if (addonsEngine.enabled) {
michael@0 943 let ids = addonsEngine._store.getAllIDs();
michael@0 944 let blessedcount = 0;
michael@0 945 for each (let i in ids) {
michael@0 946 if (i) {
michael@0 947 blessedcount++;
michael@0 948 }
michael@0 949 }
michael@0 950 // bug 600141 does not apply, as this does not have to support existing strings
michael@0 951 document.getElementById("addonCount").value =
michael@0 952 PluralForm.get(blessedcount,
michael@0 953 this._stringBundle.GetStringFromName("addonsCount.label"))
michael@0 954 .replace("#1", blessedcount);
michael@0 955 } else {
michael@0 956 document.getElementById("addonCount").hidden = true;
michael@0 957 }
michael@0 958
michael@0 959 this._case1Setup = true;
michael@0 960 break;
michael@0 961 case 2:
michael@0 962 if (this._case2Setup)
michael@0 963 break;
michael@0 964 let count = 0;
michael@0 965 function appendNode(label) {
michael@0 966 let box = document.getElementById("clientList");
michael@0 967 let node = document.createElement("label");
michael@0 968 node.setAttribute("value", label);
michael@0 969 node.setAttribute("class", "data indent");
michael@0 970 box.appendChild(node);
michael@0 971 }
michael@0 972
michael@0 973 for each (let name in Weave.Service.clientsEngine.stats.names) {
michael@0 974 // Don't list the current client
michael@0 975 if (name == Weave.Service.clientsEngine.localName)
michael@0 976 continue;
michael@0 977
michael@0 978 // Only show the first several client names
michael@0 979 if (++count <= 5)
michael@0 980 appendNode(name);
michael@0 981 }
michael@0 982 if (count > 5) {
michael@0 983 // Support %S for historical reasons (see bug 600141)
michael@0 984 let label =
michael@0 985 PluralForm.get(count - 5,
michael@0 986 this._stringBundle.GetStringFromName("additionalClientCount.label"))
michael@0 987 .replace("%S", count - 5)
michael@0 988 .replace("#1", count - 5);
michael@0 989 appendNode(label);
michael@0 990 }
michael@0 991 this._case2Setup = true;
michael@0 992 break;
michael@0 993 }
michael@0 994
michael@0 995 return true;
michael@0 996 },
michael@0 997
michael@0 998 // sets class and string on a feedback element
michael@0 999 // if no property string is passed in, we clear label/style
michael@0 1000 _setFeedback: function (element, success, string) {
michael@0 1001 element.hidden = success || !string;
michael@0 1002 let classname = success ? "success" : "error";
michael@0 1003 let image = element.getElementsByAttribute("class", "statusIcon")[0];
michael@0 1004 image.setAttribute("status", classname);
michael@0 1005 let label = element.getElementsByAttribute("class", "status")[0];
michael@0 1006 label.value = string;
michael@0 1007 },
michael@0 1008
michael@0 1009 // shim
michael@0 1010 _setFeedbackMessage: function (element, success, string) {
michael@0 1011 let str = "";
michael@0 1012 if (string) {
michael@0 1013 try {
michael@0 1014 str = this._stringBundle.GetStringFromName(string);
michael@0 1015 } catch(e) {}
michael@0 1016
michael@0 1017 if (!str)
michael@0 1018 str = Weave.Utils.getErrorString(string);
michael@0 1019 }
michael@0 1020 this._setFeedback(element, success, str);
michael@0 1021 },
michael@0 1022
michael@0 1023 loadCaptcha: function loadCaptcha() {
michael@0 1024 let captchaURI = Weave.Service.miscAPI + "captcha_html";
michael@0 1025 // First check for NoScript and whitelist the right sites.
michael@0 1026 this._handleNoScript(true);
michael@0 1027 if (this.captchaBrowser.currentURI.spec != captchaURI) {
michael@0 1028 this.captchaBrowser.loadURI(captchaURI);
michael@0 1029 }
michael@0 1030 },
michael@0 1031
michael@0 1032 onStateChange: function(webProgress, request, stateFlags, status) {
michael@0 1033 // We're only looking for the end of the frame load
michael@0 1034 if ((stateFlags & Ci.nsIWebProgressListener.STATE_STOP) == 0)
michael@0 1035 return;
michael@0 1036 if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) == 0)
michael@0 1037 return;
michael@0 1038 if ((stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) == 0)
michael@0 1039 return;
michael@0 1040
michael@0 1041 // If we didn't find a captcha, assume it's not needed and don't show it.
michael@0 1042 let responseStatus = request.QueryInterface(Ci.nsIHttpChannel).responseStatus;
michael@0 1043 setVisibility(this.captchaBrowser, responseStatus != 404);
michael@0 1044 //XXX TODO we should really log any responseStatus other than 200
michael@0 1045 },
michael@0 1046 onProgressChange: function() {},
michael@0 1047 onStatusChange: function() {},
michael@0 1048 onSecurityChange: function() {},
michael@0 1049 onLocationChange: function () {}
michael@0 1050 };
michael@0 1051
michael@0 1052 // Define lazy getters for various XUL elements.
michael@0 1053 //
michael@0 1054 // onWizardAdvance() and onPageShow() are run before init(), so we'll even
michael@0 1055 // define things that will almost certainly be used (like 'wizard') as a lazy
michael@0 1056 // getter here.
michael@0 1057 ["wizard",
michael@0 1058 "pin1",
michael@0 1059 "pin2",
michael@0 1060 "pin3",
michael@0 1061 "pairDeviceErrorRow",
michael@0 1062 "pairDeviceThrobber"].forEach(function (id) {
michael@0 1063 XPCOMUtils.defineLazyGetter(gSyncSetup, id, function() {
michael@0 1064 return document.getElementById(id);
michael@0 1065 });
michael@0 1066 });
michael@0 1067 XPCOMUtils.defineLazyGetter(gSyncSetup, "nextFocusEl", function () {
michael@0 1068 return {pin1: this.pin2,
michael@0 1069 pin2: this.pin3,
michael@0 1070 pin3: this.wizard.getButton("next")};
michael@0 1071 });
michael@0 1072 XPCOMUtils.defineLazyGetter(gSyncSetup, "_stringBundle", function() {
michael@0 1073 return Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
michael@0 1074 });

mercurial