/*
 * Copyright (C) 2010 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 ScriptWrappable_h
#define ScriptWrappable_h

#include "bindings/v8/UnsafePersistent.h"
#include "bindings/v8/V8Utilities.h"
#include "bindings/v8/WrapperTypeInfo.h"
#include <v8.h>

// Helper to call webCoreInitializeScriptWrappableForInterface in the global namespace.
template <class C> inline void initializeScriptWrappableHelper(C* object)
{
    void webCoreInitializeScriptWrappableForInterface(C*);
    webCoreInitializeScriptWrappableForInterface(object);
}

namespace WebCore {

class ScriptWrappable {
public:
    ScriptWrappable() : m_wrapperOrTypeInfo(0) { }

    // Wrappables need to be initialized with their most derrived type for which
    // bindings exist, in much the same way that certain other types need to be
    // adopted and so forth. The overloaded initializeScriptWrappableForInterface()
    // functions are implemented by the generated V8 bindings code. Declaring the
    // extern function in the template avoids making a centralized header of all
    // the bindings in the universe. C++11's extern template feature may provide
    // a cleaner solution someday.
    template <class C> static void init(C* object)
    {
        initializeScriptWrappableHelper(object);
    }

    void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
    {
        ASSERT(!containsWrapper());
        if (!*wrapper) {
            m_wrapperOrTypeInfo = 0;
            return;
        }
        v8::Persistent<v8::Object> persistent(isolate, wrapper);
        configuration.configureWrapper(&persistent);
        persistent.MakeWeak(this, &makeWeakCallback);
        m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(persistent.ClearAndLeak()) | 1;
        ASSERT(containsWrapper());
    }

    v8::Local<v8::Object> newLocalWrapper(v8::Isolate* isolate) const
    {
        return unsafePersistent().newLocal(isolate);
    }

    const WrapperTypeInfo* typeInfo()
    {
        if (containsTypeInfo())
            return reinterpret_cast<const WrapperTypeInfo*>(m_wrapperOrTypeInfo);

        if (containsWrapper())
            return toWrapperTypeInfo(*(unsafePersistent().persistent()));

        return 0;
    }

    void setTypeInfo(const WrapperTypeInfo* info)
    {
        m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(info);
        ASSERT(containsTypeInfo());
    }

    static bool wrapperCanBeStoredInObject(const void*) { return false; }
    static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true; }

    static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&)
    {
        ASSERT_NOT_REACHED();
    }

    static void setWrapperInObject(ScriptWrappable* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
    {
        object->setWrapper(wrapper, isolate, configuration);
    }

    static const WrapperTypeInfo* getTypeInfoFromObject(void* object)
    {
        ASSERT_NOT_REACHED();
        return 0;
    }

    static const WrapperTypeInfo* getTypeInfoFromObject(ScriptWrappable* object)
    {
        return object->typeInfo();
    }

    static void setTypeInfoInObject(void* object, const WrapperTypeInfo* info)
    {
        ASSERT_NOT_REACHED();
    }

    static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeInfo* info)
    {
        object->setTypeInfo(info);
    }

    template<typename V8T, typename T>
    static bool setReturnValueWithSecurityCheck(v8::ReturnValue<v8::Value> returnValue, T* object)
    {
        return ScriptWrappable::getUnsafeWrapperFromObject(object).template setReturnValueWithSecurityCheck<V8T>(returnValue, object);
    }

    template<typename T>
    static bool setReturnValue(v8::ReturnValue<v8::Value> returnValue, T* object)
    {
        return ScriptWrappable::getUnsafeWrapperFromObject(object).setReturnValue(returnValue);
    }

protected:
    ~ScriptWrappable()
    {
        ASSERT(m_wrapperOrTypeInfo);  // Assert initialization via init() even if not subsequently wrapped.
        m_wrapperOrTypeInfo = 0;      // Break UAF attempts to wrap.
    }

private:
    // For calling unsafePersistent and getWrapperFromObject.
    friend class MinorGCWrapperVisitor;
    friend class DOMDataStore;

    UnsafePersistent<v8::Object> unsafePersistent() const
    {
        v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m_wrapperOrTypeInfo & ~1) : 0;
        return UnsafePersistent<v8::Object>(object);
    }

    static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(void*)
    {
        ASSERT_NOT_REACHED();
        return UnsafePersistent<v8::Object>();
    }

    static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(ScriptWrappable* object)
    {
        return object->unsafePersistent();
    }

    inline bool containsWrapper() const { return (m_wrapperOrTypeInfo & 1) == 1; }
    inline bool containsTypeInfo() const { return m_wrapperOrTypeInfo && (m_wrapperOrTypeInfo & 1) == 0; }

    inline void disposeWrapper(v8::Persistent<v8::Object>* value, const WrapperTypeInfo* info)
    {
        ASSERT(containsWrapper());
        ASSERT(*reinterpret_cast<uintptr_t*>(value) == (m_wrapperOrTypeInfo & ~1));
        value->Dispose();
        setTypeInfo(info);
    }

    // If zero, then this contains nothing, otherwise:
    //   If the bottom bit it set, then this contains a pointer to a wrapper object in the remainging bits.
    //   If the bottom bit is clear, then this contains a pointer to the wrapper type info in the remaining bits.
    uintptr_t m_wrapperOrTypeInfo;

    static void makeWeakCallback(v8::Isolate* isolate, v8::Persistent<v8::Object>* wrapper, ScriptWrappable* key)
    {
        ASSERT(*(key->unsafePersistent().persistent()) == *wrapper);

        // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn't a left-most base class.
        void* object = toNative(*wrapper);
        const WrapperTypeInfo* info = toWrapperTypeInfo(*wrapper);
        ASSERT(info->derefObjectFunction);

        key->disposeWrapper(wrapper, info);
        // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed
        // inside key->deref(), which causes Node destructions. We should
        // make Node destructions incremental.
        info->derefObject(object);
    }
};

} // namespace WebCore

#endif // ScriptWrappable_h
