// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "url/origin.h"

#include <stdint.h>

#include <algorithm>
#include <vector>

#include "base/base64.h"
#include "polyfills/base/check_op.h"
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/pickle.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "url/gurl.h"
#include "url/url_canon.h"
#include "url/url_canon_stdstring.h"
#include "url/url_constants.h"
#include "url/url_util.h"

namespace url {

Origin::Origin() : nonce_(Nonce()) {}

Origin Origin::Create(const GURL& url) {
  if (!url.is_valid())
    return Origin();

  SchemeHostPort tuple;

  if (url.SchemeIsFileSystem()) {
    tuple = SchemeHostPort(*url.inner_url());
  } else if (url.SchemeIsBlob()) {
    // If we're dealing with a 'blob:' URL, https://url.spec.whatwg.org/#origin
    // defines the origin as the origin of the URL which results from parsing
    // the "path", which boils down to everything after the scheme. GURL's
    // 'GetContent()' gives us exactly that.
    tuple = SchemeHostPort(GURL(url.GetContent()));
  } else {
    tuple = SchemeHostPort(url);

    // It's SchemeHostPort's responsibility to filter out unrecognized schemes;
    // sanity check that this is happening.
    GURL_DCHECK(!tuple.IsValid() || url.IsStandard() ||
           gurl_base::Contains(GetLocalSchemes(), url.scheme_piece()) ||
           AllowNonStandardSchemesForAndroidWebView());
  }

  if (!tuple.IsValid())
    return Origin();
  return Origin(std::move(tuple));
}

Origin Origin::Resolve(const GURL& url, const Origin& base_origin) {
  if (url.SchemeIs(kAboutScheme))
    return base_origin;
  Origin result = Origin::Create(url);
  if (!result.opaque())
    return result;
  return base_origin.DeriveNewOpaqueOrigin();
}

Origin::Origin(const Origin&) = default;
Origin& Origin::operator=(const Origin&) = default;
Origin::Origin(Origin&&) noexcept = default;
Origin& Origin::operator=(Origin&&) noexcept = default;
Origin::~Origin() = default;

// static
gurl_base::Optional<Origin> Origin::UnsafelyCreateTupleOriginWithoutNormalization(
    gurl_base::StringPiece scheme,
    gurl_base::StringPiece host,
    uint16_t port) {
  SchemeHostPort tuple(scheme.as_string(), host.as_string(), port,
                       SchemeHostPort::CHECK_CANONICALIZATION);
  if (!tuple.IsValid())
    return gurl_base::nullopt;
  return Origin(std::move(tuple));
}

// static
gurl_base::Optional<Origin> Origin::UnsafelyCreateOpaqueOriginWithoutNormalization(
    gurl_base::StringPiece precursor_scheme,
    gurl_base::StringPiece precursor_host,
    uint16_t precursor_port,
    const Origin::Nonce& nonce) {
  SchemeHostPort precursor(precursor_scheme.as_string(),
                           precursor_host.as_string(), precursor_port,
                           SchemeHostPort::CHECK_CANONICALIZATION);
  // For opaque origins, it is okay for the SchemeHostPort to be invalid;
  // however, this should only arise when the arguments indicate the
  // canonical representation of the invalid SchemeHostPort.
  if (!precursor.IsValid() &&
      !(precursor_scheme.empty() && precursor_host.empty() &&
        precursor_port == 0)) {
    return gurl_base::nullopt;
  }
  return Origin(std::move(nonce), std::move(precursor));
}

// static
Origin Origin::CreateFromNormalizedTuple(std::string scheme,
                                         std::string host,
                                         uint16_t port) {
  SchemeHostPort tuple(std::move(scheme), std::move(host), port,
                       SchemeHostPort::ALREADY_CANONICALIZED);
  if (!tuple.IsValid())
    return Origin();
  return Origin(std::move(tuple));
}

// static
Origin Origin::CreateOpaqueFromNormalizedPrecursorTuple(
    std::string precursor_scheme,
    std::string precursor_host,
    uint16_t precursor_port,
    const Origin::Nonce& nonce) {
  SchemeHostPort precursor(std::move(precursor_scheme),
                           std::move(precursor_host), precursor_port,
                           SchemeHostPort::ALREADY_CANONICALIZED);
  // For opaque origins, it is okay for the SchemeHostPort to be invalid.
  return Origin(std::move(nonce), std::move(precursor));
}

std::string Origin::Serialize() const {
  if (opaque())
    return "null";

  if (scheme() == kFileScheme)
    return "file://";

  return tuple_.Serialize();
}

GURL Origin::GetURL() const {
  if (opaque())
    return GURL();

  if (scheme() == kFileScheme)
    return GURL("file:///");

  return tuple_.GetURL();
}

gurl_base::Optional<gurl_base::UnguessableToken> Origin::GetNonceForSerialization()
    const {
  // TODO(nasko): Consider not making a copy here, but return a reference to
  // the nonce.
  return nonce_ ? gurl_base::make_optional(nonce_->token()) : gurl_base::nullopt;
}

bool Origin::IsSameOriginWith(const Origin& other) const {
  // scheme/host/port must match, even for opaque origins where |tuple_| holds
  // the precursor origin.
  return std::tie(tuple_, nonce_) == std::tie(other.tuple_, other.nonce_);
}

bool Origin::CanBeDerivedFrom(const GURL& url) const {
  GURL_DCHECK(url.is_valid());

  // For "no access" schemes, blink's SecurityOrigin will always create an
  // opaque unique one. However, about: scheme is also registered as such but
  // does not behave this way, therefore exclude it from this check.
  if (gurl_base::Contains(url::GetNoAccessSchemes(), url.scheme()) &&
      !url.SchemeIs(kAboutScheme)) {
    // If |this| is not opaque, definitely return false as the expectation
    // is for opaque origin.
    if (!opaque())
      return false;

    // And if it is unique opaque origin, it definitely is fine. But if there
    // is a precursor stored, we should fall through to compare the tuples.
    if (!tuple_.IsValid())
      return true;
  }

  SchemeHostPort url_tuple;

  // Optimization for the common, success case: Scheme/Host/Port match on the
  // precursor, and the URL is standard. Opaqueness does not matter as a tuple
  // origin can always create an opaque tuple origin.
  if (url.IsStandard()) {
    // Note: if extra copies of the scheme and host are undesirable, this check
    // can be implemented using StringPiece comparisons, but it has to account
    // explicitly checks on port numbers.
    if (url.SchemeIsFileSystem()) {
      url_tuple = SchemeHostPort(*url.inner_url());
    } else {
      url_tuple = SchemeHostPort(url);
    }
    return url_tuple == tuple_;

    // Blob URLs still contain an inner origin, however it is not accessible
    // through inner_url(), therefore it requires specific case to handle it.
  } else if (url.SchemeIsBlob()) {
    // If |this| doesn't contain any precursor information, it is an unique
    // opaque origin. It is valid case, as any browser-initiated navigation
    // to about:blank or data: URL will result in a document with such
    // origin and it is valid for it to create blob: URLs.
    if (!tuple_.IsValid())
      return true;

    url_tuple = SchemeHostPort(GURL(url.GetContent()));
    return url_tuple == tuple_;
  }

  // At this point, the URL has non-standard scheme.
  GURL_DCHECK(!url.IsStandard());

  // All about: URLs (about:blank, about:srcdoc) inherit their origin from
  // the context which navigated them, which means that they can be in any
  // type of origin.
  if (url.SchemeIs(kAboutScheme))
    return true;

  // All data: URLs commit in opaque origins, therefore |this| must be opaque
  // if |url| has data: scheme.
  if (url.SchemeIs(kDataScheme))
    return opaque();

  // If |this| does not have valid precursor tuple, it is unique opaque origin,
  // which is what we expect non-standard schemes to get.
  if (!tuple_.IsValid())
    return true;

  // However, when there is precursor present, the schemes must match.
  return url.scheme() == tuple_.scheme();
}

bool Origin::DomainIs(gurl_base::StringPiece canonical_domain) const {
  return !opaque() && url::DomainIs(tuple_.host(), canonical_domain);
}

bool Origin::operator<(const Origin& other) const {
  return std::tie(tuple_, nonce_) < std::tie(other.tuple_, other.nonce_);
}

Origin Origin::DeriveNewOpaqueOrigin() const {
  return Origin(Nonce(), tuple_);
}

std::string Origin::GetDebugString(bool include_nonce) const {
  // Handle non-opaque origins first, as they are simpler.
  if (!opaque()) {
    std::string out = Serialize();
    if (scheme() == kFileScheme)
      gurl_base::StrAppend(&out, {" [internally: ", tuple_.Serialize(), "]"});
    return out;
  }

  // For opaque origins, log the nonce and precursor as well. Without this,
  // EXPECT_EQ failures between opaque origins are nearly impossible to
  // understand.
  std::string out = gurl_base::StrCat({Serialize(), " [internally:"});
  if (include_nonce) {
    out += " (";
    if (nonce_->raw_token().is_empty())
      out += "nonce TBD";
    else
      out += nonce_->raw_token().ToString();
    out += ")";
  }
  if (!tuple_.IsValid())
    gurl_base::StrAppend(&out, {" anonymous]"});
  else
    gurl_base::StrAppend(&out, {" derived from ", tuple_.Serialize(), "]"});
  return out;
}

Origin::Origin(SchemeHostPort tuple) : tuple_(std::move(tuple)) {
  GURL_DCHECK(!opaque());
  GURL_DCHECK(tuple_.IsValid());
}

// Constructs an opaque origin derived from |precursor|.
Origin::Origin(const Nonce& nonce, SchemeHostPort precursor)
    : tuple_(std::move(precursor)), nonce_(std::move(nonce)) {
  GURL_DCHECK(opaque());
  // |precursor| is retained, but not accessible via scheme()/host()/port().
  GURL_DCHECK_EQ("", scheme());
  GURL_DCHECK_EQ("", host());
  GURL_DCHECK_EQ(0U, port());
}

gurl_base::Optional<std::string> Origin::SerializeWithNonce() const {
  return SerializeWithNonceImpl();
}

gurl_base::Optional<std::string> Origin::SerializeWithNonceAndInitIfNeeded() {
  GetNonceForSerialization();
  return SerializeWithNonceImpl();
}

// The pickle is saved in the following format, in order:
// string - tuple_.GetURL().spec().
// uint64_t (if opaque) - high bits of nonce if opaque. 0 if not initialized.
// uint64_t (if opaque) - low bits of nonce if opaque. 0 if not initialized.
gurl_base::Optional<std::string> Origin::SerializeWithNonceImpl() const {
  if (!opaque() && !tuple_.IsValid())
    return gurl_base::nullopt;

  gurl_base::Pickle pickle;
  pickle.WriteString(tuple_.Serialize());
  if (opaque() && !nonce_->raw_token().is_empty()) {
    pickle.WriteUInt64(nonce_->token().GetHighForSerialization());
    pickle.WriteUInt64(nonce_->token().GetLowForSerialization());
  } else if (opaque()) {
    // Nonce hasn't been initialized.
    pickle.WriteUInt64(0);
    pickle.WriteUInt64(0);
  }

  gurl_base::span<const uint8_t> data(
      static_cast<const uint8_t*>(pickle.data()),
      static_cast<const uint8_t*>(pickle.data()) + pickle.size());
  // Base64 encode the data to make it nicer to play with.
  return gurl_base::Base64Encode(data);
}

// static
gurl_base::Optional<Origin> Origin::Deserialize(const std::string& value) {
  std::string data;
  if (!gurl_base::Base64Decode(value, &data))
    return gurl_base::nullopt;
  gurl_base::Pickle pickle(reinterpret_cast<char*>(&data[0]), data.size());
  gurl_base::PickleIterator reader(pickle);

  std::string pickled_url;
  if (!reader.ReadString(&pickled_url))
    return gurl_base::nullopt;
  GURL url(pickled_url);

  // If only a tuple was serialized, then this origin is not opaque. For opaque
  // origins, we expect two uint64's to be left in the pickle.
  bool is_opaque = !reader.ReachedEnd();

  // Opaque origins without a tuple are ok.
  if (!is_opaque && !url.is_valid())
    return gurl_base::nullopt;
  SchemeHostPort tuple(url);

  // Possible successful early return if the pickled Origin was not opaque.
  if (!is_opaque) {
    Origin origin(tuple);
    if (origin.opaque())
      return gurl_base::nullopt;  // Something went horribly wrong.
    return origin;
  }

  uint64_t nonce_high = 0;
  if (!reader.ReadUInt64(&nonce_high))
    return gurl_base::nullopt;

  uint64_t nonce_low = 0;
  if (!reader.ReadUInt64(&nonce_low))
    return gurl_base::nullopt;

  Origin::Nonce nonce;
  if (nonce_high != 0 && nonce_low != 0) {
    // The serialized nonce wasn't empty, so copy it here.
    nonce = Origin::Nonce(
        gurl_base::UnguessableToken::Deserialize(nonce_high, nonce_low));
  }
  Origin origin;
  origin.nonce_ = std::move(nonce);
  origin.tuple_ = tuple;
  return origin;
}

std::ostream& operator<<(std::ostream& out, const url::Origin& origin) {
  out << origin.GetDebugString();
  return out;
}

std::ostream& operator<<(std::ostream& out, const url::Origin::Nonce& nonce) {
  // Subtle: don't let logging trigger lazy-generation of the token value.
  if (nonce.raw_token().is_empty())
    return (out << "(nonce TBD)");
  else
    return (out << nonce.raw_token());
}

bool IsSameOriginWith(const GURL& a, const GURL& b) {
  return Origin::Create(a).IsSameOriginWith(Origin::Create(b));
}

Origin::Nonce::Nonce() = default;
Origin::Nonce::Nonce(const gurl_base::UnguessableToken& token) : token_(token) {
  GURL_CHECK(!token_.is_empty());
}

const gurl_base::UnguessableToken& Origin::Nonce::token() const {
  // Inspecting the value of a nonce triggers lazy-generation.
  // TODO(dcheng): UnguessableToken::is_empty should go away -- what sentinel
  // value to use instead?
  if (token_.is_empty())
    token_ = gurl_base::UnguessableToken::Create();
  return token_;
}

const gurl_base::UnguessableToken& Origin::Nonce::raw_token() const {
  return token_;
}

// Copying a Nonce triggers lazy-generation of the token.
Origin::Nonce::Nonce(const Origin::Nonce& other) : token_(other.token()) {}

Origin::Nonce& Origin::Nonce::operator=(const Origin::Nonce& other) {
  // Copying a Nonce triggers lazy-generation of the token.
  token_ = other.token();
  return *this;
}

// Moving a nonce does NOT trigger lazy-generation of the token.
Origin::Nonce::Nonce(Origin::Nonce&& other) : token_(other.token_) {
  other.token_ = gurl_base::UnguessableToken();  // Reset |other|.
}

Origin::Nonce& Origin::Nonce::operator=(Origin::Nonce&& other) {
  token_ = other.token_;
  other.token_ = gurl_base::UnguessableToken();  // Reset |other|.
  return *this;
}

bool Origin::Nonce::operator<(const Origin::Nonce& other) const {
  // When comparing, lazy-generation is required of both tokens, so that an
  // ordering is established.
  return token() < other.token();
}

bool Origin::Nonce::operator==(const Origin::Nonce& other) const {
  // Equality testing doesn't actually require that the tokens be generated.
  // If the tokens are both zero, equality only holds if they're the same
  // object.
  return (other.token_ == token_) && !(token_.is_empty() && (&other != this));
}

bool Origin::Nonce::operator!=(const Origin::Nonce& other) const {
  return !(*this == other);
}

namespace debug {

ScopedOriginCrashKey::ScopedOriginCrashKey(
    gurl_base::debug::CrashKeyString* crash_key,
    const url::Origin* value)
    : gurl_base::debug::ScopedCrashKeyString(
          crash_key,
          value ? value->GetDebugString(false /* include_nonce */)
                : "nullptr") {}

ScopedOriginCrashKey::~ScopedOriginCrashKey() = default;

}  // namespace debug

}  // namespace url
