blob: d51c60e2c4f4188950a84cc45eb95bb9d3e2badb [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_ISOLATED_WEB_APP_RESPONSE_READER_FACTORY_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_ISOLATED_WEB_APP_RESPONSE_READER_FACTORY_H_
#include <memory>
#include <string>
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/types/expected.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader.h"
#include "chrome/browser/web_applications/isolated_web_apps/signed_web_bundle_reader.h"
#include "components/web_package/mojom/web_bundle_parser.mojom-forward.h"
#include "components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace web_package {
class SignedWebBundleId;
class SignedWebBundleIntegrityBlock;
} // namespace web_package
namespace web_app {
class IsolatedWebAppValidator;
// Simple struct used to represent errors related to the integrity block of the
// Signed Web Bundle.
struct IntegrityBlockError {
explicit IntegrityBlockError(std::string message)
: message(std::move(message)) {}
std::string message;
};
// Simple struct used to represent errors related to the metadata of the Signed
// Web Bundle.
struct MetadataError {
explicit MetadataError(std::string message) : message(std::move(message)) {}
std::string message;
};
// Factory for creating instances of `IsolatedWebAppResponseReader` that are
// ready to read responses from the bundle. Instances returned by this class are
// guaranteed to have previously read a valid integrity block and metadata, as
// well as to have verified that the signatures are valid (unless
// `skip_signature_verification` is set).
class IsolatedWebAppResponseReaderFactory {
public:
IsolatedWebAppResponseReaderFactory(
std::unique_ptr<IsolatedWebAppValidator> validator,
base::RepeatingCallback<
std::unique_ptr<web_package::SignedWebBundleSignatureVerifier>()>
signature_verifier_factory);
~IsolatedWebAppResponseReaderFactory();
IsolatedWebAppResponseReaderFactory(
const IsolatedWebAppResponseReaderFactory&) = delete;
IsolatedWebAppResponseReaderFactory& operator=(
const IsolatedWebAppResponseReaderFactory&) = delete;
using Error = absl::variant<
// Triggered when the integrity block of the Signed Web
// Bundle does not exist or parsing it fails.
web_package::mojom::BundleIntegrityBlockParseErrorPtr,
// Triggered when the integrity block is not valid for this Isolated Web
// App or when the user agent does not trust the Isolated Web App.
IntegrityBlockError,
// Triggered when signature verification fails.
web_package::SignedWebBundleSignatureVerifier::Error,
// Triggered when metadata parsing fails.
web_package::mojom::BundleMetadataParseErrorPtr,
// Triggered when the metadata is not valid for this Isolated Web App.
MetadataError>;
using Callback = base::OnceCallback<void(
base::expected<std::unique_ptr<IsolatedWebAppResponseReader>, Error>)>;
void CreateResponseReader(const base::FilePath& web_bundle_path,
const web_package::SignedWebBundleId& web_bundle_id,
bool skip_signature_verification,
Callback callback);
// This enum represents every error type that can occur during integrity block
// and metadata parsing, before responses are read from Signed Web Bundles.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class ReadIntegrityBlockAndMetadataStatus {
kSuccess = 0,
// Integrity Block-related errors
kIntegrityBlockParserInternalError = 1,
kIntegrityBlockParserFormatError = 2,
kIntegrityBlockParserVersionError = 3,
kIntegrityBlockValidationError = 4,
// Signature verification errors
kSignatureVerificationError = 5,
// Metadata-related errors
kMetadataParserInternalError = 6,
kMetadataParserFormatError = 7,
kMetadataParserVersionError = 8,
kMetadataValidationError = 9,
kMaxValue = kMetadataValidationError
};
private:
void OnIntegrityBlockRead(
const web_package::SignedWebBundleId& web_bundle_id,
bool skip_signature_verification,
const web_package::SignedWebBundleIntegrityBlock integrity_block,
base::OnceCallback<
void(SignedWebBundleReader::SignatureVerificationAction)> callback);
void OnIntegrityBlockValidated(
bool skip_signature_verification,
base::OnceCallback<
void(SignedWebBundleReader::SignatureVerificationAction)>
integrity_callback,
absl::optional<std::string> integrity_block_error);
void OnIntegrityBlockAndMetadataRead(
std::unique_ptr<SignedWebBundleReader> reader,
const base::FilePath& web_bundle_path,
const web_package::SignedWebBundleId& web_bundle_id,
Callback callback,
absl::optional<SignedWebBundleReader::ReadIntegrityBlockAndMetadataError>
read_integrity_block_and_metadata_error);
ReadIntegrityBlockAndMetadataStatus GetStatusFromError(
const SignedWebBundleReader::ReadIntegrityBlockAndMetadataError& error);
std::unique_ptr<IsolatedWebAppValidator> validator_;
base::RepeatingCallback<
std::unique_ptr<web_package::SignedWebBundleSignatureVerifier>()>
signature_verifier_factory_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<IsolatedWebAppResponseReaderFactory> weak_ptr_factory_{
this};
};
} // namespace web_app
#endif // CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_ISOLATED_WEB_APP_RESPONSE_READER_FACTORY_H_