blob: 1f34b773a31881fbf94287e9ac1110298ae3e8a3 [file] [log] [blame]
// Copyright 2024 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_ISOLATION_DATA_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_ISOLATION_DATA_H_
#include <optional>
#include <set>
#include <string>
#include "base/version.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_integrity_block_data.h"
#include "components/webapps/isolated_web_apps/types/storage_location.h"
#include "components/webapps/isolated_web_apps/types/update_channel.h"
#include "url/gurl.h"
namespace web_app {
// Represents IWA-specific pieces of a Web App.
class IsolationData {
public:
struct PendingUpdateInfo {
PendingUpdateInfo(IsolatedWebAppStorageLocation location,
base::Version version,
std::optional<IsolatedWebAppIntegrityBlockData>
integrity_block_data = std::nullopt);
~PendingUpdateInfo();
PendingUpdateInfo(const PendingUpdateInfo&);
PendingUpdateInfo& operator=(const PendingUpdateInfo&);
bool operator==(const PendingUpdateInfo&) const = default;
base::Value AsDebugValue() const;
friend std::ostream& operator<<(std::ostream& os,
const PendingUpdateInfo& update_info) {
return os << update_info.AsDebugValue();
}
IsolatedWebAppStorageLocation location;
base::Version version;
std::optional<IsolatedWebAppIntegrityBlockData> integrity_block_data;
};
class OpenedTabsCounterNotificationState {
public:
explicit OpenedTabsCounterNotificationState(
proto::IsolationData_OpenedTabsCounterNotificationState state);
OpenedTabsCounterNotificationState(bool acknowledged, uint32_t times_shown);
~OpenedTabsCounterNotificationState() = default;
OpenedTabsCounterNotificationState(
const OpenedTabsCounterNotificationState&) = default;
OpenedTabsCounterNotificationState& operator=(
const OpenedTabsCounterNotificationState&) = default;
OpenedTabsCounterNotificationState(OpenedTabsCounterNotificationState&&) =
default;
OpenedTabsCounterNotificationState& operator=(
OpenedTabsCounterNotificationState&&) = default;
bool operator==(const OpenedTabsCounterNotificationState& other) const {
return proto_state_.SerializeAsString() ==
other.proto_state_.SerializeAsString();
}
bool acknowledged() const { return proto_state_.acknowledged(); }
uint32_t times_shown() const { return proto_state_.times_shown(); }
const proto::IsolationData::OpenedTabsCounterNotificationState& GetState()
const;
private:
proto::IsolationData::OpenedTabsCounterNotificationState proto_state_;
};
~IsolationData();
IsolationData(const IsolationData&);
IsolationData& operator=(const IsolationData&);
IsolationData(IsolationData&&);
IsolationData& operator=(IsolationData&&);
bool operator==(const IsolationData&) const = default;
base::Value AsDebugValue() const;
friend std::ostream& operator<<(std::ostream& os,
const IsolationData& isolation_data) {
return os << isolation_data.AsDebugValue();
}
const IsolatedWebAppStorageLocation& location() const { return location_; }
const base::Version& version() const { return version_; }
const std::set<std::string>& controlled_frame_partitions() const {
return controlled_frame_partitions_;
}
const std::optional<PendingUpdateInfo>& pending_update_info() const {
return pending_update_info_;
}
const std::optional<IsolatedWebAppIntegrityBlockData>& integrity_block_data()
const {
return integrity_block_data_;
}
const std::optional<GURL>& update_manifest_url() const {
return update_manifest_url_;
}
const std::optional<UpdateChannel>& update_channel() const {
return update_channel_;
}
const std::optional<OpenedTabsCounterNotificationState>&
opened_tabs_counter_notification_state() const {
return opened_tabs_counter_notification_state_;
}
private:
IsolationData(
IsolatedWebAppStorageLocation location,
base::Version version,
std::set<std::string> controlled_frame_partitions,
std::optional<PendingUpdateInfo> pending_update_info,
std::optional<IsolatedWebAppIntegrityBlockData> integrity_block_data,
std::optional<GURL> update_manifest_url,
std::optional<UpdateChannel> update_channel,
std::optional<OpenedTabsCounterNotificationState>
opened_tabs_counter_notification_state);
IsolatedWebAppStorageLocation location_;
base::Version version_;
std::set<std::string> controlled_frame_partitions_;
// If present, signals that an update for this app is available locally and
// waiting to be applied.
std::optional<PendingUpdateInfo> pending_update_info_;
// Might be nullopt if this IWA is not backed by a signed web bundle (for
// instance, in case of a proxy mode installation).
// This field is used to prevent redundant update attempts in case of key
// rotation by comparing the stored public keys against the rotated key.
// key. Please don't rely on it for anything security-critical!
std::optional<IsolatedWebAppIntegrityBlockData> integrity_block_data_;
// Informs the browser where to look up the update manifest for this IWA and
// which update channel to use.
// These fields are only used for dev mode installs from update manifest via
// chrome://web-app-internals; for all other install types they are left
// blank. For unmanaged installs this will likely need to have a counterpart
// in PendingUpdateInfo.
std::optional<GURL> update_manifest_url_;
std::optional<OpenedTabsCounterNotificationState>
opened_tabs_counter_notification_state_;
std::optional<UpdateChannel> update_channel_;
public:
class Builder {
public:
Builder(IsolatedWebAppStorageLocation location, base::Version version);
explicit Builder(const IsolationData& isolation_data);
~Builder();
Builder(const Builder&);
Builder& operator=(const Builder&);
Builder(Builder&&);
Builder& operator=(Builder&&);
Builder& SetControlledFramePartitions(
std::set<std::string> controlled_frame_partitions) &;
Builder&& SetControlledFramePartitions(
std::set<std::string> controlled_frame_partitions) &&;
// Will `CHECK` if dev mode is different between
// `pending_update_info.location` and `location`. In other words, a dev mode
// owned bundle can never be updated to a prod mode owned bundle.
Builder& SetPendingUpdateInfo(
IsolationData::PendingUpdateInfo pending_update_info) &;
Builder&& SetPendingUpdateInfo(
IsolationData::PendingUpdateInfo pending_update_info) &&;
Builder& SetOpenedTabsCounterNotificationState(
OpenedTabsCounterNotificationState notification_state) &;
Builder&& SetOpenedTabsCounterNotificationState(
OpenedTabsCounterNotificationState notification_state) &&;
Builder& ClearPendingUpdateInfo() &;
Builder&& ClearPendingUpdateInfo() &&;
Builder& SetIntegrityBlockData(
IsolatedWebAppIntegrityBlockData integrity_block_data) &;
Builder&& SetIntegrityBlockData(
IsolatedWebAppIntegrityBlockData integrity_block_data) &&;
// Update manifest is supposed to be set only for selected dev-mode
// installs. Will `CHECK`-fail if applied to a prod-mode location.
Builder& SetUpdateManifestUrl(GURL update_manifest_url) &;
Builder&& SetUpdateManifestUrl(GURL update_manifest_url) &&;
// Update channel is supposed to be set only for selected dev-mode
// installs. Will `CHECK`-fail if applied to a prod-mode location.
Builder& SetUpdateChannel(UpdateChannel update_channel) &;
Builder&& SetUpdateChannel(UpdateChannel update_channel) &&;
// During an update the foundational pieces of the IWA (`location` and
// `version`) of the IWA change, and hence the IsolationData has to be
// re-built from scratch. This function is called as part of the update
// finalize routine -- all fields that have to be persisted (such as
// `controlled_frame_partitions`, etc) can be copied over here.
Builder& PersistFieldsForUpdate(const IsolationData& isolation_data) &;
Builder&& PersistFieldsForUpdate(const IsolationData& isolation_data) &&;
// When adding new setters to the builder, make sure to update the the
// Builder(const IsolationData&) constructor to forward the new field as
// well as PersistFieldsForUpdate(const IsolationData&) if necessary.
IsolationData Build() &&;
private:
IsolatedWebAppStorageLocation location_;
base::Version version_;
std::set<std::string> controlled_frame_partitions_;
std::optional<IsolationData::PendingUpdateInfo> pending_update_info_;
std::optional<IsolatedWebAppIntegrityBlockData> integrity_block_data_;
std::optional<GURL> update_manifest_url_;
std::optional<OpenedTabsCounterNotificationState>
opened_tabs_counter_notification_state_;
std::optional<UpdateChannel> update_channel_;
};
};
} // namespace web_app
#endif // CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_ISOLATION_DATA_H_