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 /** 6 * Converts a number in bytes to a string in megabytes split by comma into 7 * three digit block. 8 * @param {number} bytes The number in bytes. 9 * @return {string} Formatted string in megabytes. 10 */ 11 function ToMegaByteString(bytes) { 12 var mb = Math.floor(bytes / (1 << 20)); 13 return mb.toString().replace( 14 /\d+?(?=(\d{3})+$)/g, // Digit sequence (\d+) followed (?=) by 3n digits. 15 function(three_digit_block) { return three_digit_block + ','; } 16 ); 17 } 18 19 /** 20 * Updates the Drive related Flags section. 21 * @param {Array} flags List of dictionaries describing flags. 22 */ 23 function updateDriveRelatedFlags(flags) { 24 var ul = $('drive-related-flags'); 25 updateKeyValueList(ul, flags); 26 } 27 28 /** 29 * Updates the Drive related Preferences section. 30 * @param {Array} preferences List of dictionaries describing preferences. 31 */ 32 function updateDriveRelatedPreferences(preferences) { 33 var ul = $('drive-related-preferences'); 34 updateKeyValueList(ul, preferences); 35 } 36 37 /** 38 * Updates the Authentication Status section. 39 * @param {Object} authStatus Dictionary containing auth status. 40 */ 41 function updateAuthStatus(authStatus) { 42 $('has-refresh-token').textContent = authStatus['has-refresh-token']; 43 $('has-access-token').textContent = authStatus['has-access-token']; 44 } 45 46 /** 47 * Updates the GCache Contents section. 48 * @param {Array} gcacheContents List of dictionaries describing metadata 49 * of files and directories under the GCache directory. 50 * @param {Object} gcacheSummary Dictionary of summary of GCache. 51 */ 52 function updateGCacheContents(gcacheContents, gcacheSummary) { 53 var tbody = $('gcache-contents'); 54 for (var i = 0; i < gcacheContents.length; i++) { 55 var entry = gcacheContents[i]; 56 var tr = document.createElement('tr'); 57 58 // Add some suffix based on the type. 59 var path = entry.path; 60 if (entry.is_directory) 61 path += '/'; 62 else if (entry.is_symbolic_link) 63 path += '@'; 64 65 tr.appendChild(createElementFromText('td', path)); 66 tr.appendChild(createElementFromText('td', entry.size)); 67 tr.appendChild(createElementFromText('td', entry.last_modified)); 68 tr.appendChild(createElementFromText('td', entry.permission)); 69 tbody.appendChild(tr); 70 } 71 72 $('gcache-summary-total-size').textContent = 73 ToMegaByteString(gcacheSummary['total_size']); 74 } 75 76 /** 77 * Updates the File System Contents section. The function is called from the 78 * C++ side repeatedly with contents of a directory. 79 * @param {string} directoryContentsAsText Pre-formatted string representation 80 * of contents a directory in the file system. 81 */ 82 function updateFileSystemContents(directoryContentsAsText) { 83 var div = $('file-system-contents'); 84 div.appendChild(createElementFromText('pre', directoryContentsAsText)); 85 } 86 87 /** 88 * Updates the Cache Contents section. 89 * @param {Object} cacheEntry Dictionary describing a cache entry. 90 * The function is called from the C++ side repeatedly. 91 */ 92 function updateCacheContents(cacheEntry) { 93 var tr = document.createElement('tr'); 94 tr.appendChild(createElementFromText('td', cacheEntry.resource_id)); 95 tr.appendChild(createElementFromText('td', cacheEntry.md5)); 96 tr.appendChild(createElementFromText('td', cacheEntry.is_present)); 97 tr.appendChild(createElementFromText('td', cacheEntry.is_pinned)); 98 tr.appendChild(createElementFromText('td', cacheEntry.is_dirty)); 99 100 $('cache-contents').appendChild(tr); 101 } 102 103 /** 104 * Updates the Local Storage summary. 105 * @param {Object} localStorageSummary Dictionary describing the status of local 106 * stogage. 107 */ 108 function updateLocalStorageUsage(localStorageSummary) { 109 var freeSpaceInMB = ToMegaByteString(localStorageSummary.free_space); 110 $('local-storage-freespace').innerText = freeSpaceInMB; 111 } 112 113 /** 114 * Updates the summary about in-flight operations. 115 * @param {Array} inFlightOperations List of dictionaries describing the status 116 * of in-flight operations. 117 */ 118 function updateInFlightOperations(inFlightOperations) { 119 var container = $('in-flight-operations-contents'); 120 121 // Reset the table. Remove children in reverse order. Otherwides each 122 // existingNodes[i] changes as a side effect of removeChild. 123 var existingNodes = container.childNodes; 124 for (var i = existingNodes.length - 1; i >= 0; i--) { 125 var node = existingNodes[i]; 126 if (node.className == 'in-flight-operation') 127 container.removeChild(node); 128 } 129 130 // Add in-flight operations. 131 for (var i = 0; i < inFlightOperations.length; i++) { 132 var operation = inFlightOperations[i]; 133 var tr = document.createElement('tr'); 134 tr.className = 'in-flight-operation'; 135 tr.appendChild(createElementFromText('td', operation.id)); 136 tr.appendChild(createElementFromText('td', operation.type)); 137 tr.appendChild(createElementFromText('td', operation.file_path)); 138 tr.appendChild(createElementFromText('td', operation.state)); 139 var progress = operation.progress_current + '/' + operation.progress_total; 140 if (operation.progress_total > 0) { 141 var percent = operation.progress_current / operation.progress_total * 100; 142 progress += ' (' + Math.round(percent) + '%)'; 143 } 144 tr.appendChild(createElementFromText('td', progress)); 145 146 container.appendChild(tr); 147 } 148 } 149 150 /** 151 * Updates the summary about about resource. 152 * @param {Object} aboutResource Dictionary describing about resource. 153 */ 154 function updateAboutResource(aboutResource) { 155 var quotaTotalInMb = ToMegaByteString(aboutResource['account-quota-total']); 156 var quotaUsedInMb = ToMegaByteString(aboutResource['account-quota-used']); 157 158 $('account-quota-info').textContent = 159 quotaUsedInMb + ' / ' + quotaTotalInMb + ' (MB)'; 160 $('account-largest-changestamp-remote').textContent = 161 aboutResource['account-largest-changestamp-remote']; 162 $('root-resource-id').textContent = aboutResource['root-resource-id']; 163 } 164 165 /** 166 * Updates the summary about app list. 167 * @param {Object} appList Dictionary describing app list. 168 */ 169 function updateAppList(appList) { 170 $('app-list-etag').textContent = appList['etag']; 171 172 var itemContainer = $('app-list-items'); 173 for (var i = 0; i < appList['items'].length; i++) { 174 var app = appList['items'][i]; 175 var tr = document.createElement('tr'); 176 tr.className = 'installed-app'; 177 tr.appendChild(createElementFromText('td', app.name)); 178 tr.appendChild(createElementFromText('td', app.application_id)); 179 tr.appendChild(createElementFromText('td', app.object_type)); 180 tr.appendChild(createElementFromText('td', app.supports_create)); 181 182 itemContainer.appendChild(tr); 183 } 184 } 185 186 /** 187 * Updates the local cache information about account metadata. 188 * @param {Object} localMetadata Dictionary describing account metadata. 189 */ 190 function updateLocalMetadata(localMetadata) { 191 var changestamp = localMetadata['account-largest-changestamp-local']; 192 193 $('account-largest-changestamp-local').textContent = 194 changestamp.toString() + 195 (changestamp > 0 ? ' (loaded)' : ' (not loaded)') + 196 (localMetadata['account-metadata-refreshing'] ? ' (refreshing)' : ''); 197 } 198 199 /** 200 * Updates the summary about delta update status. 201 * @param {Object} deltaUpdateStatus Dictionary describing delta update status. 202 */ 203 function updateDeltaUpdateStatus(deltaUpdateStatus) { 204 $('push-notification-enabled').textContent = 205 deltaUpdateStatus['push-notification-enabled']; 206 $('last-update-check-time').textContent = 207 deltaUpdateStatus['last-update-check-time']; 208 $('last-update-check-error').textContent = 209 deltaUpdateStatus['last-update-check-error']; 210 } 211 212 /** 213 * Updates the event log section. 214 * @param {Array} log Array of events. 215 */ 216 function updateEventLog(log) { 217 var ul = $('event-log'); 218 updateKeyValueList(ul, log); 219 } 220 221 /** 222 * Creates an element named |elementName| containing the content |text|. 223 * @param {string} elementName Name of the new element to be created. 224 * @param {string} text Text to be contained in the new element. 225 * @return {HTMLElement} The newly created HTML element. 226 */ 227 function createElementFromText(elementName, text) { 228 var element = document.createElement(elementName); 229 element.appendChild(document.createTextNode(text)); 230 return element; 231 } 232 233 /** 234 * Updates <ul> element with the given key-value list. 235 * @param {HTMLElement} ul <ul> element to be modified. 236 * @param {Array} list List of dictionaries containing 'key', 'value' (optional) 237 * and 'class' (optional). For each element <li> element with specified class is 238 * created. 239 */ 240 function updateKeyValueList(ul, list) { 241 for (var i = 0; i < list.length; i++) { 242 var item = list[i]; 243 var text = item.key; 244 if (item.value != '') 245 text += ': ' + item.value; 246 247 var li = createElementFromText('li', text); 248 if (item.class) 249 li.classList.add(item.class); 250 ul.appendChild(li); 251 } 252 } 253 254 document.addEventListener('DOMContentLoaded', function() { 255 chrome.send('pageLoaded'); 256 257 // Update the table of contents. 258 var toc = $('toc'); 259 var sections = document.getElementsByTagName('h2'); 260 for (var i = 0; i < sections.length; i++) { 261 var section = sections[i]; 262 var a = createElementFromText('a', section.textContent); 263 a.href = '#' + section.id; 264 var li = document.createElement('li'); 265 li.appendChild(a); 266 toc.appendChild(li); 267 } 268 269 $('button-clear-access-token').addEventListener('click', function() { 270 chrome.send('clearAccessToken'); 271 }); 272 273 $('button-clear-refresh-token').addEventListener('click', function() { 274 chrome.send('clearRefreshToken'); 275 }); 276 277 $('button-show-file-entries').addEventListener('click', function() { 278 var button = $('button-show-file-entries'); 279 button.parentNode.removeChild(button); 280 chrome.send('listFileEntries'); 281 }); 282 283 window.setInterval(function() { 284 chrome.send('periodicUpdate'); 285 }, 1000); 286 }); 287