summaryrefslogtreecommitdiffstats
path: root/content/manager/accounts.js
blob: 45774b1bf7c33fda4fe244e5fe30ac57848b45a6 (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
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
/*
 * This file is part of TbSync.
 *
 * 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/. 
 */
 
 "use strict";

var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");

var tbSyncAccounts = {

  selectedAccount: null,

  onload: function () {
    //scan accounts, update list and select first entry (because no id is passed to updateAccountList)
    //the onSelect event of the List will load the selected account
    //also update/init add menu
    this.updateAvailableProvider(); 
    
    Services.obs.addObserver(tbSyncAccounts.updateProviderListObserver, "tbsync.observer.manager.updateProviderList", false);
    Services.obs.addObserver(tbSyncAccounts.updateAccountsListObserver, "tbsync.observer.manager.updateAccountsList", false);
    Services.obs.addObserver(tbSyncAccounts.updateAccountSyncStateObserver, "tbsync.observer.manager.updateSyncstate", false);
    Services.obs.addObserver(tbSyncAccounts.updateAccountNameObserver, "tbsync.observer.manager.updateAccountName", false);
    Services.obs.addObserver(tbSyncAccounts.toggleEnableStateObserver, "tbsync.observer.manager.toggleEnableState", false);
  },

  onunload: function () {
    Services.obs.removeObserver(tbSyncAccounts.updateProviderListObserver, "tbsync.observer.manager.updateProviderList");
    Services.obs.removeObserver(tbSyncAccounts.updateAccountsListObserver, "tbsync.observer.manager.updateAccountsList");
    Services.obs.removeObserver(tbSyncAccounts.updateAccountSyncStateObserver, "tbsync.observer.manager.updateSyncstate");
    Services.obs.removeObserver(tbSyncAccounts.updateAccountNameObserver, "tbsync.observer.manager.updateAccountName");
    Services.obs.removeObserver(tbSyncAccounts.toggleEnableStateObserver, "tbsync.observer.manager.toggleEnableState");
  },       
  
  hasInstalledProvider: function (accountID) {
    let provider = TbSync.db.getAccountProperty(accountID, "provider");
    return TbSync.providers.loadedProviders.hasOwnProperty(provider);
  },

  updateDropdown: function (selector) {
    let accountsList = document.getElementById("tbSyncAccounts.accounts");
    let selectedAccount = null;
    let selectedAccountName = "";
    let isActionsDropdown = (selector == "accountActions");

    let isSyncing = false;
    let isConnected = false;
    let isEnabled = false;
    let isInstalled = false;
    
    if (accountsList.selectedItem !== null && !isNaN(accountsList.selectedItem.value)) {
      //some item is selected
      let selectedItem = accountsList.selectedItem;
      selectedAccount = selectedItem.value;
      selectedAccountName = selectedItem.childNodes[1].getAttribute("value");
      isSyncing = TbSync.core.isSyncing(selectedAccount);
      isConnected = TbSync.core.isConnected(selectedAccount);
      isEnabled = TbSync.core.isEnabled(selectedAccount);
      isInstalled = tbSyncAccounts.hasInstalledProvider(selectedAccount);
    }

    //hide if no accounts are avail (which is identical to no account selected)
    if (isActionsDropdown) document.getElementById(selector + "SyncAllAccounts").hidden = (selectedAccount === null);
    
    //hide if no account is selected
    if (isActionsDropdown) document.getElementById(selector + "Separator").hidden = (selectedAccount === null);
    document.getElementById(selector + "DeleteAccount").hidden = (selectedAccount === null);
    document.getElementById(selector + "DisableAccount").hidden = (selectedAccount === null) || !isEnabled || !isInstalled;
    document.getElementById(selector + "EnableAccount").hidden = (selectedAccount === null) || isEnabled || !isInstalled;
    document.getElementById(selector + "SyncAccount").hidden = (selectedAccount === null) || !isConnected || !isInstalled;
    document.getElementById(selector + "RetryConnectAccount").hidden = (selectedAccount === null) || isConnected || !isEnabled || !isInstalled;

    if (document.getElementById(selector + "ShowEventLog")) {
      document.getElementById(selector + "ShowEventLog").hidden = false;
      document.getElementById(selector + "ShowEventLog").disabled = false;
    }
    
    if (selectedAccount !== null) {
      //disable if currently syncing (and displayed)
      document.getElementById(selector + "DeleteAccount").disabled = isSyncing;
      document.getElementById(selector + "DisableAccount").disabled = isSyncing;
      document.getElementById(selector + "EnableAccount").disabled = isSyncing;
      document.getElementById(selector + "SyncAccount").disabled = isSyncing;
      //adjust labels - only in global actions dropdown
      if (isActionsDropdown) document.getElementById(selector + "DeleteAccount").label = TbSync.getString("accountacctions.delete").replace("##accountname##", selectedAccountName);
      if (isActionsDropdown) document.getElementById(selector + "SyncAccount").label = TbSync.getString("accountacctions.sync").replace("##accountname##", selectedAccountName);
      if (isActionsDropdown) document.getElementById(selector + "EnableAccount").label = TbSync.getString("accountacctions.enable").replace("##accountname##", selectedAccountName);
      if (isActionsDropdown) document.getElementById(selector + "DisableAccount").label = TbSync.getString("accountacctions.disable").replace("##accountname##", selectedAccountName);
    }
  },
  
  synchronizeAccount: function () {
    let accountsList = document.getElementById("tbSyncAccounts.accounts");
    if (accountsList.selectedItem !== null && !isNaN(accountsList.selectedItem.value)  && !TbSync.core.isSyncing(accountsList.selectedItem.value)) {            
      if (tbSyncAccounts.hasInstalledProvider(accountsList.selectedItem.value)) {
        TbSync.core.syncAccount(accountsList.selectedItem.value);
      }
    }
  },

  deleteAccount: function () {
    let accountsList = document.getElementById("tbSyncAccounts.accounts");
    if (accountsList.selectedItem !== null && !isNaN(accountsList.selectedItem.value)  && !TbSync.core.isSyncing(accountsList.selectedItem.value)) {
      let nextAccount =  -1;
      if (accountsList.selectedIndex > 0) {
        //first try to select the item after this one, otherwise take the one before
        if (accountsList.selectedIndex + 1 < accountsList.getRowCount()) nextAccount = accountsList.getItemAtIndex(accountsList.selectedIndex + 1).value;
        else nextAccount = accountsList.getItemAtIndex(accountsList.selectedIndex - 1).value;
      }
      
      if (!tbSyncAccounts.hasInstalledProvider(accountsList.selectedItem.value)) {
        if (confirm(TbSync.getString("prompt.Erase").replace("##accountName##", accountsList.selectedItem.getAttribute("label")))) {
          //delete account and all folders from db
          TbSync.db.removeAccount(accountsList.selectedItem.value);
          //update list
          this.updateAccountsList(nextAccount);
        } 
      } else if (confirm(TbSync.getString("prompt.DeleteAccount").replace("##accountName##", accountsList.selectedItem.getAttribute("label")))) {
        //cache all folders and remove associated targets 
        TbSync.core.disableAccount(accountsList.selectedItem.value);
        
        // the following call might fail, as not all providers provide that method, it was mainly added to cleanup stored passwords
        try  {
          let accountData = new TbSync.AccountData(accountsList.selectedItem.value);
          TbSync.providers[accountData.getAccountProperty("provider")].Base.onDeleteAccount(accountData);
        } catch (e) {                Components.utils.reportError(e);}

        //delete account and all folders from db
        TbSync.db.removeAccount(accountsList.selectedItem.value);
        //update list
        this.updateAccountsList(nextAccount);
      }
    }
  },



  /* * *
  * Observer to catch update list request (upon provider load/unload)
  */
  updateAccountsListObserver: {
    observe: function (aSubject, aTopic, aData) {
      //aData is the accountID to be selected
      //if missing, it will try to not change selection
      tbSyncAccounts.updateAccountsList(aData); 
    }
  },
  
  updateProviderListObserver: {
    observe: function (aSubject, aTopic, aData) {
      //aData is a provider
      tbSyncAccounts.updateAvailableProvider(aData); 
    }
  },    

  toggleEnableState: function () {
    let accountsList = document.getElementById("tbSyncAccounts.accounts");
    
    if (accountsList.selectedItem !== null && !isNaN(accountsList.selectedItem.value) && !TbSync.core.isSyncing(accountsList.selectedItem.value)) {            
      let isConnected = TbSync.core.isConnected(accountsList.selectedItem.value);
      if (!isConnected || window.confirm(TbSync.getString("prompt.Disable"))) {           
        tbSyncAccounts.toggleAccountEnableState(accountsList.selectedItem.value);
      }
    }
  },

  /* * *
  * Observer to catch enable state toggle
  */
  toggleEnableStateObserver: {
    observe: function (aSubject, aTopic, aData) {
      tbSyncAccounts.toggleAccountEnableState(aData);
    }
  },
  
  //is not prompting, this is doing the actual toggle
  toggleAccountEnableState: function (accountID) {
    if (tbSyncAccounts.hasInstalledProvider(accountID)) {
      let isEnabled = TbSync.core.isEnabled(accountID);
      
      if (isEnabled) {
        //we are enabled and want to disable (do not ask, if not connected)
        TbSync.core.disableAccount(accountID);
        Services.obs.notifyObservers(null, "tbsync.observer.manager.updateAccountSettingsGui", accountID);
        tbSyncAccounts.updateAccountStatus(accountID);
      } else {
        //we are disabled and want to enabled
        TbSync.core.enableAccount(accountID);
        Services.obs.notifyObservers(null, "tbsync.observer.manager.updateAccountSettingsGui", accountID);
        TbSync.core.syncAccount(accountID);
      }
    }
  },

  /* * *
  * Observer to catch synstate changes and to update account icons
  */
  updateAccountSyncStateObserver: {
    observe: function (aSubject, aTopic, aData) {
      if (aData) {
        //since we want rotating arrows on each syncstate change, we need to run this on each syncstate
        tbSyncAccounts.updateAccountStatus(aData);
      }
    }
  },

  setStatusImage: function (accountID, obj) {
    let statusImage = this.getStatusImage(accountID, obj.src);
    if (statusImage != obj.src) {
      obj.src = statusImage;
    }
  },
  
  getStatusImage: function (accountID, current = "") {
    let src = "";   

    if (!tbSyncAccounts.hasInstalledProvider(accountID)) {
      src = "error16.png";
    } else {
      switch (TbSync.db.getAccountProperty(accountID, "status").split(".")[0]) {
        case "success":
          src = "tick16.png";
          break;
        
        case "disabled":
          src = "disabled16.png";
          break;
        
        case "info":
        case "notsyncronized":
        case "modified":
          src = "info16.png";
          break;

        case "warning":
          src = "warning16.png";
          break;

        case "syncing":
          switch (current.replace("chrome://tbsync/content/skin/","")) {
            case "sync16_1.png": 
              src = "sync16_2.png"; 
              break;
            case "sync16_2.png": 
              src = "sync16_3.png"; 
              break;
            case "sync16_3.png": 
              src = "sync16_4.png"; 
              break;
            case "sync16_4.png": 
              src = "sync16_1.png"; 
              break;
            default: 
              src = "sync16_1.png";
              TbSync.core.getSyncDataObject(accountID).accountManagerLastUpdated = 0;
              break;
          }                
          if ((Date.now() - TbSync.core.getSyncDataObject(accountID).accountManagerLastUpdated) < 300) {
            return current;
          }
          TbSync.core.getSyncDataObject(accountID).accountManagerLastUpdated = Date.now();
          break;

        default:
          src = "error16.png";
      }
    }
    
    return "chrome://tbsync/content/skin/" + src;
  },

  updateAccountLogo: function (id) {
    let accountData = new TbSync.AccountData(id);
    let listItem = document.getElementById("tbSyncAccounts.accounts." + id);
    if (listItem) {
      let obj = listItem.childNodes[0];
      obj.src = tbSyncAccounts.hasInstalledProvider(id) ? TbSync.providers[accountData.getAccountProperty("provider")].Base.getProviderIcon(16, accountData) : "chrome://tbsync/content/skin/provider16.png";
    }
  },

  updateAccountStatus: function (id) {
    let listItem = document.getElementById("tbSyncAccounts.accounts." + id);
    if (listItem) {
      let obj = listItem.childNodes[2];
      this.setStatusImage(id, obj);
    }
  },

  updateAccountNameObserver: {
    observe: function (aSubject, aTopic, aData) {
      let pos = aData.indexOf(":");
      let id = aData.substring(0, pos);
      let name = aData.substring(pos+1);
      tbSyncAccounts.updateAccountName (id, name);
    }
  },

  updateAccountName: function (id, name) {
    let listItem = document.getElementById("tbSyncAccounts.accounts." + id);
    if (listItem.childNodes[1].getAttribute("value") != name) {
      listItem.childNodes[1].setAttribute("value", name);
    }
  },
  
  updateAvailableProvider: function (provider = null) {        
    //either add/remove a specific provider, or rebuild the list from scratch
    if (provider) {
      //update single provider entry
      tbSyncAccounts.updateAddMenuEntry(provider);
    } else {
      //add default providers
      for (let provider in TbSync.providers.defaultProviders) {
        tbSyncAccounts.updateAddMenuEntry(provider);
      }
      //update/add all remaining installed providers
      for (let provider in TbSync.providers.loadedProviders) {
        tbSyncAccounts.updateAddMenuEntry(provider);
      }
    }
    
    this.updateAccountsList();
    
    let selectedAccount = this.getSelectedAccount();
    if (selectedAccount !== null && TbSync.db.getAccountProperty(selectedAccount, "provider") == provider) {
      tbSyncAccounts.loadSelectedAccount();
    }
  },
  
  updateAccountsList: function (accountToSelect = null) {
    let accountsList = document.getElementById("tbSyncAccounts.accounts");
    let accounts = TbSync.db.getAccounts();

    // try to keep the currently selected account, if accountToSelect is not given
    if (accountToSelect === null) {
      let s = accountsList.getItemAtIndex(accountsList.selectedIndex);
      if (s) {
        // there is an entry selected, do not change it
        accountToSelect = s.value;
      }
    }
    
    if (accounts.allIDs.length > null) {

      //get current accounts in list and remove entries of accounts no longer there
      let listedAccounts = [];
      for (let i=accountsList.getRowCount()-1; i>=0; i--) {
        let item = accountsList.getItemAtIndex(i);
        listedAccounts.push(item.value);
        if (accounts.allIDs.indexOf(item.value) == -1) {
          item.remove();
        }
      }

      //accounts array is without order, extract keys (ids) and loop over keys
      for (let i = 0; i < accounts.allIDs.length; i++) {

        if (listedAccounts.indexOf(accounts.allIDs[i]) == -1) {
          //add all missing accounts (always to the end of the list)
          let newListItem = document.createXULElement("richlistitem");
          newListItem.setAttribute("id", "tbSyncAccounts.accounts." + accounts.allIDs[i]);
          newListItem.setAttribute("value", accounts.allIDs[i]);
          newListItem.setAttribute("align", "center");
          newListItem.setAttribute("label", accounts.data[accounts.allIDs[i]].accountname);
          newListItem.setAttribute("style", "padding: 5px 0px;");
          newListItem.setAttribute("ondblclick", "tbSyncAccounts.toggleEnableState();");
          
          //add icon (use "install provider" icon, if provider not installed)
          let itemType = document.createXULElement("image");
          //itemType.setAttribute("width", "16");
          //itemType.setAttribute("height", "16");
          itemType.setAttribute("style", "margin: 0px 0px 0px 5px; width:16px; height:16px");
          newListItem.appendChild(itemType);

          //add account name
          let itemLabel = document.createXULElement("label");
          itemLabel.setAttribute("flex", "1");
          newListItem.appendChild(itemLabel);

          //add account status
          let itemStatus = document.createXULElement("image");
          //itemStatus.setAttribute("width", "16");
          //itemStatus.setAttribute("height", "16");
          itemStatus.setAttribute("style", "margin: 0px 5px; width:16px; height:16px");
          newListItem.appendChild(itemStatus);
          
          accountsList.appendChild(newListItem);
        } 
        
        //update/set actual values
        this.updateAccountName(accounts.allIDs[i], accounts.data[accounts.allIDs[i]].accountname);
        this.updateAccountStatus(accounts.allIDs[i]);
        this.updateAccountLogo(accounts.allIDs[i]);
      }
      
      //find selected item
      for (let i=0; i<accountsList.getRowCount(); i++) {
        if (accountToSelect === null || accountToSelect == accountsList.getItemAtIndex(i).value) {
          accountsList.selectedIndex = i;
          accountsList.ensureIndexIsVisible(i);
          break;
        }
      }

    } else {
      //No defined accounts, empty accounts list and load dummy
      for (let i=accountsList.getRowCount()-1; i>=0; i--) {
        accountsList.getItemAtIndex(i).remove();
      }
      document.getElementById("tbSyncAccounts.contentFrame").setAttribute("src", "chrome://tbsync/content/manager/noaccounts.xhtml");
    }
  },

  updateAddMenuEntry: function (provider) {
    let isDefault = TbSync.providers.defaultProviders.hasOwnProperty(provider);
    let isInstalled = TbSync.providers.loadedProviders.hasOwnProperty(provider);
    
    let entry = document.getElementById("addMenuEntry_" + provider);
    if (entry === null) {
      //add basic menu entry
      let newItem = window.document.createXULElement("menuitem");
      newItem.setAttribute("id", "addMenuEntry_" + provider);
      newItem.setAttribute("value",  provider);
      newItem.setAttribute("class", "menuitem-iconic");
      newItem.addEventListener("click", function () {tbSyncAccounts.addAccountAction(provider)}, false);
      newItem.setAttribute("hidden", true);
      entry = window.document.getElementById("accountActionsAddAccount").appendChild(newItem);
    }
    
    //Update label, icon and hidden according to isDefault and isInstalled
    if (isInstalled) {
      entry.setAttribute("label",  TbSync.providers[provider].Base.getProviderName());
      entry.setAttribute("image", TbSync.providers[provider].Base.getProviderIcon(16));
      entry.setAttribute("hidden", false);
    } else if (isDefault) {
      entry.setAttribute("label", TbSync.providers.defaultProviders[provider].name);
      entry.setAttribute("image", "chrome://tbsync/content/skin/provider16.png");                    
      entry.setAttribute("hidden", false);
    } else {
      entry.setAttribute("hidden", true);
    }
  },

  getSelectedAccount: function () {
    let accountsList = document.getElementById("tbSyncAccounts.accounts");
    if (accountsList.selectedItem !== null && !isNaN(accountsList.selectedItem.value)) {
      //get id of selected account from value of selectedItem
      return accountsList.selectedItem.value;
    }
    return null;
  },
  
  //load the pref page for the currently selected account (triggered by onSelect)
  loadSelectedAccount: function () {
    let selectedAccount = this.getSelectedAccount();
    
    if (selectedAccount !== null) { //account id could be 0, so need to check for null explicitly
      let provider = TbSync.db.getAccountProperty(selectedAccount, "provider");            
      if (tbSyncAccounts.hasInstalledProvider(selectedAccount)) {
        document.getElementById("tbSyncAccounts.contentFrame").setAttribute("src", "chrome://tbsync/content/manager/editAccount.xhtml?provider="+provider+"&id=" + selectedAccount);
      } else {
        document.getElementById("tbSyncAccounts.contentFrame").setAttribute("src", "chrome://tbsync/content/manager/missingProvider.xhtml?provider="+provider);
      }
    }
  },
  



  addAccountAction: function (provider) {
    let isDefault = TbSync.providers.defaultProviders.hasOwnProperty(provider);
    let isInstalled = TbSync.providers.loadedProviders.hasOwnProperty(provider);
    
    if (isInstalled) {
      tbSyncAccounts.addAccount(provider);
    } else if (isDefault) {
      tbSyncAccounts.installProvider(provider);
    }
  },
  
  addAccount: function (provider) {
    TbSync.providers.loadedProviders[provider].createAccountWindow = window.openDialog(TbSync.providers[provider].Base.getCreateAccountWindowUrl(), "TbSyncNewAccountWindow", "centerscreen,resizable=no");
    TbSync.providers.loadedProviders[provider].createAccountWindow.addEventListener("unload", function () { TbSync.manager.prefWindowObj.focus(); });
  },

  installProvider: function (provider) {
    for (let i=0; i<TbSync.AccountManagerTabs.length; i++) {            
       TbSync.manager.prefWindowObj.document.getElementById("tbSyncAccountManager.t" + i).setAttribute("active","false");
    }
    TbSync.manager.prefWindowObj.document.getElementById("tbSyncAccountManager.installProvider").hidden=false;
    TbSync.manager.prefWindowObj.document.getElementById("tbSyncAccountManager.installProvider").setAttribute("active","true");
    TbSync.manager.prefWindowObj.document.getElementById("tbSyncAccountManager.contentWindow").setAttribute("src", "chrome://tbsync/content/manager/installProvider.xhtml?provider="+provider);        
  },
      
};