// 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/browser_switcher/browser_switcher_service.h"

#include <algorithm>
#include <optional>
#include <string>
#include <utility>

#include "base/functional/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/syslog_logging.h"
#include "base/task/single_thread_task_runner.h"
#include "chrome/browser/browser_switcher/alternative_browser_driver.h"
#include "chrome/browser/browser_switcher/browser_switcher_prefs.h"
#include "chrome/browser/browser_switcher/browser_switcher_sitelist.h"
#include "chrome/browser/browser_switcher/ieem_sitelist_parser.h"
#include "chrome/browser/profiles/profile.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/file_url_loader.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"

namespace browser_switcher {

namespace {

// How long to wait after |BrowserSwitcherService| is created before initiating
// the sitelist fetch. Non-zero values are used for testing.
//
// TODO(nicolaso): get rid of this.
const base::TimeDelta kFetchSitelistDelay = base::TimeDelta();

// How long to wait after a fetch to re-fetch the sitelist to keep it fresh.
const base::TimeDelta kRefreshSitelistDelay = base::Minutes(30);

// How many times to re-try fetching the XML file for the sitelist.
const int kFetchNumRetries = 1;

constexpr net::NetworkTrafficAnnotationTag traffic_annotation =
    net::DefineNetworkTrafficAnnotation("browser_switcher_ieem_sitelist", R"(
        semantics {
          sender: "Legacy Browser Support "
          description:
            "Legacy Browser Support  may download Internet Explorer's "
            "Enterprise Mode SiteList XML, to load the list of URLs to open in "
            "an alternative browser. This is often on the organization's "
            "intranet. For more information on Internet Explorer's Enterprise "
            "Mode, see: "
            "https://docs.microsoft.com/internet-explorer/ie11-deploy-guide"
            "/what-is-enterprise-mode"
          trigger:
            "1 minute after browser startup, and then refreshes every 30 "
            "minutes afterwards. Only happens if Legacy Browser Support is "
            "enabled via enterprise policies."
          data:
            "Up to 3 (plus retries) HTTP or HTTPS GET requests to the URLs "
            "configured in Internet Explorer's SiteList policy, and Chrome's "
            "BrowserSwitcherExternalSitelistUrl and "
            "BrowserSwitcherExternalGreylistUrl policies."
          destination: OTHER
          destination_other:
            "URL configured in Internet Explorer's SiteList policy, and URLs "
            "configured in Chrome's BrowserSwitcherExternalSitelistUrl and "
            "BrowserSwitcherExternalGreylistUrl policies."
        }
        policy {
          cookies_allowed: NO
          setting: "This feature cannot be disabled by settings."
          chrome_policy: {
            BrowserSwitcherEnabled: {
              BrowserSwitcherEnabled: false
            }
          }
        })");

}  // namespace

RulesetSource::RulesetSource(
    std::string pref_name_,
    GURL url_,
    bool contains_inverted_rules_,
    base::OnceCallback<void(ParsedXml xml)> parsed_callback_)
    : pref_name(std::move(pref_name_)),
      url(std::move(url_)),
      contains_inverted_rules(contains_inverted_rules_),
      parsed_callback(std::move(parsed_callback_)) {}

RulesetSource::RulesetSource(RulesetSource&&) = default;

RulesetSource::~RulesetSource() = default;

XmlDownloader::XmlDownloader(Profile* profile,
                             BrowserSwitcherService* service,
                             base::TimeDelta first_fetch_delay,
                             base::RepeatingCallback<void()> all_done_callback)
    : service_(service), all_done_callback_(std::move(all_done_callback)) {
  file_url_factory_.Bind(
      content::CreateFileURLLoaderFactory(base::FilePath(), nullptr));
  other_url_factory_ = profile->GetDefaultStoragePartition()
                           ->GetURLLoaderFactoryForBrowserProcess();

  sources_ = service_->GetRulesetSources();

  for (auto& source : sources_) {
    if (!source.url.is_valid())
      DoneParsing(&source, ParsedXml({}, {}, std::nullopt));
  }

  // Fetch in 1 minute.
  ScheduleRefresh(first_fetch_delay);
}

XmlDownloader::~XmlDownloader() = default;

bool XmlDownloader::HasValidSources() const {
  return std::ranges::any_of(sources_, [](const RulesetSource& source) {
    return source.url.is_valid();
  });
}

base::Time XmlDownloader::last_refresh_time() const {
  return last_refresh_time_;
}

base::Time XmlDownloader::next_refresh_time() const {
  return next_refresh_time_;
}

void XmlDownloader::FetchXml() {
  for (auto& source : sources_) {
    if (!source.url.is_valid()) {
      DoneParsing(&source, ParsedXml({}));
      continue;
    }

    auto request = std::make_unique<network::ResourceRequest>();
    request->url = source.url;
    request->site_for_cookies = net::SiteForCookies::FromUrl(source.url);
    request->load_flags = net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
    request->credentials_mode = network::mojom::CredentialsMode::kInclude;
    request->priority = net::IDLE;
    source.url_loader = network::SimpleURLLoader::Create(std::move(request),
                                                         traffic_annotation);
    source.url_loader->SetRetryOptions(
        kFetchNumRetries,
        network::SimpleURLLoader::RetryMode::RETRY_ON_NETWORK_CHANGE);
    source.url_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
        GetURLLoaderFactoryForURL(source.url),
        base::BindOnce(&XmlDownloader::ParseXml, weak_ptr_factory_.GetWeakPtr(),
                       base::Unretained(&source)));
  }
}

