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