1/* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2009 Joseph Pecoraro 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30WebInspector.CookieItemsView = function(treeElement, cookieDomain) 31{ 32 WebInspector.View.call(this); 33 34 this.element.addStyleClass("storage-view"); 35 this.element.addStyleClass("table"); 36 37 this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); 38 this.deleteButton.visible = false; 39 this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); 40 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 this._treeElement = treeElement; 45 this._cookieDomain = cookieDomain; 46 47 this._emptyMsgElement = document.createElement("div"); 48 this._emptyMsgElement.className = "storage-table-empty"; 49 this._emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies."); 50 this.element.appendChild(this._emptyMsgElement); 51} 52 53WebInspector.CookieItemsView.prototype = { 54 get statusBarItems() 55 { 56 return [this.refreshButton.element, this.deleteButton.element]; 57 }, 58 59 show: function(parentElement) 60 { 61 WebInspector.View.prototype.show.call(this, parentElement); 62 this._update(); 63 }, 64 65 hide: function() 66 { 67 WebInspector.View.prototype.hide.call(this); 68 this.deleteButton.visible = false; 69 }, 70 71 _update: function() 72 { 73 WebInspector.Cookies.getCookiesAsync(this._updateWithCookies.bind(this)); 74 }, 75 76 _updateWithCookies: function(allCookies, isAdvanced) 77 { 78 if (isAdvanced) 79 this._filterCookiesForDomain(allCookies); 80 else 81 this._cookies = allCookies; 82 83 if (!this._cookies.length) { 84 // Nothing to show. 85 this._emptyMsgElement.removeStyleClass("hidden"); 86 this.deleteButton.visible = false; 87 if (this._dataGrid) 88 this._dataGrid.element.addStyleClass("hidden"); 89 return; 90 } 91 92 if (!this._dataGrid) { 93 if (isAdvanced) { 94 this._createDataGrid(); 95 this._populateDataGrid(); 96 this._dataGrid.autoSizeColumns(6, 33); 97 this._treeElement.subtitle = String.sprintf(WebInspector.UIString("%d cookies (%s)"), this._cookies.length, 98 Number.bytesToString(this._totalSize, WebInspector.UIString)); 99 } else { 100 this._createSimpleDataGrid(); 101 this._populateSimpleDataGrid(); 102 this._dataGrid.autoSizeColumns(20, 80); 103 } 104 } else { 105 if (isAdvanced) 106 this._populateDataGrid(); 107 else 108 this._populateSimpleDataGrid(); 109 } 110 111 this._dataGrid.element.removeStyleClass("hidden"); 112 this._emptyMsgElement.addStyleClass("hidden"); 113 if (isAdvanced) 114 this.deleteButton.visible = true; 115 }, 116 117 _filterCookiesForDomain: function(allCookies) 118 { 119 this._cookies = []; 120 var resourceURLsForDocumentURL = []; 121 this._totalSize = 0; 122 123 for (var id in WebInspector.resources) { 124 var resource = WebInspector.resources[id]; 125 var match = resource.documentURL.match(WebInspector.URLRegExp); 126 if (match && match[2] === this._cookieDomain) 127 resourceURLsForDocumentURL.push(resource.url); 128 } 129 130 for (var i = 0; i < allCookies.length; ++i) { 131 var pushed = false; 132 var size = allCookies[i].size; 133 for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) { 134 var resourceURL = resourceURLsForDocumentURL[j]; 135 if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) { 136 this._totalSize += size; 137 if (!pushed) { 138 pushed = true; 139 this._cookies.push(allCookies[i]); 140 } 141 } 142 } 143 } 144 }, 145 146 _createDataGrid: function() 147 { 148 var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} }; 149 columns[0].title = WebInspector.UIString("Name"); 150 columns[0].sortable = true; 151 columns[1].title = WebInspector.UIString("Value"); 152 columns[1].sortable = true; 153 columns[2].title = WebInspector.UIString("Domain"); 154 columns[2].sortable = true; 155 columns[3].title = WebInspector.UIString("Path"); 156 columns[3].sortable = true; 157 columns[4].title = WebInspector.UIString("Expires"); 158 columns[4].sortable = true; 159 columns[5].title = WebInspector.UIString("Size"); 160 columns[5].aligned = "right"; 161 columns[5].sortable = true; 162 columns[6].title = WebInspector.UIString("HTTP"); 163 columns[6].aligned = "centered"; 164 columns[6].sortable = true; 165 columns[7].title = WebInspector.UIString("Secure"); 166 columns[7].aligned = "centered"; 167 columns[7].sortable = true; 168 169 this._dataGrid = new WebInspector.DataGrid(columns, null, this._deleteCookieCallback.bind(this)); 170 this._dataGrid.addEventListener("sorting changed", this._populateDataGrid, this); 171 this.element.appendChild(this._dataGrid.element); 172 this._dataGrid.updateWidths(); 173 }, 174 175 _populateDataGrid: function() 176 { 177 var selectedCookie = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.cookie : null; 178 var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1; 179 180 function localeCompare(field, cookie1, cookie2) 181 { 182 return sortDirection * (cookie1[field] + "").localeCompare(cookie2[field] + "") 183 } 184 185 function numberCompare(field, cookie1, cookie2) 186 { 187 return sortDirection * (cookie1[field] - cookie2[field]); 188 } 189 190 function expiresCompare(cookie1, cookie2) 191 { 192 if (cookie1.session !== cookie2.session) 193 return sortDirection * (cookie1.session ? 1 : -1); 194 195 if (cookie1.session) 196 return 0; 197 198 return sortDirection * (cookie1.expires - cookie2.expires); 199 } 200 201 var comparator; 202 switch (parseInt(this._dataGrid.sortColumnIdentifier)) { 203 case 0: comparator = localeCompare.bind(this, "name"); break; 204 case 1: comparator = localeCompare.bind(this, "value"); break; 205 case 2: comparator = localeCompare.bind(this, "domain"); break; 206 case 3: comparator = localeCompare.bind(this, "path"); break; 207 case 4: comparator = expiresCompare; break; 208 case 5: comparator = numberCompare.bind(this, "size"); break; 209 case 6: comparator = localeCompare.bind(this, "httpOnly"); break; 210 case 7: comparator = localeCompare.bind(this, "secure"); break; 211 default: localeCompare.bind(this, "name"); 212 } 213 214 this._cookies.sort(comparator); 215 216 this._dataGrid.removeChildren(); 217 var nodeToSelect; 218 for (var i = 0; i < this._cookies.length; ++i) { 219 var data = {}; 220 var cookie = this._cookies[i]; 221 data[0] = cookie.name; 222 data[1] = cookie.value; 223 data[2] = cookie.domain; 224 data[3] = cookie.path; 225 data[4] = (cookie.session ? WebInspector.UIString("Session") : new Date(cookie.expires).toGMTString()); 226 data[5] = Number.bytesToString(cookie.size, WebInspector.UIString); 227 data[6] = (cookie.httpOnly ? "\u2713" : ""); // Checkmark 228 data[7] = (cookie.secure ? "\u2713" : ""); // Checkmark 229 230 var node = new WebInspector.DataGridNode(data); 231 node.cookie = cookie; 232 node.selectable = true; 233 this._dataGrid.appendChild(node); 234 if (cookie === selectedCookie) 235 nodeToSelect = node; 236 } 237 if (nodeToSelect) 238 nodeToSelect.selected = true; 239 else 240 this._dataGrid.children[0].selected = true; 241 }, 242 243 _createSimpleDataGrid: function() 244 { 245 var columns = {}; 246 columns[0] = {}; 247 columns[1] = {}; 248 columns[0].title = WebInspector.UIString("Name"); 249 columns[1].title = WebInspector.UIString("Value"); 250 251 this._dataGrid = new WebInspector.DataGrid(columns); 252 this.element.appendChild(this._dataGrid.element); 253 this._dataGrid.updateWidths(); 254 }, 255 256 _populateSimpleDataGrid: function() 257 { 258 var cookies = this._cookies; 259 this._dataGrid.removeChildren(); 260 var addedCookies = {}; 261 for (var i = 0; i < cookies.length; ++i) { 262 if (addedCookies[cookies[i].name]) 263 continue; 264 addedCookies[cookies[i].name] = true; 265 var data = {}; 266 data[0] = cookies[i].name; 267 data[1] = cookies[i].value; 268 269 var node = new WebInspector.DataGridNode(data, false); 270 node.selectable = true; 271 this._dataGrid.appendChild(node); 272 } 273 this._dataGrid.children[0].selected = true; 274 }, 275 276 resize: function() 277 { 278 if (this._dataGrid) 279 this._dataGrid.updateWidths(); 280 }, 281 282 _deleteButtonClicked: function(event) 283 { 284 if (!this._dataGrid || !this._dataGrid.selectedNode) 285 return; 286 287 this._deleteCookieCallback(this._dataGrid.selectedNode); 288 }, 289 290 _deleteCookieCallback: function(node) 291 { 292 var cookie = node.cookie; 293 InspectorBackend.deleteCookie(cookie.name, this._cookieDomain); 294 this._update(); 295 }, 296 297 _refreshButtonClicked: function(event) 298 { 299 this._update(); 300 } 301} 302 303WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype; 304