// 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 "chrome/browser/profile_resetter/profile_resetter.h"

#include <stddef.h>

#include <map>
#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_path_override.h"
#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profile_resetter/brandcode_config_fetcher.h"
#include "chrome/browser/profile_resetter/profile_reset_report.pb.h"
#include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
#include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/web_data_service_factory.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/browser/website_settings_info.h"
#include "components/prefs/pref_service.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_browser_thread.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "url/gurl.h"

#if defined(OS_WIN)
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/process/process_handle.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/shortcut.h"
#endif


namespace {

const char kDistributionConfig[] = "{"
    " \"homepage\" : \"http://www.foo.com\","
    " \"homepage_is_newtabpage\" : false,"
    " \"browser\" : {"
    "   \"show_home_button\" : true"
    "  },"
    " \"session\" : {"
    "   \"restore_on_startup\" : 4,"
    "   \"startup_urls\" : [\"http://goo.gl\", \"http://foo.de\"]"
    "  },"
    " \"search_provider_overrides\" : ["
    "    {"
    "      \"name\" : \"first\","
    "      \"keyword\" : \"firstkey\","
    "      \"search_url\" : \"http://www.foo.com/s?q={searchTerms}\","
    "      \"favicon_url\" : \"http://www.foo.com/favicon.ico\","
    "      \"suggest_url\" : \"http://www.foo.com/s?q={searchTerms}\","
    "      \"encoding\" : \"UTF-8\","
    "      \"id\" : 1001"
    "    }"
    "  ],"
    " \"extensions\" : {"
    "   \"settings\" : {"
    "     \"placeholder_for_id\": {"
    "      }"
    "    }"
    "  }"
    "}";

const char kXmlConfig[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
    "<response protocol=\"3.0\" server=\"prod\">"
      "<app appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\" status=\"ok\">"
        "<data index=\"skipfirstrunui-importsearch-defaultbrowser\" "
          "name=\"install\" status=\"ok\">"
          "placeholder_for_data"
        "</data>"
      "</app>"
    "</response>";

using extensions::Extension;
using extensions::Manifest;


// ProfileResetterTest --------------------------------------------------------

// ProfileResetterTest sets up the extension, WebData and TemplateURL services.
class ProfileResetterTest : public extensions::ExtensionServiceTestBase,
                            public ProfileResetterTestBase {
 public:
  ProfileResetterTest();
  ~ProfileResetterTest() override;

 protected:
  void SetUp() override;

  TestingProfile* profile() { return profile_.get(); }

 private:
#if defined(OS_WIN)
  base::ScopedPathOverride user_desktop_override_;
  base::ScopedPathOverride app_dir_override_;
  base::ScopedPathOverride start_menu_override_;
  base::ScopedPathOverride taskbar_pins_override_;
  base::win::ScopedCOMInitializer com_init_;
#endif
};

ProfileResetterTest::ProfileResetterTest()
#if defined(OS_WIN)
    : user_desktop_override_(base::DIR_USER_DESKTOP),
      app_dir_override_(base::DIR_APP_DATA),
      start_menu_override_(base::DIR_START_MENU),
      taskbar_pins_override_(base::DIR_TASKBAR_PINS)
#endif
{}

ProfileResetterTest::~ProfileResetterTest() {
}

void ProfileResetterTest::SetUp() {
  extensions::ExtensionServiceTestBase::SetUp();
  InitializeEmptyExtensionService();

  profile()->CreateWebDataService();
  TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
      profile(), base::BindRepeating(&CreateTemplateURLServiceForTesting));
  resetter_.reset(new ProfileResetter(profile()));
}

// PinnedTabsResetTest --------------------------------------------------------

class PinnedTabsResetTest : public BrowserWithTestWindowTest,
                            public ProfileResetterTestBase {
 protected:
  void SetUp() override;

  std::unique_ptr<content::WebContents> CreateWebContents();
};

void PinnedTabsResetTest::SetUp() {
  BrowserWithTestWindowTest::SetUp();
  resetter_.reset(new ProfileResetter(profile()));
}

std::unique_ptr<content::WebContents> PinnedTabsResetTest::CreateWebContents() {
  return content::WebContents::Create(
      content::WebContents::CreateParams(profile()));
}


// ConfigParserTest -----------------------------------------------------------

class ConfigParserTest : public testing::Test {
 protected:
  ConfigParserTest();
  ~ConfigParserTest() override;

  std::unique_ptr<BrandcodeConfigFetcher> WaitForRequest(const GURL& url);

  network::TestURLLoaderFactory& test_url_loader_factory() {
    return test_url_loader_factory_;
  }

 private:
  std::unique_ptr<network::SimpleURLLoader> CreateFakeURLLoader(
      const GURL& url,
      const std::string& response_data,
      net::HttpStatusCode response_code,
      net::URLRequestStatus::Status status);

  MOCK_METHOD0(Callback, void(void));

