1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file contains the zimbra account class. 27 */ 28 29 /** 30 * Creates an account object containing meta info about the account. 31 * @class 32 * This class represents an account. This object is created primarily if a user has added sub-accounts 33 * to manage (i.e. a family mailbox). 34 * 35 * @author Parag Shah 36 * 37 * @param {String} id the unique ID for this account 38 * @param {String} name the email address 39 * @param {Boolean} visible if <code>true</code>, make this account available in the overview (i.e. child accounts) 40 * 41 * @extends ZmAccount 42 */ 43 ZmZimbraAccount = function(id, name, visible) { 44 45 ZmAccount.call(this, null, id, name); 46 47 this.visible = (visible !== false); 48 /** 49 * The account settings. 50 * @type ZmSettings 51 */ 52 this.settings = null; 53 this.trees = {}; 54 this.loaded = false; 55 /** 56 * The account Access Control List. 57 * @type ZmAccessControlList 58 */ 59 this.acl = new ZmAccessControlList(); 60 this.metaData = new ZmMetaData(this); 61 }; 62 63 ZmZimbraAccount.prototype = new ZmAccount; 64 ZmZimbraAccount.prototype.constructor = ZmZimbraAccount; 65 66 ZmZimbraAccount.prototype.isZmZimbraAccount = true; 67 ZmZimbraAccount.prototype.toString = function() { return "ZmZimbraAccount"; }; 68 69 70 // 71 // Constants 72 // 73 74 /** 75 * Defines the "unknown" status. 76 */ 77 ZmZimbraAccount.STATUS_UNKNOWN = "unknown"; 78 /** 79 * Defines the "offline" status. 80 */ 81 ZmZimbraAccount.STATUS_OFFLINE = "offline"; 82 /** 83 * Defines the "online" status. 84 */ 85 ZmZimbraAccount.STATUS_ONLINE = "online"; 86 /** 87 * Defines the "running" status. 88 */ 89 ZmZimbraAccount.STATUS_RUNNING = "running"; 90 /** 91 * Defines the "authentication fail" status. 92 */ 93 ZmZimbraAccount.STATUS_AUTHFAIL = "authfail"; 94 /** 95 * Defines the "error" status. 96 */ 97 ZmZimbraAccount.STATUS_ERROR = "error"; 98 99 // 100 // Public methods 101 // 102 103 /** 104 * Sets the name of the account. 105 * 106 * @param {String} name the account name 107 */ 108 ZmZimbraAccount.prototype.setName = 109 function(name) { 110 var identity = this.getIdentity(); 111 // TODO: If no identity and name is set, should create one! 112 if (!identity) return; 113 identity.name = name; 114 }; 115 116 /** 117 * Gets the name of the account. 118 * 119 * @return {String} the account name 120 */ 121 ZmZimbraAccount.prototype.getName = 122 function() { 123 var identity = this.getIdentity(); 124 var name = (!identity) 125 ? this.settings.get(ZmSetting.DISPLAY_NAME) 126 : identity.name; 127 128 if (!name) { 129 name = this.getDisplayName(); 130 } 131 return identity.isDefault && name == ZmIdentity.DEFAULT_NAME ? ZmMsg.accountDefault : name; 132 }; 133 134 /** 135 * Sets the email address for this account. This method does nothing. The email address is set 136 * when the object is created. 137 * 138 * @param {String} email the email address (ignored) 139 */ 140 ZmZimbraAccount.prototype.setEmail = 141 function(email) {}; // IGNORE 142 143 /** 144 * Gets the email address for this account. 145 * 146 * @return {String} the email address 147 */ 148 ZmZimbraAccount.prototype.getEmail = 149 function() { 150 return this.name; 151 }; 152 153 /** 154 * Gets the display name. 155 * 156 * @return {String} the display name 157 */ 158 ZmZimbraAccount.prototype.getDisplayName = 159 function() { 160 if (!this.displayName) { 161 var dispName = this.isMain 162 ? this.settings.get(ZmSetting.DISPLAY_NAME) 163 : this._displayName; 164 this.displayName = (this._accountName || dispName || this.name); 165 } 166 return this.displayName; 167 }; 168 169 /** 170 * Gets the identity. 171 * 172 * @return {ZmIdentity} the identity 173 */ 174 ZmZimbraAccount.prototype.getIdentity = 175 function() { 176 var defaultIdentity = appCtxt.getIdentityCollection(this).defaultIdentity; 177 if (!appCtxt.isFamilyMbox || this.isMain) { 178 return defaultIdentity; 179 } 180 181 // for family mbox, create dummy identities for child accounts 182 if (!this.dummyIdentity) { 183 this.dummyIdentity = new ZmIdentity(this.name); 184 AjxUtil.hashUpdate(this.dummyIdentity, defaultIdentity, true, ["name","isDefault"]); 185 } 186 return this.dummyIdentity; 187 }; 188 189 /** 190 * Gets the tool tip. 191 * 192 * @return {String} the tool tip 193 */ 194 ZmZimbraAccount.prototype.getToolTip = 195 function() { 196 if (this.status || this.lastSync || this.isMain) { 197 var lastSyncDate = (this.lastSync && this.lastSync != 0) 198 ? (new Date(parseInt(this.lastSync))) : null; 199 200 var quota = appCtxt.get(ZmSetting.QUOTA_USED, null, this); 201 var lastSync; 202 if (!lastSyncDate) { 203 // this means, we've synced but server lost the last sync timestamp 204 if (quota > 0 && !this.isMain) { 205 lastSync = ZmMsg.unknown; 206 } 207 } else { 208 lastSync = AjxDateUtil.computeWordyDateStr(new Date(), lastSyncDate); 209 } 210 211 var params = { 212 lastSync: lastSync, 213 hasNotSynced: this.hasNotSynced(), 214 status: this.getStatusMessage(), 215 quota: AjxUtil.formatSize(quota, false, 1) 216 }; 217 218 return AjxTemplate.expand("share.App#ZimbraAccountTooltip", params); 219 } 220 return ""; 221 }; 222 223 /** 224 * Gets the default color. 225 * 226 * @return {String} the default color 227 * @see ZmOrganizer 228 */ 229 ZmZimbraAccount.prototype.getDefaultColor = 230 function() { 231 if (this.isMain) { 232 return ZmOrganizer.C_GRAY; 233 } 234 235 switch (this.type) { 236 case ZmAccount.TYPE_GMAIL: return ZmOrganizer.C_RED; 237 case ZmAccount.TYPE_MSE: return ZmOrganizer.C_GREEN; 238 case ZmAccount.TYPE_EXCHANGE: return ZmOrganizer.C_GREEN; 239 case ZmAccount.TYPE_YMP: return ZmOrganizer.C_PURPLE; 240 } 241 242 return null; 243 }; 244 245 /** 246 * Checks if the account has sync'd. 247 * 248 * @return {Boolean} if <code>true</code>, this account has never been sync'd 249 */ 250 ZmZimbraAccount.prototype.hasNotSynced = 251 function() { 252 return (this.isOfflineInitialSync() && 253 this.status == ZmZimbraAccount.STATUS_UNKNOWN && 254 appCtxt.get(ZmSetting.QUOTA_USED, null, this) == 0); 255 }; 256 257 /** 258 * Check is this account is currently sync'ing for the first time. 259 * 260 * @return {Boolean} if <code>true</code>, this account is currently sync'ing for the first time 261 */ 262 ZmZimbraAccount.prototype.isOfflineInitialSync = 263 function() { 264 return (appCtxt.isOffline && (!this.lastSync || (this.lastSync && this.lastSync == 0))); 265 }; 266 267 /** 268 * Checks if this account is CalDAV based. 269 * 270 * @return {Boolean} if <code>true</code>, account is CalDAV based 271 */ 272 ZmZimbraAccount.prototype.isCalDavBased = 273 function() { 274 return (this.type == ZmAccount.TYPE_GMAIL || 275 this.type == ZmAccount.TYPE_YMP); 276 }; 277 278 /** 279 * Gets the default calendar. For CalDAV based accounts, the default calendar is hidden; 280 * therefore, this method returns the first non-default calendar. 281 * 282 * @return {Object} the calendar 283 * @see ZmZimbraAccount.isCalDavBased 284 */ 285 ZmZimbraAccount.prototype.getDefaultCalendar = 286 function() { 287 var tree = appCtxt.getFolderTree(this); 288 if (this.isCalDavBased()) { 289 var calendars = tree.getByType(ZmOrganizer.CALENDAR); 290 for (var i = 0; i < calendars.length; i++) { 291 if (calendars[i].nId == ZmOrganizer.ID_CALENDAR) { continue; } 292 return calendars[i]; 293 } 294 } 295 return tree.getById(ZmOrganizer.ID_CALENDAR); 296 }; 297 298 /** 299 * Updates the account status. 300 * 301 * @private 302 */ 303 ZmZimbraAccount.prototype.updateState = 304 function(acctInfo) { 305 if (this.isMain) { return; } // main account doesn't sync 306 307 // update last sync timestamp 308 var updateTooltip = false; 309 if (this.lastSync != acctInfo.lastsync) { 310 this.lastSync = acctInfo.lastsync; 311 if (this.visible) { 312 updateTooltip = true; 313 } 314 } 315 316 // set to update account (offline) status if changed 317 var updateStatus = false; 318 if (this.status != acctInfo.status) { 319 this.status = acctInfo.status; 320 if (this.visible) { 321 updateStatus = true; 322 } 323 } 324 325 // for all overview containers, update status/tooltip 326 var container = appCtxt.getOverviewController()._overviewContainer; 327 for (var i in container) { 328 var c = container[i]; 329 if (updateStatus || updateTooltip) { 330 c.updateAccountInfo(this, updateStatus, updateTooltip); 331 } 332 } 333 334 if (this.visible && acctInfo.unread != this.unread) { 335 this.unread = acctInfo.unread; 336 } 337 338 this.code = acctInfo.code; 339 if (acctInfo.error) { 340 var error = acctInfo.error[0]; 341 this.errorDetail = error.exception[0]._content; 342 this.errorMessage = error.message; 343 } 344 }; 345 346 /** 347 * Gets the status icon. 348 * 349 * @return {String} the status icon 350 */ 351 ZmZimbraAccount.prototype.getStatusIcon = 352 function() { 353 if (this.inNewMailMode) { 354 return "NewMailAlert"; 355 } 356 357 switch (this.status) { 358 // case ZmZimbraAccount.STATUS_UNKNOWN: return "Offline"; // bug: 42403 - remove 359 case ZmZimbraAccount.STATUS_OFFLINE: return "ImAway"; 360 // case ZmZimbraAccount.STATUS_ONLINE: return ""; // no icon for "online" 361 // case ZmZimbraAccount.STATUS_RUNNING: // animated, so cannot be set using AjxImg 362 case ZmZimbraAccount.STATUS_AUTHFAIL: return "ImDnd"; 363 case ZmZimbraAccount.STATUS_ERROR: return "Critical"; 364 } 365 return null; 366 }; 367 368 /** 369 * Checks if this account is in error status. 370 * 371 * @return {Boolean} if <code>true</code>, the account is in error status 372 */ 373 ZmZimbraAccount.prototype.isError = 374 function() { 375 return (this.status == ZmZimbraAccount.STATUS_AUTHFAIL || 376 this.status == ZmZimbraAccount.STATUS_ERROR); 377 }; 378 379 /** 380 * Gets the icon. 381 * 382 * @return {String} the icon 383 */ 384 ZmZimbraAccount.prototype.getIcon = 385 function() { 386 return (this.isMain && appCtxt.isOffline) ? "LocalFolders" : this.icon; 387 }; 388 389 /** 390 * Gets the Zd message. 391 * 392 * @private 393 */ 394 ZmZimbraAccount.prototype.getZdMsg = 395 function(code) { 396 var msg = ((ZdMsg["client." + code]) || (ZdMsg["exception." + code])); 397 if (!msg && code) { 398 msg = ZdMsg["exception.offline.UNEXPECTED"]; 399 } 400 return msg; 401 }; 402 403 /** 404 * Gets the status message. 405 * 406 * @return {String} the status message 407 */ 408 ZmZimbraAccount.prototype.getStatusMessage = 409 function() { 410 if (this.inNewMailMode) { 411 return AjxMessageFormat.format(ZmMsg.unreadCount, this.unread); 412 } 413 414 switch (this.status) { 415 // case ZmZimbraAccount.STATUS_UNKNOWN: return ZmMsg.unknown; 416 case ZmZimbraAccount.STATUS_OFFLINE: return ZmMsg.netStatusOffline; 417 case ZmZimbraAccount.STATUS_ONLINE: return ZmMsg.netStatusOnline; 418 case ZmZimbraAccount.STATUS_RUNNING: return ZmMsg.running; 419 case ZmZimbraAccount.STATUS_AUTHFAIL: return this.code ? this.getZdMsg(this.code) : AjxMessageFormat.format(ZmMsg.authFailure, this.getEmail()); 420 case ZmZimbraAccount.STATUS_ERROR: return this.code ? this.getZdMsg(this.code) : ZmMsg.error; 421 } 422 return ""; 423 }; 424 425 /** 426 * Shows an error message. 427 * 428 * Offline use only. 429 * 430 * @private 431 */ 432 ZmZimbraAccount.prototype.showErrorMessage = 433 function() { 434 if (!this.isError()) { return; } 435 436 var dialog = (this.status == ZmZimbraAccount.STATUS_ERROR) 437 ? appCtxt.getErrorDialog() : appCtxt.getMsgDialog(); 438 439 // short message 440 var msg = this.getZdMsg(this.code); 441 if (msg == "") { 442 msg = this.getStatusMessage(); 443 } 444 dialog.setMessage(msg); 445 446 if (this.status == ZmZimbraAccount.STATUS_ERROR) { 447 // detailed message 448 var html = []; 449 var i = 0; 450 if (this.errorMessage) { 451 html[i++] = "<p><b>"; 452 html[i++] = ZdMsg.DebugMsg; 453 html[i++] = "</b>: "; 454 html[i++] = this.errorMessage; 455 html[i++] = "</p>"; 456 } 457 458 if (this.errorDetail) { 459 html[i++] = "<p><b>"; 460 html[i++] = ZdMsg.DebugStack; 461 html[i++] = "</b>:</p><p><pre>"; 462 html[i++] = this.errorDetail; 463 html[i++] = "</pre></p>"; 464 } 465 466 html[i++] = "<p><b>"; 467 html[i++] = ZdMsg.DebugActionNote; 468 html[i++] = "</b></p>"; 469 470 dialog.setDetailString(html.join("")); 471 } 472 473 dialog.popup(null, true); 474 }; 475 476 /** 477 * @private 478 */ 479 ZmZimbraAccount.createFromDom = 480 function(node) { 481 var acct = new ZmZimbraAccount(); 482 acct._loadFromDom(node); 483 return acct; 484 }; 485 486 /** 487 * Loads the account. 488 * 489 * @param {AjxCallback} callback the callback 490 */ 491 ZmZimbraAccount.prototype.load = 492 function(callback) { 493 if (!this.loaded) { 494 // create new ZmSetting for this account 495 this.settings = new ZmSettings(); 496 497 // check "{APP}_ENABLED" state against main account's settings 498 var mainAcct = appCtxt.accountList.mainAccount; 499 500 // for all *loaded* apps, add their app-specific settings 501 for (var i = 0; i < ZmApp.APPS.length; i++) { 502 var appName = ZmApp.APPS[i]; 503 var setting = ZmApp.SETTING[appName]; 504 if (setting && appCtxt.get(setting, null, mainAcct)) { 505 var app = appCtxt.getApp(appName); 506 if (app) { 507 app._registerSettings(this.settings); 508 } 509 } 510 } 511 512 var command = new ZmBatchCommand(null, this.name); 513 514 // load user settings retrieved from server now 515 var loadCallback = new AjxCallback(this, this._handleLoadSettings); 516 this.settings.loadUserSettings(loadCallback, null, this.name, null, command); 517 518 // get tag info for this account *FIRST* - otherwise, root ID get overridden 519 var tagDoc = AjxSoapDoc.create("GetTagRequest", "urn:zimbraMail"); 520 var tagCallback = new AjxCallback(this, this._handleLoadTags); 521 command.addNewRequestParams(tagDoc, tagCallback); 522 523 // get meta data for this account 524 this.loadMetaData(null, command); 525 526 // get folder info for this account 527 var folderDoc = AjxSoapDoc.create("GetFolderRequest", "urn:zimbraMail"); 528 folderDoc.getMethod().setAttribute("visible", "1"); 529 var folderCallback = new AjxCallback(this, this._handleLoadFolders); 530 command.addNewRequestParams(folderDoc, folderCallback); 531 532 var respCallback = new AjxCallback(this, this._handleLoadUserInfo, callback); 533 var errCallback = new AjxCallback(this, this._handleErrorLoad, callback); 534 command.run(respCallback, errCallback); 535 } 536 else if (callback) { 537 callback.run(); 538 } 539 }; 540 541 ZmZimbraAccount.prototype.loadMetaData = 542 function(callback, batchCommand) { 543 var metaDataCallback = new AjxCallback(this, this._handleLoadMetaData, [callback]); 544 var sections = [ZmSetting.M_IMPLICIT, ZmSetting.M_OFFLINE]; 545 this.metaData.load(sections, metaDataCallback, batchCommand); 546 }; 547 548 /** 549 * Unloads the account and removes any account-specific data stored globally. 550 * 551 */ 552 ZmZimbraAccount.prototype.unload = 553 function() { 554 if (!appCtxt.inStartup) { 555 // unset account-specific shortcuts 556 this.settings.loadShortcuts(true); 557 } 558 }; 559 560 /** 561 * Sync the account. 562 * 563 * @param {AjxCallback} callback the callback 564 */ 565 ZmZimbraAccount.prototype.sync = 566 function(callback) { 567 var soapDoc = AjxSoapDoc.create("SyncRequest", "urn:zimbraOffline"); 568 if (appCtxt.get(ZmSetting.OFFLINE_DEBUG_TRACE)) { 569 var method = soapDoc.getMethod(); 570 method.setAttribute("debug", 1); 571 } 572 appCtxt.getAppController().sendRequest({ 573 soapDoc:soapDoc, 574 asyncMode:true, 575 noBusyOverlay:true, 576 callback:callback, 577 accountName:this.name 578 }); 579 }; 580 581 /** 582 * Saves the account. 583 * 584 * @param {AjxCallback} callback the callback 585 * @param {AjxCallback} errorCallback the error callback 586 * @param {Object} batchCmd the batch command 587 */ 588 ZmZimbraAccount.prototype.save = 589 function(callback, errorCallback, batchCmd) { 590 return (this.getIdentity().save(callback, errorCallback, batchCmd)); 591 }; 592 593 /** 594 * Saves implicit prefs. Because it's done onunload, the save is sync. 595 * 596 * @private 597 */ 598 ZmZimbraAccount.prototype.saveImplicitPrefs = 599 function() { 600 var isExternal = this.settings ? this.settings.get(ZmSetting.IS_EXTERNAL) : false; 601 if (isExternal) { 602 return; 603 } 604 var list = []; 605 for (var id in ZmSetting.CHANGED_IMPLICIT) { 606 var setting = this.settings ? this.settings.getSetting(id) : null; 607 if (ZmSetting.IS_GLOBAL[setting.id] && !this.isMain) { continue; } 608 if (setting && (setting.getValue(null, true) != setting.getOrigValue(null, true))) { 609 list.push(setting); 610 } 611 } 612 613 if (list.length > 0) { 614 this.settings.save(list, null, null, this); 615 } 616 }; 617 618 /** 619 * Checks if this account supports the given application name 620 * 621 * @param {String} appName the name of the application 622 * @return {Boolean} <code>true</code> if account supports the application 623 */ 624 ZmZimbraAccount.prototype.isAppEnabled = 625 function(appName) { 626 switch (appName) { 627 case ZmApp.BRIEFCASE: return appCtxt.get(ZmSetting.BRIEFCASE_ENABLED, null, this); 628 case ZmApp.CALENDAR: return appCtxt.get(ZmSetting.CALENDAR_ENABLED, null, this); 629 case ZmApp.CONTACTS: return appCtxt.get(ZmSetting.CONTACTS_ENABLED, null, this); 630 case ZmApp.MAIL: return appCtxt.get(ZmSetting.MAIL_ENABLED, null, this); 631 case ZmApp.PREFERENCES: return appCtxt.get(ZmSetting.OPTIONS_ENABLED, null, this); 632 case ZmApp.TASKS: return appCtxt.get(ZmSetting.TASKS_ENABLED, null, this); 633 } 634 return false; 635 }; 636 637 638 // 639 // Protected methods 640 // 641 642 /** 643 * @private 644 */ 645 ZmZimbraAccount.prototype._handleLoadSettings = 646 function(result) { 647 DBG.println(AjxDebug.DBG1, "Account settings successfully loaded for " + this.name); 648 649 // set account type 650 this.type = appCtxt.isOffline 651 ? appCtxt.get(ZmSetting.OFFLINE_ACCOUNT_FLAVOR, null, this) 652 : ZmAccount.TYPE_ZIMBRA; 653 654 this.isZimbraAccount = this.type == ZmAccount.TYPE_ZIMBRA; 655 656 // set icon now that we know the type 657 switch (this.type) { 658 case ZmAccount.TYPE_AOL: this.icon = "AccountAOL"; break; 659 case ZmAccount.TYPE_GMAIL: this.icon = "AccountGmail"; break; 660 case ZmAccount.TYPE_IMAP: this.icon = "AccountIMAP"; break; 661 case ZmAccount.TYPE_LIVE: this.icon = "AccountMSN"; break; 662 case ZmAccount.TYPE_MSE: this.icon = "AccountExchange"; break; 663 case ZmAccount.TYPE_EXCHANGE: this.icon = "AccountExchange"; break; 664 case ZmAccount.TYPE_POP: this.icon = "AccountPOP"; break; 665 case ZmAccount.TYPE_YMP: this.icon = "AccountYahoo"; break; 666 case ZmAccount.TYPE_ZIMBRA: this.icon = "AccountZimbra"; break; 667 } 668 669 // initialize identities/data-sources/signatures for this account 670 var obj = result.getResponse().GetInfoResponse; 671 appCtxt.getIdentityCollection(this).initialize(obj.identities); 672 appCtxt.getDataSourceCollection(this).initialize(obj.dataSources); 673 appCtxt.getSignatureCollection(this).initialize(obj.signatures); 674 675 }; 676 677 /** 678 * @private 679 */ 680 ZmZimbraAccount.prototype._handleLoadFolders = 681 function(result) { 682 var resp = result.getResponse().GetFolderResponse; 683 var folders = resp ? resp.folder[0] : null; 684 if (folders) { 685 appCtxt.getRequestMgr()._loadTree(ZmOrganizer.FOLDER, null, resp.folder[0], "folder", this); 686 } 687 }; 688 689 /** 690 * @private 691 */ 692 ZmZimbraAccount.prototype._handleLoadTags = 693 function(result) { 694 var resp = result.getResponse().GetTagResponse; 695 appCtxt.getRequestMgr()._loadTree(ZmOrganizer.TAG, null, resp, null, this); 696 }; 697 698 /** 699 * @private 700 */ 701 ZmZimbraAccount.prototype._handleLoadUserInfo = 702 function(callback) { 703 this.loaded = true; 704 705 // bug fix #33168 - get perms for all mountpoints in account 706 var folderTree = appCtxt.getFolderTree(this); 707 if (folderTree) { 708 folderTree.getPermissions({noBusyOverlay:true, accountName:this.name}); 709 } 710 711 if (callback) { 712 callback.run(); 713 } 714 }; 715 716 /** 717 * @private 718 */ 719 ZmZimbraAccount.prototype._handleLoadMetaData = 720 function(callback, sections) { 721 for (var i in sections) { 722 this.settings.createFromJs(sections[i]); 723 } 724 725 if (callback) { 726 callback.run(); 727 } 728 }; 729 730 /** 731 * @private 732 */ 733 ZmZimbraAccount.prototype._handleErrorLoad = 734 function(callback, ev) { 735 DBG.println(AjxDebug.DBG1, "------- ERROR loading account settings for " + this.name); 736 if (callback) { 737 callback.run(); 738 } 739 }; 740 741 /** 742 * @private 743 */ 744 ZmZimbraAccount.prototype._loadFromDom = 745 function(node) { 746 this.id = node.id; 747 this.name = node.name; 748 this.visible = node.visible; 749 this.active = node.active; 750 751 var data = node.attrs && node.attrs._attrs; 752 this._displayName = data ? data.displayName : this.email; 753 this._accountName = data && data.zimbraPrefLabel; 754 }; 755