// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/extensions/external_cache_impl.h"

#include <stddef.h>

#include <utility>

#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/rand_util.h"
#include "base/scoped_multi_source_observation.h"
#include "base/strings/string_util.h"
#include "base/task/sequenced_task_runner.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/ash/extensions/external_cache_delegate.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/extensions/install_tracker_factory.h"
#include "chrome/browser/extensions/updater/chrome_extension_downloader_factory.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_manager_observer.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/install_observer.h"
#include "extensions/browser/install_tracker.h"
#include "extensions/browser/updater/extension_downloader.h"
#include "extensions/browser/updater/extension_downloader_delegate.h"
#include "extensions/browser/updater/extension_downloader_types.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/manifest.h"
#include "extensions/common/verifier_formats.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace chromeos {

namespace {

void FlushFile(const base::FilePath& path) {
  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_WRITE);
  file.Flush();
  file.Close();
}

}  // namespace

// This class observes all profiles for failures to load a CRX extension. If
// there is such a failure, it calls back into the provided
// |ExternalCacheImpl|.
//
// To do that, AnyInstallFailureObserver observes the global ProfileManager
// instance for any new profiles being created. When it observes a new
// Profile, it observes that Profile's InstallTracker. InstallTracker in turn
// notifies AnyInstallFailureObserver whenever a CRX install fails.
class ExternalCacheImpl::AnyInstallFailureObserver
    : public ProfileManagerObserver,
      public ProfileObserver,
      public extensions::InstallObserver {
 public:
  explicit AnyInstallFailureObserver(ExternalCacheImpl* owner);
  ~AnyInstallFailureObserver() override;

 private:
  // ProfileObserver:
  void OnProfileAdded(Profile* profile) override;
  void OnProfileWillBeDestroyed(Profile* profile) override;

  // ProfileManagerObserver:
  void OnProfileManagerDestroying() override;

  // extensions::InstallObserver:
  void OnFinishCrxInstall(content::BrowserContext* context,
                          const base::FilePath& source_file,
                          const std::string& extension_id,
                          const extensions::Extension* extension,
                          bool success) override;

  bool IsAnyObservedProfileUsingTracker(
      extensions::InstallTracker* tracker) const;

  base::ScopedObservation<ProfileManager, ProfileManagerObserver>
      profile_manager_observation_{this};
  base::ScopedMultiSourceObservation<Profile, ProfileObserver>
      profile_observations_{this};
  base::ScopedMultiSourceObservation<extensions::InstallTracker,
                                     InstallObserver>
      install_tracker_observations_{this};

  base::flat_set<raw_ptr<Profile, CtnExperimental>> observed_profiles_;

  // Required to outlive |this|, which is guaranteed in practice by having
  // |owner_| own |this|.
  raw_ptr<ExternalCacheImpl> owner_;
};

ExternalCacheImpl::AnyInstallFailureObserver::AnyInstallFailureObserver(
    ExternalCacheImpl* owner)
    : owner_(owner) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  CHECK(profile_manager);
  profile_manager_observation_.Observe(profile_manager);
  for (auto* profile : profile_manager->GetLoadedProfiles()) {
    OnProfileAdded(profile);
  }
}
ExternalCacheImpl::AnyInstallFailureObserver::~AnyInstallFailureObserver() =
    default;

void ExternalCacheImpl::AnyInstallFailureObserver::OnProfileAdded(
    Profile* profile) {
  CHECK(profile);
  if (!profile_observations_.IsObservingSource(profile)) {
    profile_observations_.AddObservation(profile);
    observed_profiles_.insert(profile);
  }

  auto* tracker =
      extensions::InstallTrackerFactory::GetForBrowserContext(profile);
  // Only observe the tracker if it's not already observed - it could be shared
  // between profiles (for example regular & incognito). It's also legal for the
  // tracker not to exist - some profiles (like the CrOS system profile) don't
  // have one.
  if (tracker && !install_tracker_observations_.IsObservingSource(tracker)) {
    install_tracker_observations_.AddObservation(tracker);
  }
}

void ExternalCacheImpl::AnyInstallFailureObserver::OnProfileWillBeDestroyed(
    Profile* profile) {
  auto* tracker =
      extensions::InstallTrackerFactory::GetForBrowserContext(profile);

  // If we received this notification for a given profile, we must have been
  // observing it to receive the notification in the first place.
  CHECK(profile_observations_.IsObservingSource(profile));
  profile_observations_.RemoveObservation(profile);
  CHECK_EQ(observed_profiles_.count(profile), 1u);
  observed_profiles_.erase(profile);

  bool is_observing = install_tracker_observations_.IsObservingSource(tracker);
  bool still_needed = IsAnyObservedProfileUsingTracker(tracker);
  if (tracker && is_observing && !still_needed) {
    install_tracker_observations_.RemoveObservation(tracker);
  }
}