  content::TestBrowserThreadBundle test_browser_thread_bundle_;
  network::TestURLLoaderFactory test_url_loader_factory_;
};

ConfigParserTest::ConfigParserTest()
    : test_browser_thread_bundle_(
          content::TestBrowserThreadBundle::IO_MAINLOOP) {}

ConfigParserTest::~ConfigParserTest() {}

std::unique_ptr<BrandcodeConfigFetcher> ConfigParserTest::WaitForRequest(
    const GURL& url) {
  EXPECT_CALL(*this, Callback());
  std::string upload_data;
  test_url_loader_factory_.SetInterceptor(
      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
        upload_data = network::GetUploadData(request);
      }));
  std::unique_ptr<BrandcodeConfigFetcher> fetcher(new BrandcodeConfigFetcher(
      &test_url_loader_factory_,
      base::Bind(&ConfigParserTest::Callback, base::Unretained(this)), url,
      "ABCD"));
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(fetcher->IsActive());
  // Look for the brand code in the request.
  EXPECT_NE(std::string::npos, upload_data.find("ABCD"));
  return fetcher;
}

// A helper class to create/delete/check a Chrome desktop shortcut on Windows.
class ShortcutHandler {
 public:
  ShortcutHandler();
  ~ShortcutHandler();

  static bool IsSupported();
  ShortcutCommand CreateWithArguments(const base::string16& name,
                                      const base::string16& args);
  void CheckShortcutHasArguments(const base::string16& desired_args) const;
  void Delete();

 private:
#if defined(OS_WIN)
  base::FilePath shortcut_path_;
#endif
  DISALLOW_COPY_AND_ASSIGN(ShortcutHandler);
};

#if defined(OS_WIN)
ShortcutHandler::ShortcutHandler() {
}

ShortcutHandler::~ShortcutHandler() {
  if (!shortcut_path_.empty())
    Delete();
}

// static
bool ShortcutHandler::IsSupported() {
  return true;
}

ShortcutCommand ShortcutHandler::CreateWithArguments(
    const base::string16& name,
    const base::string16& args) {
  EXPECT_TRUE(shortcut_path_.empty());
  base::FilePath path_to_create;
  EXPECT_TRUE(base::PathService::Get(base::DIR_USER_DESKTOP, &path_to_create));
  path_to_create = path_to_create.Append(name);
  EXPECT_FALSE(base::PathExists(path_to_create)) << path_to_create.value();

  base::FilePath path_exe;
  EXPECT_TRUE(base::PathService::Get(base::FILE_EXE, &path_exe));
  base::win::ShortcutProperties shortcut_properties;
  shortcut_properties.set_target(path_exe);
  shortcut_properties.set_arguments(args);
  EXPECT_TRUE(base::win::CreateOrUpdateShortcutLink(
      path_to_create, shortcut_properties,
      base::win::SHORTCUT_CREATE_ALWAYS)) << path_to_create.value();
  shortcut_path_ = path_to_create;
  return ShortcutCommand(shortcut_path_, args);
}

void ShortcutHandler::CheckShortcutHasArguments(
    const base::string16& desired_args) const {
  EXPECT_FALSE(shortcut_path_.empty());
  base::string16 args;
  EXPECT_TRUE(base::win::ResolveShortcut(shortcut_path_, NULL, &args));
  EXPECT_EQ(desired_args, args);
}

void ShortcutHandler::Delete() {
  EXPECT_FALSE(shortcut_path_.empty());
  EXPECT_TRUE(base::DeleteFile(shortcut_path_, false));
  shortcut_path_.clear();
}
#else
ShortcutHandler::ShortcutHandler() {}

ShortcutHandler::~ShortcutHandler() {}

// static
bool ShortcutHandler::IsSupported() {
  return false;
}

ShortcutCommand ShortcutHandler::CreateWithArguments(
    const base::string16& name,
    const base::string16& args) {
  return ShortcutCommand();
}

void ShortcutHandler::CheckShortcutHasArguments(
    const base::string16& desired_args) const {
}

void ShortcutHandler::Delete() {
}
#endif  // defined(OS_WIN)


// helper functions -----------------------------------------------------------

scoped_refptr<Extension> CreateExtension(const base::string16& name,
                                         const base::FilePath& path,
                                         Manifest::Location location,
                                         extensions::Manifest::Type type,
                                         bool installed_by_default) {
  base::DictionaryValue manifest;
  manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
  manifest.SetString(extensions::manifest_keys::kName, name);
  manifest.SetInteger(extensions::manifest_keys::kManifestVersion, 2);
  switch (type) {
    case extensions::Manifest::TYPE_THEME:
      manifest.Set(extensions::manifest_keys::kTheme,
                   std::make_unique<base::DictionaryValue>());
      break;
    case extensions::Manifest::TYPE_HOSTED_APP:
      manifest.SetString(extensions::manifest_keys::kLaunchWebURL,
                         "http://www.google.com");
      manifest.SetString(extensions::manifest_keys::kUpdateURL,
                         "http://clients2.google.com/service/update2/crx");
      break;
    case extensions::Manifest::TYPE_EXTENSION:
      // do nothing
      break;
    default:
      NOTREACHED();
  }
  manifest.SetString(extensions::manifest_keys::kOmniboxKeyword, name);
  std::string error;
  scoped_refptr<Extension> extension = Extension::Create(
      path,
      location,
      manifest,
      installed_by_default ? Extension::WAS_INSTALLED_BY_DEFAULT
                           : Extension::NO_FLAGS,
      &error);
  EXPECT_TRUE(extension.get() != NULL) << error;
  return extension;
}

