OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2010 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 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, | 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | |
26 /** | 25 /** |
27 * @constructor | 26 * @unrestricted |
28 * @extends {WebInspector.SimpleView} | |
29 */ | 27 */ |
30 WebInspector.ApplicationCacheItemsView = function(model, frameId) | 28 WebInspector.ApplicationCacheItemsView = class extends WebInspector.SimpleView { |
31 { | 29 constructor(model, frameId) { |
32 WebInspector.SimpleView.call(this, WebInspector.UIString("AppCache")); | 30 super(WebInspector.UIString('AppCache')); |
33 | 31 |
34 this._model = model; | 32 this._model = model; |
35 | 33 |
36 this.element.classList.add("storage-view", "table"); | 34 this.element.classList.add('storage-view', 'table'); |
37 | 35 |
38 this._deleteButton = new WebInspector.ToolbarButton(WebInspector.UIString("D
elete"), "delete-toolbar-item"); | 36 this._deleteButton = new WebInspector.ToolbarButton(WebInspector.UIString('D
elete'), 'delete-toolbar-item'); |
39 this._deleteButton.setVisible(false); | 37 this._deleteButton.setVisible(false); |
40 this._deleteButton.addEventListener("click", this._deleteButtonClicked, this
); | 38 this._deleteButton.addEventListener('click', this._deleteButtonClicked, this
); |
41 | 39 |
42 this._connectivityIcon = createElement("label", "dt-icon-label"); | 40 this._connectivityIcon = createElement('label', 'dt-icon-label'); |
43 this._connectivityIcon.style.margin = "0 2px 0 5px"; | 41 this._connectivityIcon.style.margin = '0 2px 0 5px'; |
44 this._statusIcon = createElement("label", "dt-icon-label"); | 42 this._statusIcon = createElement('label', 'dt-icon-label'); |
45 this._statusIcon.style.margin = "0 2px 0 5px"; | 43 this._statusIcon.style.margin = '0 2px 0 5px'; |
46 | 44 |
47 this._frameId = frameId; | 45 this._frameId = frameId; |
48 | 46 |
49 this._emptyWidget = new WebInspector.EmptyWidget(WebInspector.UIString("No A
pplication Cache information available.")); | 47 this._emptyWidget = |
| 48 new WebInspector.EmptyWidget(WebInspector.UIString('No Application Cache
information available.')); |
50 this._emptyWidget.show(this.element); | 49 this._emptyWidget.show(this.element); |
51 | 50 |
52 this._markDirty(); | 51 this._markDirty(); |
53 | 52 |
54 var status = this._model.frameManifestStatus(frameId); | 53 var status = this._model.frameManifestStatus(frameId); |
55 this.updateStatus(status); | 54 this.updateStatus(status); |
56 this.updateNetworkState(this._model.onLine); | 55 this.updateNetworkState(this._model.onLine); |
57 | 56 |
58 // FIXME: Status bar items don't work well enough yet, so they are being hid
den. | 57 // FIXME: Status bar items don't work well enough yet, so they are being hid
den. |
59 // http://webkit.org/b/41637 Web Inspector: Give Semantics to "Refresh" and
"Delete" Buttons in ApplicationCache DataGrid | 58 // http://webkit.org/b/41637 Web Inspector: Give Semantics to "Refresh" and
"Delete" Buttons in ApplicationCache DataGrid |
60 this._deleteButton.element.style.display = "none"; | 59 this._deleteButton.element.style.display = 'none'; |
| 60 } |
| 61 |
| 62 /** |
| 63 * @override |
| 64 * @return {!Array.<!WebInspector.ToolbarItem>} |
| 65 */ |
| 66 syncToolbarItems() { |
| 67 return [ |
| 68 this._deleteButton, new WebInspector.ToolbarItem(this._connectivityIcon),
new WebInspector.ToolbarSeparator(), |
| 69 new WebInspector.ToolbarItem(this._statusIcon) |
| 70 ]; |
| 71 } |
| 72 |
| 73 /** |
| 74 * @override |
| 75 */ |
| 76 wasShown() { |
| 77 this._maybeUpdate(); |
| 78 } |
| 79 |
| 80 /** |
| 81 * @override |
| 82 */ |
| 83 willHide() { |
| 84 this._deleteButton.setVisible(false); |
| 85 } |
| 86 |
| 87 _maybeUpdate() { |
| 88 if (!this.isShowing() || !this._viewDirty) |
| 89 return; |
| 90 |
| 91 this._update(); |
| 92 this._viewDirty = false; |
| 93 } |
| 94 |
| 95 _markDirty() { |
| 96 this._viewDirty = true; |
| 97 } |
| 98 |
| 99 /** |
| 100 * @param {number} status |
| 101 */ |
| 102 updateStatus(status) { |
| 103 var oldStatus = this._status; |
| 104 this._status = status; |
| 105 |
| 106 var statusInformation = {}; |
| 107 // We should never have UNCACHED status, since we remove frames with UNCACHE
D application cache status from the tree. |
| 108 statusInformation[applicationCache.UNCACHED] = {type: 'red-ball', text: 'UNC
ACHED'}; |
| 109 statusInformation[applicationCache.IDLE] = {type: 'green-ball', text: 'IDLE'
}; |
| 110 statusInformation[applicationCache.CHECKING] = {type: 'orange-ball', text: '
CHECKING'}; |
| 111 statusInformation[applicationCache.DOWNLOADING] = {type: 'orange-ball', text
: 'DOWNLOADING'}; |
| 112 statusInformation[applicationCache.UPDATEREADY] = {type: 'green-ball', text:
'UPDATEREADY'}; |
| 113 statusInformation[applicationCache.OBSOLETE] = {type: 'red-ball', text: 'OBS
OLETE'}; |
| 114 |
| 115 var info = statusInformation[status] || statusInformation[applicationCache.U
NCACHED]; |
| 116 |
| 117 this._statusIcon.type = info.type; |
| 118 this._statusIcon.textContent = info.text; |
| 119 |
| 120 if (this.isShowing() && this._status === applicationCache.IDLE && |
| 121 (oldStatus === applicationCache.UPDATEREADY || !this._resources)) |
| 122 this._markDirty(); |
| 123 this._maybeUpdate(); |
| 124 } |
| 125 |
| 126 /** |
| 127 * @param {boolean} isNowOnline |
| 128 */ |
| 129 updateNetworkState(isNowOnline) { |
| 130 if (isNowOnline) { |
| 131 this._connectivityIcon.type = 'green-ball'; |
| 132 this._connectivityIcon.textContent = WebInspector.UIString('Online'); |
| 133 } else { |
| 134 this._connectivityIcon.type = 'red-ball'; |
| 135 this._connectivityIcon.textContent = WebInspector.UIString('Offline'); |
| 136 } |
| 137 } |
| 138 |
| 139 _update() { |
| 140 this._model.requestApplicationCache(this._frameId, this._updateCallback.bind
(this)); |
| 141 } |
| 142 |
| 143 /** |
| 144 * @param {?ApplicationCacheAgent.ApplicationCache} applicationCache |
| 145 */ |
| 146 _updateCallback(applicationCache) { |
| 147 if (!applicationCache || !applicationCache.manifestURL) { |
| 148 delete this._manifest; |
| 149 delete this._creationTime; |
| 150 delete this._updateTime; |
| 151 delete this._size; |
| 152 delete this._resources; |
| 153 |
| 154 this._emptyWidget.show(this.element); |
| 155 this._deleteButton.setVisible(false); |
| 156 if (this._dataGrid) |
| 157 this._dataGrid.element.classList.add('hidden'); |
| 158 return; |
| 159 } |
| 160 // FIXME: are these variables needed anywhere else? |
| 161 this._manifest = applicationCache.manifestURL; |
| 162 this._creationTime = applicationCache.creationTime; |
| 163 this._updateTime = applicationCache.updateTime; |
| 164 this._size = applicationCache.size; |
| 165 this._resources = applicationCache.resources; |
| 166 |
| 167 if (!this._dataGrid) |
| 168 this._createDataGrid(); |
| 169 |
| 170 this._populateDataGrid(); |
| 171 this._dataGrid.autoSizeColumns(20, 80); |
| 172 this._dataGrid.element.classList.remove('hidden'); |
| 173 this._emptyWidget.detach(); |
| 174 this._deleteButton.setVisible(true); |
| 175 |
| 176 // FIXME: For Chrome, put creationTime and updateTime somewhere. |
| 177 // NOTE: localizedString has not yet been added. |
| 178 // WebInspector.UIString("(%s) Created: %s Updated: %s", this._size, this._c
reationTime, this._updateTime); |
| 179 } |
| 180 |
| 181 _createDataGrid() { |
| 182 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor>} */
([ |
| 183 { |
| 184 id: 'resource', |
| 185 title: WebInspector.UIString('Resource'), |
| 186 sort: WebInspector.DataGrid.Order.Ascending, |
| 187 sortable: true |
| 188 }, |
| 189 {id: 'type', title: WebInspector.UIString('Type'), sortable: true}, |
| 190 {id: 'size', title: WebInspector.UIString('Size'), align: WebInspector.Dat
aGrid.Align.Right, sortable: true} |
| 191 ]); |
| 192 this._dataGrid = new WebInspector.DataGrid(columns); |
| 193 this._dataGrid.asWidget().show(this.element); |
| 194 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged,
this._populateDataGrid, this); |
| 195 } |
| 196 |
| 197 _populateDataGrid() { |
| 198 var selectedResource = this._dataGrid.selectedNode ? this._dataGrid.selected
Node.resource : null; |
| 199 var sortDirection = this._dataGrid.isSortOrderAscending() ? 1 : -1; |
| 200 |
| 201 function numberCompare(field, resource1, resource2) { |
| 202 return sortDirection * (resource1[field] - resource2[field]); |
| 203 } |
| 204 function localeCompare(field, resource1, resource2) { |
| 205 return sortDirection * (resource1[field] + '').localeCompare(resource2[fie
ld] + ''); |
| 206 } |
| 207 |
| 208 var comparator; |
| 209 switch (this._dataGrid.sortColumnId()) { |
| 210 case 'resource': |
| 211 comparator = localeCompare.bind(null, 'url'); |
| 212 break; |
| 213 case 'type': |
| 214 comparator = localeCompare.bind(null, 'type'); |
| 215 break; |
| 216 case 'size': |
| 217 comparator = numberCompare.bind(null, 'size'); |
| 218 break; |
| 219 default: |
| 220 localeCompare.bind(null, 'resource'); // FIXME: comparator = ? |
| 221 } |
| 222 |
| 223 this._resources.sort(comparator); |
| 224 this._dataGrid.rootNode().removeChildren(); |
| 225 |
| 226 var nodeToSelect; |
| 227 for (var i = 0; i < this._resources.length; ++i) { |
| 228 var data = {}; |
| 229 var resource = this._resources[i]; |
| 230 data.resource = resource.url; |
| 231 data.type = resource.type; |
| 232 data.size = Number.bytesToString(resource.size); |
| 233 var node = new WebInspector.DataGridNode(data); |
| 234 node.resource = resource; |
| 235 node.selectable = true; |
| 236 this._dataGrid.rootNode().appendChild(node); |
| 237 if (resource === selectedResource) { |
| 238 nodeToSelect = node; |
| 239 nodeToSelect.selected = true; |
| 240 } |
| 241 } |
| 242 |
| 243 if (!nodeToSelect && this._dataGrid.rootNode().children.length) |
| 244 this._dataGrid.rootNode().children[0].selected = true; |
| 245 } |
| 246 |
| 247 _deleteButtonClicked(event) { |
| 248 if (!this._dataGrid || !this._dataGrid.selectedNode) |
| 249 return; |
| 250 |
| 251 // FIXME: Delete Button semantics are not yet defined. (Delete a single, or
all?) |
| 252 this._deleteCallback(this._dataGrid.selectedNode); |
| 253 } |
| 254 |
| 255 _deleteCallback(node) { |
| 256 // FIXME: Should we delete a single (selected) resource or all resources? |
| 257 // InspectorBackend.deleteCachedResource(...) |
| 258 // this._update(); |
| 259 } |
61 }; | 260 }; |
62 | |
63 WebInspector.ApplicationCacheItemsView.prototype = { | |
64 /** | |
65 * @override | |
66 * @return {!Array.<!WebInspector.ToolbarItem>} | |
67 */ | |
68 syncToolbarItems: function() | |
69 { | |
70 return [ | |
71 this._deleteButton, | |
72 new WebInspector.ToolbarItem(this._connectivityIcon), | |
73 new WebInspector.ToolbarSeparator(), | |
74 new WebInspector.ToolbarItem(this._statusIcon) | |
75 ]; | |
76 }, | |
77 | |
78 wasShown: function() | |
79 { | |
80 this._maybeUpdate(); | |
81 }, | |
82 | |
83 willHide: function() | |
84 { | |
85 this._deleteButton.setVisible(false); | |
86 }, | |
87 | |
88 _maybeUpdate: function() | |
89 { | |
90 if (!this.isShowing() || !this._viewDirty) | |
91 return; | |
92 | |
93 this._update(); | |
94 this._viewDirty = false; | |
95 }, | |
96 | |
97 _markDirty: function() | |
98 { | |
99 this._viewDirty = true; | |
100 }, | |
101 | |
102 /** | |
103 * @param {number} status | |
104 */ | |
105 updateStatus: function(status) | |
106 { | |
107 var oldStatus = this._status; | |
108 this._status = status; | |
109 | |
110 var statusInformation = {}; | |
111 // We should never have UNCACHED status, since we remove frames with UNC
ACHED application cache status from the tree. | |
112 statusInformation[applicationCache.UNCACHED] = { type: "red-ball", te
xt: "UNCACHED" }; | |
113 statusInformation[applicationCache.IDLE] = { type: "green-ball",
text: "IDLE" }; | |
114 statusInformation[applicationCache.CHECKING] = { type: "orange-ball",
text: "CHECKING" }; | |
115 statusInformation[applicationCache.DOWNLOADING] = { type: "orange-ball",
text: "DOWNLOADING" }; | |
116 statusInformation[applicationCache.UPDATEREADY] = { type: "green-ball",
text: "UPDATEREADY" }; | |
117 statusInformation[applicationCache.OBSOLETE] = { type: "red-ball",
text: "OBSOLETE" }; | |
118 | |
119 var info = statusInformation[status] || statusInformation[applicationCac
he.UNCACHED]; | |
120 | |
121 this._statusIcon.type = info.type; | |
122 this._statusIcon.textContent = info.text; | |
123 | |
124 if (this.isShowing() && this._status === applicationCache.IDLE && (oldSt
atus === applicationCache.UPDATEREADY || !this._resources)) | |
125 this._markDirty(); | |
126 this._maybeUpdate(); | |
127 }, | |
128 | |
129 /** | |
130 * @param {boolean} isNowOnline | |
131 */ | |
132 updateNetworkState: function(isNowOnline) | |
133 { | |
134 if (isNowOnline) { | |
135 this._connectivityIcon.type = "green-ball"; | |
136 this._connectivityIcon.textContent = WebInspector.UIString("Online")
; | |
137 } else { | |
138 this._connectivityIcon.type = "red-ball"; | |
139 this._connectivityIcon.textContent = WebInspector.UIString("Offline"
); | |
140 } | |
141 }, | |
142 | |
143 _update: function() | |
144 { | |
145 this._model.requestApplicationCache(this._frameId, this._updateCallback.
bind(this)); | |
146 }, | |
147 | |
148 /** | |
149 * @param {?ApplicationCacheAgent.ApplicationCache} applicationCache | |
150 */ | |
151 _updateCallback: function(applicationCache) | |
152 { | |
153 if (!applicationCache || !applicationCache.manifestURL) { | |
154 delete this._manifest; | |
155 delete this._creationTime; | |
156 delete this._updateTime; | |
157 delete this._size; | |
158 delete this._resources; | |
159 | |
160 this._emptyWidget.show(this.element); | |
161 this._deleteButton.setVisible(false); | |
162 if (this._dataGrid) | |
163 this._dataGrid.element.classList.add("hidden"); | |
164 return; | |
165 } | |
166 // FIXME: are these variables needed anywhere else? | |
167 this._manifest = applicationCache.manifestURL; | |
168 this._creationTime = applicationCache.creationTime; | |
169 this._updateTime = applicationCache.updateTime; | |
170 this._size = applicationCache.size; | |
171 this._resources = applicationCache.resources; | |
172 | |
173 if (!this._dataGrid) | |
174 this._createDataGrid(); | |
175 | |
176 this._populateDataGrid(); | |
177 this._dataGrid.autoSizeColumns(20, 80); | |
178 this._dataGrid.element.classList.remove("hidden"); | |
179 this._emptyWidget.detach(); | |
180 this._deleteButton.setVisible(true); | |
181 | |
182 // FIXME: For Chrome, put creationTime and updateTime somewhere. | |
183 // NOTE: localizedString has not yet been added. | |
184 // WebInspector.UIString("(%s) Created: %s Updated: %s", this._size, thi
s._creationTime, this._updateTime); | |
185 }, | |
186 | |
187 _createDataGrid: function() | |
188 { | |
189 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor>
} */ ([ | |
190 {id: "resource", title: WebInspector.UIString("Resource"), sort: Web
Inspector.DataGrid.Order.Ascending, sortable: true}, | |
191 {id: "type", title: WebInspector.UIString("Type"), sortable: true}, | |
192 {id: "size", title: WebInspector.UIString("Size"), align: WebInspect
or.DataGrid.Align.Right, sortable: true} | |
193 ]); | |
194 this._dataGrid = new WebInspector.DataGrid(columns); | |
195 this._dataGrid.asWidget().show(this.element); | |
196 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChan
ged, this._populateDataGrid, this); | |
197 }, | |
198 | |
199 _populateDataGrid: function() | |
200 { | |
201 var selectedResource = this._dataGrid.selectedNode ? this._dataGrid.sele
ctedNode.resource : null; | |
202 var sortDirection = this._dataGrid.isSortOrderAscending() ? 1 : -1; | |
203 | |
204 function numberCompare(field, resource1, resource2) | |
205 { | |
206 return sortDirection * (resource1[field] - resource2[field]); | |
207 } | |
208 function localeCompare(field, resource1, resource2) | |
209 { | |
210 return sortDirection * (resource1[field] + "").localeCompare(resourc
e2[field] + ""); | |
211 } | |
212 | |
213 var comparator; | |
214 switch (this._dataGrid.sortColumnId()) { | |
215 case "resource": comparator = localeCompare.bind(null, "url"); break; | |
216 case "type": comparator = localeCompare.bind(null, "type"); break; | |
217 case "size": comparator = numberCompare.bind(null, "size"); break; | |
218 default: localeCompare.bind(null, "resource"); // FIXME: comparator = ? | |
219 } | |
220 | |
221 this._resources.sort(comparator); | |
222 this._dataGrid.rootNode().removeChildren(); | |
223 | |
224 var nodeToSelect; | |
225 for (var i = 0; i < this._resources.length; ++i) { | |
226 var data = {}; | |
227 var resource = this._resources[i]; | |
228 data.resource = resource.url; | |
229 data.type = resource.type; | |
230 data.size = Number.bytesToString(resource.size); | |
231 var node = new WebInspector.DataGridNode(data); | |
232 node.resource = resource; | |
233 node.selectable = true; | |
234 this._dataGrid.rootNode().appendChild(node); | |
235 if (resource === selectedResource) { | |
236 nodeToSelect = node; | |
237 nodeToSelect.selected = true; | |
238 } | |
239 } | |
240 | |
241 if (!nodeToSelect && this._dataGrid.rootNode().children.length) | |
242 this._dataGrid.rootNode().children[0].selected = true; | |
243 }, | |
244 | |
245 _deleteButtonClicked: function(event) | |
246 { | |
247 if (!this._dataGrid || !this._dataGrid.selectedNode) | |
248 return; | |
249 | |
250 // FIXME: Delete Button semantics are not yet defined. (Delete a single,
or all?) | |
251 this._deleteCallback(this._dataGrid.selectedNode); | |
252 }, | |
253 | |
254 _deleteCallback: function(node) | |
255 { | |
256 // FIXME: Should we delete a single (selected) resource or all resources
? | |
257 // InspectorBackend.deleteCachedResource(...) | |
258 // this._update(); | |
259 }, | |
260 | |
261 __proto__: WebInspector.SimpleView.prototype | |
262 }; | |
263 | |
OLD | NEW |