1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// 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_UPDATE_MANIFEST_UPDATE_MANIFEST_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_UPDATE_MANIFEST_UPDATE_MANIFEST_H_
#include <iosfwd>
#include <optional>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/types/expected.h"
#include "base/types/optional_ref.h"
#include "base/values.h"
#include "base/version.h"
#include "components/webapps/isolated_web_apps/update_channel.h"
#include "url/gurl.h"
namespace web_app {
inline constexpr std::string_view kUpdateManifestAllVersionsKey = "versions";
inline constexpr std::string_view kUpdateManifestAllChannelsKey = "channels";
inline constexpr std::string_view kUpdateManifestChannelNameKey = "name";
inline constexpr std::string_view kUpdateManifestVersionKey = "version";
inline constexpr std::string_view kUpdateManifestSrcKey = "src";
inline constexpr std::string_view kUpdateManifestChannelsKey = "channels";
// An Isolated Web App Update Manifest contains a list of versions and download
// URLs of an Isolated Web App. The format is described in more detail here:
// https://github.com/WICG/isolated-web-apps/blob/main/Updates.md#web-application-update-manifest
class UpdateManifest {
public:
enum class JsonFormatError {
kRootNotADictionary,
kChannelsNotADictionary,
kChannelNotADictionary,
kVersionsNotAnArray,
kVersionEntryNotADictionary,
};
class ChannelMetadata {
public:
static base::expected<ChannelMetadata, std::monostate> ParseFromJson(
const base::Value::Dict& channel_metadata_dict);
ChannelMetadata(UpdateChannel update_channel,
std::optional<std::string> display_name);
ChannelMetadata(const ChannelMetadata& other);
ChannelMetadata& operator=(const ChannelMetadata& other);
~ChannelMetadata();
bool operator==(const ChannelMetadata& other) const;
// For gtest
friend void PrintTo(const ChannelMetadata& channel_metadata,
std::ostream* os);
// Returns the channel's display name if available, or the channel name
// otherwise.
std::string GetDisplayName() const {
return display_name_.value_or(channel_.ToString());
}
const UpdateChannel& channel() const { return channel_; }
const std::optional<std::string>& display_name() const {
return display_name_;
}
private:
UpdateChannel channel_;
std::optional<std::string> display_name_;
};
class VersionEntry {
public:
static base::expected<VersionEntry, std::monostate> ParseFromJson(
const base::Value::Dict& version_entry_dict,
const GURL& update_manifest_url);
VersionEntry(GURL src,
base::Version version,
base::flat_set<UpdateChannel> channels);
VersionEntry(const VersionEntry& other);
VersionEntry& operator=(const VersionEntry& other);
~VersionEntry();
GURL src() const;
base::Version version() const;
// Each version contains to a set of update channels, which are defined by
// the IWA's developer. While the field is optional in the spec, it is
// always present here and set to its spec-defined default value of
// `["default"]` if not provided.
const base::flat_set<UpdateChannel>& channels() const;
private:
friend bool operator==(const VersionEntry& a, const VersionEntry& b);
static base::expected<base::Version, std::monostate>
ParseAndValidateVersion(
base::optional_ref<const base::Value> version_value);
static base::expected<GURL, std::monostate> ParseAndValidateSrc(
base::optional_ref<const base::Value> src_value,
const GURL& update_manifest_url);
// Parses the `channels` field value of a version entry and either returns a
// set of channels on success or an error on failure. If `channels` is not
// set (i.e., `channels_value` is `std::nullopt`), then a set containing
// just the "default" channel is returned.
static base::expected<base::flat_set<UpdateChannel>, std::monostate>
ParseAndValidateChannels(
base::optional_ref<const base::Value> channels_value);
GURL src_;
base::Version version_;
base::flat_set<UpdateChannel> channels_;
};
// Attempts to convert the provided JSON data into an instance of
// `UpdateManifest`.
//
// Note that at least one version entry is required; otherwise the Update
// Manifest is treated as invalid.
//
// `update_manifest_url` is used to resolve relative `src` URLs in `versions`.
static base::expected<UpdateManifest, JsonFormatError> CreateFromJson(
const base::Value& json,
const GURL& update_manifest_url);
UpdateManifest(const UpdateManifest& other);
UpdateManifest& operator=(const UpdateManifest& other);
~UpdateManifest();
const std::vector<VersionEntry>& versions() const { return version_entries_; }
// Returns the most up to date version contained in the `UpdateManifest` for a
// given `channel`. May return `std::nullopt` if no applicable version is
// found.
std::optional<VersionEntry> GetLatestVersion(
const UpdateChannel& channel) const;
// Returns version entry for given version and channel. If there is no entry
// matching the criteria, then it returns `std::nullopt'.
std::optional<VersionEntry> GetVersion(const base::Version& version,
const UpdateChannel& channel) const;
// Returns channel metadata for a provided update channel ID. If no metadata
// for the provided channel ID is present in the Update Manifest, then this
// will still return an empty `ChannelMetadata` instance for that channel ID.
ChannelMetadata GetChannelMetadata(const UpdateChannel& channel) const;
private:
explicit UpdateManifest(
std::vector<VersionEntry> version_entries,
base::flat_map<UpdateChannel, ChannelMetadata> channels_metadata);
std::vector<VersionEntry> version_entries_;
base::flat_map<UpdateChannel, ChannelMetadata> channels_metadata_;
};
bool operator==(const UpdateManifest::VersionEntry& lhs,
const UpdateManifest::VersionEntry& rhs);
std::ostream& operator<<(std::ostream& os,
const UpdateManifest::VersionEntry& version_entry);
} // namespace web_app
#endif // CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_UPDATE_MANIFEST_UPDATE_MANIFEST_H_
|