/*
 *  Copyright (C) 2010 Igalia S.L.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "DOMObjectCache.h"

#include "Document.h"
#include "Node.h"
#include "glib-object.h"
#include <wtf/HashMap.h>

namespace WebKit {

typedef struct {
    GObject* object;
    WebCore::Frame* frame;
    guint timesReturned;
} DOMObjectCacheData;

typedef HashMap<void*, DOMObjectCacheData*> DOMObjectMap;

static DOMObjectMap& domObjects()
{
    static DOMObjectMap staticDOMObjects;
    return staticDOMObjects;
}

static WebCore::Frame* getFrameFromHandle(void* objectHandle)
{
    WebCore::Node* node = static_cast<WebCore::Node*>(objectHandle);
    if (!node->inDocument())
        return 0;
    WebCore::Document* document = node->document();
    if (!document)
        return 0;
    return document->frame();
}

void DOMObjectCache::forget(void* objectHandle)
{
    DOMObjectCacheData* cacheData = domObjects().get(objectHandle);
    ASSERT(cacheData);
    g_slice_free(DOMObjectCacheData, cacheData);
    domObjects().take(objectHandle);
}

static void weakRefNotify(gpointer data, GObject* zombie)
{
    gboolean* objectDead = static_cast<gboolean*>(data);
    *objectDead = TRUE;
}

void DOMObjectCache::clearByFrame(WebCore::Frame* frame)
{
    Vector<DOMObjectCacheData*> toUnref;

    // Unreffing the objects removes them from the cache in their
    // finalize method, so just save them to do that while we are not
    // iterating the cache itself.
    DOMObjectMap::iterator end = domObjects().end();
    for (DOMObjectMap::iterator iter = domObjects().begin(); iter != end; ++iter) {
        DOMObjectCacheData* data = iter->second;
        ASSERT(data);
        if ((!frame || data->frame == frame) && data->timesReturned)
            toUnref.append(data);
    }

    Vector<DOMObjectCacheData*>::iterator last = toUnref.end();
    for (Vector<DOMObjectCacheData*>::iterator it = toUnref.begin(); it != last; ++it) {
        DOMObjectCacheData* data = *it;
        // We can't really know what the user has done with the DOM
        // objects, so in case any of the external references to them
        // were unreffed (but not all, otherwise the object would be
        // dead and out of the cache) we'll add a weak ref before we
        // start to get rid of the cache's own references; if the
        // object dies in the middle of the process, we'll just stop.
        gboolean objectDead = FALSE;
        g_object_weak_ref(data->object, weakRefNotify, &objectDead);
        // We need to check objectDead first, otherwise the cache data
        // might be garbage already.
        while (!objectDead && data->timesReturned > 0) {
            // If this is the last unref we are going to do,
            // disconnect the weak ref. We cannot do it afterwards
            // because the object might be dead at that point.
            if (data->timesReturned == 1)
                g_object_weak_unref(data->object, weakRefNotify, &objectDead);
            data->timesReturned--;
            g_object_unref(data->object);
        }
    }
}

DOMObjectCache::~DOMObjectCache()
{
    clearByFrame();
}

void* DOMObjectCache::get(void* objectHandle)
{
    DOMObjectCacheData* data = domObjects().get(objectHandle);
    if (!data)
        return 0;

    // We want to add one ref each time a wrapper is returned, so that
    // the user can manually unref them if he chooses to.
    ASSERT(data->object);
    data->timesReturned++;
    return g_object_ref(data->object);
}

void* DOMObjectCache::put(void* objectHandle, void* wrapper)
{
    if (domObjects().get(objectHandle))
        return wrapper;

    DOMObjectCacheData* data = g_slice_new(DOMObjectCacheData);
    data->object = static_cast<GObject*>(wrapper);
    data->frame = 0;
    data->timesReturned = 1;

    domObjects().set(objectHandle, data);
    return wrapper;
}

void* DOMObjectCache::put(WebCore::Node* objectHandle, void* wrapper)
{
    // call the ::put version that takes void* to do the basic cache
    // insertion work
    put(static_cast<void*>(objectHandle), wrapper);

    DOMObjectCacheData* data = domObjects().get(objectHandle);
    ASSERT(data);

    data->frame = getFrameFromHandle(objectHandle);

    return wrapper;
}

}
