File: app_shim_registry.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (203 lines) | stat: -rw-r--r-- 8,426 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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// Copyright 2019 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_OS_INTEGRATION_MAC_APP_SHIM_REGISTRY_H_
#define CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_MAC_APP_SHIM_REGISTRY_H_

#include <map>
#include <set>
#include <string>

#include "base/callback_list.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/values.h"
#include "chrome/services/mac_notifications/public/mojom/mac_notifications.mojom.h"

class PrefService;
class PrefRegistrySimple;

// This class is used to store information about which app shims have been
// installed for which profiles in local storage. This is used to:
//  - Open the last active profile when an app shim is launched.
//  - Populate the profile switcher menu in the app with only those profile
//    for which the app is installed.
//  - Only delete the app shim when it has been uninstalled for all profiles.
// All base::FilePath arguments to functions are expected to be full profile
// paths (e.g, the result of calling Profile::GetPath).
//
// This class should arguably be a extensions::ExtensionRegistryObserver. It
// is not (and instead is called by WebAppShortcutManager, which is one),
// because apps are in the process of being disentangled from extensions.
class AppShimRegistry {
 public:
  AppShimRegistry(const AppShimRegistry& other) = delete;
  AppShimRegistry& operator=(const AppShimRegistry& other) = delete;

  static AppShimRegistry* Get();
  void RegisterLocalPrefs(PrefRegistrySimple* registry);

  // Query the profiles paths for which the specified app is installed.
  std::set<base::FilePath> GetInstalledProfilesForApp(
      const std::string& app_id) const;

  // Returns true if `profile` is among the profile paths in which the specified
  // app is installed.
  bool IsAppInstalledInProfile(const std::string& app_id,
                               const base::FilePath& profile) const;

  // Query the profiles paths that were last open in the app (which are the
  // profiles to open when the app starts).
  std::set<base::FilePath> GetLastActiveProfilesForApp(
      const std::string& app_id) const;

  // Called when an app is installed for a profile (or any other action that
  // would create an app shim, e.g: launching the shim).
  void OnAppInstalledForProfile(const std::string& app_id,
                                const base::FilePath& profile);

  // Called when an app is uninstalled for a profile. Returns true if no
  // profiles have this app installed anymore.
  bool OnAppUninstalledForProfile(const std::string& app_id,
                                  const base::FilePath& profile);

  // Called to save a list of the profiles that were last in use for an app.
  // This is called for example when an app quits, providing the profiles that
  // were in use at that time.
  void SaveLastActiveProfilesForApp(const std::string& app_id,
                                    std::set<base::FilePath> active_profiles);

  // Return all apps installed for the specified profile. Used to delete apps
  // when a profile is removed.
  std::set<std::string> GetInstalledAppsForProfile(
      const base::FilePath& profile) const;

  // Returns all apps installed in multiple profiles. Used for metrics.
  std::set<std::string> GetAppsInstalledInMultipleProfiles() const;

  // Called when the file and/or protocol handlers for an app are updated in a
  // specific profile. Used to calculate the union of all handlers for a app
  // when updating the app shim.
  void SaveFileHandlersForAppAndProfile(
      const std::string& app_id,
      const base::FilePath& profile,
      std::set<std::string> file_handler_extensions,
      std::set<std::string> file_handler_mime_types);
  void SaveProtocolHandlersForAppAndProfile(
      const std::string& app_id,
      const base::FilePath& profile,
      std::set<std::string> protocol_handlers);

  struct HandlerInfo {
    HandlerInfo();
    ~HandlerInfo();
    HandlerInfo(HandlerInfo&&);
    HandlerInfo(const HandlerInfo&);
    HandlerInfo& operator=(HandlerInfo&&);
    HandlerInfo& operator=(const HandlerInfo&);

    bool IsEmpty() const {
      return file_handler_extensions.empty() &&
             file_handler_mime_types.empty() && protocol_handlers.empty();
    }

    std::set<std::string> file_handler_extensions;
    std::set<std::string> file_handler_mime_types;
    std::set<std::string> protocol_handlers;
  };

  // Returns all the file and protocol handlers for the given app, keyed by
  // profile path.
  std::map<base::FilePath, HandlerInfo> GetHandlersForApp(
      const std::string& app_id);

  // Return whether a code directory hash has ever been associated with any app.
  bool HasSavedAnyCdHashes() const;

  // Associate the given code directory hash with a given app.
  void SaveCdHashForApp(const std::string& app_id,
                        base::span<const uint8_t> cd_hash);

  // Verify that the given code directory hash matches the one previously
  // associated with the given app.
  bool VerifyCdHashForApp(const std::string& app_id,
                          base::span<const uint8_t> cd_hash);

  // Called when changes to the system level notification permission status for
  // the given app have been detected.
  void SaveNotificationPermissionStatusForApp(
      const std::string& app_id,
      mac_notifications::mojom::PermissionStatus status);

  // Gets the last known system level notification permission status for the
  // given app. Returns kNotDetermined if no value has been stored.
  mac_notifications::mojom::PermissionStatus
  GetNotificationPermissionStatusForApp(const std::string& app_id);

  // Register a callback to be called any time data associated with an app
  // changes. The callback is passed the app_id of the changed app.
  base::CallbackListSubscription RegisterAppChangedCallback(
      base::RepeatingCallback<void(const std::string&)> callback);

  // Helper functions for testing.
  void SetPrefServiceAndUserDataDirForTesting(
      PrefService* pref_service,
      const base::FilePath& user_data_dir);

  // For logging and debug purposes.
  base::Value::Dict AsDebugDict() const;

 protected:
  friend class base::NoDestructor<AppShimRegistry>;

  AppShimRegistry();
  ~AppShimRegistry();

  PrefService* GetPrefService() const;
  base::FilePath GetFullProfilePath(const std::string& profile_path) const;

  // Helper function used by GetInstalledProfilesForApp and
  // GetLastActiveProfilesForApp.
  void GetProfilesSetForApp(const std::string& app_id,
                            const std::string& profiles_key,
                            std::set<base::FilePath>* profiles) const;

  using HmacKey = std::vector<uint8_t>;
  static constexpr size_t kHmacKeySize = 32;

  // Retrieve the key used to create HMACs of app's code directory hashes,
  // generating a new key if needed.
  HmacKey GetCdHashHmacKey();

  // Helper function used by GetCdHashHmacKey
  // Retrieve the existing key used to create HMACs of app's code directory
  // hashes. Returns nullopt if no key was found or the existing key could not
  // be decoded or decrypted.
  std::optional<HmacKey> GetExistingCdHashHmacKey();

  // Helper function used by GetCdHashHmacKey
  // Encode and encrypt the given HMAC key and save it to preferences.
  void SaveCdHashHmacKey(const HmacKey& key);

  // Update the local storage for |app_id|. Update |installed_profiles| and
  // |last_active_profiles| only if they are non-nullptr. If
  // |installed_profiles| is non-nullptr and empty, remove the entry for
  // |app_id|.
  void SetAppInfo(const std::string& app_id,
                  const std::set<base::FilePath>* installed_profiles,
                  const std::set<base::FilePath>* last_active_profiles,
                  const std::map<base::FilePath, HandlerInfo>* handlers,
                  const std::string* cd_hash_hmac_base64,
                  const mac_notifications::mojom::PermissionStatus*
                      notification_permission_status);

  raw_ptr<PrefService> override_pref_service_ = nullptr;
  base::FilePath override_user_data_dir_;

  base::RepeatingCallbackList<void(const std::string& app_id)>
      app_changed_callbacks_;
};

#endif  // CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_MAC_APP_SHIM_REGISTRY_H_