// Copyright 2019 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 "services/data_decoder/bundled_exchanges_parser.h"

#include <algorithm>

#include "base/big_endian.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/containers/span.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/checked_math.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "components/cbor/reader.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/http/http_util.h"

namespace data_decoder {

namespace {

// The maximum length of the CBOR item header (type and argument).
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#parse-type-argument
constexpr uint64_t kMaxCBORItemHeaderSize = 9;

// The maximum size of the section-lengths CBOR item.
constexpr uint64_t kMaxSectionLengthsCBORSize = 8192;

// The maximum size of the index section allowed in this implementation.
constexpr uint64_t kMaxIndexSectionSize = 1 * 1024 * 1024;

// The maximum size of the response header CBOR.
constexpr uint64_t kMaxResponseHeaderLength = 512 * 1024;

// The initial buffer size for reading an item from the response section.
constexpr uint64_t kInitialBufferSizeForResponse = 4096;

const uint8_t kBundleMagicBytes[] = {
    0x84, 0x48, 0xF0, 0x9F, 0x8C, 0x90, 0xF0, 0x9F, 0x93, 0xA6,
};

// Section names.
constexpr char kIndexSection[] = "index";
constexpr char kResponsesSection[] = "responses";

// https://tools.ietf.org/html/draft-ietf-cbor-7049bis-05#section-3.1
enum class CBORType {
  kByteString = 2,
  kArray = 4,
};

// A list of (section-name, length) pairs.
using SectionLengths = std::vector<std::pair<std::string, uint64_t>>;

// Parses a `section-lengths` CBOR item.
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
base::Optional<SectionLengths> ParseSectionLengths(
    base::span<const uint8_t> data) {
  cbor::Reader::DecoderError error;
  base::Optional<cbor::Value> value = cbor::Reader::Read(data, &error);
  if (!value.has_value() || !value->is_array())
    return base::nullopt;

  const cbor::Value::ArrayValue& array = value->GetArray();
  if (array.size() % 2 != 0)
    return base::nullopt;

  SectionLengths result;
  for (size_t i = 0; i < array.size(); i += 2) {
    if (!array[i].is_string() || !array[i + 1].is_unsigned())
      return base::nullopt;
    result.emplace_back(array[i].GetString(), array[i + 1].GetUnsigned());
  }
  return result;
}

struct ParsedHeaders {
  base::flat_map<std::string, std::string> headers;
  base::flat_map<std::string, std::string> pseudos;
};

// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#cbor-headers
base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
    const cbor::Value& headers_value) {
  // Step 1. If item doesn’t match the headers rule in the above CDDL, return
  // an error.
  if (!headers_value.is_map())
    return base::nullopt;

  // Step 2. Let headers be a new header list ([FETCH]).
  // Step 3. Let pseudos be an empty map ([INFRA]).
  ParsedHeaders result;

  // Step 4. For each pair (name, value) in item:
  for (const auto& item : headers_value.GetMap()) {
    if (!item.first.is_bytestring() || !item.second.is_bytestring())
      return base::nullopt;
    base::StringPiece name = item.first.GetBytestringAsString();
    base::StringPiece value = item.second.GetBytestringAsString();

    // Step 4.1. If name contains any upper-case or non-ASCII characters, return
    // an error. This matches the requirement in Section 8.1.2 of [RFC7540].
    if (!base::IsStringASCII(name) ||
        std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>))
      return base::nullopt;

    // Step 4.2. If name starts with a ‘:’:
    if (!name.empty() && name[0] == ':') {
      // Step 4.2.1. Assert: pseudos[name] does not exist, because CBOR maps
      // cannot contain duplicate keys.
      // This is ensured by cbor::Reader.
      DCHECK(!result.pseudos.contains(name));
      // Step 4.2.2. Set pseudos[name] to value.
      result.pseudos.insert(
          std::make_pair(name.as_string(), value.as_string()));
      // Step 4.3.3. Continue.
      continue;
    }

    // Step 4.3. If name or value doesn’t satisfy the requirements for a header
    // in [FETCH], return an error.
    if (!net::HttpUtil::IsValidHeaderName(name) ||
        !net::HttpUtil::IsValidHeaderValue(value))
      return base::nullopt;

    // Step 4.4. Assert: headers does not contain ([FETCH]) name, because CBOR
    // maps cannot contain duplicate keys and an earlier step rejected
    // upper-case bytes.
    // This is ensured by cbor::Reader.
    DCHECK(!result.headers.contains(name));

    // Step 4.5. Append (name, value) to headers.
    result.headers.insert(std::make_pair(name.as_string(), value.as_string()));
  }

