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

#include "extensions/browser/host_access_request_helper.h"

#include <sys/types.h>

#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/permissions_manager.h"
#include "extensions/common/extension.h"
#include "extensions/common/url_pattern.h"

namespace extensions {

HostAccessRequestsHelper::HostAccessRequestsHelper(
    PassKey pass_key,
    PermissionsManager* permissions_manager,
    content::WebContents* web_contents,
    int tab_id)
    : content::WebContentsObserver(web_contents),
      permissions_manager_(permissions_manager),
      web_contents_(web_contents),
      tab_id_(tab_id) {
  extension_registry_observation_.Observe(
      ExtensionRegistry::Get(web_contents->GetBrowserContext()));
}

HostAccessRequestsHelper::~HostAccessRequestsHelper() = default;

void HostAccessRequestsHelper::AddRequest(
    const Extension& extension,
    const std::optional<URLPattern>& filter) {
  // Extension must not have granted access to the current site.
  auto site_access = permissions_manager_->GetSiteAccess(
      extension, web_contents_->GetLastCommittedURL());
  CHECK(!site_access.has_site_access && !site_access.has_all_sites_access);

  extensions_with_requests_.insert({extension.id(), filter});
}

void HostAccessRequestsHelper::UpdateRequest(
    const Extension& extension,
    const std::optional<URLPattern>& filter) {
  // We can only update a request if there is an existent one.
  CHECK(HasRequest(extension.id()));

  // Extension must not have granted access to the current site.
  auto site_access = permissions_manager_->GetSiteAccess(
      extension, web_contents_->GetLastCommittedURL());
  CHECK(!site_access.has_site_access && !site_access.has_all_sites_access);

  extensions_with_requests_.at(extension.id()) = filter;
}

bool HostAccessRequestsHelper::RemoveRequest(
    const ExtensionId& extension_id,
    const std::optional<URLPattern>& filter) {
  auto requests_iter = extensions_with_requests_.find(extension_id);
  if (requests_iter == extensions_with_requests_.end()) {
    return false;
  }

  // Remove request iff it matches the parameter when given. Otherwise, always
  // remove the request.
  if (!filter || requests_iter->second == filter) {
    extensions_with_requests_.erase(extension_id);
    return true;
  }

  return false;
}

bool HostAccessRequestsHelper::RemoveRequestIfGrantedAccess(
    const Extension& extension) {
  // Request is removed iff extension has access to the current site.
  const GURL& url = web_contents_->GetLastCommittedURL();
  PermissionsManager::ExtensionSiteAccess site_access =
      permissions_manager_->GetSiteAccess(extension, url);
  if (!site_access.has_site_access && !site_access.has_all_sites_access &&
      !permissions_manager_->HasActiveTabAndCanAccess(extension, url)) {
    return false;
  }

  return RemoveRequest(extension.id(), /*filter=*/std::nullopt);
}

void HostAccessRequestsHelper::UserDismissedRequest(
    const ExtensionId& extension_id) {
  CHECK(extensions_with_requests_.contains(extension_id));
  extensions_with_requests_dismissed_.insert(extension_id);
}

bool HostAccessRequestsHelper::HasRequest(
    const ExtensionId& extension_id) const {
  return extensions_with_requests_.contains(extension_id);
}

bool HostAccessRequestsHelper::HasActiveRequest(
    const ExtensionId& extension_id) const {
  if (!extensions_with_requests_.contains(extension_id)) {
    return false;
  }

  if (extensions_with_requests_dismissed_.contains(extension_id)) {
    return false;
  }

  // Web contents must match the filter if provided, otherwise request is always
  // active.
  std::optional<URLPattern> filter = extensions_with_requests_.at(extension_id);
  return !filter ||
         filter.value().MatchesURL(web_contents_->GetLastCommittedURL());
}

bool HostAccessRequestsHelper::HasRequests() {
  return !extensions_with_requests_.empty();
}

void HostAccessRequestsHelper::OnExtensionUnloaded(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UnloadedExtensionReason reason) {
  RemoveRequest(extension->id(), /*filter=*/std::nullopt);

  if (!HasRequests()) {
    permissions_manager_->DeleteHostAccessRequestHelperFor(tab_id_);
    // IMPORTANT: This object is now deleted and is unsafe to use.
  }
}

void HostAccessRequestsHelper::DidFinishNavigation(
    content::NavigationHandle* navigation_handle) {
  // Sub-frames don't get specific requests.
  if (!navigation_handle->IsInPrimaryMainFrame() ||
      !navigation_handle->HasCommitted() ||
      navigation_handle->IsSameDocument()) {
    return;
  }

  // Only clear requests for cross-origin navigations.
  if (navigation_handle->IsSameOrigin()) {
    return;
  }

  extensions_with_requests_.clear();
  extensions_with_requests_dismissed_.clear();

  permissions_manager_->NotifyHostAccessRequestsCleared(tab_id_);
  permissions_manager_->DeleteHostAccessRequestHelperFor(tab_id_);
  // IMPORTANT: This object is now deleted and is unsafe to use.
}

void HostAccessRequestsHelper::WebContentsDestroyed() {
  // Delete web contents pointer so it's not dangling at helper's destruction.
  web_contents_ = nullptr;

  extensions_with_requests_.clear();
  extensions_with_requests_dismissed_.clear();

  permissions_manager_->DeleteHostAccessRequestHelperFor(tab_id_);
  // IMPORTANT: This object is now deleted and is unsafe to use.
}

}  // namespace extensions
