// Copyright (c) 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_assets_manager_chromeos.h"

#include <stddef.h>

#include <map>
#include <memory>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/sequenced_task_runner.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/constants/chromeos_switches.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_url_handlers.h"

using content::BrowserThread;

namespace extensions {
namespace {

// Path to shared extensions install dir.
const char kSharedExtensionsDir[] = "/var/cache/shared_extensions";

// Shared install dir overrider for tests only.
static const base::FilePath* g_shared_install_dir_override = NULL;

// This helper class lives on UI thread only. Main purpose of this class is to
// track shared installation in progress between multiple profiles.
class ExtensionAssetsManagerHelper {
 public:
  // Info about pending install request.
  struct PendingInstallInfo {
    base::FilePath unpacked_extension_root;
    base::FilePath local_install_dir;
    Profile* profile;
    ExtensionAssetsManager::InstallExtensionCallback callback;
  };
  typedef std::vector<PendingInstallInfo> PendingInstallList;

  static ExtensionAssetsManagerHelper* GetInstance() {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    return base::Singleton<ExtensionAssetsManagerHelper>::get();
  }

  // Remember that shared install is in progress. Return true if there is no
  // other installs for given id and version.
  bool RecordSharedInstall(
      const std::string& id,
      const std::string& version,
      const base::FilePath& unpacked_extension_root,
      const base::FilePath& local_install_dir,
      Profile* profile,
      ExtensionAssetsManager::InstallExtensionCallback callback) {
    PendingInstallInfo install_info;
    install_info.unpacked_extension_root = unpacked_extension_root;
    install_info.local_install_dir = local_install_dir;
    install_info.profile = profile;
    install_info.callback = callback;

    std::vector<PendingInstallInfo>& callbacks =
        install_queue_[InstallQueue::key_type(id, version)];
    callbacks.push_back(install_info);

    return callbacks.size() == 1;
  }

  // Remove record about shared installation in progress and return
  // |pending_installs|.
  void SharedInstallDone(const std::string& id,
                         const std::string& version,
                         PendingInstallList* pending_installs) {
    InstallQueue::iterator it = install_queue_.find(
        InstallQueue::key_type(id, version));
    DCHECK(it != install_queue_.end());
    pending_installs->swap(it->second);
    install_queue_.erase(it);
  }

 private:
  friend struct base::DefaultSingletonTraits<ExtensionAssetsManagerHelper>;

  ExtensionAssetsManagerHelper() {}
  ~ExtensionAssetsManagerHelper() {}

  // Extension ID + version pair.
  typedef std::pair<std::string, std::string> InstallItem;

  // Queue of pending installs in progress.
  typedef std::map<InstallItem, std::vector<PendingInstallInfo> > InstallQueue;

  InstallQueue install_queue_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionAssetsManagerHelper);
};

}  // namespace

const char ExtensionAssetsManagerChromeOS::kSharedExtensions[] =
    "SharedExtensions";

const char ExtensionAssetsManagerChromeOS::kSharedExtensionPath[] = "path";

const char ExtensionAssetsManagerChromeOS::kSharedExtensionUsers[] = "users";

ExtensionAssetsManagerChromeOS::ExtensionAssetsManagerChromeOS() { }

ExtensionAssetsManagerChromeOS::~ExtensionAssetsManagerChromeOS() {
  if (g_shared_install_dir_override) {
    delete g_shared_install_dir_override;
    g_shared_install_dir_override = NULL;
  }
}

// static
ExtensionAssetsManagerChromeOS* ExtensionAssetsManagerChromeOS::GetInstance() {
  return base::Singleton<ExtensionAssetsManagerChromeOS>::get();
}

// static
void ExtensionAssetsManagerChromeOS::RegisterPrefs(
    PrefRegistrySimple* registry) {
  registry->RegisterDictionaryPref(kSharedExtensions);
}

void ExtensionAssetsManagerChromeOS::InstallExtension(
    const Extension* extension,
    const base::FilePath& unpacked_extension_root,
    const base::FilePath& local_install_dir,
    Profile* profile,
    InstallExtensionCallback callback) {
  if (!CanShareAssets(extension, unpacked_extension_root)) {
    InstallLocalExtension(extension->id(),
                          extension->VersionString(),
                          unpacked_extension_root,
                          local_install_dir,
                          callback);
    return;
  }

  base::PostTask(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&ExtensionAssetsManagerChromeOS::CheckSharedExtension,
                     extension->id(), extension->VersionString(),
                     unpacked_extension_root, local_install_dir, profile,
                     callback));
}

