~ubuntu-branches/ubuntu/oneiric/thunderbird/oneiric-updates

« back to all changes in this revision

Viewing changes to debian/eds/modules/AuthHelper.jsm

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2011-08-09 19:28:44 UTC
  • mfrom: (1.6.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110809192844-tvmhdsvt1hirk9s8
Tags: 6.0~b3+build1+nobinonly-0ubuntu1
* New upstream release from the beta channel (THUNDERBIRD_6_0b3_BUILD1)

* Update globalmenu-extension to 1.9.1
  - Drop Firefox 4 and 5 compatibility
  - Drop the uIGlobalMenuLoader interface, as it never served any purpose
  - Rework how we synchronize attributes to menuitems from their
    corresponding command nodes
  - Don't synchronize attributes from command nodes associated with menus
  - Rework how we handle document insertion/removals. Rather than keeping
    our dbusmenu structure in sync at all times, and routing the events
    to the correct node in the tree, we just mark the menu as invalid and
    rebuild it from scratch next time it opens. This should reduce problems
    like LP: #821391
  - Honour the collapsed attribute. This solves a problem with multiple
    seprators appearing adjacent to each other in the greasemonkey menu
  - Store all booleans as PRPackedBool rather than PRBool
  - Add error checking around uGlobalMenuDocListener
  - Make uGlobalMenuDummy more robust, and use it as a fallback if the
    real menuitem fails to initialize. This should help reduce problems
    like LP: #831391
  - If a menu fails to build correctly, mark it invalid and stop processing
    document events on it (which should avoid the crash in LP: #831391)
  - Invalidate a menu if we fail to insert/remove a node whilst processing
    a document event (which should help avoid the crash in LP: #831391)
  - Make uGlobalMenu::CanOpen() respect the collapsed attribute
  - Allow more than one menu node to register as a listener for any DOM
    node. In the case of command nodes, these may be shared across multiple
    menu nodes, with each one interested in receiving events. Previously, we
    just erased the first listener if a second menu node tried to register
    (discovered after adding error checking around uGlobalMenuDocListener)
* Update messagingmenu-extension to r66
  - add an inbox-only mode
* Refresh shipped locales for new release
* Ship the eds contacts integration extension, based on r80
  - add debian/eds/*
  - update debian/rules
  - update debian/thunderbird.desktop.in
  - update debian/thunderbird.dirs.in
  - update debian/thunderbird.install.in
  - update debian/control
* Move the Unity depends to thunderbird-gnome-support, and make sure we only
  add them for oneiric builds
  - update debian/control
  - update debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 *       Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Mozilla Public License Version
 
6
 * 1.1 (the "License"); you may not use this file except in compliance with
 
7
 * the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/MPL/
 
9
 * 
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is edsintegration.
 
16
 *
 
17
 * The Initial Developer of the Original Code is
 
18
 * Mozilla Corp.
 
19
 * Portions created by the Initial Developer are Copyright (C) 2011
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 * Mike Conley <mconley@mozilla.com>
 
24
 *
 
25
 * Alternatively, the contents of this file may be used under the terms of
 
26
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
27
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
28
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
29
 * of those above. If you wish to allow use of your version of this file only
 
30
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
31
 * use your version of this file under the terms of the MPL, indicate your
 
32
 * decision by deleting the provisions above and replace them with the notice
 
33
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
34
 * the provisions above, a recipient may use your version of this file under
 
35
 * the terms of any one of the MPL, the GPL or the LGPL.
 
36
 * 
 
37
 * ***** END LICENSE BLOCK ***** */
 
38
 
 
39
var EXPORTED_SYMBOLS = [ "AuthHelper" ];
 
40
 
 
41
 
 
42
const Cu = Components.utils;
 
43
const Cc = Components.classes;
 
44
const Ci = Components.interfaces;
 
45
 
 
46
Cu.import("resource://gre/modules/ctypes.jsm");
 
47
Cu.import("resource://gre/modules/Services.jsm");
 
48
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
49
 
 
50
Cu.import("resource://edsintegration/libedataserver-ctypes.jsm");
 
51
Cu.import("resource://edsintegration/LibGLib.jsm");
 
52
Cu.import("resource://edsintegration/nsAbEDSCommon.jsm");
 
53
Cu.import("resource://edsintegration/LibEBookClient.jsm");
 
54
Cu.import("resource://edsintegration/LibESource.jsm");
 
55
Cu.import("resource://edsintegration/LibGCancellable.jsm");
 
56
Cu.import("resource://edsintegration/ReferenceService.jsm");
 
57
Cu.import("resource://edsintegration/LibGAsyncResult.jsm");
 
58
Cu.import("resource://edsintegration/LibEClient.jsm");
 
59
Cu.import("resource://edsintegration/LibECredentials.jsm");
 
60
 
 
61
var gAuthLookup = {};
 
62
var gAuthAnchors = {};
 
63
 
 
64
 
 
65
function openNewAsyncCb(aGObject, aAsyncResult, aData) {
 
66
  LOG("Entered openNewAsyncCb");
 
67
  if (!aData || aData.isNull()) {
 
68
    ERROR("Could not open EClient - aData was null is openNewAsyncCb");
 
69
    return;
 
70
  }
 
71
 
 
72
  try {
 
73
    var opData = AuthHelper.getOpData(aData);
 
74
  } catch(e) {
 
75
    LOG("Could not get opData (openNewAsyncCb) - this is fine if the"
 
76
        + " EBookClient does not require authentication.");
 
77
    return;
 
78
  }
 
79
 
 
80
  opData.openFinished = true;
 
81
 
 
82
  let client = ctypes.cast(aGObject, LibEClient.EClient.ptr);
 
83
  let errPtr = new LibGLib.GError.ptr();
 
84
 
 
85
  if (!LibEClient.openFinish(client, aAsyncResult, errPtr.address()
 
86
      || LibGCancellable.setErrorIfCancelled(opData.cancellable,
 
87
                                             errPtr.address()))) {
 
88
    LOG("Calling finishOrRetryOpen from openNewAsyncCb");
 
89
    AuthHelper.finishOrRetryOpen(opData, errPtr);
 
90
    LibGLib.g_error_free(errPtr);
 
91
    errPtr = null;
 
92
    return;
 
93
  }
 
94
 
 
95
  if (opData.openedCbError) {
 
96
    AuthHelper.finishOrRetryOpen(opData, opData.openedCbError);
 
97
    return;
 
98
  }
 
99
 
 
100
  if (LibEClient.isOpened(client)) {
 
101
    LOG("Huzzah!  Apparently an EClient has been opened (uri: " + opData.asyncCbData + ")");
 
102
    AuthHelper.openNewDone(opData);
 
103
    return;
 
104
  }
 
105
 
 
106
  opData.refs['openNewCancelledCbPtr'] = LibGLib
 
107
                                         .GCallback(AuthHelper
 
108
                                                    .openNewCancelledCb);
 
109
 
 
110
  opData.refs.signal_connect(opData.cancellable, "cancelled", opData.refs['openNewCancelledCbPtr'],
 
111
                             opData.uriPtr);
 
112
  return;
 
113
}
 
114
 
 
115
var openNewAsyncCbPtr = LibGAsyncResult.GAsyncReadyCallback(openNewAsyncCb);
 
116
 
 
117
var AuthHelper = {
 
118
  ADDRESSBOOK: "addressbook",
 
119
 
 
120
  newClient: function AH_newClient(aESource, aClientType, aErrPtr) {
 
121
    if (aClientType == AuthHelper.ADDRESSBOOK) {
 
122
      return LibEBookClient.newFromSource(aESource, aErrPtr);
 
123
    }
 
124
    return null;
 
125
  },
 
126
 
 
127
  openAndAuthESource: function AH_openAndAuthESource(aESource, aType,
 
128
                                                     aOnlyIfExists,
 
129
                                                     aCancellable,
 
130
                                                     aAuthHandler,
 
131
                                                     aAuthHandlerData,
 
132
                                                     aAsyncCb,
 
133
                                                     aAsyncCbData,
 
134
                                                     aURI) {
 
135
    if (gAuthLookup[aURI]) {
 
136
      WARN("There's already an auth helper trying to open an EClient with"
 
137
           + " URI: " + aURI + " - cancelling this attempt.");
 
138
      return false;
 
139
    }
 
140
 
 
141
    if (!aESource || aESource.isNull()) {
 
142
      ERROR("Tried to openAndAuth an ESource that was null!");
 
143
      return false;
 
144
    }
 
145
 
 
146
    let errPtr = new LibGLib.GError.ptr();
 
147
    let client = AuthHelper.newClient(aESource, aType, errPtr.address());
 
148
    if (!errPtr.isNull()) {
 
149
      ERROR("Could not create a client of type " + aType + " from ESource.");
 
150
      ERROR("Message was: " + errPtr.contents.message.readString());
 
151
      return false;
 
152
    }
 
153
 
 
154
    let opData = new AsyncOpData();
 
155
    LOG("Registering some opData at uri: " + aURI);
 
156
    gAuthLookup[aURI] = opData;
 
157
 
 
158
    let data = LibGLib.g_object_ref(aESource);
 
159
    opData.uriPtr = LibGLib.gchar.array()(aURI);
 
160
    opData.source = ctypes.cast(data, LibESource.ESource.ptr);
 
161
    opData.client = client;
 
162
    opData.openFinished = false;
 
163
    opData.retryOpenId = 0;
 
164
    opData.authHandler = aAuthHandler;
 
165
    opData.authHandlerData = aAuthHandlerData;
 
166
    opData.asyncCb = aAsyncCb;
 
167
 
 
168
    opData.asyncCbData = aAsyncCbData;
 
169
 
 
170
    if (aCancellable && !aCancellable.isNull())
 
171
      opData.cancellable = aCancellable;
 
172
    else
 
173
      opData.cancellable = LibGCancellable.newGCancellable();
 
174
 
 
175
    opData.onlyIfExists = aOnlyIfExists;
 
176
    opData.refs = ReferenceService.register("auth:" + aURI); 
 
177
 
 
178
    // Register the authentication callback if one exists
 
179
    if (aAuthHandler) {
 
180
      opData.refs['openNewAuthCbPtr'] = LibGLib
 
181
                                        .GBooleanCallback(AuthHelper
 
182
                                                          .openNewAuthCb);
 
183
      opData.refs.signal_connect(client, "authenticate", opData.refs['openNewAuthCbPtr'],
 
184
                                 opData.uriPtr);
 
185
    }
 
186
 
 
187
    opData.refs['openedCbPtr'] = LibGLib.GCallback(AuthHelper.openedCb);
 
188
    
 
189
    opData.refs.signal_connect(client, "opened", opData.refs['openedCbPtr'],
 
190
                               opData.uriPtr);
 
191
    let eclient = ctypes.cast(client, LibEClient.EClient.ptr);
 
192
    LibEClient.open(eclient, aOnlyIfExists, aCancellable,
 
193
                    openNewAsyncCbPtr, opData.uriPtr);
 
194
 
 
195
  },
 
196
 
 
197
  openedCb: function AH_openedCb(aEClient, aGError, aData) {
 
198
    LOG("Entered openedCb");
 
199
    if (!aEClient || aEClient.isNull()) {
 
200
      ERROR("In openedCb and aEClient is null");
 
201
      return;
 
202
    }
 
203
 
 
204
    try {
 
205
      var opData = AuthHelper.getOpData(aData);
 
206
    } catch(e) {
 
207
      ERROR("Could not complete openedCb:", e);
 
208
      return;
 
209
    }
 
210
 
 
211
    if (!opData.openFinished) {
 
212
      if (!aGError.isNull()) {
 
213
        aGError = ctypes.cast(aGError, LibGLib.GError.ptr);
 
214
        opData.openedCbError = LibGLib.g_error_copy(aGError);
 
215
      }
 
216
    } else { 
 
217
      LOG("Calling finishOrRetryOpen from openedCb");
 
218
      AuthHelper.finishOrRetryOpen(opData, aGError);
 
219
    }
 
220
    LOG("OpenedCb exited");
 
221
    return;
 
222
  },
 
223
 
 
224
 
 
225
  openNewCancelledCb: function AH_openNewCancelledCb(arg1, arg2, arg3) {
 
226
    return;
 
227
  },
 
228
 
 
229
  openNewAuthCb: function AH_openNewAuthCb(aEClient, aECredentials, aData) {
 
230
    LOG("Within openNewAuthCb");
 
231
    if (!aEClient || aEClient.isNull()) {
 
232
      ERROR("The EClient passed to openNewAuthCb was null.");
 
233
      return LibGLib.FALSE;
 
234
    }
 
235
 
 
236
    if (!aECredentials || aECredentials.isNull()) {
 
237
      ERROR("The ECredentials passed to openNewAuthCb was null.");
 
238
      return LibGLib.FALSE;
 
239
    }
 
240
 
 
241
    try {
 
242
      var opData = AuthHelper.getOpData(aData);
 
243
    } catch(e) {
 
244
      ERROR("Could not retrieve opData (openNewAuthCb): " + e);
 
245
      return LibGLib.FALSE;
 
246
    }
 
247
 
 
248
    if (!opData.authHandler) {
 
249
      ERROR("There was no authHandler for EClient");
 
250
      return LibGLib.FALSE;
 
251
    }
 
252
 
 
253
    aECredentials = ctypes.cast(aECredentials, LibECredentials.ECredentials.ptr);
 
254
 
 
255
    if (opData.usedCreds) {
 
256
      let reason = LibECredentials.peek(opData.usedCreds,
 
257
                                        LibECredentials.E_CREDENTIALS_KEY_PROMPT_REASON);
 
258
      if (reason) {
 
259
        LibECredentials.set(aECredentials, LibECredentials.E_CREDENTIALS_KEY_PROMPT_TEXT, null);
 
260
        LibECredentials.set(aECredentials, LibECredentials.E_CREDENTIALS_KEY_PROMPT_REASON, reason);
 
261
      }
 
262
    }
 
263
 
 
264
    aEClient = ctypes.cast(aEClient, LibEClient.EClient.ptr);
 
265
 
 
266
    let handled = opData.authHandler(aEClient, aECredentials, opData.authHandlerData);
 
267
 
 
268
    if (handled == LibGLib.TRUE) {
 
269
      if (opData.usedCreds) {
 
270
        LibECredentials.free(opData.usedCreds);
 
271
        opData.usedCreds = null;
 
272
      }
 
273
      opData.usedCreds = LibECredentials.newClone(aECredentials);
 
274
    }
 
275
 
 
276
    return handled;
 
277
  },
 
278
 
 
279
  finishOrRetryOpen: function AH_finishOrRetryOpen(aOpData, aErrPtr) {
 
280
    LOG("Entered finishOrRetryOpen");
 
281
    aErrPtr = ctypes.cast(aErrPtr, LibGLib.GError.ptr);
 
282
 
 
283
    if (aOpData.authHandler && !aErrPtr.isNull() &&
 
284
        LibGLib.g_error_matches(aErrPtr, LibEClient.errorQuark(),
 
285
                                LibEClient.getEnum("E_CLIENT_ERROR_AUTHENTICATION_FAILED"))) {
 
286
      if (aOpData.usedCreds && !aOpData.usedCreds.isNull()) {
 
287
        // TODO: Password remembering? Forgetting?
 
288
        LibECredentials.set(aOpData.usedCreds,
 
289
                            LibECredentials.E_CREDENTIALS_KEY_PROMPT_FLAGS,
 
290
                            LibECredentials.E_CREDENTIALS_USED);
 
291
        LibECredentials.set(aOpData.usedCreds,
 
292
                            LibECredentials.E_CREDENTIALS_KEY_PROMPT_REASON,
 
293
                            aErrPtr.contents.message.readString());
 
294
        LOG("Old credentials have been used.");
 
295
      }
 
296
      let eclient = ctypes.cast(aOpData.client, LibEClient.EClient.ptr);
 
297
      LOG("Calling LibEClient.processAuth");
 
298
      LibEClient.processAuth(eclient, aOpData.usedCreds);
 
299
 
 
300
    } else if (!aErrPtr.isNull()) {
 
301
      LOG("Calling asyncCb");
 
302
      aOpData.asyncCb(aOpData.client, aErrPtr, aOpData.asyncCbData);
 
303
      AuthHelper.freeOpData(aOpData);
 
304
    } else {
 
305
      LOG("Calling openNewDone");
 
306
      AuthHelper.openNewDone(aOpData);
 
307
    }
 
308
  },
 
309
 
 
310
  openNewDone: function AH_openNewDone(aOpData) {
 
311
    if (!aOpData.asyncCb) {
 
312
      ERROR("Entered openNewDone, but opData.asyncCb was null!");
 
313
      return;
 
314
    }
 
315
 
 
316
    // The callback should probably reconnect auth handler
 
317
    // directly.
 
318
    aOpData.asyncCb(aOpData.client, aOpData.openedCbError, aOpData.asyncCbData);
 
319
    AuthHelper.freeOpData(aOpData);
 
320
  },
 
321
 
 
322
  getOpData: function AH_getOpData(aData) {
 
323
    if (!aData || aData.isNull())
 
324
      throw("aData was null in getOpData");
 
325
 
 
326
    let uri = ctypes.cast(aData, LibGLib.gchar.ptr).readString();
 
327
 
 
328
    if (!gAuthLookup[uri])
 
329
      throw("There was no opData in gAuthLookup for URI: " + uri);
 
330
 
 
331
    return gAuthLookup[uri];
 
332
  },
 
333
 
 
334
  freeOpData: function AH_freeOpData(aOpData) {
 
335
    if (!aOpData) {
 
336
      WARN("Could not free opData, since it was null.");
 
337
      return;
 
338
    }
 
339
 
 
340
    if (!aOpData.client || aOpData.client.isNull()) {
 
341
      WARN("Could not free opData, since it didn't have a client.");
 
342
      return;
 
343
    }
 
344
 
 
345
    if (!aOpData.cancellable || aOpData.cancellable.isNull()) {
 
346
      WARN("Could not free opData, since it didn't have a cancellable.");
 
347
      return;
 
348
    }
 
349
 
 
350
    // Free signal handlers;
 
351
    LOG("Freeing signal handlers");
 
352
    aOpData.refs.dispose();
 
353
    LOG("Signal handlers free'd for uri:" + aOpData.uriPtr.readString());
 
354
 
 
355
    if (aOpData.usedCreds) {
 
356
      LibECredentials.free(aOpData.usedCreds);
 
357
      aOpData.usedCreds = null;
 
358
    }
 
359
    if (aOpData.openError) {
 
360
      LibGLib.g_error_free(aOpData.openError);
 
361
      aOpData.openError = null;
 
362
    }
 
363
    LibGLib.g_object_unref(aOpData.cancellable);
 
364
    LibGLib.g_object_unref(aOpData.client);
 
365
    LibGLib.g_object_unref(aOpData.source);
 
366
 
 
367
    let uri = aOpData.uriPtr.readString();
 
368
 
 
369
    gAuthLookup[uri] = null;
 
370
    delete opData;    
 
371
  }
 
372
}
 
373
 
 
374
var AsyncOpData = function() {
 
375
  this.uriPtr = null;
 
376
  this.authHandler = null;
 
377
  this.authHandlerData = null;
 
378
  this.client = null;
 
379
  this.source = null;
 
380
  this.creds = null;
 
381
  this.usedCreds = null;
 
382
  this.asyncCb = null;
 
383
  this.asyncCbData = null;
 
384
  this.cancellable = null;
 
385
  this.openFinished = false;
 
386
  this.openError = null;
 
387
  this.onlyIfExists = false;
 
388
  this.retryOpenId = null;
 
389
  this.openedCbError = null;
 
390
}