void ReplaceString(std::string* str,
                   const std::string& placeholder,
                   const std::string& substitution) {
  ASSERT_NE(static_cast<std::string*>(NULL), str);
  size_t placeholder_pos = str->find(placeholder);
  ASSERT_NE(std::string::npos, placeholder_pos);
  str->replace(placeholder_pos, placeholder.size(), substitution);
}


/********************* Tests *********************/

TEST_F(ProfileResetterTest, ResetNothing) {
  // The callback should be called even if there is nothing to reset.
  ResetAndWait(0);
}

TEST_F(ProfileResetterTest, ResetDefaultSearchEngineNonOrganic) {
  ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE, kDistributionConfig);

  TemplateURLService* model =
      TemplateURLServiceFactory::GetForProfile(profile());
  const TemplateURL* default_engine = model->GetDefaultSearchProvider();
  ASSERT_NE(static_cast<TemplateURL*>(NULL), default_engine);
  EXPECT_EQ(base::ASCIIToUTF16("first"), default_engine->short_name());
  EXPECT_EQ(base::ASCIIToUTF16("firstkey"), default_engine->keyword());
  EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", default_engine->url());
}

TEST_F(ProfileResetterTest, ResetDefaultSearchEnginePartially) {
  // Search engine's logic is tested by
  // TemplateURLServiceTest.RepairPrepopulatedSearchEngines.
  // Make sure TemplateURLService has loaded.
  ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);

  TemplateURLService* model =
      TemplateURLServiceFactory::GetForProfile(profile());
  TemplateURLService::TemplateURLVector urls = model->GetTemplateURLs();

  // The second call should produce no effect.
  ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE);

  EXPECT_EQ(urls, model->GetTemplateURLs());
}

TEST_F(ProfileResetterTest, ResetHomepageNonOrganic) {
  PrefService* prefs = profile()->GetPrefs();
  DCHECK(prefs);
  prefs->SetBoolean(prefs::kHomePageIsNewTabPage, true);
  prefs->SetString(prefs::kHomePage, "http://google.com");
  prefs->SetBoolean(prefs::kShowHomeButton, false);

  ResetAndWait(ProfileResetter::HOMEPAGE, kDistributionConfig);

  EXPECT_FALSE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
  EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
  EXPECT_TRUE(prefs->GetBoolean(prefs::kShowHomeButton));
}

TEST_F(ProfileResetterTest, ResetHomepagePartially) {
  PrefService* prefs = profile()->GetPrefs();
  DCHECK(prefs);
  prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
  prefs->SetString(prefs::kHomePage, "http://www.foo.com");
  prefs->SetBoolean(prefs::kShowHomeButton, true);

  ResetAndWait(ProfileResetter::HOMEPAGE);

  EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
  EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage));
  EXPECT_FALSE(prefs->GetBoolean(prefs::kShowHomeButton));
}

TEST_F(ProfileResetterTest, ResetContentSettings) {
  HostContentSettingsMap* host_content_settings_map =
      HostContentSettingsMapFactory::GetForProfile(profile());
  GURL url("http://example.org");
  std::map<ContentSettingsType, ContentSetting> default_settings;

  // TODO(raymes): Clean up this test so that we don't have such ugly iteration
  // over the content settings.
  content_settings::ContentSettingsRegistry* registry =
      content_settings::ContentSettingsRegistry::GetInstance();
  for (const content_settings::ContentSettingsInfo* info : *registry) {
    ContentSettingsType content_type = info->website_settings_info()->type();
    if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
        content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
      // These types are excluded because one can't call
      // GetDefaultContentSetting() for them.
      continue;
    }
    ContentSetting default_setting =
        host_content_settings_map->GetDefaultContentSetting(content_type, NULL);
    default_settings[content_type] = default_setting;
    ContentSetting wildcard_setting = default_setting == CONTENT_SETTING_BLOCK
                                          ? CONTENT_SETTING_ALLOW
                                          : CONTENT_SETTING_BLOCK;
    ContentSetting site_setting = default_setting == CONTENT_SETTING_ALLOW
                                      ? CONTENT_SETTING_ALLOW
                                      : CONTENT_SETTING_BLOCK;
    if (info->IsSettingValid(wildcard_setting)) {
      host_content_settings_map->SetDefaultContentSetting(content_type,
                                                          wildcard_setting);
    }
    if (info->IsSettingValid(site_setting)) {
      host_content_settings_map->SetContentSettingDefaultScope(
          url, url, content_type, std::string(), site_setting);
      ContentSettingsForOneType host_settings;
      host_content_settings_map->GetSettingsForOneType(
          content_type, std::string(), &host_settings);
      EXPECT_EQ(2U, host_settings.size());
    }
  }

  ResetAndWait(ProfileResetter::CONTENT_SETTINGS);

  for (const content_settings::ContentSettingsInfo* info : *registry) {
    ContentSettingsType content_type = info->website_settings_info()->type();
    if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
        content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS)
      continue;
    ContentSetting default_setting =
        host_content_settings_map->GetDefaultContentSetting(content_type,
                                                              NULL);
    EXPECT_TRUE(default_settings.count(content_type));
    EXPECT_EQ(default_settings[content_type], default_setting);
    ContentSetting site_setting = host_content_settings_map->GetContentSetting(
        GURL("example.org"), GURL(), content_type, std::string());
    EXPECT_EQ(default_setting, site_setting);

    ContentSettingsForOneType host_settings;
    host_content_settings_map->GetSettingsForOneType(
        content_type, std::string(), &host_settings);
    EXPECT_EQ(1U, host_settings.size());
  }
}

