Unreviewed, rolling out r143581.
[WebKit-https.git] / Source / WebCore / inspector / InspectorDOMStorageAgent.cpp
1 /*
2  * Copyright (C) 2010 Google 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 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 #include "config.h"
31
32 #if ENABLE(INSPECTOR)
33
34 #include "InspectorDOMStorageAgent.h"
35
36 #include "Database.h"
37 #include "DOMWindow.h"
38 #include "Document.h"
39 #include "ExceptionCode.h"
40 #include "Frame.h"
41 #include "InspectorDOMStorageResource.h"
42 #include "InspectorFrontend.h"
43 #include "InspectorState.h"
44 #include "InspectorValues.h"
45 #include "InstrumentingAgents.h"
46 #include "Storage.h"
47 #include "StorageArea.h"
48 #include "VoidCallback.h"
49 #include "WebCoreMemoryInstrumentation.h"
50
51 #include <wtf/MemoryInstrumentationHashMap.h>
52 #include <wtf/Vector.h>
53
54 namespace WebCore {
55
56 namespace DOMStorageAgentState {
57 static const char domStorageAgentEnabled[] = "domStorageAgentEnabled";
58 };
59
60 static bool hadException(ExceptionCode ec, ErrorString* errorString)
61 {
62     switch (ec) {
63     case 0:
64         return false;
65     case SECURITY_ERR:
66         *errorString = "Security error";
67         return true;
68     default:
69         *errorString = "Unknown DOM storage error";
70         return true;
71     }
72 }
73
74 InspectorDOMStorageAgent::InspectorDOMStorageAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
75     : InspectorBaseAgent<InspectorDOMStorageAgent>("DOMStorage", instrumentingAgents, state)
76     , m_frontend(0)
77     , m_enabled(false)
78 {
79     m_instrumentingAgents->setInspectorDOMStorageAgent(this);
80 }
81
82 InspectorDOMStorageAgent::~InspectorDOMStorageAgent()
83 {
84     m_instrumentingAgents->setInspectorDOMStorageAgent(0);
85     m_instrumentingAgents = 0;
86 }
87
88 void InspectorDOMStorageAgent::setFrontend(InspectorFrontend* frontend)
89 {
90     m_frontend = frontend;
91 }
92
93 void InspectorDOMStorageAgent::clearFrontend()
94 {
95     DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
96     for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it)
97         it->value->unbind();
98     m_frontend = 0;
99     disable(0);
100 }
101
102 void InspectorDOMStorageAgent::restore()
103 {
104     m_enabled =  m_state->getBoolean(DOMStorageAgentState::domStorageAgentEnabled);
105 }
106
107 void InspectorDOMStorageAgent::enable(ErrorString*)
108 {
109     if (m_enabled)
110         return;
111     m_enabled = true;
112     m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, m_enabled);
113
114     DOMStorageResourcesMap::iterator resourcesEnd = m_resources.end();
115     for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it)
116         it->value->bind(m_frontend);
117 }
118
119 void InspectorDOMStorageAgent::disable(ErrorString*)
120 {
121     if (!m_enabled)
122         return;
123     m_enabled = false;
124     m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, m_enabled);
125 }
126
127 void InspectorDOMStorageAgent::getDOMStorageEntries(ErrorString* errorString, const String& storageId, RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > >& entries)
128 {
129     InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
130     if (!storageResource) {
131         *errorString = "Storage resource not found for the given storage identifier";
132         return;
133     }
134     Frame* frame = storageResource->frame();
135     if (!frame) {
136         *errorString = "Frame not found";
137         return;
138     }
139
140     RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > > storageEntries = TypeBuilder::Array<TypeBuilder::Array<String> >::create();
141
142     ExceptionCode ec = 0;
143     StorageArea* storageArea = storageResource->storageArea();
144     for (unsigned i = 0; i < storageArea->length(ec, frame); ++i) {
145         String name(storageArea->key(i, ec, frame));
146         if (hadException(ec, errorString))
147             return;
148         String value(storageArea->getItem(name, ec, frame));
149         if (hadException(ec, errorString))
150             return;
151         RefPtr<TypeBuilder::Array<String> > entry = TypeBuilder::Array<String>::create();
152         entry->addItem(name);
153         entry->addItem(value);
154         storageEntries->addItem(entry);
155     }
156     entries = storageEntries.release();
157 }
158
159 void InspectorDOMStorageAgent::setDOMStorageItem(ErrorString*, const String& storageId, const String& key, const String& value, bool* success)
160 {
161     InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
162     if (storageResource) {
163         ExceptionCode exception = 0;
164         storageResource->storageArea()->setItem(key, value, exception, storageResource->frame());
165         *success = !exception;
166     } else
167         *success = false;
168 }
169
170 void InspectorDOMStorageAgent::removeDOMStorageItem(ErrorString*, const String& storageId, const String& key, bool* success)
171 {
172     InspectorDOMStorageResource* storageResource = getDOMStorageResourceForId(storageId);
173     if (storageResource) {
174         ExceptionCode exception = 0;
175         storageResource->storageArea()->removeItem(key, exception, storageResource->frame());
176         *success = !exception;
177     } else
178         *success = false;
179 }
180
181 String InspectorDOMStorageAgent::storageId(Storage* storage)
182 {
183     ASSERT(storage);
184     Frame* frame = storage->frame();
185     ExceptionCode ec = 0;
186     bool isLocalStorage = (frame->document()->domWindow()->localStorage(ec) == storage && !ec);
187     return storageId(frame->document()->securityOrigin(), isLocalStorage);
188 }
189
190 String InspectorDOMStorageAgent::storageId(SecurityOrigin* securityOrigin, bool isLocalStorage)
191 {
192     ASSERT(securityOrigin);
193     DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
194     for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it) {
195         if (it->value->isSameOriginAndType(securityOrigin, isLocalStorage))
196             return it->key;
197     }
198     return String();
199 }
200
201 InspectorDOMStorageResource* InspectorDOMStorageAgent::getDOMStorageResourceForId(const String& storageId)
202 {
203     DOMStorageResourcesMap::iterator it = m_resources.find(storageId);
204     if (it == m_resources.end())
205         return 0;
206     return it->value.get();
207 }
208
209 void InspectorDOMStorageAgent::didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame)
210 {
211     DOMStorageResourcesMap::iterator domStorageEnd = m_resources.end();
212     for (DOMStorageResourcesMap::iterator it = m_resources.begin(); it != domStorageEnd; ++it) {
213         if (it->value->isSameOriginAndType(frame->document()->securityOrigin(), isLocalStorage))
214             return;
215     }
216
217     RefPtr<InspectorDOMStorageResource> resource = InspectorDOMStorageResource::create(storageArea, isLocalStorage, frame);
218
219     m_resources.set(resource->id(), resource);
220
221     // Resources are only bound while visible.
222     if (m_enabled)
223         resource->bind(m_frontend);
224 }
225
226 void InspectorDOMStorageAgent::didDispatchDOMStorageEvent(const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin, Page*)
227 {
228     if (!m_frontend || !m_enabled)
229         return;
230
231     String id = storageId(securityOrigin, storageType == LocalStorage);
232
233     if (id.isEmpty())
234         return;
235
236     if (key.isNull())
237         m_frontend->domstorage()->domStorageItemsCleared(id);
238     else if (newValue.isNull())
239         m_frontend->domstorage()->domStorageItemRemoved(id, key);
240     else if (oldValue.isNull())
241         m_frontend->domstorage()->domStorageItemAdded(id, key, newValue);
242     else
243         m_frontend->domstorage()->domStorageItemUpdated(id, key, oldValue, newValue);
244 }
245
246 void InspectorDOMStorageAgent::clearResources()
247 {
248     m_resources.clear();
249 }
250
251 void InspectorDOMStorageAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
252 {
253     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorDOMStorageAgent);
254     InspectorBaseAgent<InspectorDOMStorageAgent>::reportMemoryUsage(memoryObjectInfo);
255     info.addMember(m_resources, "resources");
256     info.addWeakPointer(m_frontend);
257 }
258
259 } // namespace WebCore
260
261 #endif // ENABLE(INSPECTOR)