Reland "Remove profile info cache entry on user removal on Chrome OS."

This is a reland of b228999b998658b6b91fa0399f08110fb69e9250 with build fix.

Original change's description:
> Remove profile info cache entry on user removal on Chrome OS.
>
> Chrome OS removes users when profiles are not loaded, and Chrome does not know
> the exact profile path until it is mounted. So we need to be able to remove
> entries from ProfileInfoCache based solely on AccountId.
>
> This Cl implements removal of cache entries given the AccountId and engages it
> on Chrome OS.
>
> TBR=alemate@chromium.org,bauerb@chromium.org,anthonyvd@chromium.org
>
> (cherry picked from commit 4084f503be1913290db968dc81f6ceb9fe796fbc)
>
> Bug: 808125
> Change-Id: I9f8e3a5f1004d119425b92a4bdc3d8011a526dd5
> Reviewed-on: https://chromium-review.googlesource.com/905751
> Reviewed-by: anthonyvd <anthonyvd@chromium.org>
> Reviewed-by: Bernhard Bauer <bauerb@chromium.org>
> Commit-Queue: Alexander Alekseev <alemate@chromium.org>
> Cr-Original-Commit-Position: refs/heads/master@{#537905}
> Reviewed-on: https://chromium-review.googlesource.com/938571
> Reviewed-by: Alexander Alekseev <alemate@chromium.org>
> Cr-Commit-Position: refs/branch-heads/3325@{#603}
> Cr-Branched-From: bc084a8b5afa3744a74927344e304c02ae54189f-refs/heads/master@{#530369}

Bug: 808125
Change-Id: I4a3bd29bd0229639cd1aa7305c21ee3a34dada95
Reviewed-on: https://chromium-review.googlesource.com/940633
Reviewed-by: Alexander Alekseev <alemate@chromium.org>
Cr-Commit-Position: refs/branch-heads/3325@{#617}
Cr-Branched-From: bc084a8b5afa3744a74927344e304c02ae54189f-refs/heads/master@{#530369}
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
index 70584b4..975d36c 100644
--- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -60,6 +60,8 @@
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/extensions/permissions_updater.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_attributes_storage.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/easy_unlock_service.h"
 #include "chrome/browser/supervised_user/chromeos/manager_password_service_factory.h"
 #include "chrome/browser/supervised_user/chromeos/supervised_user_password_service_factory.h"
@@ -475,6 +477,9 @@
     // Owner is not allowed to be removed from the device.
     return;
   }
+  g_browser_process->profile_manager()
+      ->GetProfileAttributesStorage()
+      .RemoveProfileByAccountId(account_id);
   RemoveNonOwnerUserInternal(account_id, delegate);
 }
 
diff --git a/chrome/browser/profiles/profile_attributes_storage.h b/chrome/browser/profiles/profile_attributes_storage.h
index 9c88220..425b345 100644
--- a/chrome/browser/profiles/profile_attributes_storage.h
+++ b/chrome/browser/profiles/profile_attributes_storage.h
@@ -30,6 +30,7 @@
 class Image;
 }
 
+class AccountId;
 class PrefService;
 class ProfileAttributesEntry;
 class ProfileAvatarDownloader;
@@ -54,6 +55,11 @@
                           const base::string16& user_name,
                           size_t icon_index,
                           const std::string& supervised_user_id) = 0;
+
+  // Removes the profile matching given |account_id| from this storage.
+  // Calculates profile path and calls RemoveProfile() on it.
+  virtual void RemoveProfileByAccountId(const AccountId& account_id) = 0;
+
   // Removes the profile at |profile_path| from this storage. Does not delete or
   // affect the actual profile's data.
   virtual void RemoveProfile(const base::FilePath& profile_path) = 0;
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc
index e8ff463..ea0db1d 100644
--- a/chrome/browser/profiles/profile_info_cache.cc
+++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -27,6 +27,7 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "components/signin/core/account_id/account_id.h"
 #include "components/signin/core/browser/profile_management_switches.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -740,6 +741,31 @@
       profile_path, name, gaia_id, user_name, icon_index, supervised_user_id);
 }
 
+void ProfileInfoCache::RemoveProfileByAccountId(const AccountId& account_id) {
+  // TODO(rsorokin): https://crbug.com/810167 profile.info_cache entries for
+  // AD accounts should have enough information to be deletable.
+  if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) {
+    LOG(ERROR)
+        << "Removing of AD profile.info_cache entries is NOTIMPLEMENTED.";
+  }
+
+  for (size_t i = 0; i < GetNumberOfProfiles(); i++) {
+    std::string gaia_id;
+    std::string user_name;
+    const base::DictionaryValue* info = GetInfoForProfileAtIndex(i);
+    if ((info->GetString(kGAIAIdKey, &gaia_id) && !gaia_id.empty() &&
+         account_id.GetGaiaId() == gaia_id) ||
+        (info->GetString(kUserNameKey, &user_name) &&
+         !user_name.empty() && account_id.GetUserEmail() == user_name)) {
+      RemoveProfile(GetPathOfProfileAtIndex(i));
+      return;
+    }
+  }
+  LOG(ERROR) << "Failed to remove profile.info_cache entry for account type "
+             << static_cast<int>(account_id.GetAccountType())
+             << ": matching entry not found.";
+}
+
 void ProfileInfoCache::RemoveProfile(const base::FilePath& profile_path) {
   DeleteProfileFromCache(profile_path);
 }
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h
index 023ba92..19a8246b 100644
--- a/chrome/browser/profiles/profile_info_cache.h
+++ b/chrome/browser/profiles/profile_info_cache.h
@@ -144,6 +144,7 @@
                   const base::string16& user_name,
                   size_t icon_index,
                   const std::string& supervised_user_id) override;