void ExternalCacheImpl::AnyInstallFailureObserver::
    OnProfileManagerDestroying() {
  profile_manager_observation_.Reset();
}

void ExternalCacheImpl::AnyInstallFailureObserver::OnFinishCrxInstall(
    content::BrowserContext* context,
    const base::FilePath& source_file,
    const std::string& extension_id,
    const extensions::Extension* extension,
    bool success) {
  if (!success) {
    owner_->OnCrxInstallFailure(context, source_file);
  }
}

bool ExternalCacheImpl::AnyInstallFailureObserver::
    IsAnyObservedProfileUsingTracker(
        extensions::InstallTracker* tracker) const {
  return std::find_if(
             observed_profiles_.begin(), observed_profiles_.end(),
             [=](Profile* profile) -> bool {
               return extensions::InstallTrackerFactory::GetForBrowserContext(
                          profile) == tracker;
             }) != observed_profiles_.end();
}

ExternalCacheImpl::ExternalCacheImpl(
    const base::FilePath& cache_dir,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
    const scoped_refptr<base::SequencedTaskRunner>& backend_task_runner,
    ExternalCacheDelegate* delegate,
    bool always_check_updates,
    bool wait_for_cache_initialization,
    bool allow_scheduled_updates)
    : local_cache_(cache_dir, 0, base::TimeDelta(), backend_task_runner),
      url_loader_factory_(std::move(url_loader_factory)),
      backend_task_runner_(backend_task_runner),
      delegate_(delegate),
      always_check_updates_(always_check_updates),
      wait_for_cache_initialization_(wait_for_cache_initialization),
      allow_scheduled_updates_(allow_scheduled_updates) {
  kiosk_crx_updates_from_policy_subscription_ =
      ash::CrosSettings::Get()->AddSettingsObserver(
          ash::kKioskCRXManifestUpdateURLIgnored,
          base::BindRepeating(&ExternalCacheImpl::MaybeScheduleNextCacheCheck,
                              weak_ptr_factory_.GetWeakPtr()));

  // In unit tests, g_browser_process or the profile manager can be null.
  if (g_browser_process && g_browser_process->profile_manager()) {
    any_install_failure_observer_ =
        std::make_unique<AnyInstallFailureObserver>(this);
  }
}

ExternalCacheImpl::~ExternalCacheImpl() = default;

const base::Value::Dict& ExternalCacheImpl::GetCachedExtensions() {
  return cached_extensions_;
}

void ExternalCacheImpl::Shutdown(base::OnceClosure callback) {
  local_cache_.Shutdown(std::move(callback));
}

void ExternalCacheImpl::UpdateExtensionsList(base::Value::Dict prefs) {
  extensions_ = std::move(prefs);

  if (extensions_.empty()) {
    // If list of know extensions is empty, don't init cache on disk. It is
    // important shortcut for test to don't wait forever for cache dir
    // initialization that should happen outside of Chrome on real device.
    cached_extensions_.clear();
    UpdateExtensionLoader();
    return;
  }

  CheckCache();
}

void ExternalCacheImpl::OnDamagedFileDetected(const base::FilePath& path) {
  for (const auto [key, value] : cached_extensions_) {
    if (!value.is_dict()) {
      NOTREACHED() << "ExternalCacheImpl found bad entry with type "
                   << value.type();
    }

    const std::string* external_crx = value.GetDict().FindString(
        extensions::ExternalProviderImpl::kExternalCrx);
    if (external_crx && *external_crx == path.value()) {
      extensions::ExtensionId id = key;
      LOG(ERROR) << "ExternalCacheImpl extension at " << path.value()
                 << " failed to install, deleting it.";
      RemoveCachedExtension(id);
      UpdateExtensionLoader();

      // Don't try to DownloadMissingExtensions() from here,
      // since it can cause a fail/retry loop.
      // TODO(crbug.com/40715565) trigger re-installation mechanism with
      // exponential back-off.
      return;
    }
  }
  DLOG(ERROR) << "ExternalCacheImpl cannot find external_crx " << path.value();
}

void ExternalCacheImpl::RemoveExtensions(
    const std::vector<extensions::ExtensionId>& ids) {
  if (ids.empty())
    return;

  for (const auto& id : ids) {
    extensions_.RemoveByDottedPath(id);
    RemoveCachedExtension(id);
  }
  UpdateExtensionLoader();
}

void ExternalCacheImpl::RemoveCachedExtension(
    const extensions::ExtensionId& id) {
  cached_extensions_.RemoveByDottedPath(id);
  local_cache_.RemoveExtension(id, std::string());

  if (delegate_)
    delegate_->OnCachedExtensionFileDeleted(id);
}

