/*
 * Copyright (C) 2011 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 */

#include "config.h"
#include "WebIconDatabaseProxy.h"

#include "DataReference.h"
#include "MessageID.h"
#include "WebIconDatabaseMessages.h"
#include "WebProcess.h"
#include <WebCore/SharedBuffer.h>
#include <wtf/text/WTFString.h>

using namespace WebCore;

namespace WebKit {

WebIconDatabaseProxy::~WebIconDatabaseProxy()
{
}

WebIconDatabaseProxy::WebIconDatabaseProxy(WebProcess* process)
    : m_isEnabled(false)
    , m_process(process)
{
}

bool WebIconDatabaseProxy::isEnabled() const
{
    return m_isEnabled;
}

void WebIconDatabaseProxy::setEnabled(bool enabled)
{
    if (enabled == m_isEnabled)
        return;
    
    m_isEnabled = enabled;
    setGlobalIconDatabase(enabled ? this : 0);
}


void WebIconDatabaseProxy::retainIconForPageURL(const String& pageURL)
{
    m_process->connection()->send(Messages::WebIconDatabase::RetainIconForPageURL(pageURL), 0);
}

void WebIconDatabaseProxy::releaseIconForPageURL(const String& pageURL)
{
    m_process->connection()->send(Messages::WebIconDatabase::ReleaseIconForPageURL(pageURL), 0);
}

Image* WebIconDatabaseProxy::synchronousIconForPageURL(const String& pageURL, const IntSize& /*size*/)
{
    CoreIPC::DataReference result;
    if (!m_process->connection()->sendSync(Messages::WebIconDatabase::SynchronousIconDataForPageURL(pageURL), Messages::WebIconDatabase::SynchronousIconDataForPageURL::Reply(result), 0))
        return 0;
    
    // FIXME: Return Image created with the above data.
    return 0;
}


String WebIconDatabaseProxy::synchronousIconURLForPageURL(const String& /*pageURL*/)
{
    // FIXME: This needs to ask the UI process for the iconURL, but it can't do so synchronously because it will slow down page loading.
    // The parts in WebCore that need this data will have to be changed to work asycnchronously.
    return String();
}

bool WebIconDatabaseProxy::synchronousIconDataKnownForIconURL(const String& /*iconURL*/)
{
    // FIXME: This needs to ask the UI process for the iconURL, but it can't do so synchronously because it will slow down page loading.
    // The parts in WebCore that need this data will have to be changed to work asycnchronously.
    return false;
}

IconLoadDecision WebIconDatabaseProxy::synchronousLoadDecisionForIconURL(const String& /*iconURL*/, DocumentLoader*)
{
    // FIXME: This needs to ask the UI process for the iconURL, but it can't do so synchronously because it will slow down page loading.
    // The parts in WebCore that need this data will have to be changed to work asycnchronously.
    return IconLoadNo;
}

bool WebIconDatabaseProxy::supportsAsynchronousMode()
{
    return true;
}

void WebIconDatabaseProxy::loadDecisionForIconURL(const String& iconURL, PassRefPtr<WebCore::IconLoadDecisionCallback> callback)
{
    uint64_t id = callback->callbackID();
    m_iconLoadDecisionCallbacks.add(id, callback);
    
    m_process->connection()->send(Messages::WebIconDatabase::GetLoadDecisionForIconURL(iconURL, id), 0);
}

void WebIconDatabaseProxy::receivedIconLoadDecision(int decision, uint64_t callbackID)
{
    RefPtr<WebCore::IconLoadDecisionCallback> callback = m_iconLoadDecisionCallbacks.take(callbackID);
    if (callback)
        callback->performCallback(static_cast<WebCore::IconLoadDecision>(decision));
}

void WebIconDatabaseProxy::iconDataForIconURL(const String& /*iconURL*/, PassRefPtr<WebCore::IconDataCallback>)
{
}

void WebIconDatabaseProxy::setIconURLForPageURL(const String& iconURL, const String& pageURL)
{
    m_process->connection()->send(Messages::WebIconDatabase::SetIconURLForPageURL(iconURL, pageURL), 0);
}

void WebIconDatabaseProxy::setIconDataForIconURL(PassRefPtr<SharedBuffer> iconData, const String& iconURL)
{
    CoreIPC::DataReference data(reinterpret_cast<const uint8_t*>(iconData ? iconData->data() : 0), iconData ? iconData->size() : 0);
    m_process->connection()->send(Messages::WebIconDatabase::SetIconDataForIconURL(data, iconURL), 0);
}

void WebIconDatabaseProxy::urlImportFinished()
{
}

void WebIconDatabaseProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
{
    didReceiveWebIconDatabaseProxyMessage(connection, messageID, arguments);
}

} // namespace WebKit
