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#include "core/inspector/InspectorDOMStorageAgent.h" 32 33#include "bindings/core/v8/ExceptionState.h" 34#include "core/InspectorFrontend.h" 35#include "core/dom/DOMException.h" 36#include "core/dom/Document.h" 37#include "core/dom/ExceptionCode.h" 38#include "core/inspector/InspectorPageAgent.h" 39#include "core/inspector/InspectorState.h" 40#include "core/inspector/InstrumentingAgents.h" 41#include "core/frame/LocalDOMWindow.h" 42#include "core/frame/LocalFrame.h" 43#include "core/page/Page.h" 44#include "core/storage/Storage.h" 45#include "core/storage/StorageNamespace.h" 46#include "platform/JSONValues.h" 47#include "platform/weborigin/SecurityOrigin.h" 48 49namespace blink { 50 51namespace DOMStorageAgentState { 52static const char domStorageAgentEnabled[] = "domStorageAgentEnabled"; 53}; 54 55static bool hadException(ExceptionState& exceptionState, ErrorString* errorString) 56{ 57 if (!exceptionState.hadException()) 58 return false; 59 60 switch (exceptionState.code()) { 61 case SecurityError: 62 *errorString = "Security error"; 63 return true; 64 default: 65 *errorString = "Unknown DOM storage error"; 66 return true; 67 } 68} 69 70InspectorDOMStorageAgent::InspectorDOMStorageAgent(InspectorPageAgent* pageAgent) 71 : InspectorBaseAgent<InspectorDOMStorageAgent>("DOMStorage") 72 , m_pageAgent(pageAgent) 73 , m_frontend(0) 74{ 75} 76 77InspectorDOMStorageAgent::~InspectorDOMStorageAgent() 78{ 79} 80 81void InspectorDOMStorageAgent::trace(Visitor* visitor) 82{ 83 visitor->trace(m_pageAgent); 84 InspectorBaseAgent::trace(visitor); 85} 86 87void InspectorDOMStorageAgent::setFrontend(InspectorFrontend* frontend) 88{ 89 m_frontend = frontend->domstorage(); 90} 91 92void InspectorDOMStorageAgent::clearFrontend() 93{ 94 m_frontend = 0; 95 disable(0); 96} 97 98void InspectorDOMStorageAgent::restore() 99{ 100 if (isEnabled()) 101 enable(0); 102} 103 104bool InspectorDOMStorageAgent::isEnabled() const 105{ 106 return m_state->getBoolean(DOMStorageAgentState::domStorageAgentEnabled); 107} 108 109void InspectorDOMStorageAgent::enable(ErrorString*) 110{ 111 m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, true); 112 m_instrumentingAgents->setInspectorDOMStorageAgent(this); 113} 114 115void InspectorDOMStorageAgent::disable(ErrorString*) 116{ 117 m_instrumentingAgents->setInspectorDOMStorageAgent(0); 118 m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, false); 119} 120 121void InspectorDOMStorageAgent::getDOMStorageItems(ErrorString* errorString, const RefPtr<JSONObject>& storageId, RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > >& items) 122{ 123 LocalFrame* frame; 124 OwnPtrWillBeRawPtr<StorageArea> storageArea = findStorageArea(errorString, storageId, frame); 125 if (!storageArea) 126 return; 127 128 RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > > storageItems = TypeBuilder::Array<TypeBuilder::Array<String> >::create(); 129 130 TrackExceptionState exceptionState; 131 for (unsigned i = 0; i < storageArea->length(exceptionState, frame); ++i) { 132 String name(storageArea->key(i, exceptionState, frame)); 133 if (hadException(exceptionState, errorString)) 134 return; 135 String value(storageArea->getItem(name, exceptionState, frame)); 136 if (hadException(exceptionState, errorString)) 137 return; 138 RefPtr<TypeBuilder::Array<String> > entry = TypeBuilder::Array<String>::create(); 139 entry->addItem(name); 140 entry->addItem(value); 141 storageItems->addItem(entry); 142 } 143 items = storageItems.release(); 144} 145 146static String toErrorString(ExceptionState& exceptionState) 147{ 148 if (exceptionState.hadException()) 149 return DOMException::getErrorName(exceptionState.code()); 150 return ""; 151} 152 153void InspectorDOMStorageAgent::setDOMStorageItem(ErrorString* errorString, const RefPtr<JSONObject>& storageId, const String& key, const String& value) 154{ 155 LocalFrame* frame; 156 OwnPtrWillBeRawPtr<StorageArea> storageArea = findStorageArea(0, storageId, frame); 157 if (!storageArea) { 158 *errorString = "Storage not found"; 159 return; 160 } 161 162 TrackExceptionState exceptionState; 163 storageArea->setItem(key, value, exceptionState, frame); 164 *errorString = toErrorString(exceptionState); 165} 166 167void InspectorDOMStorageAgent::removeDOMStorageItem(ErrorString* errorString, const RefPtr<JSONObject>& storageId, const String& key) 168{ 169 LocalFrame* frame; 170 OwnPtrWillBeRawPtr<StorageArea> storageArea = findStorageArea(0, storageId, frame); 171 if (!storageArea) { 172 *errorString = "Storage not found"; 173 return; 174 } 175 176 TrackExceptionState exceptionState; 177 storageArea->removeItem(key, exceptionState, frame); 178 *errorString = toErrorString(exceptionState); 179} 180 181PassRefPtr<TypeBuilder::DOMStorage::StorageId> InspectorDOMStorageAgent::storageId(SecurityOrigin* securityOrigin, bool isLocalStorage) 182{ 183 return TypeBuilder::DOMStorage::StorageId::create() 184 .setSecurityOrigin(securityOrigin->toRawString()) 185 .setIsLocalStorage(isLocalStorage).release(); 186} 187 188void InspectorDOMStorageAgent::didDispatchDOMStorageEvent(const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin) 189{ 190 if (!m_frontend || !isEnabled()) 191 return; 192 193 RefPtr<TypeBuilder::DOMStorage::StorageId> id = storageId(securityOrigin, storageType == LocalStorage); 194 195 if (key.isNull()) 196 m_frontend->domStorageItemsCleared(id); 197 else if (newValue.isNull()) 198 m_frontend->domStorageItemRemoved(id, key); 199 else if (oldValue.isNull()) 200 m_frontend->domStorageItemAdded(id, key, newValue); 201 else 202 m_frontend->domStorageItemUpdated(id, key, oldValue, newValue); 203} 204 205PassOwnPtrWillBeRawPtr<StorageArea> InspectorDOMStorageAgent::findStorageArea(ErrorString* errorString, const RefPtr<JSONObject>& storageId, LocalFrame*& targetFrame) 206{ 207 String securityOrigin; 208 bool isLocalStorage = false; 209 bool success = storageId->getString("securityOrigin", &securityOrigin); 210 if (success) 211 success = storageId->getBoolean("isLocalStorage", &isLocalStorage); 212 if (!success) { 213 if (errorString) 214 *errorString = "Invalid storageId format"; 215 return nullptr; 216 } 217 218 LocalFrame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin); 219 if (!frame) { 220 if (errorString) 221 *errorString = "LocalFrame not found for the given security origin"; 222 return nullptr; 223 } 224 targetFrame = frame; 225 226 if (isLocalStorage) 227 return StorageNamespace::localStorageArea(frame->document()->securityOrigin()); 228 return m_pageAgent->page()->sessionStorage()->storageArea(frame->document()->securityOrigin()); 229} 230 231} // namespace blink 232 233