bool ExternalCacheImpl::GetExtension(const extensions::ExtensionId& id,
                                     base::FilePath* file_path,
                                     std::string* version) {
  return local_cache_.GetExtension(id, std::string(), file_path, version);
}

bool ExternalCacheImpl::ExtensionFetchPending(
    const extensions::ExtensionId& id) {
  return extensions_.Find(id) && !cached_extensions_.Find(id);
}

void ExternalCacheImpl::PutExternalExtension(
    const extensions::ExtensionId& id,
    const base::FilePath& crx_file_path,
    const std::string& version,
    PutExternalExtensionCallback callback) {
  local_cache_.PutExtension(
      id, std::string(), crx_file_path, base::Version(version),
      base::BindOnce(&ExternalCacheImpl::OnPutExternalExtension,
                     weak_ptr_factory_.GetWeakPtr(), id, std::move(callback)));
}

void ExternalCacheImpl::SetBackoffPolicy(
    std::optional<net::BackoffEntry::Policy> backoff_policy) {
  backoff_policy_ = backoff_policy;
  if (downloader_) {
    // If `backoff_policy` is `std::nullopt`, it will reset to default backoff
    // policy.
    downloader_->SetBackoffPolicy(backoff_policy);
  }
}

void ExternalCacheImpl::OnCrxInstallFailure(content::BrowserContext* context,
                                            const base::FilePath& source_file) {
  OnDamagedFileDetected(source_file);
}

void ExternalCacheImpl::OnExtensionDownloadFailed(
    const extensions::ExtensionId& id,
    Error error,
    const PingResult& ping_result,
    const std::set<int>& request_ids,
    const FailureData& data) {
  if (error == Error::NO_UPDATE_AVAILABLE) {
    if (!cached_extensions_.Find(id)) {
      LOG(ERROR) << "ExternalCacheImpl extension " << id
                 << " not found on update server";
      delegate_->OnExtensionDownloadFailed(id, error);
    } else {
      // No version update for an already cached extension.
      delegate_->OnExtensionLoadedInCache(id, /*is_updated=*/false);
    }
  } else {
    LOG(ERROR) << "ExternalCacheImpl failed to download extension " << id
               << ", error " << static_cast<int>(error);
    delegate_->OnExtensionDownloadFailed(id, error);
  }
}

void ExternalCacheImpl::OnExtensionDownloadFinished(
    const extensions::CRXFileInfo& file,
    bool file_ownership_passed,
    const GURL& download_url,
    const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
    const std::set<int>& request_ids,
    InstallCallback callback) {
  DCHECK(file_ownership_passed);
  DCHECK(file.expected_version.IsValid());
  local_cache_.PutExtension(
      file.extension_id, file.expected_hash, file.path, file.expected_version,
      base::BindOnce(&ExternalCacheImpl::OnPutExtension,
                     weak_ptr_factory_.GetWeakPtr(), file.extension_id));
  if (!callback.is_null())
    std::move(callback).Run(true);
}

bool ExternalCacheImpl::IsExtensionPending(const extensions::ExtensionId& id) {
  return ExtensionFetchPending(id);
}

bool ExternalCacheImpl::GetExtensionExistingVersion(
    const extensions::ExtensionId& id,
    std::string* version) {
  const base::Value::Dict* extension_dictionary =
      cached_extensions_.FindDictByDottedPath(id);
  if (!extension_dictionary) {
    return false;
  }
  const std::string* val = extension_dictionary->FindString(
      extensions::ExternalProviderImpl::kExternalVersion);
  if (!val)
    return false;
  *version = *val;
  return true;
}

ExternalCacheImpl::RequestRollbackResult ExternalCacheImpl::RequestRollback(
    const extensions::ExtensionId& id) {
  bool is_rollback_allowed = delegate_ && delegate_->IsRollbackAllowed();
  if (!is_rollback_allowed) {
    return RequestRollbackResult::kDisallowed;
  }

  if (delegate_->CanRollbackNow()) {
    RemoveCachedExtension(id);
    UpdateExtensionLoader();
    return RequestRollbackResult::kAllowed;
  }

  local_cache_.RemoveOnNextInit(id);
  return RequestRollbackResult::kScheduledForNextRun;
}

void ExternalCacheImpl::UpdateExtensionLoader() {
  VLOG(1) << "Notify ExternalCacheImpl delegate about cache update";
  if (delegate_)
    delegate_->OnExtensionListsUpdated(cached_extensions_);
}

