1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
// 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_LOOKALIKES_LOOKALIKE_URL_SERVICE_H_
#define CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_SERVICE_H_
#include <vector>
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/sequence_checker.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/lookalikes/core/lookalike_url_util.h"
#include "components/security_state/core/security_state.h"
#include "url/gurl.h"
class PrefService;
namespace base {
class Clock;
}
namespace lookalikes {
struct DomainInfo;
}
namespace content {
class WebContents;
}
// Wrapper used to store the results of a safety tip check. Specifically, this
// is passed to the callback given to GetSafetyTipStatus. |url| is the URL
// applicable for this result.
struct SafetyTipCheckResult {
SafetyTipCheckResult() = default;
SafetyTipCheckResult(const SafetyTipCheckResult& other) = default;
security_state::SafetyTipStatus safety_tip_status =
security_state::SafetyTipStatus::kNone;
GURL url;
GURL suggested_url;
// True if a lookalike heuristic was triggered. Used to track whether a
// heuristic triggered for the given URL.
bool lookalike_heuristic_triggered = false;
};
// Callback type used for retrieving safety tip status. The results of the
// check are given in |result|.
using SafetyTipCheckCallback =
base::OnceCallback<void(SafetyTipCheckResult result)>;
// A service that handles operations on lookalike URLs. It can fetch the list of
// engaged sites in a background thread and cache the results until the next
// update. This is more efficient than fetching the list on each navigation for
// each tab separately.
class LookalikeUrlService : public KeyedService {
public:
// DO NOT pass a Profile here, pass keyed services dependencies explicitly
// (crbug.com/368297674).
LookalikeUrlService(PrefService* pref_service,
HostContentSettingsMap* host_content_settings_map);
LookalikeUrlService(const LookalikeUrlService&) = delete;
LookalikeUrlService& operator=(const LookalikeUrlService&) = delete;
~LookalikeUrlService() override;
using EngagedSitesCallback =
base::OnceCallback<void(const std::vector<lookalikes::DomainInfo>&)>;
// Returns whether the engaged site list is recently updated. Returns true
// even when an update has already been queued or is in progress.
bool EngagedSitesNeedUpdating() const;
// Triggers an update to the engaged site list if one is not already inflight,
// then schedules |callback| to be called with the new list once available.
void ForceUpdateEngagedSites(EngagedSitesCallback callback);
// Returns the _current_ list of engaged sites, without updating them if
// they're out of date.
const std::vector<lookalikes::DomainInfo> GetLatestEngagedSites() const;
void SetClockForTesting(base::Clock* clock);
base::Clock* clock() const { return clock_; }
// Stores the result of a lookalike URL check.
struct LookalikeUrlCheckResult {
// Action to take. kNone means the navigated URL wasn't a lookalike.
lookalikes::LookalikeActionType action_type =
lookalikes::LookalikeActionType::kNone;
// Heuristic match type. kNone means the navigated URL wasn't a lookalike.
lookalikes::LookalikeUrlMatchType match_type =
lookalikes::LookalikeUrlMatchType::kNone;
// Good URL suggested by the matching heuristic. Can be empty if there is no
// suggestion in which case the UI will show a different string.
GURL suggested_url;
// If true, the URL was previously flagged as a lookalike and the warning
// was dismissed by the user. Clears on browser restart for a given URL.
bool is_warning_previously_dismissed = false;
// If true, the URL was allowlisted by the component updater or enterprise
// policies.
bool is_allowlisted = false;
// Elapsed time for the GetDomainInfo() call. Zero if the function wasn't
// called.
base::TimeDelta get_domain_info_duration;
};
// This is the main function to call to check if a url is a lookalike URL. It
// runs all of the necessary checks on `url` before returning a result.
// If `url` is a lookalike, returns a result with the `action_type` and
// `match_type` populated.
// If stop_checking_on_allowlist_or_ignore is true, stops checking if the
// URL is allowlisted or a warning for it was previously ignored.
LookalikeUrlCheckResult CheckUrlForLookalikes(
const GURL& url,
const std::vector<lookalikes::DomainInfo>& engaged_sites,
bool stop_checking_on_allowlist_or_ignore) const;
// Check the safety tip status of the given URL, and
// asynchronously call |callback| with the results. See
// SafetyTipCheckCallback above for details on what's returned. |callback|
// will be called regardless of whether |url| is flagged or
// not. (Specifically, |callback| will be called with SafetyTipStatus::kNone
// if the url is not flagged).
void CheckSafetyTipStatus(const GURL& url,
content::WebContents* web_contents,
SafetyTipCheckCallback callback);
// Returns whether the user has dismissed a similar warning (interstitial or
// safety tip), and thus no warning should be shown for the provided url.
bool IsIgnored(const GURL& url) const;
// Tells the service that the user has explicitly ignored the warning (thus
// adding to the profile-wide allowlist).
void SetUserIgnore(const GURL& url);
// Tells the service that the user has the UI disabled, and thus the warning
// should be ignored. This ensures that subsequent loads of the page are not
// seen as flagged in metrics. This only impacts metrics for control groups.
void OnUIDisabledFirstVisit(const GURL& url);
// Reset set of eTLD+1s to forget the user action that ignores warning. Only
// for testing.
void ResetWarningDismissedETLDPlusOnesForTesting();
private:
// Called when an async engaged site computation is finished.
void OnUpdateEngagedSitesCompleted(
std::vector<lookalikes::DomainInfo> new_engaged_sites);
// Callback once we have up-to-date |engaged_sites|. Performs checks on the
// navigated |url|. Caller will display the Safety Tip warning when needed.
void CheckSafetyTipStatusWithEngagedSites(
const GURL& url,
SafetyTipCheckCallback callback,
const std::vector<lookalikes::DomainInfo>& engaged_sites);
const raw_ptr<PrefService> pref_service_;
const raw_ptr<HostContentSettingsMap> host_content_settings_map_;
raw_ptr<base::Clock> clock_;
base::Time last_engagement_fetch_time_;
std::vector<lookalikes::DomainInfo> engaged_sites_
GUARDED_BY_CONTEXT(sequence_checker_);
// Indicates that an update to the engaged sites list has been queued. Serves
// to prevent enqueuing excessive updates.
bool update_in_progress_ = false;
std::vector<EngagedSitesCallback> pending_update_complete_callbacks_;
// Set of eTLD+1s that we've warned about, and the user has explicitly
// ignored. Used to avoid re-warning the user.
std::set<std::string> warning_dismissed_etld1s_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<LookalikeUrlService> weak_factory_{this};
};
#endif // CHROME_BROWSER_LOOKALIKES_LOOKALIKE_URL_SERVICE_H_
|