network::mojom::URLLoaderFactory* XmlDownloader::GetURLLoaderFactoryForURL(
    const GURL& url) {
  if (url.SchemeIsFile())
    return file_url_factory_.get();
  return other_url_factory_.get();
}

void XmlDownloader::ParseXml(RulesetSource* source,
                             std::unique_ptr<std::string> bytes) {
  if (!bytes) {
    DoneParsing(source, ParsedXml({}, {}, "could not fetch XML"));
    return;
  }
  ParseIeemXml(
      *bytes, service_->prefs().GetParsingMode(),
      base::BindOnce(&XmlDownloader::DoneParsing,
                     weak_ptr_factory_.GetWeakPtr(), base::Unretained(source)));
}

void XmlDownloader::DoneParsing(RulesetSource* source, ParsedXml xml) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Special processing for "greylist" XML.
  if (source->contains_inverted_rules) {
    // BrowserSwitcherExternalGreylistUrl is special: all the rules are part of
    // the greylist, regardless of what <open-in> says in the XML.
    //
    // Merge all the rules into |greylist|, and clear |sitelist|.
    xml.rules.greylist.insert(xml.rules.greylist.end(),
                              xml.rules.sitelist.begin(),
                              xml.rules.sitelist.end());
    xml.rules.sitelist.clear();

    // Greylists can't contain any negative rules either, so remove the leading
    // "!".
    for (auto& rule : xml.rules.greylist) {
      if (base::StartsWith(rule, "!", base::CompareCase::SENSITIVE))
        rule.erase(0, 1);
    }
  }

  if (xml.error)
    LOG(ERROR) << *xml.error;
  std::move(source->parsed_callback).Run(std::move(xml));

  // Run the "all done" callback if this was the last ruleset.
  counter_++;
  DCHECK(counter_ <= sources_.size());
  if (counter_ == sources_.size()) {
    all_done_callback_.Run();
    if (HasValidSources())
      last_refresh_time_ = base::Time::Now();
    ScheduleRefresh(service_->refresh_delay());
  }
}