TEST_F(ProfileResetterTest, ResetExtensionsByDisabling) {
  service_->Init();

  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  scoped_refptr<Extension> theme = CreateExtension(
      base::ASCIIToUTF16("example1"), temp_dir.GetPath(), Manifest::UNPACKED,
      extensions::Manifest::TYPE_THEME, false);
  service_->FinishInstallationForTest(theme.get());
  // Let ThemeService finish creating the theme pack.
  base::RunLoop().RunUntilIdle();

  ThemeService* theme_service =
      ThemeServiceFactory::GetForProfile(profile());
  EXPECT_FALSE(theme_service->UsingDefaultTheme());

  scoped_refptr<Extension> ext2 = CreateExtension(
      base::ASCIIToUTF16("example2"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_EXTENSION, false);
  service_->AddExtension(ext2.get());
  // Component extensions and policy-managed extensions shouldn't be disabled.
  scoped_refptr<Extension> ext3 = CreateExtension(
      base::ASCIIToUTF16("example3"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent2")),
      Manifest::COMPONENT,
      extensions::Manifest::TYPE_EXTENSION,
      false);
  service_->AddExtension(ext3.get());
  scoped_refptr<Extension> ext4 =
      CreateExtension(base::ASCIIToUTF16("example4"),
                      base::FilePath(FILE_PATH_LITERAL("//nonexistent3")),
                      Manifest::EXTERNAL_POLICY_DOWNLOAD,
                      extensions::Manifest::TYPE_EXTENSION,
                      false);
  service_->AddExtension(ext4.get());
  scoped_refptr<Extension> ext5 = CreateExtension(
      base::ASCIIToUTF16("example5"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent4")),
      Manifest::EXTERNAL_COMPONENT,
      extensions::Manifest::TYPE_EXTENSION,
      false);
  service_->AddExtension(ext5.get());
  scoped_refptr<Extension> ext6 = CreateExtension(
      base::ASCIIToUTF16("example6"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent5")),
      Manifest::EXTERNAL_POLICY,
      extensions::Manifest::TYPE_EXTENSION,
      false);
  service_->AddExtension(ext6.get());
  EXPECT_EQ(6u, registry()->enabled_extensions().size());

  ResetAndWait(ProfileResetter::EXTENSIONS);
  EXPECT_EQ(4u, registry()->enabled_extensions().size());
  EXPECT_FALSE(registry()->enabled_extensions().Contains(theme->id()));
  EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2->id()));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3->id()));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(ext4->id()));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(ext5->id()));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(ext6->id()));
  EXPECT_TRUE(theme_service->UsingDefaultTheme());
}

