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