/*
 * Copyright (C) 2013-2015 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 "PageLoadState.h"

#include "WebPageProxy.h"

namespace WebKit {

// Progress always starts at this value. This helps provide feedback as soon as a load starts.
static const double initialProgressValue = 0.1;

PageLoadState::PageLoadState(WebPageProxy& webPageProxy)
    : m_webPageProxy(webPageProxy)
    , m_mayHaveUncommittedChanges(false)
    , m_outstandingTransactionCount(0)
{
}

PageLoadState::~PageLoadState()
{
    ASSERT(m_observers.isEmpty());
}

PageLoadState::Transaction::Transaction(PageLoadState& pageLoadState)
    : m_webPageProxy(&pageLoadState.m_webPageProxy)
    , m_pageLoadState(&pageLoadState)
{
    m_pageLoadState->beginTransaction();
}

PageLoadState::Transaction::Transaction(Transaction&& other)
    : m_webPageProxy(WTFMove(other.m_webPageProxy))
    , m_pageLoadState(other.m_pageLoadState)
{
    other.m_pageLoadState = nullptr;
}

PageLoadState::Transaction::~Transaction()
{
    if (m_pageLoadState)
        m_pageLoadState->endTransaction();
}

void PageLoadState::addObserver(Observer& observer)
{
    ASSERT(!m_observers.contains(&observer));

    m_observers.append(&observer);
}

void PageLoadState::removeObserver(Observer& observer)
{
    bool removed = m_observers.removeFirst(&observer);
    ASSERT_UNUSED(removed, removed);
}

void PageLoadState::endTransaction()
{
    ASSERT(m_outstandingTransactionCount > 0);

    if (!--m_outstandingTransactionCount)
        commitChanges();
}

void PageLoadState::commitChanges()
{
    if (!m_mayHaveUncommittedChanges)
        return;

    m_mayHaveUncommittedChanges = false;

    bool canGoBackChanged = m_committedState.canGoBack != m_uncommittedState.canGoBack;
    bool canGoForwardChanged = m_committedState.canGoForward != m_uncommittedState.canGoForward;
    bool titleChanged = m_committedState.title != m_uncommittedState.title;
    bool isLoadingChanged = isLoading(m_committedState) != isLoading(m_uncommittedState);
    bool activeURLChanged = activeURL(m_committedState) != activeURL(m_uncommittedState);
    bool hasOnlySecureContentChanged = hasOnlySecureContent(m_committedState) != hasOnlySecureContent(m_uncommittedState);
    bool estimatedProgressChanged = estimatedProgress(m_committedState) != estimatedProgress(m_uncommittedState);
    bool networkRequestsInProgressChanged = m_committedState.networkRequestsInProgress != m_uncommittedState.networkRequestsInProgress;
    bool certificateInfoChanged = m_committedState.certificateInfo != m_uncommittedState.certificateInfo;

    if (canGoBackChanged)
        callObserverCallback(&Observer::willChangeCanGoBack);
    if (canGoForwardChanged)
        callObserverCallback(&Observer::willChangeCanGoForward);
    if (titleChanged)
        callObserverCallback(&Observer::willChangeTitle);
    if (isLoadingChanged)
        callObserverCallback(&Observer::willChangeIsLoading);
    if (activeURLChanged)
        callObserverCallback(&Observer::willChangeActiveURL);
    if (hasOnlySecureContentChanged)
        callObserverCallback(&Observer::willChangeHasOnlySecureContent);
    if (estimatedProgressChanged)
        callObserverCallback(&Observer::willChangeEstimatedProgress);
    if (networkRequestsInProgressChanged)
        callObserverCallback(&Observer::willChangeNetworkRequestsInProgress);
    if (certificateInfoChanged)
        callObserverCallback(&Observer::willChangeCertificateInfo);

    m_committedState = m_uncommittedState;

    // The "did" ordering is the reverse of the "will". This is a requirement of Cocoa Key-Value Observing.
    if (certificateInfoChanged)
        callObserverCallback(&Observer::didChangeCertificateInfo);
    if (networkRequestsInProgressChanged)
        callObserverCallback(&Observer::didChangeNetworkRequestsInProgress);
    if (estimatedProgressChanged)
        callObserverCallback(&Observer::didChangeEstimatedProgress);
    if (hasOnlySecureContentChanged)
        callObserverCallback(&Observer::didChangeHasOnlySecureContent);
    if (activeURLChanged)
        callObserverCallback(&Observer::didChangeActiveURL);
    if (isLoadingChanged)
        callObserverCallback(&Observer::didChangeIsLoading);
    if (titleChanged)
        callObserverCallback(&Observer::didChangeTitle);
    if (canGoForwardChanged)
        callObserverCallback(&Observer::didChangeCanGoForward);
    if (canGoBackChanged)
        callObserverCallback(&Observer::didChangeCanGoBack);
}

void PageLoadState::reset(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);

    m_uncommittedState.state = State::Finished;
    m_uncommittedState.hasInsecureContent = false;

    m_uncommittedState.pendingAPIRequestURL = String();
    m_uncommittedState.provisionalURL = String();
    m_uncommittedState.url = String();

    m_uncommittedState.unreachableURL = String();
    m_lastUnreachableURL = String();

    m_uncommittedState.title = String();

    m_uncommittedState.estimatedProgress = 0;
    m_uncommittedState.networkRequestsInProgress = false;
}

bool PageLoadState::isLoading() const
{
    return isLoading(m_committedState);
}

String PageLoadState::activeURL(const Data& data)
{
    // If there is a currently pending URL, it is the active URL,
    // even when there's no main frame yet, as it might be the
    // first API request.
    if (!data.pendingAPIRequestURL.isNull())
        return data.pendingAPIRequestURL;

    if (!data.unreachableURL.isEmpty())
        return data.unreachableURL;

    switch (data.state) {
    case State::Provisional:
        return data.provisionalURL;
    case State::Committed:
    case State::Finished:
        return data.url;
    }

    ASSERT_NOT_REACHED();
    return String();
}

String PageLoadState::activeURL() const
{
    return activeURL(m_committedState);
}

bool PageLoadState::hasOnlySecureContent(const Data& data)
{
    if (data.hasInsecureContent)
        return false;

    return WebCore::protocolIs(data.url, "https");
}

bool PageLoadState::hasOnlySecureContent() const
{
    return hasOnlySecureContent(m_committedState);
}

double PageLoadState::estimatedProgress(const Data& data)
{
    if (!data.pendingAPIRequestURL.isNull())
        return initialProgressValue;

    return data.estimatedProgress;
}

double PageLoadState::estimatedProgress() const
{
    return estimatedProgress(m_committedState);
}

const String& PageLoadState::pendingAPIRequestURL() const
{
    return m_committedState.pendingAPIRequestURL;
}

void PageLoadState::setPendingAPIRequestURL(const Transaction::Token& token, const String& pendingAPIRequestURL)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.pendingAPIRequestURL = pendingAPIRequestURL;
}

void PageLoadState::clearPendingAPIRequestURL(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.pendingAPIRequestURL = String();
}

void PageLoadState::didStartProvisionalLoad(const Transaction::Token& token, const String& url, const String& unreachableURL)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    ASSERT(m_uncommittedState.provisionalURL.isEmpty());

    m_uncommittedState.state = State::Provisional;

    m_uncommittedState.provisionalURL = url;

    setUnreachableURL(token, unreachableURL);
}

void PageLoadState::didReceiveServerRedirectForProvisionalLoad(const Transaction::Token& token, const String& url)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    ASSERT(m_uncommittedState.state == State::Provisional);

    m_uncommittedState.provisionalURL = url;
}

void PageLoadState::didFailProvisionalLoad(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    ASSERT(m_uncommittedState.state == State::Provisional);

    m_uncommittedState.state = State::Finished;

    m_uncommittedState.provisionalURL = String();
    m_uncommittedState.unreachableURL = m_lastUnreachableURL;
}

void PageLoadState::didCommitLoad(const Transaction::Token& token, WebCertificateInfo& certificateInfo, bool hasInsecureContent)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    ASSERT(m_uncommittedState.state == State::Provisional);

    m_uncommittedState.state = State::Committed;
    m_uncommittedState.hasInsecureContent = hasInsecureContent;
    m_uncommittedState.certificateInfo = &certificateInfo;

    m_uncommittedState.url = m_uncommittedState.provisionalURL;
    m_uncommittedState.provisionalURL = String();

    m_uncommittedState.title = String();
}

void PageLoadState::didFinishLoad(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    ASSERT(m_uncommittedState.state == State::Committed);
    ASSERT(m_uncommittedState.provisionalURL.isEmpty());

    m_uncommittedState.state = State::Finished;
}

void PageLoadState::didFailLoad(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    ASSERT(m_uncommittedState.provisionalURL.isEmpty());

    m_uncommittedState.state = State::Finished;
}

void PageLoadState::didSameDocumentNavigation(const Transaction::Token& token, const String& url)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    ASSERT(!m_uncommittedState.url.isEmpty());

    m_uncommittedState.url = url;
}

void PageLoadState::didDisplayOrRunInsecureContent(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);

    m_uncommittedState.hasInsecureContent = true;
}

void PageLoadState::setUnreachableURL(const Transaction::Token& token, const String& unreachableURL)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);

    m_lastUnreachableURL = m_uncommittedState.unreachableURL;
    m_uncommittedState.unreachableURL = unreachableURL;
}

const String& PageLoadState::title() const
{
    return m_committedState.title;
}

void PageLoadState::setTitle(const Transaction::Token& token, const String& title)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.title = title;
}

bool PageLoadState::canGoBack() const
{
    return m_committedState.canGoBack;
}

void PageLoadState::setCanGoBack(const Transaction::Token& token, bool canGoBack)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.canGoBack = canGoBack;
}

bool PageLoadState::canGoForward() const
{
    return m_committedState.canGoForward;
}

void PageLoadState::setCanGoForward(const Transaction::Token& token, bool canGoForward)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.canGoForward = canGoForward;
}

void PageLoadState::didStartProgress(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.estimatedProgress = initialProgressValue;
}

void PageLoadState::didChangeProgress(const Transaction::Token& token, double value)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.estimatedProgress = value;
}

void PageLoadState::didFinishProgress(const Transaction::Token& token)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.estimatedProgress = 1;
}

void PageLoadState::setNetworkRequestsInProgress(const Transaction::Token& token, bool networkRequestsInProgress)
{
    ASSERT_UNUSED(token, &token.m_pageLoadState == this);
    m_uncommittedState.networkRequestsInProgress = networkRequestsInProgress;
}

bool PageLoadState::isLoading(const Data& data)
{
    if (!data.pendingAPIRequestURL.isNull())
        return true;

    switch (data.state) {
    case State::Provisional:
    case State::Committed:
        return true;

    case State::Finished:
        return false;
    }

    ASSERT_NOT_REACHED();
    return false;
}

void PageLoadState::willChangeProcessIsResponsive()
{
    callObserverCallback(&Observer::willChangeWebProcessIsResponsive);
}

void PageLoadState::didChangeProcessIsResponsive()
{
    callObserverCallback(&Observer::didChangeWebProcessIsResponsive);
}

void PageLoadState::callObserverCallback(void (Observer::*callback)())
{
    for (auto* observer : m_observers)
        (observer->*callback)();
}

} // namespace WebKit
