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 "ExceptionCodeDescription.h" 41#include "Frame.h" 42#include "InspectorFrontend.h" 43#include "InspectorPageAgent.h" 44#include "InspectorState.h" 45#include "InspectorValues.h" 46#include "InstrumentingAgents.h" 47#include "Page.h" 48#include "PageGroup.h" 49#include "SecurityOrigin.h" 50#include "Storage.h" 51#include "StorageArea.h" 52#include "StorageNamespace.h" 53#include "VoidCallback.h" 54 55#include <wtf/Vector.h> 56 57namespace WebCore { 58 59namespace DOMStorageAgentState { 60static const char domStorageAgentEnabled[] = "domStorageAgentEnabled"; 61}; 62 63InspectorDOMStorageAgent::InspectorDOMStorageAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* state) 64 : InspectorBaseAgent<InspectorDOMStorageAgent>("DOMStorage", instrumentingAgents, state) 65 , m_pageAgent(pageAgent) 66 , m_frontend(0) 67{ 68 m_instrumentingAgents->setInspectorDOMStorageAgent(this); 69} 70 71InspectorDOMStorageAgent::~InspectorDOMStorageAgent() 72{ 73 m_instrumentingAgents->setInspectorDOMStorageAgent(0); 74 m_instrumentingAgents = 0; 75} 76 77void InspectorDOMStorageAgent::setFrontend(InspectorFrontend* frontend) 78{ 79 m_frontend = frontend; 80} 81 82void InspectorDOMStorageAgent::clearFrontend() 83{ 84 m_frontend = 0; 85 disable(0); 86} 87 88bool InspectorDOMStorageAgent::isEnabled() const 89{ 90 return m_state->getBoolean(DOMStorageAgentState::domStorageAgentEnabled); 91} 92 93void InspectorDOMStorageAgent::enable(ErrorString*) 94{ 95 m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, true); 96} 97 98void InspectorDOMStorageAgent::disable(ErrorString*) 99{ 100 m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, false); 101} 102 103void InspectorDOMStorageAgent::getDOMStorageItems(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > >& items) 104{ 105 Frame* frame; 106 RefPtr<StorageArea> storageArea = findStorageArea(errorString, storageId, frame); 107 if (!storageArea) { 108 if (errorString) 109 *errorString = "No StorageArea for given storageId"; 110 return; 111 } 112 113 RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > > storageItems = TypeBuilder::Array<TypeBuilder::Array<String> >::create(); 114 115 for (unsigned i = 0; i < storageArea->length(); ++i) { 116 String key = storageArea->key(i); 117 String value = storageArea->item(key); 118 119 RefPtr<TypeBuilder::Array<String> > entry = TypeBuilder::Array<String>::create(); 120 entry->addItem(key); 121 entry->addItem(value); 122 storageItems->addItem(entry.release()); 123 } 124 125 items = storageItems.release(); 126} 127 128void InspectorDOMStorageAgent::setDOMStorageItem(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, const String& key, const String& value) 129{ 130 Frame* frame; 131 RefPtr<StorageArea> storageArea = findStorageArea(0, storageId, frame); 132 if (!storageArea) { 133 *errorString = "Storage not found"; 134 return; 135 } 136 137 bool quotaException = false; 138 storageArea->setItem(frame, key, value, quotaException); 139 if (quotaException) 140 *errorString = ExceptionCodeDescription(QUOTA_EXCEEDED_ERR).name; 141} 142 143void InspectorDOMStorageAgent::removeDOMStorageItem(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, const String& key) 144{ 145 Frame* frame; 146 RefPtr<StorageArea> storageArea = findStorageArea(0, storageId, frame); 147 if (!storageArea) { 148 *errorString = "Storage not found"; 149 return; 150 } 151 152 storageArea->removeItem(frame, key); 153} 154 155String InspectorDOMStorageAgent::storageId(Storage* storage) 156{ 157 ASSERT(storage); 158 Document* document = storage->frame()->document(); 159 ASSERT(document); 160 DOMWindow* window = document->domWindow(); 161 ASSERT(window); 162 RefPtr<SecurityOrigin> securityOrigin = document->securityOrigin(); 163 bool isLocalStorage = window->optionalLocalStorage() == storage; 164 return storageId(securityOrigin.get(), isLocalStorage)->toJSONString(); 165} 166 167PassRefPtr<TypeBuilder::DOMStorage::StorageId> InspectorDOMStorageAgent::storageId(SecurityOrigin* securityOrigin, bool isLocalStorage) 168{ 169 return TypeBuilder::DOMStorage::StorageId::create() 170 .setSecurityOrigin(securityOrigin->toRawString()) 171 .setIsLocalStorage(isLocalStorage).release(); 172} 173 174void InspectorDOMStorageAgent::didDispatchDOMStorageEvent(const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin, Page*) 175{ 176 if (!m_frontend || !isEnabled()) 177 return; 178 179 RefPtr<TypeBuilder::DOMStorage::StorageId> id = storageId(securityOrigin, storageType == LocalStorage); 180 181 if (key.isNull()) 182 m_frontend->domstorage()->domStorageItemsCleared(id); 183 else if (newValue.isNull()) 184 m_frontend->domstorage()->domStorageItemRemoved(id, key); 185 else if (oldValue.isNull()) 186 m_frontend->domstorage()->domStorageItemAdded(id, key, newValue); 187 else 188 m_frontend->domstorage()->domStorageItemUpdated(id, key, oldValue, newValue); 189} 190 191PassRefPtr<StorageArea> InspectorDOMStorageAgent::findStorageArea(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, Frame*& targetFrame) 192{ 193 String securityOrigin; 194 bool isLocalStorage = false; 195 bool success = storageId->getString("securityOrigin", &securityOrigin); 196 if (success) 197 success = storageId->getBoolean("isLocalStorage", &isLocalStorage); 198 if (!success) { 199 if (errorString) 200 *errorString = "Invalid storageId format"; 201 targetFrame = 0; 202 return 0; 203 } 204 205 targetFrame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin); 206 if (!targetFrame) { 207 if (errorString) 208 *errorString = "Frame not found for the given security origin"; 209 return 0; 210 } 211 212 Page* page = m_pageAgent->page(); 213 if (isLocalStorage) 214 return page->group().localStorage()->storageArea(targetFrame->document()->securityOrigin()); 215 return page->sessionStorage()->storageArea(targetFrame->document()->securityOrigin()); 216} 217 218} // namespace WebCore 219 220#endif // ENABLE(INSPECTOR) 221