/*
 * Copyright (C) 2005, 2006, 2008, 2011, 2014 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. ``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
 * 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 "HistoryItem.h"

#include "BackForwardCache.h"
#include "CachedPage.h"
#include "Document.h"
#include "KeyedCoding.h"
#include "ResourceRequest.h"
#include "SerializedScriptValue.h"
#include "SharedBuffer.h"
#include <stdio.h>
#include <wtf/DateMath.h>
#include <wtf/DebugUtilities.h>
#include <wtf/WallTime.h>
#include <wtf/text/CString.h>

namespace WebCore {

int64_t HistoryItem::generateSequenceNumber()
{
    // Initialize to the current time to reduce the likelihood of generating
    // identifiers that overlap with those from past/future browser sessions.
    static long long next = static_cast<long long>(WallTime::now().secondsSinceEpoch().microseconds());
    return ++next;
}

static void defaultNotifyHistoryItemChanged(HistoryItem&)
{
}

void (*notifyHistoryItemChanged)(HistoryItem&) = defaultNotifyHistoryItemChanged;

HistoryItem::HistoryItem()
    : HistoryItem({ }, { })
{
}

HistoryItem::HistoryItem(const String& urlString, const String& title)
    : HistoryItem(urlString, title, { })
{
}

HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle)
    : HistoryItem(urlString, title, alternateTitle, { Process::identifier(), ObjectIdentifier<BackForwardItemIdentifier::ItemIdentifierType>::generate() })
{
}

HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle, BackForwardItemIdentifier BackForwardItemIdentifier)
    : m_urlString(urlString)
    , m_originalURLString(urlString)
    , m_title(title)
    , m_displayTitle(alternateTitle)
    , m_pruningReason(PruningReason::None)
    , m_identifier(BackForwardItemIdentifier)
{
}

HistoryItem::~HistoryItem()
{
    ASSERT(!m_cachedPage);
}

inline HistoryItem::HistoryItem(const HistoryItem& item)
    : RefCounted<HistoryItem>()
    , m_urlString(item.m_urlString)
    , m_originalURLString(item.m_originalURLString)
    , m_referrer(item.m_referrer)
    , m_target(item.m_target)
    , m_title(item.m_title)
    , m_displayTitle(item.m_displayTitle)
    , m_scrollPosition(item.m_scrollPosition)
    , m_pageScaleFactor(item.m_pageScaleFactor)
    , m_lastVisitWasFailure(item.m_lastVisitWasFailure)
    , m_isTargetItem(item.m_isTargetItem)
    , m_itemSequenceNumber(item.m_itemSequenceNumber)
    , m_documentSequenceNumber(item.m_documentSequenceNumber)
    , m_formContentType(item.m_formContentType)
    , m_pruningReason(PruningReason::None)
#if PLATFORM(IOS_FAMILY)
    , m_obscuredInsets(item.m_obscuredInsets)
    , m_scale(item.m_scale)
    , m_scaleIsInitial(item.m_scaleIsInitial)
#endif
    , m_identifier(item.m_identifier)
{
    if (item.m_formData)
        m_formData = item.m_formData->copy();
        
    unsigned size = item.m_children.size();
    m_children.reserveInitialCapacity(size);
    for (unsigned i = 0; i < size; ++i)
        m_children.uncheckedAppend(item.m_children[i]->copy());
}

Ref<HistoryItem> HistoryItem::copy() const
{
    return adoptRef(*new HistoryItem(*this));
}

void HistoryItem::reset()
{
    m_urlString = String();
    m_originalURLString = String();
    m_referrer = String();
    m_target = String();
    m_title = String();
    m_displayTitle = String();

    m_lastVisitWasFailure = false;
    m_isTargetItem = false;

    m_itemSequenceNumber = generateSequenceNumber();

    m_stateObject = nullptr;
    m_documentSequenceNumber = generateSequenceNumber();

    m_formData = nullptr;
    m_formContentType = String();

    clearChildren();
}

const String& HistoryItem::urlString() const
{
    return m_urlString;
}

// The first URL we loaded to get to where this history item points.  Includes both client
// and server redirects.
const String& HistoryItem::originalURLString() const
{
    return m_originalURLString;
}

const String& HistoryItem::title() const
{
    return m_title;
}

const String& HistoryItem::alternateTitle() const
{
    return m_displayTitle;
}

bool HistoryItem::hasCachedPageExpired() const
{
    return m_cachedPage ? m_cachedPage->hasExpired() : false;
}

void HistoryItem::setCachedPage(std::unique_ptr<CachedPage>&& cachedPage)
{
    bool wasInBackForwardCache = isInBackForwardCache();
    m_cachedPage = WTFMove(cachedPage);
    if (wasInBackForwardCache != isInBackForwardCache())
        notifyChanged();
}

std::unique_ptr<CachedPage> HistoryItem::takeCachedPage()
{
    ASSERT(m_cachedPage);
    auto cachedPage = std::exchange(m_cachedPage, nullptr);
    notifyChanged();
    return cachedPage;
}

URL HistoryItem::url() const
{
    return URL({ }, m_urlString);
}

URL HistoryItem::originalURL() const
{
    return URL({ }, m_originalURLString);
}

const String& HistoryItem::referrer() const
{
    return m_referrer;
}

const String& HistoryItem::target() const
{
    return m_target;
}

void HistoryItem::setAlternateTitle(const String& alternateTitle)
{
    m_displayTitle = alternateTitle;
    notifyChanged();
}

void HistoryItem::setURLString(const String& urlString)
{
    m_urlString = urlString;
    notifyChanged();
}

void HistoryItem::setURL(const URL& url)
{
    BackForwardCache::singleton().remove(*this);
    setURLString(url.string());
    clearDocumentState();
}

void HistoryItem::setOriginalURLString(const String& urlString)
{
    m_originalURLString = urlString;
    notifyChanged();
}

void HistoryItem::setReferrer(const String& referrer)
{
    m_referrer = referrer;
    notifyChanged();
}

void HistoryItem::setTitle(const String& title)
{
    m_title = title;
    notifyChanged();
}

void HistoryItem::setTarget(const String& target)
{
    m_target = target;
    notifyChanged();
}

const IntPoint& HistoryItem::scrollPosition() const
{
    return m_scrollPosition;
}

void HistoryItem::setScrollPosition(const IntPoint& position)
{
    m_scrollPosition = position;
}

void HistoryItem::clearScrollPosition()
{
    m_scrollPosition = IntPoint();
}

bool HistoryItem::shouldRestoreScrollPosition() const
{
    return m_shouldRestoreScrollPosition;
}

void HistoryItem::setShouldRestoreScrollPosition(bool shouldRestore)
{
    m_shouldRestoreScrollPosition = shouldRestore;
    notifyChanged();
}

float HistoryItem::pageScaleFactor() const
{
    return m_pageScaleFactor;
}

void HistoryItem::setPageScaleFactor(float scaleFactor)
{
    m_pageScaleFactor = scaleFactor;
}

void HistoryItem::setDocumentState(const Vector<String>& state)
{
    m_documentState = state;
}

const Vector<String>& HistoryItem::documentState() const
{
    return m_documentState;
}

void HistoryItem::clearDocumentState()
{
    m_documentState.clear();
}

void HistoryItem::setShouldOpenExternalURLsPolicy(ShouldOpenExternalURLsPolicy policy)
{
    m_shouldOpenExternalURLsPolicy = policy;
}

ShouldOpenExternalURLsPolicy HistoryItem::shouldOpenExternalURLsPolicy() const
{
    return m_shouldOpenExternalURLsPolicy;
}

bool HistoryItem::isTargetItem() const
{
    return m_isTargetItem;
}

void HistoryItem::setIsTargetItem(bool flag)
{
    m_isTargetItem = flag;
}

void HistoryItem::setStateObject(RefPtr<SerializedScriptValue>&& object)
{
    m_stateObject = WTFMove(object);
    notifyChanged();
}

void HistoryItem::addChildItem(Ref<HistoryItem>&& child)
{
    ASSERT(!childItemWithTarget(child->target()));
    m_children.append(WTFMove(child));
}

void HistoryItem::setChildItem(Ref<HistoryItem>&& child)
{
    ASSERT(!child->isTargetItem());
    unsigned size = m_children.size();
    for (unsigned i = 0; i < size; ++i)  {
        if (m_children[i]->target() == child->target()) {
            child->setIsTargetItem(m_children[i]->isTargetItem());
            m_children[i] = WTFMove(child);
            return;
        }
    }
    m_children.append(WTFMove(child));
}

HistoryItem* HistoryItem::childItemWithTarget(const String& target)
{
    unsigned size = m_children.size();
    for (unsigned i = 0; i < size; ++i) {
        if (m_children[i]->target() == target)
            return m_children[i].ptr();
    }
    return nullptr;
}

HistoryItem* HistoryItem::childItemWithDocumentSequenceNumber(long long number)
{
    unsigned size = m_children.size();
    for (unsigned i = 0; i < size; ++i) {
        if (m_children[i]->documentSequenceNumber() == number)
            return m_children[i].ptr();
    }
    return nullptr;
}

const Vector<Ref<HistoryItem>>& HistoryItem::children() const
{
    return m_children;
}

bool HistoryItem::hasChildren() const
{
    return !m_children.isEmpty();
}

void HistoryItem::clearChildren()
{
    m_children.clear();
}

// We do same-document navigation if going to a different item and if either of the following is true:
// - The other item corresponds to the same document (for history entries created via pushState or fragment changes).
// - The other item corresponds to the same set of documents, including frames (for history entries created via regular navigation)
bool HistoryItem::shouldDoSameDocumentNavigationTo(HistoryItem& otherItem) const
{
    // The following logic must be kept in sync with WebKit::WebBackForwardListItem::itemIsInSameDocument().
    if (this == &otherItem)
        return false;

    if (stateObject() || otherItem.stateObject())
        return documentSequenceNumber() == otherItem.documentSequenceNumber();
    
    if ((url().hasFragmentIdentifier() || otherItem.url().hasFragmentIdentifier()) && equalIgnoringFragmentIdentifier(url(), otherItem.url()))
        return documentSequenceNumber() == otherItem.documentSequenceNumber();
    
    return hasSameDocumentTree(otherItem);
}

// Does a recursive check that this item and its descendants have the same
// document sequence numbers as the other item.
bool HistoryItem::hasSameDocumentTree(HistoryItem& otherItem) const
{
    if (documentSequenceNumber() != otherItem.documentSequenceNumber())
        return false;
        
    if (children().size() != otherItem.children().size())
        return false;

    for (size_t i = 0; i < children().size(); i++) {
        auto& child = children()[i].get();
        auto* otherChild = otherItem.childItemWithDocumentSequenceNumber(child.documentSequenceNumber());
        if (!otherChild || !child.hasSameDocumentTree(*otherChild))
            return false;
    }

    return true;
}

// Does a non-recursive check that this item and its immediate children have the
// same frames as the other item.
bool HistoryItem::hasSameFrames(HistoryItem& otherItem) const
{
    if (target() != otherItem.target())
        return false;
        
    if (children().size() != otherItem.children().size())
        return false;

    for (size_t i = 0; i < children().size(); i++) {
        if (!otherItem.childItemWithTarget(children()[i]->target()))
            return false;
    }

    return true;
}

String HistoryItem::formContentType() const
{
    return m_formContentType;
}

void HistoryItem::setFormInfoFromRequest(const ResourceRequest& request)
{
    m_referrer = request.httpReferrer();
    
    if (equalLettersIgnoringASCIICase(request.httpMethod(), "post")) {
        // FIXME: Eventually we have to make this smart enough to handle the case where
        // we have a stream for the body to handle the "data interspersed with files" feature.
        m_formData = request.httpBody();
        m_formContentType = request.httpContentType();
    } else {
        m_formData = nullptr;
        m_formContentType = String();
    }
}

void HistoryItem::setFormData(RefPtr<FormData>&& formData)
{
    m_formData = WTFMove(formData);
}

void HistoryItem::setFormContentType(const String& formContentType)
{
    m_formContentType = formContentType;
}

FormData* HistoryItem::formData()
{
    return m_formData.get();
}

bool HistoryItem::isCurrentDocument(Document& document) const
{
    // FIXME: We should find a better way to check if this is the current document.
    return equalIgnoringFragmentIdentifier(url(), document.url());
}

void HistoryItem::notifyChanged()
{
    notifyHistoryItemChanged(*this);
}

#ifndef NDEBUG

int HistoryItem::showTree() const
{
    return showTreeWithIndent(0);
}

int HistoryItem::showTreeWithIndent(unsigned indentLevel) const
{
    Vector<char> prefix;
    for (unsigned i = 0; i < indentLevel; ++i)
        prefix.append("  ", 2);
    prefix.append("\0", 1);

    fprintf(stderr, "%s+-%s (%p)\n", prefix.data(), m_urlString.utf8().data(), this);
    
    int totalSubItems = 0;
    for (unsigned i = 0; i < m_children.size(); ++i)
        totalSubItems += m_children[i]->showTreeWithIndent(indentLevel + 1);
    return totalSubItems + 1;
}

#endif

#if !LOG_DISABLED
const char* HistoryItem::logString() const
{
    return debugString("HistoryItem current URL ", urlString(), ", identifier ", m_identifier.logString());
}
#endif

} // namespace WebCore

#ifndef NDEBUG

int showTree(const WebCore::HistoryItem* item)
{
    return item->showTree();
}

#endif
