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 5 cr.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