#ifndef CHROME_BROWSER_BROWSER_SWITCHER_BROWSER_SWITCHER_SERVICE_H_
#define CHROME_BROWSER_BROWSER_SWITCHER_BROWSER_SWITCHER_SERVICE_H_
#include <memory>
#include <optional>
#include <string>
#include "base/callback_list.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/browser_switcher/browser_switcher_prefs.h"
#include "components/keyed_service/core/keyed_service.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h"
class BrowserSwitchHandler;
class Profile;
namespace browser_switcher {
class AlternativeBrowserDriver;
class BrowserSwitcherSitelist;
class ParsedXml;
struct RulesetSource {
RulesetSource(std::string pref_name_,
GURL url_,
bool contains_inverted_rules,
base::OnceCallback<void(ParsedXml xml)> parsed_callback_);
RulesetSource(RulesetSource&&);
~RulesetSource();
std::string pref_name;
GURL url;
bool contains_inverted_rules;
base::OnceCallback<void(ParsedXml xml)> parsed_callback;
std::unique_ptr<network::SimpleURLLoader> url_loader;
};
class BrowserSwitcherService;
class XmlDownloader {
public:
XmlDownloader(Profile* profile,
BrowserSwitcherService* service,
base::TimeDelta first_fetch_delay,
base::RepeatingCallback<void()> all_done_callback);
virtual ~XmlDownloader();
base::Time last_refresh_time() const;
base::Time next_refresh_time() const;
private:
bool HasValidSources() const;
void FetchXml();
void ParseXml(RulesetSource* source, std::optional<std::string> bytes);
void DoneParsing(RulesetSource* source, ParsedXml xml);
void ScheduleRefresh(base::TimeDelta delay);
void Refresh();
network::mojom::URLLoaderFactory* GetURLLoaderFactoryForURL(const GURL& url);
mojo::Remote<network::mojom::URLLoaderFactory> file_url_factory_;
scoped_refptr<network::SharedURLLoaderFactory> other_url_factory_;
raw_ptr<BrowserSwitcherService> service_;
std::vector<RulesetSource> sources_;
base::RepeatingCallback<void()> all_done_callback_;
unsigned int counter_ = 0;
base::Time last_refresh_time_;
base::Time next_refresh_time_;
base::WeakPtrFactory<XmlDownloader> weak_ptr_factory_{this};
};
class BrowserSwitcherService : public KeyedService {
private:
using AllRulesetsParsedCallbackSignature = void(BrowserSwitcherService*);
using AllRulesetsParsedCallback =
base::RepeatingCallback<AllRulesetsParsedCallbackSignature>;
public:
BrowserSwitcherService() = delete;
explicit BrowserSwitcherService(Profile* profile);
BrowserSwitcherService(const BrowserSwitcherService&) = delete;
BrowserSwitcherService& operator=(const BrowserSwitcherService&) = delete;
~BrowserSwitcherService() override;
virtual void Init();
void Shutdown() override;
AlternativeBrowserDriver* driver();
BrowserSwitcherSitelist* sitelist();
BrowserSwitcherPrefs& prefs();
Profile* profile();
base::TimeDelta fetch_delay();
base::TimeDelta refresh_delay();
void SetDriverForTesting(std::unique_ptr<AlternativeBrowserDriver> driver);
void SetSitelistForTesting(std::unique_ptr<BrowserSwitcherSitelist> sitelist);
static void SetFetchDelayForTesting(base::TimeDelta delay);
static void SetRefreshDelayForTesting(base::TimeDelta delay);
virtual std::vector<RulesetSource> GetRulesetSources();
virtual void LoadRulesFromPrefs();
void OnAllRulesetsLoadedForTesting(base::OnceCallback<void()> callback);
protected:
virtual void OnAllRulesetsParsed();
virtual void OnBrowserSwitcherPrefsChanged(
BrowserSwitcherPrefs* prefs,
const std::vector<std::string>& changed_prefs);
static base::TimeDelta fetch_delay_;
static base::TimeDelta refresh_delay_;
private:
friend class ::BrowserSwitchHandler;
void OnExternalSitelistParsed(ParsedXml xml);
void OnExternalGreylistParsed(ParsedXml xml);
void StartDownload(base::TimeDelta delay);
XmlDownloader* sitelist_downloader();
void DownloadNow();
base::CallbackListSubscription RegisterAllRulesetsParsedCallback(
AllRulesetsParsedCallback callback);
std::unique_ptr<XmlDownloader> sitelist_downloader_;
raw_ptr<Profile> profile_;
BrowserSwitcherPrefs prefs_;
base::CallbackListSubscription prefs_subscription_;
base::RepeatingCallbackList<AllRulesetsParsedCallbackSignature>
callback_list_;
base::OnceCallback<void()> all_rulesets_loaded_callback_for_testing_;
std::unique_ptr<AlternativeBrowserDriver> driver_;
std::unique_ptr<BrowserSwitcherSitelist> sitelist_;
base::WeakPtrFactory<BrowserSwitcherService> weak_ptr_factory_{this};
};
}
#endif