/*
 * Copyright (C) 2006-2016 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. 
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.
 */

#pragma once

#include "IntRect.h"
#include "ProcessIdentifier.h"

namespace WebCore {

enum FrameState {
    FrameStateProvisional,
    // This state indicates we are ready to commit to a page,
    // which means the view will transition to use the new data source.
    FrameStateCommittedPage,
    FrameStateComplete
};

enum class PolicyAction : uint8_t {
    Use,
    Download,
    Ignore,
    StopAllLoads
};

enum class ReloadOption : uint8_t {
    ExpiredOnly = 1 << 0,
    FromOrigin  = 1 << 1,
    DisableContentBlockers = 1 << 2,
};

enum class FrameLoadType : uint8_t {
    Standard,
    Back,
    Forward,
    IndexedBackForward, // a multi-item hop in the backforward list
    Reload,
    Same, // user loads same URL again (but not reload button)
    RedirectWithLockedBackForwardList, // FIXME: Merge "lockBackForwardList", "lockHistory", "quickRedirect" and "clientRedirect" into a single concept of redirect.
    Replace,
    ReloadFromOrigin,
    ReloadExpiredOnly
};

enum class WillContinueLoading : bool { No, Yes };

class PolicyCheckIdentifier {
public:
    PolicyCheckIdentifier() = default;

    static PolicyCheckIdentifier create();

    bool isValidFor(PolicyCheckIdentifier);
    bool operator==(const PolicyCheckIdentifier& other) const { return m_process == other.m_process && m_policyCheck == other.m_policyCheck; }

    template<class Encoder> void encode(Encoder&) const;
    template<class Decoder> static Optional<PolicyCheckIdentifier> decode(Decoder&);

private:
    PolicyCheckIdentifier(ProcessIdentifier process, uint64_t policyCheck)
        : m_process(process)
        , m_policyCheck(policyCheck)
    { }

    ProcessIdentifier m_process;
    uint64_t m_policyCheck { 0 };
};

template<class Encoder>
void PolicyCheckIdentifier::encode(Encoder& encoder) const
{
    encoder << m_process << m_policyCheck;
}

template<class Decoder>
Optional<PolicyCheckIdentifier> PolicyCheckIdentifier::decode(Decoder& decoder)
{
    auto process = ProcessIdentifier::decode(decoder);
    if (!process)
        return WTF::nullopt;

    uint64_t policyCheck;
    if (!decoder.decode(policyCheck))
        return WTF::nullopt;

    return PolicyCheckIdentifier { *process, policyCheck };
}

enum class NewFrameOpenerPolicy : uint8_t {
    Suppress,
    Allow
};

enum class NavigationType : uint8_t {
    LinkClicked,
    FormSubmitted,
    BackForward,
    Reload,
    FormResubmitted,
    Other
};

enum class ShouldOpenExternalURLsPolicy : uint8_t {
    ShouldNotAllow,
    ShouldAllowExternalSchemes,
    ShouldAllow,
};

enum class InitiatedByMainFrame : uint8_t {
    Yes,
    Unknown,
};

enum ClearProvisionalItemPolicy {
    ShouldClearProvisionalItem,
    ShouldNotClearProvisionalItem
};

enum class ObjectContentType : uint8_t {
    None,
    Image,
    Frame,
    PlugIn,
};

enum UnloadEventPolicy {
    UnloadEventPolicyNone,
    UnloadEventPolicyUnloadOnly,
    UnloadEventPolicyUnloadAndPageHide
};

enum ShouldSendReferrer {
    MaybeSendReferrer,
    NeverSendReferrer
};

// Passed to FrameLoader::urlSelected() and ScriptController::executeIfJavaScriptURL()
// to control whether, in the case of a JavaScript URL, executeIfJavaScriptURL() should
// replace the document. It is a FIXME to eliminate this extra parameter from
// executeIfJavaScriptURL(), in which case this enum can go away.
enum ShouldReplaceDocumentIfJavaScriptURL {
    ReplaceDocumentIfJavaScriptURL,
    DoNotReplaceDocumentIfJavaScriptURL
};

enum WebGLLoadPolicy {
    WebGLBlockCreation,
    WebGLAllowCreation,
    WebGLPendingCreation
};

enum class LockHistory : bool { No, Yes };
enum class LockBackForwardList : bool { No, Yes };
enum class AllowNavigationToInvalidURL : bool { No, Yes };
enum class HasInsecureContent : bool { No, Yes };

struct SystemPreviewInfo {
    IntRect systemPreviewRect;
    bool isSystemPreview { false };
};

enum class LoadCompletionType : uint8_t {
    Finish,
    Cancel
};

} // namespace WebCore

namespace WTF {

template<> struct EnumTraits<WebCore::PolicyAction> {
    using values = EnumValues<
        WebCore::PolicyAction,
        WebCore::PolicyAction::Use,
        WebCore::PolicyAction::Download,
        WebCore::PolicyAction::Ignore,
        WebCore::PolicyAction::StopAllLoads
    >;
};

template<> struct EnumTraits<WebCore::FrameLoadType> {
    using values = EnumValues<
        WebCore::FrameLoadType,
        WebCore::FrameLoadType::Standard,
        WebCore::FrameLoadType::Back,
        WebCore::FrameLoadType::Forward,
        WebCore::FrameLoadType::IndexedBackForward,
        WebCore::FrameLoadType::Reload,
        WebCore::FrameLoadType::Same,
        WebCore::FrameLoadType::RedirectWithLockedBackForwardList,
        WebCore::FrameLoadType::Replace,
        WebCore::FrameLoadType::ReloadFromOrigin,
        WebCore::FrameLoadType::ReloadExpiredOnly
    >;
};

} // namespace WTF
