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(WrapperWorldType); 50 ~DOMDataStore(); 51 52 static DOMDataStore& current(v8::Isolate*); 53 54 template<typename V8T, typename T, typename Wrappable> 55 static bool setReturnValueFromWrapperFast(v8::ReturnValue<v8::Value> returnValue, T* object, v8::Local<v8::Object> holder, Wrappable* wrappable) 56 { 57 // What we'd really like to check here is whether we're in the 58 // main world or in an isolated world. The fastest way to do that 59 // is to check that there is no isolated world and the 'object' 60 // is an object that can exist in the main world. The second fastest 61 // way is to check whether the wrappable's wrapper is the same as 62 // the holder. 63 if ((!DOMWrapperWorld::isolatedWorldsExist() && !canExistInWorker(object)) || holderContainsWrapper(holder, wrappable)) { 64 if (ScriptWrappable::wrapperCanBeStoredInObject(object)) 65 return ScriptWrappable::setReturnValueWithSecurityCheck<V8T>(returnValue, object); 66 return mainWorldStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); 67 } 68 return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object); 69 } 70 71 template<typename V8T, typename T> 72 static bool setReturnValueFromWrapper(v8::ReturnValue<v8::Value> returnValue, T* object) 73 { 74 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { 75 if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) 76 return ScriptWrappable::setReturnValueWithSecurityCheck<V8T>(returnValue, object); 77 } 78 return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object); 79 } 80 81 template<typename V8T, typename T> 82 static bool setReturnValueFromWrapperForMainWorld(v8::ReturnValue<v8::Value> returnValue, T* object) 83 { 84 if (ScriptWrappable::wrapperCanBeStoredInObject(object)) 85 return ScriptWrappable::setReturnValue(returnValue, object); 86 return mainWorldStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); 87 } 88 89 template<typename V8T, typename T> 90 static v8::Handle<v8::Object> getWrapper(T* object, v8::Isolate* isolate) 91 { 92 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { 93 if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { 94 v8::Handle<v8::Object> result = ScriptWrappable::getUnsafeWrapperFromObject(object).newLocal(isolate); 95 // Security: always guard against malicious tampering. 96 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(object)); 97 return result; 98 } 99 } 100 return current(isolate).template get<V8T>(object, isolate); 101 } 102 103 template<typename V8T, typename T> 104 static void setWrapperReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate) 105 { 106 if (ScriptWrappable::wrapperCanBeStoredInObject(child) && !canExistInWorker(child)) { 107 if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { 108 UnsafePersistent<v8::Object> unsafePersistent = ScriptWrappable::getUnsafeWrapperFromObject(child); 109 // Security: always guard against malicious tampering. 110 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(unsafePersistent.isEmpty() || unsafePersistent.value()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(child)); 111 unsafePersistent.setReferenceFrom(parent, isolate); 112 } 113 } 114 current(isolate).template setReference<V8T>(parent, child, isolate); 115 } 116 117 template<typename V8T, typename T> 118 static void setWrapper(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) 119 { 120 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { 121 if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { 122 ScriptWrappable::setWrapperInObject(object, wrapper, isolate, configuration); 123 return; 124 } 125 } 126 return current(isolate).template set<V8T>(object, wrapper, isolate, configuration); 127 } 128 129 template<typename V8T, typename T> 130 static bool containsWrapper(T* object, v8::Isolate* isolate) 131 { 132 return current(isolate).template containsWrapper<V8T>(object); 133 } 134 135 template<typename V8T, typename T> 136 inline v8::Handle<v8::Object> get(T* object, v8::Isolate* isolate) 137 { 138 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) 139 return ScriptWrappable::getUnsafeWrapperFromObject(object).newLocal(isolate); 140 return m_wrapperMap.newLocal(V8T::toInternalPointer(object), isolate); 141 } 142 143 template<typename V8T, typename T> 144 inline void setReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate) 145 { 146 if (ScriptWrappable::wrapperCanBeStoredInObject(child) && m_type == MainWorld) { 147 ScriptWrappable::getUnsafeWrapperFromObject(child).setReferenceFrom(parent, isolate); 148 return; 149 } 150 m_wrapperMap.setReference(parent, V8T::toInternalPointer(child), isolate); 151 } 152 153 template<typename V8T, typename T> 154 inline bool setReturnValueFrom(v8::ReturnValue<v8::Value> returnValue, T* object) 155 { 156 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) 157 return ScriptWrappable::setReturnValue(returnValue, object); 158 return m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); 159 } 160 161 template<typename V8T, typename T> 162 inline bool containsWrapper(T* object) 163 { 164 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) 165 return !ScriptWrappable::getUnsafeWrapperFromObject(object).isEmpty(); 166 return m_wrapperMap.containsKey(V8T::toInternalPointer(object)); 167 } 168 169 private: 170 template<typename V8T, typename T> 171 inline void set(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) 172 { 173 ASSERT(!!object); 174 ASSERT(!wrapper.IsEmpty()); 175 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) { 176 ScriptWrappable::setWrapperInObject(object, wrapper, isolate, configuration); 177 return; 178 } 179 m_wrapperMap.set(V8T::toInternalPointer(object), wrapper, configuration); 180 } 181 182 static DOMDataStore& mainWorldStore(); 183 184 static bool canExistInWorker(void*) { return true; } 185 static bool canExistInWorker(Node*) { return false; } 186 187 static bool holderContainsWrapper(v8::Local<v8::Object>, void*) 188 { 189 return false; 190 } 191 192 static bool holderContainsWrapper(v8::Local<v8::Object> holder, ScriptWrappable* wrappable) 193 { 194 // Verify our assumptions about the main world. 195 UnsafePersistent<v8::Object> unsafePersistent = wrappable->unsafePersistent(); 196 ASSERT(unsafePersistent.isEmpty() || !(holder == *unsafePersistent.persistent()) || current(v8::Isolate::GetCurrent()).m_type == MainWorld); 197 return holder == *unsafePersistent.persistent(); 198 } 199 200 WrapperWorldType m_type; 201 DOMWrapperMap<void> m_wrapperMap; 202 }; 203 204 } // namespace WebCore 205 206 #endif // DOMDataStore_h 207