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

#include <memory>

#include "base/memory/ref_counted.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/buildflags/buildflags.h"

static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));

namespace extensions {

namespace {
const char kCouldNotUninstallExtension[] = "Failed to uninstall the extension.";
const char kTabClosed[] = "Tab was closed.";
}

WebstoreReinstaller::WebstoreReinstaller(
    content::WebContents* web_contents,
    const std::string& extension_id,
    WebstoreStandaloneInstaller::Callback callback)
    : WebstoreStandaloneInstaller(
          extension_id,
          Profile::FromBrowserContext(web_contents->GetBrowserContext()),
          std::move(callback)),
      content::WebContentsObserver(web_contents) {
  DCHECK(
      ExtensionPrefs::Get(web_contents->GetBrowserContext())
          ->HasDisableReason(extension_id, disable_reason::DISABLE_CORRUPTED));
}

WebstoreReinstaller::~WebstoreReinstaller() = default;

void WebstoreReinstaller::BeginReinstall() {
  WebstoreStandaloneInstaller::BeginInstall();
}

bool WebstoreReinstaller::CheckRequestorAlive() const {
  return web_contents() != nullptr;
}

std::unique_ptr<InstallPromptData> WebstoreReinstaller::CreateInstallPrompt()
    const {
  std::unique_ptr<InstallPromptData> prompt =
      std::make_unique<InstallPromptData>(InstallPromptData::REPAIR_PROMPT);
  prompt->SetWebstoreData(localized_user_count(), show_user_count(),
                          average_rating(), rating_count(),
                          localized_rating_count());
  return prompt;
}

bool WebstoreReinstaller::ShouldShowPostInstallUI() const {
  return false;
}

content::WebContents* WebstoreReinstaller::GetWebContents() const {
  return web_contents();
}

void WebstoreReinstaller::WebContentsDestroyed() {
  // Run the callback now, because AbortInstall() doesn't do it.
  RunCallback(false, kTabClosed, webstore_install::ABORTED);
  AbortInstall();
}

void WebstoreReinstaller::OnInstallPromptDone(
    ExtensionInstallPrompt::DoneCallbackPayload payload) {
  // This dialog doesn't support the "withhold permissions" checkbox.
  DCHECK_NE(payload.result,
            ExtensionInstallPrompt::Result::ACCEPTED_WITH_WITHHELD_PERMISSIONS);

  if (payload.result != ExtensionInstallPrompt::Result::ACCEPTED) {
    WebstoreStandaloneInstaller::OnInstallPromptDone(std::move(payload));
    return;
  }

  // The extension can be uninstalled in another window while the repair prompt
  // was showing. `UninstallExtension()` CHECKs that the extension is still
  // installed, so bail out gracefully if it is gone to avoid crashing.
  if (!ExtensionRegistry::Get(profile())->GetInstalledExtension(id())) {
    // Run the callback now, because AbortInstall() doesn't do it.
    RunCallback(false, kCouldNotUninstallExtension,
                webstore_install::OTHER_ERROR);
    AbortInstall();
    return;
  }

  if (!ExtensionRegistrar::Get(profile())->UninstallExtension(
          id(), UNINSTALL_REASON_REINSTALL, nullptr)) {
    // Run the callback now, because AbortInstall() doesn't do it.
    RunCallback(
        false, kCouldNotUninstallExtension, webstore_install::OTHER_ERROR);
    AbortInstall();
    return;
  }
  WebstoreStandaloneInstaller::OnInstallPromptDone(std::move(payload));
}

}  // namespace extensions
