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_
|