  // Step 5. Return (headers, pseudos).
  return result;
}

// A utility class for reading various values from input buffer.
class InputReader {
 public:
  explicit InputReader(base::span<const uint8_t> buf) : buf_(buf) {}

  uint64_t CurrentOffset() const { return current_offset_; }
  size_t Size() const { return buf_.size(); }

  base::Optional<uint8_t> ReadByte() {
    if (buf_.empty())
      return base::nullopt;
    uint8_t byte = buf_[0];
    Advance(1);
    return byte;
  }

  template <typename T>
  bool ReadBigEndian(T* out) {
    auto bytes = ReadBytes(sizeof(T));
    if (!bytes)
      return false;
    base::ReadBigEndian(reinterpret_cast<const char*>(bytes->data()), out);
    return true;
  }

  base::Optional<base::span<const uint8_t>> ReadBytes(size_t n) {
    if (buf_.size() < n)
      return base::nullopt;
    auto result = buf_.subspan(0, n);
    Advance(n);
    return result;
  }

  // Parses the type and argument of a CBOR item from the input head. If parsed
  // successfully and the type matches |expected_type|, returns the argument.
  // Otherwise returns nullopt.
  base::Optional<uint64_t> ReadCBORHeader(CBORType expected_type) {
    auto pair = ReadTypeAndArgument();
    if (!pair || pair->first != expected_type)
      return base::nullopt;
    return pair->second;
  }

 private:
  // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#parse-type-argument
  base::Optional<std::pair<CBORType, uint64_t>> ReadTypeAndArgument() {
    base::Optional<uint8_t> first_byte = ReadByte();
    if (!first_byte)
      return base::nullopt;

    CBORType type = static_cast<CBORType>((*first_byte & 0xE0) / 0x20);
    uint8_t b = *first_byte & 0x1F;

    if (b <= 23)
      return std::make_pair(type, b);
    if (b == 24) {
      auto content = ReadByte();
      if (!content || *content < 24)
        return base::nullopt;
      return std::make_pair(type, *content);
    }
    if (b == 25) {
      uint16_t content;
      if (!ReadBigEndian(&content) || content >> 8 == 0)
        return base::nullopt;
      return std::make_pair(type, content);
    }
    if (b == 26) {
      uint32_t content;
      if (!ReadBigEndian(&content) || content >> 16 == 0)
        return base::nullopt;
      return std::make_pair(type, content);
    }
    if (b == 27) {
      uint64_t content;
      if (!ReadBigEndian(&content) || content >> 32 == 0)
        return base::nullopt;
      return std::make_pair(type, content);
    }
    return base::nullopt;
  }

  void Advance(size_t n) {
    DCHECK_LE(n, buf_.size());
    buf_ = buf_.subspan(n);
    current_offset_ += n;
  }

  base::span<const uint8_t> buf_;
  uint64_t current_offset_ = 0;

  DISALLOW_COPY_AND_ASSIGN(InputReader);
};

}  // namespace

class BundledExchangesParser::SharedBundleDataSource::Observer {
 public:
  Observer() {}
  virtual ~Observer() {}
  virtual void OnDisconnect() = 0;

  DISALLOW_COPY_AND_ASSIGN(Observer);
};

