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

#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"

using content::NavigationController;
using content::NavigationEntry;

namespace extensions {

namespace {
// Whether to repeatedly prompt for the same extension id.
bool g_repeat_prompting = false;
}

NavigationObserver::NavigationObserver(Profile* profile)
    : profile_(profile),
      extension_registry_observer_(this),
      weak_factory_(this) {
  RegisterForNotifications();
  extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
}

NavigationObserver::~NavigationObserver() {}

void NavigationObserver::Observe(int type,
                                 const content::NotificationSource& source,
                                 const content::NotificationDetails& details) {
  DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type);

  NavigationController* controller =
      content::Source<NavigationController>(source).ptr();
  if (!profile_->IsSameProfile(
          Profile::FromBrowserContext(controller->GetBrowserContext())))
    return;

  PromptToEnableExtensionIfNecessary(controller);
}

// static
void NavigationObserver::SetAllowedRepeatedPromptingForTesting(bool allowed) {
  g_repeat_prompting = allowed;
}

void NavigationObserver::RegisterForNotifications() {
  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
                 content::NotificationService::AllSources());
}

void NavigationObserver::PromptToEnableExtensionIfNecessary(
    NavigationController* nav_controller) {
  // Bail out if we're already running a prompt.
  if (!in_progress_prompt_extension_id_.empty())
    return;

  NavigationEntry* nav_entry = nav_controller->GetVisibleEntry();
  if (!nav_entry)
    return;

  const GURL& url = nav_entry->GetURL();

  // NOTE: We only consider chrome-extension:// urls, and deliberately don't
  // consider hosted app urls. This is because it's really annoying to visit the
  // site associated with a hosted app (like calendar.google.com or
  // drive.google.com) and have it repeatedly prompt you to re-enable an item.
  // Visiting a chrome-extension:// url is a much stronger signal, and, without
  // the item enabled, we won't show anything.
  // TODO(devlin): While true, I still wonder how useful this is. We should get
  // metrics.
  if (!url.SchemeIs(kExtensionScheme))
    return;

  const Extension* extension = ExtensionRegistry::Get(profile_)
                                   ->disabled_extensions()
                                   .GetExtensionOrAppByURL(url);
  if (!extension)
    return;

  // Try not to repeatedly prompt the user about the same extension.
  if (!prompted_extensions_.insert(extension->id()).second &&
      !g_repeat_prompting) {
    return;
  }

  ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
  // TODO(devlin): Why do we only consider extensions that escalate permissions?
  // Maybe because it's the only one we have a good prompt for?
  if (extension_prefs->DidExtensionEscalatePermissions(extension->id())) {
    // Keep track of the extension id and nav controller we're prompting for.
    // These must be reset in OnInstallPromptDone.
    in_progress_prompt_extension_id_ = extension->id();
    in_progress_prompt_navigation_controller_ = nav_controller;

    extension_install_prompt_.reset(
        new ExtensionInstallPrompt(nav_controller->GetWebContents()));
    ExtensionInstallPrompt::PromptType type =
        ExtensionInstallPrompt::GetReEnablePromptTypeForExtension(profile_,
                                                                  extension);
    extension_install_prompt_->ShowDialog(
        base::Bind(&NavigationObserver::OnInstallPromptDone,
                   weak_factory_.GetWeakPtr()),
        extension, nullptr,
        std::make_unique<ExtensionInstallPrompt::Prompt>(type),
        ExtensionInstallPrompt::GetDefaultShowDialogCallback());
  }
}

void NavigationObserver::OnInstallPromptDone(
    ExtensionInstallPrompt::Result result) {
  // The extension was already uninstalled.
  if (in_progress_prompt_extension_id_.empty())
    return;

  ExtensionService* extension_service =
      extensions::ExtensionSystem::Get(profile_)->extension_service();
  const Extension* extension = extension_service->GetExtensionById(
      in_progress_prompt_extension_id_, true);
  CHECK(extension);

  if (result == ExtensionInstallPrompt::Result::ACCEPTED) {
    NavigationController* nav_controller =
        in_progress_prompt_navigation_controller_;
    CHECK(nav_controller);

    // Grant permissions, re-enable the extension, and then reload the tab.
    extension_service->GrantPermissionsAndEnableExtension(extension);
    nav_controller->Reload(content::ReloadType::NORMAL, true);
  } else {
    // TODO(devlin): These metrics aren't very useful, since they're lumped in
    // with the same for re-enabling/canceling when the extension first gets
    // disabled, which is likely significantly more common (though impossible to
    // tell). We need to separate these.
    std::string histogram_name =
       result == ExtensionInstallPrompt::Result::USER_CANCELED
            ? "ReEnableCancel"
            : "ReEnableAbort";
    ExtensionService::RecordPermissionMessagesHistogram(extension,
                                                        histogram_name.c_str());
  }

  in_progress_prompt_extension_id_ = std::string();
  in_progress_prompt_navigation_controller_ = nullptr;
  extension_install_prompt_.reset();
}

void NavigationObserver::OnExtensionUninstalled(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UninstallReason reason) {
  if (in_progress_prompt_extension_id_.empty() ||
      in_progress_prompt_extension_id_ != extension->id()) {
    return;
  }

  in_progress_prompt_extension_id_ = std::string();
  in_progress_prompt_navigation_controller_ = nullptr;
  extension_install_prompt_.reset();
}

}  // namespace extensions