+  void RemoveProfileByAccountId(const AccountId& account_id) override;
   void RemoveProfile(const base::FilePath& profile_path) override;
 
   bool GetProfileAttributesWithPath(const base::FilePath& path,
diff --git a/chrome/browser/profiles/profile_info_cache_unittest.cc b/chrome/browser/profiles/profile_info_cache_unittest.cc
index 60edb57..d271f04 100644
--- a/chrome/browser/profiles/profile_info_cache_unittest.cc
+++ b/chrome/browser/profiles/profile_info_cache_unittest.cc
@@ -27,6 +27,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/signin/core/account_id/account_id.h"
 #include "components/signin/core/browser/profile_management_switches.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -767,3 +768,66 @@
       GetCache()->GetIndexOfProfileWithPath(path_4)));
 }
 #endif
+
+TEST_F(ProfileInfoCacheTest, RemoveProfileByAccountId) {
+  EXPECT_EQ(0u, GetCache()->GetNumberOfProfiles());
+
+  base::FilePath path_1 = GetProfilePath("path_1");
+  const AccountId account_id_1(
+      AccountId::FromUserEmailGaiaId("email1", "111111"));
+  base::string16 name_1 = ASCIIToUTF16("name_1");
+  GetCache()->AddProfileToCache(path_1, name_1, account_id_1.GetGaiaId(),
+                                UTF8ToUTF16(account_id_1.GetUserEmail()), 0,
+                                std::string());
+  EXPECT_EQ(1u, GetCache()->GetNumberOfProfiles());
+
+  base::FilePath path_2 = GetProfilePath("path_2");
+  base::string16 name_2 = ASCIIToUTF16("name_2");
+  const AccountId account_id_2(
+      AccountId::FromUserEmailGaiaId("email2", "222222"));
+  GetCache()->AddProfileToCache(path_2, name_2, account_id_2.GetGaiaId(),
+                                UTF8ToUTF16(account_id_2.GetUserEmail()), 0,
+                                std::string());
+  EXPECT_EQ(2u, GetCache()->GetNumberOfProfiles());
+
+  base::FilePath path_3 = GetProfilePath("path_3");
+  base::string16 name_3 = ASCIIToUTF16("name_3");
+  const AccountId account_id_3(
+      AccountId::FromUserEmailGaiaId("email3", "333333"));
+  GetCache()->AddProfileToCache(path_3, name_3, account_id_3.GetGaiaId(),
+                                UTF8ToUTF16(account_id_3.GetUserEmail()), 0,
+                                std::string());
+  EXPECT_EQ(3u, GetCache()->GetNumberOfProfiles());
+
+  base::FilePath path_4 = GetProfilePath("path_4");
+  base::string16 name_4 = ASCIIToUTF16("name_4");
+  const AccountId account_id_4(
+      AccountId::FromUserEmailGaiaId("email4", "444444"));
+  GetCache()->AddProfileToCache(path_4, name_4, account_id_4.GetGaiaId(),
+                                UTF8ToUTF16(account_id_4.GetUserEmail()), 0,
+                                std::string());
+  EXPECT_EQ(4u, GetCache()->GetNumberOfProfiles());
+
+  GetCache()->RemoveProfileByAccountId(account_id_3);
+  EXPECT_EQ(3u, GetCache()->GetNumberOfProfiles());
+  EXPECT_EQ(name_1, GetCache()->GetNameOfProfileAtIndex(0));
+
+  GetCache()->RemoveProfileByAccountId(account_id_1);
+  EXPECT_EQ(2u, GetCache()->GetNumberOfProfiles());
+  EXPECT_EQ(name_2, GetCache()->GetNameOfProfileAtIndex(0));
+
+  // this profile is already deleted.
+  GetCache()->RemoveProfileByAccountId(account_id_3);
+  EXPECT_EQ(2u, GetCache()->GetNumberOfProfiles());
+  EXPECT_EQ(name_2, GetCache()->GetNameOfProfileAtIndex(0));
+
+  // Remove profile by partial match
+  GetCache()->RemoveProfileByAccountId(
+      AccountId::FromUserEmail(account_id_2.GetUserEmail()));
+  EXPECT_EQ(1u, GetCache()->GetNumberOfProfiles());
+  EXPECT_EQ(name_4, GetCache()->GetNameOfProfileAtIndex(0));
+
+  // Remove last profile
+  GetCache()->RemoveProfileByAccountId(account_id_4);
+  EXPECT_EQ(0u, GetCache()->GetNumberOfProfiles());
+}