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

#include "DataReference.h"
#include "Logging.h"
#include "SessionState.h"
#include "WebBackForwardList.h"
#include "WebData.h"
#include "WebPageMessages.h"
#include "WebProcessProxy.h"

#include <wtf/RetainPtr.h>
#include <CoreFoundation/CFPropertyList.h>

using namespace WebCore;

namespace WebKit {

DEFINE_STATIC_GETTER(CFStringRef, SessionHistoryKey, (CFSTR("SessionHistory")));
DEFINE_STATIC_GETTER(CFStringRef, ProvisionalURLKey, (CFSTR("ProvisionalURL")));

static const UInt32 CurrentSessionStateDataVersion = 2;

PassRefPtr<WebData> WebPageProxy::sessionStateData(WebPageProxySessionStateFilterCallback filter, void* context) const
{
    const void* keys[2];
    const void* values[2];
    CFIndex numValues = 0;

    RetainPtr<CFDictionaryRef> sessionHistoryDictionary(AdoptCF, m_backForwardList->createCFDictionaryRepresentation(filter, context));
    if (sessionHistoryDictionary) {
        keys[numValues] = SessionHistoryKey();
        values[numValues] = sessionHistoryDictionary.get();
        ++numValues;
    }

    RetainPtr<CFStringRef> provisionalURLString;
    if (m_mainFrame) {
        String provisionalURL = pendingAPIRequestURL();
        if (provisionalURL.isEmpty())
            provisionalURL = m_mainFrame->provisionalURL();
        if (!provisionalURL.isEmpty()) {
            provisionalURLString.adoptCF(provisionalURL.createCFString());
            keys[numValues] = ProvisionalURLKey();
            values[numValues] = provisionalURLString.get();
            ++numValues;
        }
    }

    if (!numValues)
        return 0;

    RetainPtr<CFDictionaryRef> stateDictionary(AdoptCF, CFDictionaryCreate(0, keys, values, numValues, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));

    RetainPtr<CFWriteStreamRef> writeStream(AdoptCF, CFWriteStreamCreateWithAllocatedBuffers(0, 0));
    if (!writeStream)
        return 0;
    
    if (!CFWriteStreamOpen(writeStream.get()))
        return 0;
        
    if (!CFPropertyListWriteToStream(stateDictionary.get(), writeStream.get(), kCFPropertyListBinaryFormat_v1_0, 0))
        return 0;
        
    RetainPtr<CFDataRef> stateCFData(AdoptCF, (CFDataRef)CFWriteStreamCopyProperty(writeStream.get(), kCFStreamPropertyDataWritten));

    CFIndex length = CFDataGetLength(stateCFData.get());
    Vector<unsigned char> stateVector(length + sizeof(UInt32));
    
    // Put the session state version number at the start of the buffer
    stateVector.data()[0] = (CurrentSessionStateDataVersion & 0xFF000000) >> 24;
    stateVector.data()[1] = (CurrentSessionStateDataVersion & 0x00FF0000) >> 16;
    stateVector.data()[2] = (CurrentSessionStateDataVersion & 0x0000FF00) >> 8;
    stateVector.data()[3] = (CurrentSessionStateDataVersion & 0x000000FF);
    
    // Copy in the actual session state data
    CFDataGetBytes(stateCFData.get(), CFRangeMake(0, length), stateVector.data() + sizeof(UInt32));
    
    return WebData::create(stateVector);
}

void WebPageProxy::restoreFromSessionStateData(WebData* webData)
{
    if (!webData || webData->size() < sizeof(UInt32))
        return;

    const unsigned char* buffer = webData->bytes();
    UInt32 versionHeader = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
    
    if (versionHeader != CurrentSessionStateDataVersion) {
        LOG(SessionState, "Unrecognized version header for session state data - cannot restore");
        return;
    }
    
    RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, webData->bytes() + sizeof(UInt32), webData->size() - sizeof(UInt32)));

    CFStringRef propertyListError = 0;
    RetainPtr<CFPropertyListRef> propertyList(AdoptCF, CFPropertyListCreateFromXMLData(0, data.get(), kCFPropertyListImmutable, &propertyListError));
    if (propertyListError) {
        CFRelease(propertyListError);
        LOG(SessionState, "Could not read session state property list");
        return;
    }

    if (!propertyList)
        return;
        
    if (CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID()) {
        LOG(SessionState, "SessionState property list is not a CFDictionaryRef (%i) - its CFTypeID is %i", (int)CFDictionaryGetTypeID(), (int)CFGetTypeID(propertyList.get()));
        return;
    }

    CFDictionaryRef backForwardListDictionary = 0;
    if (CFTypeRef value = CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyList.get()), SessionHistoryKey())) {
        if (CFGetTypeID(value) != CFDictionaryGetTypeID())
            LOG(SessionState, "SessionState dictionary has a SessionHistory key, but the value is not a dictionary");
        else
            backForwardListDictionary = static_cast<CFDictionaryRef>(value);
    }

    CFStringRef provisionalURL = 0;
    if (CFTypeRef value = CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyList.get()), ProvisionalURLKey())) {
        if (CFGetTypeID(value) != CFStringGetTypeID())
            LOG(SessionState, "SessionState dictionary has a ProvisionalValue key, but the value is not a string");
        else
            provisionalURL = static_cast<CFStringRef>(value);
    }

    if (backForwardListDictionary) {
        if (!m_backForwardList->restoreFromCFDictionaryRepresentation(backForwardListDictionary))
            LOG(SessionState, "Failed to restore back/forward list from SessionHistory dictionary");
        else {
            const BackForwardListItemVector& entries = m_backForwardList->entries();
            if (size_t size = entries.size()) {
                for (size_t i = 0; i < size; ++i)
                    process()->registerNewWebBackForwardListItem(entries[i].get());

                SessionState state(m_backForwardList->entries(), m_backForwardList->currentIndex());
                if (provisionalURL)
                    process()->send(Messages::WebPage::RestoreSession(state), m_pageID);
                else {
                    if (WebBackForwardListItem* item = m_backForwardList->currentItem())
                        setPendingAPIRequestURL(item->url());

                    process()->send(Messages::WebPage::RestoreSessionAndNavigateToCurrentItem(state), m_pageID);
                }
            }
        }
    }

    if (provisionalURL)
        loadURL(provisionalURL);
}

