// Copyright 2018 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/lookalikes/lookalike_url_service.h"

#include <utility>

#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/singleton.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/default_clock.h"
#include "base/trace_event/trace_event.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/engagement/site_engagement_service_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h"
#include "chrome/browser/safe_browsing/user_interaction_observer.h"
#include "chrome/common/channel_info.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/lookalikes/core/lookalike_url_util.h"
#include "components/lookalikes/core/safety_tips_config.h"
#include "components/security_state/core/security_state.h"
#include "components/site_engagement/content/site_engagement_score.h"
#include "components/site_engagement/content/site_engagement_service.h"
#include "components/url_formatter/spoof_checks/top_domains/top_domain_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "url/url_constants.h"

using lookalikes::DomainInfo;
using lookalikes::LookalikeActionType;
using lookalikes::LookalikeUrlMatchType;
using security_state::SafetyTipStatus;

namespace {

constexpr base::TimeDelta kEngagedSiteUpdateInterval = base::Seconds(60);

class LookalikeUrlServiceFactory : public ProfileKeyedServiceFactory {
 public:
  static LookalikeUrlService* GetForProfile(Profile* profile) {
    return static_cast<LookalikeUrlService*>(
        GetInstance()->GetServiceForBrowserContext(profile,
                                                   /*create_service=*/true));
  }
  static LookalikeUrlServiceFactory* GetInstance() {
    return base::Singleton<LookalikeUrlServiceFactory>::get();
  }

  LookalikeUrlServiceFactory(const LookalikeUrlServiceFactory&) = delete;
  LookalikeUrlServiceFactory& operator=(const LookalikeUrlServiceFactory&) =
      delete;

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

  // LookalikeUrlServiceFactory();
  LookalikeUrlServiceFactory()
      : ProfileKeyedServiceFactory(
            "LookalikeUrlServiceFactory",
            ProfileSelections::Builder()
                .WithRegular(ProfileSelection::kOwnInstance)
                // TODO(crbug.com/40257657): Check if this service is needed in
                // Guest mode.
                .WithGuest(ProfileSelection::kOwnInstance)
                // TODO(crbug.com/41488885): Check if this service is needed for
                // Ash Internals.
                .WithAshInternals(ProfileSelection::kOwnInstance)
                .Build()) {
    DependsOn(site_engagement::SiteEngagementServiceFactory::GetInstance());
  }

  ~LookalikeUrlServiceFactory() override {}

  // BrowserContextKeyedServiceFactory:
  KeyedService* BuildServiceInstanceFor(
      content::BrowserContext* profile) const override {
    return new LookalikeUrlService(static_cast<Profile*>(profile));
  }
};

// static
std::vector<DomainInfo> UpdateEngagedSitesOnWorkerThread(
    base::Time now,
    scoped_refptr<HostContentSettingsMap> map) {
  TRACE_EVENT0("navigation",
               "LookalikeUrlService UpdateEngagedSitesOnWorkerThread");
  std::vector<DomainInfo> new_engaged_sites;

  auto details =
      site_engagement::SiteEngagementService::GetAllDetailsInBackground(now,
                                                                        map);
  TRACE_EVENT1("navigation", "LookalikeUrlService SiteEngagementService",
               "site_count", details.size());
  for (const site_engagement::mojom::SiteEngagementDetails& detail : details) {
    if (!detail.origin.SchemeIsHTTPOrHTTPS()) {
      continue;
    }
    // Ignore sites with an engagement score below threshold.
    if (!site_engagement::SiteEngagementService::IsEngagementAtLeast(
            detail.total_score, blink::mojom::EngagementLevel::MEDIUM)) {
      continue;
    }
    const DomainInfo domain_info = lookalikes::GetDomainInfo(detail.origin);
    if (domain_info.domain_and_registry.empty()) {
      continue;
    }
    new_engaged_sites.push_back(domain_info);
  }

  return new_engaged_sites;
}

// Gets the eTLD+1 of the provided hostname, including private registries (e.g.
// foo.blogspot.com returns blogspot.com.
std::string GetETLDPlusOneWithPrivateRegistries(const std::string& hostname) {
  return net::registry_controlled_domains::GetDomainAndRegistry(
      hostname, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
}

void RecordReputationStatusWithEngagedSitesTime(base::TimeTicks start) {
  UMA_HISTOGRAM_TIMES(
      "Security.SafetyTips.GetReputationStatusWithEngagedSitesTime",
      base::TimeTicks::Now() - start);
}

}  // namespace

LookalikeUrlService::LookalikeUrlService(Profile* profile)
    : profile_(profile), clock_(base::DefaultClock::GetInstance()) {}

LookalikeUrlService::~LookalikeUrlService() = default;

// static
LookalikeUrlService* LookalikeUrlService::Get(Profile* profile) {
  return LookalikeUrlServiceFactory::GetForProfile(profile);
}

bool LookalikeUrlService::EngagedSitesNeedUpdating() const {
  if (last_engagement_fetch_time_.is_null())
    return true;
  const base::TimeDelta elapsed = clock_->Now() - last_engagement_fetch_time_;
  return elapsed >= kEngagedSiteUpdateInterval;
}

void LookalikeUrlService::ForceUpdateEngagedSites(
    EngagedSitesCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  TRACE_EVENT0("navigation", "LookalikeUrlService::ForceUpdateEngagedSites");

  // Queue an update on a worker thread if necessary.
  if (!update_in_progress_) {
    update_in_progress_ = true;

    base::ThreadPool::PostTaskAndReplyWithResult(
        FROM_HERE,
        {base::TaskPriority::USER_BLOCKING,
         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
        base::BindOnce(
            &UpdateEngagedSitesOnWorkerThread,
            clock_->Now(),
            base::WrapRefCounted(
                HostContentSettingsMapFactory::GetForProfile(profile_))),
        base::BindOnce(&LookalikeUrlService::OnUpdateEngagedSitesCompleted,
                       weak_factory_.GetWeakPtr()));
  }

  // Postpone the execution of the callback after the update is completed.
  pending_update_complete_callbacks_.push_back(std::move(callback));
}

void LookalikeUrlService::OnUpdateEngagedSitesCompleted(
    std::vector<DomainInfo> new_engaged_sites) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(update_in_progress_);
  TRACE_EVENT0("navigation",
               "LookalikeUrlService::OnUpdateEngagedSitesCompleted");
  engaged_sites_.swap(new_engaged_sites);
  last_engagement_fetch_time_ = clock_->Now();
  update_in_progress_ = false;

  // Call pending callbacks.
  std::vector<EngagedSitesCallback> callbacks;
  callbacks.swap(pending_update_complete_callbacks_);
  for (auto&& callback : callbacks) {
    std::move(callback).Run(engaged_sites_);
  }
}

const std::vector<DomainInfo> LookalikeUrlService::GetLatestEngagedSites()
    const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return engaged_sites_;
}