TEST_F(ProfileResetterTest, ResetExtensionsByDisablingNonOrganic) {
  scoped_refptr<Extension> ext2 = CreateExtension(
      base::ASCIIToUTF16("example2"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_EXTENSION, false);
  service_->AddExtension(ext2.get());
  // Components and external policy extensions shouldn't be deleted.
  scoped_refptr<Extension> ext3 = CreateExtension(
      base::ASCIIToUTF16("example3"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent2")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_EXTENSION, false);
  service_->AddExtension(ext3.get());
  EXPECT_EQ(2u, registry()->enabled_extensions().size());

  std::string master_prefs(kDistributionConfig);
  ReplaceString(&master_prefs, "placeholder_for_id", ext3->id());

  ResetAndWait(ProfileResetter::EXTENSIONS, master_prefs);

  EXPECT_EQ(1u, registry()->enabled_extensions().size());
  EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3->id()));
}

TEST_F(ProfileResetterTest, ResetExtensionsAndDefaultApps) {
  service_->Init();

  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  scoped_refptr<Extension> ext1 = CreateExtension(
      base::ASCIIToUTF16("example1"), temp_dir.GetPath(), Manifest::UNPACKED,
      extensions::Manifest::TYPE_THEME, false);
  service_->FinishInstallationForTest(ext1.get());
  // Let ThemeService finish creating the theme pack.
  base::RunLoop().RunUntilIdle();

  ThemeService* theme_service =
      ThemeServiceFactory::GetForProfile(profile());
  EXPECT_FALSE(theme_service->UsingDefaultTheme());

  scoped_refptr<Extension> ext2 = CreateExtension(
      base::ASCIIToUTF16("example2"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent2")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_EXTENSION, false);
  service_->AddExtension(ext2.get());

  scoped_refptr<Extension> ext3 = CreateExtension(
      base::ASCIIToUTF16("example2"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent3")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_HOSTED_APP, true);
  service_->AddExtension(ext3.get());
  EXPECT_EQ(3u, registry()->enabled_extensions().size());

  ResetAndWait(ProfileResetter::EXTENSIONS);

  EXPECT_EQ(1u, registry()->enabled_extensions().size());
  EXPECT_FALSE(registry()->enabled_extensions().Contains(ext1->id()));
  EXPECT_FALSE(registry()->enabled_extensions().Contains(ext2->id()));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(ext3->id()));
  EXPECT_TRUE(theme_service->UsingDefaultTheme());
}

TEST_F(ProfileResetterTest, ResetExtensionsByReenablingExternalComponents) {
  service_->Init();

  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  scoped_refptr<Extension> ext =
      CreateExtension(base::ASCIIToUTF16("example"),
                      base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
                      Manifest::EXTERNAL_COMPONENT,
                      extensions::Manifest::TYPE_EXTENSION, false);
  service_->AddExtension(ext.get());

  service_->DisableExtension(ext->id(),
                             extensions::disable_reason::DISABLE_USER_ACTION);
  EXPECT_FALSE(registry()->enabled_extensions().Contains(ext->id()));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(ext->id()));

  ResetAndWait(ProfileResetter::EXTENSIONS);
  EXPECT_TRUE(registry()->enabled_extensions().Contains(ext->id()));
  EXPECT_FALSE(registry()->disabled_extensions().Contains(ext->id()));
}

TEST_F(ProfileResetterTest, ResetStartPageNonOrganic) {
  PrefService* prefs = profile()->GetPrefs();
  DCHECK(prefs);

  SessionStartupPref startup_pref(SessionStartupPref::LAST);
  SessionStartupPref::SetStartupPref(prefs, startup_pref);

  ResetAndWait(ProfileResetter::STARTUP_PAGES, kDistributionConfig);

  startup_pref = SessionStartupPref::GetStartupPref(prefs);
  EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type);
  const GURL urls[] = {GURL("http://goo.gl"), GURL("http://foo.de")};
  EXPECT_EQ(std::vector<GURL>(urls, urls + base::size(urls)),
            startup_pref.urls);
}


TEST_F(ProfileResetterTest, ResetStartPagePartially) {
  PrefService* prefs = profile()->GetPrefs();
  DCHECK(prefs);

  const GURL urls[] = {GURL("http://foo"), GURL("http://bar")};
  SessionStartupPref startup_pref(SessionStartupPref::URLS);
  startup_pref.urls.assign(urls, urls + base::size(urls));
  SessionStartupPref::SetStartupPref(prefs, startup_pref);

  ResetAndWait(ProfileResetter::STARTUP_PAGES, std::string());

  startup_pref = SessionStartupPref::GetStartupPref(prefs);
  EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref.type);
  EXPECT_EQ(std::vector<GURL>(urls, urls + base::size(urls)),
            startup_pref.urls);
}

TEST_F(PinnedTabsResetTest, ResetPinnedTabs) {
  std::unique_ptr<content::WebContents> contents1(CreateWebContents());
  std::unique_ptr<content::WebContents> contents2(CreateWebContents());
  std::unique_ptr<content::WebContents> contents3(CreateWebContents());
  std::unique_ptr<content::WebContents> contents4(CreateWebContents());
  content::WebContents* raw_contents1 = contents1.get();
  content::WebContents* raw_contents2 = contents2.get();
  content::WebContents* raw_contents3 = contents3.get();
  content::WebContents* raw_contents4 = contents4.get();
  TabStripModel* tab_strip_model = browser()->tab_strip_model();

  tab_strip_model->AppendWebContents(std::move(contents4), true);
  tab_strip_model->AppendWebContents(std::move(contents3), true);
  tab_strip_model->AppendWebContents(std::move(contents2), true);
  tab_strip_model->SetTabPinned(2, true);
  tab_strip_model->AppendWebContents(std::move(contents1), true);
  tab_strip_model->SetTabPinned(3, true);

  EXPECT_EQ(raw_contents2, tab_strip_model->GetWebContentsAt(0));
  EXPECT_EQ(raw_contents1, tab_strip_model->GetWebContentsAt(1));
  EXPECT_EQ(raw_contents4, tab_strip_model->GetWebContentsAt(2));
  EXPECT_EQ(raw_contents3, tab_strip_model->GetWebContentsAt(3));
  EXPECT_EQ(2, tab_strip_model->IndexOfFirstNonPinnedTab());

  ResetAndWait(ProfileResetter::PINNED_TABS);

  EXPECT_EQ(raw_contents2, tab_strip_model->GetWebContentsAt(0));
  EXPECT_EQ(raw_contents1, tab_strip_model->GetWebContentsAt(1));
  EXPECT_EQ(raw_contents4, tab_strip_model->GetWebContentsAt(2));
  EXPECT_EQ(raw_contents3, tab_strip_model->GetWebContentsAt(3));
  EXPECT_EQ(0, tab_strip_model->IndexOfFirstNonPinnedTab());
}

TEST_F(ProfileResetterTest, ResetShortcuts) {
  ShortcutHandler shortcut;
  ShortcutCommand command_line = shortcut.CreateWithArguments(
      base::ASCIIToUTF16("chrome.lnk"),
      base::ASCIIToUTF16("--profile-directory=Default foo.com"));
  shortcut.CheckShortcutHasArguments(base::ASCIIToUTF16(
      "--profile-directory=Default foo.com"));

  ResetAndWait(ProfileResetter::SHORTCUTS);

  shortcut.CheckShortcutHasArguments(base::ASCIIToUTF16(
      "--profile-directory=Default"));
}

TEST_F(ProfileResetterTest, ResetFewFlags) {
  // mock_object_ is a StrictMock, so we verify that it is called only once.
  ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
               ProfileResetter::HOMEPAGE |
               ProfileResetter::CONTENT_SETTINGS);
}

