blob: 9aa9fb4b7cbfea306fd24185b3ddcf8ca79a81d8 [file] [log] [blame] [edit]
// 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.
#ifndef CHROME_BROWSER_BROWSER_SWITCHER_BROWSER_SWITCHER_PREFS_H_
#define CHROME_BROWSER_BROWSER_SWITCHER_BROWSER_SWITCHER_PREFS_H_
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include "base/callback_list.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/policy/core/common/policy_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "url/gurl.h"
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
class PrefService;
class Profile;
namespace browser_switcher {
// This type pre-computes some strings from the URL's parts, so we don't have
// to pay the cost of constructing those strings multiple times. i.e., the same
// NoCopyUrl can be passed to multiple calls of Rule::Matches().
class NoCopyUrl {
public:
explicit NoCopyUrl(const GURL& original);
NoCopyUrl(const NoCopyUrl&) = delete;
const GURL& original() const { return *original_; }
std::string_view host_and_port() const { return host_and_port_; }
std::string_view spec() const { return original_->spec(); }
std::string_view spec_without_port() const { return spec_without_port_; }
private:
const raw_ref<const GURL> original_;
// If there is a port number, then this is "<host>:<port>". Otherwise, this is
// just the host.
std::string host_and_port_;
// Same as |original_.spec()|, but with the port removed.
std::string spec_without_port_;
};
// A named pair type, for rules that haven't been pre-processed and
// canonicalized (e.g., just loaded from prefs or policies).
struct RawRuleSet {
RawRuleSet();
RawRuleSet(std::vector<std::string>&& sitelist,
std::vector<std::string>&& greylist);
RawRuleSet(RawRuleSet&&);
~RawRuleSet();
RawRuleSet& operator=(RawRuleSet&&);
std::vector<std::string> sitelist;
std::vector<std::string> greylist;
};
// A single "rule" from a sitelist or greylist, after pre-processing and
// canonicalization.
class Rule {
public:
explicit Rule(std::string_view original_rule);
virtual ~Rule() = default;
// Returns true if |no_copy_url| matches this rule. Ignores the value of
// |inverted_|.
virtual bool Matches(const NoCopyUrl& no_copy_url) const = 0;
// Returns true if the rule is valid. If this returns false, the rule will be
// removed from the final list of canonicalized rules.
virtual bool IsValid() const = 0;
// Converts the rule to a human-readable string, for display on
// chrome://browser-switch/internals and serializing to cache.dat.
virtual std::string ToString() const = 0;
int priority() const { return priority_; }
bool inverted() const { return inverted_; }
private:
// The "priority" of this rule for making decisions. This should be the length
// of the original string this rule was parsed from. When 2 rules conflict,
// the one with higher priority always wins.
int priority_;
// Whether this rule is inverted or not. Inverted rules change the decision
// from "open in alternative browser" to "don't open in alternative browser".
bool inverted_;
};
// A named pair type, for pre-processed and canonicalized rules.
struct RuleSet {
RuleSet();
RuleSet(RuleSet&&);
~RuleSet();
std::vector<std::unique_ptr<Rule>> sitelist;
std::vector<std::unique_ptr<Rule>> greylist;
};
// Values for the BrowserSwitcherParsingMode policy. Make sure they match the
// values in policy_templates.json.
enum class ParsingMode {
kDefault = 0,
kIESiteListMode = 1,
kMaxValue = kIESiteListMode, // Always keep up-to-date.
};
// Contains the current state of the prefs related to LBS. For sensitive prefs,
// only respects managed prefs. Also does some type conversions and
// transformations on the prefs (e.g. expanding preset values for
// AlternativeBrowserPath).
class BrowserSwitcherPrefs : public KeyedService,
public policy::PolicyService::Observer {
private:
using PrefsChangedSignature = void(BrowserSwitcherPrefs*,
const std::vector<std::string>&);
public:
using PrefsChangedCallback = base::RepeatingCallback<PrefsChangedSignature>;
BrowserSwitcherPrefs() = delete;
explicit BrowserSwitcherPrefs(Profile* profile);
BrowserSwitcherPrefs(const BrowserSwitcherPrefs&) = delete;
BrowserSwitcherPrefs& operator=(const BrowserSwitcherPrefs&) = delete;
~BrowserSwitcherPrefs() override;
// KeyedService:
void Shutdown() override;
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Returns true if the BrowserSwitcher feature is enabled via policy.
bool IsEnabled() const;
// Returns the path to the alternative browser to launch, before
// substitutions. If the pref is not managed, returns the empty string.
const std::string& GetAlternativeBrowserPath() const;
// Returns the arguments to pass to the alternative browser, before
// substitutions. If the pref is not managed, returns the empty string.
const std::vector<std::string>& GetAlternativeBrowserParameters() const;
// Returns true if Chrome should keep at least one tab open after switching.
bool KeepLastTab() const;
// Returns the delay before switching, in milliseconds.
int GetDelay() const;
ParsingMode GetParsingMode() const;
// Returns the sitelist + greylist configured directly through Chrome
// policies. If the pref is not managed, returns an empty vector.
const RuleSet& GetRules() const;
// Retrieves or stores the locally cached external sitelist from the
// PrefStore.
RawRuleSet GetCachedExternalSitelist() const;
void SetCachedExternalSitelist(const RawRuleSet& sitelist);
// Retrieves or stores the locally cached external greylist from the
// PrefStore.
RawRuleSet GetCachedExternalGreylist() const;
void SetCachedExternalGreylist(const RawRuleSet& greylist);
#if BUILDFLAG(IS_WIN)
// Retrieves or stores the locally cached IEEM sitelist from the PrefStore.
RawRuleSet GetCachedIeemSitelist() const;
void SetCachedIeemSitelist(const RawRuleSet& sitelist);
#endif
// Returns the URL to download for an external XML sitelist. If the pref is
// not managed, returns an invalid URL.
GURL GetExternalSitelistUrl() const;
// Returns the URL to download for an external XML greylist. If the pref is
// not managed, returns an invalid URL.
GURL GetExternalGreylistUrl() const;
#if BUILDFLAG(IS_WIN)
// Returns true if Chrome should download and apply the XML sitelist from
// IEEM's SiteList policy. If the pref is not managed, returns false.
bool UseIeSitelist() const;
// Returns the path to the Chrome executable to launch when switching from IE,
// before substitutions.
const base::FilePath& GetChromePath() const;
// Returns the arguments to pass to Chrome when switching from IE, before
// substitutions.
const std::vector<std::string>& GetChromeParameters() const;
#endif
// policy::PolicyService::Observer
void OnPolicyUpdated(const policy::PolicyNamespace& ns,
const policy::PolicyMap& previous,
const policy::PolicyMap& current) override;
base::CallbackListSubscription RegisterPrefsChangedCallback(
PrefsChangedCallback cb);
protected:
// For internal use and testing.
BrowserSwitcherPrefs(PrefService* prefs,
policy::PolicyService* policy_service);
private:
void RunCallbacksIfDirty();
void MarkDirty(const std::string& pref_name);
// Hooks for PrefChangeRegistrar.
void AlternativeBrowserPathChanged();
void AlternativeBrowserParametersChanged();
void ParsingModeChanged();
void UrlListChanged();
void GreylistChanged();
#if BUILDFLAG(IS_WIN)
void ChromePathChanged();
void ChromeParametersChanged();
#endif
const raw_ptr<policy::PolicyService> policy_service_;
const raw_ptr<PrefService> prefs_;
// We need 2 change registrars because we can't bind 2 observers to the same
// pref on the same registrar.
// Listens on *some* prefs, to apply a filter to them
// (e.g. convert Value::List => vector<string>).
PrefChangeRegistrar filtering_change_registrar_;
// Listens on *all* BrowserSwitcher prefs, to notify observers when prefs
// change as a result of a policy refresh.
PrefChangeRegistrar notifying_change_registrar_;
// Type-converted and/or expanded pref values, updated by the
// PrefChangeRegistrar hooks.
std::string alt_browser_path_;
std::vector<std::string> alt_browser_params_;
ParsingMode parsing_mode_ = ParsingMode::kDefault;
#if BUILDFLAG(IS_WIN)
base::FilePath chrome_path_;
std::vector<std::string> chrome_params_;
#endif
// Rules from the BrowserSwitcherUrlList and BrowserSwitcherGreylist policies.
//
// Other rules are parsed from XML, and stored in BrowserSwitcherSitelist
// instead of here.
RuleSet rules_;
// List of prefs (pref names) that changed since the last policy refresh.
std::vector<std::string> dirty_prefs_;
base::RepeatingCallbackList<PrefsChangedSignature> callback_list_;
base::WeakPtrFactory<BrowserSwitcherPrefs> weak_ptr_factory_{this};
};
namespace prefs {
extern const char kEnabled[];
extern const char kDelay[];
extern const char kAlternativeBrowserPath[];
extern const char kAlternativeBrowserParameters[];
extern const char kKeepLastTab[];
extern const char kParsingMode[];
extern const char kUrlList[];
extern const char kUrlGreylist[];
extern const char kExternalSitelistUrl[];
extern const char kCachedExternalSitelist[];
extern const char kCachedExternalSitelistGreylist[];
extern const char kExternalGreylistUrl[];
extern const char kCachedExternalGreylist[];
#if BUILDFLAG(IS_WIN)
extern const char kUseIeSitelist[];
extern const char kCachedIeSitelist[];
extern const char kCachedIeSitelistGreylist[];
extern const char kChromePath[];
extern const char kChromeParameters[];
#endif
} // namespace prefs
} // namespace browser_switcher
#endif // CHROME_BROWSER_BROWSER_SWITCHER_BROWSER_SWITCHER_PREFS_H_