1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5cr.define('options', function() {
6  var OptionsPage = options.OptionsPage;
7
8  /////////////////////////////////////////////////////////////////////////////
9  // CertificateManagerTab class:
10
11  /**
12   * blah
13   * @param {!string} id The id of this tab.
14   */
15  function CertificateManagerTab(id) {
16    this.tree = $(id + '-tree');
17
18    options.CertificatesTree.decorate(this.tree);
19    this.tree.addEventListener('change',
20        this.handleCertificatesTreeChange_.bind(this));
21
22    var tree = this.tree;
23
24    this.viewButton = $(id + '-view');
25    this.viewButton.onclick = function(e) {
26      var selected = tree.selectedItem;
27      chrome.send('viewCertificate', [selected.data.id]);
28    }
29
30    this.editButton = $(id + '-edit');
31    if (this.editButton !== null) {
32      if (id == 'serverCertsTab') {
33        this.editButton.onclick = function(e) {
34          var selected = tree.selectedItem;
35          chrome.send('editServerCertificate', [selected.data.id]);
36        }
37      } else if (id == 'caCertsTab') {
38        this.editButton.onclick = function(e) {
39          var data = tree.selectedItem.data;
40          CertificateEditCaTrustOverlay.show(data.id, data.name);
41        }
42      }
43    }
44
45    this.backupButton = $(id + '-backup');
46    if (this.backupButton !== null) {
47      this.backupButton.onclick = function(e) {
48        var selected = tree.selectedItem;
49        chrome.send('exportPersonalCertificate', [selected.data.id]);
50      }
51    }
52
53    this.backupAllButton = $(id + '-backup-all');
54    if (this.backupAllButton !== null) {
55      this.backupAllButton.onclick = function(e) {
56        chrome.send('exportAllPersonalCertificates');
57      }
58    }
59
60    this.importButton = $(id + '-import');
61    if (this.importButton !== null) {
62      if (id == 'personalCertsTab') {
63        this.importButton.onclick = function(e) {
64          chrome.send('importPersonalCertificate', [false]);
65        }
66      } else if (id == 'serverCertsTab') {
67        this.importButton.onclick = function(e) {
68          chrome.send('importServerCertificate');
69        }
70      } else if (id == 'caCertsTab') {
71        this.importButton.onclick = function(e) {
72          chrome.send('importCaCertificate');
73        }
74      }
75    }
76
77    this.importAndBindButton = $(id + '-import-and-bind');
78    if (this.importAndBindButton !== null) {
79      if (id == 'personalCertsTab') {
80        this.importAndBindButton.onclick = function(e) {
81          chrome.send('importPersonalCertificate', [true]);
82        }
83      }
84    }
85
86    this.exportButton = $(id + '-export');
87    if (this.exportButton !== null) {
88      this.exportButton.onclick = function(e) {
89        var selected = tree.selectedItem;
90        chrome.send('exportCertificate', [selected.data.id]);
91      }
92    }
93
94    this.deleteButton = $(id + '-delete');
95    this.deleteButton.onclick = function(e) {
96      var data = tree.selectedItem.data;
97      AlertOverlay.show(
98          loadTimeData.getStringF(id + 'DeleteConfirm', data.name),
99          loadTimeData.getString(id + 'DeleteImpact'),
100          loadTimeData.getString('ok'),
101          loadTimeData.getString('cancel'),
102          function() {
103            tree.selectedItem = null;
104            chrome.send('deleteCertificate', [data.id]);
105          });
106    }
107  }
108
109  CertificateManagerTab.prototype = {
110
111    /**
112     * Update button state.
113     * @private
114     * @param {!Object} data The data of the selected item.
115     */
116    updateButtonState: function(data) {
117      var isCert = !!data && data.isCert;
118      var readOnly = !!data && data.readonly;
119      var extractable = !!data && data.extractable;
120      var hasChildren = this.tree.items.length > 0;
121      var isPolicy = !!data && data.policy;
122      this.viewButton.disabled = !isCert;
123      if (this.editButton !== null)
124        this.editButton.disabled = !isCert || isPolicy;
125      if (this.backupButton !== null)
126        this.backupButton.disabled = !isCert || !extractable;
127      if (this.backupAllButton !== null)
128        this.backupAllButton.disabled = !hasChildren;
129      if (this.exportButton !== null)
130        this.exportButton.disabled = !isCert;
131      this.deleteButton.disabled = !isCert || readOnly || isPolicy;
132    },
133
134    /**
135     * Handles certificate tree selection change.
136     * @private
137     * @param {!Event} e The change event object.
138     */
139    handleCertificatesTreeChange_: function(e) {
140      var data = null;
141      if (this.tree.selectedItem) {
142        data = this.tree.selectedItem.data;
143      }
144
145      this.updateButtonState(data);
146    },
147  };
148
149  // TODO(xiyuan): Use notification from backend instead of polling.
150  // TPM token check polling timer.
151  var tpmPollingTimer;
152
153  // Initiate tpm token check if needed.
154  function checkTpmToken() {
155    var importAndBindButton = $('personalCertsTab-import-and-bind');
156
157    if (importAndBindButton && importAndBindButton.disabled)
158      chrome.send('checkTpmTokenReady');
159  }
160
161  // Stop tpm polling timer.
162  function stopTpmTokenCheckPolling() {
163    if (tpmPollingTimer) {
164      window.clearTimeout(tpmPollingTimer);
165      tpmPollingTimer = undefined;
166    }
167  }
168
169  /////////////////////////////////////////////////////////////////////////////
170  // CertificateManager class:
171
172  /**
173   * Encapsulated handling of ChromeOS accounts options page.
174   * @constructor
175   */
176  function CertificateManager(model) {
177    OptionsPage.call(this, 'certificates',
178                     loadTimeData.getString('certificateManagerPageTabTitle'),
179                     'certificateManagerPage');
180  }
181
182  cr.addSingletonGetter(CertificateManager);
183
184  CertificateManager.prototype = {
185    __proto__: OptionsPage.prototype,
186
187    initializePage: function() {
188      OptionsPage.prototype.initializePage.call(this);
189
190      this.personalTab = new CertificateManagerTab('personalCertsTab');
191      this.serverTab = new CertificateManagerTab('serverCertsTab');
192      this.caTab = new CertificateManagerTab('caCertsTab');
193      this.otherTab = new CertificateManagerTab('otherCertsTab');
194
195      this.addEventListener('visibleChange', this.handleVisibleChange_);
196
197      $('certificate-confirm').onclick = function() {
198        OptionsPage.closeOverlay();
199      };
200    },
201
202    initalized_: false,
203
204    /**
205     * Handler for OptionsPage's visible property change event.
206     * @private
207     * @param {Event} e Property change event.
208     */
209    handleVisibleChange_: function(e) {
210      if (!this.initalized_ && this.visible) {
211        this.initalized_ = true;
212        OptionsPage.showTab($('personal-certs-nav-tab'));
213        chrome.send('populateCertificateManager');
214      }
215
216      if (cr.isChromeOS) {
217        // Ensure TPM token check on visible and stop polling when hidden.
218        if (this.visible)
219          checkTpmToken();
220        else
221          stopTpmTokenCheckPolling();
222      }
223    }
224  };
225
226  // CertificateManagerHandler callbacks.
227  CertificateManager.onPopulateTree = function(args) {
228    $(args[0]).populate(args[1]);
229  };
230
231  CertificateManager.exportPersonalAskPassword = function(args) {
232    CertificateBackupOverlay.show();
233  };
234
235  CertificateManager.importPersonalAskPassword = function(args) {
236    CertificateRestoreOverlay.show();
237  };
238
239  CertificateManager.onCheckTpmTokenReady = function(ready) {
240    var importAndBindButton = $('personalCertsTab-import-and-bind');
241    if (importAndBindButton) {
242      importAndBindButton.disabled = !ready;
243
244      // Check again after 5 seconds if Tpm is not ready and certificate manager
245      // is still visible.
246      if (!ready && CertificateManager.getInstance().visible)
247        tpmPollingTimer = window.setTimeout(checkTpmToken, 5000);
248    }
249  };
250
251  // Export
252  return {
253    CertificateManagerTab: CertificateManagerTab,
254    CertificateManager: CertificateManager
255  };
256});
257