• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
36    this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
37    this._deleteButton.visible = false;
38    this._deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
39
40    this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
41    this._refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
42
43    this._treeElement = treeElement;
44    this._cookieDomain = cookieDomain;
45
46    this._emptyMsgElement = document.createElement("div");
47    this._emptyMsgElement.className = "storage-empty-view";
48    this._emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies.");
49    this.element.appendChild(this._emptyMsgElement);
50}
51
52WebInspector.CookieItemsView.prototype = {
53    get statusBarItems()
54    {
55        return [this._refreshButton.element, this._deleteButton.element];
56    },
57
58    show: function(parentElement)
59    {
60        WebInspector.View.prototype.show.call(this, parentElement);
61        this._update();
62    },
63
64    hide: function()
65    {
66        WebInspector.View.prototype.hide.call(this);
67        this._deleteButton.visible = false;
68    },
69
70    resize: function()
71    {
72        if (this._cookiesTable)
73            this._cookiesTable.updateWidths();
74    },
75
76    _update: function()
77    {
78        WebInspector.Cookies.getCookiesAsync(this._updateWithCookies.bind(this));
79    },
80
81    _updateWithCookies: function(allCookies, isAdvanced)
82    {
83        this._cookies = isAdvanced ? this._filterCookiesForDomain(allCookies) : allCookies;
84
85        if (!this._cookies.length) {
86            // Nothing to show.
87            this._emptyMsgElement.removeStyleClass("hidden");
88            this._deleteButton.visible = false;
89            if (this._cookiesTable)
90                this._cookiesTable.element.addStyleClass("hidden");
91            return;
92        }
93
94        if (!this._cookiesTable) {
95            this._cookiesTable = isAdvanced ? new WebInspector.CookiesTable(this._cookieDomain, false, this._deleteCookie.bind(this)) : new WebInspector.SimpleCookiesTable();
96            this.element.appendChild(this._cookiesTable.element);
97        }
98
99        this._cookiesTable.setCookies(this._cookies);
100        this._cookiesTable.element.removeStyleClass("hidden");
101        this._emptyMsgElement.addStyleClass("hidden");
102        if (isAdvanced) {
103            this._treeElement.subtitle = String.sprintf(WebInspector.UIString("%d cookies (%s)"), this._cookies.length,
104                Number.bytesToString(this._totalSize));
105            this._deleteButton.visible = true;
106        }
107        this._cookiesTable.updateWidths();
108    },
109
110    _filterCookiesForDomain: function(allCookies)
111    {
112        var cookies = [];
113        var resourceURLsForDocumentURL = [];
114        this._totalSize = 0;
115
116        function populateResourcesForDocuments(resource)
117        {
118            var url = resource.documentURL.asParsedURL();
119            if (url && url.host == this._cookieDomain)
120                resourceURLsForDocumentURL.push(resource.url);
121        }
122        WebInspector.forAllResources(populateResourcesForDocuments.bind(this));
123
124        for (var i = 0; i < allCookies.length; ++i) {
125            var pushed = false;
126            var size = allCookies[i].size;
127            for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) {
128                var resourceURL = resourceURLsForDocumentURL[j];
129                if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) {
130                    this._totalSize += size;
131                    if (!pushed) {
132                        pushed = true;
133                        cookies.push(allCookies[i]);
134                    }
135                }
136            }
137        }
138        return cookies;
139    },
140
141    _deleteCookie: function(cookie)
142    {
143        PageAgent.deleteCookie(cookie.name, this._cookieDomain);
144        this._update();
145    },
146
147    _deleteButtonClicked: function()
148    {
149        if (this._cookiesTable.selectedCookie)
150            this._deleteCookie(this._cookiesTable.selectedCookie);
151    },
152
153    _refreshButtonClicked: function(event)
154    {
155        this._update();
156    }
157}
158
159WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype;
160
161WebInspector.SimpleCookiesTable = function()
162{
163    this.element = document.createElement("div");
164    var columns = {};
165    columns[0] = {};
166    columns[1] = {};
167    columns[0].title = WebInspector.UIString("Name");
168    columns[1].title = WebInspector.UIString("Value");
169
170    this._dataGrid = new WebInspector.DataGrid(columns);
171    this._dataGrid.autoSizeColumns(20, 80);
172    this.element.appendChild(this._dataGrid.element);
173    this._dataGrid.updateWidths();
174}
175
176WebInspector.SimpleCookiesTable.prototype = {
177    setCookies: function(cookies)
178    {
179        this._dataGrid.removeChildren();
180        var addedCookies = {};
181        for (var i = 0; i < cookies.length; ++i) {
182            if (addedCookies[cookies[i].name])
183                continue;
184            addedCookies[cookies[i].name] = true;
185            var data = {};
186            data[0] = cookies[i].name;
187            data[1] = cookies[i].value;
188
189            var node = new WebInspector.DataGridNode(data, false);
190            node.selectable = true;
191            this._dataGrid.appendChild(node);
192        }
193        this._dataGrid.children[0].selected = true;
194    },
195
196    resize: function()
197    {
198        if (this._dataGrid)
199            this._dataGrid.updateWidths();
200    }
201}
202
203
204WebInspector.Cookies = {}
205
206WebInspector.Cookies.getCookiesAsync = function(callback)
207{
208    function mycallback(error, cookies, cookiesString)
209    {
210        if (error)
211            return;
212        if (cookiesString)
213            callback(WebInspector.Cookies.buildCookiesFromString(cookiesString), false);
214        else
215            callback(cookies, true);
216    }
217
218    PageAgent.getCookies(mycallback);
219}
220
221WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
222{
223    var rawCookies = rawCookieString.split(/;\s*/);
224    var cookies = [];
225
226    if (!(/^\s*$/.test(rawCookieString))) {
227        for (var i = 0; i < rawCookies.length; ++i) {
228            var cookie = rawCookies[i];
229            var delimIndex = cookie.indexOf("=");
230            var name = cookie.substring(0, delimIndex);
231            var value = cookie.substring(delimIndex + 1);
232            var size = name.length + value.length;
233            cookies.push({ name: name, value: value, size: size });
234        }
235    }
236
237    return cookies;
238}
239
240WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL)
241{
242    var url = resourceURL.asParsedURL();
243    if (!url || !this.cookieDomainMatchesResourceDomain(cookie.domain, url.host))
244        return false;
245    return (url.path.indexOf(cookie.path) === 0
246        && (!cookie.port || url.port == cookie.port)
247        && (!cookie.secure || url.scheme === "https"));
248}
249
250WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain)
251{
252    if (cookieDomain.charAt(0) !== '.')
253        return resourceDomain === cookieDomain;
254    return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)?" + cookieDomain.substring(1).escapeForRegExp() + "$"), "i");
255}
256