void ExternalCacheImpl::CheckCache() {
  if (local_cache_.is_shutdown())
    return;

  if (local_cache_.is_uninitialized()) {
    local_cache_.Init(wait_for_cache_initialization_,
                      base::BindOnce(&ExternalCacheImpl::CheckCache,
                                     weak_ptr_factory_.GetWeakPtr()));
    return;
  }

  // If url_loader_factory_ is missing we can't download anything.
  if (url_loader_factory_) {
    downloader_ = ChromeExtensionDownloaderFactory::CreateForURLLoaderFactory(
        url_loader_factory_, this, extensions::GetExternalVerifierFormat());
    if (backoff_policy_) {
      downloader_->SetBackoffPolicy(backoff_policy_);
    }
  }

  cached_extensions_.clear();
  for (const auto [id, value] : extensions_) {
    if (!value.is_dict()) {
      LOG(ERROR) << "ExternalCacheImpl found bad entry with type "
                 << value.type();
      continue;
    }

    base::FilePath file_path;
    std::string version;
    std::string hash;
    bool is_cached = local_cache_.GetExtension(id, hash, &file_path, &version);
    if (!is_cached)
      version = "0.0.0.0";
    if (downloader_) {
      GURL update_url =
          GetExtensionUpdateUrl(value.GetDict(), always_check_updates_);

      if (update_url.is_valid()) {
        downloader_->AddPendingExtension(extensions::ExtensionDownloaderTask(
            id, update_url,
            extensions::mojom::ManifestLocation::kExternalPolicy, false, 0,
            extensions::DownloadFetchPriority::kBackground,
            base::Version(version), extensions::Manifest::TYPE_UNKNOWN,
            std::string()));
      }
    }
    if (is_cached) {
      cached_extensions_.Set(
          id, GetExtensionValueToCache(value.GetDict(), file_path.value(),
                                       version));
    } else if (ShouldCacheImmediately(value.GetDict())) {
      cached_extensions_.Set(id, value.Clone());
    }
  }

  if (downloader_)
    downloader_->StartAllPending(nullptr);

  VLOG(1) << "Updated ExternalCacheImpl, there are "
          << cached_extensions_.size() << " extensions cached";

  UpdateExtensionLoader();

  // Cancel already-scheduled check, if any. We want scheduled update to happen
  // when update interval passes after previous check, independent of what has
  // triggered this check.
  scheduler_weak_ptr_factory_.InvalidateWeakPtrs();

  MaybeScheduleNextCacheCheck();
}

void ExternalCacheImpl::MaybeScheduleNextCacheCheck() {
  if (!allow_scheduled_updates_) {
    return;
  }
  bool kiosk_crx_updates_from_policy = false;
  if (!(ash::CrosSettings::Get()->GetBoolean(
            ash::kKioskCRXManifestUpdateURLIgnored,
            &kiosk_crx_updates_from_policy) &&
        kiosk_crx_updates_from_policy)) {
    return;
  }

  // Jitter the frequency by +/- 20% like it's done in ExtensionUpdater.
  const double jitter_factor = base::RandDouble() * 0.4 + 0.8;
  base::TimeDelta delay = extensions::kDefaultUpdateFrequency;
  delay *= jitter_factor;
  content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
      ->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&ExternalCacheImpl::CheckCache,
                         scheduler_weak_ptr_factory_.GetWeakPtr()),
          delay);
}

void ExternalCacheImpl::OnPutExtension(const extensions::ExtensionId& id,
                                       const base::FilePath& file_path,
                                       bool file_ownership_passed) {
  if (local_cache_.is_shutdown() || file_ownership_passed) {
    backend_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(base::IgnoreResult(&base::DeletePathRecursively),
                       file_path));
    return;
  }

  VLOG(1) << "ExternalCacheImpl installed a new extension in the cache " << id;

  const base::Value::Dict* original_entry = extensions_.FindDict(id);
  if (!original_entry) {
    LOG(ERROR) << "ExternalCacheImpl cannot find entry for extension " << id;
    return;
  }

  std::string version;
  std::string hash;
  if (!local_cache_.GetExtension(id, hash, nullptr, &version)) {
    // Copy entry to don't modify it inside extensions_.
    LOG(ERROR) << "Can't find installed extension in cache " << id;
    return;
  }

  if (flush_on_put_) {
    backend_task_runner_->PostTask(FROM_HERE,
                                   base::BindOnce(&FlushFile, file_path));
  }

  // Whether the extension is updated. Must be set before cached_extensions_.Set
  // or it always returns true.
  bool is_updated = cached_extensions_.contains(id);

  cached_extensions_.Set(id, GetExtensionValueToCache(
                                 *original_entry, file_path.value(), version));

  if (delegate_)
    delegate_->OnExtensionLoadedInCache(id, is_updated);

  UpdateExtensionLoader();
}

void ExternalCacheImpl::OnPutExternalExtension(
    const extensions::ExtensionId& id,
    PutExternalExtensionCallback callback,
    const base::FilePath& file_path,
    bool file_ownership_passed) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  OnPutExtension(id, file_path, file_ownership_passed);
  std::move(callback).Run(id, !file_ownership_passed);
}

}  // namespace chromeos
