1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/base/content/sync/quota.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,268 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +const Ci = Components.interfaces; 1.9 +const Cc = Components.classes; 1.10 +const Cr = Components.results; 1.11 +const Cu = Components.utils; 1.12 + 1.13 +Cu.import("resource://services-sync/main.js"); 1.14 +Cu.import("resource://gre/modules/DownloadUtils.jsm"); 1.15 + 1.16 +let gSyncQuota = { 1.17 + 1.18 + init: function init() { 1.19 + this.bundle = document.getElementById("quotaStrings"); 1.20 + let caption = document.getElementById("treeCaption"); 1.21 + caption.firstChild.nodeValue = this.bundle.getString("quota.treeCaption.label"); 1.22 + 1.23 + gUsageTreeView.init(); 1.24 + this.tree = document.getElementById("usageTree"); 1.25 + this.tree.view = gUsageTreeView; 1.26 + 1.27 + this.loadData(); 1.28 + }, 1.29 + 1.30 + loadData: function loadData() { 1.31 + this._usage_req = Weave.Service.getStorageInfo(Weave.INFO_COLLECTION_USAGE, 1.32 + function (error, usage) { 1.33 + delete gSyncQuota._usage_req; 1.34 + // displayUsageData handles null values, so no need to check 'error'. 1.35 + gUsageTreeView.displayUsageData(usage); 1.36 + }); 1.37 + 1.38 + let usageLabel = document.getElementById("usageLabel"); 1.39 + let bundle = this.bundle; 1.40 + 1.41 + this._quota_req = Weave.Service.getStorageInfo(Weave.INFO_QUOTA, 1.42 + function (error, quota) { 1.43 + delete gSyncQuota._quota_req; 1.44 + 1.45 + if (error) { 1.46 + usageLabel.value = bundle.getString("quota.usageError.label"); 1.47 + return; 1.48 + } 1.49 + let used = gSyncQuota.convertKB(quota[0]); 1.50 + if (!quota[1]) { 1.51 + // No quota on the server. 1.52 + usageLabel.value = bundle.getFormattedString( 1.53 + "quota.usageNoQuota.label", used); 1.54 + return; 1.55 + } 1.56 + let percent = Math.round(100 * quota[0] / quota[1]); 1.57 + let total = gSyncQuota.convertKB(quota[1]); 1.58 + usageLabel.value = bundle.getFormattedString( 1.59 + "quota.usagePercentage.label", [percent].concat(used).concat(total)); 1.60 + }); 1.61 + }, 1.62 + 1.63 + onCancel: function onCancel() { 1.64 + if (this._usage_req) { 1.65 + this._usage_req.abort(); 1.66 + } 1.67 + if (this._quota_req) { 1.68 + this._quota_req.abort(); 1.69 + } 1.70 + return true; 1.71 + }, 1.72 + 1.73 + onAccept: function onAccept() { 1.74 + let engines = gUsageTreeView.getEnginesToDisable(); 1.75 + for each (let engine in engines) { 1.76 + Weave.Service.engineManager.get(engine).enabled = false; 1.77 + } 1.78 + if (engines.length) { 1.79 + // The 'Weave' object will disappear once the window closes. 1.80 + let Service = Weave.Service; 1.81 + Weave.Utils.nextTick(function() { Service.sync(); }); 1.82 + } 1.83 + return this.onCancel(); 1.84 + }, 1.85 + 1.86 + convertKB: function convertKB(value) { 1.87 + return DownloadUtils.convertByteUnits(value * 1024); 1.88 + } 1.89 + 1.90 +}; 1.91 + 1.92 +let gUsageTreeView = { 1.93 + 1.94 + _ignored: {keys: true, 1.95 + meta: true, 1.96 + clients: true}, 1.97 + 1.98 + /* 1.99 + * Internal data structures underlaying the tree. 1.100 + */ 1.101 + _collections: [], 1.102 + _byname: {}, 1.103 + 1.104 + init: function init() { 1.105 + let retrievingLabel = gSyncQuota.bundle.getString("quota.retrieving.label"); 1.106 + for each (let engine in Weave.Service.engineManager.getEnabled()) { 1.107 + if (this._ignored[engine.name]) 1.108 + continue; 1.109 + 1.110 + // Some engines use the same pref, which means they can only be turned on 1.111 + // and off together. We need to combine them here as well. 1.112 + let existing = this._byname[engine.prefName]; 1.113 + if (existing) { 1.114 + existing.engines.push(engine.name); 1.115 + continue; 1.116 + } 1.117 + 1.118 + let obj = {name: engine.prefName, 1.119 + title: this._collectionTitle(engine), 1.120 + engines: [engine.name], 1.121 + enabled: true, 1.122 + sizeLabel: retrievingLabel}; 1.123 + this._collections.push(obj); 1.124 + this._byname[engine.prefName] = obj; 1.125 + } 1.126 + }, 1.127 + 1.128 + _collectionTitle: function _collectionTitle(engine) { 1.129 + try { 1.130 + return gSyncQuota.bundle.getString( 1.131 + "collection." + engine.prefName + ".label"); 1.132 + } catch (ex) { 1.133 + return engine.Name; 1.134 + } 1.135 + }, 1.136 + 1.137 + /* 1.138 + * Process the quota information as returned by info/collection_usage. 1.139 + */ 1.140 + displayUsageData: function displayUsageData(data) { 1.141 + for each (let coll in this._collections) { 1.142 + coll.size = 0; 1.143 + // If we couldn't retrieve any data, just blank out the label. 1.144 + if (!data) { 1.145 + coll.sizeLabel = ""; 1.146 + continue; 1.147 + } 1.148 + 1.149 + for each (let engineName in coll.engines) 1.150 + coll.size += data[engineName] || 0; 1.151 + let sizeLabel = ""; 1.152 + sizeLabel = gSyncQuota.bundle.getFormattedString( 1.153 + "quota.sizeValueUnit.label", gSyncQuota.convertKB(coll.size)); 1.154 + coll.sizeLabel = sizeLabel; 1.155 + } 1.156 + let sizeColumn = this.treeBox.columns.getNamedColumn("size"); 1.157 + this.treeBox.invalidateColumn(sizeColumn); 1.158 + }, 1.159 + 1.160 + /* 1.161 + * Handle click events on the tree. 1.162 + */ 1.163 + onTreeClick: function onTreeClick(event) { 1.164 + if (event.button == 2) 1.165 + return; 1.166 + 1.167 + let row = {}, col = {}; 1.168 + this.treeBox.getCellAt(event.clientX, event.clientY, row, col, {}); 1.169 + if (col.value && col.value.id == "enabled") 1.170 + this.toggle(row.value); 1.171 + }, 1.172 + 1.173 + /* 1.174 + * Toggle enabled state of an engine. 1.175 + */ 1.176 + toggle: function toggle(row) { 1.177 + // Update the tree 1.178 + let collection = this._collections[row]; 1.179 + collection.enabled = !collection.enabled; 1.180 + this.treeBox.invalidateRow(row); 1.181 + 1.182 + // Display which ones will be removed 1.183 + let freeup = 0; 1.184 + let toremove = []; 1.185 + for each (collection in this._collections) { 1.186 + if (collection.enabled) 1.187 + continue; 1.188 + toremove.push(collection.name); 1.189 + freeup += collection.size; 1.190 + } 1.191 + 1.192 + let caption = document.getElementById("treeCaption"); 1.193 + if (!toremove.length) { 1.194 + caption.className = ""; 1.195 + caption.firstChild.nodeValue = gSyncQuota.bundle.getString( 1.196 + "quota.treeCaption.label"); 1.197 + return; 1.198 + } 1.199 + 1.200 + toremove = [this._byname[coll].title for each (coll in toremove)]; 1.201 + toremove = toremove.join(gSyncQuota.bundle.getString("quota.list.separator")); 1.202 + caption.firstChild.nodeValue = gSyncQuota.bundle.getFormattedString( 1.203 + "quota.removal.label", [toremove]); 1.204 + if (freeup) 1.205 + caption.firstChild.nodeValue += gSyncQuota.bundle.getFormattedString( 1.206 + "quota.freeup.label", gSyncQuota.convertKB(freeup)); 1.207 + caption.className = "captionWarning"; 1.208 + }, 1.209 + 1.210 + /* 1.211 + * Return a list of engines (or rather their pref names) that should be 1.212 + * disabled. 1.213 + */ 1.214 + getEnginesToDisable: function getEnginesToDisable() { 1.215 + return [coll.name for each (coll in this._collections) if (!coll.enabled)]; 1.216 + }, 1.217 + 1.218 + // nsITreeView 1.219 + 1.220 + get rowCount() { 1.221 + return this._collections.length; 1.222 + }, 1.223 + 1.224 + getRowProperties: function(index) { return ""; }, 1.225 + getCellProperties: function(row, col) { return ""; }, 1.226 + getColumnProperties: function(col) { return ""; }, 1.227 + isContainer: function(index) { return false; }, 1.228 + isContainerOpen: function(index) { return false; }, 1.229 + isContainerEmpty: function(index) { return false; }, 1.230 + isSeparator: function(index) { return false; }, 1.231 + isSorted: function() { return false; }, 1.232 + canDrop: function(index, orientation, dataTransfer) { return false; }, 1.233 + drop: function(row, orientation, dataTransfer) {}, 1.234 + getParentIndex: function(rowIndex) {}, 1.235 + hasNextSibling: function(rowIndex, afterIndex) { return false; }, 1.236 + getLevel: function(index) { return 0; }, 1.237 + getImageSrc: function(row, col) {}, 1.238 + 1.239 + getCellValue: function(row, col) { 1.240 + return this._collections[row].enabled; 1.241 + }, 1.242 + 1.243 + getCellText: function getCellText(row, col) { 1.244 + let collection = this._collections[row]; 1.245 + switch (col.id) { 1.246 + case "collection": 1.247 + return collection.title; 1.248 + case "size": 1.249 + return collection.sizeLabel; 1.250 + default: 1.251 + return ""; 1.252 + } 1.253 + }, 1.254 + 1.255 + setTree: function setTree(tree) { 1.256 + this.treeBox = tree; 1.257 + }, 1.258 + 1.259 + toggleOpenState: function(index) {}, 1.260 + cycleHeader: function(col) {}, 1.261 + selectionChanged: function() {}, 1.262 + cycleCell: function(row, col) {}, 1.263 + isEditable: function(row, col) { return false; }, 1.264 + isSelectable: function (row, col) { return false; }, 1.265 + setCellValue: function(row, col, value) {}, 1.266 + setCellText: function(row, col, value) {}, 1.267 + performAction: function(action) {}, 1.268 + performActionOnRow: function(action, row) {}, 1.269 + performActionOnCell: function(action, row, col) {} 1.270 + 1.271 +};