// Tries to load unavailable config file.
TEST_F(ConfigParserTest, NoConnectivity) {
  const GURL url("http://test");
  test_url_loader_factory().AddResponse(
      url, network::ResourceResponseHead(), "",
      network::URLLoaderCompletionStatus(net::HTTP_INTERNAL_SERVER_ERROR));

  std::unique_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
  EXPECT_FALSE(fetcher->GetSettings());
}

// Tries to load available config file.
TEST_F(ConfigParserTest, ParseConfig) {
  const GURL url("http://test");
  std::string xml_config(kXmlConfig);
  ReplaceString(&xml_config, "placeholder_for_data", kDistributionConfig);
  ReplaceString(&xml_config,
                "placeholder_for_id",
                "abbaabbaabbaabbaabbaabbaabbaabba");
  network::ResourceResponseHead head;
  std::string headers("HTTP/1.1 200 OK\nContent-type: text/xml\n\n");
  head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
      net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
  head.mime_type = "text/xml";
  network::URLLoaderCompletionStatus status;
  status.decoded_body_length = xml_config.size();
  test_url_loader_factory().AddResponse(url, head, xml_config, status);

  std::unique_ptr<BrandcodeConfigFetcher> fetcher = WaitForRequest(GURL(url));
  std::unique_ptr<BrandcodedDefaultSettings> settings = fetcher->GetSettings();
  ASSERT_TRUE(settings);

  std::vector<std::string> extension_ids;
  EXPECT_TRUE(settings->GetExtensions(&extension_ids));
  EXPECT_EQ(1u, extension_ids.size());
  EXPECT_EQ("abbaabbaabbaabbaabbaabbaabbaabba", extension_ids[0]);

  std::string homepage;
  EXPECT_TRUE(settings->GetHomepage(&homepage));
  EXPECT_EQ("http://www.foo.com", homepage);

  std::unique_ptr<base::ListValue> startup_list(
      settings->GetUrlsToRestoreOnStartup());
  EXPECT_TRUE(startup_list);
  std::vector<std::string> startup_pages;
  for (auto i = startup_list->begin(); i != startup_list->end(); ++i) {
    std::string url;
    EXPECT_TRUE(i->GetAsString(&url));
    startup_pages.push_back(url);
  }
  ASSERT_EQ(2u, startup_pages.size());
  EXPECT_EQ("http://goo.gl", startup_pages[0]);
  EXPECT_EQ("http://foo.de", startup_pages[1]);
}