void ExtensionAssetsManagerChromeOS::UninstallExtension(
    const std::string& id,
    Profile* profile,
    const base::FilePath& local_install_dir,
    const base::FilePath& extension_root) {
  if (local_install_dir.IsParent(extension_root)) {
    file_util::UninstallExtension(local_install_dir, id);
    return;
  }

  if (GetSharedInstallDir().IsParent(extension_root)) {
    // In some test extensions installed outside local_install_dir emulate
    // previous behavior that just do nothing in this case.
    base::PostTask(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(
            &ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused, id,
            profile));
  }
}

// static
base::FilePath ExtensionAssetsManagerChromeOS::GetSharedInstallDir() {
  if (g_shared_install_dir_override)
    return *g_shared_install_dir_override;
  else
    return base::FilePath(kSharedExtensionsDir);
}

// static
bool ExtensionAssetsManagerChromeOS::IsSharedInstall(
    const Extension* extension) {
  return GetSharedInstallDir().IsParent(extension->path());
}

// static
bool ExtensionAssetsManagerChromeOS::CleanUpSharedExtensions(
    std::multimap<std::string, base::FilePath>* live_extension_paths) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  PrefService* local_state = g_browser_process->local_state();
  // It happens in many unit tests.
  if (!local_state)
    return false;

  DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
  std::vector<std::string> extensions;
  extensions.reserve(shared_extensions->size());
  for (base::DictionaryValue::Iterator it(*shared_extensions);
       !it.IsAtEnd(); it.Advance()) {
    extensions.push_back(it.key());
  }

  for (std::vector<std::string>::iterator it = extensions.begin();
       it != extensions.end(); it++) {
    base::DictionaryValue* extension_info = NULL;
    if (!shared_extensions->GetDictionary(*it, &extension_info)) {
      NOTREACHED();
      return false;
    }
    if (!CleanUpExtension(*it, extension_info, live_extension_paths)) {
      return false;
    }
    if (extension_info->empty())
      shared_extensions->RemoveWithoutPathExpansion(*it, NULL);
  }

  return true;
}

// static
void ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(
    const base::FilePath& install_dir) {
  DCHECK(!g_shared_install_dir_override);
  g_shared_install_dir_override = new base::FilePath(install_dir);
}

// static
bool ExtensionAssetsManagerChromeOS::CanShareAssets(
    const Extension* extension,
    const base::FilePath& unpacked_extension_root) {
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
          chromeos::switches::kEnableExtensionAssetsSharing)) {
    return false;
  }

  GURL update_url = ManifestURL::GetUpdateURL(extension);
  if (!update_url.is_empty() &&
      !extension_urls::IsWebstoreUpdateUrl(update_url)) {
    return false;
  }

  // Chrome caches crx files for installed by default apps so sharing assets is
  // also possible. User specific apps should be excluded to not expose apps
  // unique for the user outside of user's cryptohome.
  return Manifest::IsExternalLocation(extension->location());
}

// static
void ExtensionAssetsManagerChromeOS::CheckSharedExtension(
    const std::string& id,
    const std::string& version,
    const base::FilePath& unpacked_extension_root,
    const base::FilePath& local_install_dir,
    Profile* profile,
    InstallExtensionCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  const std::string& user_id = profile->GetProfileUserName();
  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
  if (!user_manager) {
    NOTREACHED();
    return;
  }

  if (user_manager->IsUserNonCryptohomeDataEphemeral(
          AccountId::FromUserEmail(user_id)) ||
      !user_manager->IsLoggedInAsUserWithGaiaAccount()) {
    // Don't cache anything in shared location for ephemeral user or special
    // user types.
    GetExtensionFileTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(&ExtensionAssetsManagerChromeOS::InstallLocalExtension,
                       id, version, unpacked_extension_root, local_install_dir,
                       callback));
    return;
  }

  PrefService* local_state = g_browser_process->local_state();
  DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
  base::DictionaryValue* extension_info = NULL;
  base::DictionaryValue* version_info = NULL;
  base::ListValue* users = NULL;
  std::string shared_path;
  if (shared_extensions->GetDictionary(id, &extension_info) &&
      extension_info->GetDictionaryWithoutPathExpansion(
          version, &version_info) &&
      version_info->GetString(kSharedExtensionPath, &shared_path) &&
      version_info->GetList(kSharedExtensionUsers, &users)) {
    // This extension version already in shared location.
    size_t users_size = users->GetSize();
    bool user_found = false;
    for (size_t i = 0; i < users_size; i++) {
      std::string temp;
      if (users->GetString(i, &temp) && temp == user_id) {
        // Re-installation for the same user.
        user_found = true;
        break;
      }
    }
    if (!user_found)
      users->AppendString(user_id);

    // unpacked_extension_root will be deleted by CrxInstaller.
    GetExtensionFileTaskRunner()->PostTask(
        FROM_HERE, base::BindOnce(callback, base::FilePath(shared_path)));
  } else {
    // Desired version is not found in shared location.
    ExtensionAssetsManagerHelper* helper =
        ExtensionAssetsManagerHelper::GetInstance();
    if (helper->RecordSharedInstall(id, version, unpacked_extension_root,
                                    local_install_dir, profile, callback)) {
      // There is no install in progress for given <id, version> so run install.
      GetExtensionFileTaskRunner()->PostTask(
          FROM_HERE,
          base::BindOnce(
              &ExtensionAssetsManagerChromeOS::InstallSharedExtension, id,
              version, unpacked_extension_root));
    }
  }
}

