File: account_extension_tracker.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 (174 lines) | stat: -rw-r--r-- 7,275 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
// 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 CHROME_BROWSER_EXTENSIONS_ACCOUNT_EXTENSION_TRACKER_H_
#define CHROME_BROWSER_EXTENSIONS_ACCOUNT_EXTENSION_TRACKER_H_

#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_id.h"

class BrowserContextKeyedServiceFactory;
class Profile;

namespace content {
class BrowserContext;
}

namespace extensions {

// This service manages each extension's AccountExtensionType, which describes
// whether the extension is associated with a signed in user's account data.
class AccountExtensionTracker : public KeyedService,
                                public signin::IdentityManager::Observer {
 public:
  // Maximum delay between initiating a sign in from the extension installed
  // bubble and completing the sign in for the associated extension to still be
  // promoted to an account extension. Beyond this delay, it is assumed that the
  // user did not intend to sign in after installing the extension.
  static constexpr base::TimeDelta kMaxSigninFromExtensionBubbleDelay =
      base::Minutes(50);

  enum AccountExtensionType {
    // The extension is only associated with the current device. This is used
    // for:
    // - all unsyncable extensions
    // - all extensions if there is no signed in user with sync enabled
    // - all extensions installed before the user signed in, that are not part
    //   the user's account's data.
    kLocal = 0,
    // The extension is part of the signed in user's account data but was
    // installed on this device before the user has signed in.
    kAccountInstalledLocally = 1,
    // The extension is part of the signed in user's account data and was
    // installed on this device after the user has signed in.
    kAccountInstalledSignedIn = 2,
    kLast = 2,
  };

  class Observer : public base::CheckedObserver {
   public:
    // Called when an extension's eligibility to be uploaded to the user's
    // account may have changed.
    virtual void OnExtensionUploadabilityChanged(const ExtensionId& id) = 0;

    // Called when whether extensions can be uploaded to the user's account may
    // be changed. Usually emitted when the initial sync download completes or
    // when the user is no longer syncing extensions in transport mode.
    virtual void OnExtensionsUploadabilityChanged() = 0;
  };

  explicit AccountExtensionTracker(Profile* profile);

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

  ~AccountExtensionTracker() override;

  // Convenience method to get the AccountExtensionTracker for a profile.
  // Creates the tracker for the profile if none exists.
  static AccountExtensionTracker* Get(content::BrowserContext* context);

  // Returns the singleton instance of the factory for this KeyedService.
  static BrowserContextKeyedServiceFactory* GetFactory();

  // Computes and sets the AccountExtensionType for `extension` when it is
  // installed. Needs to be called by the sync service before it handles the
  // install.
  void SetAccountExtensionTypeOnExtensionInstalled(const Extension& extension);

  // IdentityManagerObserver implementation.
  void OnPrimaryAccountChanged(
      const signin::PrimaryAccountChangeEvent& event_details) override;

  // Called when sync data is received for the given `extension_id`.
  void OnExtensionSyncDataReceived(const ExtensionId& extension_id);

  // Called just after the initial set of extension sync data is received.
  // i.e. during browser startup (if extensions sync is already enabled), or
  // once the initial download completes after extensions sync gets enabled.
  void OnInitialExtensionsSyncDataReceived();

  AccountExtensionType GetAccountExtensionType(
      const ExtensionId& extension_id) const;

  // Returns all account extensions with type `kAccountInstalledSignedIn`.
  std::vector<const Extension*> GetSignedInAccountExtensions() const;

  // Called when the user initiates a signin from a promo that appears after an
  // extension with the given `extension_id` is installed.
  void OnSignInInitiatedFromExtensionPromo(const ExtensionId& extension_id);

  // Whether the given `extension` can be uploaded to/associated with the
  // current signed in user.
  bool CanUploadAsAccountExtension(const Extension& extension) const;

  // Called when the user initiates an upload for the given `extension_id` to
  // their account.
  void OnAccountUploadInitiatedForExtension(const ExtensionId& extension_id);

  void set_uninstall_account_extensions_on_signout(
      bool uninstall_account_extensions_on_signout) {
    uninstall_account_extensions_on_signout_ =
        uninstall_account_extensions_on_signout;
  }

  void SetAccountExtensionTypeForTesting(const ExtensionId& extension_id,
                                         AccountExtensionType type);

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

 private:
  // Sets the extension's AccountExtensionType. Called when the extension is
  // installed (not updated) or when there is incoming sync data for the
  // extension, which implies that it's associated with a user's account data.
  void SetAccountExtensionType(const ExtensionId& extension_id,
                               AccountExtensionType type);

  // Removes `extension_id` in `extensions_installed_with_signin_promo_`.
  void RemoveExpiredExtension(const ExtensionId& extension_id);

  // Promotes `extension_id` from a local to an account extension specified by
  // `type`. Unlike just calling `SetAccountExtensionType`, this always alerts
  // observers that the extension's uploadability may have changed.
  void PromoteLocalToAccountExtension(const ExtensionId& extension_id,
                                      AccountExtensionType type);

  // Notifies observers that the eligibility of multiple extensions to be
  // uploaded to the user's account may have changed.
  void NotifyOnExtensionsUploadabilityChanged();

  const raw_ptr<Profile> profile_;

  // Keeps track of extensions for which a signin promo was shown after
  // installation.
  std::vector<ExtensionId> extensions_installed_with_signin_promo_;

  // Whether account extensions with type `kAccountInstalledSignedIn` should be
  // uninstalled when the primary user signs out.
  bool uninstall_account_extensions_on_signout_ = false;

  base::ObserverList<Observer> observers_;

  // IdentityManager observer.
  base::ScopedObservation<signin::IdentityManager,
                          signin::IdentityManager::Observer>
      identity_manager_observation_{this};

  // Must be the last member variable. See WeakPtrFactory documentation for
  // details.
  base::WeakPtrFactory<AccountExtensionTracker> weak_factory_{this};
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_ACCOUNT_EXTENSION_TRACKER_H_