/* * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef V8PerContextData_h #define V8PerContextData_h #include "bindings/v8/CustomElementBinding.h" #include "bindings/v8/ScopedPersistent.h" #include "bindings/v8/UnsafePersistent.h" #include "bindings/v8/V8DOMActivityLogger.h" #include "bindings/v8/WrapperTypeInfo.h" #include "gin/public/context_holder.h" #include "gin/public/gin_embedders.h" #include #include "wtf/HashMap.h" #include "wtf/PassOwnPtr.h" #include "wtf/Vector.h" #include "wtf/text/AtomicString.h" #include "wtf/text/AtomicStringHash.h" namespace WebCore { class CustomElementDefinition; class DOMWrapperWorld; class V8PerContextData; struct V8NPObject; typedef WTF::Vector V8NPObjectVector; typedef WTF::HashMap V8NPObjectMap; enum V8ContextEmbedderDataField { v8ContextDebugIdIndex = static_cast(gin::kDebugIdIndex), v8ContextPerContextDataIndex = static_cast(gin::kPerContextDataStartIndex + gin::kEmbedderBlink), }; class V8PerContextDataHolder { WTF_MAKE_NONCOPYABLE(V8PerContextDataHolder); public: static void install(v8::Handle context) { new V8PerContextDataHolder(context); } static V8PerContextDataHolder* from(v8::Handle context) { return static_cast(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); } V8PerContextData* perContextData() const { return m_perContextData; } void setPerContextData(V8PerContextData* data) { m_perContextData = data; } DOMWrapperWorld* isolatedWorld() const { return m_isolatedWorld; } void setIsolatedWorld(DOMWrapperWorld* world) { m_isolatedWorld = world; } private: explicit V8PerContextDataHolder(v8::Handle context) : m_context(v8::Isolate::GetCurrent(), context) , m_perContextData(0) , m_isolatedWorld(0) { m_context.SetWeak(this, &V8PerContextDataHolder::weakCallback); context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, this); } ~V8PerContextDataHolder() {} static void weakCallback(const v8::WeakCallbackData& data) { data.GetValue()->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, 0); data.GetParameter()->m_context.Reset(); delete data.GetParameter(); } v8::Persistent m_context; V8PerContextData* m_perContextData; DOMWrapperWorld* m_isolatedWorld; }; class V8PerContextData { public: static PassOwnPtr create(v8::Handle context) { return adoptPtr(new V8PerContextData(context)); } ~V8PerContextData() { dispose(); } bool init(); static V8PerContextData* from(v8::Handle context) { return V8PerContextDataHolder::from(context)->perContextData(); } // To create JS Wrapper objects, we create a cache of a 'boiler plate' // object, and then simply Clone that object each time we need a new one. // This is faster than going through the full object creation process. v8::Local createWrapperFromCache(const WrapperTypeInfo* type) { UnsafePersistent boilerplate = m_wrapperBoilerplates.get(type); return !boilerplate.isEmpty() ? boilerplate.newLocal(v8::Isolate::GetCurrent())->Clone() : createWrapperFromCacheSlowCase(type); } v8::Local constructorForType(const WrapperTypeInfo* type) { UnsafePersistent function = m_constructorMap.get(type); if (!function.isEmpty()) return function.newLocal(v8::Isolate::GetCurrent()); return constructorForTypeSlowCase(type); } v8::Local prototypeForType(const WrapperTypeInfo*); V8NPObjectMap* v8NPObjectMap() { return &m_v8NPObjectMap; } V8DOMActivityLogger* activityLogger() { return m_activityLogger; } void setActivityLogger(V8DOMActivityLogger* logger) { m_activityLogger = logger; } void addCustomElementBinding(CustomElementDefinition*, PassOwnPtr); void clearCustomElementBinding(CustomElementDefinition*); CustomElementBinding* customElementBinding(CustomElementDefinition*); private: explicit V8PerContextData(v8::Handle context) : m_activityLogger(0) , m_isolate(v8::Isolate::GetCurrent()) , m_context(m_isolate, context) , m_customElementBindings(adoptPtr(new CustomElementBindingMap())) { } void dispose(); v8::Local createWrapperFromCacheSlowCase(const WrapperTypeInfo*); v8::Local constructorForTypeSlowCase(const WrapperTypeInfo*); // For each possible type of wrapper, we keep a boilerplate object. // The boilerplate is used to create additional wrappers of the same type. typedef WTF::HashMap > WrapperBoilerplateMap; WrapperBoilerplateMap m_wrapperBoilerplates; typedef WTF::HashMap > ConstructorMap; ConstructorMap m_constructorMap; V8NPObjectMap m_v8NPObjectMap; // We cache a pointer to the V8DOMActivityLogger associated with the world // corresponding to this context. The ownership of the pointer is retained // by the DOMActivityLoggerMap in DOMWrapperWorld. V8DOMActivityLogger* m_activityLogger; v8::Isolate* m_isolate; v8::Persistent m_context; ScopedPersistent m_errorPrototype; typedef WTF::HashMap > CustomElementBindingMap; OwnPtr m_customElementBindings; }; class V8PerContextDebugData { public: static bool setContextDebugData(v8::Handle, const char* worldName, int debugId); static int contextDebugId(v8::Handle); }; } // namespace WebCore #endif // V8PerContextData_h