summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc')
-rw-r--r--chromium/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc285
1 files changed, 285 insertions, 0 deletions
diff --git a/chromium/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc b/chromium/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc
new file mode 100644
index 00000000000..b0d813a17ec
--- /dev/null
+++ b/chromium/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc
@@ -0,0 +1,285 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/signin/dice_signed_in_profile_creator.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/raw_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/profiles/profile_attributes_entry.h"
+#include "chrome/browser/profiles/profile_attributes_storage.h"
+#include "chrome/browser/profiles/profile_avatar_icon_util.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_manager_observer.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
+#include "chrome/test/base/fake_profile_manager.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char16_t kProfileTestName[] = u"profile_test_name";
+
+std::unique_ptr<TestingProfile> BuildTestingProfile(const base::FilePath& path,
+ Profile::Delegate* delegate,
+ bool tokens_loaded) {
+ TestingProfile::Builder profile_builder;
+ profile_builder.SetDelegate(delegate);
+ profile_builder.SetPath(path);
+ std::unique_ptr<TestingProfile> profile =
+ IdentityTestEnvironmentProfileAdaptor::
+ CreateProfileForIdentityTestEnvironment(profile_builder);
+ if (!tokens_loaded) {
+ IdentityTestEnvironmentProfileAdaptor adaptor(profile.get());
+ adaptor.identity_test_env()->ResetToAccountsNotYetLoadedFromDiskState();
+ }
+ if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
+ profile->SetGuestSession(true);
+ return profile;
+}
+
+class UnittestProfileManager : public FakeProfileManager {
+ public:
+ explicit UnittestProfileManager(const base::FilePath& user_data_dir)
+ : FakeProfileManager(user_data_dir) {}
+
+ void set_tokens_loaded_at_creation(bool loaded) {
+ tokens_loaded_at_creation_ = loaded;
+ }
+
+ std::unique_ptr<TestingProfile> BuildTestingProfile(
+ const base::FilePath& path,
+ Profile::Delegate* delegate) override {
+ return ::BuildTestingProfile(path, delegate, tokens_loaded_at_creation_);
+ }
+
+ bool tokens_loaded_at_creation_ = true;
+};
+
+} // namespace
+
+class DiceSignedInProfileCreatorTest : public testing::Test,
+ public ProfileManagerObserver {
+ public:
+ DiceSignedInProfileCreatorTest()
+ : local_state_(TestingBrowserProcess::GetGlobal()) {
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+ auto profile_manager_unique =
+ std::make_unique<UnittestProfileManager>(temp_dir_.GetPath());
+ profile_manager_ = profile_manager_unique.get();
+ TestingBrowserProcess::GetGlobal()->SetProfileManager(
+ std::move(profile_manager_unique));
+ profile_ = BuildTestingProfile(base::FilePath(), /*delegate=*/nullptr,
+ /*tokens_loaded=*/true);
+ identity_test_env_profile_adaptor_ =
+ std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile());
+ profile_manager()->AddObserver(this);
+ }
+
+ ~DiceSignedInProfileCreatorTest() override { DeleteProfiles(); }
+
+ UnittestProfileManager* profile_manager() { return profile_manager_; }
+
+ // Test environment attached to profile().
+ signin::IdentityTestEnvironment* identity_test_env() {
+ return identity_test_env_profile_adaptor_->identity_test_env();
+ }
+
+ // Source profile (the one which we are extracting credentials from).
+ Profile* profile() { return profile_.get(); }
+
+ // Profile created by the DiceSignedInProfileCreator.
+ Profile* signed_in_profile() { return signed_in_profile_; }
+
+ // Profile added to the ProfileManager. In general this should be the same as
+ // signed_in_profile() except in error cases.
+ Profile* added_profile() { return added_profile_; }
+
+ bool creator_callback_called() { return creator_callback_called_; }
+
+ void set_profile_added_closure(base::OnceClosure closure) {
+ profile_added_closure_ = std::move(closure);
+ }
+
+ bool use_guest_profile() const { return use_guest_profile_; }
+
+ void DeleteProfiles() {
+ identity_test_env_profile_adaptor_.reset();
+ if (profile_manager_) {
+ profile_manager()->RemoveObserver(this);
+ TestingBrowserProcess::GetGlobal()->SetProfileManager(nullptr);
+ profile_manager_ = nullptr;
+ }
+ }
+
+ // Callback for the DiceSignedInProfileCreator.
+ void OnProfileCreated(base::OnceClosure quit_closure, Profile* profile) {
+ creator_callback_called_ = true;
+ signed_in_profile_ = profile;
+ if (quit_closure)
+ std::move(quit_closure).Run();
+ }
+
+ // ProfileManagerObserver:
+ void OnProfileAdded(Profile* profile) override {
+ added_profile_ = profile;
+ if (profile_added_closure_)
+ std::move(profile_added_closure_).Run();
+ }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ base::ScopedTempDir temp_dir_;
+ ScopedTestingLocalState local_state_;
+ raw_ptr<UnittestProfileManager> profile_manager_ = nullptr;
+ std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
+ identity_test_env_profile_adaptor_;
+ std::unique_ptr<TestingProfile> profile_;
+ raw_ptr<Profile> signed_in_profile_ = nullptr;
+ raw_ptr<Profile> added_profile_ = nullptr;
+ base::OnceClosure profile_added_closure_;
+ bool creator_callback_called_ = false;
+ base::test::ScopedFeatureList scoped_feature_list_;
+ bool use_guest_profile_ = false;
+};
+
+TEST_F(DiceSignedInProfileCreatorTest, CreateWithTokensLoaded) {
+ AccountInfo account_info =
+ identity_test_env()->MakeAccountAvailable("bob@example.com");
+ size_t kTestIcon = profiles::GetModernAvatarIconStartIndex();
+
+ base::RunLoop loop;
+ std::unique_ptr<DiceSignedInProfileCreator> creator =
+ std::make_unique<DiceSignedInProfileCreator>(
+ profile(), account_info.account_id, kProfileTestName, kTestIcon,
+ use_guest_profile(),
+ base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated,
+ base::Unretained(this), loop.QuitClosure()));
+ loop.Run();
+
+ // Check that the account was moved.
+ EXPECT_TRUE(creator_callback_called());
+ EXPECT_TRUE(signed_in_profile());
+ EXPECT_NE(profile(), signed_in_profile());
+ EXPECT_EQ(signed_in_profile(), added_profile());
+ EXPECT_FALSE(IdentityManagerFactory::GetForProfile(profile())
+ ->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_EQ(1u, IdentityManagerFactory::GetForProfile(signed_in_profile())
+ ->GetAccountsWithRefreshTokens()
+ .size());
+ EXPECT_TRUE(IdentityManagerFactory::GetForProfile(signed_in_profile())
+ ->HasAccountWithRefreshToken(account_info.account_id));
+
+ // Check profile type
+ ASSERT_EQ(use_guest_profile(), signed_in_profile()->IsGuestSession());
+
+ // Check the profile name and icon.
+ ProfileAttributesStorage& storage =
+ profile_manager()->GetProfileAttributesStorage();
+ ProfileAttributesEntry* entry =
+ storage.GetProfileAttributesWithPath(signed_in_profile()->GetPath());
+ ASSERT_TRUE(entry);
+ if (!use_guest_profile()) {
+ EXPECT_EQ(kProfileTestName, entry->GetLocalProfileName());
+ EXPECT_EQ(kTestIcon, entry->GetAvatarIconIndex());
+ }
+}
+
+TEST_F(DiceSignedInProfileCreatorTest, CreateWithTokensNotLoaded) {
+ AccountInfo account_info =
+ identity_test_env()->MakeAccountAvailable("bob@example.com");
+ profile_manager()->set_tokens_loaded_at_creation(false);
+
+ base::RunLoop creator_loop;
+ base::RunLoop profile_added_loop;
+ set_profile_added_closure(profile_added_loop.QuitClosure());
+ std::unique_ptr<DiceSignedInProfileCreator> creator =
+ std::make_unique<DiceSignedInProfileCreator>(
+ profile(), account_info.account_id, std::u16string(), absl::nullopt,
+ use_guest_profile(),
+ base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated,
+ base::Unretained(this), creator_loop.QuitClosure()));
+ profile_added_loop.Run();
+ base::RunLoop().RunUntilIdle();
+
+ // The profile was created, but tokens not loaded. The callback has not been
+ // called yet.
+ EXPECT_FALSE(creator_callback_called());
+ EXPECT_TRUE(added_profile());
+ EXPECT_NE(profile(), added_profile());
+
+ // Load the tokens.
+ IdentityTestEnvironmentProfileAdaptor adaptor(added_profile());
+ adaptor.identity_test_env()->ReloadAccountsFromDisk();
+ creator_loop.Run();
+
+ // Check that the account was moved.
+ EXPECT_EQ(signed_in_profile(), added_profile());
+ EXPECT_TRUE(creator_callback_called());
+ EXPECT_FALSE(IdentityManagerFactory::GetForProfile(profile())
+ ->HasAccountWithRefreshToken(account_info.account_id));
+ EXPECT_EQ(1u, IdentityManagerFactory::GetForProfile(signed_in_profile())
+ ->GetAccountsWithRefreshTokens()
+ .size());
+ EXPECT_TRUE(IdentityManagerFactory::GetForProfile(signed_in_profile())
+ ->HasAccountWithRefreshToken(account_info.account_id));
+}
+
+// Deleting the creator while it is running does not crash.
+TEST_F(DiceSignedInProfileCreatorTest, DeleteWhileCreating) {
+ AccountInfo account_info =
+ identity_test_env()->MakeAccountAvailable("bob@example.com");
+ std::unique_ptr<DiceSignedInProfileCreator> creator =
+ std::make_unique<DiceSignedInProfileCreator>(
+ profile(), account_info.account_id, std::u16string(), absl::nullopt,
+ use_guest_profile(),
+ base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated,
+ base::Unretained(this), base::OnceClosure()));
+ EXPECT_FALSE(creator_callback_called());
+ creator.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
+// Deleting the profile while waiting for the tokens.
+TEST_F(DiceSignedInProfileCreatorTest, DeleteProfile) {
+ AccountInfo account_info =
+ identity_test_env()->MakeAccountAvailable("bob@example.com");
+ profile_manager()->set_tokens_loaded_at_creation(false);
+
+ base::RunLoop creator_loop;
+ base::RunLoop profile_added_loop;
+ set_profile_added_closure(profile_added_loop.QuitClosure());
+ std::unique_ptr<DiceSignedInProfileCreator> creator =
+ std::make_unique<DiceSignedInProfileCreator>(
+ profile(), account_info.account_id, std::u16string(), absl::nullopt,
+ use_guest_profile(),
+ base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated,
+ base::Unretained(this), creator_loop.QuitClosure()));
+ profile_added_loop.Run();
+ base::RunLoop().RunUntilIdle();
+
+ // The profile was created, but tokens not loaded. The callback has not been
+ // called yet.
+ EXPECT_FALSE(creator_callback_called());
+ EXPECT_TRUE(added_profile());
+ EXPECT_NE(profile(), added_profile());
+
+ DeleteProfiles();
+ creator_loop.Run();
+
+ // The callback is called with nullptr profile.
+ EXPECT_TRUE(creator_callback_called());
+ EXPECT_FALSE(signed_in_profile());
+}