1/*
2 * Copyright (C) 2008 Nokia Inc.  All rights reserved.
3 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
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 "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/**
31 * @constructor
32 * @extends {WebInspector.Object}
33 * @param {!WebInspector.DOMStorageModel} model
34 * @param {string} securityOrigin
35 * @param {boolean} isLocalStorage
36 */
37WebInspector.DOMStorage = function(model, securityOrigin, isLocalStorage)
38{
39    this._model = model;
40    this._securityOrigin = securityOrigin;
41    this._isLocalStorage = isLocalStorage;
42}
43
44/**
45 * @param {string} securityOrigin
46 * @param {boolean} isLocalStorage
47 * @return {!DOMStorageAgent.StorageId}
48 */
49WebInspector.DOMStorage.storageId = function(securityOrigin, isLocalStorage)
50{
51    return { securityOrigin: securityOrigin, isLocalStorage: isLocalStorage };
52}
53
54WebInspector.DOMStorage.Events = {
55    DOMStorageItemsCleared: "DOMStorageItemsCleared",
56    DOMStorageItemRemoved: "DOMStorageItemRemoved",
57    DOMStorageItemAdded: "DOMStorageItemAdded",
58    DOMStorageItemUpdated: "DOMStorageItemUpdated"
59}
60
61WebInspector.DOMStorage.prototype = {
62
63    /** @return {!DOMStorageAgent.StorageId} */
64    get id()
65    {
66        return WebInspector.DOMStorage.storageId(this._securityOrigin, this._isLocalStorage);
67    },
68
69    /** @return {string} */
70    get securityOrigin()
71    {
72        return this._securityOrigin;
73    },
74
75    /** @return {boolean} */
76    get isLocalStorage()
77    {
78        return this._isLocalStorage;
79    },
80
81    /**
82     * @param {function(?Protocol.Error, !Array.<!DOMStorageAgent.Item>):void=} callback
83     */
84    getItems: function(callback)
85    {
86        this._model._agent.getDOMStorageItems(this.id, callback);
87    },
88
89    /**
90     * @param {string} key
91     * @param {string} value
92     */
93    setItem: function(key, value)
94    {
95        this._model._agent.setDOMStorageItem(this.id, key, value);
96    },
97
98    /**
99     * @param {string} key
100     */
101    removeItem: function(key)
102    {
103        this._model._agent.removeDOMStorageItem(this.id, key);
104    },
105
106    __proto__: WebInspector.Object.prototype
107}
108
109/**
110 * @constructor
111 * @extends {WebInspector.SDKModel}
112 * @param {!WebInspector.Target} target
113 */
114WebInspector.DOMStorageModel = function(target)
115{
116    WebInspector.SDKModel.call(this, WebInspector.DOMStorageModel, target);
117
118    /** @type {!Object.<string, !WebInspector.DOMStorage>} */
119    this._storages = {};
120    target.registerDOMStorageDispatcher(new WebInspector.DOMStorageDispatcher(this));
121    this._agent = target.domstorageAgent();
122    this._agent.enable();
123    target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginAdded, this._securityOriginAdded, this);
124    target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginRemoved, this._securityOriginRemoved, this);
125}
126
127WebInspector.DOMStorageModel.Events = {
128    DOMStorageAdded: "DOMStorageAdded",
129    DOMStorageRemoved: "DOMStorageRemoved"
130}
131
132WebInspector.DOMStorageModel.prototype = {
133
134    /**
135     * @param {!WebInspector.Event} event
136     */
137    _securityOriginAdded: function(event)
138    {
139        var securityOrigin = /** @type {string} */ (event.data);
140        var localStorageKey = this._storageKey(securityOrigin, true);
141        console.assert(!this._storages[localStorageKey]);
142        var localStorage = new WebInspector.DOMStorage(this, securityOrigin, true);
143        this._storages[localStorageKey] = localStorage;
144        this.dispatchEventToListeners(WebInspector.DOMStorageModel.Events.DOMStorageAdded, localStorage);
145
146        var sessionStorageKey = this._storageKey(securityOrigin, false);
147        console.assert(!this._storages[sessionStorageKey]);
148        var sessionStorage = new WebInspector.DOMStorage(this, securityOrigin, false);
149        this._storages[sessionStorageKey] = sessionStorage;
150        this.dispatchEventToListeners(WebInspector.DOMStorageModel.Events.DOMStorageAdded, sessionStorage);
151    },
152
153    /**
154     * @param {!WebInspector.Event} event
155     */
156    _securityOriginRemoved: function(event)
157    {
158        var securityOrigin = /** @type {string} */ (event.data);
159        var localStorageKey = this._storageKey(securityOrigin, true);
160        var localStorage = this._storages[localStorageKey];
161        console.assert(localStorage);
162        delete this._storages[localStorageKey];
163        this.dispatchEventToListeners(WebInspector.DOMStorageModel.Events.DOMStorageRemoved, localStorage);
164
165        var sessionStorageKey = this._storageKey(securityOrigin, false);
166        var sessionStorage = this._storages[sessionStorageKey];
167        console.assert(sessionStorage);
168        delete this._storages[sessionStorageKey];
169        this.dispatchEventToListeners(WebInspector.DOMStorageModel.Events.DOMStorageRemoved, sessionStorage);
170    },
171
172    /**
173     * @param {string} securityOrigin
174     * @param {boolean} isLocalStorage
175     * @return {string}
176     */
177    _storageKey: function(securityOrigin, isLocalStorage)
178    {
179        return JSON.stringify(WebInspector.DOMStorage.storageId(securityOrigin, isLocalStorage));
180    },
181
182    /**
183     * @param {!DOMStorageAgent.StorageId} storageId
184     */
185    _domStorageItemsCleared: function(storageId)
186    {
187        var domStorage = this.storageForId(storageId);
188        if (!domStorage)
189            return;
190
191        var eventData = {};
192        domStorage.dispatchEventToListeners(WebInspector.DOMStorage.Events.DOMStorageItemsCleared, eventData);
193    },
194
195    /**
196     * @param {!DOMStorageAgent.StorageId} storageId
197     * @param {string} key
198     */
199    _domStorageItemRemoved: function(storageId, key)
200    {
201        var domStorage = this.storageForId(storageId);
202        if (!domStorage)
203            return;
204
205        var eventData = { key: key };
206        domStorage.dispatchEventToListeners(WebInspector.DOMStorage.Events.DOMStorageItemRemoved, eventData);
207    },
208
209    /**
210     * @param {!DOMStorageAgent.StorageId} storageId
211     * @param {string} key
212     * @param {string} value
213     */
214    _domStorageItemAdded: function(storageId, key, value)
215    {
216        var domStorage = this.storageForId(storageId);
217        if (!domStorage)
218            return;
219
220        var eventData = { key: key, value: value };
221        domStorage.dispatchEventToListeners(WebInspector.DOMStorage.Events.DOMStorageItemAdded, eventData);
222    },
223
224    /**
225     * @param {!DOMStorageAgent.StorageId} storageId
226     * @param {string} key
227     * @param {string} oldValue
228     * @param {string} value
229     */
230    _domStorageItemUpdated: function(storageId, key, oldValue, value)
231    {
232        var domStorage = this.storageForId(storageId);
233        if (!domStorage)
234            return;
235
236        var eventData = { key: key, oldValue: oldValue, value: value };
237        domStorage.dispatchEventToListeners(WebInspector.DOMStorage.Events.DOMStorageItemUpdated, eventData);
238    },
239
240    /**
241     * @param {!DOMStorageAgent.StorageId} storageId
242     * @return {!WebInspector.DOMStorage}
243     */
244    storageForId: function(storageId)
245    {
246        return this._storages[JSON.stringify(storageId)];
247    },
248
249    /**
250     * @return {!Array.<!WebInspector.DOMStorage>}
251     */
252    storages: function()
253    {
254        var result = [];
255        for (var id in this._storages)
256            result.push(this._storages[id]);
257        return result;
258    },
259
260    __proto__: WebInspector.SDKModel.prototype
261}
262
263/**
264 * @constructor
265 * @implements {DOMStorageAgent.Dispatcher}
266 * @param {!WebInspector.DOMStorageModel} model
267 */
268WebInspector.DOMStorageDispatcher = function(model)
269{
270    this._model = model;
271}
272
273WebInspector.DOMStorageDispatcher.prototype = {
274
275    /**
276     * @param {!DOMStorageAgent.StorageId} storageId
277     */
278    domStorageItemsCleared: function(storageId)
279    {
280        this._model._domStorageItemsCleared(storageId);
281    },
282
283    /**
284     * @param {!DOMStorageAgent.StorageId} storageId
285     * @param {string} key
286     */
287    domStorageItemRemoved: function(storageId, key)
288    {
289        this._model._domStorageItemRemoved(storageId, key);
290    },
291
292    /**
293     * @param {!DOMStorageAgent.StorageId} storageId
294     * @param {string} key
295     * @param {string} value
296     */
297    domStorageItemAdded: function(storageId, key, value)
298    {
299        this._model._domStorageItemAdded(storageId, key, value);
300    },
301
302    /**
303     * @param {!DOMStorageAgent.StorageId} storageId
304     * @param {string} key
305     * @param {string} oldValue
306     * @param {string} value
307     */
308    domStorageItemUpdated: function(storageId, key, oldValue, value)
309    {
310        this._model._domStorageItemUpdated(storageId, key, oldValue, value);
311    },
312}
313
314/**
315 * @type {!WebInspector.DOMStorageModel}
316 */
317WebInspector.domStorageModel;
318