/*
 * 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 "SecurityOriginData.h"
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

class URL;

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

    enum StorageBlockingPolicy {
        AllowAllStorage = 0,
        BlockThirdPartyStorage,
        BlockAllStorage
    };

    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);

    // 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; }

    // 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.
    static bool isSecure(const URL&);

    // 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 canAccess(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 setStorageBlockingPolicy(StorageBlockingPolicy policy) { m_storageBlockingPolicy = policy; }

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

    WEBCORE_EXPORT String domainForCachePartition() const;

    bool canAccessDatabase(const SecurityOrigin& topOrigin) const { return canAccessStorage(&topOrigin); };
    bool canAccessSessionStorage(const SecurityOrigin& topOrigin) const { return canAccessStorage(&topOrigin, AlwaysAllowFromThirdParty); }
    bool canAccessLocalStorage(const SecurityOrigin* topOrigin) const { return canAccessStorage(topOrigin); };
    bool canAccessPluginStorage(const SecurityOrigin& topOrigin) const { return canAccessStorage(&topOrigin); }
    bool canAccessApplicationCache(const SecurityOrigin& topOrigin) const { return canAccessStorage(&topOrigin); }
    bool canAccessCookies() const { return !isUnique(); }
    bool canRequestGeolocation() const { return !isUnique(); }
    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_isUnique; }

    // 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;

    // 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 canAccess().
    // 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;

    bool isPotentiallyTrustworthy() const { return m_isPotentiallyTrustworthy; }

    static bool isLocalHostOrLoopbackIPAddress(const String& host);

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

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

private:
    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" || m_data.protocol == "https"; }
    
    enum ShouldAllowFromThirdParty { AlwaysAllowFromThirdParty, MaybeAllowFromThirdParty };
    WEBCORE_EXPORT bool canAccessStorage(const SecurityOrigin*, ShouldAllowFromThirdParty = MaybeAllowFromThirdParty) const;

    SecurityOriginData m_data;
    String m_domain;
    String m_filePath;
    bool m_isUnique { false };
    bool m_universalAccess { false };
    bool m_domainWasSetInDOM { false };
    bool m_canLoadLocalResources { false };
    StorageBlockingPolicy m_storageBlockingPolicy { AllowAllStorage };
    bool m_enforcesFilePathSeparation { false };
    bool m_needsStorageAccessFromFileURLsQuirk { false };
    bool m_isPotentiallyTrustworthy { false };
    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 originsMatch(const SecurityOrigin&, const SecurityOrigin&);
bool originsMatch(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_isUnique;
    encoder << m_universalAccess;
    encoder << m_domainWasSetInDOM;
    encoder << m_canLoadLocalResources;
    encoder.encodeEnum(m_storageBlockingPolicy);
    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 = SecurityOrigin::create(data->protocol, data->host, data->port);

    if (!decoder.decode(origin->m_domain))
        return nullptr;
    if (!decoder.decode(origin->m_filePath))
        return nullptr;
    if (!decoder.decode(origin->m_isUnique))
        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.decodeEnum(origin->m_storageBlockingPolicy))
        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 WTFMove(origin);
}

} // namespace WebCore
