summaryrefslogtreecommitdiffstats
path: root/webbrowser/components/sync/utils.js
blob: d41ecf18a3db2add36338fb15ad71d9dc965d531 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Equivalent to 0o600 permissions; used for saved Sync Recovery Key.
// This constant can be replaced when the equivalent values are available to
// chrome JS; see Bug 433295 and Bug 757351.
const PERMISSIONS_RWUSR = 0x180;

// Weave should always exist before before this file gets included.
var gSyncUtils = {
  get bundle() {
    delete this.bundle;
    return this.bundle = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
  },

  // opens in a new window if we're in a modal prefwindow world, in a new tab otherwise
  _openLink: function (url) {
    let thisDocEl = document.documentElement,
        openerDocEl = window.opener && window.opener.document.documentElement;
    if (thisDocEl.id == "accountSetup" && window.opener &&
        openerDocEl.id == "BrowserPreferences" && !openerDocEl.instantApply)
      openUILinkIn(url, "window");
    else if (thisDocEl.id == "BrowserPreferences" && !thisDocEl.instantApply)
      openUILinkIn(url, "window");
    else if (document.documentElement.id == "change-dialog")
      Services.wm.getMostRecentWindow("navigator:browser")
              .openUILinkIn(url, "tab");
    else
      openUILinkIn(url, "tab");
  },

  changeName: function changeName(input) {
    // Make sure to update to a modified name, e.g., empty-string -> default
    Weave.Service.clientsEngine.localName = input.value;
    input.value = Weave.Service.clientsEngine.localName;
  },

  openChange: function openChange(type, duringSetup) {
    // Just re-show the dialog if it's already open
    let openedDialog = Services.wm.getMostRecentWindow("Sync:" + type);
    if (openedDialog != null) {
      openedDialog.focus();
      return;
    }

    // Open up the change dialog
    let changeXUL = "chrome://browser/content/sync/genericChange.xul";
    let changeOpt = "centerscreen,chrome,resizable=no";
    Services.ww.activeWindow.openDialog(changeXUL, "", changeOpt,
                                        type, duringSetup);
  },

  changePassword: function () {
    if (Weave.Utils.ensureMPUnlocked())
      this.openChange("ChangePassword");
  },

  resetPassphrase: function (duringSetup) {
    if (Weave.Utils.ensureMPUnlocked())
      this.openChange("ResetPassphrase", duringSetup);
  },

  updatePassphrase: function () {
    if (Weave.Utils.ensureMPUnlocked())
      this.openChange("UpdatePassphrase");
  },

  resetPassword: function () {
    this._openLink(Weave.Service.pwResetURL);
  },

  openToS: function () {
    this._openLink(Weave.Svc.Prefs.get("termsURL"));
  },

  openPrivacyPolicy: function () {
    this._openLink(Weave.Svc.Prefs.get("privacyURL"));
  },

  openFirstSyncProgressPage: function () {
    this._openLink("about:sync-progress");
  },

  /**
   * Prepare an invisible iframe with the passphrase backup document.
   * Used by both the print and saving methods.
   *
   * @param elid : ID of the form element containing the passphrase.
   * @param callback : Function called once the iframe has loaded.
   */
  _preparePPiframe: function(elid, callback) {
    let pp = document.getElementById(elid).value;

    // Create an invisible iframe whose contents we can print.
    let iframe = document.createElement("iframe");
    iframe.setAttribute("src", "chrome://browser/content/sync/key.xhtml");
    iframe.collapsed = true;
    document.documentElement.appendChild(iframe);
    iframe.contentWindow.addEventListener("load", function() {
      iframe.contentWindow.removeEventListener("load", arguments.callee, false);

      // Insert the Sync Key into the page.
      let el = iframe.contentDocument.getElementById("synckey");
      el.firstChild.nodeValue = pp;

      // Insert the TOS and Privacy Policy URLs into the page.
      let termsURL = Weave.Svc.Prefs.get("termsURL");
      el = iframe.contentDocument.getElementById("tosLink");
      el.setAttribute("href", termsURL);
      el.firstChild.nodeValue = termsURL;

      let privacyURL = Weave.Svc.Prefs.get("privacyURL");
      el = iframe.contentDocument.getElementById("ppLink");
      el.setAttribute("href", privacyURL);
      el.firstChild.nodeValue = privacyURL;

      callback(iframe);
    }, false);
  },

  /**
   * Print passphrase backup document.
   * 
   * @param elid : ID of the form element containing the passphrase.
   */
  passphrasePrint: function(elid) {
    this._preparePPiframe(elid, function(iframe) {
      let webBrowserPrint = iframe.contentWindow
                                  .QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIWebBrowserPrint);
      let printSettings = PrintUtils.getPrintSettings();

      // Display no header/footer decoration except for the date.
      printSettings.headerStrLeft
        = printSettings.headerStrCenter
        = printSettings.headerStrRight
        = printSettings.footerStrLeft
        = printSettings.footerStrCenter = "";
      printSettings.footerStrRight = "&D";

      try {
        webBrowserPrint.print(printSettings, null);
      } catch (ex) {
        // print()'s return codes are expressed as exceptions. Ignore.
      }
    });
  },

  /**
   * Save passphrase backup document to disk as HTML file.
   * 
   * @param elid : ID of the form element containing the passphrase.
   */
  passphraseSave: function(elid) {
    let dialogTitle = this.bundle.GetStringFromName("save.recoverykey.title");
    let defaultSaveName = this.bundle.GetStringFromName("save.recoverykey.defaultfilename");
    this._preparePPiframe(elid, function(iframe) {
      let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
      let fpCallback = function fpCallback_done(aResult) {
        if (aResult == Ci.nsIFilePicker.returnOK ||
            aResult == Ci.nsIFilePicker.returnReplace) {
          let stream = Cc["@mozilla.org/network/file-output-stream;1"].
                       createInstance(Ci.nsIFileOutputStream);
          stream.init(fp.file, -1, PERMISSIONS_RWUSR, 0);

          let serializer = new XMLSerializer();
          let output = serializer.serializeToString(iframe.contentDocument);
          output = output.replace(/<!DOCTYPE (.|\n)*?]>/,
            '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
            '"DTD/xhtml1-strict.dtd">');
          output = Weave.Utils.encodeUTF8(output);
          stream.write(output, output.length);
        }
      };

      fp.init(window, dialogTitle, Ci.nsIFilePicker.modeSave);
      fp.appendFilters(Ci.nsIFilePicker.filterHTML);
      fp.defaultString = defaultSaveName;
      fp.open(fpCallback);
      return false;
    });
  },

  /**
   * validatePassword
   *
   * @param el1 : the first textbox element in the form
   * @param el2 : the second textbox element, if omitted it's an update form
   * 
   * returns [valid, errorString]
   */
  validatePassword: function (el1, el2) {
    let valid = false;
    let val1 = el1.value;
    let val2 = el2 ? el2.value : "";
    let error = "";

    if (!el2)
      valid = val1.length >= Weave.MIN_PASS_LENGTH;
    else if (val1 && val1 == Weave.Service.identity.username)
      error = "change.password.pwSameAsUsername";
    else if (val1 && val1 == Weave.Service.identity.account)
      error = "change.password.pwSameAsEmail";
    else if (val1 && val1 == Weave.Service.identity.basicPassword)
      error = "change.password.pwSameAsPassword";
    else if (val1 && val2) {
      if (val1 == val2 && val1.length >= Weave.MIN_PASS_LENGTH)
        valid = true;
      else if (val1.length < Weave.MIN_PASS_LENGTH)
        error = "change.password.tooShort";
      else if (val1 != val2)
        error = "change.password.mismatch";
    }
    let errorString = error ? Weave.Utils.getErrorString(error) : "";
    return [valid, errorString];
  }
};