blob: 8f1960521c42828cb3f6cf2f1144a346db4110c8 [file] [log] [blame]
// 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.
#ifndef CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_READER_H_
#define CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_READER_H_
#include <string>
#include "base/containers/flat_map.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_producer.h"
#include "services/data_decoder/public/cpp/safe_bundled_exchanges_parser.h"
#include "services/data_decoder/public/mojom/bundled_exchanges_parser.mojom.h"
#include "url/gurl.h"
namespace content {
struct BundledExchangesSource;
// A class to handle a BundledExchanges that is specified by |source|.
// It asks the utility process to parse metadata and response structures, and
// provides body data based on parsed information.
// Running on the UI thread.
class CONTENT_EXPORT BundledExchangesReader final {
public:
explicit BundledExchangesReader(const BundledExchangesSource& source);
~BundledExchangesReader();
// Starts parsing, and runs |callback| when meta data gets to be available.
// |error| is set only on failures.
// Other methods below are only available after this |callback| invocation.
using MetadataCallback = base::OnceCallback<void(
data_decoder::mojom::BundleMetadataParseErrorPtr error)>;
void ReadMetadata(MetadataCallback callback);
// Gets data_decoder::mojom::BundleResponsePtr for the given |url| that
// contains response headers and range information for its body.
// Should be called after ReadMetadata finishes.
using ResponseCallback =
base::OnceCallback<void(data_decoder::mojom::BundleResponsePtr)>;
void ReadResponse(const GURL& url, ResponseCallback callback);
// Starts loading response body. |response| should be obtained by
// ReadResponse above beforehand. Body will be written into |producer_handle|.
// After all body data is written, |callback| will be invoked.
using BodyCompletionCallback = base::OnceCallback<void(MojoResult result)>;
void ReadResponseBody(data_decoder::mojom::BundleResponsePtr response,
mojo::ScopedDataPipeProducerHandle producer_handle,
BodyCompletionCallback callback);
// Returns true if the BundledExchangesSource this object was constructed with
// contains an exchange for |url|.
// Should be called after ReadMetadata finishes.
bool HasEntry(const GURL& url) const;
// Returns the bundle's primary URL.
// Should be called after ReadMetadata finishes.
const GURL& GetPrimaryURL() const;
void SetBundledExchangesParserFactoryForTesting(
mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> factory);
private:
// A simple wrapper class to share a single base::File instance among multiple
// SharedFileDataSource instances.
class SharedFile final : public base::RefCountedThreadSafe<SharedFile> {
public:
explicit SharedFile(const base::FilePath& file_path);
void DuplicateFile(base::OnceCallback<void(base::File)> callback);
base::File* operator->();
private:
friend class base::RefCountedThreadSafe<SharedFile>;
~SharedFile();
void SetFile(std::unique_ptr<base::File> file);
base::FilePath file_path_;
std::unique_ptr<base::File> file_;
base::OnceCallback<void(base::File)> duplicate_callback_;
DISALLOW_COPY_AND_ASSIGN(SharedFile);
};
class SharedFileDataSource;
void ReadMetadataInternal(MetadataCallback callback, base::File file);
void OnMetadataParsed(MetadataCallback callback,
data_decoder::mojom::BundleMetadataPtr metadata,
data_decoder::mojom::BundleMetadataParseErrorPtr error);
void OnResponseParsed(ResponseCallback callback,
data_decoder::mojom::BundleResponsePtr response,
data_decoder::mojom::BundleResponseParseErrorPtr error);
SEQUENCE_CHECKER(sequence_checker_);
data_decoder::SafeBundledExchangesParser parser_;
scoped_refptr<SharedFile> file_;
GURL primary_url_;
base::flat_map<GURL, data_decoder::mojom::BundleIndexValuePtr> entries_;
bool metadata_ready_ = false;
base::WeakPtrFactory<BundledExchangesReader> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(BundledExchangesReader);
};
} // namespace content
#endif // CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_READER_H_