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
|
// 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_SUPERVISED_USER_SUPERVISED_USER_EXTENSIONS_MANAGER_H_
#define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_EXTENSIONS_MANAGER_H_
#include <set>
#include <string>
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "components/prefs/pref_change_registrar.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/management_policy.h"
namespace content {
class BrowserContext;
} // namespace content
namespace extensions {
class Extension;
class ExtensionPrefs;
class ExtensionSystem;
class ExtensionRegistry;
// UMA metrics for auto-approved extensions.
inline constexpr char
kInitialLocallyApprovedExtensionCountWinLinuxMacHistogramName[] =
"SupervisedUsers.InitialLocallyApprovedExtensionsCountOnWinLinuxMac";
inline constexpr char kExtensionApprovalsCountOnExtensionToggleHistogramName[] =
"SupervisedUsers.ExtensionApprovalsCountOnExtensionToggle";
// This class groups all the functionality to handle extensions
// for supervised users.
class SupervisedUserExtensionsManager : public ExtensionRegistryObserver,
public ManagementPolicy::Provider {
public:
explicit SupervisedUserExtensionsManager(content::BrowserContext* context);
SupervisedUserExtensionsManager(const SupervisedUserExtensionsManager&) =
delete;
SupervisedUserExtensionsManager& operator=(
const SupervisedUserExtensionsManager&) = delete;
~SupervisedUserExtensionsManager() override;
// Updates registration of this class as a management policy provider
// for supervised users. It needs to be called after
// extension::ManagementPolicy has been set.
void UpdateManagementPolicyRegistration();
// Updates the set of approved extensions to add approval for `extension`.
void AddExtensionApproval(const Extension& extension);
// Checks if the extension escalated permissions during an upgrade
// and records the corresponding metrics.
void MaybeRecordPermissionsIncreaseMetrics(const extensions::Extension& extension);
// Updates the set of approved extensions to remove approval for `extension`.
void RemoveExtensionApproval(const Extension& extension);
// Returns whether the extension is allowed by the parent.
bool IsExtensionAllowed(const Extension& extension) const;
// Returns whether the supervised user can install extensions.
// If the feature that allows skipping parent approval is enabled, supervised
// user are always allowed to install extensions.
// If the feature is disabled, the permission to install is based on existing
// Family Link parental controls ("Permissions" switch).
bool CanInstallExtensions() const;
// Records the state of extension approvals.
void RecordExtensionEnablementUmaMetrics(bool enabled) const;
// extensions::ManagementPolicy::Provider implementation:
std::string GetDebugPolicyProviderName() const override;
bool UserMayLoad(const Extension* extension,
std::u16string* error) const override;
bool MustRemainDisabled(const Extension* extension,
disable_reason::DisableReason* reason) const override;
// extensions::ExtensionRegistryObserver overrides:
void OnExtensionInstalled(content::BrowserContext* browser_context,
const Extension* extension,
bool is_update) override;
void OnExtensionUninstalled(content::BrowserContext* browser_context,
const Extension* extension,
UninstallReason reason) override;
private:
// These enum values represent operations to manage the
// kSupervisedUserApprovedExtensions user pref, which stores parent approved
// extension ids.
enum class ApprovedExtensionChange {
// Adds a new approved extension to the pref.
kAdd,
// Removes extension approval.
kRemove
};
// An extension can be in one of the following states:
//
// BLOCKED: if kSupervisedUserExtensionsMayRequestPermissions is false and the
// child user is attempting to install a new extension or an existing
// extension is asking for additional permissions.
// ALLOWED: Components, Themes, Default extensions ..etc
// are generally allowed. Extensions that have been approved by the
// custodian are also allowed.
// REQUIRE_APPROVAL: if it is installed by the child user and
// hasn't been approved by the custodian yet.
enum class ExtensionState { BLOCKED, ALLOWED, REQUIRE_APPROVAL };
// Returns the state of an extension whether being BLOCKED, ALLOWED or
// REQUIRE_APPROVAL from the Supervised User service's point of view.
ExtensionState GetExtensionState(const Extension& extension) const;
// Updates the set of approved extensions when the preference is changed.
void RefreshApprovedExtensionsFromPrefs();
// Activates the extension manager for supervised users.
void SetActiveForSupervisedUsers();
// Marks the class as active manegment policy provider for supervised users
// and updates management policy registration.
void ActivateManagementPolicyAndUpdateRegistration();
// Updates the synced set of approved extension ids.
// Use AddExtensionApproval() or RemoveExtensionApproval() for public access.
// If `type` is kAdd, then add approval.
// If `type` is kRemove, then remove approval.
// Triggers a call to RefreshApprovedExtensionsFromPrefs() via a listener.
// TODO(crbug.com/40685974): We don't need the extension version information.
// It's only included for backwards compatibility with previous versions of
// Chrome. Remove the version information once a sufficient number of users
// have migrated away from M83.
void UpdateApprovedExtension(const std::string& extension_id,
const std::string& version,
ApprovedExtensionChange type);
// Returns a message saying that extensions can only be modified by the
// custodian.
std::u16string GetExtensionsLockedMessage() const;
// Enables/Disables extensions upon change in approvals. This function is
// idempotent.
void ChangeExtensionStateIfNecessary(const std::string& extension_id);
// Returns whether we should block an extension.
// If the toggle "Permissions for sites, apps and extensions" toggle
// is used to manage supervised user extensions, the result depends on the
// value of the toggle.
// If the new toggle "Extensions" is used to manage supervised user
// extensions, this method return always false.
// TODO(b/321239324): De-release when the "Extensions" toggle-management is
// launched.
bool ShouldBlockExtension(const std::string& extension_id) const;
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
// Triggers an one-time migration of the present extensions as parent-approved
// when the feature
// `kEnableSupervisedUserSkipParentApprovalToInstallExtensions` becomes
// enabled.
void MaybeMarkExtensionsLocallyParentApproved();
// Marks the extensions available to the child user as locally parent-approved
// on a preference on this device.
void DoExtensionsMigrationToParentApproved();
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
// Returns true if the given `extension_id` has been marked locally parent
// approved.
bool IsLocallyParentApprovedExtension(const std::string& extension_id) const;
// Removes from the locally approved extension preference the given
// `extension_ids`. The input `extension_ids` doesn't have to be a subset of
// the locally approved extensions: the method will remove those that are
// locally approved and ignore the rest.
void RemoveLocalParentalApproval(const std::set<std::string>& extension_ids);
// Handles the parent-approval state of the present extensions,
// whenever the parent changes the value of the FL "Extension" switch.
void OnSkipParentApprovalToInstallExtensionsChanged();
// The current state of registration of this class as a management policy.
bool is_active_policy_for_supervised_users_ = false;
const raw_ptr<content::BrowserContext> context_;
raw_ptr<ExtensionPrefs> extension_prefs_;
raw_ptr<ExtensionSystem> extension_system_;
raw_ptr<ExtensionRegistry> extension_registry_;
raw_ptr<PrefService> user_prefs_;
PrefChangeRegistrar pref_change_registrar_;
// Store a set of extension ids approved by the custodian.
// It is only relevant for SU-initiated installs.
std::set<std::string> approved_extensions_set_;
base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
registry_observation_{this};
};
} // namespace extensions
#endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_EXTENSIONS_MANAGER_H_
|