| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.h" |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/containers/span.h" |
| #include "components/account_manager_core/account.h" |
| #include "components/account_manager_core/account_manager_util.h" |
| #include "components/signin/public/identity_manager/account_info.h" |
| #include "components/sync/chromeos/explicit_passphrase_mojo_utils.h" |
| #include "components/sync/driver/sync_user_settings.h" |
| #include "components/sync/engine/nigori/nigori.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| bool IsPassphraseAvailable(const syncer::SyncService& sync_service) { |
| return sync_service.GetUserSettings()->IsUsingExplicitPassphrase() && |
| !sync_service.GetUserSettings()->IsPassphraseRequired(); |
| } |
| |
| } // namespace |
| |
| SyncExplicitPassphraseClientAsh::SyncExplicitPassphraseClientAsh( |
| syncer::SyncService* sync_service) |
| : sync_service_(sync_service), |
| is_passphrase_required_( |
| sync_service_->GetUserSettings()->IsPassphraseRequired()), |
| is_passphrase_available_(IsPassphraseAvailable(*sync_service_)) { |
| sync_service_->AddObserver(this); |
| } |
| |
| SyncExplicitPassphraseClientAsh::~SyncExplicitPassphraseClientAsh() { |
| sync_service_->RemoveObserver(this); |
| } |
| |
| void SyncExplicitPassphraseClientAsh::BindReceiver( |
| mojo::PendingReceiver<crosapi::mojom::SyncExplicitPassphraseClient> |
| receiver) { |
| receivers_.Add(this, std::move(receiver)); |
| } |
| |
| void SyncExplicitPassphraseClientAsh::AddObserver( |
| mojo::PendingRemote<crosapi::mojom::SyncExplicitPassphraseClientObserver> |
| observer) { |
| auto observer_id = observers_.Add(std::move(observer)); |
| // Immediately notify observer if passphrase is required or available. |
| // |is_passphrase_required_| and |is_passphrase_available_| are mutually |
| // exclusive. |
| DCHECK(!is_passphrase_required_ || !is_passphrase_available_); |
| if (is_passphrase_required_) { |
| observers_.Get(observer_id)->OnPassphraseRequired(); |
| } else if (is_passphrase_available_) { |
| observers_.Get(observer_id)->OnPassphraseAvailable(); |
| } |
| } |
| |
| void SyncExplicitPassphraseClientAsh::GetDecryptionNigoriKey( |
| crosapi::mojom::AccountKeyPtr mojo_account_key, |
| GetDecryptionNigoriKeyCallback callback) { |
| if (!ValidateAccountKey(mojo_account_key)) { |
| std::move(callback).Run(nullptr); |
| return; |
| } |
| |
| std::unique_ptr<syncer::Nigori> decryption_key = |
| sync_service_->GetUserSettings()->GetDecryptionNigoriKey(); |
| if (!decryption_key) { |
| std::move(callback).Run(nullptr); |
| return; |
| } |
| |
| std::move(callback).Run(syncer::NigoriToMojo(*decryption_key)); |
| } |
| |
| void SyncExplicitPassphraseClientAsh::SetDecryptionNigoriKey( |
| crosapi::mojom::AccountKeyPtr mojo_account_key, |
| crosapi::mojom::NigoriKeyPtr mojo_nigori_key) { |
| if (!ValidateAccountKey(mojo_account_key) || !mojo_nigori_key) { |
| return; |
| } |
| |
| std::unique_ptr<syncer::Nigori> nigori_key = |
| syncer::NigoriFromMojo(*mojo_nigori_key); |
| if (!nigori_key) { |
| // Deserialization failed, |mojo_nigori_key| doesn't represent an actual |
| // Nigori key. |
| return; |
| } |
| sync_service_->GetUserSettings()->SetDecryptionNigoriKey( |
| std::move(nigori_key)); |
| } |
| |
| void SyncExplicitPassphraseClientAsh::OnStateChanged( |
| syncer::SyncService* sync_service) { |
| bool new_is_passphrase_required = |
| sync_service->GetUserSettings()->IsPassphraseRequired(); |
| if (new_is_passphrase_required && !is_passphrase_required_) { |
| for (auto& observer : observers_) { |
| observer->OnPassphraseRequired(); |
| } |
| } |
| is_passphrase_required_ = new_is_passphrase_required; |
| |
| bool new_is_passphrase_available = IsPassphraseAvailable(*sync_service); |
| if (new_is_passphrase_available && !is_passphrase_available_) { |
| for (auto& observer : observers_) { |
| observer->OnPassphraseAvailable(); |
| } |
| } |
| is_passphrase_available_ = new_is_passphrase_available; |
| } |
| |
| void SyncExplicitPassphraseClientAsh::FlushMojoForTesting() { |
| observers_.FlushForTesting(); // IN-TEST |
| } |
| |
| bool SyncExplicitPassphraseClientAsh::ValidateAccountKey( |
| const crosapi::mojom::AccountKeyPtr& mojo_account_key) const { |
| const absl::optional<account_manager::AccountKey> account_key = |
| account_manager::FromMojoAccountKey(mojo_account_key); |
| if (!account_key.has_value()) { |
| return false; |
| } |
| |
| if (account_key->account_type() != account_manager::AccountType::kGaia) { |
| // ActiveDirectory accounts are not supported. |
| return false; |
| } |
| |
| return !account_key->id().empty() && |
| account_key->id() == sync_service_->GetAccountInfo().gaia; |
| } |
| |
| } // namespace ash |