summaryrefslogtreecommitdiffstats
path: root/mailnews/base/prefs/content/accountcreation/util.js
blob: d867bfbe9668c0309fd092bd1e5c043907fd6efe (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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/**
 * Some common, generic functions
 */

try {
  var Cc = Components.classes;
  var Ci = Components.interfaces;
} catch (e) { ddump(e); } // if already declared, as in xpcshell-tests
try {
  var Cu = Components.utils;
} catch (e) { ddump(e); }

Cu.import("resource:///modules/errUtils.js");
Cu.import("resource://gre/modules/Services.jsm");

function assert(test, errorMsg)
{
  if (!test)
    throw new NotReached(errorMsg ? errorMsg :
          "Programming bug. Assertion failed, see log.");
}

function makeCallback(obj, func)
{
  return function()
  {
    return func.apply(obj, arguments);
  }
}


/**
 * Runs the given function sometime later
 *
 * Currently implemented using setTimeout(), but
 * can later be replaced with an nsITimer impl,
 * when code wants to use it in a module.
 */
function runAsync(func)
{
  setTimeout(func, 0);
}


/**
 * @param uriStr {String}
 * @result {nsIURI}
 */
function makeNSIURI(uriStr)
{
  return Services.io.newURI(uriStr, null, null);
}


/**
 * Reads UTF8 data from a URL.
 *
 * @param uri {nsIURI}   what you want to read
 * @return {Array of String}   the contents of the file, one string per line
 */
function readURLasUTF8(uri)
{
  assert(uri instanceof Ci.nsIURI, "uri must be an nsIURI");
  try {
    let chan = Services.io.newChannelFromURI2(uri,
                                              null,
                                              Services.scriptSecurityManager.getSystemPrincipal(),
                                              null,
                                              Ci.nsILoadInfo.SEC_NORMAL,
                                              Ci.nsIContentPolicy.TYPE_OTHER);
    let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
             .createInstance(Ci.nsIConverterInputStream);
    is.init(chan.open(), "UTF-8", 1024,
            Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);

    let content = "";
    let strOut = new Object();
    try {
      while (is.readString(1024, strOut) != 0)
        content += strOut.value;
    // catch in outer try/catch
    } finally {
      is.close();
    }

    return content;
  } catch (e) {
    // TODO this has a numeric error message. We need to ship translations
    // into human language.
    throw e;
  }
}

/**
 * Takes a string (which is typically the content of a file,
 * e.g. the result returned from readURLUTF8() ), and splits
 * it into lines, and returns an array with one string per line
 *
 * Linebreaks are not contained in the result,,
 * and all of \r\n, (Windows) \r (Mac) and \n (Unix) counts as linebreak.
 *
 * @param content {String} one long string with the whole file
 * @return {Array of String} one string per line (no linebreaks)
 */
function splitLines(content)
{
  content = content.replace("\r\n", "\n");
  content = content.replace("\r", "\n");
  return content.split("\n");
}

/**
 * @param bundleURI {String}   chrome URL to properties file
 * @return nsIStringBundle
 */
function getStringBundle(bundleURI)
{
  try {
    return Services.strings.createBundle(bundleURI);
  } catch (e) {
    throw new Exception("Failed to get stringbundle URI <" + bundleURI +
                        ">. Error: " + e);
  }
}


function Exception(msg)
{
  this._message = msg;

  // get stack
  try {
    not.found.here += 1; // force a native exception ...
  } catch (e) {
    this.stack = e.stack; // ... to get the current stack
  }
}
Exception.prototype =
{
  get message()
  {
    return this._message;
  },
  toString : function()
  {
    return this._message;
  }
}

function NotReached(msg)
{
  Exception.call(this, msg); // call super constructor
  logException(this);
}
// Make NotReached extend Exception.
NotReached.prototype = Object.create(Exception.prototype);
NotReached.prototype.constructor = NotReached;

/**
 * A handle for an async function which you can cancel.
 * The async function will return an object of this type (a subtype)
 * and you can call cancel() when you feel like killing the function.
 */
function Abortable()
{
}
Abortable.prototype =
{
  cancel : function()
  {
  }
}

/**
 * Utility implementation, for allowing to abort a setTimeout.
 * Use like: return new TimeoutAbortable(setTimeout(function(){ ... }, 0));
 * @param setTimeoutID {Integer}  Return value of setTimeout()
 */
function TimeoutAbortable(setTimeoutID)
{
  Abortable.call(this, setTimeoutID); // call super constructor
  this._id = setTimeoutID;
}
TimeoutAbortable.prototype = Object.create(Abortable.prototype);
TimeoutAbortable.prototype.constructor = TimeoutAbortable;
TimeoutAbortable.prototype.cancel = function() { clearTimeout(this._id); }

/**
 * Utility implementation, for allowing to abort a setTimeout.
 * Use like: return new TimeoutAbortable(setTimeout(function(){ ... }, 0));
 * @param setIntervalID {Integer}  Return value of setInterval()
 */
function IntervalAbortable(setIntervalID)
{
  Abortable.call(this, setIntervalID); // call super constructor
  this._id = setIntervalID;
}
IntervalAbortable.prototype = Object.create(Abortable.prototype);
IntervalAbortable.prototype.constructor = IntervalAbortable;
IntervalAbortable.prototype.cancel = function() { clearInterval(this._id); }

// Allows you to make several network calls, but return
// only one Abortable object.
function SuccessiveAbortable()
{
  Abortable.call(this); // call super constructor
  this._current = null;
}
SuccessiveAbortable.prototype = {
  __proto__: Abortable.prototype,
  get current() { return this._current; },
  set current(abortable)
  {
    assert(abortable instanceof Abortable || abortable == null,
        "need an Abortable object (or null)");
    this._current = abortable;
  },
  cancel: function()
  {
    if (this._current)
      this._current.cancel();
  }
}

function deepCopy(org)
{
  if (typeof(org) == "undefined")
    return undefined;
  if (org == null)
    return null;
  if (typeof(org) == "string")
    return org;
  if (typeof(org) == "number")
    return org;
  if (typeof(org) == "boolean")
    return org == true;
  if (typeof(org) == "function")
    return org;
  if (typeof(org) != "object")
    throw "can't copy objects of type " + typeof(org) + " yet";

  //TODO still instanceof org != instanceof copy
  //var result = new org.constructor();
  var result = new Object();
  if (typeof(org.length) != "undefined")
    var result = new Array();
  for (var prop in org)
    result[prop] = deepCopy(org[prop]);
  return result;
}

if (typeof gEmailWizardLogger == "undefined") {
  Cu.import("resource:///modules/gloda/log4moz.js");
  var gEmailWizardLogger = Log4Moz.getConfiguredLogger("mail.wizard");
}
function ddump(text)
{
  gEmailWizardLogger.info(text);
}

function debugObject(obj, name, maxDepth, curDepth)
{
  if (curDepth == undefined)
    curDepth = 0;
  if (maxDepth != undefined && curDepth > maxDepth)
    return "";

  var result = "";
  var i = 0;
  for (let prop in obj)
  {
    i++;
    try {
      if (typeof(obj[prop]) == "object")
      {
        if (obj[prop] && obj[prop].length != undefined)
          result += name + "." + prop + "=[probably array, length " +
                obj[prop].length + "]\n";
        else
          result += name + "." + prop + "=[" + typeof(obj[prop]) + "]\n";
        result += debugObject(obj[prop], name + "." + prop,
                              maxDepth, curDepth + 1);
      }
      else if (typeof(obj[prop]) == "function")
        result += name + "." + prop + "=[function]\n";
      else
        result += name + "." + prop + "=" + obj[prop] + "\n";
    } catch (e) {
      result += name + "." + prop + "-> Exception(" + e + ")\n";
    }
  }
  if (!i)
    result += name + " is empty\n";
  return result;
}

function alertPrompt(alertTitle, alertMsg)
{
  Services.prompt.alert(window, alertTitle, alertMsg);
}