void XmlDownloader::ScheduleRefresh(base::TimeDelta delay) {
  // Avoid doing unnecessary work.
  if (!HasValidSources())
    return;

  // Refresh in 30 minutes, so the sitelists are never too stale.
  base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&XmlDownloader::Refresh, weak_ptr_factory_.GetWeakPtr()),
      delay);
  next_refresh_time_ = base::Time::Now() + delay;
}

void XmlDownloader::Refresh() {
  sources_ = service_->GetRulesetSources();
  counter_ = 0;
  FetchXml();
}

BrowserSwitcherService::BrowserSwitcherService(Profile* profile)
    : profile_(profile),
      prefs_(profile),
      driver_(new AlternativeBrowserDriverImpl(&prefs_)),
      sitelist_(new BrowserSwitcherSitelistImpl(&prefs_)) {
  prefs_subscription_ =
      prefs().RegisterPrefsChangedCallback(base::BindRepeating(
          &BrowserSwitcherService::OnBrowserSwitcherPrefsChanged,
          base::Unretained(this)));

  if (prefs_.IsEnabled()) {
    UMA_HISTOGRAM_ENUMERATION("BrowserSwitcher.AlternativeBrowser",
                              driver_->GetBrowserType());
  }
}

BrowserSwitcherService::~BrowserSwitcherService() = default;

void BrowserSwitcherService::Init() {
  LoadRulesFromPrefs();
  StartDownload(fetch_delay());
}

void BrowserSwitcherService::OnAllRulesetsLoadedForTesting(
    base::OnceCallback<void()> cb) {
  all_rulesets_loaded_callback_for_testing_ = std::move(cb);
}

void BrowserSwitcherService::StartDownload(base::TimeDelta delay) {
  // This destroys the previous XmlDownloader, which cancels any scheduled
  // refresh operations.
  sitelist_downloader_ = std::make_unique<XmlDownloader>(
      profile_, this, delay,
      base::BindRepeating(&BrowserSwitcherService::OnAllRulesetsParsed,
                          base::Unretained(this)));
}

void BrowserSwitcherService::Shutdown() {
  prefs_.Shutdown();
}

AlternativeBrowserDriver* BrowserSwitcherService::driver() {
  return driver_.get();
}

BrowserSwitcherSitelist* BrowserSwitcherService::sitelist() {
  return sitelist_.get();
}

BrowserSwitcherPrefs& BrowserSwitcherService::prefs() {
  return prefs_;
}

Profile* BrowserSwitcherService::profile() {
  return profile_;
}

XmlDownloader* BrowserSwitcherService::sitelist_downloader() {
  return sitelist_downloader_.get();
}

base::TimeDelta BrowserSwitcherService::fetch_delay() {
  return fetch_delay_;
}

base::TimeDelta BrowserSwitcherService::refresh_delay() {
  return refresh_delay_;
}

void BrowserSwitcherService::SetDriverForTesting(
    std::unique_ptr<AlternativeBrowserDriver> driver) {
  driver_ = std::move(driver);
}

void BrowserSwitcherService::SetSitelistForTesting(
    std::unique_ptr<BrowserSwitcherSitelist> sitelist) {
  sitelist_ = std::move(sitelist);
}

std::vector<RulesetSource> BrowserSwitcherService::GetRulesetSources() {
  std::vector<RulesetSource> sources;

  GURL sitelist_url = prefs_.GetExternalSitelistUrl();
  sources.emplace_back(
      prefs::kExternalSitelistUrl, sitelist_url, /* invert_rules */ false,
      base::BindOnce(&BrowserSwitcherService::OnExternalSitelistParsed,
                     weak_ptr_factory_.GetWeakPtr()));

  GURL greylist_url = prefs_.GetExternalGreylistUrl();
  sources.emplace_back(
      prefs::kExternalGreylistUrl, greylist_url, /* invert_rules */ true,
      base::BindOnce(&BrowserSwitcherService::OnExternalGreylistParsed,
                     weak_ptr_factory_.GetWeakPtr()));

  return sources;
}

