Home | History | Annotate | Download | only in v8
      1 /*
      2  * Copyright (C) 2009 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef DOMDataStore_h
     32 #define DOMDataStore_h
     33 
     34 #include "bindings/v8/DOMWrapperMap.h"
     35 #include "bindings/v8/DOMWrapperWorld.h"
     36 #include "bindings/v8/ScriptWrappable.h"
     37 #include "bindings/v8/WrapperTypeInfo.h"
     38 #include <v8.h>
     39 #include "wtf/Noncopyable.h"
     40 #include "wtf/StdLibExtras.h"
     41 
     42 namespace WebCore {
     43 
     44 class Node;
     45 
     46 class DOMDataStore {
     47     WTF_MAKE_NONCOPYABLE(DOMDataStore);
     48 public:
     49     explicit DOMDataStore(bool isMainWorld);
     50     ~DOMDataStore();
     51 
     52     static DOMDataStore& current(v8::Isolate*);
     53 
     54     // We can use a wrapper stored in a ScriptWrappable when we're in the main world.
     55     // This method does the fast check if we're in the main world. If this method returns true,
     56     // it is guaranteed that we're in the main world. On the other hand, if this method returns
     57     // false, nothing is guaranteed (we might be in the main world).
     58     template<typename T>
     59     static bool canUseScriptWrappable(T* object)
     60     {
     61         return !DOMWrapperWorld::isolatedWorldsExist()
     62             && !canExistInWorker(object)
     63             && ScriptWrappable::wrapperCanBeStoredInObject(object);
     64     }
     65 
     66     template<typename V8T, typename T, typename Wrappable>
     67     static bool setReturnValueFromWrapperFast(v8::ReturnValue<v8::Value> returnValue, T* object, v8::Local<v8::Object> holder, Wrappable* wrappable)
     68     {
     69         if (canUseScriptWrappable(object)) {
     70             ScriptWrappable::assertWrapperSanity<V8T, T>(object, object);
     71             return ScriptWrappable::fromObject(object)->setReturnValue(returnValue);
     72         }
     73         // The second fastest way to check if we're in the main world is to check if
     74         // the wrappable's wrapper is the same as the holder.
     75         // FIXME: Investigate if it's worth having this check for performance.
     76         if (holderContainsWrapper(holder, wrappable)) {
     77             if (ScriptWrappable::wrapperCanBeStoredInObject(object)) {
     78                 ScriptWrappable::assertWrapperSanity<V8T, T>(object, object);
     79                 return ScriptWrappable::fromObject(object)->setReturnValue(returnValue);
     80             }
     81             return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object));
     82         }
     83         return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object);
     84     }
     85 
     86     template<typename V8T, typename T>
     87     static bool setReturnValueFromWrapper(v8::ReturnValue<v8::Value> returnValue, T* object)
     88     {
     89         if (canUseScriptWrappable(object)) {
     90             ScriptWrappable::assertWrapperSanity<V8T, T>(object, object);
     91             return ScriptWrappable::fromObject(object)->setReturnValue(returnValue);
     92         }
     93         return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object);
     94     }
     95 
     96     template<typename V8T, typename T>
     97     static bool setReturnValueFromWrapperForMainWorld(v8::ReturnValue<v8::Value> returnValue, T* object)
     98     {
     99         if (ScriptWrappable::wrapperCanBeStoredInObject(object))
    100             return ScriptWrappable::fromObject(object)->setReturnValue(returnValue);
    101         return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object));
    102     }
    103 
    104     template<typename V8T, typename T>
    105     static v8::Handle<v8::Object> getWrapper(T* object, v8::Isolate* isolate)
    106     {
    107         if (canUseScriptWrappable(object)) {
    108             v8::Handle<v8::Object> result = ScriptWrappable::fromObject(object)->newLocalWrapper(isolate);
    109             // Security: always guard against malicious tampering.
    110             ScriptWrappable::assertWrapperSanity<V8T, T>(result, object);
    111             return result;
    112         }
    113         return current(isolate).template get<V8T>(object, isolate);
    114     }
    115 
    116     template<typename V8T, typename T>
    117     static void setWrapperReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate)
    118     {
    119         if (canUseScriptWrappable(child)) {
    120             ScriptWrappable::assertWrapperSanity<V8T, T>(child, child);
    121             ScriptWrappable::fromObject(child)->setReference(parent, isolate);
    122             return;
    123         }
    124         current(isolate).template setReference<V8T>(parent, child, isolate);
    125     }
    126 
    127     template<typename V8T, typename T>
    128     static void setWrapper(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
    129     {
    130         if (canUseScriptWrappable(object)) {
    131             ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, configuration);
    132             return;
    133         }
    134         return current(isolate).template set<V8T>(object, wrapper, isolate, configuration);
    135     }
    136 
    137     template<typename V8T, typename T>
    138     static bool containsWrapper(T* object, v8::Isolate* isolate)
    139     {
    140         return current(isolate).template containsWrapper<V8T>(object);
    141     }
    142 
    143     template<typename V8T, typename T>
    144     inline v8::Handle<v8::Object> get(T* object, v8::Isolate* isolate)
    145     {
    146         if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld)
    147             return ScriptWrappable::fromObject(object)->newLocalWrapper(isolate);
    148         return m_wrapperMap.newLocal(V8T::toInternalPointer(object), isolate);
    149     }
    150 
    151     template<typename V8T, typename T>
    152     inline void setReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate)
    153     {
    154         if (ScriptWrappable::wrapperCanBeStoredInObject(child) && m_isMainWorld) {
    155             ScriptWrappable::fromObject(child)->setReference(parent, isolate);
    156             return;
    157         }
    158         m_wrapperMap.setReference(parent, V8T::toInternalPointer(child), isolate);
    159     }
    160 
    161     template<typename V8T, typename T>
    162     inline bool setReturnValueFrom(v8::ReturnValue<v8::Value> returnValue, T* object)
    163     {
    164         if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld)
    165             return ScriptWrappable::fromObject(object)->setReturnValue(returnValue);
    166         return m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object));
    167     }
    168 
    169     template<typename V8T, typename T>
    170     inline bool containsWrapper(T* object)
    171     {
    172         if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld)
    173             return ScriptWrappable::fromObject(object)->containsWrapper();
    174         return m_wrapperMap.containsKey(V8T::toInternalPointer(object));
    175     }
    176 
    177 private:
    178     template<typename V8T, typename T>
    179     inline void set(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
    180     {
    181         ASSERT(!!object);
    182         ASSERT(!wrapper.IsEmpty());
    183         if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) {
    184             ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, configuration);
    185             return;
    186         }
    187         m_wrapperMap.set(V8T::toInternalPointer(object), wrapper, configuration);
    188     }
    189 
    190     static bool canExistInWorker(void*) { return true; }
    191     static bool canExistInWorker(Node*) { return false; }
    192 
    193     static bool holderContainsWrapper(v8::Local<v8::Object>, void*)
    194     {
    195         return false;
    196     }
    197 
    198     static bool holderContainsWrapper(v8::Local<v8::Object> holder, ScriptWrappable* wrappable)
    199     {
    200         // Verify our assumptions about the main world.
    201         ASSERT(wrappable);
    202         ASSERT(!wrappable->containsWrapper() || !wrappable->isEqualTo(holder) || current(v8::Isolate::GetCurrent()).m_isMainWorld);
    203         return wrappable->isEqualTo(holder);
    204     }
    205 
    206     bool m_isMainWorld;
    207     DOMWrapperMap<void> m_wrapperMap;
    208 };
    209 
    210 } // namespace WebCore
    211 
    212 #endif // DOMDataStore_h
    213