// static
void ExtensionAssetsManagerChromeOS::InstallSharedExtension(
      const std::string& id,
      const std::string& version,
      const base::FilePath& unpacked_extension_root) {
  base::FilePath shared_install_dir = GetSharedInstallDir();
  base::FilePath shared_version_dir = file_util::InstallExtension(
      unpacked_extension_root, id, version, shared_install_dir);
  base::PostTask(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(
          &ExtensionAssetsManagerChromeOS::InstallSharedExtensionDone, id,
          version, shared_version_dir));
}

// static
void ExtensionAssetsManagerChromeOS::InstallSharedExtensionDone(
    const std::string& id,
    const std::string& version,
    const base::FilePath& shared_version_dir) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  ExtensionAssetsManagerHelper* helper =
      ExtensionAssetsManagerHelper::GetInstance();
  ExtensionAssetsManagerHelper::PendingInstallList pending_installs;
  helper->SharedInstallDone(id, version, &pending_installs);

  if (shared_version_dir.empty()) {
    // Installation to shared location failed, try local dir.
    // TODO(dpolukhin): add UMA stats reporting.
    for (size_t i = 0; i < pending_installs.size(); i++) {
      ExtensionAssetsManagerHelper::PendingInstallInfo& info =
          pending_installs[i];
      GetExtensionFileTaskRunner()->PostTask(
          FROM_HERE,
          base::BindOnce(&ExtensionAssetsManagerChromeOS::InstallLocalExtension,
                         id, version, info.unpacked_extension_root,
                         info.local_install_dir, info.callback));
    }
    return;
  }

  PrefService* local_state = g_browser_process->local_state();
  DictionaryPrefUpdate shared_extensions(local_state, 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));
  }

  CHECK(!shared_extensions->HasKey(version));
  auto version_info = std::make_unique<base::DictionaryValue>();
  version_info->SetString(kSharedExtensionPath, shared_version_dir.value());

  auto users = std::make_unique<base::ListValue>();
  for (size_t i = 0; i < pending_installs.size(); i++) {
    ExtensionAssetsManagerHelper::PendingInstallInfo& info =
        pending_installs[i];
      users->AppendString(info.profile->GetProfileUserName());

      GetExtensionFileTaskRunner()->PostTask(
          FROM_HERE, base::BindOnce(info.callback, shared_version_dir));
  }
  version_info->Set(kSharedExtensionUsers, std::move(users));
  extension_info_weak->SetWithoutPathExpansion(version,
                                               std::move(version_info));
}

// static
void ExtensionAssetsManagerChromeOS::InstallLocalExtension(
    const std::string& id,
    const std::string& version,
    const base::FilePath& unpacked_extension_root,
    const base::FilePath& local_install_dir,
    InstallExtensionCallback callback) {
  callback.Run(file_util::InstallExtension(
      unpacked_extension_root, id, version, local_install_dir));
}