// A parser for bundle's metadata. This currently looks only at the "index"
// section. This class owns itself and will self destruct after calling the
// ParseMetadataCallback.
// TODO(crbug.com/966753): Add support for the "manifest" section and "critical"
// section.
class BundledExchangesParser::MetadataParser
    : BundledExchangesParser::SharedBundleDataSource::Observer {
 public:
  MetadataParser(scoped_refptr<SharedBundleDataSource> data_source,
                 ParseMetadataCallback callback)
      : data_source_(data_source), callback_(std::move(callback)) {
    data_source_->AddObserver(this);
  }
  ~MetadataParser() override { data_source_->RemoveObserver(this); }

  void Start() {
    data_source_->GetSize(base::BindOnce(&MetadataParser::DidGetSize,
                                         weak_factory_.GetWeakPtr()));
  }

 private:
  void DidGetSize(uint64_t size) {
    size_ = size;

    // In the next step, we will parse `magic`, `section-lengths`, and the CBOR
    // header of `sections`.
    // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#top-level
    const uint64_t length =
        std::min(size, sizeof(kBundleMagicBytes) + kMaxSectionLengthsCBORSize +
                           kMaxCBORItemHeaderSize * 2);
    data_source_->Read(0, length,
                       base::BindOnce(&MetadataParser::ParseBundleHeader,
                                      weak_factory_.GetWeakPtr(), length));
  }

  // Step 1-15 of
  // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
  void ParseBundleHeader(uint64_t expected_data_length,
                         const base::Optional<std::vector<uint8_t>>& data) {
    if (!data || data->size() != expected_data_length) {
      RunErrorCallbackAndDestroy("Error reading bundle header.");
      return;
    }

    // Step 1. "Seek to offset 0 in stream. Assert: this operation doesn't
    // fail."
    InputReader input(*data);

    // Step 2. "If reading 10 bytes from stream returns an error or doesn't
    // return the bytes with hex encoding "84 48 F0 9F 8C 90 F0 9F 93 A6"
    // (the CBOR encoding of the 4-item array initial byte and 8-byte bytestring
    // initial byte, followed by 🌐📦 in UTF-8), return an error."
    const auto magic = input.ReadBytes(sizeof(kBundleMagicBytes));
    if (!magic ||
        !std::equal(magic->begin(), magic->end(), std::begin(kBundleMagicBytes),
                    std::end(kBundleMagicBytes))) {
      RunErrorCallbackAndDestroy("Wrong magic bytes.");
      return;
    }

    // Step 3. "Let sectionLengthsLength be the result of getting the length of
    // the CBOR bytestring header from stream (Section 3.5.2). If this is an
    // error, return that error."
    const auto section_lengths_length =
        input.ReadCBORHeader(CBORType::kByteString);
    if (!section_lengths_length) {
      RunErrorCallbackAndDestroy("Cannot parse the size of section-lengths.");
      return;
    }
    // Step 4. "If sectionLengthsLength is 8192 (8*1024) or greater, return an
    // error."
    if (*section_lengths_length >= kMaxSectionLengthsCBORSize) {
      RunErrorCallbackAndDestroy(
          "The section-lengths CBOR must be smaller than 8192 bytes.");
      return;
    }

    // Step 5. "Let sectionLengthsBytes be the result of reading
    // sectionLengthsLength bytes from stream. If sectionLengthsBytes is an
    // error, return that error."
    const auto section_lengths_bytes = input.ReadBytes(*section_lengths_length);
    if (!section_lengths_bytes) {
      RunErrorCallbackAndDestroy("Cannot read section-lengths.");
      return;
    }

    // Step 6. "Let sectionLengths be the result of parsing one CBOR item
    // (Section 3.5) from sectionLengthsBytes, matching the section-lengths
    // rule in the CDDL ([I-D.ietf-cbor-cddl]) above. If sectionLengths is an
    // error, return an error."
    const auto section_lengths = ParseSectionLengths(*section_lengths_bytes);
    if (!section_lengths) {
      RunErrorCallbackAndDestroy("Cannot parse section-lengths.");
      return;
    }

    // Step 7. "Let (sectionsType, numSections) be the result of parsing the
    // type and argument of a CBOR item from stream (Section 3.5.3)."
    const auto num_sections = input.ReadCBORHeader(CBORType::kArray);
    if (!num_sections) {
      RunErrorCallbackAndDestroy("Cannot parse the number of sections.");
      return;
    }

    // Step 8. "If sectionsType is not 4 (a CBOR array) or numSections is not
    // half of the length of sectionLengths, return an error."
    if (*num_sections != section_lengths->size()) {
      RunErrorCallbackAndDestroy("Unexpected number of sections.");
      return;
    }

    // Step 9. "Let sectionsStart be the current offset within stream."
    const uint64_t sections_start = input.CurrentOffset();

    // Step 10. "Let knownSections be the subset of the Section 6.2 that this
    // client has implemented."
    // Step 11. "Let ignoredSections be an empty set."

    // This implementation doesn't use knownSections nor ignoredSections.

    // Step 12. "Let sectionOffsets be an empty map ([INFRA]) from section names
    // to (offset, length) pairs. These offsets are relative to the start of
    // stream."

    // |section_offsets_| is defined as a class member field.

    // Step 13. "Let currentOffset be sectionsStart."
    uint64_t current_offset = sections_start;

    // Step 14. "For each ("name", length) pair of adjacent elements in
    // sectionLengths:"
    for (const auto& pair : *section_lengths) {
      const std::string& name = pair.first;
      const uint64_t length = pair.second;
      // Step 14.1. "If "name"'s specification in knownSections says not to
      // process other sections, add those sections' names to ignoredSections."

      // There're no such sections at the moment.

      // Step 14.2. "If sectionOffsets["name"] exists, return an error. That is,
      // duplicate sections are forbidden."
      // Step 14.3. "Set sectionOffsets["name"] to (currentOffset, length)."
      bool added = section_offsets_
                       .insert(std::make_pair(
                           name, std::make_pair(current_offset, length)))
                       .second;
      if (!added) {
        RunErrorCallbackAndDestroy("Duplicated section.");
        return;
      }

      // Step 14.4. "Set currentOffset to currentOffset + length."
      if (!base::CheckAdd(current_offset, length)
               .AssignIfValid(&current_offset) ||
          current_offset > size_) {
        RunErrorCallbackAndDestroy("Section doesn't fit in the bundle.");
        return;
      }
    }

    // Step 15. "If the "responses" section is not last in sectionLengths,
    // return an error. This allows a streaming parser to assume that it'll
    // know the requests by the time their responses arrive."
    if (section_lengths->empty() ||
        section_lengths->back().first != kResponsesSection) {
      RunErrorCallbackAndDestroy(
          "Responses section is not the last in section-lengths.");
      return;
    }

    // Read the index section.
    auto index_section = section_offsets_.find(kIndexSection);
    if (index_section == section_offsets_.end()) {
      RunErrorCallbackAndDestroy("No index section.");
      return;
    }
    const uint64_t index_section_offset = index_section->second.first;
    const uint64_t index_section_length = index_section->second.second;

    if (index_section_length > kMaxIndexSectionSize) {
      RunErrorCallbackAndDestroy(
          "Index section larger than 1MB is not supported.");
      return;
    }

    data_source_->Read(
        index_section_offset, index_section_length,
        base::BindOnce(&MetadataParser::ParseIndexSection,
                       weak_factory_.GetWeakPtr(), index_section_length));
  }

  // Step 1. of
  // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#index-section
  void ParseIndexSection(uint64_t expected_data_length,
                         const base::Optional<std::vector<uint8_t>>& data) {
    if (!data || data->size() != expected_data_length) {
      RunErrorCallbackAndDestroy("Error reading index section.");
      return;
    }

    // Step 1. "Let index be the result of parsing sectionContents as a CBOR
    // item matching the index rule in the above CDDL (Section 3.5). If index is
    // an error, return an error."
    cbor::Reader::DecoderError error;
    base::Optional<cbor::Value> index_section_value =
        cbor::Reader::Read(*data, &error);
    if (!index_section_value) {
      VLOG(1) << cbor::Reader::ErrorCodeToString(error);
      RunErrorCallbackAndDestroy("Error parsing index section.");
      return;
    }
    if (!index_section_value->is_array()) {
      RunErrorCallbackAndDestroy("Index section must be an array.");
      return;
    }

    // Read the header of the response section.
    auto responses_section = section_offsets_.find(kResponsesSection);
    DCHECK(responses_section != section_offsets_.end());
    const uint64_t responses_section_offset = responses_section->second.first;
    const uint64_t responses_section_length = responses_section->second.second;

    const uint64_t length =
        std::min(responses_section_length, kMaxCBORItemHeaderSize);
    data_source_->Read(
        responses_section_offset, length,
        base::BindOnce(&MetadataParser::ParseResponsesSectionHeader,
                       weak_factory_.GetWeakPtr(),
                       std::move(*index_section_value), length));
  }

  // Step 2- of
  // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#index-section
  void ParseResponsesSectionHeader(
      cbor::Value index_section_value,
      uint64_t expected_data_length,
      const base::Optional<std::vector<uint8_t>>& data) {
    const cbor::Value::ArrayValue& index_section_array =
        index_section_value.GetArray();

    // Step 2.1. "Seek to offset sectionOffsets["responses"].offset in stream.
    // If this fails, return an error."
    if (!data || data->size() != expected_data_length) {
      RunErrorCallbackAndDestroy("Error reading responses section header.");
      return;
    }
    InputReader input(*data);

    // Step 2.2. "Let (responsesType, numResponses) be the result of parsing the
    // type and argument of a CBOR item from the stream (Section 3.5.3). If this
    // returns an error, return that error."
    auto num_responses = input.ReadCBORHeader(CBORType::kArray);
    if (!num_responses) {
      RunErrorCallbackAndDestroy(
          "Cannot parse the number of elements of the responses section.");
      return;
    }
    // Step 2.3. "If responsesType is not 4 (a CBOR array) or numResponses is
    // not half of the length of index, return an error."
    if (index_section_array.size() % 2 != 0 ||
        *num_responses != index_section_array.size() / 2) {
      RunErrorCallbackAndDestroy(
          "Wrong number of elements in the responses section.");
      return;
    }

    // Step 3. "Let currentOffset be the current offset within stream minus
    // sectionOffsets["responses"].offset."
    uint64_t current_offset = input.CurrentOffset();

    // Step 4. "Let requests be an initially-empty map ([INFRA]) from HTTP
    // requests ([FETCH]) to structs ([INFRA]) with items named "offset" and
    // "length"."

    // Step 5. "For each (cbor-http-request, length) pair of adjacent elements
    // in index:"
    for (size_t i = 0; i < index_section_array.size(); i += 2) {
      const cbor::Value& cbor_http_request_value = index_section_array[i];
      const cbor::Value& length_value = index_section_array[i + 1];

      // Step 5.1. "Let (headers, pseudos) be the result of converting
      // cbor-http-request to a header list and pseudoheaders using the
      // algorithm in Section 3.6. If this returns an error, return that error."
      auto parsed_headers = ConvertCBORValueToHeaders(cbor_http_request_value);
      if (!parsed_headers) {
        RunErrorCallbackAndDestroy(
            "Cannot parse headers in the index section.");
        return;
      }

      // Step 5.2. "If pseudos does not have keys named ':method' and
      // ':url', or its size isn't 2, return an error."
      const auto pseudo_method = parsed_headers->pseudos.find(":method");
      const auto pseudo_url = parsed_headers->pseudos.find(":url");
      if (parsed_headers->pseudos.size() != 2 ||
          pseudo_method == parsed_headers->pseudos.end() ||
          pseudo_url == parsed_headers->pseudos.end()) {
        RunErrorCallbackAndDestroy(
            "Request headers map must have exactly two pseudo-headers, :method "
            "and :url.");
        return;
      }

      // Step 5.3. "If pseudos[':method'] is not 'GET', return an error."
      if (pseudo_method->second != "GET") {
        RunErrorCallbackAndDestroy("Request method must be GET.");
        return;
      }

      // Step 5.4. "Let parsedUrl be the result of parsing ([URL])
      // pseudos[':url'] with no base URL."
      GURL parsed_url(pseudo_url->second);

      // Step 5.5. "If parsedUrl is a failure, its fragment is not null, or it
      // includes credentials, return an error."
      if (!parsed_url.is_valid() || parsed_url.has_ref() ||
          parsed_url.has_username() || parsed_url.has_password()) {
        RunErrorCallbackAndDestroy(
            ":url in header map must be a valid URL without fragment or "
            "credentials.");
        return;
      }

      // Step 5.6. "Let http-request be a new request ([FETCH]) whose:
      // - method is pseudos[':method'],
      // - url is parsedUrl,
      // - header list is headers, and
      // - client is null."
      mojom::BundleIndexItemPtr item = mojom::BundleIndexItem::New();
      item->request_method = pseudo_method->second;
      item->request_url = std::move(parsed_url);
      item->request_headers = std::move(parsed_headers->headers);

      // Step 5.7. "Let responseOffset be sectionOffsets["responses"].offset +
      // currentOffset. This is relative to the start of the stream."
      const uint64_t response_offset =
          section_offsets_[kResponsesSection].first + current_offset;

      // Step 5.8. "If currentOffset + length is greater than
      // sectionOffsets["responses"].length, return an error."
      if (!length_value.is_unsigned()) {
        RunErrorCallbackAndDestroy(
            "Length value in the index section should be an unsigned.");
        return;
      }
      const uint64_t length = length_value.GetUnsigned();

      uint64_t response_end;
      if (!base::CheckAdd(current_offset, length)
               .AssignIfValid(&response_end) ||
          response_end > section_offsets_[kResponsesSection].second) {
        RunErrorCallbackAndDestroy(
            "Index map is invalid: total length of responses exceeds the "
            "length of the responses section.");
        return;
      }

      // Step 5.9. "If requests[http-request] exists, return an error. That is,
      // duplicate requests are forbidden."

      // TODO(crbug.com/966753): Implement this check.

      // Step 5.10. "Set requests[http-request] to a struct whose "offset"
      // item is responseOffset and whose "length" item is length."
      item->response_offset = response_offset;
      item->response_length = length;
      items_.push_back(std::move(item));

      // Step 5.11. "Set currentOffset to currentOffset + length."
      current_offset = response_end;
    }

    // We're done.
    RunSuccessCallbackAndDestroy(
        mojom::BundleMetadata::New(std::move(items_), manifest_url_));
  }

  void RunSuccessCallbackAndDestroy(mojom::BundleMetadataPtr metadata) {
    std::move(callback_).Run(std::move(metadata), nullptr);
    delete this;
  }

  void RunErrorCallbackAndDestroy(const std::string& message) {
    std::move(callback_).Run(nullptr,
                             mojom::BundleMetadataParseError::New(message));
    delete this;
  }

  // Implements SharedBundleDataSource::Observer.
  void OnDisconnect() override {
    RunErrorCallbackAndDestroy("Data source disconnected.");
  }

  scoped_refptr<SharedBundleDataSource> data_source_;
  ParseMetadataCallback callback_;
  uint64_t size_;
  // name -> (offset, length)
  std::map<std::string, std::pair<uint64_t, uint64_t>> section_offsets_;
  std::vector<mojom::BundleIndexItemPtr> items_;
  GURL manifest_url_;

  base::WeakPtrFactory<MetadataParser> weak_factory_{this};

  DISALLOW_COPY_AND_ASSIGN(MetadataParser);
};

