// Copyright 2014 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/extensions/extension_garbage_collector_chromeos.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/account_id/account_id.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_names.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/install_flag.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/value_builder.h"
#include "ppapi/buildflags/buildflags.h"

namespace {
const char kExtensionId1[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const char kExtensionId2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
}  // namespace

namespace extensions {

class ExtensionGarbageCollectorChromeOSUnitTest
    : public ExtensionServiceTestBase {
 protected:
  const base::FilePath& cache_dir() { return cache_dir_.GetPath(); }

  void SetUp() override {
    ExtensionServiceTestBase::SetUp();

#if BUILDFLAG(ENABLE_PLUGINS)
    content::PluginService::GetInstance()->Init();
#endif
    InitializeGoodInstalledExtensionService();

    CHECK(cache_dir_.CreateUniqueTempDir());
    ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(cache_dir());
    ExtensionGarbageCollectorChromeOS::ClearGarbageCollectedForTesting();

    // Initialize the UserManager singleton to a fresh FakeChromeUserManager
    // instance.
    user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
        std::make_unique<chromeos::FakeChromeUserManager>());

    GetFakeUserManager()->AddUser(user_manager::StubAccountId());
    GetFakeUserManager()->LoginUser(user_manager::StubAccountId());
    chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(
        GetFakeUserManager()->GetActiveUser(), profile_.get());
  }

  void GarbageCollectExtensions() {
    ExtensionGarbageCollector::Get(profile_.get())
        ->GarbageCollectExtensionsForTest();
    // Wait for GarbageCollectExtensions task to complete.
    content::RunAllTasksUntilIdle();
  }

  base::FilePath CreateSharedExtensionDir(const std::string& id,
                                          const std::string& version,
                                          const base::FilePath& shared_dir) {
    base::FilePath path = shared_dir.AppendASCII(id).AppendASCII(version);
    CreateDirectory(path);
    return path;
  }

  void CreateSharedExtensionPrefs(const std::string& id,
                                  const std::string& version,
                                  const std::string& users_string,
                                  const base::FilePath& path) {
    DictionaryPrefUpdate shared_extensions(testing_local_state_.Get(),
        ExtensionAssetsManagerChromeOS::kSharedExtensions);

    base::DictionaryValue* extension_info_weak = NULL;
    if (!shared_extensions->GetDictionary(id, &extension_info_weak)) {
      auto extension_info = std::make_unique<base::DictionaryValue>();
      extension_info_weak = extension_info.get();
      shared_extensions->Set(id, std::move(extension_info));
    }

    auto version_info = std::make_unique<base::DictionaryValue>();
    version_info->SetString(
        ExtensionAssetsManagerChromeOS::kSharedExtensionPath, path.value());

    auto users = std::make_unique<base::ListValue>();
    for (const std::string& user :
         base::SplitString(users_string, ",", base::KEEP_WHITESPACE,
                           base::SPLIT_WANT_NONEMPTY)) {
      users->AppendString(user);
    }
    version_info->Set(ExtensionAssetsManagerChromeOS::kSharedExtensionUsers,
                      std::move(users));
    extension_info_weak->SetWithoutPathExpansion(version,
                                                 std::move(version_info));
  }

  scoped_refptr<Extension> CreateExtension(const std::string& id,
                                           const std::string& version,
                                           const base::FilePath& path) {
    return ExtensionBuilder("test")
        .SetManifestKey(manifest_keys::kVersion, version)
        .SetID(id)
        .SetPath(path)
        .SetLocation(Manifest::INTERNAL)
        .Build();
  }

  ExtensionPrefs* GetExtensionPrefs() {
    return ExtensionPrefs::Get(profile_.get());
  }

  chromeos::FakeChromeUserManager* GetFakeUserManager() {
    return static_cast<chromeos::FakeChromeUserManager*>(
        user_manager::UserManager::Get());
  }

 private:
  std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
  base::ScopedTempDir cache_dir_;
};

// Test shared extensions clean up.
TEST_F(ExtensionGarbageCollectorChromeOSUnitTest, SharedExtensions) {
  // Version for non-existing user.
  base::FilePath path_id1_1 = CreateSharedExtensionDir(
      kExtensionId1, "1.0", cache_dir());
  CreateSharedExtensionPrefs(kExtensionId1, "1.0", "test@test.com", path_id1_1);
  EXPECT_TRUE(base::PathExists(path_id1_1));

  // Version for current user but the extension is not installed.
  base::FilePath path_id1_2 = CreateSharedExtensionDir(
      kExtensionId1, "2.0", cache_dir());
  CreateSharedExtensionPrefs(kExtensionId1, "2.0",
                             user_manager::StubAccountId().GetUserEmail(),
                             path_id1_2);
  EXPECT_TRUE(base::PathExists(path_id1_2));

  // Version for current user that delayed install.
  base::FilePath path_id2_1 = CreateSharedExtensionDir(
      kExtensionId2, "1.0", cache_dir());
  CreateSharedExtensionPrefs(kExtensionId2, "1.0",
                             user_manager::StubAccountId().GetUserEmail(),
                             path_id2_1);
  scoped_refptr<Extension> extension2 = CreateExtension(kExtensionId2, "1.0",
                                                        path_id2_1);
  GetExtensionPrefs()->SetDelayedInstallInfo(
      extension2.get(),
      Extension::ENABLED,
      kInstallFlagNone,
      ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
      syncer::StringOrdinal(),
      std::string());
  EXPECT_TRUE(base::PathExists(path_id2_1));

  GarbageCollectExtensions();

  EXPECT_FALSE(base::PathExists(path_id1_1));
  EXPECT_FALSE(base::PathExists(path_id1_2));
  EXPECT_FALSE(base::PathExists(cache_dir().AppendASCII(kExtensionId1)));

  EXPECT_TRUE(base::PathExists(path_id2_1));

  const base::DictionaryValue* shared_extensions = testing_local_state_.Get()->
      GetDictionary(ExtensionAssetsManagerChromeOS::kSharedExtensions);
  ASSERT_TRUE(shared_extensions);

  EXPECT_FALSE(shared_extensions->HasKey(kExtensionId1));
  EXPECT_TRUE(shared_extensions->HasKey(kExtensionId2));
}

}  // namespace extensions
