1/*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30
31#include "InspectorDOMStorageAgent.h"
32
33#if ENABLE(INSPECTOR) && ENABLE(DOM_STORAGE)
34
35#include "Database.h"
36#include "DOMWindow.h"
37#include "ExceptionCode.h"
38#include "Frame.h"
39#include "InspectorDOMStorageResource.h"
40#include "InspectorFrontend.h"
41#include "InspectorValues.h"
42#include "InstrumentingAgents.h"
43#include "Storage.h"
44#include "StorageArea.h"
45#include "VoidCallback.h"
46
47#include <wtf/Vector.h>
48
49namespace WebCore {
50
51typedef HashMap<int, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
52
53InspectorDOMStorageAgent::InspectorDOMStorageAgent(InstrumentingAgents* instrumentingAgents)
54    : m_instrumentingAgents(instrumentingAgents)
55    , m_frontend(0)
56{
57    m_instrumentingAgents->setInspectorDOMStorageAgent(this);
58}
59
60InspectorDOMStorageAgent::~InspectorDOMStorageAgent()
61{
62    m_instrumentingAgents->setInspectorDOMStorageAgent(0);
63    m_instrumentingAgents = 0;
64}
65
66void InspectorDOMStorageAgent::setFrontend(InspectorFrontend* frontend)
67{
68    m_frontend = frontend;
69    DOMStorageResourcesMap::iterator resourcesEnd = m_resources.end();
70    for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it)
71        it->second->bind(m_frontend);
72}
73
74void InspectorDOMStorageAgent::clearFrontend()
75{
76    DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
77    for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it)
78        it->second->unbind();
79    m_frontend = 0;
80}
81
82void InspectorDOMStorageAgent::getDOMStorageEntries(ErrorString*, int storageId, RefPtr<InspectorArray>* entries)
83{
84    InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
85    if (storageResource) {
86        storageResource->startReportingChangesToFrontend();
87        Storage* domStorage = storageResource->domStorage();
88        for (unsigned i = 0; i < domStorage->length(); ++i) {
89            String name(domStorage->key(i));
90            String value(domStorage->getItem(name));
91            RefPtr<InspectorArray> entry = InspectorArray::create();
92            entry->pushString(name);
93            entry->pushString(value);
94            (*entries)->pushArray(entry);
95        }
96    }
97}
98
99void InspectorDOMStorageAgent::setDOMStorageItem(ErrorString*, int storageId, const String& key, const String& value, bool* success)
100{
101    InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
102    if (storageResource) {
103        ExceptionCode exception = 0;
104        storageResource->domStorage()->setItem(key, value, exception);
105        *success = !exception;
106    }
107}
108
109void InspectorDOMStorageAgent::removeDOMStorageItem(ErrorString*, int storageId, const String& key, bool* success)
110{
111    InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
112    if (storageResource) {
113        storageResource->domStorage()->removeItem(key);
114        *success = true;
115    }
116}
117
118int InspectorDOMStorageAgent::storageId(Storage* storage)
119{
120    ASSERT(storage);
121    Frame* frame = storage->frame();
122    ExceptionCode ec = 0;
123    bool isLocalStorage = (frame->domWindow()->localStorage(ec) == storage && !ec);
124    DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
125    for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it) {
126        if (it->second->isSameHostAndType(frame, isLocalStorage))
127            return it->first;
128    }
129    return 0;
130}
131
132InspectorDOMStorageResource* InspectorDOMStorageAgent::getDOMStorageResourceForId(int storageId)
133{
134    DOMStorageResourcesMap::iterator it = m_resources.find(storageId);
135    if (it == m_resources.end())
136        return 0;
137    return it->second.get();
138}
139
140void InspectorDOMStorageAgent::didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame)
141{
142    DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
143    for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it) {
144        if (it->second->isSameHostAndType(frame, isLocalStorage))
145            return;
146    }
147
148    RefPtr<Storage> domStorage = Storage::create(frame, storageArea);
149    RefPtr<InspectorDOMStorageResource> resource = InspectorDOMStorageResource::create(domStorage.get(), isLocalStorage, frame);
150
151    m_resources.set(resource->id(), resource);
152
153    // Resources are only bound while visible.
154    if (m_frontend)
155        resource->bind(m_frontend);
156}
157
158void InspectorDOMStorageAgent::clearResources()
159{
160    m_resources.clear();
161}
162
163
164} // namespace WebCore
165
166#endif // ENABLE(INSPECTOR) && ENABLE(DOM_STORE)
167