chromium/chrome/browser/profiles/android/profile_resolver_unittest.cc

// Copyright 2021 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/profiles/android/profile_resolver.h"

#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/test/bind.h"
#include "chrome/browser/android/proto/profile_token.pb.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace profile_resolver {

class ProfileResolverTest : public testing::Test {
 public:
  ProfileResolverTest() : manager_(TestingBrowserProcess::GetGlobal()) {}

  TestingProfileManager* manager() { return &manager_; }

  void SetUp() override {
    // Otherwise we see a /data/data vs /data/user/ mismatch.
    base::FilePath user_data_dir;
    base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
    ASSERT_TRUE(manager_.SetUp(user_data_dir));
  }

  Profile* ResolveProfileSync(std::string token) {
    Profile* profile;
    base::RunLoop run_loop;
    ResolveProfile(token, base::BindLambdaForTesting([&](Profile* p) {
                     profile = p;
                     run_loop.Quit();
                   }));
    run_loop.Run();
    return profile;
  }

  ProfileKey* ResolveProfileKeySync(std::string token) {
    ProfileKey* profile_key;
    base::RunLoop run_loop;
    ResolveProfileKey(token, base::BindLambdaForTesting([&](ProfileKey* pk) {
                        profile_key = pk;
                        run_loop.Quit();
                      }));
    run_loop.Run();
    return profile_key;
  }

 private:
  content::BrowserTaskEnvironment task_environment_;
  TestingProfileManager manager_;
};

TEST_F(ProfileResolverTest, TestTokenizeResolve) {
  TestingProfile* profile = manager()->CreateTestingProfile("foo");
  std::string token = TokenizeProfile(profile);
  Profile* resolved_profile = ResolveProfileSync(token);
  ASSERT_EQ(profile, resolved_profile);

  std::string another_token = TokenizeProfile(profile);
  ASSERT_EQ(token, another_token);
}

TEST_F(ProfileResolverTest, TestResolveDifferentProfiles) {
  TestingProfile* profile1 = manager()->CreateTestingProfile("foo");
  TestingProfile* profile2 = manager()->CreateTestingProfile("bar");

  std::string token1 = TokenizeProfile(profile1);
  std::string token2 = TokenizeProfile(profile2);
  ASSERT_NE(token1, token2);

  Profile* resolved_profile1 = ResolveProfileSync(token1);
  Profile* resolved_profile2 = ResolveProfileSync(token2);
  ASSERT_EQ(profile1, resolved_profile1);
  ASSERT_EQ(profile2, resolved_profile2);
  ASSERT_NE(resolved_profile1, resolved_profile2);
}

TEST_F(ProfileResolverTest, TestResolveOtrProfiles) {
  TestingProfile* profile = manager()->CreateTestingProfile("foo");
  Profile* primaryOtrProfile =
      profile->GetPrimaryOTRProfile(/*create_if_needed=*/true);
  Profile* anotherOtrProfile = profile->GetOffTheRecordProfile(
      Profile::OTRProfileID::CreateUnique("Test:Foo"),
      /*create_if_needed=*/true);

  std::string token = TokenizeProfile(profile);
  std::string primaryOtrToken = TokenizeProfile(primaryOtrProfile);
  std::string anotherOtrToken = TokenizeProfile(anotherOtrProfile);
  ASSERT_NE(token, primaryOtrToken);
  ASSERT_NE(token, anotherOtrToken);
  ASSERT_NE(primaryOtrToken, anotherOtrToken);

  Profile* resolved_primary_otr_profile = ResolveProfileSync(primaryOtrToken);
  Profile* another_primary_otr_profile = ResolveProfileSync(anotherOtrToken);
  ASSERT_EQ(primaryOtrProfile, resolved_primary_otr_profile);
  ASSERT_EQ(anotherOtrProfile, another_primary_otr_profile);
}

TEST_F(ProfileResolverTest, TestResolveProfileKeys) {
  ProfileKey* profile_key1 =
      manager()->CreateTestingProfile("foo")->GetProfileKey();
  ProfileKey* profile_key2 =
      manager()->CreateTestingProfile("bar")->GetProfileKey();

  std::string token1 = TokenizeProfileKey(profile_key1);
  std::string token2 = TokenizeProfileKey(profile_key2);
  ASSERT_NE(token1, token2);

  ProfileKey* resolved_profile_key1 = ResolveProfileKeySync(token1);
  ProfileKey* resolved_profile_key2 = ResolveProfileKeySync(token2);
  ASSERT_EQ(profile_key1, resolved_profile_key1);
  ASSERT_EQ(profile_key2, resolved_profile_key2);
  ASSERT_NE(resolved_profile_key1, resolved_profile_key2);
}

TEST_F(ProfileResolverTest, TestResolveBadToken) {
  ProfileToken token_proto;
  token_proto.set_relative_path("foo");
  std::string token_string;
  token_proto.SerializeToString(&token_string);

  ASSERT_EQ(nullptr, ResolveProfileSync(token_string));
  ASSERT_EQ(nullptr, ResolveProfileKeySync(token_string));
}

TEST_F(ProfileResolverTest, TestResolveBadOtrToken) {
  ProfileToken otr_token_proto;
  otr_token_proto.set_relative_path("bar");
  otr_token_proto.set_otr_profile_id(
      Profile::OTRProfileID::CreateUnique("Test:Bar").Serialize());
  std::string otr_token_string;
  otr_token_proto.SerializeToString(&otr_token_string);

  ASSERT_EQ(nullptr, ResolveProfileSync(otr_token_string));
  ASSERT_EQ(nullptr, ResolveProfileKeySync(otr_token_string));
}

TEST_F(ProfileResolverTest, TestResolveUnloadedProfile) {
  TestingProfile* profile = manager()->CreateTestingProfile("foo");
  ProfileKey* profile_key = profile->GetProfileKey();
  Profile* primary_otr_profile =
      profile->GetPrimaryOTRProfile(/*create_if_needed=*/true);

  std::string profile_token = TokenizeProfile(profile);
  std::string profile_key_token = TokenizeProfileKey(profile_key);
  std::string primary_otr_profile_token = TokenizeProfile(primary_otr_profile);

  // TODO(alexilin): Call some sort of UnloadProfile() mechanism on
  // TestingProfileManager to remove these profiles from memory but leave the
  // metadata.

  // Our old raw pointers are all now invalid and should not be used again.
  profile = nullptr;
  profile_key = nullptr;
  primary_otr_profile = nullptr;

  Profile* resolved_profile = ResolveProfileSync(profile_token);
  ProfileKey* resolved_profile_key = ResolveProfileKeySync(profile_key_token);
  Profile* resolved_primary_otr_profile =
      ResolveProfileSync(primary_otr_profile_token);
  ASSERT_NE(nullptr, resolved_profile);
  ASSERT_NE(nullptr, resolved_profile_key);
  ASSERT_NE(nullptr, resolved_primary_otr_profile);
}

}  // namespace profile_resolver