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