Home | History | Annotate | Download | only in components
      1 /*
      2  * Copyright (C) 2009 Apple Inc.  All rights reserved.
      3  * Copyright (C) 2009 Joseph Pecoraro
      4  * Copyright (C) 2010 Google Inc. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  * 1.  Redistributions of source code must retain the above copyright
     11  *     notice, this list of conditions and the following disclaimer.
     12  * 2.  Redistributions in binary form must reproduce the above copyright
     13  *     notice, this list of conditions and the following disclaimer in the
     14  *     documentation and/or other materials provided with the distribution.
     15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     16  *     its contributors may be used to endorse or promote products derived
     17  *     from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @extends {WebInspector.VBox}
     34  * @param {boolean} expandable
     35  * @param {function()=} refreshCallback
     36  * @param {function()=} selectedCallback
     37  */
     38 WebInspector.CookiesTable = function(expandable, refreshCallback, selectedCallback)
     39 {
     40     WebInspector.VBox.call(this);
     41 
     42     var readOnly = expandable;
     43     this._refreshCallback = refreshCallback;
     44 
     45     var columns = [
     46         {id: "name", title: WebInspector.UIString("Name"), sortable: true, disclosure: expandable, sort: WebInspector.DataGrid.Order.Ascending, longText: true, weight: 24},
     47         {id: "value", title: WebInspector.UIString("Value"), sortable: true, longText: true, weight: 34},
     48         {id: "domain", title: WebInspector.UIString("Domain"), sortable: true, weight: 7},
     49         {id: "path", title: WebInspector.UIString("Path"), sortable: true, weight: 7},
     50         {id: "expires", title: WebInspector.UIString("Expires / Max-Age"), sortable: true, weight: 7},
     51         {id: "size", title: WebInspector.UIString("Size"), sortable: true, align: WebInspector.DataGrid.Align.Right, weight: 7},
     52         {id: "httpOnly", title: WebInspector.UIString("HTTP"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7},
     53         {id: "secure", title: WebInspector.UIString("Secure"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7}
     54     ];
     55 
     56     if (readOnly)
     57         this._dataGrid = new WebInspector.DataGrid(columns);
     58     else
     59         this._dataGrid = new WebInspector.DataGrid(columns, undefined, this._onDeleteCookie.bind(this), refreshCallback, this._onContextMenu.bind(this));
     60 
     61     this._dataGrid.setName("cookiesTable");
     62     this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._rebuildTable, this);
     63 
     64     if (selectedCallback)
     65         this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, selectedCallback, this);
     66 
     67     this._nextSelectedCookie = /** @type {?WebInspector.Cookie} */ (null);
     68 
     69     this._dataGrid.show(this.element);
     70     this._data = [];
     71 }
     72 
     73 WebInspector.CookiesTable.prototype = {
     74     /**
     75      * @param {?string} domain
     76      */
     77     _clearAndRefresh: function(domain)
     78     {
     79         this.clear(domain);
     80         this._refresh();
     81     },
     82 
     83     /**
     84      * @param {!WebInspector.ContextMenu} contextMenu
     85      * @param {!WebInspector.DataGridNode} node
     86      */
     87     _onContextMenu: function(contextMenu, node)
     88     {
     89         if (node === this._dataGrid.creationNode)
     90             return;
     91         var cookie = node.cookie;
     92         var domain = cookie.domain();
     93         if (domain)
     94             contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear all from \"%s\"" : "Clear All from \"%s\"", domain), this._clearAndRefresh.bind(this, domain));
     95         contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear all" : "Clear All"), this._clearAndRefresh.bind(this, null));
     96     },
     97 
     98     /**
     99      * @param {!Array.<!WebInspector.Cookie>} cookies
    100      */
    101     setCookies: function(cookies)
    102     {
    103         this.setCookieFolders([{cookies: cookies}]);
    104     },
    105 
    106     /**
    107      * @param {!Array.<!{folderName: ?string, cookies: !Array.<!WebInspector.Cookie>}>} cookieFolders
    108      */
    109     setCookieFolders: function(cookieFolders)
    110     {
    111         this._data = cookieFolders;
    112         this._rebuildTable();
    113     },
    114 
    115     /**
    116      * @return {?WebInspector.Cookie}
    117      */
    118     selectedCookie: function()
    119     {
    120         var node = this._dataGrid.selectedNode;
    121         return node ? node.cookie : null;
    122     },
    123 
    124     /**
    125      * @param {?string=} domain
    126      */
    127     clear: function(domain)
    128     {
    129         for (var i = 0, length = this._data.length; i < length; ++i) {
    130             var cookies = this._data[i].cookies;
    131             for (var j = 0, cookieCount = cookies.length; j < cookieCount; ++j) {
    132                 if (!domain || cookies[j].domain() === domain)
    133                     cookies[j].remove();
    134             }
    135         }
    136     },
    137 
    138     _rebuildTable: function()
    139     {
    140         var selectedCookie = this._nextSelectedCookie || this.selectedCookie();
    141         this._nextSelectedCookie = null;
    142         this._dataGrid.rootNode().removeChildren();
    143         for (var i = 0; i < this._data.length; ++i) {
    144             var item = this._data[i];
    145             if (item.folderName) {
    146                 var groupData = {name: item.folderName, value: "", domain: "", path: "", expires: "", size: this._totalSize(item.cookies), httpOnly: "", secure: ""};
    147                 var groupNode = new WebInspector.DataGridNode(groupData);
    148                 groupNode.selectable = true;
    149                 this._dataGrid.rootNode().appendChild(groupNode);
    150                 groupNode.element.classList.add("row-group");
    151                 this._populateNode(groupNode, item.cookies, selectedCookie);
    152                 groupNode.expand();
    153             } else
    154                 this._populateNode(this._dataGrid.rootNode(), item.cookies, selectedCookie);
    155         }
    156     },
    157 
    158     /**
    159      * @param {!WebInspector.DataGridNode} parentNode
    160      * @param {?Array.<!WebInspector.Cookie>} cookies
    161      * @param {?WebInspector.Cookie} selectedCookie
    162      */
    163     _populateNode: function(parentNode, cookies, selectedCookie)
    164     {
    165         parentNode.removeChildren();
    166         if (!cookies)
    167             return;
    168 
    169         this._sortCookies(cookies);
    170         for (var i = 0; i < cookies.length; ++i) {
    171             var cookie = cookies[i];
    172             var cookieNode = this._createGridNode(cookie);
    173             parentNode.appendChild(cookieNode);
    174             if (selectedCookie && selectedCookie.name() === cookie.name() && selectedCookie.domain() === cookie.domain() && selectedCookie.path() === cookie.path())
    175                 cookieNode.select();
    176         }
    177     },
    178 
    179     _totalSize: function(cookies)
    180     {
    181         var totalSize = 0;
    182         for (var i = 0; cookies && i < cookies.length; ++i)
    183             totalSize += cookies[i].size();
    184         return totalSize;
    185     },
    186 
    187     /**
    188      * @param {!Array.<!WebInspector.Cookie>} cookies
    189      */
    190     _sortCookies: function(cookies)
    191     {
    192         var sortDirection = this._dataGrid.isSortOrderAscending() ? 1 : -1;
    193 
    194         function compareTo(getter, cookie1, cookie2)
    195         {
    196             return sortDirection * (getter.apply(cookie1) + "").compareTo(getter.apply(cookie2) + "")
    197         }
    198 
    199         function numberCompare(getter, cookie1, cookie2)
    200         {
    201             return sortDirection * (getter.apply(cookie1) - getter.apply(cookie2));
    202         }
    203 
    204         function expiresCompare(cookie1, cookie2)
    205         {
    206             if (cookie1.session() !== cookie2.session())
    207                 return sortDirection * (cookie1.session() ? 1 : -1);
    208 
    209             if (cookie1.session())
    210                 return 0;
    211 
    212             if (cookie1.maxAge() && cookie2.maxAge())
    213                 return sortDirection * (cookie1.maxAge() - cookie2.maxAge());
    214             if (cookie1.expires() && cookie2.expires())
    215                 return sortDirection * (cookie1.expires() - cookie2.expires());
    216             return sortDirection * (cookie1.expires() ? 1 : -1);
    217         }
    218 
    219         var comparator;
    220         switch (this._dataGrid.sortColumnIdentifier()) {
    221             case "name": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.name); break;
    222             case "value": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.value); break;
    223             case "domain": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.domain); break;
    224             case "path": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.path); break;
    225             case "expires": comparator = expiresCompare; break;
    226             case "size": comparator = numberCompare.bind(null, WebInspector.Cookie.prototype.size); break;
    227             case "httpOnly": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.httpOnly); break;
    228             case "secure": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.secure); break;
    229             default: compareTo.bind(null, WebInspector.Cookie.prototype.name);
    230         }
    231 
    232         cookies.sort(comparator);
    233     },
    234 
    235     /**
    236      * @param {!WebInspector.Cookie} cookie
    237      * @return {!WebInspector.DataGridNode}
    238      */
    239     _createGridNode: function(cookie)
    240     {
    241         var data = {};
    242         data.name = cookie.name();
    243         data.value = cookie.value();
    244         if (cookie.type() === WebInspector.Cookie.Type.Request) {
    245             data.domain = WebInspector.UIString("N/A");
    246             data.path = WebInspector.UIString("N/A");
    247             data.expires = WebInspector.UIString("N/A");
    248         } else {
    249             data.domain = cookie.domain() || "";
    250             data.path = cookie.path() || "";
    251             if (cookie.maxAge())
    252                 data.expires = Number.secondsToString(parseInt(cookie.maxAge(), 10));
    253             else if (cookie.expires())
    254                 data.expires = new Date(cookie.expires()).toISOString();
    255             else
    256                 data.expires = WebInspector.UIString("Session");
    257         }
    258         data.size = cookie.size();
    259         const checkmark = "\u2713";
    260         data.httpOnly = (cookie.httpOnly() ? checkmark : "");
    261         data.secure = (cookie.secure() ? checkmark : "");
    262 
    263         var node = new WebInspector.DataGridNode(data);
    264         node.cookie = cookie;
    265         node.selectable = true;
    266         return node;
    267     },
    268 
    269     _onDeleteCookie: function(node)
    270     {
    271         var cookie = node.cookie;
    272         var neighbour = node.traverseNextNode() || node.traversePreviousNode();
    273         if (neighbour)
    274             this._nextSelectedCookie = neighbour.cookie;
    275         cookie.remove();
    276         this._refresh();
    277     },
    278 
    279     _refresh: function()
    280     {
    281         if (this._refreshCallback)
    282             this._refreshCallback();
    283     },
    284 
    285     __proto__: WebInspector.VBox.prototype
    286 }
    287