TEST_F(ProfileResetterTest, CheckSnapshots) {
  ResettableSettingsSnapshot empty_snap(profile());
  EXPECT_EQ(0, empty_snap.FindDifferentFields(empty_snap));

  scoped_refptr<Extension> ext = CreateExtension(
      base::ASCIIToUTF16("example"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_EXTENSION, false);
  ASSERT_TRUE(ext.get());
  service_->AddExtension(ext.get());

  std::string master_prefs(kDistributionConfig);
  std::string ext_id = ext->id();
  ReplaceString(&master_prefs, "placeholder_for_id", ext_id);

  // Reset to non organic defaults.
  ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
               ProfileResetter::HOMEPAGE |
               ProfileResetter::STARTUP_PAGES,
               master_prefs);
  ShortcutHandler shortcut_hijacked;
  ShortcutCommand command_line = shortcut_hijacked.CreateWithArguments(
      base::ASCIIToUTF16("chrome1.lnk"),
      base::ASCIIToUTF16("--profile-directory=Default foo.com"));
  shortcut_hijacked.CheckShortcutHasArguments(
      base::ASCIIToUTF16("--profile-directory=Default foo.com"));
  ShortcutHandler shortcut_ok;
  shortcut_ok.CreateWithArguments(
      base::ASCIIToUTF16("chrome2.lnk"),
      base::ASCIIToUTF16("--profile-directory=Default1"));

  ResettableSettingsSnapshot nonorganic_snap(profile());
  nonorganic_snap.RequestShortcuts(base::Closure());
  // Let it enumerate shortcuts on a blockable task runner.
  content::RunAllTasksUntilIdle();
  int diff_fields = ResettableSettingsSnapshot::ALL_FIELDS;
  if (!ShortcutHandler::IsSupported())
    diff_fields &= ~ResettableSettingsSnapshot::SHORTCUTS;
  EXPECT_EQ(diff_fields,
            empty_snap.FindDifferentFields(nonorganic_snap));
  empty_snap.Subtract(nonorganic_snap);
  EXPECT_TRUE(empty_snap.startup_urls().empty());
  EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
            empty_snap.startup_type());
  EXPECT_TRUE(empty_snap.homepage().empty());
  EXPECT_TRUE(empty_snap.homepage_is_ntp());
  EXPECT_FALSE(empty_snap.show_home_button());
  EXPECT_NE(std::string::npos, empty_snap.dse_url().find("{google:baseURL}"));
  EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(),
            empty_snap.enabled_extensions());
  EXPECT_EQ(std::vector<ShortcutCommand>(), empty_snap.shortcuts());

  // Reset to organic defaults.
  ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
               ProfileResetter::HOMEPAGE |
               ProfileResetter::STARTUP_PAGES |
               ProfileResetter::EXTENSIONS |
               ProfileResetter::SHORTCUTS);

  ResettableSettingsSnapshot organic_snap(profile());
  organic_snap.RequestShortcuts(base::Closure());
  // Let it enumerate shortcuts on a blockable task runner.
  content::RunAllTasksUntilIdle();
  EXPECT_EQ(diff_fields, nonorganic_snap.FindDifferentFields(organic_snap));
  nonorganic_snap.Subtract(organic_snap);
  const GURL urls[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
  EXPECT_EQ(std::vector<GURL>(urls, urls + base::size(urls)),
            nonorganic_snap.startup_urls());
  EXPECT_EQ(SessionStartupPref::URLS, nonorganic_snap.startup_type());
  EXPECT_EQ("http://www.foo.com", nonorganic_snap.homepage());
  EXPECT_FALSE(nonorganic_snap.homepage_is_ntp());
  EXPECT_TRUE(nonorganic_snap.show_home_button());
  EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap.dse_url());
  EXPECT_EQ(ResettableSettingsSnapshot::ExtensionList(
      1, std::make_pair(ext_id, "example")),
      nonorganic_snap.enabled_extensions());
  if (ShortcutHandler::IsSupported()) {
    std::vector<ShortcutCommand> shortcuts = nonorganic_snap.shortcuts();
    ASSERT_EQ(1u, shortcuts.size());
    EXPECT_EQ(command_line.first.value(), shortcuts[0].first.value());
    EXPECT_EQ(command_line.second, shortcuts[0].second);
  }
}

TEST_F(ProfileResetterTest, FeedbackSerializationAsProtoTest) {
  // Reset to non organic defaults.
  ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
               ProfileResetter::HOMEPAGE |
               ProfileResetter::STARTUP_PAGES,
               kDistributionConfig);

  scoped_refptr<Extension> ext = CreateExtension(
      base::ASCIIToUTF16("example"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_EXTENSION, false);
  ASSERT_TRUE(ext.get());
  service_->AddExtension(ext.get());

  ShortcutHandler shortcut;
  ShortcutCommand command_line = shortcut.CreateWithArguments(
      base::ASCIIToUTF16("chrome.lnk"),
      base::ASCIIToUTF16("--profile-directory=Default foo.com"));

  ResettableSettingsSnapshot nonorganic_snap(profile());
  nonorganic_snap.RequestShortcuts(base::Closure());
  // Let it enumerate shortcuts on a blockable task runner.
  content::RunAllTasksUntilIdle();

  static_assert(ResettableSettingsSnapshot::ALL_FIELDS == 31,
                "this test needs to be expanded");
  for (int field_mask = 0; field_mask <= ResettableSettingsSnapshot::ALL_FIELDS;
       ++field_mask) {
    std::unique_ptr<reset_report::ChromeResetReport> report =
        SerializeSettingsReportToProto(nonorganic_snap, field_mask);

    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
              report->startup_url_path_size() > 0);
    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE),
              report->has_startup_type());
    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
              report->has_homepage_path());
    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
              report->has_homepage_is_new_tab_page());
    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE),
              report->has_show_home_button());
    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::DSE_URL),
              report->has_default_search_engine_path());
    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::EXTENSIONS),
              report->enabled_extensions_size() > 0);
    EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::SHORTCUTS) &&
                  ShortcutHandler::IsSupported(),
              report->shortcuts_size() > 0);
  }
}