void BrowserSwitcherService::LoadRulesFromPrefs() {
  if (prefs().GetExternalSitelistUrl().is_valid())
    sitelist()->SetExternalSitelist(prefs().GetCachedExternalSitelist());
  if (prefs().GetExternalGreylistUrl().is_valid())
    sitelist()->SetExternalGreylist(prefs().GetCachedExternalGreylist());
}

void BrowserSwitcherService::OnAllRulesetsParsed() {
  callback_list_.Notify(this);
  if (all_rulesets_loaded_callback_for_testing_)
    std::move(all_rulesets_loaded_callback_for_testing_).Run();
}

base::CallbackListSubscription
BrowserSwitcherService::RegisterAllRulesetsParsedCallback(
    AllRulesetsParsedCallback callback) {
  return callback_list_.Add(callback);
}

void BrowserSwitcherService::OnBrowserSwitcherPrefsChanged(
    BrowserSwitcherPrefs* prefs,
    const std::vector<std::string>& changed_prefs) {
  // Record |BrowserSwitcher.AlternativeBrowser| when the
  // |BrowserSwitcherEnabled| or |AlternativeBrowserPath| policies change.
  bool should_record_metrics =
      std::ranges::any_of(changed_prefs, [](const std::string& pref) {
        return pref == prefs::kEnabled ||
               pref == prefs::kAlternativeBrowserPath;
      });
  if (should_record_metrics && prefs_.IsEnabled()) {
    UMA_HISTOGRAM_ENUMERATION("BrowserSwitcher.AlternativeBrowser",
                              driver_->GetBrowserType());
  }

  auto sources = GetRulesetSources();

  // Re-download if one of the URLs or the ParsingMode changed. O(n^2), but n<=3
  // so it's fast.
  auto it = std::ranges::find(changed_prefs, prefs::kParsingMode);
  bool parsing_mode_changed = it != changed_prefs.end();
  bool should_redownload =
      parsing_mode_changed ||
      std::ranges::any_of(
          sources,
          [&changed_prefs](const std::string& pref_name) {
            auto it = std::ranges::find(changed_prefs, pref_name);
            return it != changed_prefs.end();
          },
          &RulesetSource::pref_name);

  if (should_redownload)
    StartDownload(fetch_delay());
}

void BrowserSwitcherService::OnExternalSitelistParsed(ParsedXml xml) {
  if (xml.error) {
    SYSLOG(INFO) << "Unable to parse IEEM SiteList: " << *xml.error;
  } else {
    VLOG(2) << "Done parsing external SiteList for sitelist rules. "
            << "Applying rules to future navigations.";

    if (prefs().GetExternalSitelistUrl().is_valid())
      prefs().SetCachedExternalSitelist(xml.rules);

    sitelist()->SetExternalSitelist(std::move(xml.rules));
  }
}

void BrowserSwitcherService::OnExternalGreylistParsed(ParsedXml xml) {
  if (xml.error) {
    SYSLOG(INFO) << "Unable to parse IEEM SiteList: " << *xml.error;
  } else {
    VLOG(2) << "Done parsing external SiteList for greylist rules. "
            << "Applying rules to future navigations.";
    DCHECK(xml.rules.sitelist.empty());

    if (prefs().GetExternalGreylistUrl().is_valid()) {
      prefs().SetCachedExternalGreylist(xml.rules);
    }

    sitelist()->SetExternalGreylist(std::move(xml.rules));
  }
}

base::TimeDelta BrowserSwitcherService::fetch_delay_ = kFetchSitelistDelay;
base::TimeDelta BrowserSwitcherService::refresh_delay_ = kRefreshSitelistDelay;

// static
void BrowserSwitcherService::SetFetchDelayForTesting(base::TimeDelta delay) {
  fetch_delay_ = delay;
}

// static
void BrowserSwitcherService::SetRefreshDelayForTesting(base::TimeDelta delay) {
  refresh_delay_ = delay;
}

}  // namespace browser_switcher
