1 // Copyright 2013 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('identity_internals', function() { 6 'use strict'; 7 8 /** 9 * Creates an identity token item. 10 * @param {!Object} tokenInfo Object containing token information. 11 * @constructor 12 */ 13 function TokenListItem(tokenInfo) { 14 var el = cr.doc.createElement('div'); 15 el.data_ = tokenInfo; 16 el.__proto__ = TokenListItem.prototype; 17 el.decorate(); 18 return el; 19 } 20 21 TokenListItem.prototype = { 22 __proto__: HTMLDivElement.prototype, 23 24 /** @override */ 25 decorate: function() { 26 this.textContent = ''; 27 this.id = this.data_.accessToken; 28 29 var table = this.ownerDocument.createElement('table'); 30 var tbody = this.ownerDocument.createElement('tbody'); 31 tbody.appendChild(this.createEntry_( 32 'accessToken', this.data_.accessToken, 'access-token')); 33 tbody.appendChild(this.createEntry_( 34 'extensionName', this.data_.extensionName, 'extension-name')); 35 tbody.appendChild(this.createEntry_( 36 'extensionId', this.data_.extensionId, 'extension-id')); 37 tbody.appendChild(this.createEntry_( 38 'tokenStatus', this.data_.status, 'token-status')); 39 tbody.appendChild(this.createEntry_( 40 'expirationTime', this.data_.expirationTime, 'expiration-time')); 41 tbody.appendChild(this.createEntryForScopes_()); 42 table.appendChild(tbody); 43 var tfoot = this.ownerDocument.createElement('tfoot'); 44 tfoot.appendChild(this.createButtons_()); 45 table.appendChild(tfoot); 46 this.appendChild(table); 47 }, 48 49 /** 50 * Creates an entry for a single property of the token. 51 * @param {string} label An i18n label of the token's property name. 52 * @param {string} value A value of the token property. 53 * @param {string} accessor Additional class to tag the field for testing. 54 * @return {HTMLElement} An HTML element with the property name and value. 55 */ 56 createEntry_: function(label, value, accessor) { 57 var row = this.ownerDocument.createElement('tr'); 58 var labelField = this.ownerDocument.createElement('td'); 59 labelField.classList.add('label'); 60 labelField.textContent = loadTimeData.getString(label); 61 row.appendChild(labelField); 62 var valueField = this.ownerDocument.createElement('td'); 63 valueField.classList.add('value'); 64 valueField.classList.add(accessor); 65 valueField.textContent = value; 66 row.appendChild(valueField); 67 return row; 68 }, 69 70 /** 71 * Creates an entry for a list of token scopes. 72 * @return {!HTMLElement} An HTML element with scopes. 73 */ 74 createEntryForScopes_: function() { 75 var row = this.ownerDocument.createElement('tr'); 76 var labelField = this.ownerDocument.createElement('td'); 77 labelField.classList.add('label'); 78 labelField.textContent = loadTimeData.getString('scopes'); 79 row.appendChild(labelField); 80 var valueField = this.ownerDocument.createElement('td'); 81 valueField.classList.add('value'); 82 valueField.classList.add('scope-list'); 83 this.data_.scopes.forEach(function(scope) { 84 valueField.appendChild(this.ownerDocument.createTextNode(scope)); 85 valueField.appendChild(this.ownerDocument.createElement('br')); 86 }, this); 87 row.appendChild(valueField); 88 return row; 89 }, 90 91 /** 92 * Creates buttons for the token. 93 * @return {HTMLElement} An HTML element with actionable buttons for the 94 * token. 95 */ 96 createButtons_: function() { 97 var row = this.ownerDocument.createElement('tr'); 98 var buttonHolder = this.ownerDocument.createElement('td'); 99 buttonHolder.colSpan = 2; 100 buttonHolder.classList.add('token-actions'); 101 buttonHolder.appendChild(this.createRevokeButton_()); 102 row.appendChild(buttonHolder); 103 return row; 104 }, 105 106 /** 107 * Creates a revoke button with an event sending a revoke token message 108 * to the controller. 109 * @return {!HTMLButtonElement} The created revoke button. 110 * @private 111 */ 112 createRevokeButton_: function() { 113 var revokeButton = this.ownerDocument.createElement('button'); 114 revokeButton.classList.add('revoke-button'); 115 revokeButton.addEventListener('click', function() { 116 chrome.send('identityInternalsRevokeToken', 117 [this.data_.extensionId, this.data_.accessToken]); 118 }.bind(this)); 119 revokeButton.textContent = loadTimeData.getString('revoke'); 120 return revokeButton; 121 }, 122 }; 123 124 /** 125 * Creates a new list of identity tokens. 126 * @param {Object=} opt_propertyBag Optional properties. 127 * @constructor 128 * @extends {cr.ui.div} 129 */ 130 var TokenList = cr.ui.define('div'); 131 132 TokenList.prototype = { 133 __proto__: HTMLDivElement.prototype, 134 135 /** @override */ 136 decorate: function() { 137 this.textContent = ''; 138 this.showTokenNodes_(); 139 }, 140 141 /** 142 * Populates the list of tokens. 143 */ 144 showTokenNodes_: function() { 145 this.data_.forEach(function(tokenInfo) { 146 this.appendChild(new TokenListItem(tokenInfo)); 147 }, this); 148 }, 149 150 /** 151 * Removes a token node related to the specifed token ID from both the 152 * internals data source as well as the user internface. 153 * @param {string} accessToken The id of the token to remove. 154 * @private 155 */ 156 removeTokenNode_: function(accessToken) { 157 var tokenIndex; 158 for (var index = 0; index < this.data_.length; index++) { 159 if (this.data_[index].accessToken == accessToken) { 160 tokenIndex = index; 161 break; 162 } 163 } 164 165 // Remove from the data_ source if token found. 166 if (tokenIndex) 167 this.data_.splice(tokenIndex, 1); 168 169 // Remove from the user interface. 170 var tokenNode = $(accessToken); 171 if (tokenNode) 172 this.removeChild(tokenNode); 173 }, 174 }; 175 176 var tokenList_; 177 178 /** 179 * Initializes the UI by asking the contoller for list of identity tokens. 180 */ 181 function initialize() { 182 chrome.send('identityInternalsGetTokens'); 183 tokenList_ = $('token-list'); 184 tokenList_.data_ = []; 185 tokenList_.__proto__ = TokenList.prototype; 186 tokenList_.decorate(); 187 } 188 189 /** 190 * Callback function accepting a list of tokens to be displayed. 191 * @param {!Token[]} tokens A list of tokens to be displayed 192 */ 193 function returnTokens(tokens) { 194 tokenList_.data_ = tokens; 195 tokenList_.showTokenNodes_(); 196 } 197 198 /** 199 * Callback function that removes a token from UI once it has been revoked. 200 * @param {!Array.<string>} accessTokens Array with a single element, which is 201 * an access token to be removed. 202 */ 203 function tokenRevokeDone(accessTokens) { 204 assert(accessTokens.length > 0); 205 tokenList_.removeTokenNode_(accessTokens[0]); 206 } 207 208 // Return an object with all of the exports. 209 return { 210 initialize: initialize, 211 returnTokens: returnTokens, 212 tokenRevokeDone: tokenRevokeDone, 213 }; 214 }); 215 216 document.addEventListener('DOMContentLoaded', identity_internals.initialize); 217