blob: 25cf166e53e5325f6f9ea92522e37de0bc806f93 [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_WEB_BUNDLE_BLOB_DATA_SOURCE_H_
#define CONTENT_BROWSER_WEB_PACKAGE_WEB_BUNDLE_BLOB_DATA_SOURCE_H_
#include <vector>
#include "base/callback_forward.h"
#include "components/web_package/mojom/web_bundle_parser.mojom.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_context.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/net_errors.h"
#include "services/network/public/mojom/url_loader.mojom.h"
namespace storage {
class BlobBuilderFromStream;
class BlobDataHandle;
} // namespace storage
namespace content {
// This class is used to read partial body data of a web bundle response from
// server. Currently this class can't read any partial body data before
// receiving the whole body. TODO(crbug/1018640): Support progressive loading.
class CONTENT_EXPORT WebBundleBlobDataSource {
public:
using CompletionCallback = base::OnceCallback<void(net::Error net_error)>;
// This class keeps |endpoints| to keep the ongoing network request.
WebBundleBlobDataSource(
uint64_t length_hint,
mojo::ScopedDataPipeConsumerHandle outer_response_body,
network::mojom::URLLoaderClientEndpointsPtr endpoints,
BrowserContext::BlobContextGetter blob_context_getter);
WebBundleBlobDataSource(const WebBundleBlobDataSource&) = delete;
WebBundleBlobDataSource& operator=(const WebBundleBlobDataSource&) = delete;
~WebBundleBlobDataSource();
void AddReceiver(mojo::PendingReceiver<web_package::mojom::BundleDataSource>
pending_receiver);
void ReadToDataPipe(uint64_t offset,
uint64_t length,
mojo::ScopedDataPipeProducerHandle producer_handle,
CompletionCallback callback);
private:
// This class lives on the IO thread.
class BlobDataSourceCore : public web_package::mojom::BundleDataSource {
public:
BlobDataSourceCore(uint64_t length_hint,
network::mojom::URLLoaderClientEndpointsPtr endpoints,
BrowserContext::BlobContextGetter blob_context_getter);
BlobDataSourceCore(const BlobDataSourceCore&) = delete;
BlobDataSourceCore& operator=(const BlobDataSourceCore&) = delete;
~BlobDataSourceCore() override;
void Start(mojo::ScopedDataPipeConsumerHandle outer_response_body);
void AddReceiver(mojo::PendingReceiver<web_package::mojom::BundleDataSource>
pending_receiver);
void ReadToDataPipe(uint64_t offset,
uint64_t length,
mojo::ScopedDataPipeProducerHandle producer_handle,
CompletionCallback callback);
base::WeakPtr<BlobDataSourceCore> GetWeakPtr();
private:
// Implements web_package::mojom::BundleDataSource.
void Read(uint64_t offset, uint64_t length, ReadCallback callback) override;
void Length(LengthCallback callback) override;
void IsRandomAccessContext(IsRandomAccessContextCallback callback) override;
void StreamingBlobDone(storage::BlobBuilderFromStream* builder,
std::unique_ptr<storage::BlobDataHandle> result);
void WaitForBlob(base::OnceClosure closure);
void OnBlobReadyForRead(uint64_t offset,
uint64_t length,
ReadCallback callback);
void OnBlobReadyForReadToDataPipe(
uint64_t offset,
uint64_t length,
mojo::ScopedDataPipeProducerHandle producer_handle,
CompletionCallback callback);
const uint64_t length_hint_;
// Used to keep the ongoing network request.
network::mojom::URLLoaderClientEndpointsPtr endpoints_;
mojo::ReceiverSet<web_package::mojom::BundleDataSource> receivers_;
std::unique_ptr<storage::BlobBuilderFromStream> blob_builder_from_stream_;
std::unique_ptr<storage::BlobDataHandle> blob_;
// Used to wait StreamingBlobDone() to be called.
std::vector<base::OnceClosure> pending_get_blob_tasks_;
base::WeakPtrFactory<BlobDataSourceCore> weak_factory_{this};
};
static void CreateCoreOnIO(
base::WeakPtr<WebBundleBlobDataSource> weak_ptr,
uint64_t length_hint,
mojo::ScopedDataPipeConsumerHandle outer_response_body,
network::mojom::URLLoaderClientEndpointsPtr endpoints,
BrowserContext::BlobContextGetter blob_context_getter);
static void SetCoreOnUI(base::WeakPtr<WebBundleBlobDataSource> weak_ptr,
base::WeakPtr<BlobDataSourceCore> weak_core,
std::unique_ptr<BlobDataSourceCore> core);
void WaitForCore(base::OnceClosure callback);
void ReadToDataPipeImpl(uint64_t offset,
uint64_t length,
mojo::ScopedDataPipeProducerHandle producer_handle,
CompletionCallback callback);
void SetCoreOnUIImpl(base::WeakPtr<BlobDataSourceCore> weak_core,
std::unique_ptr<BlobDataSourceCore> core);
void AddReceiverImpl(
mojo::PendingReceiver<web_package::mojom::BundleDataSource>
pending_receiver);
// Used to call BlobDataSourceCore's method on the IO thread.
base::WeakPtr<BlobDataSourceCore> weak_core_;
// Owned by |this|. Must be deleted on the IO thread.
std::unique_ptr<BlobDataSourceCore> core_;
// Used to wait SetCoreOnUI() to be called.
std::vector<base::OnceClosure> pending_get_core_tasks_;
base::WeakPtrFactory<WebBundleBlobDataSource> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WEB_PACKAGE_WEB_BUNDLE_BLOB_DATA_SOURCE_H_