Javascript  |  691行  |  23.3 KB

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('options', function() {
  const OptionsPage = options.OptionsPage;

  // Variable to track if a captcha challenge was issued. If this gets set to
  // true, it stays that way until we are told about successful login from
  // the browser.  This means subsequent errors (like invalid password) are
  // rendered in the captcha state, which is basically identical except we
  // don't show the top error blurb "Error Signing in" or the "Create
  // account" link.
  var captchaChallengeActive_ = false;

  // True if the synced account uses a custom passphrase.
  var usePassphrase_ = false;

  /**
   * SyncSetupOverlay class
   * Encapsulated handling of the 'Sync Setup' overlay page.
   * @class
   */
  function SyncSetupOverlay() {
    OptionsPage.call(this, 'syncSetup',
                     templateData.syncSetupOverlayTitle,
                     'sync-setup-overlay');
  }

  cr.addSingletonGetter(SyncSetupOverlay);

  SyncSetupOverlay.prototype = {
    __proto__: OptionsPage.prototype,

    /**
     * Initializes the page.
     */
    initializePage: function() {
      OptionsPage.prototype.initializePage.call(this);

      var acct_text = $('gaia-account-text');
      var translated_text = acct_text.textContent;
      var posGoogle = translated_text.indexOf('Google');
      if (posGoogle != -1) {
        var ltr = templateData['textdirection'] == 'ltr';
        var googleIsAtEndOfSentence = posGoogle != 0;
        if (googleIsAtEndOfSentence == ltr) {
          // We're in ltr and in the translation the word 'Google' is AFTER the
          // word 'Account' OR we're in rtl and 'Google' is BEFORE 'Account'.
          var logo_td = $('gaia-logo');
          logo_td.parentNode.appendChild(logo_td);
        }
        acct_text.textContent = translated_text.replace('Google','');
      }

      var self = this;
      $('gaia-login-form').onsubmit = function() {
        self.sendCredentialsAndClose_();
        return false;
      };
      $('chooseDataTypesForm').onsubmit = function() {
        self.sendConfiguration_();
        return false;
      };
      $('google-option').onchange = $('explicit-option').onchange = function() {
        self.onRadioChange_();
      };
      $('choose-datatypes-cancel').onclick = $('sync-setup-cancel').onclick =
          $('confirm-everything-cancel').onclick = function() {
        self.closeOverlay_();
      };
      $('customize-link').onclick = function() {
        self.showCustomizePage_(false);
      };
      $('confirm-everything-ok').onclick = function() {
        self.sendConfiguration_();
      };
      $('use-default-link').onclick = function() {
        self.showSyncEverythingPage_();
      };
      $('cancel-no-button').onclick = function() {
        self.hideCancelWarning_();
        return false;
      };
      $('cancel-yes-button').onclick = function() {
        chrome.send('PassphraseCancel', ['']);
        return false;
      };
      $('passphraseForm').onsubmit = $('passphrase-ok').onclick = function() {
        self.sendPassphraseAndClose_();
        return false;
      };
      $('passphrase-cancel').onclick = function() {
        self.showCancelWarning_();
        return false;
      };
    },

    closeOverlay_: function() {
      OptionsPage.closeOverlay();
    },

    /** @inheritDoc */
    didShowPage: function() {
      chrome.send('didShowPage');
    },

    /** @inheritDoc */
    didClosePage: function() {
      chrome.send('didClosePage');
    },

    showCancelWarning_: function() {
      $('cancel-warning-box').hidden = false;
      $('passphrase-ok').disabled = true;
      $('passphrase-cancel').disabled = true;
      $('cancel-no-button').focus();
    },

    sendPassphraseAndClose_: function() {
      var f = $('passphraseForm');
      var result = JSON.stringify({"passphrase": f.passphrase.value});
      chrome.send("Passphrase", [result]);
    },

    getRadioCheckedValue_: function() {
      var f = $('chooseDataTypesForm');
      for (var i = 0; i < f.option.length; ++i) {
        if (f.option[i].checked) {
          return f.option[i].value;
        }
      }

      return undefined;
    },

    // TODO(jhawkins): Remove this method.
    switchToMode_: function(mode) {
      if (mode == "google")
        $('sync-custom-passphrase').hidden = true;
      else if (mode =="explicit")
        $('sync-custom-passphrase').hidden = false;
    },

    onRadioChange_: function() {
      this.switchToMode_(this.getRadioCheckedValue_());
    },

    checkAllDataTypeCheckboxes_: function() {
      var checkboxes = document.getElementsByName("dataTypeCheckbox");
      for (var i = 0; i < checkboxes.length; i++) {
        // Only check the visible ones (since there's no way to uncheck
        // the invisible ones).
        if (checkboxes[i].parentElement.className == "sync-item-show") {
          checkboxes[i].checked = true;
        }
      }
    },

    setDataTypeCheckboxesEnabled_: function(enabled) {
      var checkboxes = document.getElementsByName("dataTypeCheckbox");
      var labels = document.getElementsByName("dataTypeLabel");
      for (var i = 0; i < checkboxes.length; i++) {
        checkboxes[i].disabled = !enabled;
        if (checkboxes[i].disabled) {
          labels[i].className = "sync-label-inactive";
        } else {
          labels[i].className = "sync-label-active";
        }
      }
    },

    setCheckboxesToKeepEverythingSynced_: function(value) {
      this.setDataTypeCheckboxesEnabled_(!value);
      if (value)
        this.checkAllDataTypeCheckboxes_();
    },

    // Returns true if at least one data type is enabled and no data types are
    // checked. (If all data type checkboxes are disabled, it's because "keep
    // everything synced" is checked.)
    noDataTypesChecked_: function() {
      var checkboxes = document.getElementsByName("dataTypeCheckbox");
      var atLeastOneChecked = false;
      var atLeastOneEnabled = false;
      for (var i = 0; i < checkboxes.length; i++) {
        if (!checkboxes[i].disabled &&
            checkboxes[i].parentElement.className == "sync-item-show") {
          atLeastOneEnabled = true;
          if (checkboxes[i].checked) {
            atLeastOneChecked = true;
          }
        }
      }

      return atLeastOneEnabled && !atLeastOneChecked;
    },

    checkPassphraseMatch_: function() {
      var emptyError = $('emptyerror');
      var mismatchError = $('mismatcherror');
      emptyError.style.display = "none";
      mismatchError.style.display = "none";

      var f = $('chooseDataTypesForm');
      if (this.getRadioCheckedValue_() != "explicit" || f.option[0].disabled)
        return true;

      var customPassphrase = $('custom-passphrase');
      if (customPassphrase.value.length == 0) {
        emptyError.style.display = "block";
        return false;
      }

      var confirmPassphrase = $('confirm-passphrase');
      if (confirmPassphrase.value != customPassphrase.value) {
        mismatchError.style.display = "block";
        return false;
      }

      return true;
    },

    hideCancelWarning_: function() {
      $('cancel-warning-box').hidden = true;
      $('passphrase-ok').disabled = false;
      $('passphrase-cancel').disabled = false;
    },

    sendConfiguration_: function() {
      // Trying to submit, so hide previous errors.
      $('aborted-text').className = "sync-error-hide";
      $('error-text').className = "sync-error-hide";

      if (this.noDataTypesChecked_()) {
        $('error-text').className = "sync-error-show";
        return;
      }

      var f = $('chooseDataTypesForm');
      if (!this.checkPassphraseMatch_())
        return;

      // Don't allow the user to tweak the settings once we send the
      // configuration to the backend.
      this.disableConfigureElements_();

      var syncAll =
        document.getElementById('sync-select-datatypes').selectedIndex == 0;
      var customPassphrase = $('custom-passphrase');

      // These values need to be kept in sync with where they are read in
      // SyncSetupFlow::GetDataTypeChoiceData().
      var result = JSON.stringify({
          "keepEverythingSynced": syncAll,
          "syncBookmarks": syncAll || f.bookmarksCheckbox.checked,
          "syncPreferences": syncAll || f.preferencesCheckbox.checked,
          "syncThemes": syncAll || f.themesCheckbox.checked,
          "syncPasswords": syncAll || f.passwordsCheckbox.checked,
          "syncAutofill": syncAll || f.autofillCheckbox.checked,
          "syncExtensions": syncAll || f.extensionsCheckbox.checked,
          "syncTypedUrls": syncAll || f.typedUrlsCheckbox.checked,
          "syncApps": syncAll || f.appsCheckbox.checked,
          "syncSessions": syncAll || f.sessionsCheckbox.checked,
          "usePassphrase": (this.getRadioCheckedValue_() == 'explicit'),
          "passphrase": customPassphrase.value
      });
      chrome.send("Configure", [result]);
    },

    /**
     * Disables all input elements within the 'Customize Sync Preferences'
     * screen. This is used to prohibit the user from changing the inputs after
     * confirming the customized sync preferences.
     * @private
     */
    disableConfigureElements_: function() {
      var configureElements =
          $('customize-sync-preferences').querySelectorAll('input');
      for (var i = 0; i < configureElements.length; i++)
        configureElements[i].disabled = true;
    },

    setChooseDataTypesCheckboxes_: function(args) {
      // If this frame is on top, the focus should be on it, so pressing enter
      // submits this form.
      if (args.iframeToShow == 'configure') {
        $('choose-datatypes-ok').focus();
      }

      var datatypeSelect = document.getElementById('sync-select-datatypes');
      datatypeSelect.selectedIndex = args.keepEverythingSynced ? 0 : 1;

      $('bookmarksCheckbox').checked = args.syncBookmarks;
      $('preferencesCheckbox').checked = args.syncPreferences;
      $('themesCheckbox').checked = args.syncThemes;

      if (args.passwordsRegistered) {
        $('passwordsCheckbox').checked = args.syncPasswords;
        $('passwordsItem').className = "sync-item-show";
      } else {
        $('passwordsItem').className = "sync-item-hide";
      }
      if (args.autofillRegistered) {
        $('autofillCheckbox').checked = args.syncAutofill;
        $('autofillItem').className = "sync-item-show";
      } else {
        $('autofillItem').className = "sync-item-hide";
      }
      if (args.extensionsRegistered) {
        $('extensionsCheckbox').checked = args.syncExtensions;
        $('extensionsItem').className = "sync-item-show";
      } else {
        $('extensionsItem').className = "sync-item-hide";
      }
      if (args.typedUrlsRegistered) {
        $('typedUrlsCheckbox').checked = args.syncTypedUrls;
        $('omniboxItem').className = "sync-item-show";
      } else {
        $('omniboxItem').className = "sync-item-hide";
      }
      if (args.appsRegistered) {
        $('appsCheckbox').checked = args.syncApps;
        $('appsItem').className = "sync-item-show";
      } else {
        $('appsItem').className = "sync-item-hide";
      }

      this.setCheckboxesToKeepEverythingSynced_(args.keepEverythingSynced);
      if (args.sessionsRegistered) {
        $('sessionsCheckbox').checked = args.syncSessions;
        $('sessionsItem').className = "sync-item-show";
      } else {
        $('sessionsItem').className = "sync-item-hide";
      }
    },

    setEncryptionCheckboxes_: function(args) {
      if (args["usePassphrase"]) {
        $('explicit-option').checked = true;

        // The passphrase, once set, cannot be unset, but we show a reset link.
        $('explicit-option').disabled = true;
        $('google-option').disabled = true;
        $('sync-custom-passphrase').hidden = true;
      } else {
        $('google-option').checked = true;
      }

      this.switchToMode_("");
    },

    setErrorState_: function(args) {
      if (!args.was_aborted)
        return;

      $('aborted-text').className = "sync-error-show";
      $('choose-datatypes-ok').disabled = true;
      $('keepEverythingSyncedRadio').disabled = true;
      $('chooseDataTypesRadio').disabled = true;
    },

    setCheckboxesAndErrors_: function(args) {
      this.setChooseDataTypesCheckboxes_(args);
      this.setEncryptionCheckboxes_(args);
      this.setErrorState_(args);
    },

    // Called once, when this html/js is loaded.
    showConfigure_: function(args) {
      var datatypeSelect = document.getElementById('sync-select-datatypes');
      var self = this;
      datatypeSelect.onchange = function() {
        var syncAll = this.selectedIndex == 0;
        self.setCheckboxesToKeepEverythingSynced_(syncAll);
      };

      $('sync-setup-configure').classList.remove('hidden');

      if (args) {
        this.setCheckboxesAndErrors_(args);

        // Whether to display the 'Sync everything' confirmation screen or the
        // customize data types screen.
        // TODO(jhawkins): Rename |keepEverythingSynced| to |syncAllDataTypes|.
        var syncEverything = args['syncEverything'];
        var syncAllDataTypes = args['keepEverythingSynced'];
        this.usePassphrase_ = args['usePassphrase'];
        if (syncEverything == false || syncAllDataTypes == false ||
            this.usePassphrase_) {
          this.showCustomizePage_(syncAllDataTypes);
        } else {
          this.showSyncEverythingPage_();
        }
      }
    },

    showSyncEverythingPage_: function() {
      $('confirm-sync-preferences').hidden = false;
      $('customize-sync-preferences').hidden = true;

      // Reset the selection to 'Sync everything'.
      $('sync-select-datatypes').selectedIndex = 0;

      // The default state is to sync everything.
      this.setCheckboxesToKeepEverythingSynced_(true);

      // If the account is not synced with a custom passphrase, reset the
      // passphrase radio when switching to the 'Sync everything' page.
      if (!this.usePassphrase_) {
        $('google-option').checked = true;
        this.switchToMode_("google");
      }

      $('confirm-everything-ok').focus();
    },

    showCustomizePage_: function(syncEverything) {
      document.getElementById('confirm-sync-preferences').hidden = true;
      document.getElementById('customize-sync-preferences').hidden = false;

      // If the user has selected the 'Customize' page on initial set up, it's
      // likely he intends to change the data types.  Select the
      // 'Choose data types' option in this case.
      var index = syncEverything ? 0 : 1;
      document.getElementById('sync-select-datatypes').selectedIndex = index;
      this.setDataTypeCheckboxesEnabled_(!syncEverything);
      $('choose-datatypes-ok').focus();
    },

    showSyncSetupPage_: function(page, args) {
      if (page == 'settingUp') {
        this.setThrobbersVisible_(true);
        return;
      } else {
        this.setThrobbersVisible_(false);
      }

      // Hide an existing visible overlay.
      var overlay = $('sync-setup-overlay');
      for (var i = 0; i < overlay.children.length; i++)
        overlay.children[i].classList.add('hidden');

      if (page == 'login')
        this.showGaiaLogin_(args);
      else if (page == 'configure')
        this.showConfigure_(args);
      else if (page == 'passphrase')
        this.showPassphrase_(args);
      else if (page == 'done')
        this.closeOverlay_();
    },

    setThrobbersVisible_: function(visible) {
      var throbbers = document.getElementsByClassName("throbber");
        for (var i = 0; i < throbbers.length; i++)
          throbbers[i].style.visibility = visible ? "visible" : "hidden";
    },

    showPassphrase_: function(args) {
      $('sync-setup-passphrase').classList.remove('hidden');

      $('passphraseRejectedBody').style.display = "none";
      $('normalBody').style.display = "none";
      $('incorrectPassphrase').style.display = "none";

      if (args["passphrase_creation_rejected"]) {
        $('passphraseRejectedBody').style.display = "block";
      } else {
        $('normalBody').style.display = "block";
      }

      if (args["passphrase_setting_rejected"]) {
        $('incorrectPassphrase').style.display = "block";
      }

      $('passphrase').focus();
    },

    setElementDisplay_: function(id, display) {
      var d = document.getElementById(id);
      if (d)
        d.style.display = display;
    },

    loginSetFocus_: function() {
      var email = $('gaia-email');
      var passwd = $('gaia-passwd');
      if (email && (email.value == null || email.value == "")) {
        email.focus();
      } else if (passwd) {
        passwd.focus();
      }
    },

    showAccessCodeRequired_: function() {
      this.setElementDisplay_("password-row", "none");
      this.setElementDisplay_("email-row", "none");
      $('create-account-cell').style.visibility = "hidden";

      this.setElementDisplay_("access-code-label-row", "table-row");
      this.setElementDisplay_("access-code-input-row", "table-row");
      this.setElementDisplay_("access-code-help-row", "table-row");
      document.getElementById('access-code').disabled = false;
    },

    showCaptcha_: function(args) {
      this.captchaChallengeActive_ = true;

      // The captcha takes up lots of space, so make room.
      this.setElementDisplay_("top-blurb", "none");
      this.setElementDisplay_("top-blurb-error", "none");
      this.setElementDisplay_("create-account-div", "none");
      document.getElementById('create-account-cell').height = 0;

      // It's showtime for the captcha now.
      this.setElementDisplay_("captcha-div", "block");
      document.getElementById('gaia-email').disabled = true;
      document.getElementById('gaia-passwd').disabled = false;
      document.getElementById('captcha-value').disabled = false;
      document.getElementById('captcha-wrapper').style.backgroundImage =
          url(args.captchaUrl);
    },

    showGaiaLogin_: function(args) {
      $('sync-setup-login').classList.remove('hidden');

      document.getElementById('gaia-email').disabled = false;
      document.getElementById('gaia-passwd').disabled = false;

      var f = $('gaia-login-form');
      var email = $('gaia-email');
      var passwd = $('gaia-passwd');
      if (f) {
        if (args.user != undefined) {
          if (email.value != args.user)
            passwd.value = ""; // Reset the password field
          email.value = args.user;
        }

        if (!args.editable_user) {
          email.style.display = 'none';
          var span = document.getElementById('email-readonly');
          span.appendChild(document.createTextNode(email.value));
          span.style.display = 'inline';
          this.setElementDisplay_("create-account-div", "none");
        }

        f.accessCode.disabled = true;
      }

      if (1 == args.error) {
        var access_code = document.getElementById('access-code');
        if (access_code.value && access_code.value != "") {
          this.setElementDisplay_("errormsg-0-access-code", 'block');
          this.showAccessCodeRequired_();
        } else {
          this.setElementDisplay_("errormsg-1-password", 'table-row');
        }
        this.setBlurbError_(args.error_message);
      } else if (3 == args.error) {
        this.setElementDisplay_("errormsg-0-connection", 'table-row');
        this.setBlurbError_(args.error_message);
      } else if (4 == args.error) {
        this.showCaptcha_(args);
      } else if (8 == args.error) {
        this.showAccessCodeRequired_();
      } else if (args.error_message) {
        this.setBlurbError_(args.error_message);
      }

      $('sign-in').disabled = false;
      $('sign-in').value = templateData['signin'];
      this.loginSetFocus_();
    },

    resetErrorVisibility_: function() {
      this.setElementDisplay_("errormsg-0-email", 'none');
      this.setElementDisplay_("errormsg-0-password", 'none');
      this.setElementDisplay_("errormsg-1-password", 'none');
      this.setElementDisplay_("errormsg-0-connection", 'none');
      this.setElementDisplay_("errormsg-0-access-code", 'none');
    },

    setBlurbError_: function(error_message) {
      if (this.captchaChallengeActive_)
        return;  // No blurb in captcha challenge mode.

      if (error_message) {
        document.getElementById('error-signing-in').style.display = 'none';
        document.getElementById('error-custom').style.display = 'inline';
        document.getElementById('error-custom').textContent = error_message;
      } else {
        document.getElementById('error-signing-in').style.display = 'inline';
        document.getElementById('error-custom').style.display = 'none';
      }

      $('top-blurb-error').style.visibility = "visible";
      document.getElementById('gaia-email').disabled = false;
      document.getElementById('gaia-passwd').disabled = false;
    },

    setErrorVisibility_: function() {
      this.resetErrorVisibility_();
      var f = $('gaia-login-form');
      var email = $('gaia-email');
      var passwd = $('gaia-passwd');
      if (null == email.value || "" == email.value) {
        this.setElementDisplay_("errormsg-0-email", 'table-row');
        this.setBlurbError_();
        return false;
      }
      if (null == passwd.value || "" == passwd.value) {
        this.setElementDisplay_("errormsg-0-password", 'table-row');
        this.setBlurbError_();
        return false;
      }
      if (!f.accessCode.disabled && (null == f.accessCode.value ||
          "" == f.accessCode.value)) {
        this.setElementDisplay_("errormsg-0-password", 'table-row');
        return false;
      }
      return true;
    },

    sendCredentialsAndClose_: function() {
      if (!this.setErrorVisibility_()) {
        return false;
      }

      $('gaia-email').disabled = true;
      $('gaia-passwd').disabled = true;
      $('captcha-value').disabled = true;
      $('access-code').disabled = true;

      $('logging-in-throbber').style.visibility = "visible";

      var f = $('gaia-login-form');
      var email = $('gaia-email');
      var passwd = $('gaia-passwd');
      var result = JSON.stringify({"user" : email.value,
                                   "pass" : passwd.value,
                                   "captcha" : f.captchaValue.value,
                                   "access_code" : f.accessCode.value});
      $('sign-in').disabled = true;
      chrome.send("SubmitAuth", [result]);
    },

    showGaiaSuccessAndClose_: function() {
      $('sign-in').value = localStrings.getString('loginSuccess');
      setTimeout(this.closeOverlay_, 1600);
    },

    showSuccessAndSettingUp_: function() {
      $('sign-in').value = localStrings.getString('settingup');
    },

    /** @inheritDoc */
    shouldClose: function() {
      if (!$('cancel-warning-box').hidden) {
        chrome.send('PassphraseCancel', ['']);
        return true;
      } else if (!$('sync-setup-passphrase').classList.contains('hidden')) {
        // The Passphrase page is showing, and the use has pressed escape.
        // Activate the cancel logic in this case.
        this.showCancelWarning_();
        return false;
      }

      return true;
    },
  };

  SyncSetupOverlay.showSyncSetupPage = function(page, args) {
    SyncSetupOverlay.getInstance().showSyncSetupPage_(page, args);
  };

  SyncSetupOverlay.showSuccessAndClose = function() {
    SyncSetupOverlay.getInstance().showSuccessAndClose_();
  };

  SyncSetupOverlay.showSuccessAndSettingUp = function() {
    SyncSetupOverlay.getInstance().showSuccessAndSettingUp_();
  };

  // Export
  return {
    SyncSetupOverlay: SyncSetupOverlay
  };
});