Home | History | Annotate | Download | only in front-end
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 WebInspector.ApplicationCacheItemsView = function(treeElement, appcacheDomain)
     27 {
     28     WebInspector.View.call(this);
     29 
     30     this.element.addStyleClass("storage-view");
     31     this.element.addStyleClass("table");
     32 
     33     // FIXME: Delete Button semantics are not yet defined.
     34     // FIXME: Needs better tooltip. (Localized)
     35     this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
     36     this.deleteButton.visible = false;
     37     this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
     38 
     39     // FIXME: Refresh Button semantics are not yet defined.
     40     // FIXME: Needs better tooltip. (Localized)
     41     this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
     42     this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
     43 
     44     if (Preferences.onlineDetectionEnabled) {
     45         this.connectivityIcon = document.createElement("img");
     46         this.connectivityIcon.className = "storage-application-cache-connectivity-icon";
     47         this.connectivityIcon.src = "";
     48         this.connectivityMessage = document.createElement("span");
     49         this.connectivityMessage.className = "storage-application-cache-connectivity";
     50         this.connectivityMessage.textContent = "";
     51     }
     52 
     53     this.divider = document.createElement("span");
     54     this.divider.className = "status-bar-item status-bar-divider";
     55 
     56     this.statusIcon = document.createElement("img");
     57     this.statusIcon.className = "storage-application-cache-status-icon";
     58     this.statusIcon.src = "";
     59     this.statusMessage = document.createElement("span");
     60     this.statusMessage.className = "storage-application-cache-status";
     61     this.statusMessage.textContent = "";
     62 
     63     this._treeElement = treeElement;
     64     this._appcacheDomain = appcacheDomain;
     65 
     66     this._emptyMsgElement = document.createElement("div");
     67     this._emptyMsgElement.className = "storage-empty-view";
     68     this._emptyMsgElement.textContent = WebInspector.UIString("No Application Cache information available.");
     69     this.element.appendChild(this._emptyMsgElement);
     70 
     71     this.updateStatus(applicationCache.UNCACHED);
     72 }
     73 
     74 WebInspector.ApplicationCacheItemsView.prototype = {
     75     get statusBarItems()
     76     {
     77         if (Preferences.onlineDetectionEnabled) {
     78             return [
     79                 this.refreshButton.element, this.deleteButton.element,
     80                 this.connectivityIcon, this.connectivityMessage, this.divider,
     81                 this.statusIcon, this.statusMessage
     82             ];
     83         } else {
     84             return [
     85                 this.refreshButton.element, this.deleteButton.element, this.divider,
     86                 this.statusIcon, this.statusMessage
     87             ];
     88         }
     89     },
     90 
     91     show: function(parentElement)
     92     {
     93         WebInspector.View.prototype.show.call(this, parentElement);
     94         this.updateNetworkState(navigator.onLine);
     95         this._update();
     96     },
     97 
     98     hide: function()
     99     {
    100         WebInspector.View.prototype.hide.call(this);
    101         this.deleteButton.visible = false;
    102     },
    103 
    104     updateStatus: function(status)
    105     {
    106         var statusInformation = {};
    107         statusInformation[applicationCache.UNCACHED]    = { src: "Images/warningOrangeDot.png", text: "UNCACHED"    };
    108         statusInformation[applicationCache.IDLE]        = { src: "Images/warningOrangeDot.png", text: "IDLE"        };
    109         statusInformation[applicationCache.CHECKING]    = { src: "Images/successGreenDot.png",  text: "CHECKING"    };
    110         statusInformation[applicationCache.DOWNLOADING] = { src: "Images/successGreenDot.png",  text: "DOWNLOADING" };
    111         statusInformation[applicationCache.UPDATEREADY] = { src: "Images/successGreenDot.png",  text: "UPDATEREADY" };
    112         statusInformation[applicationCache.OBSOLETE]    = { src: "Images/errorRedDot.png",      text: "OBSOLETE"    };
    113 
    114         var info = statusInformation[status];
    115         if (!info) {
    116             console.error("Unknown Application Cache Status was Not Handled: %d", status);
    117             return;
    118         }
    119 
    120         this.statusIcon.src = info.src;
    121         this.statusMessage.textContent = info.text;
    122     },
    123 
    124     updateNetworkState: function(isNowOnline)
    125     {
    126         if (Preferences.onlineDetectionEnabled) {
    127             if (isNowOnline) {
    128                 this.connectivityIcon.src = "Images/successGreenDot.png";
    129                 this.connectivityMessage.textContent = WebInspector.UIString("Online");
    130             } else {
    131                 this.connectivityIcon.src = "Images/errorRedDot.png";
    132                 this.connectivityMessage.textContent = WebInspector.UIString("Offline");
    133             }
    134         }
    135     },
    136 
    137     _update: function()
    138     {
    139         WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync(this._updateCallback.bind(this));
    140     },
    141 
    142     _updateCallback: function(applicationCaches)
    143     {
    144         // FIXME: applicationCaches is just one cache.
    145         // FIXME: are these variables needed anywhere else?
    146         this._manifest = applicationCaches.manifest;
    147         this._creationTime = applicationCaches.creationTime;
    148         this._updateTime = applicationCaches.updateTime;
    149         this._size = applicationCaches.size;
    150         this._resources = applicationCaches.resources;
    151         var lastPathComponent = applicationCaches.lastPathComponent;
    152 
    153         if (!this._manifest) {
    154             this._emptyMsgElement.removeStyleClass("hidden");
    155             this.deleteButton.visible = false;
    156             if (this._dataGrid)
    157                 this._dataGrid.element.addStyleClass("hidden");
    158             return;
    159         }
    160 
    161         if (!this._dataGrid)
    162             this._createDataGrid();
    163 
    164         this._populateDataGrid();
    165         this._dataGrid.autoSizeColumns(20, 80);
    166         this._dataGrid.element.removeStyleClass("hidden");
    167         this._emptyMsgElement.addStyleClass("hidden");
    168         this.deleteButton.visible = true;
    169 
    170         var totalSizeString = Number.bytesToString(this._size);
    171         this._treeElement.subtitle = WebInspector.UIString("%s (%s)", lastPathComponent, totalSizeString);
    172 
    173         // FIXME: For Chrome, put creationTime and updateTime somewhere.
    174         // NOTE: localizedString has not yet been added.
    175         // WebInspector.UIString("(%s) Created: %s Updated: %s", this._size, this._creationTime, this._updateTime);
    176     },
    177 
    178     _createDataGrid: function()
    179     {
    180         var columns = { 0: {}, 1: {}, 2: {} };
    181         columns[0].title = WebInspector.UIString("Resource");
    182         columns[0].sort = "ascending";
    183         columns[0].sortable = true;
    184         columns[1].title = WebInspector.UIString("Type");
    185         columns[1].sortable = true;
    186         columns[2].title = WebInspector.UIString("Size");
    187         columns[2].aligned = "right";
    188         columns[2].sortable = true;
    189         this._dataGrid = new WebInspector.DataGrid(columns);
    190         this.element.appendChild(this._dataGrid.element);
    191         this._dataGrid.addEventListener("sorting changed", this._populateDataGrid, this);
    192         this._dataGrid.updateWidths();
    193     },
    194 
    195     _populateDataGrid: function()
    196     {
    197         var selectedResource = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.resource : null;
    198         var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1;
    199 
    200         function numberCompare(field, resource1, resource2)
    201         {
    202             return sortDirection * (resource1[field] - resource2[field]);
    203         }
    204         function localeCompare(field, resource1, resource2)
    205         {
    206              return sortDirection * (resource1[field] + "").localeCompare(resource2[field] + "")
    207         }
    208 
    209         var comparator;
    210         switch (parseInt(this._dataGrid.sortColumnIdentifier)) {
    211             case 0: comparator = localeCompare.bind(this, "name"); break;
    212             case 1: comparator = localeCompare.bind(this, "type"); break;
    213             case 2: comparator = numberCompare.bind(this, "size"); break;
    214             default: localeCompare.bind(this, "resource"); // FIXME: comparator = ?
    215         }
    216 
    217         this._resources.sort(comparator);
    218         this._dataGrid.removeChildren();
    219 
    220         var nodeToSelect;
    221         for (var i = 0; i < this._resources.length; ++i) {
    222             var data = {};
    223             var resource = this._resources[i];
    224             data[0] = resource.name;
    225             data[1] = resource.type;
    226             data[2] = Number.bytesToString(resource.size);
    227             var node = new WebInspector.DataGridNode(data);
    228             node.resource = resource;
    229             node.selectable = true;
    230             this._dataGrid.appendChild(node);
    231             if (resource === selectedResource) {
    232                 nodeToSelect = node;
    233                 nodeToSelect.selected = true;
    234             }
    235         }
    236 
    237         if (!nodeToSelect)
    238             this._dataGrid.children[0].selected = true;
    239     },
    240 
    241     resize: function()
    242     {
    243         if (this._dataGrid)
    244             this._dataGrid.updateWidths();
    245     },
    246 
    247     _deleteButtonClicked: function(event)
    248     {
    249         if (!this._dataGrid || !this._dataGrid.selectedNode)
    250             return;
    251 
    252         // FIXME: Delete Button semantics are not yet defined. (Delete a single, or all?)
    253         this._deleteCallback(this._dataGrid.selectedNode);
    254     },
    255 
    256     _deleteCallback: function(node)
    257     {
    258         // FIXME: Should we delete a single (selected) resource or all resources?
    259         // InspectorBackend.deleteCachedResource(...)
    260         // this._update();
    261     },
    262 
    263     _refreshButtonClicked: function(event)
    264     {
    265         // FIXME: Is this a refresh button or a re-fetch manifest button?
    266         // this._update();
    267     }
    268 }
    269 
    270 WebInspector.ApplicationCacheItemsView.prototype.__proto__ = WebInspector.View.prototype;
    271 
    272 WebInspector.ApplicationCacheDispatcher = function()
    273 {
    274 }
    275 
    276 WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync = function(callback)
    277 {
    278     function mycallback(error, applicationCaches)
    279     {
    280         // FIXME: Currently, this list only returns a single application cache.
    281         if (!error && applicationCaches)
    282             callback(applicationCaches);
    283     }
    284 
    285     ApplicationCacheAgent.getApplicationCaches(mycallback);
    286 }
    287 
    288 WebInspector.ApplicationCacheDispatcher.prototype = {
    289     updateApplicationCacheStatus: function(status)
    290     {
    291         WebInspector.panels.resources.updateApplicationCacheStatus(status);
    292     },
    293 
    294     updateNetworkState: function(isNowOnline)
    295     {
    296         WebInspector.panels.resources.updateNetworkState(isNowOnline);
    297     }
    298 }
    299 
    300 InspectorBackend.registerDomainDispatcher("ApplicationCache", new WebInspector.ApplicationCacheDispatcher());
    301