/*
 * Copyright (C) 2012 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"

#if WK_HAVE_C_SPI

#include "InjectedBundleTest.h"
#include <WebKit/WKBundleDOMWindowExtension.h>
#include <WebKit/WKBundleFrame.h>
#include <WebKit/WKBundlePage.h>
#include <WebKit/WKBundlePageGroup.h>
#include <WebKit/WKBundlePrivate.h>
#include <WebKit/WKBundleScriptWorld.h>
#include <WebKit/WKRetainPtr.h>
#include <wtf/HashMap.h>
#include <assert.h>

namespace TestWebKitAPI {

static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void* clientInfo);
static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFrameRef, WKBundleScriptWorldRef, const void* clientInfo);
static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef, const void* clientInfo);
static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef, const void* clientInfo);
static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef, const void* clientInfo);

enum ExtensionState {
    Uncreated = 0, Connected, Disconnected, Destroyed, Removed
};

const char* states[5] = {
    "Uncreated",
    "Connected",
    "Disconnected",
    "Destroyed",
    "Removed"
};

typedef struct {
    const char* name;
    ExtensionState state;
} ExtensionRecord;

class DOMWindowExtensionNoCache : public InjectedBundleTest {
public:
    DOMWindowExtensionNoCache(const std::string& identifier);

    virtual void initialize(WKBundleRef, WKTypeRef userData);
    virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
    virtual void willDestroyPage(WKBundleRef, WKBundlePageRef);

    void globalObjectIsAvailableForFrame(WKBundleFrameRef, WKBundleScriptWorldRef);
    void willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExtensionRef);
    void didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtensionRef);
    void willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtensionRef);

    void frameLoadFinished(WKBundleFrameRef);

private:
    void updateExtensionStateRecord(WKBundleDOMWindowExtensionRef, ExtensionState);
    void sendExtensionStateMessage();
    void sendBundleMessage(const char*);

    WKBundleRef m_bundle;
    ExtensionRecord m_extensionRecords[10];
    HashMap<WKBundleDOMWindowExtensionRef, int> m_extensionToRecordMap;
    int m_numberMainFrameLoads;
};

static InjectedBundleTest::Register<DOMWindowExtensionNoCache> registrar("DOMWindowExtensionNoCache");

DOMWindowExtensionNoCache::DOMWindowExtensionNoCache(const std::string& identifier)
    : InjectedBundleTest(identifier)
    , m_numberMainFrameLoads(0)
{
    m_extensionRecords[0].name = "First page, main frame, standard world";
    m_extensionRecords[1].name = "First page, main frame, non-standard world";
    m_extensionRecords[2].name = "First page, subframe, standard world";
    m_extensionRecords[3].name = "First page, subframe, non-standard world";
    m_extensionRecords[4].name = "Second page, main frame, standard world";
    m_extensionRecords[5].name = "Second page, main frame, non-standard world";
    m_extensionRecords[6].name = "First page, main frame, standard world";
    m_extensionRecords[7].name = "First page, main frame, non-standard world";
    m_extensionRecords[8].name = "First page, subframe, standard world";
    m_extensionRecords[9].name = "First page, subframe, non-standard world";

    for (size_t i = 0; i < 10; ++i)
      m_extensionRecords[i].state = Uncreated;
}

void DOMWindowExtensionNoCache::frameLoadFinished(WKBundleFrameRef frame)
{
    bool mainFrame = !WKBundleFrameGetParentFrame(frame);
    if (mainFrame)
        m_numberMainFrameLoads++;

    char body[16384];
    sprintf(body, "%s finished loading", mainFrame ? "Main frame" : "Subframe");

    // Only consider load finished for the main frame
    const char* name = mainFrame ? "DidFinishLoadForMainFrame" : "DidFinishLoadForFrame";

    WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString(name));
    WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(body));
    WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());

    sendExtensionStateMessage();
}

void DOMWindowExtensionNoCache::sendExtensionStateMessage()
{
    char body[16384];
    sprintf(body, "Extension states:\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s",
            m_extensionRecords[0].name, states[m_extensionRecords[0].state],
            m_extensionRecords[1].name, states[m_extensionRecords[1].state],
            m_extensionRecords[2].name, states[m_extensionRecords[2].state],
            m_extensionRecords[3].name, states[m_extensionRecords[3].state],
            m_extensionRecords[4].name, states[m_extensionRecords[4].state],
            m_extensionRecords[5].name, states[m_extensionRecords[5].state],
            m_extensionRecords[6].name, states[m_extensionRecords[6].state],
            m_extensionRecords[7].name, states[m_extensionRecords[7].state],
            m_extensionRecords[8].name, states[m_extensionRecords[8].state],
            m_extensionRecords[9].name, states[m_extensionRecords[9].state]);

    WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ExtensionStates"));
    WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithUTF8CString(body));
    WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());
}

void DOMWindowExtensionNoCache::initialize(WKBundleRef bundle, WKTypeRef userData)
{
    assert(WKGetTypeID(userData) == WKBundlePageGroupGetTypeID());
    WKBundlePageGroupRef pageGroup = static_cast<WKBundlePageGroupRef>(userData);

    WKRetainPtr<WKStringRef> source = adoptWK(WKStringCreateWithUTF8CString("alert('Unimportant alert');"));
    WKBundleAddUserScript(bundle, pageGroup, WKBundleScriptWorldCreateWorld(), source.get(), 0, 0, 0, kWKInjectAtDocumentStart, kWKInjectInAllFrames);
}

void DOMWindowExtensionNoCache::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
{
    m_bundle = bundle;

    WKBundlePageLoaderClientV7 pageLoaderClient;
    memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));

    pageLoaderClient.base.version = 7;
    pageLoaderClient.base.clientInfo = this;
    pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrameCallback;
    pageLoaderClient.globalObjectIsAvailableForFrame = globalObjectIsAvailableForFrameCallback;
    pageLoaderClient.willDisconnectDOMWindowExtensionFromGlobalObject = willDisconnectDOMWindowExtensionFromGlobalObjectCallback;
    pageLoaderClient.didReconnectDOMWindowExtensionToGlobalObject = didReconnectDOMWindowExtensionToGlobalObjectCallback;
    pageLoaderClient.willDestroyGlobalObjectForDOMWindowExtension = willDestroyGlobalObjectForDOMWindowExtensionCallback;

    WKBundlePageSetPageLoaderClient(page, &pageLoaderClient.base);
}

void DOMWindowExtensionNoCache::willDestroyPage(WKBundleRef, WKBundlePageRef)
{
    HashMap<WKBundleDOMWindowExtensionRef, int>::iterator it = m_extensionToRecordMap.begin();
    HashMap<WKBundleDOMWindowExtensionRef, int>::iterator end = m_extensionToRecordMap.end();
    for (; it != end; ++it) {
        updateExtensionStateRecord(it->key, Removed);
        WKRelease(it->key);
    }

    m_extensionToRecordMap.clear();

    sendExtensionStateMessage();
    sendBundleMessage("TestComplete");
}

void DOMWindowExtensionNoCache::updateExtensionStateRecord(WKBundleDOMWindowExtensionRef extension, ExtensionState state)
{
    int index = m_extensionToRecordMap.get(extension);
    m_extensionRecords[index].state = state;
}

void DOMWindowExtensionNoCache::sendBundleMessage(const char* message)
{
    WKRetainPtr<WKStringRef> wkMessage = adoptWK(WKStringCreateWithUTF8CString(message));
    WKBundlePostMessage(m_bundle, wkMessage.get(), wkMessage.get());
}

void DOMWindowExtensionNoCache::globalObjectIsAvailableForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
{
    WKBundleDOMWindowExtensionRef extension = WKBundleDOMWindowExtensionCreate(frame, world);

    int index = 0;
    bool standard;
    standard = world == WKBundleScriptWorldNormalWorld();

    bool mainFrame = !WKBundleFrameGetParentFrame(frame);
    switch (m_numberMainFrameLoads) {
    case 0:
        index = mainFrame ? (standard ? 0 : 1) : (standard ? 2 : 3);
        break;
    case 1:
        index = standard ? 4 : 5;
        break;
    case 2:
        index = mainFrame ? (standard ? 6 : 7) : (standard ? 8 : 9);
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }

    m_extensionToRecordMap.set(extension, index);

    updateExtensionStateRecord(extension, Connected);
    sendBundleMessage("GlobalObjectIsAvailableForFrame called");
}

void DOMWindowExtensionNoCache::willDisconnectDOMWindowExtensionFromGlobalObject(WKBundleDOMWindowExtensionRef extension)
{
    // No items should be going into a 0-capacity back/forward cache.
    ASSERT_NOT_REACHED();
}

void DOMWindowExtensionNoCache::didReconnectDOMWindowExtensionToGlobalObject(WKBundleDOMWindowExtensionRef)
{
    // No items should be coming out of a 0-capacity back/forward cache.
    ASSERT_NOT_REACHED();
}

void DOMWindowExtensionNoCache::willDestroyGlobalObjectForDOMWindowExtension(WKBundleDOMWindowExtensionRef extension)
{
    sendBundleMessage("WillDestroyDOMWindowExtensionToGlobalObject called");
    updateExtensionStateRecord(extension, Destroyed);
    m_extensionToRecordMap.remove(extension);
    WKRelease(extension);
}

static void didFinishLoadForFrameCallback(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
{
    ((DOMWindowExtensionNoCache*)clientInfo)->frameLoadFinished(frame);
}

static void globalObjectIsAvailableForFrameCallback(WKBundlePageRef, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void* clientInfo)
{
    ((DOMWindowExtensionNoCache*)clientInfo)->globalObjectIsAvailableForFrame(frame, world);
}

static void willDisconnectDOMWindowExtensionFromGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo)
{
    ((DOMWindowExtensionNoCache*)clientInfo)->willDisconnectDOMWindowExtensionFromGlobalObject(extension);
}

static void didReconnectDOMWindowExtensionToGlobalObjectCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension, const void* clientInfo)
{
    ((DOMWindowExtensionNoCache*)clientInfo)->didReconnectDOMWindowExtensionToGlobalObject(extension);
}

static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef, WKBundleDOMWindowExtensionRef extension , const void* clientInfo)
{
    ((DOMWindowExtensionNoCache*)clientInfo)->willDestroyGlobalObjectForDOMWindowExtension(extension);
}

} // namespace TestWebKitAPI

#endif
