summaryrefslogtreecommitdiff
path: root/chromium/components/account_manager_core/account_manager_facade_impl.h
blob: 2e5011724833421dfa9872b874eadaac39f2b7e6 (plain)
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// Copyright 2020 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_ACCOUNT_MANAGER_CORE_ACCOUNT_MANAGER_FACADE_IMPL_H_
#define COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_MANAGER_FACADE_IMPL_H_

#include <memory>
#include <string>

#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chromeos/crosapi/mojom/account_manager.mojom.h"
#include "components/account_manager_core/account_addition_result.h"
#include "components/account_manager_core/account_manager_facade.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"

class OAuth2AccessTokenFetcher;
class OAuth2AccessTokenConsumer;

namespace account_manager {

class AccountManager;

// ChromeOS-specific implementation of |AccountManagerFacade| that talks to
// |account_manager::AccountManager| over Mojo. Used by both Lacros and Ash.
class COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE) AccountManagerFacadeImpl
    : public AccountManagerFacade,
      public crosapi::mojom::AccountManagerObserver {
 public:
  // Constructs `AccountManagerFacadeImpl`.
  // `account_manager_remote` is a Mojo `Remote` to Account Manager in Ash -
  // either in-process or out-of-process.
  // `remote_version` is the Mojo API version of the remote.
  // `init_finished` is called after `this` has been fully initialized.
  AccountManagerFacadeImpl(
      mojo::Remote<crosapi::mojom::AccountManager> account_manager_remote,
      uint32_t remote_version,
      AccountManager* account_manager_for_tests,
      base::OnceClosure init_finished = base::DoNothing());
  AccountManagerFacadeImpl(const AccountManagerFacadeImpl&) = delete;
  AccountManagerFacadeImpl& operator=(const AccountManagerFacadeImpl&) = delete;
  ~AccountManagerFacadeImpl() override;

  // AccountManagerFacade overrides:
  void AddObserver(Observer* observer) override;
  void RemoveObserver(Observer* observer) override;
  void GetAccounts(
      base::OnceCallback<void(const std::vector<Account>&)> callback) override;
  void GetPersistentErrorForAccount(
      const AccountKey& account,
      base::OnceCallback<void(const GoogleServiceAuthError&)> callback)
      override;
  void ShowAddAccountDialog(AccountAdditionSource source) override;
  void ShowAddAccountDialog(
      AccountAdditionSource source,
      base::OnceCallback<void(const account_manager::AccountAdditionResult&
                                  result)> callback) override;
  void ShowReauthAccountDialog(AccountAdditionSource source,
                               const std::string& email,
                               base::OnceClosure callback) override;
  void ShowManageAccountsSettings() override;
  std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
      const AccountKey& account,
      OAuth2AccessTokenConsumer* consumer) override;
  void ReportAuthError(const account_manager::AccountKey& account,
                       const GoogleServiceAuthError& error) override;
  void UpsertAccountForTesting(const Account& account,
                               const std::string& token_value) override;
  void RemoveAccountForTesting(const AccountKey& account) override;

  // crosapi::mojom::AccountManagerObserver overrides:
  void OnTokenUpserted(crosapi::mojom::AccountPtr account) override;
  void OnAccountRemoved(crosapi::mojom::AccountPtr account) override;
  void OnAuthErrorChanged(
      crosapi::mojom::AccountKeyPtr account,
      crosapi::mojom::GoogleServiceAuthErrorPtr error) override;
  void OnSigninDialogClosed() override;

 private:
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           ShowAddAccountDialogCallsMojo);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           GetAccountsHangsWhenRemoteIsNull);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           ShowAddAccountDialogUMA);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           ShowReauthAccountDialogCallsMojo);
  FRIEND_TEST_ALL_PREFIXES(
      AccountManagerFacadeImplTest,
      ShowAddAccountDialogSetsCorrectOptionsForAdditionFromAsh);
  FRIEND_TEST_ALL_PREFIXES(
      AccountManagerFacadeImplTest,
      ShowAddAccountDialogSetsCorrectOptionsForAdditionFromLacros);
  FRIEND_TEST_ALL_PREFIXES(
      AccountManagerFacadeImplTest,
      ShowAddAccountDialogSetsCorrectOptionsForAdditionFromArc);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           ShowReauthAccountDialogUMA);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           ShowManageAccountsSettingsCallsMojo);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           InitializationStatusIsCorrectlySet);
  FRIEND_TEST_ALL_PREFIXES(
      AccountManagerFacadeImplTest,
      AccessTokenFetcherCanBeCreatedBeforeAccountManagerFacadeInitialization);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           HistogramsForZeroAccountManagerRemoteDisconnections);
  FRIEND_TEST_ALL_PREFIXES(AccountManagerFacadeImplTest,
                           HistogramsForAccountManagerRemoteDisconnection);
  FRIEND_TEST_ALL_PREFIXES(
      AccountManagerFacadeImplTest,
      HistogramsForZeroAccountManagerObserverReceiverDisconnections);
  FRIEND_TEST_ALL_PREFIXES(
      AccountManagerFacadeImplTest,
      HistogramsForAccountManagerObserverReceiverDisconnections);

  // Status of the mojo connection.
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  enum class FacadeMojoStatus {
    kOk = 0,
    kUninitialized = 1,
    kNoRemote = 2,
    kVersionMismatch = 3,

    kMaxValue = kVersionMismatch
  };

  static std::string GetAccountAdditionResultStatusHistogramNameForTesting();
  static std::string GetAccountsMojoStatusHistogramNameForTesting();

  // A utility class to fetch access tokens over Mojo.
  class AccessTokenFetcher;

  void OnReceiverReceived(
      mojo::PendingReceiver<AccountManagerObserver> receiver);
  // Callback for `crosapi::mojom::AccountManager::ShowAddAccountDialog`.
  void OnShowAddAccountDialogFinished(
      base::OnceCallback<
          void(const account_manager::AccountAdditionResult& result)> callback,
      crosapi::mojom::AccountAdditionResultPtr mojo_result);
  void FinishAddAccount(
      base::OnceCallback<
          void(const account_manager::AccountAdditionResult& result)> callback,
      const account_manager::AccountAdditionResult& result);

  void GetAccountsInternal(
      base::OnceCallback<void(const std::vector<Account>&)> callback);

  void GetPersistentErrorInternal(
      const AccountKey& account,
      base::OnceCallback<void(const GoogleServiceAuthError&)> callback);

  // Proxy method to call `CreateAccessTokenFetcher` on
  // `account_manager_remote_`. Returns `true` if `account_manager_remote_` is
  // bound and the call was queued successfully.
  bool CreateAccessTokenFetcher(
      crosapi::mojom::AccountKeyPtr account_key,
      const std::string& oauth_consumer_name,
      crosapi::mojom::AccountManager::CreateAccessTokenFetcherCallback
          callback);

  // The initialization sequence for `AccountManagerFacadeImpl` consists of
  // adding an observer to the remote.
  //
  // Remote-querying methods like `GetAccounts` won't actually produce a remote
  // call until the initialization sequence is finished (instead, they will be
  // queued in `initialization_callbacks_`).
  //
  // `FinishInitSequenceIfNotAlreadyFinished` invokes callbacks from
  // `initialization_callbacks_` and marks the initialization as finished.
  void FinishInitSequenceIfNotAlreadyFinished();
  // `closure` will be invoked after the initialization sequence is finished.
  // See `FinishInitSequenceIfNotAlreadyFinished` for details.
  void RunAfterInitializationSequence(base::OnceClosure closure);

  // Runs `closure` if/when `account_manager_remote_` gets disconnected.
  void RunOnAccountManagerRemoteDisconnection(base::OnceClosure closure);

  // Mojo disconnect handler for `account_manager_remote_`.
  void OnAccountManagerRemoteDisconnected();

  // Mojo disconnect handler for `receiver_`.
  void OnAccountManagerObserverReceiverDisconnected();

  bool IsInitialized();

  void FlushMojoForTesting();

  // Mojo API version on the remote (Ash) side.
  const uint32_t remote_version_;

  // Number of Mojo pipe disconnections seen by `account_manager_remote_`.
  int num_remote_disconnections_ = 0;

  // Number of Mojo pipe disconnections seen by `receiver_`.
  int num_receiver_disconnections_ = 0;

  bool is_initialized_ = false;
  std::vector<base::OnceClosure> initialization_callbacks_;
  std::vector<base::OnceClosure> account_manager_remote_disconnection_handlers_;

  mojo::Remote<crosapi::mojom::AccountManager> account_manager_remote_;
  std::unique_ptr<mojo::Receiver<crosapi::mojom::AccountManagerObserver>>
      receiver_;

  base::ObserverList<Observer> observer_list_;

  raw_ptr<AccountManager> account_manager_for_tests_ = nullptr;

  base::WeakPtrFactory<AccountManagerFacadeImpl> weak_factory_{this};
};

}  // namespace account_manager

#endif  // COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_MANAGER_FACADE_IMPL_H_