// A parser for reading single item from the responses section. This class owns
// itself and will self destruct after calling the ParseResponseCallback.
class BundledExchangesParser::ResponseParser
    : public BundledExchangesParser::SharedBundleDataSource::Observer {
 public:
  ResponseParser(scoped_refptr<SharedBundleDataSource> data_source,
                 uint64_t response_offset,
                 uint64_t response_length,
                 BundledExchangesParser::ParseResponseCallback callback)
      : data_source_(data_source),
        response_offset_(response_offset),
        response_length_(response_length),
        callback_(std::move(callback)) {
    data_source_->AddObserver(this);
  }
  ~ResponseParser() override { data_source_->RemoveObserver(this); }

  void Start(uint64_t buffer_size = kInitialBufferSizeForResponse) {
    const uint64_t length = std::min(response_length_, buffer_size);
    data_source_->Read(response_offset_, length,
                       base::BindOnce(&ResponseParser::ParseResponseHeader,
                                      weak_factory_.GetWeakPtr(), length));
  }

 private:
  // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-response
  void ParseResponseHeader(uint64_t expected_data_length,
                           const base::Optional<std::vector<uint8_t>>& data) {
    // Step 1. "Seek to offset requestMetadata.offset in stream. If this fails,
    // return an error."
    if (!data || data->size() != expected_data_length) {
      RunErrorCallbackAndDestroy("Error reading response header.");
      return;
    }
    InputReader input(*data);

    // Step 2. "Read 1 byte from stream. If this is an error or isn't 0x82,
    // return an error."
    auto num_elements = input.ReadCBORHeader(CBORType::kArray);
    if (!num_elements || *num_elements != 2) {
      RunErrorCallbackAndDestroy("Array size of response must be 2.");
      return;
    }

    // Step 3. "Let headerLength be the result of getting the length of a CBOR
    // bytestring header from stream (Section 3.5.2). If headerLength is an
    // error, return that error."
    auto header_length = input.ReadCBORHeader(CBORType::kByteString);
    if (!header_length) {
      RunErrorCallbackAndDestroy("Cannot parse response header length.");
      return;
    }

    // Step 4. "If headerLength is 524288 (512*1024) or greater, return an
    // error."
    if (*header_length >= kMaxResponseHeaderLength) {
      RunErrorCallbackAndDestroy("Response header is too big.");
      return;
    }

    // If we don't have enough data for the headers and the CBOR header of the
    // payload, re-read with a larger buffer size.
    const uint64_t required_buffer_size = std::min(
        input.CurrentOffset() + *header_length + kMaxCBORItemHeaderSize,
        response_length_);
    if (data->size() < required_buffer_size) {
      DVLOG(1) << "Re-reading response header with a buffer of size "
               << required_buffer_size;
      Start(required_buffer_size);
      return;
    }

    // Step 5. "Let headerCbor be the result of reading headerLength bytes from
    // stream and parsing a CBOR item from them matching the headers CDDL rule.
    // If either the read or parse returns an error, return that error."
    auto headers_bytes = input.ReadBytes(*header_length);
    if (!headers_bytes) {
      RunErrorCallbackAndDestroy("Cannot read response headers.");
      return;
    }
    cbor::Reader::DecoderError error;
    base::Optional<cbor::Value> headers_value =
        cbor::Reader::Read(*headers_bytes, &error);
    if (!headers_value) {
      RunErrorCallbackAndDestroy("Cannot parse response headers.");
      return;
    }

    // Step 6. "Let (headers, pseudos) be the result of converting headerCbor
    // to a header list and pseudoheaders using the algorithm in Section 3.6.
    // If this returns an error, return that error."
    auto parsed_headers = ConvertCBORValueToHeaders(*headers_value);
    if (!parsed_headers) {
      RunErrorCallbackAndDestroy("Cannot parse response headers.");
      return;
    }

    // Step 7. "If pseudos does not have a key named ':status' or its size
    // isn't 1, return an error."
    const auto pseudo_status = parsed_headers->pseudos.find(":status");
    if (parsed_headers->pseudos.size() != 1 ||
        pseudo_status == parsed_headers->pseudos.end()) {
      RunErrorCallbackAndDestroy(
          "Response headers map must have exactly one pseudo-header, :status.");
      return;
    }

    // Step 8. "If pseudos[':status'] isn't exactly 3 ASCII decimal digits,
    // return an error."
    int status;
    const auto& status_str = pseudo_status->second;
    if (status_str.size() != 3 ||
        !std::all_of(status_str.begin(), status_str.end(),
                     base::IsAsciiDigit<char>) ||
        !base::StringToInt(status_str, &status)) {
      RunErrorCallbackAndDestroy(":status must be 3 ASCII decimal digits.");
      return;
    }

    // Step 9. "If headers does not contain a Content-Type header, return an
    // error."

    // TODO(crbug.com/966753): Implement this once
    // https://github.com/WICG/webpackage/issues/445 is resolved.

    // Step 10. "Let payloadLength be the result of getting the length of a CBOR
    // bytestring header from stream (Section 3.5.2). If payloadLength is an
    // error, return that error."
    auto payload_length = input.ReadCBORHeader(CBORType::kByteString);
    if (!payload_length) {
      RunErrorCallbackAndDestroy("Cannot parse response payload length.");
      return;
    }

    // Step 11. "If stream.currentOffset + payloadLength !=
    // requestMetadata.offset + requestMetadata.length, return an error."
    if (input.CurrentOffset() + *payload_length != response_length_) {
      RunErrorCallbackAndDestroy("Unexpected payload length.");
      return;
    }

    // Step 12. "Let body be a new body ([FETCH]) whose stream is a tee'd copy
    // of stream starting at the current offset and ending after payloadLength
    // bytes."

    // Step 13. "Let response be a new response ([FETCH]) whose:
    // - Url list is request's url list,
    // - status is pseudos[':status'],
    // - header list is headers, and
    // - body is body."
    mojom::BundleResponsePtr response = mojom::BundleResponse::New();
    response->response_code = status;
    response->response_headers = std::move(parsed_headers->headers);
    response->payload_offset = response_offset_ + input.CurrentOffset();
    response->payload_length = *payload_length;
    RunSuccessCallbackAndDestroy(std::move(response));
  }

  void RunSuccessCallbackAndDestroy(mojom::BundleResponsePtr response) {
    std::move(callback_).Run(std::move(response), nullptr);
    delete this;
  }

  void RunErrorCallbackAndDestroy(const std::string& message) {
    std::move(callback_).Run(nullptr,
                             mojom::BundleResponseParseError::New(message));
    delete this;
  }

  // Implements SharedBundleDataSource::Observer.
  void OnDisconnect() override {
    RunErrorCallbackAndDestroy("Data source disconnected.");
  }

  scoped_refptr<SharedBundleDataSource> data_source_;
  uint64_t response_offset_;
  uint64_t response_length_;
  ParseResponseCallback callback_;

  base::WeakPtrFactory<ResponseParser> weak_factory_{this};

  DISALLOW_COPY_AND_ASSIGN(ResponseParser);
};

