File: update_manifest.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (180 lines) | stat: -rw-r--r-- 6,649 bytes parent folder | download | duplicates (5)
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_