08c32ea4f0c871162fb5f05ed9043c193f48be9b
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / ApplicationCacheFrameContentView.js
1 /*
2  * Copyright (C) 2010, 2013, 2014 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.ApplicationCacheFrameContentView = function(representedObject)
27 {
28     console.assert(representedObject instanceof WebInspector.ApplicationCacheFrame);
29
30     WebInspector.ContentView.call(this, representedObject);
31
32     this.element.classList.add(WebInspector.ApplicationCacheFrameContentView.StyleClassName);
33
34     this.element.classList.add("storage-view");
35     this.element.classList.add("table");
36
37     this._frame = representedObject.frame;
38
39     this._emptyView = WebInspector.createMessageTextView(WebInspector.UIString("No Application Cache information available"), false);
40     this._emptyView.classList.add("hidden");
41     this.element.appendChild(this._emptyView);
42
43     this._markDirty();
44
45     var status = representedObject.status;
46     this.updateStatus(status);
47
48     WebInspector.applicationCacheManager.addEventListener(WebInspector.ApplicationCacheManager.Event.FrameManifestStatusChanged, this._updateStatus, this);
49 }
50
51 WebInspector.ApplicationCacheFrameContentView.StyleClassName = "application-cache-frame";
52
53 WebInspector.ApplicationCacheFrameContentView.prototype = {
54     constructor: WebInspector.ApplicationCacheFrameContentView,
55
56     get allowedNavigationSidebarPanels()
57     {
58         return [WebInspector.resourceSidebarPanel.identifier];
59     },
60
61     shown: function()
62     {
63         this._maybeUpdate();
64     },
65
66     closed: function()
67     {
68         WebInspector.applicationCacheManager.removeEventListener(null, null, this);
69     },
70
71     updateLayout: function()
72     {
73         if (this.dataGrid)
74             this.dataGrid.updateLayout();
75     },
76
77     saveToCookie: function(cookie)
78     {
79         cookie.type = WebInspector.ContentViewCookieType.ApplicationCache;
80         cookie.frame = this.representedObject.frame.url;
81         cookie.manifest = this.representedObject.manifest.manifestURL;
82     },
83
84     get scrollableElements()
85     {
86         if (!this._dataGrid)
87             return [];
88         return [this._dataGrid.scrollContainer];
89     },
90
91     _maybeUpdate: function()
92     {
93         if (!this.visible || !this._viewDirty)
94             return;
95
96         this._update();
97         this._viewDirty = false;
98     },
99
100     _markDirty: function()
101     {
102         this._viewDirty = true;
103     },
104
105     _updateStatus: function(event)
106     {
107         var frameManifest = event.data.frameManifest;
108         if (frameManifest !== this.representedObject)
109             return;
110
111         console.assert(frameManifest instanceof WebInspector.ApplicationCacheFrame);
112
113         this.updateStatus(frameManifest.status);
114     },
115
116     updateStatus: function(status)
117     {
118         var oldStatus = this._status;
119         this._status = status;
120
121         if (this.visible && this._status === WebInspector.ApplicationCacheManager.Status.Idle && (oldStatus === WebInspector.ApplicationCacheManager.Status.UpdateReady || !this._resources))
122             this._markDirty();
123
124         this._maybeUpdate();
125     },
126
127     _update: function()
128     {
129         WebInspector.applicationCacheManager.requestApplicationCache(this._frame, this._updateCallback.bind(this));
130     },
131
132     _updateCallback: function(applicationCache)
133     {
134         if (!applicationCache || !applicationCache.manifestURL) {
135             delete this._manifest;
136             delete this._creationTime;
137             delete this._updateTime;
138             delete this._size;
139             delete this._resources;
140
141             this._emptyView.classList.remove("hidden");
142
143             if (this._dataGrid)
144                 this._dataGrid.element.classList.add("hidden");
145             return;
146         }
147
148         // FIXME: are these variables needed anywhere else?
149         this._manifest = applicationCache.manifestURL;
150         this._creationTime = applicationCache.creationTime;
151         this._updateTime = applicationCache.updateTime;
152         this._size = applicationCache.size;
153         this._resources = applicationCache.resources;
154
155         if (!this._dataGrid)
156             this._createDataGrid();
157
158         this._populateDataGrid();
159         this._dataGrid.autoSizeColumns(20, 80);
160         this._dataGrid.element.classList.remove("hidden");
161
162         this._emptyView.classList.add("hidden");
163     },
164
165     _createDataGrid: function()
166     {
167         var columns = {url: {}, type: {}, size: {}};
168
169         columns.url.title = WebInspector.UIString("Resource");
170         columns.url.sortable = true;
171
172         columns.type.title = WebInspector.UIString("Type");
173         columns.type.sortable = true;
174
175         columns.size.title = WebInspector.UIString("Size");
176         columns.size.aligned = "right";
177         columns.size.sortable = true;
178
179         this._dataGrid = new WebInspector.DataGrid(columns);
180         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SortChanged, this._sortDataGrid, this);
181
182         this._dataGrid.sortColumnIdentifier = "url";
183         this._dataGrid.sortOrder = WebInspector.DataGrid.SortOrder.Ascending;
184
185         this.element.appendChild(this._dataGrid.element);
186         this._dataGrid.updateLayout();
187     },
188
189     _sortDataGrid: function()
190     {
191         function numberCompare(columnIdentifier, nodeA, nodeB)
192         {
193             return nodeA.data[columnIdentifier] - nodeB.data[columnIdentifier];
194         }
195         function localeCompare(columnIdentifier, nodeA, nodeB)
196         {
197              return (nodeA.data[columnIdentifier] + "").localeCompare(nodeB.data[columnIdentifier] + "");
198         }
199
200         var comparator;
201         switch (this._dataGrid.sortColumnIdentifier) {
202             case "type": comparator = localeCompare.bind(this, "type"); break;
203             case "size": comparator = numberCompare.bind(this, "size"); break;
204             case "url":
205             default:  comparator = localeCompare.bind(this, "url"); break;
206         }
207
208         this._dataGrid.sortNodes(comparator);
209     },
210
211     _populateDataGrid: function()
212     {
213         this._dataGrid.removeChildren();
214
215         for (var resource of this._resources) {
216             var data = {
217                 url: resource.url,
218                 type: resource.type,
219                 size: Number.bytesToString(resource.size)
220             };
221             var node = new WebInspector.DataGridNode(data);
222             this._dataGrid.appendChild(node);
223         }
224     },
225
226     _deleteButtonClicked: function(event)
227     {
228         if (!this._dataGrid || !this._dataGrid.selectedNode)
229             return;
230
231         // FIXME: Delete Button semantics are not yet defined. (Delete a single, or all?)
232         this._deleteCallback(this._dataGrid.selectedNode);
233     },
234
235     _deleteCallback: function(node)
236     {
237         // FIXME: Should we delete a single (selected) resource or all resources?
238         // InspectorBackend.deleteCachedResource(...)
239         // this._update();
240     }
241 }
242
243 WebInspector.ApplicationCacheFrameContentView.prototype.__proto__ = WebInspector.ContentView.prototype;