/*
 * Copyright (C) 2007-2018 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 "ProcessQualified.h"
#include "SecurityOriginData.h"
#include <wtf/EnumTraits.h>
#include <wtf/Hasher.h>
#include <wtf/Markable.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

class SecurityOrigin : public ThreadSafeRefCounted<SecurityOrigin> {
public:
    enum Policy {
        AlwaysDeny = 0,
        AlwaysAllow,
        Ask
    };

    WEBCORE_EXPORT static Ref<SecurityOrigin> create(const URL&);
    WEBCORE_EXPORT static Ref<SecurityOrigin> createUnique();

    WEBCORE_EXPORT static Ref<SecurityOrigin> createFromString(const String&);
    WEBCORE_EXPORT static Ref<SecurityOrigin> create(const String& protocol, const String& host, std::optional<uint16_t> port);

    // QuickLook documents are in non-local origins even when loaded from file: URLs. They need to
    // be allowed to display their own file: URLs in order to perform reloads and same-document
    // navigations. This lets those documents specify the file path that should be allowed to be
    // displayed from their non-local origin.
    static Ref<SecurityOrigin> createNonLocalWithAllowedFilePath(const URL&, const String& filePath);

    // Some URL schemes use nested URLs for their security context. For example,
    // filesystem URLs look like the following:
    //
    //   filesystem:http://example.com/temporary/path/to/file.png
    //
    // We're supposed to use "http://example.com" as the origin.
    //
    // Generally, we add URL schemes to this list when WebKit support them. For
    // example, we don't include the "jar" scheme, even though Firefox
    // understands that "jar" uses an inner URL for it's security origin.
    static bool shouldUseInnerURL(const URL&);
    static URL extractInnerURL(const URL&);

    // Create a deep copy of this SecurityOrigin. This method is useful
    // when marshalling a SecurityOrigin to another thread.
    WEBCORE_EXPORT Ref<SecurityOrigin> isolatedCopy() const;

    // Set the domain property of this security origin to newDomain. This
    // function does not check whether newDomain is a suffix of the current
    // domain. The caller is responsible for validating newDomain.
    void setDomainFromDOM(const String& newDomain);
    bool domainWasSetInDOM() const { return m_domainWasSetInDOM; }

    const String& protocol() const { return m_data.protocol; }
    const String& host() const { return m_data.host; }
    const String& domain() const { return m_domain; }
    std::optional<uint16_t> port() const { return m_data.port; }

    static bool shouldIgnoreHost(const URL&);

    // Returns true if a given URL is secure, based either directly on its
    // own protocol, or, when relevant, on the protocol of its "inner URL"
    // Protocols like blob: and filesystem: fall into this latter category.
    WEBCORE_EXPORT static bool isSecure(const URL&);

    // This method implements the "same origin-domain" algorithm from the HTML Standard:
    // https://html.spec.whatwg.org/#same-origin-domain
    // Returns true if this SecurityOrigin can script objects in the given
    // SecurityOrigin. For example, call this function before allowing
    // script from one security origin to read or write objects from
    // another SecurityOrigin.
    WEBCORE_EXPORT bool isSameOriginDomain(const SecurityOrigin&) const;

    // Returns true if this SecurityOrigin can read content retrieved from
    // the given URL. For example, call this function before issuing
    // XMLHttpRequests.
    WEBCORE_EXPORT bool canRequest(const URL&) const;

    // Returns true if this SecurityOrigin can receive drag content from the
    // initiator. For example, call this function before allowing content to be
    // dropped onto a target.
    bool canReceiveDragData(const SecurityOrigin& dragInitiator) const;

    // Returns true if |document| can display content from the given URL (e.g.,
    // in an iframe or as an image). For example, web sites generally cannot
    // display content from the user's files system.
    WEBCORE_EXPORT bool canDisplay(const URL&) const;

    // Returns true if this SecurityOrigin can load local resources, such
    // as images, iframes, and style sheets, and can link to local URLs.
    // For example, call this function before creating an iframe to a
    // file:// URL.
    //
    // Note: A SecurityOrigin might be allowed to load local resources
    //       without being able to issue an XMLHttpRequest for a local URL.
    //       To determine whether the SecurityOrigin can issue an
    //       XMLHttpRequest for a URL, call canRequest(url).
    bool canLoadLocalResources() const { return m_canLoadLocalResources; }

    // Explicitly grant the ability to load local resources to this
    // SecurityOrigin.
    //
    // Note: This method exists only to support backwards compatibility
    //       with older versions of WebKit.
    void grantLoadLocalResources();

    // Explicitly grant the ability to access very other SecurityOrigin.
    //
    // WARNING: This is an extremely powerful ability. Use with caution!
    void grantUniversalAccess();
    bool hasUniversalAccess() const { return m_universalAccess; }

    void grantStorageAccessFromFileURLsQuirk();
    bool needsStorageAccessFromFileURLsQuirk() const { return m_needsStorageAccessFromFileURLsQuirk; }

    WEBCORE_EXPORT String domainForCachePartition() const;
    Policy canShowNotifications() const;

    // The local SecurityOrigin is the most privileged SecurityOrigin.
    // The local SecurityOrigin can script any document, navigate to local
    // resources, and can set arbitrary headers on XMLHttpRequests.
    bool isLocal() const { return m_isLocal; }

    // The origin is a globally unique identifier assigned when the Document is
    // created. http://www.whatwg.org/specs/web-apps/current-work/#sandboxOrigin
    //
    // There's a subtle difference between a unique origin and an origin that
    // has the SandboxOrigin flag set. The latter implies the former, and, in
    // addition, the SandboxOrigin flag is inherited by iframes.
    bool isUnique() const { return !!m_uniqueOriginIdentifier; }

    // Marks a file:// origin as being in a domain defined by its path.
    // FIXME 81578: The naming of this is confusing. Files with restricted access to other local files
    // still can have other privileges that can be remembered, thereby not making them unique.
    void setEnforcesFilePathSeparation();
    bool enforcesFilePathSeparation() const { return m_enforcesFilePathSeparation; }

    // Convert this SecurityOrigin into a string. The string
    // representation of a SecurityOrigin is similar to a URL, except it
    // lacks a path component. The string representation does not encode
    // the value of the SecurityOrigin's domain property.
    //
    // When using the string value, it's important to remember that it might be
    // "null". This happens when this SecurityOrigin is unique. For example,
    // this SecurityOrigin might have come from a sandboxed iframe, the
    // SecurityOrigin might be empty, or we might have explicitly decided that
    // we shouldTreatURLSchemeAsNoAccess.
    WEBCORE_EXPORT String toString() const;

    // Similar to toString(), but does not take into account any factors that
    // could make the string return "null".
    WEBCORE_EXPORT String toRawString() const;

    URL toURL() const;

    // This method checks for equality between SecurityOrigins, not whether
    // one origin can access another. It is used for hash table keys.
    // For access checks, use isSameOriginDomain().
    // FIXME: If this method is really only useful for hash table keys, it
    // should be refactored into SecurityOriginHash.
    WEBCORE_EXPORT bool equal(const SecurityOrigin*) const;

    // This method checks for equality, ignoring the value of document.domain
    // (and whether it was set) but considering the host. It is used for postMessage.
    WEBCORE_EXPORT bool isSameSchemeHostPort(const SecurityOrigin&) const;

    // This method implements the "same origin" algorithm from the HTML Standard:
    // https://html.spec.whatwg.org/multipage/browsers.html#same-origin
    WEBCORE_EXPORT bool isSameOriginAs(const SecurityOrigin&) const;

    // This method implements the "is a registrable domain suffix of or is equal to" algorithm from the HTML Standard:
    // https://html.spec.whatwg.org/multipage/origin.html#is-a-registrable-domain-suffix-of-or-is-equal-to
    WEBCORE_EXPORT bool isMatchingRegistrableDomainSuffix(const String&, bool treatIPAddressAsDomain = false) const;

    WEBCORE_EXPORT bool isPotentiallyTrustworthy() const;
    void setIsPotentiallyTrustworthy(bool value) { m_isPotentiallyTrustworthy = value; }

    WEBCORE_EXPORT static bool isLocalHostOrLoopbackIPAddress(StringView);

    const SecurityOriginData& data() const { return m_data; }

    template<class Encoder> void encode(Encoder&) const;
    template<class Decoder> static RefPtr<SecurityOrigin> decode(Decoder&);

private:
    WEBCORE_EXPORT SecurityOrigin();
    explicit SecurityOrigin(const URL&);
    explicit SecurityOrigin(const SecurityOrigin*);

    // FIXME: Rename this function to something more semantic.
    bool passesFileCheck(const SecurityOrigin&) const;

    // This method checks that the scheme for this origin is an HTTP-family
    // scheme, e.g. HTTP and HTTPS.
    bool isHTTPFamily() const { return m_data.protocol == "http"_s || m_data.protocol == "https"_s; }
    
    enum ShouldAllowFromThirdParty { AlwaysAllowFromThirdParty, MaybeAllowFromThirdParty };
    WEBCORE_EXPORT bool canAccessStorage(const SecurityOrigin*, ShouldAllowFromThirdParty = MaybeAllowFromThirdParty) const;

    enum UniqueOriginIdentifierType { };
    using UniqueOriginIdentifier = ProcessQualified<ObjectIdentifier<UniqueOriginIdentifierType>>;

    SecurityOriginData m_data;
    String m_domain;
    String m_filePath;
    Markable<UniqueOriginIdentifier, UniqueOriginIdentifier::MarkableTraits> m_uniqueOriginIdentifier;
    bool m_universalAccess { false };
    bool m_domainWasSetInDOM { false };
    bool m_canLoadLocalResources { false };
    bool m_enforcesFilePathSeparation { false };
    bool m_needsStorageAccessFromFileURLsQuirk { false };
    mutable std::optional<bool> m_isPotentiallyTrustworthy;
    bool m_isLocal { false };
};

bool shouldTreatAsPotentiallyTrustworthy(const URL&);

// Returns true if the Origin header values serialized from these two origins would be the same.
bool serializedOriginsMatch(const SecurityOrigin&, const SecurityOrigin&);
bool serializedOriginsMatch(const SecurityOrigin*, const SecurityOrigin*);

template<class Encoder> inline void SecurityOrigin::encode(Encoder& encoder) const
{
    encoder << m_data;
    encoder << m_domain;
    encoder << m_filePath;
    encoder << m_uniqueOriginIdentifier;
    encoder << m_universalAccess;
    encoder << m_domainWasSetInDOM;
    encoder << m_canLoadLocalResources;
    encoder << m_enforcesFilePathSeparation;
    encoder << m_needsStorageAccessFromFileURLsQuirk;
    encoder << m_isPotentiallyTrustworthy;
    encoder << m_isLocal;
}

template<class Decoder> inline RefPtr<SecurityOrigin> SecurityOrigin::decode(Decoder& decoder)
{
    std::optional<SecurityOriginData> data;
    decoder >> data;
    if (!data)
        return nullptr;

    auto origin = adoptRef(*new SecurityOrigin);
    origin->m_data = WTFMove(*data);

    if (!decoder.decode(origin->m_domain))
        return nullptr;
    if (!decoder.decode(origin->m_filePath))
        return nullptr;
    if (!decoder.decode(origin->m_uniqueOriginIdentifier))
        return nullptr;
    if (!decoder.decode(origin->m_universalAccess))
        return nullptr;
    if (!decoder.decode(origin->m_domainWasSetInDOM))
        return nullptr;
    if (!decoder.decode(origin->m_canLoadLocalResources))
        return nullptr;
    if (!decoder.decode(origin->m_enforcesFilePathSeparation))
        return nullptr;
    if (!decoder.decode(origin->m_needsStorageAccessFromFileURLsQuirk))
        return nullptr;
    if (!decoder.decode(origin->m_isPotentiallyTrustworthy))
        return nullptr;
    if (!decoder.decode(origin->m_isLocal))
        return nullptr;

    return origin;
}

inline void add(Hasher& hasher, const SecurityOrigin& origin)
{
    add(hasher, origin.protocol(), origin.host(), origin.port());
}

} // namespace WebCore