void LookalikeUrlService::SetClockForTesting(base::Clock* clock) {
  clock_ = clock;
}

LookalikeUrlService::LookalikeUrlCheckResult
LookalikeUrlService::CheckUrlForLookalikes(
    const GURL& url,
    const std::vector<DomainInfo>& engaged_sites,
    bool stop_checking_on_allowlist_or_ignore) const {
  LookalikeUrlCheckResult result;

  // Don't warn on non-HTTP(s) sites or non-public domains.
  if (!url.SchemeIsHTTPOrHTTPS() || net::HostStringIsLocalhost(url.host()) ||
      net::IsHostnameNonUnique(url.host()) ||
      lookalikes::GetETLDPlusOne(url.host()).empty() ||
      lookalikes::IsSafeTLD(url.host())) {
    return result;
  }

  if (IsIgnored(url)) {
    result.is_warning_previously_dismissed = true;
    if (stop_checking_on_allowlist_or_ignore) {
      return result;
    }
  }

  // When there's no proto (like at browser start), fail-safe and don't block.
  const auto* proto = lookalikes::GetSafetyTipsRemoteConfigProto();
  if (!proto) {
    return result;
  }

  // If the host is allowlisted by policy, don't show any warning.
  if (lookalikes::IsAllowedByEnterprisePolicy(profile_->GetPrefs(), url)) {
    result.is_allowlisted = true;
    if (stop_checking_on_allowlist_or_ignore) {
      return result;
    }
  }

  // GetDomainInfo() is expensive, so do possible early-abort checks first.
  base::TimeTicks get_domain_info_start = base::TimeTicks::Now();
  const DomainInfo navigated_domain = lookalikes::GetDomainInfo(url);
  result.get_domain_info_duration =
      base::TimeTicks::Now() - get_domain_info_start;

  if (IsTopDomain(navigated_domain)) {
    return result;
  }

  // Ensure that this URL is not already engaged. We can't use the synchronous
  // SiteEngagementService::IsEngagementAtLeast as it has side effects. We check
  // in PerformChecks to ensure we have up-to-date engaged_sites. This check
  // ignores the scheme which is okay since it's more conservative: If the user
  // is engaged with http://domain.test, not showing the warning on
  // https://domain.test is acceptable.
  if (base::Contains(engaged_sites, navigated_domain.domain_and_registry,
                     &DomainInfo::domain_and_registry)) {
    return result;
  }

  const lookalikes::LookalikeTargetAllowlistChecker in_target_allowlist =
      base::BindRepeating(
          &lookalikes::IsTargetHostAllowlistedBySafetyTipsComponent, proto);
  std::string matched_domain;
  if (GetMatchingDomain(navigated_domain, engaged_sites, in_target_allowlist,
                        proto, &matched_domain, &result.match_type)) {
    DCHECK(!matched_domain.empty());
    result.suggested_url =
        GetSuggestedURL(result.match_type, url, matched_domain);

    if (lookalikes::IsUrlAllowlistedBySafetyTipsComponent(
            proto, url.GetWithEmptyPath(), result.suggested_url)) {
      result.is_allowlisted = true;
      if (stop_checking_on_allowlist_or_ignore) {
        return result;
      }
    }
    result.action_type = GetActionForMatchType(
        proto, chrome::GetChannel(), navigated_domain.domain_and_registry,
        result.match_type);
  } else if (ShouldBlockBySpoofCheckResult(navigated_domain)) {
    result.match_type = LookalikeUrlMatchType::kFailedSpoofChecks;
    result.suggested_url = GURL();

    // Domains that trigger spoof checking are allowlisted as if they were
    // spoofing themselves, so pass in the spoofing URL as the canonical.
    if (lookalikes::IsUrlAllowlistedBySafetyTipsComponent(
            proto, url.GetWithEmptyPath(), url)) {
      result.is_allowlisted = true;
      if (stop_checking_on_allowlist_or_ignore) {
        return result;
      }
    }
    result.action_type = GetActionForMatchType(
        proto, chrome::GetChannel(), navigated_domain.domain_and_registry,
        result.match_type);
  }

  return result;
}

