File: iwa_key_distribution_info_provider.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 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 (206 lines) | stat: -rw-r--r-- 7,799 bytes parent folder | download | duplicates (3)
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// 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 COMPONENTS_WEBAPPS_ISOLATED_WEB_APPS_IWA_KEY_DISTRIBUTION_INFO_PROVIDER_H_
#define COMPONENTS_WEBAPPS_ISOLATED_WEB_APPS_IWA_KEY_DISTRIBUTION_INFO_PROVIDER_H_

#include <optional>
#include <string>
#include <string_view>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/one_shot_event.h"
#include "base/task/sequenced_task_runner.h"
#include "base/types/expected.h"
#include "base/types/pass_key.h"
#include "base/values.h"
#include "base/version.h"
#include "components/webapps/isolated_web_apps/iwa_key_distribution_histograms.h"
#include "components/webapps/isolated_web_apps/proto/key_distribution.pb.h"

namespace base {
class FilePath;
}  // namespace base

namespace web_app {

class IwaInternalsHandler;

// This class is a singleton responsible for processing the IWA Key Distribution
// Component data.
class IwaKeyDistributionInfoProvider {
 public:
  struct KeyRotationInfo {
    using PublicKeyData = std::vector<uint8_t>;

    explicit KeyRotationInfo(std::optional<PublicKeyData> public_key);
    ~KeyRotationInfo();
    KeyRotationInfo(const KeyRotationInfo&);

    base::Value AsDebugValue() const;

    std::optional<PublicKeyData> public_key;
  };

  struct SpecialAppPermissionsInfo {
    base::Value AsDebugValue() const;

    bool skip_capture_started_notification;
  };

  using KeyRotations = base::flat_map<std::string, KeyRotationInfo>;
  using ManagedAllowlist = base::flat_set<std::string>;
  using SpecialAppPermissions =
      base::flat_map<std::string, SpecialAppPermissionsInfo>;
  using KeyDistributionData =
      std::tuple<KeyRotations, SpecialAppPermissions, ManagedAllowlist>;

  using QueueOnDemandUpdateCallback = base::RepeatingCallback<bool(
      base::PassKey<IwaKeyDistributionInfoProvider>)>;

  class Observer : public base::CheckedObserver {
   public:
    virtual void OnComponentUpdateSuccess(const base::Version& version,
                                          bool is_preloaded) {}
    virtual void OnComponentUpdateError(const base::Version& version,
                                        IwaComponentUpdateError error) {}
  };

  struct ComponentData {
    ComponentData(base::Version version,
                  KeyRotations key_rotations,
                  SpecialAppPermissions special_app_permissions,
                  ManagedAllowlist managed_allowlist,
                  bool is_preloaded);
    ~ComponentData();
    ComponentData(const ComponentData&);

    base::Version version;
    KeyRotations key_rotations;
    SpecialAppPermissions special_app_permissions;
    ManagedAllowlist managed_allowlist;

    bool is_preloaded = false;
  };

  static IwaKeyDistributionInfoProvider& GetInstance();
  static void DestroyInstanceForTesting();

  ~IwaKeyDistributionInfoProvider();

  IwaKeyDistributionInfoProvider(const IwaKeyDistributionInfoProvider&) =
      delete;
  IwaKeyDistributionInfoProvider& operator=(
      const IwaKeyDistributionInfoProvider&) = delete;

  const KeyRotationInfo* GetKeyRotationInfo(
      const std::string& web_bundle_id) const;
  const SpecialAppPermissionsInfo* GetSpecialAppPermissionsInfo(
      const std::string& web_bundle_id) const;
  std::vector<std::string> GetSkipMultiCaptureNotificationBundleIds() const;

  // Only bundles present in the managed allowlist can be installed and updated.
  bool IsManagedInstallPermitted(std::string_view web_bundle_id) const;
  bool IsManagedUpdatePermitted(std::string_view web_bundle_id) const;

