blob: 1414e718cb1efd5a2068b4e6c0360c4df389476f [file] [log] [blame]
// Copyright 2018 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.
#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PROLOGUE_H_
#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PROLOGUE_H_
#include <string>
#include "base/containers/span.h"
#include "base/gtest_prod_util.h"
#include "base/optional.h"
#include "content/common/content_export.h"
#include "url/gurl.h"
namespace content {
class SignedExchangeDevToolsProxy;
// signed_exchange_prologue namespace contains parsers for the first bytes of
// the "application/signed-exchange" format, preceding the cbor-encoded
// response header.
namespace signed_exchange_prologue {
// Parse 2-byte encoded length of the variable-length field in the signed
// exchange. Note: |input| must be pointing to a valid memory address that has
// at least 2 bytes.
CONTENT_EXPORT size_t Parse2BytesEncodedLength(base::span<const uint8_t> input);
// Parse 3-byte encoded length of the variable-length field in the signed
// exchange. Note: |input| must be pointing to a valid memory address that has
// at least 3 bytes.
CONTENT_EXPORT size_t Parse3BytesEncodedLength(base::span<const uint8_t> input);
// BeforeFallbackUrl holds the decoded data from the first
// |BeforeFallbackUrl::kEncodedSizeInBytes| bytes of the
// "application/signed-exchange" format.
class CONTENT_EXPORT BeforeFallbackUrl {
public:
// Size of the BeforeFallbackUrl part of "application/signed-exchange"
// prologue.
static const size_t kEncodedSizeInBytes;
BeforeFallbackUrl() = default;
BeforeFallbackUrl(bool is_valid, size_t fallback_url_length)
: is_valid_(is_valid), fallback_url_length_(fallback_url_length) {}
BeforeFallbackUrl(const BeforeFallbackUrl&) = default;
~BeforeFallbackUrl() = default;
// Parses the first |kEncodedSizeInBytes| bytes of the
// "application/signed-exchange" format.
// |input| must be a valid span with length of |kEncodedSizeInBytes|.
// If success, returns a |is_valid()| result.
// Otherwise, returns a |!is_valid()| result and report the error to
// |devtools_proxy|.
static BeforeFallbackUrl Parse(base::span<const uint8_t> input,
SignedExchangeDevToolsProxy* devtools_proxy);
size_t ComputeFallbackUrlAndAfterLength() const;
// |is_valid()| returns false if magic string was invalid.
bool is_valid() const { return is_valid_; }
size_t fallback_url_length() const { return fallback_url_length_; }
private:
bool is_valid_ = false;
// Corresponds to `fallbackUrlLength` in the spec text.
// Encoded length of the Signature header field's value.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
size_t fallback_url_length_ = 0;
};
class CONTENT_EXPORT FallbackUrlAndAfter {
public:
FallbackUrlAndAfter() = default;
FallbackUrlAndAfter(const FallbackUrlAndAfter&) = default;
~FallbackUrlAndAfter() = default;
// Parses the bytes of the "application/signed-exchange" format,
// proceeding the BeforeFallbackUrl bytes.
// |input| must be a valid span with length of
// |before_fallback_url.ComputeFallbackUrlAndAfterLength()|.
// If success, returns a |is_valid()| result.
// Otherwise, returns a |!is_valid()| result and report the error to
// |devtools_proxy|.
static FallbackUrlAndAfter Parse(base::span<const uint8_t> input,
const BeforeFallbackUrl& before_fallback_url,
SignedExchangeDevToolsProxy* devtools_proxy);
bool is_valid() const { return is_valid_; }
// Note: fallback_url() may still be called even if |!is_valid()|,
// for trigering fallback redirect.
const GURL& fallback_url() const { return fallback_url_; }
size_t signature_header_field_length() const;
size_t cbor_header_length() const;
size_t ComputeFollowingSectionsLength() const;
private:
static FallbackUrlAndAfter ParseFailedButFallbackUrlAvailable(
GURL fallback_url);
FallbackUrlAndAfter(bool is_valid,
GURL fallback_url,
size_t signature_header_field_length,
size_t cbor_header_length)
: is_valid_(is_valid),
fallback_url_(std::move(fallback_url)),
signature_header_field_length_(signature_header_field_length),
cbor_header_length_(cbor_header_length) {}
bool is_valid_ = false;
// Corresponds to `fallbackUrl` in the spec text.
// The URL to redirect navigation to when the signed exchange processing steps
// has failed.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
GURL fallback_url_;
// Corresponds to `sigLength` in the spec text.
// Encoded length of the Signature header field's value.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
size_t signature_header_field_length_ = 0;
// Corresponds to `headerLength` in the spec text.
// Length of the CBOR representation of the request and response headers.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
size_t cbor_header_length_ = 0;
};
} // namespace signed_exchange_prologue
} // namespace content
#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PROLOGUE_H_