void LookalikeUrlService::CheckSafetyTipStatus(
    const GURL& url,
    content::WebContents* web_contents,
    SafetyTipCheckCallback callback) {
  DCHECK(url.SchemeIsHTTPOrHTTPS());
  if (EngagedSitesNeedUpdating()) {
    ForceUpdateEngagedSites(base::BindOnce(
        &LookalikeUrlService::CheckSafetyTipStatusWithEngagedSites,
        weak_factory_.GetWeakPtr(), url, std::move(callback)));
    // If the engaged sites need updating, there's nothing to do until callback.
    return;
  }

  CheckSafetyTipStatusWithEngagedSites(url, std::move(callback),
                                       GetLatestEngagedSites());
}

void LookalikeUrlService::CheckSafetyTipStatusWithEngagedSites(
    const GURL& url,
    SafetyTipCheckCallback callback,
    const std::vector<DomainInfo>& engaged_sites) {
  base::TimeTicks start = base::TimeTicks::Now();

  LookalikeUrlCheckResult lookalike_result =
      CheckUrlForLookalikes(url, engaged_sites,
                            /*stop_checking_on_allowlist_or_ignore=*/false);

  SafetyTipCheckResult result;
  result.url = url;

  if (lookalike_result.action_type != LookalikeActionType::kShowSafetyTip) {
    std::move(callback).Run(result);
    RecordReputationStatusWithEngagedSitesTime(start);
    return;
  }

  result.safety_tip_status = SafetyTipStatus::kNone;
  result.suggested_url = lookalike_result.suggested_url;
  result.safety_tip_status = SafetyTipStatus::kLookalike;
  result.lookalike_heuristic_triggered = true;

  if (lookalike_result.is_allowlisted) {
    // This will record a UKM but it won't show a warning.
    result.safety_tip_status = SafetyTipStatus::kNone;
    std::move(callback).Run(result);
    RecordReputationStatusWithEngagedSitesTime(start);
    return;
  }

  if (lookalike_result.is_warning_previously_dismissed) {
    result.safety_tip_status = SafetyTipStatus::kLookalikeIgnored;
    // The local allowlist is used by both the interstitial and safety tips, so
    // it's possible to hit this case even when we're not in the conditions
    // above. It's also possible to get kNone here when a domain is added to
    // the server-side allowlist after it has been ignored. In these cases,
    // there's no additional action required.
  }
  std::move(callback).Run(result);
  RecordReputationStatusWithEngagedSitesTime(start);
}

bool LookalikeUrlService::IsIgnored(const GURL& url) const {
  return warning_dismissed_etld1s_.count(
             GetETLDPlusOneWithPrivateRegistries(url.host())) > 0;
}

void LookalikeUrlService::SetUserIgnore(const GURL& url) {
  warning_dismissed_etld1s_.insert(
      GetETLDPlusOneWithPrivateRegistries(url.host()));
}

void LookalikeUrlService::OnUIDisabledFirstVisit(const GURL& url) {
  warning_dismissed_etld1s_.insert(
      GetETLDPlusOneWithPrivateRegistries(url.host()));
}

void LookalikeUrlService::ResetWarningDismissedETLDPlusOnesForTesting() {
  warning_dismissed_etld1s_.clear();
}

// static
void LookalikeUrlService::EnsureFactoryBuilt() {
  LookalikeUrlServiceFactory::GetInstance();
}
