1 /* 2 * Copyright (C) 2007, 2008 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 30 WebInspector.StoragePanel = function(database) 31 { 32 WebInspector.Panel.call(this); 33 34 this.createSidebar(); 35 36 this.databasesListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("DATABASES"), {}, true); 37 this.sidebarTree.appendChild(this.databasesListTreeElement); 38 this.databasesListTreeElement.expand(); 39 40 this.localStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("LOCAL STORAGE"), {}, true); 41 this.sidebarTree.appendChild(this.localStorageListTreeElement); 42 this.localStorageListTreeElement.expand(); 43 44 this.sessionStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("SESSION STORAGE"), {}, true); 45 this.sidebarTree.appendChild(this.sessionStorageListTreeElement); 46 this.sessionStorageListTreeElement.expand(); 47 48 this.cookieListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("COOKIES"), {}, true); 49 this.sidebarTree.appendChild(this.cookieListTreeElement); 50 this.cookieListTreeElement.expand(); 51 52 this.storageViews = document.createElement("div"); 53 this.storageViews.id = "storage-views"; 54 this.element.appendChild(this.storageViews); 55 56 this.storageViewStatusBarItemsContainer = document.createElement("div"); 57 this.storageViewStatusBarItemsContainer.id = "storage-view-status-bar-items"; 58 59 this.reset(); 60 } 61 62 WebInspector.StoragePanel.prototype = { 63 toolbarItemClass: "storage", 64 65 get toolbarItemLabel() 66 { 67 return WebInspector.UIString("Storage"); 68 }, 69 70 get statusBarItems() 71 { 72 return [this.storageViewStatusBarItemsContainer]; 73 }, 74 75 reset: function() 76 { 77 if (this._databases) { 78 var databasesLength = this._databases.length; 79 for (var i = 0; i < databasesLength; ++i) { 80 var database = this._databases[i]; 81 82 delete database._tableViews; 83 delete database._queryView; 84 } 85 } 86 87 this._databases = []; 88 89 if (this._domStorage) { 90 var domStorageLength = this._domStorage.length; 91 for (var i = 0; i < domStorageLength; ++i) { 92 var domStorage = this._domStorage[i]; 93 94 delete domStorage._domStorageView; 95 } 96 } 97 98 this._domStorage = []; 99 100 this._cookieViews = {}; 101 102 this.databasesListTreeElement.removeChildren(); 103 this.localStorageListTreeElement.removeChildren(); 104 this.sessionStorageListTreeElement.removeChildren(); 105 this.cookieListTreeElement.removeChildren(); 106 107 this.storageViews.removeChildren(); 108 109 this.storageViewStatusBarItemsContainer.removeChildren(); 110 111 if (this.sidebarTree.selectedTreeElement) 112 this.sidebarTree.selectedTreeElement.deselect(); 113 }, 114 115 addDatabase: function(database) 116 { 117 this._databases.push(database); 118 119 var databaseTreeElement = new WebInspector.DatabaseSidebarTreeElement(database); 120 database._databasesTreeElement = databaseTreeElement; 121 this.databasesListTreeElement.appendChild(databaseTreeElement); 122 }, 123 124 addCookieDomain: function(domain) 125 { 126 var cookieDomainTreeElement = new WebInspector.CookieSidebarTreeElement(domain); 127 this.cookieListTreeElement.appendChild(cookieDomainTreeElement); 128 }, 129 130 addDOMStorage: function(domStorage) 131 { 132 this._domStorage.push(domStorage); 133 var domStorageTreeElement = new WebInspector.DOMStorageSidebarTreeElement(domStorage, (domStorage.isLocalStorage ? "local-storage" : "session-storage")); 134 domStorage._domStorageTreeElement = domStorageTreeElement; 135 if (domStorage.isLocalStorage) 136 this.localStorageListTreeElement.appendChild(domStorageTreeElement); 137 else 138 this.sessionStorageListTreeElement.appendChild(domStorageTreeElement); 139 }, 140 141 selectDatabase: function(databaseId) 142 { 143 var database; 144 for (var i = 0, len = this._databases.length; i < len; ++i) { 145 database = this._databases[i]; 146 if (database.id === databaseId) { 147 this.showDatabase(database); 148 database._databasesTreeElement.select(); 149 return; 150 } 151 } 152 }, 153 154 selectDOMStorage: function(storageId) 155 { 156 var domStorage = this._domStorageForId(storageId); 157 if (domStorage) { 158 this.showDOMStorage(domStorage); 159 domStorage._domStorageTreeElement.select(); 160 } 161 }, 162 163 showDatabase: function(database, tableName) 164 { 165 if (!database) 166 return; 167 168 if (this.visibleView) 169 this.visibleView.hide(); 170 171 var view; 172 if (tableName) { 173 if (!("_tableViews" in database)) 174 database._tableViews = {}; 175 view = database._tableViews[tableName]; 176 if (!view) { 177 view = new WebInspector.DatabaseTableView(database, tableName); 178 database._tableViews[tableName] = view; 179 } 180 } else { 181 view = database._queryView; 182 if (!view) { 183 view = new WebInspector.DatabaseQueryView(database); 184 database._queryView = view; 185 } 186 } 187 188 view.show(this.storageViews); 189 190 this.visibleView = view; 191 192 this.storageViewStatusBarItemsContainer.removeChildren(); 193 var statusBarItems = view.statusBarItems || []; 194 for (var i = 0; i < statusBarItems.length; ++i) 195 this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i].element); 196 }, 197 198 showDOMStorage: function(domStorage) 199 { 200 if (!domStorage) 201 return; 202 203 if (this.visibleView) 204 this.visibleView.hide(); 205 206 var view; 207 view = domStorage._domStorageView; 208 if (!view) { 209 view = new WebInspector.DOMStorageItemsView(domStorage); 210 domStorage._domStorageView = view; 211 } 212 213 view.show(this.storageViews); 214 215 this.visibleView = view; 216 217 this.storageViewStatusBarItemsContainer.removeChildren(); 218 var statusBarItems = view.statusBarItems; 219 for (var i = 0; i < statusBarItems.length; ++i) 220 this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]); 221 }, 222 223 showCookies: function(treeElement, cookieDomain) 224 { 225 if (this.visibleView) 226 this.visibleView.hide(); 227 228 var view = this._cookieViews[cookieDomain]; 229 if (!view) { 230 view = new WebInspector.CookieItemsView(treeElement, cookieDomain); 231 this._cookieViews[cookieDomain] = view; 232 } 233 234 view.show(this.storageViews); 235 236 this.visibleView = view; 237 238 this.storageViewStatusBarItemsContainer.removeChildren(); 239 var statusBarItems = view.statusBarItems; 240 for (var i = 0; i < statusBarItems.length; ++i) 241 this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]); 242 }, 243 244 closeVisibleView: function() 245 { 246 if (this.visibleView) 247 this.visibleView.hide(); 248 delete this.visibleView; 249 }, 250 251 updateDatabaseTables: function(database) 252 { 253 if (!database || !database._databasesTreeElement) 254 return; 255 256 database._databasesTreeElement.shouldRefreshChildren = true; 257 258 if (!("_tableViews" in database)) 259 return; 260 261 var tableNamesHash = {}; 262 var self = this; 263 function tableNamesCallback(tableNames) 264 { 265 var tableNamesLength = tableNames.length; 266 for (var i = 0; i < tableNamesLength; ++i) 267 tableNamesHash[tableNames[i]] = true; 268 269 for (var tableName in database._tableViews) { 270 if (!(tableName in tableNamesHash)) { 271 if (self.visibleView === database._tableViews[tableName]) 272 self.closeVisibleView(); 273 delete database._tableViews[tableName]; 274 } 275 } 276 } 277 database.getTableNames(tableNamesCallback); 278 }, 279 280 dataGridForResult: function(rows) 281 { 282 if (!rows.length) 283 return null; 284 285 var columns = {}; 286 var numColumns = 0; 287 288 for (var columnIdentifier in rows[0]) { 289 var column = {}; 290 column.width = columnIdentifier.length; 291 column.title = columnIdentifier; 292 293 columns[columnIdentifier] = column; 294 ++numColumns; 295 } 296 297 var nodes = []; 298 var length = rows.length; 299 for (var i = 0; i < length; ++i) { 300 var data = {}; 301 302 var row = rows[i]; 303 for (var columnIdentifier in row) 304 data[columnIdentifier] = row[columnIdentifier]; 305 306 var node = new WebInspector.DataGridNode(data, false); 307 node.selectable = false; 308 nodes.push(node); 309 } 310 311 var dataGrid = new WebInspector.DataGrid(columns); 312 var length = nodes.length; 313 for (var i = 0; i < length; ++i) 314 dataGrid.appendChild(nodes[i]); 315 316 return dataGrid; 317 }, 318 319 updateDOMStorage: function(storageId) 320 { 321 var domStorage = this._domStorageForId(storageId); 322 if (!domStorage) 323 return; 324 325 var view = domStorage._domStorageView; 326 if (this.visibleView && view === this.visibleView) 327 domStorage._domStorageView.update(); 328 }, 329 330 _domStorageForId: function(storageId) 331 { 332 if (!this._domStorage) 333 return null; 334 var domStorageLength = this._domStorage.length; 335 for (var i = 0; i < domStorageLength; ++i) { 336 var domStorage = this._domStorage[i]; 337 if (domStorage.id == storageId) 338 return domStorage; 339 } 340 return null; 341 }, 342 343 updateMainViewWidth: function(width) 344 { 345 this.storageViews.style.left = width + "px"; 346 this.storageViewStatusBarItemsContainer.style.left = width + "px"; 347 this.resize(); 348 } 349 } 350 351 WebInspector.StoragePanel.prototype.__proto__ = WebInspector.Panel.prototype; 352 353 WebInspector.DatabaseSidebarTreeElement = function(database) 354 { 355 this.database = database; 356 357 WebInspector.SidebarTreeElement.call(this, "database-sidebar-tree-item", "", "", database, true); 358 359 this.refreshTitles(); 360 } 361 362 WebInspector.DatabaseSidebarTreeElement.prototype = { 363 onselect: function() 364 { 365 WebInspector.panels.storage.showDatabase(this.database); 366 }, 367 368 oncollapse: function() 369 { 370 // Request a refresh after every collapse so the next 371 // expand will have an updated table list. 372 this.shouldRefreshChildren = true; 373 }, 374 375 onpopulate: function() 376 { 377 this.removeChildren(); 378 379 var self = this; 380 function tableNamesCallback(tableNames) 381 { 382 var tableNamesLength = tableNames.length; 383 for (var i = 0; i < tableNamesLength; ++i) 384 self.appendChild(new WebInspector.SidebarDatabaseTableTreeElement(self.database, tableNames[i])); 385 } 386 this.database.getTableNames(tableNamesCallback); 387 }, 388 389 get mainTitle() 390 { 391 return this.database.name; 392 }, 393 394 set mainTitle(x) 395 { 396 // Do nothing. 397 }, 398 399 get subtitle() 400 { 401 return this.database.displayDomain; 402 }, 403 404 set subtitle(x) 405 { 406 // Do nothing. 407 } 408 } 409 410 WebInspector.DatabaseSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; 411 412 WebInspector.SidebarDatabaseTableTreeElement = function(database, tableName) 413 { 414 this.database = database; 415 this.tableName = tableName; 416 417 WebInspector.SidebarTreeElement.call(this, "database-table-sidebar-tree-item small", tableName, "", null, false); 418 } 419 420 WebInspector.SidebarDatabaseTableTreeElement.prototype = { 421 onselect: function() 422 { 423 WebInspector.panels.storage.showDatabase(this.database, this.tableName); 424 } 425 } 426 427 WebInspector.SidebarDatabaseTableTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; 428 429 WebInspector.DOMStorageSidebarTreeElement = function(domStorage, className) 430 { 431 432 this.domStorage = domStorage; 433 434 WebInspector.SidebarTreeElement.call(this, "domstorage-sidebar-tree-item " + className, domStorage, "", null, false); 435 436 this.refreshTitles(); 437 } 438 439 WebInspector.DOMStorageSidebarTreeElement.prototype = { 440 onselect: function() 441 { 442 WebInspector.panels.storage.showDOMStorage(this.domStorage); 443 }, 444 445 get mainTitle() 446 { 447 return this.domStorage.domain ? this.domStorage.domain : WebInspector.UIString("Local Files"); 448 }, 449 450 set mainTitle(x) 451 { 452 // Do nothing. 453 }, 454 455 get subtitle() 456 { 457 return ""; //this.database.displayDomain; 458 }, 459 460 set subtitle(x) 461 { 462 // Do nothing. 463 } 464 } 465 466 WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; 467 468 WebInspector.CookieSidebarTreeElement = function(cookieDomain) 469 { 470 WebInspector.SidebarTreeElement.call(this, "cookie-sidebar-tree-item", cookieDomain, "", null, false); 471 this._cookieDomain = cookieDomain; 472 this._subtitle = ""; 473 474 this.refreshTitles(); 475 } 476 477 WebInspector.CookieSidebarTreeElement.prototype = { 478 onselect: function() 479 { 480 WebInspector.panels.storage.showCookies(this, this._cookieDomain); 481 }, 482 483 get mainTitle() 484 { 485 return this._cookieDomain ? this._cookieDomain : WebInspector.UIString("Local Files"); 486 }, 487 488 set mainTitle(x) 489 { 490 // Do nothing. 491 }, 492 493 get subtitle() 494 { 495 return this._subtitle; 496 }, 497 498 set subtitle(x) 499 { 500 this._subtitle = x; 501 this.refreshTitles(); 502 } 503 } 504 505 WebInspector.CookieSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; 506