struct FeedbackCapture {
  void SetFeedback(Profile* profile,
                   const ResettableSettingsSnapshot& snapshot) {
    list_ = GetReadableFeedbackForSnapshot(profile, snapshot);
    OnUpdatedList();
  }

  void Fail() {
    ADD_FAILURE() << "This method shouldn't be called.";
  }

  MOCK_METHOD0(OnUpdatedList, void(void));

  std::unique_ptr<base::ListValue> list_;
};

// Make sure GetReadableFeedback handles non-ascii letters.
TEST_F(ProfileResetterTest, GetReadableFeedback) {
  scoped_refptr<Extension> ext = CreateExtension(
      base::WideToUTF16(L"Tiësto"),
      base::FilePath(FILE_PATH_LITERAL("//nonexistent")), Manifest::UNPACKED,
      extensions::Manifest::TYPE_EXTENSION, false);
  ASSERT_TRUE(ext.get());
  service_->AddExtension(ext.get());

  PrefService* prefs = profile()->GetPrefs();
  DCHECK(prefs);
  // The URL is "http://россия.рф".
  std::wstring url(L"http://"
    L"\u0440\u043e\u0441\u0441\u0438\u044f.\u0440\u0444");
  prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
  prefs->SetString(prefs::kHomePage, base::WideToUTF8(url));

  SessionStartupPref startup_pref(SessionStartupPref::URLS);
  startup_pref.urls.push_back(GURL(base::WideToUTF8(url)));
  SessionStartupPref::SetStartupPref(prefs, startup_pref);

  ShortcutHandler shortcut;
  ShortcutCommand command_line = shortcut.CreateWithArguments(
      base::ASCIIToUTF16("chrome.lnk"),
      base::ASCIIToUTF16("--profile-directory=Default foo.com"));

  FeedbackCapture capture;
  EXPECT_CALL(capture, OnUpdatedList());
  ResettableSettingsSnapshot snapshot(profile());
  snapshot.RequestShortcuts(base::Bind(&FeedbackCapture::SetFeedback,
                                       base::Unretained(&capture),
                                       profile(),
                                       base::ConstRef(snapshot)));
  // Let it enumerate shortcuts on a blockable task runner.
  content::RunAllTasksUntilIdle();
  EXPECT_TRUE(snapshot.shortcuts_determined());
  ::testing::Mock::VerifyAndClearExpectations(&capture);
  // The homepage and the startup page are in punycode. They are unreadable.
  // Trying to find the extension name.
  std::unique_ptr<base::ListValue> list = std::move(capture.list_);
  ASSERT_TRUE(list);
  bool checked_extensions = false;
  bool checked_shortcuts = false;
  for (size_t i = 0; i < list->GetSize(); ++i) {
    base::DictionaryValue* dict = NULL;
    ASSERT_TRUE(list->GetDictionary(i, &dict));
    std::string value;
    ASSERT_TRUE(dict->GetString("key", &value));
    if (value == "Extensions") {
      base::string16 extensions;
      EXPECT_TRUE(dict->GetString("value", &extensions));
      EXPECT_EQ(base::WideToUTF16(L"Tiësto"), extensions);
      checked_extensions = true;
    } else if (value == "Shortcut targets") {
      base::string16 targets;
      EXPECT_TRUE(dict->GetString("value", &targets));
      EXPECT_NE(base::string16::npos,
                targets.find(base::ASCIIToUTF16("foo.com"))) << targets;
      checked_shortcuts = true;
    }
  }
  EXPECT_TRUE(checked_extensions);
  EXPECT_EQ(ShortcutHandler::IsSupported(), checked_shortcuts);
}

TEST_F(ProfileResetterTest, DestroySnapshotFast) {
  FeedbackCapture capture;
  std::unique_ptr<ResettableSettingsSnapshot> deleted_snapshot(
      new ResettableSettingsSnapshot(profile()));
  deleted_snapshot->RequestShortcuts(base::Bind(&FeedbackCapture::Fail,
                                                base::Unretained(&capture)));
  deleted_snapshot.reset();
  // Running remaining tasks shouldn't trigger the callback to be called as
  // |deleted_snapshot| was deleted before it could run.
  base::RunLoop().RunUntilIdle();
}

}  // namespace