// static
void ExtensionAssetsManagerChromeOS::MarkSharedExtensionUnused(
    const std::string& id,
    Profile* profile) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  PrefService* local_state = g_browser_process->local_state();
  DictionaryPrefUpdate shared_extensions(local_state, kSharedExtensions);
  base::DictionaryValue* extension_info = NULL;
  if (!shared_extensions->GetDictionary(id, &extension_info)) {
    NOTREACHED();
    return;
  }

  std::vector<std::string> versions;
  versions.reserve(extension_info->size());
  for (base::DictionaryValue::Iterator it(*extension_info);
       !it.IsAtEnd();
       it.Advance()) {
    versions.push_back(it.key());
  }

  base::Value user_name(profile->GetProfileUserName());
  for (std::vector<std::string>::const_iterator it = versions.begin();
       it != versions.end(); it++) {
    base::DictionaryValue* version_info = NULL;
    if (!extension_info->GetDictionaryWithoutPathExpansion(*it,
                                                           &version_info)) {
      NOTREACHED();
      continue;
    }
    base::ListValue* users = NULL;
    if (!version_info->GetList(kSharedExtensionUsers, &users)) {
      NOTREACHED();
      continue;
    }
    if (users->Remove(user_name, NULL) && !users->GetSize()) {
      std::string shared_path;
      if (!version_info->GetString(kSharedExtensionPath, &shared_path)) {
        NOTREACHED();
        continue;
      }
      GetExtensionFileTaskRunner()->PostTask(
          FROM_HERE,
          base::BindOnce(&ExtensionAssetsManagerChromeOS::DeleteSharedVersion,
                         base::FilePath(shared_path)));
      extension_info->RemoveWithoutPathExpansion(*it, NULL);
    }
  }
  if (extension_info->empty()) {
    shared_extensions->RemoveWithoutPathExpansion(id, NULL);
    // Don't remove extension dir in shared location. It will be removed by GC
    // when it is safe to do so, and this avoids a race condition between
    // concurrent uninstall by one user and install by another.
  }
}

// static
void ExtensionAssetsManagerChromeOS::DeleteSharedVersion(
    const base::FilePath& shared_version_dir) {
  CHECK(GetSharedInstallDir().IsParent(shared_version_dir));
  base::DeleteFile(shared_version_dir, true);  // recursive.
}

// static
bool ExtensionAssetsManagerChromeOS::CleanUpExtension(
    const std::string& id,
    base::DictionaryValue* extension_info,
    std::multimap<std::string, base::FilePath>* live_extension_paths) {
  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
  if (!user_manager) {
    NOTREACHED();
    return false;
  }

  std::vector<std::string> versions;
  versions.reserve(extension_info->size());
  for (base::DictionaryValue::Iterator it(*extension_info);
       !it.IsAtEnd(); it.Advance()) {
    versions.push_back(it.key());
  }

  for (std::vector<std::string>::const_iterator it = versions.begin();
       it != versions.end(); it++) {
    base::DictionaryValue* version_info = NULL;
    base::ListValue* users = NULL;
    std::string shared_path;
    if (!extension_info->GetDictionaryWithoutPathExpansion(*it,
                                                           &version_info) ||
        !version_info->GetList(kSharedExtensionUsers, &users) ||
        !version_info->GetString(kSharedExtensionPath, &shared_path)) {
      NOTREACHED();
      return false;
    }

    size_t num_users = users->GetSize();
    for (size_t i = 0; i < num_users; i++) {
      std::string user_id;
      if (!users->GetString(i, &user_id)) {
        NOTREACHED();
        return false;
      }
      const user_manager::User* user =
          user_manager->FindUser(AccountId::FromUserEmail(user_id));
      bool not_used = false;
      if (!user) {
        not_used = true;
      } else if (user->is_logged_in()) {
        // For logged in user also check that this path is actually used as
        // installed extension or as delayed install.
        Profile* profile =
            chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user);
        ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile);
        if (!extension_prefs || extension_prefs->pref_service()->ReadOnly())
          return false;

        std::unique_ptr<ExtensionInfo> info =
            extension_prefs->GetInstalledExtensionInfo(id);
        if (!info || info->extension_path != base::FilePath(shared_path)) {
          info = extension_prefs->GetDelayedInstallInfo(id);
          if (!info || info->extension_path != base::FilePath(shared_path)) {
            not_used = true;
          }
        }
      }

      if (not_used) {
        users->Remove(i, NULL);

        i--;
        num_users--;
      }
    }

    if (num_users) {
      live_extension_paths->insert(
          std::make_pair(id, base::FilePath(shared_path)));
    } else {
      extension_info->RemoveWithoutPathExpansion(*it, NULL);
    }
  }

  return true;
}

}  // namespace extensions
