/*
 * Copyright (C) 2010-2017 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 "VisitedLinkStore.h"

#include "VisitedLinkStoreMessages.h"
#include "VisitedLinkTableControllerMessages.h"
#include "WebProcessMessages.h"
#include "WebProcessPool.h"
#include "WebProcessProxy.h"

using namespace WebCore;

namespace WebKit {

Ref<VisitedLinkStore> VisitedLinkStore::create()
{
    return adoptRef(*new VisitedLinkStore);
}

VisitedLinkStore::~VisitedLinkStore()
{
    for (WebProcessProxy* process : m_processes) {
        process->removeMessageReceiver(Messages::VisitedLinkStore::messageReceiverName(), identifier());
        process->didDestroyVisitedLinkStore(*this);
    }
}

VisitedLinkStore::VisitedLinkStore()
    : m_linkHashStore(*this)
{
}

void VisitedLinkStore::addProcess(WebProcessProxy& process)
{
    ASSERT(process.state() == WebProcessProxy::State::Running);

    if (!m_processes.add(&process).isNewEntry)
        return;

    process.addMessageReceiver(Messages::VisitedLinkStore::messageReceiverName(), identifier(), *this);

    if (m_linkHashStore.isEmpty())
        return;

    sendStoreHandleToProcess(process);
}

void VisitedLinkStore::removeProcess(WebProcessProxy& process)
{
    ASSERT(m_processes.contains(&process));

    m_processes.remove(&process);
    process.removeMessageReceiver(Messages::VisitedLinkStore::messageReceiverName(), identifier());
}

void VisitedLinkStore::addVisitedLinkHash(SharedStringHash linkHash)
{
    m_linkHashStore.scheduleAddition(linkHash);
}

bool VisitedLinkStore::containsVisitedLinkHash(WebCore::SharedStringHash linkHash)
{
    return m_linkHashStore.contains(linkHash);
}

void VisitedLinkStore::removeVisitedLinkHash(WebCore::SharedStringHash linkHash)
{
    m_linkHashStore.scheduleRemoval(linkHash);
}

void VisitedLinkStore::removeAll()
{
    m_linkHashStore.clear();

    for (WebProcessProxy* process : m_processes) {
        ASSERT(process->processPool().processes().contains(process));
        process->send(Messages::VisitedLinkTableController::RemoveAllVisitedLinks(), identifier());
    }
}

void VisitedLinkStore::webProcessWillOpenConnection(WebProcessProxy&, IPC::Connection&)
{
    // FIXME: Implement.
}

void VisitedLinkStore::webProcessDidCloseConnection(WebProcessProxy&, IPC::Connection&)
{
    // FIXME: Implement.
}

void VisitedLinkStore::addVisitedLinkHashFromPage(uint64_t pageID, SharedStringHash linkHash)
{
    if (auto* webPageProxy = WebProcessProxy::webPage(pageID)) {
        if (!webPageProxy->addsVisitedLinks())
            return;
    }

    addVisitedLinkHash(linkHash);
}

void VisitedLinkStore::sendStoreHandleToProcess(WebProcessProxy& process)
{
    ASSERT(process.processPool().processes().contains(&process));

    SharedMemory::Handle handle;
    if (!m_linkHashStore.createSharedMemoryHandle(handle))
        return;

    process.send(Messages::VisitedLinkTableController::SetVisitedLinkTable(handle), identifier());
}

void VisitedLinkStore::didInvalidateSharedMemory()
{
    for (WebProcessProxy* process : m_processes)
        sendStoreHandleToProcess(*process);
}

void VisitedLinkStore::didUpdateSharedStringHashes(const Vector<WebCore::SharedStringHash>& addedHashes, const Vector<WebCore::SharedStringHash>& removedHashes)
{
    ASSERT(!addedHashes.isEmpty() || !removedHashes.isEmpty());

    for (auto* process : m_processes) {
        ASSERT(process->processPool().processes().contains(process));

        if (addedHashes.size() > 20 || !removedHashes.isEmpty())
            process->send(Messages::VisitedLinkTableController::AllVisitedLinkStateChanged(), identifier());
        else
            process->send(Messages::VisitedLinkTableController::VisitedLinkStateChanged(addedHashes), identifier());
    }
}

} // namespace WebKit
