// Copyright (c) 2013 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 <stddef.h>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_window.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/user_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/test_utils.h"

namespace {

// An observer that returns back to test code after a new profile is
// initialized.
void OnUnblockOnProfileCreation(Profile* profile,
                                Profile::CreateStatus status) {
  if (status == Profile::CREATE_STATUS_INITIALIZED)
    base::RunLoop::QuitCurrentWhenIdleDeprecated();
}

}  // namespace

class ProfileListDesktopBrowserTest : public InProcessBrowserTest {
 public:
  ProfileListDesktopBrowserTest() {}

  std::unique_ptr<AvatarMenu> CreateAvatarMenu(
      ProfileAttributesStorage* storage) {
    return std::unique_ptr<AvatarMenu>(
        new AvatarMenu(storage, NULL, browser()));
  }

 private:
  std::unique_ptr<AvatarMenu> avatar_menu_;

  DISALLOW_COPY_AND_ASSIGN(ProfileListDesktopBrowserTest);
};

#if defined(OS_WIN) || (defined(OS_MACOSX) && defined(ADDRESS_SANITIZER))
// SignOut is flaky on Windows, crbug.com/357329,
// and Mac with ASAN, crbug.com/674497.
#define MAYBE_SignOut DISABLED_SignOut
#elif defined(OS_CHROMEOS)
// This test doesn't make sense for Chrome OS since it has a different
// multi-profiles menu in the system tray instead.
#define MAYBE_SignOut DISABLED_SignOut
#elif defined(OS_LINUX)
// Flaky on Linux debug builds with libc++ (https://crbug.com/734875)
#define MAYBE_SignOut DISABLED_SignOut
#else
#define MAYBE_SignOut SignOut
#endif
IN_PROC_BROWSER_TEST_F(ProfileListDesktopBrowserTest, MAYBE_SignOut) {
  if (!profiles::IsMultipleProfilesEnabled())
    return;

  ProfileManager* profile_manager = g_browser_process->profile_manager();
  Profile* current_profile = browser()->profile();
  ProfileAttributesStorage& storage =
      profile_manager->GetProfileAttributesStorage();
  ProfileAttributesEntry* entry;
  ASSERT_TRUE(storage.GetProfileAttributesWithPath(current_profile->GetPath(),
                                                   &entry));

  std::unique_ptr<AvatarMenu> menu = CreateAvatarMenu(&storage);
  menu->RebuildMenu();

  BrowserList* browser_list = BrowserList::GetInstance();
  EXPECT_EQ(1u, browser_list->size());
  content::WindowedNotificationObserver window_close_observer(
      chrome::NOTIFICATION_BROWSER_CLOSED,
      content::Source<Browser>(browser()));

  content::WindowedNotificationObserver system_profile_created_observer(
      chrome::NOTIFICATION_PROFILE_CREATED,
      content::NotificationService::AllSources());

  EXPECT_FALSE(entry->IsSigninRequired());
  profiles::LockProfile(current_profile);
  window_close_observer.Wait();  // rely on test time-out for failure indication

  EXPECT_TRUE(entry->IsSigninRequired());
  EXPECT_EQ(0u, browser_list->size());

  // Signing out brings up the User Manager which we should close before exit.
  // But the User Manager is shown only when the system profile is created,
  // which happens asynchronously.
  system_profile_created_observer.Wait();
  UserManager::Hide();
}

#if defined(OS_CHROMEOS)
// This test doesn't make sense for Chrome OS since it has a different
// multi-profiles menu in the system tray instead.
#define MAYBE_SwitchToProfile DISABLED_SwitchToProfile
#else
#define MAYBE_SwitchToProfile SwitchToProfile
#endif
IN_PROC_BROWSER_TEST_F(ProfileListDesktopBrowserTest, MAYBE_SwitchToProfile) {
  if (!profiles::IsMultipleProfilesEnabled())
    return;

  ProfileManager* profile_manager = g_browser_process->profile_manager();
  ProfileAttributesStorage& storage =
      profile_manager->GetProfileAttributesStorage();
  base::FilePath path_profile1 = browser()->profile()->GetPath();

  // Create an additional profile.
  base::FilePath path_profile2 = profile_manager->user_data_dir().Append(
      FILE_PATH_LITERAL("New Profile 2"));
  profile_manager->CreateProfileAsync(path_profile2,
                                      base::Bind(&OnUnblockOnProfileCreation),
                                      base::string16(), std::string());

  // Spin to allow profile creation to take place, loop is terminated
  // by OnUnblockOnProfileCreation when the profile is created.
  content::RunMessageLoop();
  ASSERT_EQ(2u, storage.GetNumberOfProfiles());

  std::unique_ptr<AvatarMenu> menu = CreateAvatarMenu(&storage);
  menu->RebuildMenu();
  BrowserList* browser_list = BrowserList::GetInstance();
  EXPECT_EQ(1u, browser_list->size());
  EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());

  // Open a browser window for the first profile.
  menu->SwitchToProfile(menu->GetIndexOfItemWithProfilePath(path_profile1),
                        false, ProfileMetrics::SWITCH_PROFILE_ICON);
  EXPECT_EQ(1u, browser_list->size());
  EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());

  // Open a browser window for the second profile.
  menu->SwitchToProfile(menu->GetIndexOfItemWithProfilePath(path_profile2),
                        false, ProfileMetrics::SWITCH_PROFILE_ICON);
  EXPECT_EQ(2u, browser_list->size());

  // Switch to the first profile without opening a new window.
  menu->SwitchToProfile(menu->GetIndexOfItemWithProfilePath(path_profile1),
                        false, ProfileMetrics::SWITCH_PROFILE_ICON);
  EXPECT_EQ(2u, browser_list->size());
  EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());
  EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath());
}
