Home | History | Annotate | Download | only in inspector
      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