static RetainPtr<CFStringRef> autosaveKey(const String& name)
{
    String key = "com.apple.WebKit.searchField:" + name;
    return RetainPtr<CFStringRef>(AdoptCF, key.createCFString());
}

void WebPageProxy::saveRecentSearches(const String& name, const Vector<String>& searchItems)
{
    // The WebProcess shouldn't have bothered to send this message if the name was empty.
    ASSERT(!name.isEmpty());

    RetainPtr<CFMutableArrayRef> items;

    if (size_t size = searchItems.size()) {
        items.adoptCF(CFArrayCreateMutable(0, size, &kCFTypeArrayCallBacks));
        for (size_t i = 0; i < size; ++i) {
            RetainPtr<CFStringRef> item(AdoptCF, searchItems[i].createCFString());
            CFArrayAppendValue(items.get(), item.get());
        }
    }

    CFPreferencesSetAppValue(autosaveKey(name).get(), items.get(), kCFPreferencesCurrentApplication);
    CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
}

void WebPageProxy::loadRecentSearches(const String& name, Vector<String>& searchItems)
{
    // The WebProcess shouldn't have bothered to send this message if the name was empty.
    ASSERT(!name.isEmpty());

    searchItems.clear();
    RetainPtr<CFArrayRef> items(AdoptCF, reinterpret_cast<CFArrayRef>(CFPreferencesCopyAppValue(autosaveKey(name).get(), kCFPreferencesCurrentApplication)));

    if (!items || CFGetTypeID(items.get()) != CFArrayGetTypeID())
        return;

    size_t size = CFArrayGetCount(items.get());
    for (size_t i = 0; i < size; ++i) {
        CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(items.get(), i);
        if (CFGetTypeID(item) == CFStringGetTypeID())
            searchItems.append(item);
    }
}

} // namespace WebKit