BundledExchangesParser::SharedBundleDataSource::SharedBundleDataSource(
    mojo::PendingRemote<mojom::BundleDataSource> pending_data_source)
    : data_source_(std::move(pending_data_source)) {
  data_source_.set_disconnect_handler(base::BindOnce(
      &SharedBundleDataSource::OnDisconnect, base::Unretained(this)));
}

void BundledExchangesParser::SharedBundleDataSource::AddObserver(
    Observer* observer) {
  DCHECK(observers_.end() == observers_.find(observer));
  observers_.insert(observer);
}

void BundledExchangesParser::SharedBundleDataSource::RemoveObserver(
    Observer* observer) {
  auto it = observers_.find(observer);
  DCHECK(observers_.end() != it);
  observers_.erase(it);
}

BundledExchangesParser::SharedBundleDataSource::~SharedBundleDataSource() =
    default;

void BundledExchangesParser::SharedBundleDataSource::OnDisconnect() {
  for (auto* observer : observers_)
    observer->OnDisconnect();
}

void BundledExchangesParser::SharedBundleDataSource::GetSize(
    GetSizeCallback callback) {
  data_source_->GetSize(std::move(callback));
}

void BundledExchangesParser::SharedBundleDataSource::Read(
    uint64_t offset,
    uint64_t length,
    ReadCallback callback) {
  data_source_->Read(offset, length, std::move(callback));
}

BundledExchangesParser::BundledExchangesParser(
    mojo::PendingReceiver<mojom::BundledExchangesParser> receiver,
    mojo::PendingRemote<mojom::BundleDataSource> data_source)
    : receiver_(this, std::move(receiver)),
      data_source_(base::MakeRefCounted<SharedBundleDataSource>(
          std::move(data_source))) {
  receiver_.set_disconnect_handler(base::BindOnce(
      &base::DeletePointer<BundledExchangesParser>, base::Unretained(this)));
}

BundledExchangesParser::~BundledExchangesParser() = default;

void BundledExchangesParser::ParseMetadata(ParseMetadataCallback callback) {
  MetadataParser* parser =
      new MetadataParser(data_source_, std::move(callback));
  parser->Start();
}

void BundledExchangesParser::ParseResponse(
    uint64_t response_offset,
    uint64_t response_length,
    ParseResponseCallback callback) {
  ResponseParser* parser = new ResponseParser(
      data_source_, response_offset, response_length, std::move(callback));
  parser->Start();
}

}  // namespace data_decoder