  // When set to true both above functions always return true
  void SkipManagedAllowlistChecksForTesting(bool skip_managed_checks);

  // Sets up the `IwaKeyDistributionInfoProvider`, i.e. adds the capability to
  // schedule on demand callbacks.
  void SetUp(bool is_on_demand_supported, QueueOnDemandUpdateCallback callback);

  // Asynchronously loads new component data and replaces the current `data_`
  // upon success and if `component_version` is greater than the stored one, and
  // informs observers about the operation result.
  void LoadKeyDistributionData(const base::Version& component_version,
                               const base::FilePath& file_path,
                               bool is_preloaded);

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Sets a custom key rotation outside of the component updater flow and
  // triggers an `OnComponentUpdateSuccess()` event. The usage of this function
  // is intentionally limited to chrome://web-app-internals.
  void RotateKeyForDevMode(
      base::PassKey<IwaInternalsHandler>,
      const std::string& web_bundle_id,
      const std::optional<std::vector<uint8_t>>& rotated_key);

  // Dumps the entire component data to web-app-internals.
  base::Value AsDebugValue() const;

  // Writes component metadata (version and whether it's preloaded) to `log`.
  void WriteComponentMetadata(base::Value::Dict& log) const;

  // Use this to post IWA-related tasks if they rely on the key distribution
  // component. The event will be signalled
  //  * Immediately if the kIwaKeyDistributionComponent flag is disabled
  //  * Upon component loading if the available component is downloaded and not
  //    preloaded
  //  * In 15 seconds after the first call to this function if the available
  //  component is preloaded and the component updater is unable to fetch a
  //  newer version.
  base::OneShotEvent& OnMaybeDownloadedComponentDataReady();

  std::optional<bool> IsPreloadedForTesting() const;
  void SetComponentDataForTesting(ComponentData component_data);

 private:
  IwaKeyDistributionInfoProvider();

  // Posts `MaybeQueueComponentUpdate()` onto `any_data_ready_` once.
  void PostMaybeQueueComponentUpdateOnceOnDataReady();

  // Queues a component update request with a fallback.
  // By the time of this call, `any_data_ready_` is already signalled.
  //  * If the request succeeds, will signal `maybe_downloaded_data_ready_` via
  //    OnKeyDistributionDataLoaded();
  //  * If not, will signal `maybe_downloaded_data_ready_` in 15 seconds after
  //    the call. Note that the fallback preloaded version is guaranteed to be
  //    loaded in this case.
  void MaybeQueueComponentUpdate();

  void OnKeyDistributionDataLoaded(
      const base::Version& version,
      bool is_preloaded,
      base::expected<KeyDistributionData, IwaComponentUpdateError>);

  void DispatchComponentUpdateSuccess(const base::Version& version,
                                      bool is_preloaded);

  void DispatchComponentUpdateError(const base::Version& version,
                                    IwaComponentUpdateError error);

  void SignalOnDataReady(bool is_preloaded);

  // Will be signalled once any component version (regardless of whether
  // preloaded or downloaded) is loaded.
  base::OneShotEvent any_data_ready_;

  // Will be signalled either if a downloaded component version is loaded or in
  // 15 seconds after the preloaded version has been loaded. See
  // OnMaybeDownloadedComponentDataReady() for details.
  base::OneShotEvent maybe_downloaded_data_ready_;

  bool maybe_queue_component_update_posted_ = false;
  bool is_on_demand_supported_ = false;

  QueueOnDemandUpdateCallback queue_on_demand_update_;

  std::optional<ComponentData> data_;
  base::ObserverList<Observer> observers_;
  bool skip_managed_checks_for_testing_ = false;
};

}  // namespace web_app

#endif  // COMPONENTS_WEBAPPS_ISOLATED_WEB_APPS_IWA_KEY_DISTRIBUTION_INFO_PROVIDER_H_